@xmldom/xmldom 0.8.3 → 0.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/lib/dom.js +203 -48
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,19 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [0.8.4](https://github.com/xmldom/xmldom/compare/0.8.3...0.8.4)
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- Security: Prevent inserting DOM nodes when they are not well-formed [`CVE-2022-39353`](https://github.com/xmldom/xmldom/security/advisories/GHSA-crh6-fp67-6883)
|
|
12
|
+
In case such a DOM would be created, the part that is not well-formed will be transformed into text nodes, in which xml specific characters like `<` and `>` are encoded accordingly.
|
|
13
|
+
In the upcoming version 0.9.0 those text nodes will no longer be added and an error will be thrown instead.
|
|
14
|
+
This change can break your code, if you relied on this behavior, e.g. multiple root elements in the past. We consider it more important to align with the specs that we want to be aligned with, considering the potential security issues that might derive from people not being aware of the difference in behavior.
|
|
15
|
+
Related Spec: <https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity>
|
|
16
|
+
|
|
17
|
+
Thank you, [@frumioj](https://github.com/frumioj), [@cjbarth](https://github.com/cjbarth), [@markgollnick](https://github.com/markgollnick) for your contributions
|
|
18
|
+
|
|
19
|
+
|
|
7
20
|
## [0.8.3](https://github.com/xmldom/xmldom/compare/0.8.3...0.8.2)
|
|
8
21
|
|
|
9
22
|
### Fixed
|
package/lib/dom.js
CHANGED
|
@@ -158,14 +158,14 @@ NodeList.prototype = {
|
|
|
158
158
|
* The number of nodes in the list. The range of valid child node indices is 0 to length-1 inclusive.
|
|
159
159
|
* @standard level1
|
|
160
160
|
*/
|
|
161
|
-
length:0,
|
|
161
|
+
length:0,
|
|
162
162
|
/**
|
|
163
163
|
* Returns the indexth item in the collection. If index is greater than or equal to the number of nodes in the list, this returns null.
|
|
164
164
|
* @standard level1
|
|
165
|
-
* @param index unsigned long
|
|
165
|
+
* @param index unsigned long
|
|
166
166
|
* Index into the collection.
|
|
167
167
|
* @return Node
|
|
168
|
-
* The node at the indexth position in the NodeList, or null if that is not a valid index.
|
|
168
|
+
* The node at the indexth position in the NodeList, or null if that is not a valid index.
|
|
169
169
|
*/
|
|
170
170
|
item: function(index) {
|
|
171
171
|
return this[index] || null;
|
|
@@ -175,7 +175,31 @@ NodeList.prototype = {
|
|
|
175
175
|
serializeToString(this[i],buf,isHTML,nodeFilter);
|
|
176
176
|
}
|
|
177
177
|
return buf.join('');
|
|
178
|
-
}
|
|
178
|
+
},
|
|
179
|
+
/**
|
|
180
|
+
* @private
|
|
181
|
+
* @param {function (Node):boolean} predicate
|
|
182
|
+
* @returns {Node | undefined}
|
|
183
|
+
*/
|
|
184
|
+
find: function (predicate) {
|
|
185
|
+
return Array.prototype.find.call(this, predicate);
|
|
186
|
+
},
|
|
187
|
+
/**
|
|
188
|
+
* @private
|
|
189
|
+
* @param {function (Node):boolean} predicate
|
|
190
|
+
* @returns {Node[]}
|
|
191
|
+
*/
|
|
192
|
+
filter: function (predicate) {
|
|
193
|
+
return Array.prototype.filter.call(this, predicate);
|
|
194
|
+
},
|
|
195
|
+
/**
|
|
196
|
+
* @private
|
|
197
|
+
* @param {Node} item
|
|
198
|
+
* @returns {number}
|
|
199
|
+
*/
|
|
200
|
+
indexOf: function (item) {
|
|
201
|
+
return Array.prototype.indexOf.call(this, item);
|
|
202
|
+
},
|
|
179
203
|
};
|
|
180
204
|
|
|
181
205
|
function LiveNodeList(node,refresh){
|
|
@@ -209,7 +233,7 @@ _extends(LiveNodeList,NodeList);
|
|
|
209
233
|
* but this is simply to allow convenient enumeration of the contents of a NamedNodeMap,
|
|
210
234
|
* and does not imply that the DOM specifies an order to these Nodes.
|
|
211
235
|
* NamedNodeMap objects in the DOM are live.
|
|
212
|
-
* used for attributes or DocumentType entities
|
|
236
|
+
* used for attributes or DocumentType entities
|
|
213
237
|
*/
|
|
214
238
|
function NamedNodeMap() {
|
|
215
239
|
};
|
|
@@ -253,7 +277,7 @@ function _removeNamedNode(el,list,attr){
|
|
|
253
277
|
}
|
|
254
278
|
}
|
|
255
279
|
}else{
|
|
256
|
-
throw DOMException(NOT_FOUND_ERR,new Error(el.tagName+'@'+attr))
|
|
280
|
+
throw new DOMException(NOT_FOUND_ERR,new Error(el.tagName+'@'+attr))
|
|
257
281
|
}
|
|
258
282
|
}
|
|
259
283
|
NamedNodeMap.prototype = {
|
|
@@ -298,10 +322,10 @@ NamedNodeMap.prototype = {
|
|
|
298
322
|
var attr = this.getNamedItem(key);
|
|
299
323
|
_removeNamedNode(this._ownerElement,this,attr);
|
|
300
324
|
return attr;
|
|
301
|
-
|
|
302
|
-
|
|
325
|
+
|
|
326
|
+
|
|
303
327
|
},// raises: NOT_FOUND_ERR,NO_MODIFICATION_ALLOWED_ERR
|
|
304
|
-
|
|
328
|
+
|
|
305
329
|
//for level2
|
|
306
330
|
removeNamedItemNS:function(namespaceURI,localName){
|
|
307
331
|
var attr = this.getNamedItemNS(namespaceURI,localName);
|
|
@@ -447,10 +471,10 @@ Node.prototype = {
|
|
|
447
471
|
prefix : null,
|
|
448
472
|
localName : null,
|
|
449
473
|
// Modified in DOM Level 2:
|
|
450
|
-
insertBefore:function(newChild, refChild){//raises
|
|
474
|
+
insertBefore:function(newChild, refChild){//raises
|
|
451
475
|
return _insertBefore(this,newChild,refChild);
|
|
452
476
|
},
|
|
453
|
-
replaceChild:function(newChild, oldChild){//raises
|
|
477
|
+
replaceChild:function(newChild, oldChild){//raises
|
|
454
478
|
this.insertBefore(newChild,oldChild);
|
|
455
479
|
if(oldChild){
|
|
456
480
|
this.removeChild(oldChild);
|
|
@@ -656,48 +680,177 @@ function _removeChild (parentNode, child) {
|
|
|
656
680
|
_onUpdateChild(parentNode.ownerDocument, parentNode);
|
|
657
681
|
return child;
|
|
658
682
|
}
|
|
683
|
+
|
|
684
|
+
/**
|
|
685
|
+
* Returns `true` if `node` can be a parent for insertion.
|
|
686
|
+
* @param {Node} node
|
|
687
|
+
* @returns {boolean}
|
|
688
|
+
*/
|
|
689
|
+
function hasValidParentNodeType(node) {
|
|
690
|
+
return (
|
|
691
|
+
node &&
|
|
692
|
+
(node.nodeType === Node.DOCUMENT_NODE || node.nodeType === Node.DOCUMENT_FRAGMENT_NODE || node.nodeType === Node.ELEMENT_NODE)
|
|
693
|
+
);
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
/**
|
|
697
|
+
* Returns `true` if `node` can be inserted according to it's `nodeType`.
|
|
698
|
+
* @param {Node} node
|
|
699
|
+
* @returns {boolean}
|
|
700
|
+
*/
|
|
701
|
+
function hasInsertableNodeType(node) {
|
|
702
|
+
return (
|
|
703
|
+
node &&
|
|
704
|
+
(isElementNode(node) ||
|
|
705
|
+
isTextNode(node) ||
|
|
706
|
+
isDocTypeNode(node) ||
|
|
707
|
+
node.nodeType === Node.DOCUMENT_FRAGMENT_NODE ||
|
|
708
|
+
node.nodeType === Node.COMMENT_NODE ||
|
|
709
|
+
node.nodeType === Node.PROCESSING_INSTRUCTION_NODE)
|
|
710
|
+
);
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
/**
|
|
714
|
+
* Returns true if `node` is a DOCTYPE node
|
|
715
|
+
* @param {Node} node
|
|
716
|
+
* @returns {boolean}
|
|
717
|
+
*/
|
|
718
|
+
function isDocTypeNode(node) {
|
|
719
|
+
return node && node.nodeType === Node.DOCUMENT_TYPE_NODE;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
/**
|
|
723
|
+
* Returns true if the node is an element
|
|
724
|
+
* @param {Node} node
|
|
725
|
+
* @returns {boolean}
|
|
726
|
+
*/
|
|
727
|
+
function isElementNode(node) {
|
|
728
|
+
return node && node.nodeType === Node.ELEMENT_NODE;
|
|
729
|
+
}
|
|
730
|
+
/**
|
|
731
|
+
* Returns true if `node` is a text node
|
|
732
|
+
* @param {Node} node
|
|
733
|
+
* @returns {boolean}
|
|
734
|
+
*/
|
|
735
|
+
function isTextNode(node) {
|
|
736
|
+
return node && node.nodeType === Node.TEXT_NODE;
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
/**
|
|
740
|
+
* Check if en element node can be inserted before `child`, or at the end if child is falsy,
|
|
741
|
+
* according to the presence and position of a doctype node on the same level.
|
|
742
|
+
*
|
|
743
|
+
* @param {Document} doc The document node
|
|
744
|
+
* @param {Node} child the node that would become the nextSibling if the element would be inserted
|
|
745
|
+
* @returns {boolean} `true` if an element can be inserted before child
|
|
746
|
+
* @private
|
|
747
|
+
* https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity
|
|
748
|
+
*/
|
|
749
|
+
function isElementInsertionPossible(doc, child) {
|
|
750
|
+
var parentChildNodes = doc.childNodes || [];
|
|
751
|
+
if (parentChildNodes.find(isElementNode) || isDocTypeNode(child)) {
|
|
752
|
+
return false;
|
|
753
|
+
}
|
|
754
|
+
var docTypeNode = parentChildNodes.find(isDocTypeNode);
|
|
755
|
+
return !(child && docTypeNode && parentChildNodes.indexOf(docTypeNode) > parentChildNodes.indexOf(child));
|
|
756
|
+
}
|
|
659
757
|
/**
|
|
660
|
-
*
|
|
758
|
+
* @private
|
|
759
|
+
* @param {Node} parent the parent node to insert `node` into
|
|
760
|
+
* @param {Node} node the node to insert
|
|
761
|
+
* @param {Node=} child the node that should become the `nextSibling` of `node`
|
|
762
|
+
* @returns {Node}
|
|
763
|
+
* @throws DOMException for several node combinations that would create a DOM that is not well-formed.
|
|
764
|
+
* @throws DOMException if `child` is provided but is not a child of `parent`.
|
|
765
|
+
* @see https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity
|
|
661
766
|
*/
|
|
662
|
-
function _insertBefore(
|
|
663
|
-
|
|
767
|
+
function _insertBefore(parent, node, child) {
|
|
768
|
+
if (!hasValidParentNodeType(parent)) {
|
|
769
|
+
throw new DOMException(HIERARCHY_REQUEST_ERR, 'Unexpected parent node type ' + parent.nodeType);
|
|
770
|
+
}
|
|
771
|
+
if (child && child.parentNode !== parent) {
|
|
772
|
+
throw new DOMException(NOT_FOUND_ERR, 'child not in parent');
|
|
773
|
+
}
|
|
774
|
+
if (
|
|
775
|
+
!hasInsertableNodeType(node) ||
|
|
776
|
+
// the sax parser currently adds top level text nodes, this will be fixed in 0.9.0
|
|
777
|
+
// || (node.nodeType === Node.TEXT_NODE && parent.nodeType === Node.DOCUMENT_NODE)
|
|
778
|
+
(isDocTypeNode(node) && parent.nodeType !== Node.DOCUMENT_NODE)
|
|
779
|
+
) {
|
|
780
|
+
throw new DOMException(
|
|
781
|
+
HIERARCHY_REQUEST_ERR,
|
|
782
|
+
'Unexpected node type ' + node.nodeType + ' for parent node type ' + parent.nodeType
|
|
783
|
+
);
|
|
784
|
+
}
|
|
785
|
+
var parentChildNodes = parent.childNodes || [];
|
|
786
|
+
var nodeChildNodes = node.childNodes || [];
|
|
787
|
+
if (parent.nodeType === Node.DOCUMENT_NODE) {
|
|
788
|
+
if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
|
|
789
|
+
let nodeChildElements = nodeChildNodes.filter(isElementNode);
|
|
790
|
+
if (nodeChildElements.length > 1 || nodeChildNodes.find(isTextNode)) {
|
|
791
|
+
throw new DOMException(HIERARCHY_REQUEST_ERR, 'More than one element or text in fragment');
|
|
792
|
+
}
|
|
793
|
+
if (nodeChildElements.length === 1 && !isElementInsertionPossible(parent, child)) {
|
|
794
|
+
throw new DOMException(HIERARCHY_REQUEST_ERR, 'Element in fragment can not be inserted before doctype');
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
if (isElementNode(node)) {
|
|
798
|
+
if (parentChildNodes.find(isElementNode) || !isElementInsertionPossible(parent, child)) {
|
|
799
|
+
throw new DOMException(HIERARCHY_REQUEST_ERR, 'Only one element can be added and only after doctype');
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
if (isDocTypeNode(node)) {
|
|
803
|
+
if (parentChildNodes.find(isDocTypeNode)) {
|
|
804
|
+
throw new DOMException(HIERARCHY_REQUEST_ERR, 'Only one doctype is allowed');
|
|
805
|
+
}
|
|
806
|
+
let parentElementChild = parentChildNodes.find(isElementNode);
|
|
807
|
+
if (child && parentChildNodes.indexOf(parentElementChild) < parentChildNodes.indexOf(child)) {
|
|
808
|
+
throw new DOMException(HIERARCHY_REQUEST_ERR, 'Doctype can only be inserted before an element');
|
|
809
|
+
}
|
|
810
|
+
if (!child && parentElementChild) {
|
|
811
|
+
throw new DOMException(HIERARCHY_REQUEST_ERR, 'Doctype can not be appended since element is present');
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
var cp = node.parentNode;
|
|
664
817
|
if(cp){
|
|
665
|
-
cp.removeChild(
|
|
818
|
+
cp.removeChild(node);//remove and update
|
|
666
819
|
}
|
|
667
|
-
if(
|
|
668
|
-
var newFirst =
|
|
820
|
+
if(node.nodeType === DOCUMENT_FRAGMENT_NODE){
|
|
821
|
+
var newFirst = node.firstChild;
|
|
669
822
|
if (newFirst == null) {
|
|
670
|
-
return
|
|
823
|
+
return node;
|
|
671
824
|
}
|
|
672
|
-
var newLast =
|
|
825
|
+
var newLast = node.lastChild;
|
|
673
826
|
}else{
|
|
674
|
-
newFirst = newLast =
|
|
827
|
+
newFirst = newLast = node;
|
|
675
828
|
}
|
|
676
|
-
var pre =
|
|
829
|
+
var pre = child ? child.previousSibling : parent.lastChild;
|
|
677
830
|
|
|
678
831
|
newFirst.previousSibling = pre;
|
|
679
|
-
newLast.nextSibling =
|
|
680
|
-
|
|
681
|
-
|
|
832
|
+
newLast.nextSibling = child;
|
|
833
|
+
|
|
834
|
+
|
|
682
835
|
if(pre){
|
|
683
836
|
pre.nextSibling = newFirst;
|
|
684
837
|
}else{
|
|
685
|
-
|
|
838
|
+
parent.firstChild = newFirst;
|
|
686
839
|
}
|
|
687
|
-
if(
|
|
688
|
-
|
|
840
|
+
if(child == null){
|
|
841
|
+
parent.lastChild = newLast;
|
|
689
842
|
}else{
|
|
690
|
-
|
|
843
|
+
child.previousSibling = newLast;
|
|
691
844
|
}
|
|
692
845
|
do{
|
|
693
|
-
newFirst.parentNode =
|
|
846
|
+
newFirst.parentNode = parent;
|
|
694
847
|
}while(newFirst !== newLast && (newFirst= newFirst.nextSibling))
|
|
695
|
-
_onUpdateChild(
|
|
696
|
-
//console.log(
|
|
697
|
-
if (
|
|
698
|
-
|
|
848
|
+
_onUpdateChild(parent.ownerDocument||parent, parent);
|
|
849
|
+
//console.log(parent.lastChild.nextSibling == null)
|
|
850
|
+
if (node.nodeType == DOCUMENT_FRAGMENT_NODE) {
|
|
851
|
+
node.firstChild = node.lastChild = null;
|
|
699
852
|
}
|
|
700
|
-
return
|
|
853
|
+
return node;
|
|
701
854
|
}
|
|
702
855
|
|
|
703
856
|
/**
|
|
@@ -752,11 +905,13 @@ Document.prototype = {
|
|
|
752
905
|
}
|
|
753
906
|
return newChild;
|
|
754
907
|
}
|
|
755
|
-
|
|
908
|
+
_insertBefore(this, newChild, refChild);
|
|
909
|
+
newChild.ownerDocument = this;
|
|
910
|
+
if (this.documentElement === null && newChild.nodeType === ELEMENT_NODE) {
|
|
756
911
|
this.documentElement = newChild;
|
|
757
912
|
}
|
|
758
913
|
|
|
759
|
-
return
|
|
914
|
+
return newChild;
|
|
760
915
|
},
|
|
761
916
|
removeChild : function(oldChild){
|
|
762
917
|
if(this.documentElement == oldChild){
|
|
@@ -950,7 +1105,7 @@ Element.prototype = {
|
|
|
950
1105
|
var attr = this.getAttributeNode(name)
|
|
951
1106
|
attr && this.removeAttributeNode(attr);
|
|
952
1107
|
},
|
|
953
|
-
|
|
1108
|
+
|
|
954
1109
|
//four real opeartion method
|
|
955
1110
|
appendChild:function(newChild){
|
|
956
1111
|
if(newChild.nodeType === DOCUMENT_FRAGMENT_NODE){
|
|
@@ -974,7 +1129,7 @@ Element.prototype = {
|
|
|
974
1129
|
var old = this.getAttributeNodeNS(namespaceURI, localName);
|
|
975
1130
|
old && this.removeAttributeNode(old);
|
|
976
1131
|
},
|
|
977
|
-
|
|
1132
|
+
|
|
978
1133
|
hasAttributeNS : function(namespaceURI, localName){
|
|
979
1134
|
return this.getAttributeNodeNS(namespaceURI, localName)!=null;
|
|
980
1135
|
},
|
|
@@ -990,7 +1145,7 @@ Element.prototype = {
|
|
|
990
1145
|
getAttributeNodeNS : function(namespaceURI, localName){
|
|
991
1146
|
return this.attributes.getNamedItemNS(namespaceURI, localName);
|
|
992
1147
|
},
|
|
993
|
-
|
|
1148
|
+
|
|
994
1149
|
getElementsByTagName : function(tagName){
|
|
995
1150
|
return new LiveNodeList(this,function(base){
|
|
996
1151
|
var ls = [];
|
|
@@ -1011,7 +1166,7 @@ Element.prototype = {
|
|
|
1011
1166
|
}
|
|
1012
1167
|
});
|
|
1013
1168
|
return ls;
|
|
1014
|
-
|
|
1169
|
+
|
|
1015
1170
|
});
|
|
1016
1171
|
}
|
|
1017
1172
|
};
|
|
@@ -1040,7 +1195,7 @@ CharacterData.prototype = {
|
|
|
1040
1195
|
},
|
|
1041
1196
|
insertData: function(offset,text) {
|
|
1042
1197
|
this.replaceData(offset,0,text);
|
|
1043
|
-
|
|
1198
|
+
|
|
1044
1199
|
},
|
|
1045
1200
|
appendChild:function(newChild){
|
|
1046
1201
|
throw new Error(ExceptionMessage[HIERARCHY_REQUEST_ERR])
|
|
@@ -1134,7 +1289,7 @@ function nodeSerializeToString(isHtml,nodeFilter){
|
|
|
1134
1289
|
var refNode = this.nodeType == 9 && this.documentElement || this;
|
|
1135
1290
|
var prefix = refNode.prefix;
|
|
1136
1291
|
var uri = refNode.namespaceURI;
|
|
1137
|
-
|
|
1292
|
+
|
|
1138
1293
|
if(uri && prefix == null){
|
|
1139
1294
|
//console.log(prefix)
|
|
1140
1295
|
var prefix = refNode.lookupPrefix(uri);
|
|
@@ -1167,8 +1322,8 @@ function needNamespaceDefine(node, isHTML, visibleNamespaces) {
|
|
|
1167
1322
|
if (prefix === "xml" && uri === NAMESPACE.XML || uri === NAMESPACE.XMLNS) {
|
|
1168
1323
|
return false;
|
|
1169
1324
|
}
|
|
1170
|
-
|
|
1171
|
-
var i = visibleNamespaces.length
|
|
1325
|
+
|
|
1326
|
+
var i = visibleNamespaces.length
|
|
1172
1327
|
while (i--) {
|
|
1173
1328
|
var ns = visibleNamespaces[i];
|
|
1174
1329
|
// get namespace prefix
|
|
@@ -1219,7 +1374,7 @@ function serializeToString(node,buf,isHTML,nodeFilter,visibleNamespaces){
|
|
|
1219
1374
|
var len = attrs.length;
|
|
1220
1375
|
var child = node.firstChild;
|
|
1221
1376
|
var nodeName = node.tagName;
|
|
1222
|
-
|
|
1377
|
+
|
|
1223
1378
|
isHTML = NAMESPACE.isHTML(node.namespaceURI) || isHTML
|
|
1224
1379
|
|
|
1225
1380
|
var prefixedNodeName = nodeName
|
|
@@ -1278,14 +1433,14 @@ function serializeToString(node,buf,isHTML,nodeFilter,visibleNamespaces){
|
|
|
1278
1433
|
serializeToString(attr,buf,isHTML,nodeFilter,visibleNamespaces);
|
|
1279
1434
|
}
|
|
1280
1435
|
|
|
1281
|
-
// add namespace for current node
|
|
1436
|
+
// add namespace for current node
|
|
1282
1437
|
if (nodeName === prefixedNodeName && needNamespaceDefine(node, isHTML, visibleNamespaces)) {
|
|
1283
1438
|
var prefix = node.prefix||'';
|
|
1284
1439
|
var uri = node.namespaceURI;
|
|
1285
1440
|
addSerializedAttribute(buf, prefix ? 'xmlns:' + prefix : "xmlns", uri);
|
|
1286
1441
|
visibleNamespaces.push({ prefix: prefix, namespace:uri });
|
|
1287
1442
|
}
|
|
1288
|
-
|
|
1443
|
+
|
|
1289
1444
|
if(child || isHTML && !/^(?:meta|link|img|br|hr|input)$/i.test(nodeName)){
|
|
1290
1445
|
buf.push('>');
|
|
1291
1446
|
//if is cdata child node
|
|
@@ -1500,7 +1655,7 @@ try{
|
|
|
1500
1655
|
}
|
|
1501
1656
|
}
|
|
1502
1657
|
})
|
|
1503
|
-
|
|
1658
|
+
|
|
1504
1659
|
function getTextContent(node){
|
|
1505
1660
|
switch(node.nodeType){
|
|
1506
1661
|
case ELEMENT_NODE:
|