@xmldom/xmldom 0.9.0-beta.6 → 0.9.0-beta.8
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 +92 -2
- package/lib/conventions.js +22 -0
- package/lib/dom.js +339 -80
- package/lib/entities.js +2095 -210
- package/lib/sax.js +13 -7
- package/package.json +7 -7
package/lib/dom.js
CHANGED
|
@@ -65,6 +65,51 @@ function arrayIncludes(list) {
|
|
|
65
65
|
};
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
/**
|
|
69
|
+
* @param {string} qualifiedName
|
|
70
|
+
* @throws DOMException
|
|
71
|
+
* @see https://dom.spec.whatwg.org/#validate
|
|
72
|
+
*/
|
|
73
|
+
function validateQualifiedName(qualifiedName) {
|
|
74
|
+
if (!conventions.QNAME.test(qualifiedName)) {
|
|
75
|
+
throw new DOMException(INVALID_CHARACTER_ERR, 'invalid character in qualified name "' + qualifiedName + '"');
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
*
|
|
81
|
+
* @param {string | null} namespace
|
|
82
|
+
* @param {string} qualifiedName
|
|
83
|
+
*
|
|
84
|
+
* @returns {[namespace:string|null, prefix:string|null, localName:string]}
|
|
85
|
+
* @see https://dom.spec.whatwg.org/#validate-and-extract
|
|
86
|
+
*/
|
|
87
|
+
function validateAndExtract(namespace, qualifiedName) {
|
|
88
|
+
validateQualifiedName(qualifiedName);
|
|
89
|
+
namespace = namespace || null;
|
|
90
|
+
/** @type {string | null} */
|
|
91
|
+
var prefix = null;
|
|
92
|
+
var localName = qualifiedName;
|
|
93
|
+
if (qualifiedName.indexOf(':') >= 0) {
|
|
94
|
+
var splitResult = qualifiedName.split(':');
|
|
95
|
+
prefix = splitResult[0];
|
|
96
|
+
localName = splitResult[1];
|
|
97
|
+
}
|
|
98
|
+
if (prefix !== null && namespace === null) {
|
|
99
|
+
throw new DOMException(NAMESPACE_ERR, 'prefix is non-null and namespace is null');
|
|
100
|
+
}
|
|
101
|
+
if (prefix === 'xml' && namespace !== conventions.NAMESPACE.XML) {
|
|
102
|
+
throw new DOMException(NAMESPACE_ERR, 'prefix is "xml" and namespace is not the XML namespace');
|
|
103
|
+
}
|
|
104
|
+
if ((prefix === 'xmlns' || qualifiedName === 'xmlns') && namespace !== conventions.NAMESPACE.XMLNS) {
|
|
105
|
+
throw new DOMException(NAMESPACE_ERR, 'either qualifiedName or prefix is "xmlns" and namespace is not the XMLNS namespace');
|
|
106
|
+
}
|
|
107
|
+
if (namespace === conventions.NAMESPACE.XMLNS && prefix !== 'xmlns' && qualifiedName !== 'xmlns') {
|
|
108
|
+
throw new DOMException(NAMESPACE_ERR, 'namespace is the XMLNS namespace and neither qualifiedName nor prefix is "xmlns"');
|
|
109
|
+
}
|
|
110
|
+
return [namespace, prefix, localName];
|
|
111
|
+
}
|
|
112
|
+
|
|
68
113
|
function copy(src, dest) {
|
|
69
114
|
for (var p in src) {
|
|
70
115
|
if (Object.prototype.hasOwnProperty.call(src, p)) {
|
|
@@ -130,6 +175,58 @@ var INVALID_MODIFICATION_ERR = (ExceptionCode.INVALID_MODIFICATION_ERR = ((Excep
|
|
|
130
175
|
var NAMESPACE_ERR = (ExceptionCode.NAMESPACE_ERR = ((ExceptionMessage[14] = 'Invalid namespace'), 14));
|
|
131
176
|
var INVALID_ACCESS_ERR = (ExceptionCode.INVALID_ACCESS_ERR = ((ExceptionMessage[15] = 'Invalid access'), 15));
|
|
132
177
|
|
|
178
|
+
// compareDocumentPosition bitmask results
|
|
179
|
+
var DocumentPosition = {};
|
|
180
|
+
var DOCUMENT_POSITION_DISCONNECTED = (DocumentPosition.DOCUMENT_POSITION_DISCONNECTED = 1);
|
|
181
|
+
var DOCUMENT_POSITION_PRECEDING = (DocumentPosition.DOCUMENT_POSITION_PRECEDING = 2);
|
|
182
|
+
var DOCUMENT_POSITION_FOLLOWING = (DocumentPosition.DOCUMENT_POSITION_FOLLOWING = 4);
|
|
183
|
+
var DOCUMENT_POSITION_CONTAINS = (DocumentPosition.DOCUMENT_POSITION_CONTAINS = 8);
|
|
184
|
+
var DOCUMENT_POSITION_CONTAINED_BY = (DocumentPosition.DOCUMENT_POSITION_CONTAINED_BY = 16);
|
|
185
|
+
var DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = (DocumentPosition.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 32);
|
|
186
|
+
|
|
187
|
+
//helper functions for compareDocumentPosition
|
|
188
|
+
/**
|
|
189
|
+
* Construct a parent chain for a node.
|
|
190
|
+
* @param {Node} node The start node.
|
|
191
|
+
* @return {Node[]} The parent chain.
|
|
192
|
+
*/
|
|
193
|
+
function parentChain(node) {
|
|
194
|
+
var chain = [];
|
|
195
|
+
while (node.parentNode || node.ownerElement) {
|
|
196
|
+
node = node.parentNode || node.ownerElement;
|
|
197
|
+
chain.unshift(node);
|
|
198
|
+
}
|
|
199
|
+
return chain;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Find the common ancestor in two parent chains.
|
|
204
|
+
* @param {Node[]} a A parent chain.
|
|
205
|
+
* @param {Node[]} b A parent chain.
|
|
206
|
+
* @return {Node} The common ancestor if it exists.
|
|
207
|
+
*/
|
|
208
|
+
function commonAncestor(a, b) {
|
|
209
|
+
if (b.length < a.length) return commonAncestor(b, a);
|
|
210
|
+
var c = null;
|
|
211
|
+
for (var n in a) {
|
|
212
|
+
if (a[n] !== b[n]) return c;
|
|
213
|
+
c = a[n];
|
|
214
|
+
}
|
|
215
|
+
return c;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Comparing unrelated nodes must be consistent, so we assign a guid to the
|
|
220
|
+
* compared docs for further reference.
|
|
221
|
+
* @param {Document} doc The document.
|
|
222
|
+
* @return {string} The document's guid.
|
|
223
|
+
*/
|
|
224
|
+
function docGUID(doc) {
|
|
225
|
+
if (!doc.guid) doc.guid = Math.random();
|
|
226
|
+
return doc.guid;
|
|
227
|
+
}
|
|
228
|
+
//-- end of helper functions
|
|
229
|
+
|
|
133
230
|
/**
|
|
134
231
|
* DOM Level 2
|
|
135
232
|
* Object DOMException
|
|
@@ -231,15 +328,22 @@ _extends(LiveNodeList, NodeList);
|
|
|
231
328
|
* and does not imply that the DOM specifies an order to these Nodes.
|
|
232
329
|
* NamedNodeMap objects in the DOM are live.
|
|
233
330
|
* used for attributes or DocumentType entities
|
|
331
|
+
*
|
|
332
|
+
* This implementation only supports property indices, but does not support named properties,
|
|
333
|
+
* as specified in the living standard.
|
|
334
|
+
*
|
|
335
|
+
* @see https://dom.spec.whatwg.org/#interface-namednodemap
|
|
336
|
+
* @see https://webidl.spec.whatwg.org/#dfn-supported-property-names
|
|
234
337
|
*/
|
|
235
338
|
function NamedNodeMap() {}
|
|
236
339
|
|
|
237
340
|
function _findNodeIndex(list, node) {
|
|
238
|
-
var i =
|
|
239
|
-
while (i
|
|
341
|
+
var i = 0;
|
|
342
|
+
while (i < list.length) {
|
|
240
343
|
if (list[i] === node) {
|
|
241
344
|
return i;
|
|
242
345
|
}
|
|
346
|
+
i++;
|
|
243
347
|
}
|
|
244
348
|
}
|
|
245
349
|
|
|
@@ -247,7 +351,8 @@ function _addNamedNode(el, list, newAttr, oldAttr) {
|
|
|
247
351
|
if (oldAttr) {
|
|
248
352
|
list[_findNodeIndex(list, oldAttr)] = newAttr;
|
|
249
353
|
} else {
|
|
250
|
-
list[list.length
|
|
354
|
+
list[list.length] = newAttr;
|
|
355
|
+
list.length++;
|
|
251
356
|
}
|
|
252
357
|
if (el) {
|
|
253
358
|
newAttr.ownerElement = el;
|
|
@@ -263,7 +368,7 @@ function _removeNamedNode(el, list, attr) {
|
|
|
263
368
|
var i = _findNodeIndex(list, attr);
|
|
264
369
|
if (i >= 0) {
|
|
265
370
|
var lastIndex = list.length - 1;
|
|
266
|
-
while (i
|
|
371
|
+
while (i <= lastIndex) {
|
|
267
372
|
list[i] = list[++i];
|
|
268
373
|
}
|
|
269
374
|
list.length = lastIndex;
|
|
@@ -271,72 +376,127 @@ function _removeNamedNode(el, list, attr) {
|
|
|
271
376
|
var doc = el.ownerDocument;
|
|
272
377
|
if (doc) {
|
|
273
378
|
_onRemoveAttribute(doc, el, attr);
|
|
274
|
-
attr.ownerElement = null;
|
|
275
379
|
}
|
|
380
|
+
attr.ownerElement = null;
|
|
276
381
|
}
|
|
277
|
-
} else {
|
|
278
|
-
throw new DOMException(NOT_FOUND_ERR, new Error(el.tagName + '@' + attr));
|
|
279
382
|
}
|
|
280
383
|
}
|
|
281
384
|
NamedNodeMap.prototype = {
|
|
282
385
|
length: 0,
|
|
283
386
|
item: NodeList.prototype.item,
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* get an attribute by name (lower case in case of HTML namespace and document)
|
|
390
|
+
*
|
|
391
|
+
* @param {string} localName
|
|
392
|
+
* @return {Attr | null}
|
|
393
|
+
*
|
|
394
|
+
* @see https://dom.spec.whatwg.org/#concept-element-attributes-get-by-name
|
|
395
|
+
*/
|
|
396
|
+
getNamedItem: function (localName) {
|
|
397
|
+
if (this._ownerElement && this._ownerElement._isInHTMLDocumentAndNamespace()) {
|
|
398
|
+
localName = localName.toLowerCase();
|
|
399
|
+
}
|
|
400
|
+
var i = 0;
|
|
401
|
+
while (i < this.length) {
|
|
291
402
|
var attr = this[i];
|
|
292
|
-
|
|
293
|
-
if (attr.nodeName == key) {
|
|
403
|
+
if (attr.nodeName === localName) {
|
|
294
404
|
return attr;
|
|
295
405
|
}
|
|
406
|
+
i++;
|
|
296
407
|
}
|
|
408
|
+
return null;
|
|
297
409
|
},
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* set an attribute
|
|
413
|
+
*
|
|
414
|
+
* @param {Attr} attr
|
|
415
|
+
* @return {Attr | null}
|
|
416
|
+
* @see https://dom.spec.whatwg.org/#concept-element-attributes-set
|
|
417
|
+
*/
|
|
298
418
|
setNamedItem: function (attr) {
|
|
299
419
|
var el = attr.ownerElement;
|
|
300
|
-
if (el && el
|
|
420
|
+
if (el && el !== this._ownerElement) {
|
|
301
421
|
throw new DOMException(INUSE_ATTRIBUTE_ERR);
|
|
302
422
|
}
|
|
303
|
-
var oldAttr = this.
|
|
423
|
+
var oldAttr = this.getNamedItemNS(attr.namespaceURI, attr.localName);
|
|
424
|
+
if (oldAttr === attr) {
|
|
425
|
+
return attr;
|
|
426
|
+
}
|
|
304
427
|
_addNamedNode(this._ownerElement, this, attr, oldAttr);
|
|
305
428
|
return oldAttr;
|
|
306
429
|
},
|
|
307
|
-
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* set an attribute
|
|
433
|
+
*
|
|
434
|
+
* @param {Attr} attr
|
|
435
|
+
* @return {Attr | null}
|
|
436
|
+
*
|
|
437
|
+
* @see https://dom.spec.whatwg.org/#concept-element-attributes-set
|
|
438
|
+
*/
|
|
308
439
|
setNamedItemNS: function (attr) {
|
|
309
|
-
|
|
310
|
-
var el = attr.ownerElement,
|
|
311
|
-
oldAttr;
|
|
312
|
-
if (el && el != this._ownerElement) {
|
|
313
|
-
throw new DOMException(INUSE_ATTRIBUTE_ERR);
|
|
314
|
-
}
|
|
315
|
-
oldAttr = this.getNamedItemNS(attr.namespaceURI, attr.localName);
|
|
316
|
-
_addNamedNode(this._ownerElement, this, attr, oldAttr);
|
|
317
|
-
return oldAttr;
|
|
440
|
+
return this.setNamedItem(attr);
|
|
318
441
|
},
|
|
319
442
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
443
|
+
/**
|
|
444
|
+
* remove an attribute by name (lower case in case of HTML namespace and document)
|
|
445
|
+
*
|
|
446
|
+
* @param {string} localName
|
|
447
|
+
* @return {Attr | null}
|
|
448
|
+
*
|
|
449
|
+
* @see https://dom.spec.whatwg.org/#dom-namednodemap-removenameditem
|
|
450
|
+
* @see https://dom.spec.whatwg.org/#concept-element-attributes-remove-by-name
|
|
451
|
+
*/
|
|
452
|
+
removeNamedItem: function (localName) {
|
|
453
|
+
var attr = this.getNamedItem(localName);
|
|
454
|
+
if (!attr) {
|
|
455
|
+
throw new DOMException(NOT_FOUND_ERR, localName);
|
|
456
|
+
}
|
|
323
457
|
_removeNamedNode(this._ownerElement, this, attr);
|
|
324
458
|
return attr;
|
|
325
|
-
},
|
|
459
|
+
},
|
|
326
460
|
|
|
327
|
-
|
|
461
|
+
/**
|
|
462
|
+
* remove an attribute by namespace and local name
|
|
463
|
+
*
|
|
464
|
+
* @param {string | null} namespaceURI
|
|
465
|
+
* @param {string} localName
|
|
466
|
+
* @return {Attr | null}
|
|
467
|
+
*
|
|
468
|
+
* @see https://dom.spec.whatwg.org/#dom-namednodemap-removenameditemns
|
|
469
|
+
* @see https://dom.spec.whatwg.org/#concept-element-attributes-remove-by-namespace
|
|
470
|
+
*/
|
|
328
471
|
removeNamedItemNS: function (namespaceURI, localName) {
|
|
329
472
|
var attr = this.getNamedItemNS(namespaceURI, localName);
|
|
473
|
+
if (!attr) {
|
|
474
|
+
throw new DOMException(NOT_FOUND_ERR, namespaceURI ? namespaceURI + ' : ' + localName : localName);
|
|
475
|
+
}
|
|
330
476
|
_removeNamedNode(this._ownerElement, this, attr);
|
|
331
477
|
return attr;
|
|
332
478
|
},
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* get an attribute by namespace and local name
|
|
482
|
+
*
|
|
483
|
+
* @param {string | null} namespaceURI
|
|
484
|
+
* @param {string} localName
|
|
485
|
+
* @return {Attr | null}
|
|
486
|
+
*
|
|
487
|
+
* @see https://dom.spec.whatwg.org/#concept-element-attributes-get-by-namespace
|
|
488
|
+
*/
|
|
333
489
|
getNamedItemNS: function (namespaceURI, localName) {
|
|
334
|
-
|
|
335
|
-
|
|
490
|
+
if (!namespaceURI) {
|
|
491
|
+
namespaceURI = null;
|
|
492
|
+
}
|
|
493
|
+
var i = 0;
|
|
494
|
+
while (i < this.length) {
|
|
336
495
|
var node = this[i];
|
|
337
|
-
if (node.localName
|
|
496
|
+
if (node.localName === localName && node.namespaceURI === namespaceURI) {
|
|
338
497
|
return node;
|
|
339
498
|
}
|
|
499
|
+
i++;
|
|
340
500
|
}
|
|
341
501
|
return null;
|
|
342
502
|
},
|
|
@@ -426,8 +586,6 @@ DOMImplementation.prototype = {
|
|
|
426
586
|
* Returns a doctype, with the given `qualifiedName`, `publicId`, and `systemId`.
|
|
427
587
|
*
|
|
428
588
|
* __This behavior is slightly different from the in the specs__:
|
|
429
|
-
* - this implementation is not validating names or qualified names
|
|
430
|
-
* (when parsing XML strings, the SAX parser takes care of that)
|
|
431
589
|
* - `encoding`, `mode`, `origin`, `url` fields are currently not declared.
|
|
432
590
|
*
|
|
433
591
|
* @param {string} qualifiedName
|
|
@@ -439,12 +597,9 @@ DOMImplementation.prototype = {
|
|
|
439
597
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/DOMImplementation/createDocumentType MDN
|
|
440
598
|
* @see https://www.w3.org/TR/DOM-Level-2-Core/core.html#Level-2-Core-DOM-createDocType DOM Level 2 Core
|
|
441
599
|
* @see https://dom.spec.whatwg.org/#dom-domimplementation-createdocumenttype DOM Living Standard
|
|
442
|
-
*
|
|
443
|
-
* @see https://dom.spec.whatwg.org/#validate-and-extract DOM: Validate and extract
|
|
444
|
-
* @see https://www.w3.org/TR/xml/#NT-NameStartChar XML Spec: Names
|
|
445
|
-
* @see https://www.w3.org/TR/xml-names/#ns-qualnames XML Namespaces: Qualified names
|
|
446
600
|
*/
|
|
447
601
|
createDocumentType: function (qualifiedName, publicId, systemId) {
|
|
602
|
+
validateQualifiedName(qualifiedName);
|
|
448
603
|
var node = new DocumentType();
|
|
449
604
|
node.name = qualifiedName;
|
|
450
605
|
node.nodeName = qualifiedName;
|
|
@@ -603,6 +758,62 @@ Node.prototype = {
|
|
|
603
758
|
var prefix = this.lookupPrefix(namespaceURI);
|
|
604
759
|
return prefix == null;
|
|
605
760
|
},
|
|
761
|
+
// Introduced in DOM Level 3:
|
|
762
|
+
/**
|
|
763
|
+
* Compares the reference node with a node with regard to their position
|
|
764
|
+
* in the document and according to the document order.
|
|
765
|
+
*
|
|
766
|
+
* @param {Node} other The node to compare the reference node to.
|
|
767
|
+
* @return {number} Returns how the node is positioned relatively to the
|
|
768
|
+
* reference node according to the bitmask. 0 if reference node and
|
|
769
|
+
* given node are the same.
|
|
770
|
+
* @see https://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#Node3-compareDocumentPosition
|
|
771
|
+
*/
|
|
772
|
+
compareDocumentPosition: function (other) {
|
|
773
|
+
if (this === other) return 0;
|
|
774
|
+
var node1 = other;
|
|
775
|
+
var node2 = this;
|
|
776
|
+
var attr1 = null;
|
|
777
|
+
var attr2 = null;
|
|
778
|
+
if (node1 instanceof Attr) {
|
|
779
|
+
attr1 = node1;
|
|
780
|
+
node1 = attr1.ownerElement;
|
|
781
|
+
}
|
|
782
|
+
if (node2 instanceof Attr) {
|
|
783
|
+
attr2 = node2;
|
|
784
|
+
node2 = attr2.ownerElement;
|
|
785
|
+
if (attr1 && node1 && node2 === node1) {
|
|
786
|
+
for (var i = 0, attr; (attr = node2.attributes[i]); i++) {
|
|
787
|
+
if (attr === attr1) return DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC + DOCUMENT_POSITION_PRECEDING;
|
|
788
|
+
if (attr === attr2) return DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC + DOCUMENT_POSITION_FOLLOWING;
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
if (!node1 || !node2 || node2.ownerDocument !== node1.ownerDocument) {
|
|
793
|
+
return (
|
|
794
|
+
DOCUMENT_POSITION_DISCONNECTED +
|
|
795
|
+
DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC +
|
|
796
|
+
(docGUID(node2.ownerDocument) > docGUID(node1.ownerDocument) ? DOCUMENT_POSITION_FOLLOWING : DOCUMENT_POSITION_PRECEDING)
|
|
797
|
+
);
|
|
798
|
+
}
|
|
799
|
+
var chain1 = parentChain(node1);
|
|
800
|
+
var chain2 = parentChain(node2);
|
|
801
|
+
if ((!attr1 && chain2.indexOf(node1) >= 0) || (attr2 && node1 === node2)) {
|
|
802
|
+
return DOCUMENT_POSITION_CONTAINS + DOCUMENT_POSITION_PRECEDING;
|
|
803
|
+
}
|
|
804
|
+
if ((!attr2 && chain1.indexOf(node2) >= 0) || (attr1 && node1 === node2)) {
|
|
805
|
+
return DOCUMENT_POSITION_CONTAINED_BY + DOCUMENT_POSITION_FOLLOWING;
|
|
806
|
+
}
|
|
807
|
+
var ca = commonAncestor(chain2, chain1);
|
|
808
|
+
for (var n in ca.childNodes) {
|
|
809
|
+
var child = ca.childNodes[n];
|
|
810
|
+
if (child === node2) return DOCUMENT_POSITION_FOLLOWING;
|
|
811
|
+
if (child === node1) return DOCUMENT_POSITION_PRECEDING;
|
|
812
|
+
if (chain2.indexOf(child) >= 0) return DOCUMENT_POSITION_FOLLOWING;
|
|
813
|
+
if (chain1.indexOf(child) >= 0) return DOCUMENT_POSITION_PRECEDING;
|
|
814
|
+
}
|
|
815
|
+
return 0;
|
|
816
|
+
},
|
|
606
817
|
};
|
|
607
818
|
|
|
608
819
|
function _xmlEncoder(c) {
|
|
@@ -613,6 +824,8 @@ function _xmlEncoder(c) {
|
|
|
613
824
|
|
|
614
825
|
copy(NodeType, Node);
|
|
615
826
|
copy(NodeType, Node.prototype);
|
|
827
|
+
copy(DocumentPosition, Node);
|
|
828
|
+
copy(DocumentPosition, Node.prototype);
|
|
616
829
|
|
|
617
830
|
/**
|
|
618
831
|
* @param callback return true for continue,false for break
|
|
@@ -739,22 +952,26 @@ function _onUpdateChild(doc, el, newChild) {
|
|
|
739
952
|
* @private
|
|
740
953
|
*/
|
|
741
954
|
function _removeChild(parentNode, child) {
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
955
|
+
if (parentNode !== child.parentNode) {
|
|
956
|
+
throw new DOMException(NOT_FOUND_ERR, "child's parent is not parent");
|
|
957
|
+
}
|
|
958
|
+
//var index = parentNode.childNodes.
|
|
959
|
+
var oldPreviousSibling = child.previousSibling;
|
|
960
|
+
var oldNextSibling = child.nextSibling;
|
|
961
|
+
if (oldPreviousSibling) {
|
|
962
|
+
oldPreviousSibling.nextSibling = oldNextSibling;
|
|
746
963
|
} else {
|
|
747
|
-
parentNode.firstChild =
|
|
964
|
+
parentNode.firstChild = oldNextSibling;
|
|
748
965
|
}
|
|
749
|
-
if (
|
|
750
|
-
|
|
966
|
+
if (oldNextSibling) {
|
|
967
|
+
oldNextSibling.previousSibling = oldPreviousSibling;
|
|
751
968
|
} else {
|
|
752
|
-
parentNode.lastChild =
|
|
969
|
+
parentNode.lastChild = oldPreviousSibling;
|
|
753
970
|
}
|
|
971
|
+
_onUpdateChild(parentNode.ownerDocument, parentNode);
|
|
754
972
|
child.parentNode = null;
|
|
755
973
|
child.previousSibling = null;
|
|
756
974
|
child.nextSibling = null;
|
|
757
|
-
_onUpdateChild(parentNode.ownerDocument, parentNode);
|
|
758
975
|
return child;
|
|
759
976
|
}
|
|
760
977
|
|
|
@@ -1132,10 +1349,11 @@ Document.prototype = {
|
|
|
1132
1349
|
return newChild;
|
|
1133
1350
|
},
|
|
1134
1351
|
removeChild: function (oldChild) {
|
|
1135
|
-
|
|
1352
|
+
var removed = _removeChild(this, oldChild);
|
|
1353
|
+
if (removed === this.documentElement) {
|
|
1136
1354
|
this.documentElement = null;
|
|
1137
1355
|
}
|
|
1138
|
-
return
|
|
1356
|
+
return removed;
|
|
1139
1357
|
},
|
|
1140
1358
|
replaceChild: function (newChild, oldChild) {
|
|
1141
1359
|
//raises
|
|
@@ -1293,6 +1511,9 @@ Document.prototype = {
|
|
|
1293
1511
|
* @see https://dom.spec.whatwg.org/#dom-document-createattribute
|
|
1294
1512
|
*/
|
|
1295
1513
|
createAttribute: function (name) {
|
|
1514
|
+
if (!conventions.QNAME.test(name)) {
|
|
1515
|
+
throw new DOMException(INVALID_CHARACTER_ERR, 'invalid character in name "' + name + '"');
|
|
1516
|
+
}
|
|
1296
1517
|
if (this.type === 'html') {
|
|
1297
1518
|
name = name.toLowerCase();
|
|
1298
1519
|
}
|
|
@@ -1315,40 +1536,31 @@ Document.prototype = {
|
|
|
1315
1536
|
},
|
|
1316
1537
|
// Introduced in DOM Level 2:
|
|
1317
1538
|
createElementNS: function (namespaceURI, qualifiedName) {
|
|
1539
|
+
var validated = validateAndExtract(namespaceURI, qualifiedName);
|
|
1318
1540
|
var node = new Element();
|
|
1319
|
-
var pl = qualifiedName.split(':');
|
|
1320
1541
|
var attrs = (node.attributes = new NamedNodeMap());
|
|
1321
1542
|
node.childNodes = new NodeList();
|
|
1322
1543
|
node.ownerDocument = this;
|
|
1323
1544
|
node.nodeName = qualifiedName;
|
|
1324
1545
|
node.tagName = qualifiedName;
|
|
1325
|
-
node.namespaceURI =
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
node.localName = pl[1];
|
|
1329
|
-
} else {
|
|
1330
|
-
//el.prefix = null;
|
|
1331
|
-
node.localName = qualifiedName;
|
|
1332
|
-
}
|
|
1546
|
+
node.namespaceURI = validated[0];
|
|
1547
|
+
node.prefix = validated[1];
|
|
1548
|
+
node.localName = validated[2];
|
|
1333
1549
|
attrs._ownerElement = node;
|
|
1334
1550
|
return node;
|
|
1335
1551
|
},
|
|
1336
1552
|
// Introduced in DOM Level 2:
|
|
1337
1553
|
createAttributeNS: function (namespaceURI, qualifiedName) {
|
|
1554
|
+
var validated = validateAndExtract(namespaceURI, qualifiedName);
|
|
1338
1555
|
var node = new Attr();
|
|
1339
1556
|
var pl = qualifiedName.split(':');
|
|
1340
1557
|
node.ownerDocument = this;
|
|
1341
1558
|
node.nodeName = qualifiedName;
|
|
1342
1559
|
node.name = qualifiedName;
|
|
1343
|
-
node.namespaceURI = namespaceURI;
|
|
1344
1560
|
node.specified = true;
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
} else {
|
|
1349
|
-
//el.prefix = null;
|
|
1350
|
-
node.localName = qualifiedName;
|
|
1351
|
-
}
|
|
1561
|
+
node.namespaceURI = validated[0];
|
|
1562
|
+
node.prefix = validated[1];
|
|
1563
|
+
node.localName = validated[2];
|
|
1352
1564
|
return node;
|
|
1353
1565
|
},
|
|
1354
1566
|
};
|
|
@@ -1366,11 +1578,17 @@ Element.prototype = {
|
|
|
1366
1578
|
return this.ownerDocument.type === 'html' && this.namespaceURI === NAMESPACE.HTML;
|
|
1367
1579
|
},
|
|
1368
1580
|
hasAttribute: function (name) {
|
|
1369
|
-
return this.getAttributeNode(name)
|
|
1581
|
+
return !!this.getAttributeNode(name);
|
|
1370
1582
|
},
|
|
1583
|
+
/**
|
|
1584
|
+
* Returns element’s first attribute whose qualified name is `name`, and `null` if there is no such attribute.
|
|
1585
|
+
*
|
|
1586
|
+
* @param {string} name
|
|
1587
|
+
* @return {string | null}
|
|
1588
|
+
*/
|
|
1371
1589
|
getAttribute: function (name) {
|
|
1372
1590
|
var attr = this.getAttributeNode(name);
|
|
1373
|
-
return
|
|
1591
|
+
return attr ? attr.value : null;
|
|
1374
1592
|
},
|
|
1375
1593
|
getAttributeNode: function (name) {
|
|
1376
1594
|
if (this._isInHTMLDocumentAndNamespace()) {
|
|
@@ -1378,13 +1596,24 @@ Element.prototype = {
|
|
|
1378
1596
|
}
|
|
1379
1597
|
return this.attributes.getNamedItem(name);
|
|
1380
1598
|
},
|
|
1599
|
+
/**
|
|
1600
|
+
* Sets the value of element’s first attribute whose qualified name is qualifiedName to value.
|
|
1601
|
+
*
|
|
1602
|
+
* @param {string} name
|
|
1603
|
+
* @param {string} value
|
|
1604
|
+
*/
|
|
1381
1605
|
setAttribute: function (name, value) {
|
|
1382
1606
|
if (this._isInHTMLDocumentAndNamespace()) {
|
|
1383
1607
|
name = name.toLowerCase();
|
|
1384
1608
|
}
|
|
1385
|
-
var attr = this.
|
|
1386
|
-
|
|
1387
|
-
|
|
1609
|
+
var attr = this.getAttributeNode(name);
|
|
1610
|
+
if (attr) {
|
|
1611
|
+
attr.value = attr.nodeValue = '' + value;
|
|
1612
|
+
} else {
|
|
1613
|
+
attr = this.ownerDocument._createAttribute(name);
|
|
1614
|
+
attr.value = attr.nodeValue = '' + value;
|
|
1615
|
+
this.setAttributeNode(attr);
|
|
1616
|
+
}
|
|
1388
1617
|
},
|
|
1389
1618
|
removeAttribute: function (name) {
|
|
1390
1619
|
var attr = this.getAttributeNode(name);
|
|
@@ -1418,14 +1647,38 @@ Element.prototype = {
|
|
|
1418
1647
|
hasAttributeNS: function (namespaceURI, localName) {
|
|
1419
1648
|
return this.getAttributeNodeNS(namespaceURI, localName) != null;
|
|
1420
1649
|
},
|
|
1650
|
+
/**
|
|
1651
|
+
* Returns element’s attribute whose namespace is `namespaceURI` and local name is `localName`,
|
|
1652
|
+
* or `null` if there is no such attribute.
|
|
1653
|
+
*
|
|
1654
|
+
* @param {string} namespaceURI
|
|
1655
|
+
* @param {string} localName
|
|
1656
|
+
* @return {string | null}
|
|
1657
|
+
*/
|
|
1421
1658
|
getAttributeNS: function (namespaceURI, localName) {
|
|
1422
1659
|
var attr = this.getAttributeNodeNS(namespaceURI, localName);
|
|
1423
|
-
return
|
|
1660
|
+
return attr ? attr.value : null;
|
|
1424
1661
|
},
|
|
1662
|
+
/**
|
|
1663
|
+
* Sets the value of element’s attribute whose namespace is `namespaceURI` and local name is `localName` to value.
|
|
1664
|
+
*
|
|
1665
|
+
* @param {string} namespaceURI
|
|
1666
|
+
* @param {string} qualifiedName
|
|
1667
|
+
* @param {string} value
|
|
1668
|
+
*
|
|
1669
|
+
* @see https://dom.spec.whatwg.org/#dom-element-setattributens
|
|
1670
|
+
*/
|
|
1425
1671
|
setAttributeNS: function (namespaceURI, qualifiedName, value) {
|
|
1426
|
-
var
|
|
1427
|
-
|
|
1428
|
-
this.
|
|
1672
|
+
var validated = validateAndExtract(namespaceURI, qualifiedName);
|
|
1673
|
+
var localName = validated[2];
|
|
1674
|
+
var attr = this.getAttributeNodeNS(namespaceURI, localName);
|
|
1675
|
+
if (attr) {
|
|
1676
|
+
attr.value = attr.nodeValue = '' + value;
|
|
1677
|
+
} else {
|
|
1678
|
+
attr = this.ownerDocument.createAttributeNS(namespaceURI, qualifiedName);
|
|
1679
|
+
attr.value = attr.nodeValue = '' + value;
|
|
1680
|
+
this.setAttributeNode(attr);
|
|
1681
|
+
}
|
|
1429
1682
|
},
|
|
1430
1683
|
getAttributeNodeNS: function (namespaceURI, localName) {
|
|
1431
1684
|
return this.attributes.getNamedItemNS(namespaceURI, localName);
|
|
@@ -1499,7 +1752,11 @@ Document.prototype.getElementsByTagName = Element.prototype.getElementsByTagName
|
|
|
1499
1752
|
Document.prototype.getElementsByTagNameNS = Element.prototype.getElementsByTagNameNS;
|
|
1500
1753
|
|
|
1501
1754
|
_extends(Element, Node);
|
|
1502
|
-
function Attr() {
|
|
1755
|
+
function Attr() {
|
|
1756
|
+
this.namespaceURI = null;
|
|
1757
|
+
this.prefix = null;
|
|
1758
|
+
this.ownerElement = null;
|
|
1759
|
+
}
|
|
1503
1760
|
Attr.prototype.nodeType = ATTRIBUTE_NODE;
|
|
1504
1761
|
_extends(Attr, Node);
|
|
1505
1762
|
|
|
@@ -1994,11 +2251,13 @@ try {
|
|
|
1994
2251
|
//ie8
|
|
1995
2252
|
}
|
|
1996
2253
|
|
|
2254
|
+
exports.Attr = Attr;
|
|
1997
2255
|
exports.Document = Document;
|
|
1998
2256
|
exports.DocumentType = DocumentType;
|
|
1999
2257
|
exports.DOMException = DOMException;
|
|
2000
2258
|
exports.DOMImplementation = DOMImplementation;
|
|
2001
2259
|
exports.Element = Element;
|
|
2260
|
+
exports.NamedNodeMap = NamedNodeMap;
|
|
2002
2261
|
exports.Node = Node;
|
|
2003
2262
|
exports.NodeList = NodeList;
|
|
2004
2263
|
exports.XMLSerializer = XMLSerializer;
|