@xmldom/xmldom 0.9.0-beta.8 → 0.9.0

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/lib/dom.js CHANGED
@@ -2,25 +2,63 @@
2
2
 
3
3
  var conventions = require('./conventions');
4
4
  var find = conventions.find;
5
+ var hasDefaultHTMLNamespace = conventions.hasDefaultHTMLNamespace;
6
+ var hasOwn = conventions.hasOwn;
7
+ var isHTMLMimeType = conventions.isHTMLMimeType;
5
8
  var isHTMLRawTextElement = conventions.isHTMLRawTextElement;
6
9
  var isHTMLVoidElement = conventions.isHTMLVoidElement;
7
10
  var MIME_TYPE = conventions.MIME_TYPE;
8
11
  var NAMESPACE = conventions.NAMESPACE;
9
12
 
10
13
  /**
11
- * A prerequisite for `[].filter`, to drop elements that are empty
14
+ * Private DOM Constructor symbol
15
+ *
16
+ * Internal symbol used for construction of all classes whose constructors should be private.
17
+ * Currently used for checks in `Node`, `Document`, `Element`, `Attr`, `CharacterData`, `Text`, `Comment`,
18
+ * `CDATASection`, `DocumentType`, `Notation`, `Entity`, `EntityReference`, `DocumentFragment`, `ProcessingInstruction`
19
+ * so the constructor can't be used from outside the module.
20
+ */
21
+ var PDC = Symbol();
22
+
23
+ var errors = require('./errors');
24
+ var DOMException = errors.DOMException;
25
+
26
+ var g = require('./grammar');
27
+
28
+ /**
29
+ * Checks if the given symbol equals the Private DOM Constructor symbol (PDC)
30
+ * and throws an Illegal constructor exception when the symbols don't match.
31
+ * This ensures that the constructor remains private and can't be used outside this module.
32
+ */
33
+ function checkSymbol(symbol) {
34
+ if (symbol !== PDC) {
35
+ throw new TypeError('Illegal constructor');
36
+ }
37
+ }
38
+
39
+ /**
40
+ * A prerequisite for `[].filter`, to drop elements that are empty.
41
+ *
12
42
  * @param {string} input
43
+ * The string to be checked.
13
44
  * @returns {boolean}
45
+ * Returns `true` if the input string is not empty, `false` otherwise.
14
46
  */
15
47
  function notEmptyString(input) {
16
48
  return input !== '';
17
49
  }
18
50
  /**
19
- * @see https://infra.spec.whatwg.org/#split-on-ascii-whitespace
20
- * @see https://infra.spec.whatwg.org/#ascii-whitespace
51
+ * Splits a string on ASCII whitespace characters (U+0009 TAB, U+000A LF, U+000C FF, U+000D CR,
52
+ * U+0020 SPACE).
53
+ * It follows the definition from the infra specification from WHATWG.
21
54
  *
22
55
  * @param {string} input
23
- * @returns {string[]} (can be empty)
56
+ * The string to be split.
57
+ * @returns {string[]}
58
+ * An array of the split strings. The array can be empty if the input string is empty or only
59
+ * contains whitespace characters.
60
+ * @see {@link https://infra.spec.whatwg.org/#split-on-ascii-whitespace}
61
+ * @see {@link https://infra.spec.whatwg.org/#ascii-whitespace}
24
62
  */
25
63
  function splitOnASCIIWhitespace(input) {
26
64
  // U+0009 TAB, U+000A LF, U+000C FF, U+000D CR, U+0020 SPACE
@@ -31,20 +69,31 @@ function splitOnASCIIWhitespace(input) {
31
69
  * Adds element as a key to current if it is not already present.
32
70
  *
33
71
  * @param {Record<string, boolean | undefined>} current
72
+ * The current record object to which the element will be added as a key.
73
+ * The object's keys are string types and values are either boolean or undefined.
34
74
  * @param {string} element
75
+ * The string to be added as a key to the current record.
35
76
  * @returns {Record<string, boolean | undefined>}
77
+ * The updated record object after the addition of the new element.
36
78
  */
37
79
  function orderedSetReducer(current, element) {
38
- if (!current.hasOwnProperty(element)) {
80
+ if (!hasOwn(current, element)) {
39
81
  current[element] = true;
40
82
  }
41
83
  return current;
42
84
  }
43
85
 
44
86
  /**
45
- * @see https://infra.spec.whatwg.org/#ordered-set
87
+ * Converts a string into an ordered set by splitting the input on ASCII whitespace and
88
+ * ensuring uniqueness of elements.
89
+ * This follows the definition of an ordered set from the infra specification by WHATWG.
90
+ *
46
91
  * @param {string} input
92
+ * The input string to be transformed into an ordered set.
47
93
  * @returns {string[]}
94
+ * An array of unique strings obtained from the input, preserving the original order.
95
+ * The array can be empty if the input string is empty or only contains whitespace characters.
96
+ * @see {@link https://infra.spec.whatwg.org/#ordered-set}
48
97
  */
49
98
  function toOrderedSet(input) {
50
99
  if (!input) return [];
@@ -53,11 +102,14 @@ function toOrderedSet(input) {
53
102
  }
54
103
 
55
104
  /**
56
- * Uses `list.indexOf` to implement something like `Array.prototype.includes`,
57
- * which we can not rely on being available.
105
+ * Uses `list.indexOf` to implement a function that behaves like `Array.prototype.includes`.
106
+ * This function is used in environments where `Array.prototype.includes` may not be available.
58
107
  *
59
108
  * @param {any[]} list
109
+ * The array in which to search for the element.
60
110
  * @returns {function(any): boolean}
111
+ * A function that accepts an element and returns a boolean indicating whether the element is
112
+ * included in the provided list.
61
113
  */
62
114
  function arrayIncludes(list) {
63
115
  return function (element) {
@@ -66,28 +118,43 @@ function arrayIncludes(list) {
66
118
  }
67
119
 
68
120
  /**
121
+ * Validates a qualified name based on the criteria provided in the DOM specification by
122
+ * WHATWG.
123
+ *
69
124
  * @param {string} qualifiedName
70
- * @throws DOMException
71
- * @see https://dom.spec.whatwg.org/#validate
125
+ * The qualified name to be validated.
126
+ * @throws {DOMException}
127
+ * With code {@link DOMException.INVALID_CHARACTER_ERR} if the qualified name contains an
128
+ * invalid character.
129
+ * @see {@link https://dom.spec.whatwg.org/#validate}
72
130
  */
73
131
  function validateQualifiedName(qualifiedName) {
74
- if (!conventions.QNAME.test(qualifiedName)) {
75
- throw new DOMException(INVALID_CHARACTER_ERR, 'invalid character in qualified name "' + qualifiedName + '"');
132
+ if (!g.QName_exact.test(qualifiedName)) {
133
+ throw new DOMException(DOMException.INVALID_CHARACTER_ERR, 'invalid character in qualified name "' + qualifiedName + '"');
76
134
  }
77
135
  }
78
136
 
79
137
  /**
138
+ * Validates a qualified name and the namespace associated with it,
139
+ * based on the criteria provided in the DOM specification by WHATWG.
80
140
  *
81
141
  * @param {string | null} namespace
142
+ * The namespace to be validated. It can be a string or null.
82
143
  * @param {string} qualifiedName
83
- *
84
- * @returns {[namespace:string|null, prefix:string|null, localName:string]}
85
- * @see https://dom.spec.whatwg.org/#validate-and-extract
144
+ * The qualified name to be validated.
145
+ * @returns {[namespace: string | null, prefix: string | null, localName: string]}
146
+ * Returns a tuple with the namespace,
147
+ * prefix and local name of the qualified name.
148
+ * @throws {DOMException}
149
+ * Throws a DOMException if the qualified name or the namespace is not valid.
150
+ * @see {@link https://dom.spec.whatwg.org/#validate-and-extract}
86
151
  */
87
152
  function validateAndExtract(namespace, qualifiedName) {
88
153
  validateQualifiedName(qualifiedName);
89
154
  namespace = namespace || null;
90
- /** @type {string | null} */
155
+ /**
156
+ * @type {string | null}
157
+ */
91
158
  var prefix = null;
92
159
  var localName = qualifiedName;
93
160
  if (qualifiedName.indexOf(':') >= 0) {
@@ -96,31 +163,57 @@ function validateAndExtract(namespace, qualifiedName) {
96
163
  localName = splitResult[1];
97
164
  }
98
165
  if (prefix !== null && namespace === null) {
99
- throw new DOMException(NAMESPACE_ERR, 'prefix is non-null and namespace is null');
166
+ throw new DOMException(DOMException.NAMESPACE_ERR, 'prefix is non-null and namespace is null');
100
167
  }
101
168
  if (prefix === 'xml' && namespace !== conventions.NAMESPACE.XML) {
102
- throw new DOMException(NAMESPACE_ERR, 'prefix is "xml" and namespace is not the XML namespace');
169
+ throw new DOMException(DOMException.NAMESPACE_ERR, 'prefix is "xml" and namespace is not the XML namespace');
103
170
  }
104
171
  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');
172
+ throw new DOMException(
173
+ DOMException.NAMESPACE_ERR,
174
+ 'either qualifiedName or prefix is "xmlns" and namespace is not the XMLNS namespace'
175
+ );
106
176
  }
107
177
  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"');
178
+ throw new DOMException(
179
+ DOMException.NAMESPACE_ERR,
180
+ 'namespace is the XMLNS namespace and neither qualifiedName nor prefix is "xmlns"'
181
+ );
109
182
  }
110
183
  return [namespace, prefix, localName];
111
184
  }
112
185
 
186
+ /**
187
+ * Copies properties from one object to another.
188
+ * It only copies the object's own (not inherited) properties.
189
+ *
190
+ * @param {Object} src
191
+ * The source object from which properties are copied.
192
+ * @param {Object} dest
193
+ * The destination object to which properties are copied.
194
+ */
113
195
  function copy(src, dest) {
114
196
  for (var p in src) {
115
- if (Object.prototype.hasOwnProperty.call(src, p)) {
197
+ if (hasOwn(src, p)) {
116
198
  dest[p] = src[p];
117
199
  }
118
200
  }
119
201
  }
120
202
 
121
203
  /**
122
- ^\w+\.prototype\.([_\w]+)\s*=\s*((?:.*\{\s*?[\r\n][\s\S]*?^})|\S.*?(?=[;\r\n]));?
123
- ^\w+\.prototype\.([_\w]+)\s*=\s*(\S.*?(?=[;\r\n]));?
204
+ * Extends a class with the properties and methods of a super class.
205
+ * It uses a form of prototypal inheritance, and establishes the `constructor` property
206
+ * correctly(?).
207
+ *
208
+ * It is not clear to the current maintainers if this implementation is making sense,
209
+ * since it creates an intermediate prototype function,
210
+ * which all properties of `Super` are copied onto using `_copy`.
211
+ *
212
+ * @param {Object} Class
213
+ * The class that is to be extended.
214
+ * @param {Object} Super
215
+ * The super class from which properties and methods are inherited.
216
+ * @private
124
217
  */
125
218
  function _extends(Class, Super) {
126
219
  var pt = Class.prototype;
@@ -139,7 +232,6 @@ function _extends(Class, Super) {
139
232
  }
140
233
  }
141
234
 
142
- // Node Types
143
235
  var NodeType = {};
144
236
  var ELEMENT_NODE = (NodeType.ELEMENT_NODE = 1);
145
237
  var ATTRIBUTE_NODE = (NodeType.ATTRIBUTE_NODE = 2);
@@ -154,41 +246,23 @@ var DOCUMENT_TYPE_NODE = (NodeType.DOCUMENT_TYPE_NODE = 10);
154
246
  var DOCUMENT_FRAGMENT_NODE = (NodeType.DOCUMENT_FRAGMENT_NODE = 11);
155
247
  var NOTATION_NODE = (NodeType.NOTATION_NODE = 12);
156
248
 
157
- // ExceptionCode
158
- var ExceptionCode = {};
159
- var ExceptionMessage = {};
160
- var INDEX_SIZE_ERR = (ExceptionCode.INDEX_SIZE_ERR = ((ExceptionMessage[1] = 'Index size error'), 1));
161
- var DOMSTRING_SIZE_ERR = (ExceptionCode.DOMSTRING_SIZE_ERR = ((ExceptionMessage[2] = 'DOMString size error'), 2));
162
- var HIERARCHY_REQUEST_ERR = (ExceptionCode.HIERARCHY_REQUEST_ERR = ((ExceptionMessage[3] = 'Hierarchy request error'), 3));
163
- var WRONG_DOCUMENT_ERR = (ExceptionCode.WRONG_DOCUMENT_ERR = ((ExceptionMessage[4] = 'Wrong document'), 4));
164
- var INVALID_CHARACTER_ERR = (ExceptionCode.INVALID_CHARACTER_ERR = ((ExceptionMessage[5] = 'Invalid character'), 5));
165
- var NO_DATA_ALLOWED_ERR = (ExceptionCode.NO_DATA_ALLOWED_ERR = ((ExceptionMessage[6] = 'No data allowed'), 6));
166
- var NO_MODIFICATION_ALLOWED_ERR = (ExceptionCode.NO_MODIFICATION_ALLOWED_ERR =
167
- ((ExceptionMessage[7] = 'No modification allowed'), 7));
168
- var NOT_FOUND_ERR = (ExceptionCode.NOT_FOUND_ERR = ((ExceptionMessage[8] = 'Not found'), 8));
169
- var NOT_SUPPORTED_ERR = (ExceptionCode.NOT_SUPPORTED_ERR = ((ExceptionMessage[9] = 'Not supported'), 9));
170
- var INUSE_ATTRIBUTE_ERR = (ExceptionCode.INUSE_ATTRIBUTE_ERR = ((ExceptionMessage[10] = 'Attribute in use'), 10));
171
- //level2
172
- var INVALID_STATE_ERR = (ExceptionCode.INVALID_STATE_ERR = ((ExceptionMessage[11] = 'Invalid state'), 11));
173
- var SYNTAX_ERR = (ExceptionCode.SYNTAX_ERR = ((ExceptionMessage[12] = 'Syntax error'), 12));
174
- var INVALID_MODIFICATION_ERR = (ExceptionCode.INVALID_MODIFICATION_ERR = ((ExceptionMessage[13] = 'Invalid modification'), 13));
175
- var NAMESPACE_ERR = (ExceptionCode.NAMESPACE_ERR = ((ExceptionMessage[14] = 'Invalid namespace'), 14));
176
- var INVALID_ACCESS_ERR = (ExceptionCode.INVALID_ACCESS_ERR = ((ExceptionMessage[15] = 'Invalid access'), 15));
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);
249
+ var DocumentPosition = conventions.freeze({
250
+ DOCUMENT_POSITION_DISCONNECTED: 1,
251
+ DOCUMENT_POSITION_PRECEDING: 2,
252
+ DOCUMENT_POSITION_FOLLOWING: 4,
253
+ DOCUMENT_POSITION_CONTAINS: 8,
254
+ DOCUMENT_POSITION_CONTAINED_BY: 16,
255
+ DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC: 32,
256
+ });
186
257
 
187
258
  //helper functions for compareDocumentPosition
188
259
  /**
189
- * Construct a parent chain for a node.
190
- * @param {Node} node The start node.
191
- * @return {Node[]} The parent chain.
260
+ * Constructs a parent chain for a node.
261
+ *
262
+ * @param {Node} node
263
+ * The start node from which the parent chain will be constructed.
264
+ * @returns {Node[]}
265
+ * The array of nodes representing the parent chain from the root to the specified node.
192
266
  */
193
267
  function parentChain(node) {
194
268
  var chain = [];
@@ -200,10 +274,15 @@ function parentChain(node) {
200
274
  }
201
275
 
202
276
  /**
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.
277
+ * Finds the common ancestor in two parent chains.
278
+ *
279
+ * @param {Node[]} a
280
+ * The first parent chain.
281
+ * @param {Node[]} b
282
+ * The second parent chain.
283
+ * @returns {Node}
284
+ * The common ancestor node if it exists. If there is no common ancestor, the function will
285
+ * return `null`.
207
286
  */
208
287
  function commonAncestor(a, b) {
209
288
  if (b.length < a.length) return commonAncestor(b, a);
@@ -216,10 +295,14 @@ function commonAncestor(a, b) {
216
295
  }
217
296
 
218
297
  /**
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.
298
+ * Assigns a unique identifier to a document to ensure consistency while comparing unrelated
299
+ * nodes.
300
+ *
301
+ * @param {Document} doc
302
+ * The document to which a unique identifier is to be assigned.
303
+ * @returns {string}
304
+ * The unique identifier of the document. If the document already had a unique identifier, the
305
+ * function will return the existing one.
223
306
  */
224
307
  function docGUID(doc) {
225
308
  if (!doc.guid) doc.guid = Math.random();
@@ -228,50 +311,46 @@ function docGUID(doc) {
228
311
  //-- end of helper functions
229
312
 
230
313
  /**
231
- * DOM Level 2
232
- * Object DOMException
233
- * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/ecma-script-binding.html
234
- * @see http://www.w3.org/TR/REC-DOM-Level-1/ecma-script-language-binding.html
235
- */
236
- function DOMException(code, message) {
237
- if (message instanceof Error) {
238
- var error = message;
239
- } else {
240
- error = this;
241
- Error.call(this, ExceptionMessage[code]);
242
- this.message = ExceptionMessage[code];
243
- if (Error.captureStackTrace) Error.captureStackTrace(this, DOMException);
244
- }
245
- error.code = code;
246
- if (message) this.message = this.message + ': ' + message;
247
- return error;
248
- }
249
- DOMException.prototype = Error.prototype;
250
- copy(ExceptionCode, DOMException);
251
-
252
- /**
253
- * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-536297177
254
- * The NodeList interface provides the abstraction of an ordered collection of nodes, without defining or constraining how this collection is implemented. NodeList objects in the DOM are live.
314
+ * The NodeList interface provides the abstraction of an ordered collection of nodes,
315
+ * without defining or constraining how this collection is implemented.
316
+ * NodeList objects in the DOM are live.
255
317
  * The items in the NodeList are accessible via an integral index, starting from 0.
318
+ * You can also access the items of the NodeList with a `for...of` loop.
319
+ *
320
+ * @class NodeList
321
+ * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-536297177
322
+ * @constructs NodeList
256
323
  */
257
324
  function NodeList() {}
258
325
  NodeList.prototype = {
259
326
  /**
260
- * The number of nodes in the list. The range of valid child node indices is 0 to length-1 inclusive.
261
- * @standard level1
327
+ * The number of nodes in the list. The range of valid child node indices is 0 to length-1
328
+ * inclusive.
329
+ *
330
+ * @type {number}
262
331
  */
263
332
  length: 0,
264
333
  /**
265
- * 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.
266
- * @standard level1
267
- * @param index unsigned long
268
- * Index into the collection.
269
- * @return Node
270
- * The node at the indexth position in the NodeList, or null if that is not a valid index.
334
+ * Returns the item at `index`. If index is greater than or equal to the number of nodes in
335
+ * the list, this returns null.
336
+ *
337
+ * @param index
338
+ * Unsigned long Index into the collection.
339
+ * @returns {Node | null}
340
+ * The node at position `index` in the NodeList,
341
+ * or null if that is not a valid index.
271
342
  */
272
343
  item: function (index) {
273
- return this[index] || null;
344
+ return index >= 0 && index < this.length ? this[index] : null;
274
345
  },
346
+ /**
347
+ * Returns a string representation of the NodeList.
348
+ *
349
+ * @param {unknown} nodeFilter
350
+ * __A filter function? Not implemented according to the spec?__.
351
+ * @returns {string}
352
+ * A string representation of the NodeList.
353
+ */
275
354
  toString: function (nodeFilter) {
276
355
  for (var buf = [], i = 0; i < this.length; i++) {
277
356
  serializeToString(this[i], buf, nodeFilter);
@@ -279,51 +358,119 @@ NodeList.prototype = {
279
358
  return buf.join('');
280
359
  },
281
360
  /**
282
- * @private
283
- * @param {function (Node):boolean} predicate
361
+ * Filters the NodeList based on a predicate.
362
+ *
363
+ * @param {function(Node): boolean} predicate
364
+ * - A predicate function to filter the NodeList.
284
365
  * @returns {Node[]}
366
+ * An array of nodes that satisfy the predicate.
367
+ * @private
285
368
  */
286
369
  filter: function (predicate) {
287
370
  return Array.prototype.filter.call(this, predicate);
288
371
  },
289
372
  /**
290
- * @private
373
+ * Returns the first index at which a given node can be found in the NodeList, or -1 if it is
374
+ * not present.
375
+ *
291
376
  * @param {Node} item
377
+ * - The Node item to locate in the NodeList.
292
378
  * @returns {number}
379
+ * The first index of the node in the NodeList; -1 if not found.
380
+ * @private
293
381
  */
294
382
  indexOf: function (item) {
295
383
  return Array.prototype.indexOf.call(this, item);
296
384
  },
297
385
  };
386
+ NodeList.prototype[Symbol.iterator] = function () {
387
+ var me = this;
388
+ var index = 0;
389
+
390
+ return {
391
+ next: function () {
392
+ if (index < me.length) {
393
+ return {
394
+ value: me[index++],
395
+ done: false,
396
+ };
397
+ } else {
398
+ return {
399
+ done: true,
400
+ };
401
+ }
402
+ },
403
+ return: function () {
404
+ return {
405
+ done: true,
406
+ };
407
+ },
408
+ };
409
+ };
298
410
 
411
+ /**
412
+ * Represents a live collection of nodes that is automatically updated when its associated
413
+ * document changes.
414
+ *
415
+ * @class LiveNodeList
416
+ * @param {Node} node
417
+ * The associated node.
418
+ * @param {function} refresh
419
+ * The function to refresh the live node list.
420
+ * @augments NodeList
421
+ * @constructs LiveNodeList
422
+ */
299
423
  function LiveNodeList(node, refresh) {
300
424
  this._node = node;
301
425
  this._refresh = refresh;
302
426
  _updateLiveList(this);
303
427
  }
428
+ /**
429
+ * Updates the live node list.
430
+ *
431
+ * @param {LiveNodeList} list
432
+ * The live node list to update.
433
+ * @private
434
+ */
304
435
  function _updateLiveList(list) {
305
436
  var inc = list._node._inc || list._node.ownerDocument._inc;
306
- if (list._inc != inc) {
437
+ if (list._inc !== inc) {
307
438
  var ls = list._refresh(list._node);
308
- //console.log(ls.length)
309
439
  __set__(list, 'length', ls.length);
440
+ if (!list.$$length || ls.length < list.$$length) {
441
+ for (var i = ls.length; i in list; i++) {
442
+ if (hasOwn(list, i)) {
443
+ delete list[i];
444
+ }
445
+ }
446
+ }
310
447
  copy(ls, list);
311
448
  list._inc = inc;
312
449
  }
313
450
  }
451
+ /**
452
+ * Returns the node at position `index` in the LiveNodeList, or null if that is not a valid
453
+ * index.
454
+ *
455
+ * @param {number} i
456
+ * Index into the collection.
457
+ * @returns {Node | null}
458
+ * The node at position `index` in the LiveNodeList, or null if that is not a valid index.
459
+ */
314
460
  LiveNodeList.prototype.item = function (i) {
315
461
  _updateLiveList(this);
316
- return this[i];
462
+ return this[i] || null;
317
463
  };
318
464
 
319
465
  _extends(LiveNodeList, NodeList);
320
466
 
321
467
  /**
322
- * Objects implementing the NamedNodeMap interface are used
323
- * to represent collections of nodes that can be accessed by name.
468
+ * Objects implementing the NamedNodeMap interface are used to represent collections of nodes
469
+ * that can be accessed by name.
324
470
  * Note that NamedNodeMap does not inherit from NodeList;
325
471
  * NamedNodeMaps are not maintained in any particular order.
326
- * Objects contained in an object implementing NamedNodeMap may also be accessed by an ordinal index,
472
+ * Objects contained in an object implementing NamedNodeMap may also be accessed by an ordinal
473
+ * index,
327
474
  * but this is simply to allow convenient enumeration of the contents of a NamedNodeMap,
328
475
  * and does not imply that the DOM specifies an order to these Nodes.
329
476
  * NamedNodeMap objects in the DOM are live.
@@ -332,11 +479,23 @@ _extends(LiveNodeList, NodeList);
332
479
  * This implementation only supports property indices, but does not support named properties,
333
480
  * as specified in the living standard.
334
481
  *
482
+ * @class NamedNodeMap
335
483
  * @see https://dom.spec.whatwg.org/#interface-namednodemap
336
484
  * @see https://webidl.spec.whatwg.org/#dfn-supported-property-names
485
+ * @constructs NamedNodeMap
337
486
  */
338
487
  function NamedNodeMap() {}
339
-
488
+ /**
489
+ * Returns the index of a node within the list.
490
+ *
491
+ * @param {Array} list
492
+ * The list of nodes.
493
+ * @param {Node} node
494
+ * The node to find.
495
+ * @returns {number}
496
+ * The index of the node within the list, or -1 if not found.
497
+ * @private
498
+ */
340
499
  function _findNodeIndex(list, node) {
341
500
  var i = 0;
342
501
  while (i < list.length) {
@@ -346,7 +505,20 @@ function _findNodeIndex(list, node) {
346
505
  i++;
347
506
  }
348
507
  }
349
-
508
+ /**
509
+ * Adds a new attribute to the list and updates the owner element of the attribute.
510
+ *
511
+ * @param {Element} el
512
+ * The element which will become the owner of the new attribute.
513
+ * @param {NamedNodeMap} list
514
+ * The list to which the new attribute will be added.
515
+ * @param {Attr} newAttr
516
+ * The new attribute to be added.
517
+ * @param {Attr} oldAttr
518
+ * The old attribute to be replaced, or null if no attribute is to be replaced.
519
+ * @returns {void}
520
+ * @private
521
+ */
350
522
  function _addNamedNode(el, list, newAttr, oldAttr) {
351
523
  if (oldAttr) {
352
524
  list[_findNodeIndex(list, oldAttr)] = newAttr;
@@ -363,6 +535,18 @@ function _addNamedNode(el, list, newAttr, oldAttr) {
363
535
  }
364
536
  }
365
537
  }
538
+ /**
539
+ * Removes an attribute from the list and updates the owner element of the attribute.
540
+ *
541
+ * @param {Element} el
542
+ * The element which is the current owner of the attribute.
543
+ * @param {NamedNodeMap} list
544
+ * The list from which the attribute will be removed.
545
+ * @param {Attr} attr
546
+ * The attribute to be removed.
547
+ * @returns {void}
548
+ * @private
549
+ */
366
550
  function _removeNamedNode(el, list, attr) {
367
551
  //console.log('remove attr:'+attr)
368
552
  var i = _findNodeIndex(list, attr);
@@ -386,11 +570,13 @@ NamedNodeMap.prototype = {
386
570
  item: NodeList.prototype.item,
387
571
 
388
572
  /**
389
- * get an attribute by name (lower case in case of HTML namespace and document)
390
- *
391
- * @param {string} localName
392
- * @return {Attr | null}
573
+ * Get an attribute by name. Note: Name is in lower case in case of HTML namespace and
574
+ * document.
393
575
  *
576
+ * @param {string} localName
577
+ * The local name of the attribute.
578
+ * @returns {Attr | null}
579
+ * The attribute with the given local name, or null if no such attribute exists.
394
580
  * @see https://dom.spec.whatwg.org/#concept-element-attributes-get-by-name
395
581
  */
396
582
  getNamedItem: function (localName) {
@@ -409,16 +595,23 @@ NamedNodeMap.prototype = {
409
595
  },
410
596
 
411
597
  /**
412
- * set an attribute
598
+ * Set an attribute.
413
599
  *
414
600
  * @param {Attr} attr
415
- * @return {Attr | null}
601
+ * The attribute to set.
602
+ * @returns {Attr | null}
603
+ * The old attribute with the same local name and namespace URI as the new one, or null if no
604
+ * such attribute exists.
605
+ * @throws {DOMException}
606
+ * With code:
607
+ * - {@link INUSE_ATTRIBUTE_ERR} - If the attribute is already an attribute of another
608
+ * element.
416
609
  * @see https://dom.spec.whatwg.org/#concept-element-attributes-set
417
610
  */
418
611
  setNamedItem: function (attr) {
419
612
  var el = attr.ownerElement;
420
613
  if (el && el !== this._ownerElement) {
421
- throw new DOMException(INUSE_ATTRIBUTE_ERR);
614
+ throw new DOMException(DOMException.INUSE_ATTRIBUTE_ERR);
422
615
  }
423
616
  var oldAttr = this.getNamedItemNS(attr.namespaceURI, attr.localName);
424
617
  if (oldAttr === attr) {
@@ -429,11 +622,17 @@ NamedNodeMap.prototype = {
429
622
  },
430
623
 
431
624
  /**
432
- * set an attribute
625
+ * Set an attribute, replacing an existing attribute with the same local name and namespace
626
+ * URI if one exists.
433
627
  *
434
628
  * @param {Attr} attr
435
- * @return {Attr | null}
436
- *
629
+ * The attribute to set.
630
+ * @returns {Attr | null}
631
+ * The old attribute with the same local name and namespace URI as the new one, or null if no
632
+ * such attribute exists.
633
+ * @throws {DOMException}
634
+ * Throws a DOMException with the name "InUseAttributeError" if the attribute is already an
635
+ * attribute of another element.
437
636
  * @see https://dom.spec.whatwg.org/#concept-element-attributes-set
438
637
  */
439
638
  setNamedItemNS: function (attr) {
@@ -441,49 +640,62 @@ NamedNodeMap.prototype = {
441
640
  },
442
641
 
443
642
  /**
444
- * remove an attribute by name (lower case in case of HTML namespace and document)
643
+ * Removes an attribute specified by the local name.
445
644
  *
446
645
  * @param {string} localName
447
- * @return {Attr | null}
448
- *
646
+ * The local name of the attribute to be removed.
647
+ * @returns {Attr}
648
+ * The attribute node that was removed.
649
+ * @throws {DOMException}
650
+ * With code:
651
+ * - {@link DOMException.NOT_FOUND_ERR} if no attribute with the given name is found.
449
652
  * @see https://dom.spec.whatwg.org/#dom-namednodemap-removenameditem
450
653
  * @see https://dom.spec.whatwg.org/#concept-element-attributes-remove-by-name
451
654
  */
452
655
  removeNamedItem: function (localName) {
453
656
  var attr = this.getNamedItem(localName);
454
657
  if (!attr) {
455
- throw new DOMException(NOT_FOUND_ERR, localName);
658
+ throw new DOMException(DOMException.NOT_FOUND_ERR, localName);
456
659
  }
457
660
  _removeNamedNode(this._ownerElement, this, attr);
458
661
  return attr;
459
662
  },
460
663
 
461
664
  /**
462
- * remove an attribute by namespace and local name
665
+ * Removes an attribute specified by the namespace and local name.
463
666
  *
464
667
  * @param {string | null} namespaceURI
668
+ * The namespace URI of the attribute to be removed.
465
669
  * @param {string} localName
466
- * @return {Attr | null}
467
- *
670
+ * The local name of the attribute to be removed.
671
+ * @returns {Attr}
672
+ * The attribute node that was removed.
673
+ * @throws {DOMException}
674
+ * With code:
675
+ * - {@link DOMException.NOT_FOUND_ERR} if no attribute with the given namespace URI and local
676
+ * name is found.
468
677
  * @see https://dom.spec.whatwg.org/#dom-namednodemap-removenameditemns
469
678
  * @see https://dom.spec.whatwg.org/#concept-element-attributes-remove-by-namespace
470
679
  */
471
680
  removeNamedItemNS: function (namespaceURI, localName) {
472
681
  var attr = this.getNamedItemNS(namespaceURI, localName);
473
682
  if (!attr) {
474
- throw new DOMException(NOT_FOUND_ERR, namespaceURI ? namespaceURI + ' : ' + localName : localName);
683
+ throw new DOMException(DOMException.NOT_FOUND_ERR, namespaceURI ? namespaceURI + ' : ' + localName : localName);
475
684
  }
476
685
  _removeNamedNode(this._ownerElement, this, attr);
477
686
  return attr;
478
687
  },
479
688
 
480
689
  /**
481
- * get an attribute by namespace and local name
690
+ * Get an attribute by namespace and local name.
482
691
  *
483
692
  * @param {string | null} namespaceURI
693
+ * The namespace URI of the attribute.
484
694
  * @param {string} localName
485
- * @return {Attr | null}
486
- *
695
+ * The local name of the attribute.
696
+ * @returns {Attr | null}
697
+ * The attribute with the given namespace URI and local name, or null if no such attribute
698
+ * exists.
487
699
  * @see https://dom.spec.whatwg.org/#concept-element-attributes-get-by-namespace
488
700
  */
489
701
  getNamedItemNS: function (namespaceURI, localName) {
@@ -501,66 +713,138 @@ NamedNodeMap.prototype = {
501
713
  return null;
502
714
  },
503
715
  };
716
+ NamedNodeMap.prototype[Symbol.iterator] = function () {
717
+ var me = this;
718
+ var index = 0;
719
+
720
+ return {
721
+ next: function () {
722
+ if (index < me.length) {
723
+ return {
724
+ value: me[index++],
725
+ done: false,
726
+ };
727
+ } else {
728
+ return {
729
+ done: true,
730
+ };
731
+ }
732
+ },
733
+ return: function () {
734
+ return {
735
+ done: true,
736
+ };
737
+ },
738
+ };
739
+ };
504
740
 
505
741
  /**
506
- * The DOMImplementation interface represents an object providing methods
507
- * which are not dependent on any particular document.
508
- * Such an object is returned by the `Document.implementation` property.
742
+ * The DOMImplementation interface provides a number of methods for performing operations that
743
+ * are independent of any particular instance of the document object model.
509
744
  *
510
- * __The individual methods describe the differences compared to the specs.__
745
+ * The DOMImplementation interface represents an object providing methods which are not
746
+ * dependent on any particular document.
747
+ * Such an object is returned by the `Document.implementation` property.
511
748
  *
512
- * @constructor
749
+ * **The individual methods describe the differences compared to the specs**.
513
750
  *
751
+ * @class DOMImplementation
514
752
  * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMImplementation MDN
515
- * @see https://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html#ID-102161490 DOM Level 1 Core (Initial)
753
+ * @see https://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html#ID-102161490 DOM Level 1 Core
754
+ * (Initial)
516
755
  * @see https://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-102161490 DOM Level 2 Core
517
756
  * @see https://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-102161490 DOM Level 3 Core
518
757
  * @see https://dom.spec.whatwg.org/#domimplementation DOM Living Standard
758
+ * @constructs DOMImplementation
519
759
  */
520
760
  function DOMImplementation() {}
521
761
 
522
762
  DOMImplementation.prototype = {
523
763
  /**
524
- * The DOMImplementation.hasFeature() method returns a Boolean flag indicating if a given feature is supported.
525
- * The different implementations fairly diverged in what kind of features were reported.
526
- * The latest version of the spec settled to force this method to always return true, where the functionality was accurate and in use.
764
+ * Test if the DOM implementation implements a specific feature and version, as specified in
765
+ * {@link https://www.w3.org/TR/DOM-Level-3-Core/core.html#DOMFeatures DOM Features}.
527
766
  *
528
- * @deprecated It is deprecated and modern browsers return true in all cases.
767
+ * The DOMImplementation.hasFeature() method returns a Boolean flag indicating if a given
768
+ * feature is supported. The different implementations fairly diverged in what kind of
769
+ * features were reported. The latest version of the spec settled to force this method to
770
+ * always return true, where the functionality was accurate and in use.
529
771
  *
772
+ * @deprecated
773
+ * It is deprecated and modern browsers return true in all cases.
774
+ * @function DOMImplementation#hasFeature
530
775
  * @param {string} feature
776
+ * The name of the feature to test.
531
777
  * @param {string} [version]
532
- * @returns {boolean} always true
533
- *
778
+ * This is the version number of the feature to test.
779
+ * @returns {boolean}
780
+ * Always returns true.
534
781
  * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMImplementation/hasFeature MDN
535
782
  * @see https://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html#ID-5CED94D7 DOM Level 1 Core
536
783
  * @see https://dom.spec.whatwg.org/#dom-domimplementation-hasfeature DOM Living Standard
784
+ * @see https://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-5CED94D7 DOM Level 3 Core
537
785
  */
538
786
  hasFeature: function (feature, version) {
539
787
  return true;
540
788
  },
541
789
  /**
542
- * Creates an XML Document object of the specified type with its document element.
790
+ * Creates a DOM Document object of the specified type with its document element. Note that
791
+ * based on the {@link DocumentType}
792
+ * given to create the document, the implementation may instantiate specialized
793
+ * {@link Document} objects that support additional features than the "Core", such as "HTML"
794
+ * {@link https://www.w3.org/TR/DOM-Level-3-Core/references.html#DOM2HTML DOM Level 2 HTML}.
795
+ * On the other hand, setting the {@link DocumentType} after the document was created makes
796
+ * this very unlikely to happen. Alternatively, specialized {@link Document} creation methods,
797
+ * such as createHTMLDocument
798
+ * {@link https://www.w3.org/TR/DOM-Level-3-Core/references.html#DOM2HTML DOM Level 2 HTML},
799
+ * can be used to obtain specific types of {@link Document} objects.
543
800
  *
544
801
  * __It behaves slightly different from the description in the living standard__:
545
- * - There is no interface/class `XMLDocument`, it returns a `Document` instance (with it's `type` set to `'xml'`).
802
+ * - There is no interface/class `XMLDocument`, it returns a `Document`
803
+ * instance (with it's `type` set to `'xml'`).
546
804
  * - `encoding`, `mode`, `origin`, `url` fields are currently not declared.
547
- * - The methods provided by this implementation are not validating names or qualified names.
548
- * (They are only validated by the SAX parser when calling `DOMParser.parseFromString`)
549
805
  *
806
+ * @function DOMImplementation.createDocument
550
807
  * @param {string | null} namespaceURI
551
- * @param {string} qualifiedName
808
+ * The
809
+ * {@link https://www.w3.org/TR/DOM-Level-3-Core/glossary.html#dt-namespaceURI namespace URI}
810
+ * of the document element to create or null.
811
+ * @param {string | null} qualifiedName
812
+ * The
813
+ * {@link https://www.w3.org/TR/DOM-Level-3-Core/glossary.html#dt-qualifiedname qualified name}
814
+ * of the document element to be created or null.
552
815
  * @param {DocumentType | null} [doctype=null]
553
- * @returns {Document} the XML document
554
- *
555
- * @see #createHTMLDocument
816
+ * The type of document to be created or null. When doctype is not null, its
817
+ * {@link Node#ownerDocument} attribute is set to the document being created. Default is
818
+ * `null`
819
+ * @returns {Document}
820
+ * A new {@link Document} object with its document element. If the NamespaceURI,
821
+ * qualifiedName, and doctype are null, the returned {@link Document} is empty with no
822
+ * document element.
823
+ * @throws {DOMException}
824
+ * With code:
556
825
  *
826
+ * - `INVALID_CHARACTER_ERR`: Raised if the specified qualified name is not an XML name
827
+ * according to {@link https://www.w3.org/TR/DOM-Level-3-Core/references.html#XML XML 1.0}.
828
+ * - `NAMESPACE_ERR`: Raised if the qualifiedName is malformed, if the qualifiedName has a
829
+ * prefix and the namespaceURI is null, or if the qualifiedName is null and the namespaceURI
830
+ * is different from null, or if the qualifiedName has a prefix that is "xml" and the
831
+ * namespaceURI is different from "{@link http://www.w3.org/XML/1998/namespace}"
832
+ * {@link https://www.w3.org/TR/DOM-Level-3-Core/references.html#Namespaces XML Namespaces},
833
+ * or if the DOM implementation does not support the "XML" feature but a non-null namespace
834
+ * URI was provided, since namespaces were defined by XML.
835
+ * - `WRONG_DOCUMENT_ERR`: Raised if doctype has already been used with a different document
836
+ * or was created from a different implementation.
837
+ * - `NOT_SUPPORTED_ERR`: May be raised if the implementation does not support the feature
838
+ * "XML" and the language exposed through the Document does not support XML Namespaces (such
839
+ * as {@link https://www.w3.org/TR/DOM-Level-3-Core/references.html#HTML40 HTML 4.01}).
840
+ * @since DOM Level 2.
841
+ * @see {@link #createHTMLDocument}
557
842
  * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMImplementation/createDocument MDN
558
- * @see https://www.w3.org/TR/DOM-Level-2-Core/core.html#Level-2-Core-DOM-createDocument DOM Level 2 Core (initial)
559
- * @see https://dom.spec.whatwg.org/#dom-domimplementation-createdocument DOM Level 2 Core
560
- *
561
- * @see https://dom.spec.whatwg.org/#validate-and-extract DOM: Validate and extract
562
- * @see https://www.w3.org/TR/xml/#NT-NameStartChar XML Spec: Names
563
- * @see https://www.w3.org/TR/xml-names/#ns-qualnames XML Namespaces: Qualified names
843
+ * @see https://dom.spec.whatwg.org/#dom-domimplementation-createdocument DOM Living Standard
844
+ * @see https://www.w3.org/TR/DOM-Level-3-Core/core.html#Level-2-Core-DOM-createDocument DOM
845
+ * Level 3 Core
846
+ * @see https://www.w3.org/TR/DOM-Level-2-Core/core.html#Level-2-Core-DOM-createDocument DOM
847
+ * Level 2 Core (initial)
564
848
  */
565
849
  createDocument: function (namespaceURI, qualifiedName, doctype) {
566
850
  var contentType = MIME_TYPE.XML_APPLICATION;
@@ -569,7 +853,7 @@ DOMImplementation.prototype = {
569
853
  } else if (namespaceURI === NAMESPACE.SVG) {
570
854
  contentType = MIME_TYPE.XML_SVG_IMAGE;
571
855
  }
572
- var doc = new Document({ contentType: contentType });
856
+ var doc = new Document(PDC, { contentType: contentType });
573
857
  doc.implementation = this;
574
858
  doc.childNodes = new NodeList();
575
859
  doc.doctype = doctype || null;
@@ -583,28 +867,58 @@ DOMImplementation.prototype = {
583
867
  return doc;
584
868
  },
585
869
  /**
586
- * Returns a doctype, with the given `qualifiedName`, `publicId`, and `systemId`.
870
+ * Creates an empty DocumentType node. Entity declarations and notations are not made
871
+ * available. Entity reference expansions and default attribute additions do not occur.
587
872
  *
588
- * __This behavior is slightly different from the in the specs__:
873
+ * **This behavior is slightly different from the in the specs**:
589
874
  * - `encoding`, `mode`, `origin`, `url` fields are currently not declared.
875
+ * - `publicId` and `systemId` contain the raw data including any possible quotes,
876
+ * so they can always be serialized back to the original value
877
+ * - `internalSubset` contains the raw string between `[` and `]` if present,
878
+ * but is not parsed or validated in any form.
590
879
  *
880
+ * @function DOMImplementation#createDocumentType
591
881
  * @param {string} qualifiedName
882
+ * The {@link https://www.w3.org/TR/DOM-Level-3-Core/glossary.html#dt-qualifiedname qualified
883
+ * name} of the document type to be created.
592
884
  * @param {string} [publicId]
885
+ * The external subset public identifier.
593
886
  * @param {string} [systemId]
594
- * @returns {DocumentType} which can either be used with `DOMImplementation.createDocument` upon document creation
595
- * or can be put into the document via methods like `Node.insertBefore()` or `Node.replaceChild()`
887
+ * The external subset system identifier.
888
+ * @param {string} [internalSubset]
889
+ * the internal subset or an empty string if it is not present
890
+ * @returns {DocumentType}
891
+ * A new {@link DocumentType} node with {@link Node#ownerDocument} set to null.
892
+ * @throws {DOMException}
893
+ * With code:
596
894
  *
597
- * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMImplementation/createDocumentType MDN
598
- * @see https://www.w3.org/TR/DOM-Level-2-Core/core.html#Level-2-Core-DOM-createDocType DOM Level 2 Core
599
- * @see https://dom.spec.whatwg.org/#dom-domimplementation-createdocumenttype DOM Living Standard
895
+ * - `INVALID_CHARACTER_ERR`: Raised if the specified qualified name is not an XML name
896
+ * according to {@link https://www.w3.org/TR/DOM-Level-3-Core/references.html#XML XML 1.0}.
897
+ * - `NAMESPACE_ERR`: Raised if the qualifiedName is malformed.
898
+ * - `NOT_SUPPORTED_ERR`: May be raised if the implementation does not support the feature
899
+ * "XML" and the language exposed through the Document does not support XML Namespaces (such
900
+ * as {@link https://www.w3.org/TR/DOM-Level-3-Core/references.html#HTML40 HTML 4.01}).
901
+ * @since DOM Level 2.
902
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMImplementation/createDocumentType
903
+ * MDN
904
+ * @see https://dom.spec.whatwg.org/#dom-domimplementation-createdocumenttype DOM Living
905
+ * Standard
906
+ * @see https://www.w3.org/TR/DOM-Level-3-Core/core.html#Level-3-Core-DOM-createDocType DOM
907
+ * Level 3 Core
908
+ * @see https://www.w3.org/TR/DOM-Level-2-Core/core.html#Level-2-Core-DOM-createDocType DOM
909
+ * Level 2 Core
910
+ * @see https://github.com/xmldom/xmldom/blob/master/CHANGELOG.md#050
911
+ * @see https://www.w3.org/TR/DOM-Level-2-Core/#core-ID-Core-DocType-internalSubset
912
+ * @prettierignore
600
913
  */
601
- createDocumentType: function (qualifiedName, publicId, systemId) {
914
+ createDocumentType: function (qualifiedName, publicId, systemId, internalSubset) {
602
915
  validateQualifiedName(qualifiedName);
603
- var node = new DocumentType();
916
+ var node = new DocumentType(PDC);
604
917
  node.name = qualifiedName;
605
918
  node.nodeName = qualifiedName;
606
919
  node.publicId = publicId || '';
607
920
  node.systemId = systemId || '';
921
+ node.internalSubset = internalSubset || '';
608
922
 
609
923
  return node;
610
924
  },
@@ -612,17 +926,21 @@ DOMImplementation.prototype = {
612
926
  * Returns an HTML document, that might already have a basic DOM structure.
613
927
  *
614
928
  * __It behaves slightly different from the description in the living standard__:
615
- * - If the first argument is `false` no initial nodes are added (steps 3-7 in the specs are omitted)
929
+ * - If the first argument is `false` no initial nodes are added (steps 3-7 in the specs are
930
+ * omitted)
616
931
  * - `encoding`, `mode`, `origin`, `url` fields are currently not declared.
617
932
  *
618
933
  * @param {string | false} [title]
619
- * @returns {Document} The HTML document
620
- *
934
+ * A string containing the title to give the new HTML document.
935
+ * @returns {Document}
936
+ * The HTML document.
937
+ * @since WHATWG Living Standard.
938
+ * @see {@link #createDocument}
621
939
  * @see https://dom.spec.whatwg.org/#dom-domimplementation-createhtmldocument
622
940
  * @see https://dom.spec.whatwg.org/#html-document
623
941
  */
624
942
  createHTMLDocument: function (title) {
625
- var doc = new Document({ contentType: MIME_TYPE.HTML });
943
+ var doc = new Document(PDC, { contentType: MIME_TYPE.HTML });
626
944
  doc.implementation = this;
627
945
  doc.childNodes = new NodeList();
628
946
  if (title !== false) {
@@ -645,48 +963,225 @@ DOMImplementation.prototype = {
645
963
  };
646
964
 
647
965
  /**
966
+ * The DOM Node interface is an abstract base class upon which many other DOM API objects are
967
+ * based, thus letting those object types to be used similarly and often interchangeably. As an
968
+ * abstract class, there is no such thing as a plain Node object. All objects that implement
969
+ * Node functionality are based on one of its subclasses. Most notable are Document, Element,
970
+ * and DocumentFragment.
971
+ *
972
+ * In addition, every kind of DOM node is represented by an interface based on Node. These
973
+ * include Attr, CharacterData (which Text, Comment, CDATASection and ProcessingInstruction are
974
+ * all based on), and DocumentType.
975
+ *
976
+ * In some cases, a particular feature of the base Node interface may not apply to one of its
977
+ * child interfaces; in that case, the inheriting node may return null or throw an exception,
978
+ * depending on circumstances. For example, attempting to add children to a node type that
979
+ * cannot have children will throw an exception.
980
+ *
981
+ * **This behavior is slightly different from the in the specs**:
982
+ * - undeclared properties: nodeType, baseURI, isConnected, parentElement, textContent
983
+ * - missing methods: nodeType, baseURI, isConnected, parentElement, textContent
984
+ *
985
+ * @class
986
+ * @abstract
987
+ * @param {Symbol} symbol
648
988
  * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247
989
+ * @see https://dom.spec.whatwg.org/#node
990
+ * @prettierignore
649
991
  */
650
- function Node() {}
992
+ function Node(symbol) {
993
+ checkSymbol(symbol);
994
+ }
651
995
 
652
996
  Node.prototype = {
997
+ /**
998
+ * The first child of this node.
999
+ *
1000
+ * @type {Node | null}
1001
+ */
653
1002
  firstChild: null,
1003
+ /**
1004
+ * The last child of this node.
1005
+ *
1006
+ * @type {Node | null}
1007
+ */
654
1008
  lastChild: null,
1009
+ /**
1010
+ * The previous sibling of this node.
1011
+ *
1012
+ * @type {Node | null}
1013
+ */
655
1014
  previousSibling: null,
1015
+ /**
1016
+ * The next sibling of this node.
1017
+ *
1018
+ * @type {Node | null}
1019
+ */
656
1020
  nextSibling: null,
1021
+ /**
1022
+ * The attributes of this node.
1023
+ *
1024
+ * @type {NamedNodeMap | null}
1025
+ */
657
1026
  attributes: null,
1027
+ /**
1028
+ * The parent node of this node.
1029
+ *
1030
+ * @type {Node | null}
1031
+ */
658
1032
  parentNode: null,
1033
+ /**
1034
+ * The child nodes of this node.
1035
+ *
1036
+ * @type {NodeList | null}
1037
+ */
659
1038
  childNodes: null,
1039
+ /**
1040
+ * The document object associated with this node.
1041
+ *
1042
+ * @type {Document | null}
1043
+ */
660
1044
  ownerDocument: null,
1045
+ /**
1046
+ * The value of this node.
1047
+ *
1048
+ * @type {string | null}
1049
+ */
661
1050
  nodeValue: null,
1051
+ /**
1052
+ * The namespace URI of this node.
1053
+ *
1054
+ * @type {string | null}
1055
+ */
662
1056
  namespaceURI: null,
1057
+ /**
1058
+ * The prefix of the namespace for this node.
1059
+ *
1060
+ * @type {string | null}
1061
+ */
663
1062
  prefix: null,
1063
+ /**
1064
+ * The local part of the qualified name of this node.
1065
+ *
1066
+ * @type {string | null}
1067
+ */
664
1068
  localName: null,
665
- // Modified in DOM Level 2:
1069
+ /**
1070
+ * Inserts a node before a reference node as a child of this node.
1071
+ *
1072
+ * @param {Node} newChild
1073
+ * The new child node to be inserted.
1074
+ * @param {Node | null} refChild
1075
+ * The reference node before which newChild will be inserted.
1076
+ * @returns {Node}
1077
+ * The new child node successfully inserted.
1078
+ * @throws {DOMException}
1079
+ * Throws a DOMException if inserting the node would result in a DOM tree that is not
1080
+ * well-formed, or if `child` is provided but is not a child of `parent`.
1081
+ * See {@link _insertBefore} for more details.
1082
+ * @since Modified in DOM L2
1083
+ */
666
1084
  insertBefore: function (newChild, refChild) {
667
- //raises
668
1085
  return _insertBefore(this, newChild, refChild);
669
1086
  },
1087
+ /**
1088
+ * Replaces an old child node with a new child node within this node.
1089
+ *
1090
+ * @param {Node} newChild
1091
+ * The new node that is to replace the old node.
1092
+ * If it already exists in the DOM, it is removed from its original position.
1093
+ * @param {Node} oldChild
1094
+ * The existing child node to be replaced.
1095
+ * @returns {Node}
1096
+ * Returns the replaced child node.
1097
+ * @throws {DOMException}
1098
+ * Throws a DOMException if replacing the node would result in a DOM tree that is not
1099
+ * well-formed, or if `oldChild` is not a child of `this`.
1100
+ * This can also occur if the pre-replacement validity assertion fails.
1101
+ * See {@link _insertBefore}, {@link Node.removeChild}, and
1102
+ * {@link assertPreReplacementValidityInDocument} for more details.
1103
+ * @see https://dom.spec.whatwg.org/#concept-node-replace
1104
+ */
670
1105
  replaceChild: function (newChild, oldChild) {
671
- //raises
672
1106
  _insertBefore(this, newChild, oldChild, assertPreReplacementValidityInDocument);
673
1107
  if (oldChild) {
674
1108
  this.removeChild(oldChild);
675
1109
  }
676
1110
  },
1111
+ /**
1112
+ * Removes an existing child node from this node.
1113
+ *
1114
+ * @param {Node} oldChild
1115
+ * The child node to be removed.
1116
+ * @returns {Node}
1117
+ * Returns the removed child node.
1118
+ * @throws {DOMException}
1119
+ * Throws a DOMException if `oldChild` is not a child of `this`.
1120
+ * See {@link _removeChild} for more details.
1121
+ */
677
1122
  removeChild: function (oldChild) {
678
1123
  return _removeChild(this, oldChild);
679
1124
  },
1125
+ /**
1126
+ * Appends a child node to this node.
1127
+ *
1128
+ * @param {Node} newChild
1129
+ * The child node to be appended to this node.
1130
+ * If it already exists in the DOM, it is removed from its original position.
1131
+ * @returns {Node}
1132
+ * Returns the appended child node.
1133
+ * @throws {DOMException}
1134
+ * Throws a DOMException if appending the node would result in a DOM tree that is not
1135
+ * well-formed, or if `newChild` is not a valid Node.
1136
+ * See {@link insertBefore} for more details.
1137
+ */
680
1138
  appendChild: function (newChild) {
681
1139
  return this.insertBefore(newChild, null);
682
1140
  },
1141
+ /**
1142
+ * Determines whether this node has any child nodes.
1143
+ *
1144
+ * @returns {boolean}
1145
+ * Returns true if this node has any child nodes, and false otherwise.
1146
+ */
683
1147
  hasChildNodes: function () {
684
1148
  return this.firstChild != null;
685
1149
  },
1150
+ /**
1151
+ * Creates a copy of the calling node.
1152
+ *
1153
+ * @param {boolean} deep
1154
+ * If true, the contents of the node are recursively copied.
1155
+ * If false, only the node itself (and its attributes, if it is an element) are copied.
1156
+ * @returns {Node}
1157
+ * Returns the newly created copy of the node.
1158
+ * @throws {DOMException}
1159
+ * May throw a DOMException if operations within {@link Element#setAttributeNode} or
1160
+ * {@link Node#appendChild} (which are potentially invoked in this method) do not meet their
1161
+ * specific constraints.
1162
+ * @see {@link cloneNode}
1163
+ */
686
1164
  cloneNode: function (deep) {
687
1165
  return cloneNode(this.ownerDocument || this, this, deep);
688
1166
  },
689
- // Modified in DOM Level 2:
1167
+ /**
1168
+ * Puts the specified node and all of its subtree into a "normalized" form. In a normalized
1169
+ * subtree, no text nodes in the subtree are empty and there are no adjacent text nodes.
1170
+ *
1171
+ * Specifically, this method merges any adjacent text nodes (i.e., nodes for which `nodeType`
1172
+ * is `TEXT_NODE`) into a single node with the combined data. It also removes any empty text
1173
+ * nodes.
1174
+ *
1175
+ * This method operates recursively, so it also normalizes any and all descendent nodes within
1176
+ * the subtree.
1177
+ *
1178
+ * @throws {DOMException}
1179
+ * May throw a DOMException if operations within removeChild or appendData (which are
1180
+ * potentially invoked in this method) do not meet their specific constraints.
1181
+ * @since Modified in DOM Level 2
1182
+ * @see {@link Node.removeChild}
1183
+ * @see {@link CharacterData.appendData}
1184
+ */
690
1185
  normalize: function () {
691
1186
  var child = this.firstChild;
692
1187
  while (child) {
@@ -700,11 +1195,31 @@ Node.prototype = {
700
1195
  }
701
1196
  }
702
1197
  },
703
- // Introduced in DOM Level 2:
1198
+ /**
1199
+ * Checks whether the DOM implementation implements a specific feature and its version.
1200
+ *
1201
+ * @deprecated
1202
+ * Since `DOMImplementation.hasFeature` is deprecated and always returns true.
1203
+ * @param {string} feature
1204
+ * The package name of the feature to test. This is the same name that can be passed to the
1205
+ * method `hasFeature` on `DOMImplementation`.
1206
+ * @param {string} version
1207
+ * This is the version number of the package name to test.
1208
+ * @returns {boolean}
1209
+ * Returns true in all cases in the current implementation.
1210
+ * @since Introduced in DOM Level 2
1211
+ * @see {@link DOMImplementation.hasFeature}
1212
+ */
704
1213
  isSupported: function (feature, version) {
705
1214
  return this.ownerDocument.implementation.hasFeature(feature, version);
706
1215
  },
707
- // Introduced in DOM Level 2:
1216
+ /**
1217
+ * Determines if the node has any attributes.
1218
+ *
1219
+ * @returns {boolean}
1220
+ * Returns true if the node has any attributes, and false otherwise.
1221
+ * @since Introduced in DOM Level 2
1222
+ */
708
1223
  hasAttributes: function () {
709
1224
  return this.attributes.length > 0;
710
1225
  },
@@ -713,14 +1228,19 @@ Node.prototype = {
713
1228
  * **The default namespace declarations are ignored by this method.**
714
1229
  * See Namespace Prefix Lookup for details on the algorithm used by this method.
715
1230
  *
716
- * _Note: The implementation seems to be incomplete when compared to the algorithm described in the specs._
1231
+ * **This behavior is different from the in the specs**:
1232
+ * - no node type specific handling
1233
+ * - uses the internal attribute _nsMap for resolving namespaces that is updated when changing attributes
717
1234
  *
718
1235
  * @param {string | null} namespaceURI
1236
+ * The namespace URI for which to find the associated prefix.
719
1237
  * @returns {string | null}
1238
+ * The associated prefix, if found; otherwise, null.
720
1239
  * @see https://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-lookupNamespacePrefix
721
1240
  * @see https://www.w3.org/TR/DOM-Level-3-Core/namespaces-algorithms.html#lookupNamespacePrefixAlgo
722
1241
  * @see https://dom.spec.whatwg.org/#dom-node-lookupprefix
723
1242
  * @see https://github.com/xmldom/xmldom/issues/322
1243
+ * @prettierignore
724
1244
  */
725
1245
  lookupPrefix: function (namespaceURI) {
726
1246
  var el = this;
@@ -729,7 +1249,7 @@ Node.prototype = {
729
1249
  //console.dir(map)
730
1250
  if (map) {
731
1251
  for (var n in map) {
732
- if (Object.prototype.hasOwnProperty.call(map, n) && map[n] === namespaceURI) {
1252
+ if (hasOwn(map, n) && map[n] === namespaceURI) {
733
1253
  return n;
734
1254
  }
735
1255
  }
@@ -738,14 +1258,30 @@ Node.prototype = {
738
1258
  }
739
1259
  return null;
740
1260
  },
741
- // Introduced in DOM Level 3:
1261
+ /**
1262
+ * This function is used to look up the namespace URI associated with the given prefix,
1263
+ * starting from this node.
1264
+ *
1265
+ * **This behavior is different from the in the specs**:
1266
+ * - no node type specific handling
1267
+ * - uses the internal attribute _nsMap for resolving namespaces that is updated when changing attributes
1268
+ *
1269
+ * @param {string | null} prefix
1270
+ * The prefix for which to find the associated namespace URI.
1271
+ * @returns {string | null}
1272
+ * The associated namespace URI, if found; otherwise, null.
1273
+ * @since DOM Level 3
1274
+ * @see https://dom.spec.whatwg.org/#dom-node-lookupnamespaceuri
1275
+ * @see https://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-lookupNamespaceURI
1276
+ * @prettierignore
1277
+ */
742
1278
  lookupNamespaceURI: function (prefix) {
743
1279
  var el = this;
744
1280
  while (el) {
745
1281
  var map = el._nsMap;
746
1282
  //console.dir(map)
747
1283
  if (map) {
748
- if (Object.prototype.hasOwnProperty.call(map, prefix)) {
1284
+ if (hasOwn(map, prefix)) {
749
1285
  return map[prefix];
750
1286
  }
751
1287
  }
@@ -753,21 +1289,43 @@ Node.prototype = {
753
1289
  }
754
1290
  return null;
755
1291
  },
756
- // Introduced in DOM Level 3:
1292
+ /**
1293
+ * Determines whether the given namespace URI is the default namespace.
1294
+ *
1295
+ * The function works by looking up the prefix associated with the given namespace URI. If no
1296
+ * prefix is found (i.e., the namespace URI is not registered in the namespace map of this
1297
+ * node or any of its ancestors), it returns `true`, implying the namespace URI is considered
1298
+ * the default.
1299
+ *
1300
+ * **This behavior is different from the in the specs**:
1301
+ * - no node type specific handling
1302
+ * - uses the internal attribute _nsMap for resolving namespaces that is updated when changing attributes
1303
+ *
1304
+ * @param {string | null} namespaceURI
1305
+ * The namespace URI to be checked.
1306
+ * @returns {boolean}
1307
+ * Returns true if the given namespace URI is the default namespace, false otherwise.
1308
+ * @since DOM Level 3
1309
+ * @see https://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-isDefaultNamespace
1310
+ * @see https://dom.spec.whatwg.org/#dom-node-isdefaultnamespace
1311
+ * @prettierignore
1312
+ */
757
1313
  isDefaultNamespace: function (namespaceURI) {
758
1314
  var prefix = this.lookupPrefix(namespaceURI);
759
1315
  return prefix == null;
760
1316
  },
761
- // Introduced in DOM Level 3:
762
1317
  /**
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
1318
+ * Compares the reference node with a node with regard to their position in the document and
1319
+ * according to the document order.
1320
+ *
1321
+ * @param {Node} other
1322
+ * The node to compare the reference node to.
1323
+ * @returns {number}
1324
+ * Returns how the node is positioned relatively to the reference node according to the
1325
+ * bitmask. 0 if reference node and given node are the same.
1326
+ * @since DOM Level 3
1327
+ * @see https://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#Node3-compare
1328
+ * @see https://dom.spec.whatwg.org/#dom-node-comparedocumentposition
771
1329
  */
772
1330
  compareDocumentPosition: function (other) {
773
1331
  if (this === other) return 0;
@@ -784,38 +1342,51 @@ Node.prototype = {
784
1342
  node2 = attr2.ownerElement;
785
1343
  if (attr1 && node1 && node2 === node1) {
786
1344
  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;
1345
+ if (attr === attr1)
1346
+ return DocumentPosition.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC + DocumentPosition.DOCUMENT_POSITION_PRECEDING;
1347
+ if (attr === attr2)
1348
+ return DocumentPosition.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC + DocumentPosition.DOCUMENT_POSITION_FOLLOWING;
789
1349
  }
790
1350
  }
791
1351
  }
792
1352
  if (!node1 || !node2 || node2.ownerDocument !== node1.ownerDocument) {
793
1353
  return (
794
- DOCUMENT_POSITION_DISCONNECTED +
795
- DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC +
796
- (docGUID(node2.ownerDocument) > docGUID(node1.ownerDocument) ? DOCUMENT_POSITION_FOLLOWING : DOCUMENT_POSITION_PRECEDING)
1354
+ DocumentPosition.DOCUMENT_POSITION_DISCONNECTED +
1355
+ DocumentPosition.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC +
1356
+ (docGUID(node2.ownerDocument) > docGUID(node1.ownerDocument)
1357
+ ? DocumentPosition.DOCUMENT_POSITION_FOLLOWING
1358
+ : DocumentPosition.DOCUMENT_POSITION_PRECEDING)
797
1359
  );
798
1360
  }
799
1361
  var chain1 = parentChain(node1);
800
1362
  var chain2 = parentChain(node2);
801
1363
  if ((!attr1 && chain2.indexOf(node1) >= 0) || (attr2 && node1 === node2)) {
802
- return DOCUMENT_POSITION_CONTAINS + DOCUMENT_POSITION_PRECEDING;
1364
+ return DocumentPosition.DOCUMENT_POSITION_CONTAINS + DocumentPosition.DOCUMENT_POSITION_PRECEDING;
803
1365
  }
804
1366
  if ((!attr2 && chain1.indexOf(node2) >= 0) || (attr1 && node1 === node2)) {
805
- return DOCUMENT_POSITION_CONTAINED_BY + DOCUMENT_POSITION_FOLLOWING;
1367
+ return DocumentPosition.DOCUMENT_POSITION_CONTAINED_BY + DocumentPosition.DOCUMENT_POSITION_FOLLOWING;
806
1368
  }
807
1369
  var ca = commonAncestor(chain2, chain1);
808
1370
  for (var n in ca.childNodes) {
809
1371
  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;
1372
+ if (child === node2) return DocumentPosition.DOCUMENT_POSITION_FOLLOWING;
1373
+ if (child === node1) return DocumentPosition.DOCUMENT_POSITION_PRECEDING;
1374
+ if (chain2.indexOf(child) >= 0) return DocumentPosition.DOCUMENT_POSITION_FOLLOWING;
1375
+ if (chain1.indexOf(child) >= 0) return DocumentPosition.DOCUMENT_POSITION_PRECEDING;
814
1376
  }
815
1377
  return 0;
816
1378
  },
817
1379
  };
818
1380
 
1381
+ /**
1382
+ * Encodes special XML characters to their corresponding entities.
1383
+ *
1384
+ * @param {string} c
1385
+ * The character to be encoded.
1386
+ * @returns {string}
1387
+ * The encoded character.
1388
+ * @private
1389
+ */
819
1390
  function _xmlEncoder(c) {
820
1391
  return (
821
1392
  (c == '<' && '&lt;') || (c == '>' && '&gt;') || (c == '&' && '&amp;') || (c == '"' && '&quot;') || '&#' + c.charCodeAt() + ';'
@@ -828,8 +1399,10 @@ copy(DocumentPosition, Node);
828
1399
  copy(DocumentPosition, Node.prototype);
829
1400
 
830
1401
  /**
831
- * @param callback return true for continue,false for break
832
- * @return boolean true: break visit;
1402
+ * @param callback
1403
+ * Return true for continue,false for break.
1404
+ * @returns
1405
+ * boolean true: break visit;
833
1406
  */
834
1407
  function _visitNode(node, callback) {
835
1408
  if (callback(node)) {
@@ -854,41 +1427,52 @@ function _visitNode(node, callback) {
854
1427
  * It should usually be created using `new DOMImplementation().createDocument(...)`
855
1428
  * or `new DOMImplementation().createHTMLDocument(...)`.
856
1429
  *
857
- * The constructor is considered a private API and offers to initially set the `contentType` property
858
- * via it's options parameter.
1430
+ * The constructor is considered a private API and offers to initially set the `contentType`
1431
+ * property via it's options parameter.
859
1432
  *
1433
+ * @class
1434
+ * @param {Symbol} symbol
860
1435
  * @param {DocumentOptions} [options]
1436
+ * @augments Node
861
1437
  * @private
862
- * @constructor
863
- *
864
1438
  * @see https://developer.mozilla.org/en-US/docs/Web/API/Document
865
1439
  * @see https://dom.spec.whatwg.org/#interface-document
866
1440
  */
867
- function Document(options) {
1441
+ function Document(symbol, options) {
1442
+ checkSymbol(symbol);
1443
+
868
1444
  var opt = options || {};
869
1445
  this.ownerDocument = this;
870
1446
  /**
871
1447
  * The mime type of the document is determined at creation time and can not be modified.
872
1448
  *
873
1449
  * @type {string}
874
- * @readonly
875
- *
876
1450
  * @see https://dom.spec.whatwg.org/#concept-document-content-type
877
- * @see DOMImplementation
878
- * @see MIME_TYPE
1451
+ * @see {@link DOMImplementation}
1452
+ * @see {@link MIME_TYPE}
1453
+ * @readonly
879
1454
  */
880
1455
  this.contentType = opt.contentType || MIME_TYPE.XML_APPLICATION;
881
1456
  /**
882
- *
883
1457
  * @type {'html' | 'xml'}
884
- * @readonly
885
- *
886
1458
  * @see https://dom.spec.whatwg.org/#concept-document-type
887
- * @see DOMImplementation
1459
+ * @see {@link DOMImplementation}
1460
+ * @readonly
888
1461
  */
889
- this.type = MIME_TYPE.isHTML(this.contentType) ? 'html' : 'xml';
1462
+ this.type = isHTMLMimeType(this.contentType) ? 'html' : 'xml';
890
1463
  }
891
1464
 
1465
+ /**
1466
+ * Updates the namespace mapping of an element when a new attribute is added.
1467
+ *
1468
+ * @param {Document} doc
1469
+ * The document that the element belongs to.
1470
+ * @param {Element} el
1471
+ * The element to which the attribute is being added.
1472
+ * @param {Attr} newAttr
1473
+ * The new attribute being added.
1474
+ * @private
1475
+ */
892
1476
  function _onAddAttribute(doc, el, newAttr) {
893
1477
  doc && doc._inc++;
894
1478
  var ns = newAttr.namespaceURI;
@@ -898,6 +1482,19 @@ function _onAddAttribute(doc, el, newAttr) {
898
1482
  }
899
1483
  }
900
1484
 
1485
+ /**
1486
+ * Updates the namespace mapping of an element when an attribute is removed.
1487
+ *
1488
+ * @param {Document} doc
1489
+ * The document that the element belongs to.
1490
+ * @param {Element} el
1491
+ * The element from which the attribute is being removed.
1492
+ * @param {Attr} newAttr
1493
+ * The attribute being removed.
1494
+ * @param {boolean} remove
1495
+ * Indicates whether the attribute is to be removed.
1496
+ * @private
1497
+ */
901
1498
  function _onRemoveAttribute(doc, el, newAttr, remove) {
902
1499
  doc && doc._inc++;
903
1500
  var ns = newAttr.namespaceURI;
@@ -908,15 +1505,19 @@ function _onRemoveAttribute(doc, el, newAttr, remove) {
908
1505
  }
909
1506
 
910
1507
  /**
911
- * Updates `el.childNodes`, updating the indexed items and it's `length`.
912
- * Passing `newChild` means it will be appended.
913
- * Otherwise it's assumed that an item has been removed,
914
- * and `el.firstNode` and it's `.nextSibling` are used
915
- * to walk the current list of child nodes.
1508
+ * Updates `el.childNodes`, adjusting the indexed items and its `length`.
1509
+ * If `newChild` is provided, it will be appended to the childNodes list.
1510
+ * Otherwise, it's assumed that an item has been removed,
1511
+ * and `el.firstNode` and its `.nextSibling` are used to iterate over the current list of child
1512
+ * nodes, effectively reindexing them.
916
1513
  *
917
1514
  * @param {Document} doc
1515
+ * The parent document of `el`.
918
1516
  * @param {Node} el
1517
+ * The parent node whose childNodes list needs to be updated.
919
1518
  * @param {Node} [newChild]
1519
+ * The new child node to be appended. If not provided, the function assumes a node has been
1520
+ * removed.
920
1521
  * @private
921
1522
  */
922
1523
  function _onUpdateChild(doc, el, newChild) {
@@ -943,17 +1544,22 @@ function _onUpdateChild(doc, el, newChild) {
943
1544
  * Removes the connections between `parentNode` and `child`
944
1545
  * and any existing `child.previousSibling` or `child.nextSibling`.
945
1546
  *
946
- * @see https://github.com/xmldom/xmldom/issues/135
947
- * @see https://github.com/xmldom/xmldom/issues/145
948
- *
949
1547
  * @param {Node} parentNode
1548
+ * The parent node from which the child node is to be removed.
950
1549
  * @param {Node} child
951
- * @returns {Node} the child that was removed.
1550
+ * The child node to be removed from the parentNode.
1551
+ * @returns {Node}
1552
+ * Returns the child node that was removed.
1553
+ * @throws {DOMException}
1554
+ * With code:
1555
+ * - {@link DOMException.NOT_FOUND_ERR} If the parentNode is not the parent of the child node.
952
1556
  * @private
1557
+ * @see https://github.com/xmldom/xmldom/issues/135
1558
+ * @see https://github.com/xmldom/xmldom/issues/145
953
1559
  */
954
1560
  function _removeChild(parentNode, child) {
955
1561
  if (parentNode !== child.parentNode) {
956
- throw new DOMException(NOT_FOUND_ERR, "child's parent is not parent");
1562
+ throw new DOMException(DOMException.NOT_FOUND_ERR, "child's parent is not parent");
957
1563
  }
958
1564
  //var index = parentNode.childNodes.
959
1565
  var oldPreviousSibling = child.previousSibling;
@@ -977,6 +1583,7 @@ function _removeChild(parentNode, child) {
977
1583
 
978
1584
  /**
979
1585
  * Returns `true` if `node` can be a parent for insertion.
1586
+ *
980
1587
  * @param {Node} node
981
1588
  * @returns {boolean}
982
1589
  */
@@ -989,6 +1596,7 @@ function hasValidParentNodeType(node) {
989
1596
 
990
1597
  /**
991
1598
  * Returns `true` if `node` can be inserted according to it's `nodeType`.
1599
+ *
992
1600
  * @param {Node} node
993
1601
  * @returns {boolean}
994
1602
  */
@@ -996,7 +1604,7 @@ function hasInsertableNodeType(node) {
996
1604
  return (
997
1605
  node &&
998
1606
  (isElementNode(node) ||
999
- isTextNode(node) ||
1607
+ node instanceof CharacterData ||
1000
1608
  isDocTypeNode(node) ||
1001
1609
  node.nodeType === Node.DOCUMENT_FRAGMENT_NODE ||
1002
1610
  node.nodeType === Node.COMMENT_NODE ||
@@ -1005,7 +1613,8 @@ function hasInsertableNodeType(node) {
1005
1613
  }
1006
1614
 
1007
1615
  /**
1008
- * Returns true if `node` is a DOCTYPE node
1616
+ * Returns true if `node` is a DOCTYPE node.
1617
+ *
1009
1618
  * @param {Node} node
1010
1619
  * @returns {boolean}
1011
1620
  */
@@ -1014,7 +1623,8 @@ function isDocTypeNode(node) {
1014
1623
  }
1015
1624
 
1016
1625
  /**
1017
- * Returns true if the node is an element
1626
+ * Returns true if the node is an element.
1627
+ *
1018
1628
  * @param {Node} node
1019
1629
  * @returns {boolean}
1020
1630
  */
@@ -1022,7 +1632,8 @@ function isElementNode(node) {
1022
1632
  return node && node.nodeType === Node.ELEMENT_NODE;
1023
1633
  }
1024
1634
  /**
1025
- * Returns true if `node` is a text node
1635
+ * Returns true if `node` is a text node.
1636
+ *
1026
1637
  * @param {Node} node
1027
1638
  * @returns {boolean}
1028
1639
  */
@@ -1034,11 +1645,13 @@ function isTextNode(node) {
1034
1645
  * Check if en element node can be inserted before `child`, or at the end if child is falsy,
1035
1646
  * according to the presence and position of a doctype node on the same level.
1036
1647
  *
1037
- * @param {Document} doc The document node
1038
- * @param {Node} child the node that would become the nextSibling if the element would be inserted
1039
- * @returns {boolean} `true` if an element can be inserted before child
1648
+ * @param {Document} doc
1649
+ * The document node.
1650
+ * @param {Node} child
1651
+ * The node that would become the nextSibling if the element would be inserted.
1652
+ * @returns {boolean}
1653
+ * `true` if an element can be inserted before child.
1040
1654
  * @private
1041
- * https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity
1042
1655
  */
1043
1656
  function isElementInsertionPossible(doc, child) {
1044
1657
  var parentChildNodes = doc.childNodes || [];
@@ -1053,11 +1666,13 @@ function isElementInsertionPossible(doc, child) {
1053
1666
  * Check if en element node can be inserted before `child`, or at the end if child is falsy,
1054
1667
  * according to the presence and position of a doctype node on the same level.
1055
1668
  *
1056
- * @param {Node} doc The document node
1057
- * @param {Node} child the node that would become the nextSibling if the element would be inserted
1058
- * @returns {boolean} `true` if an element can be inserted before child
1669
+ * @param {Node} doc
1670
+ * The document node.
1671
+ * @param {Node} child
1672
+ * The node that would become the nextSibling if the element would be inserted.
1673
+ * @returns {boolean}
1674
+ * `true` if an element can be inserted before child.
1059
1675
  * @private
1060
- * https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity
1061
1676
  */
1062
1677
  function isElementReplacementPossible(doc, child) {
1063
1678
  var parentChildNodes = doc.childNodes || [];
@@ -1074,28 +1689,41 @@ function isElementReplacementPossible(doc, child) {
1074
1689
  }
1075
1690
 
1076
1691
  /**
1077
- * @private
1078
- * Steps 1-5 of the checks before inserting and before replacing a child are the same.
1692
+ * Asserts pre-insertion validity of a node into a parent before a child.
1693
+ * Throws errors for invalid node combinations that would result in an ill-formed DOM.
1079
1694
  *
1080
- * @param {Node} parent the parent node to insert `node` into
1081
- * @param {Node} node the node to insert
1082
- * @param {Node=} child the node that should become the `nextSibling` of `node`
1083
- * @returns {Node}
1084
- * @throws DOMException for several node combinations that would create a DOM that is not well-formed.
1085
- * @throws DOMException if `child` is provided but is not a child of `parent`.
1695
+ * @param {Node} parent
1696
+ * The parent node to insert `node` into.
1697
+ * @param {Node} node
1698
+ * The node to insert.
1699
+ * @param {Node | null} child
1700
+ * The node that should become the `nextSibling` of `node`. If null, no sibling is considered.
1701
+ * @throws {DOMException}
1702
+ * With code:
1703
+ * - {@link DOMException.HIERARCHY_REQUEST_ERR} If `parent` is not a Document,
1704
+ * DocumentFragment, or Element node.
1705
+ * - {@link DOMException.HIERARCHY_REQUEST_ERR} If `node` is a host-including inclusive
1706
+ * ancestor of `parent`. (Currently not implemented)
1707
+ * - {@link DOMException.NOT_FOUND_ERR} If `child` is non-null and its `parent` is not
1708
+ * `parent`.
1709
+ * - {@link DOMException.HIERARCHY_REQUEST_ERR} If `node` is not a DocumentFragment,
1710
+ * DocumentType, Element, or CharacterData node.
1711
+ * - {@link DOMException.HIERARCHY_REQUEST_ERR} If either `node` is a Text node and `parent` is
1712
+ * a document, or if `node` is a doctype and `parent` is not a document.
1713
+ * @private
1086
1714
  * @see https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity
1087
1715
  * @see https://dom.spec.whatwg.org/#concept-node-replace
1088
1716
  */
1089
1717
  function assertPreInsertionValidity1to5(parent, node, child) {
1090
1718
  // 1. If `parent` is not a Document, DocumentFragment, or Element node, then throw a "HierarchyRequestError" DOMException.
1091
1719
  if (!hasValidParentNodeType(parent)) {
1092
- throw new DOMException(HIERARCHY_REQUEST_ERR, 'Unexpected parent node type ' + parent.nodeType);
1720
+ throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, 'Unexpected parent node type ' + parent.nodeType);
1093
1721
  }
1094
1722
  // 2. If `node` is a host-including inclusive ancestor of `parent`, then throw a "HierarchyRequestError" DOMException.
1095
1723
  // not implemented!
1096
1724
  // 3. If `child` is non-null and its parent is not `parent`, then throw a "NotFoundError" DOMException.
1097
1725
  if (child && child.parentNode !== parent) {
1098
- throw new DOMException(NOT_FOUND_ERR, 'child not in parent');
1726
+ throw new DOMException(DOMException.NOT_FOUND_ERR, 'child not in parent');
1099
1727
  }
1100
1728
  if (
1101
1729
  // 4. If `node` is not a DocumentFragment, DocumentType, Element, or CharacterData node, then throw a "HierarchyRequestError" DOMException.
@@ -1107,22 +1735,38 @@ function assertPreInsertionValidity1to5(parent, node, child) {
1107
1735
  (isDocTypeNode(node) && parent.nodeType !== Node.DOCUMENT_NODE)
1108
1736
  ) {
1109
1737
  throw new DOMException(
1110
- HIERARCHY_REQUEST_ERR,
1738
+ DOMException.HIERARCHY_REQUEST_ERR,
1111
1739
  'Unexpected node type ' + node.nodeType + ' for parent node type ' + parent.nodeType
1112
1740
  );
1113
1741
  }
1114
1742
  }
1115
1743
 
1116
1744
  /**
1117
- * @private
1118
- * Step 6 of the checks before inserting and before replacing a child are different.
1745
+ * Asserts pre-insertion validity of a node into a document before a child.
1746
+ * Throws errors for invalid node combinations that would result in an ill-formed DOM.
1119
1747
  *
1120
- * @param {Document} parent the parent node to insert `node` into
1121
- * @param {Node} node the node to insert
1122
- * @param {Node | undefined} child the node that should become the `nextSibling` of `node`
1748
+ * @param {Document} parent
1749
+ * The parent node to insert `node` into.
1750
+ * @param {Node} node
1751
+ * The node to insert.
1752
+ * @param {Node | undefined} child
1753
+ * The node that should become the `nextSibling` of `node`. If undefined, no sibling is
1754
+ * considered.
1123
1755
  * @returns {Node}
1124
- * @throws DOMException for several node combinations that would create a DOM that is not well-formed.
1125
- * @throws DOMException if `child` is provided but is not a child of `parent`.
1756
+ * @throws {DOMException}
1757
+ * With code:
1758
+ * - {@link DOMException.HIERARCHY_REQUEST_ERR} If `node` is a DocumentFragment with more than
1759
+ * one element child or has a Text node child.
1760
+ * - {@link DOMException.HIERARCHY_REQUEST_ERR} If `node` is a DocumentFragment with one
1761
+ * element child and either `parent` has an element child, `child` is a doctype, or `child` is
1762
+ * non-null and a doctype is following `child`.
1763
+ * - {@link DOMException.HIERARCHY_REQUEST_ERR} If `node` is an Element and `parent` has an
1764
+ * element child, `child` is a doctype, or `child` is non-null and a doctype is following
1765
+ * `child`.
1766
+ * - {@link DOMException.HIERARCHY_REQUEST_ERR} If `node` is a DocumentType and `parent` has a
1767
+ * doctype child, `child` is non-null and an element is preceding `child`, or `child` is null
1768
+ * and `parent` has an element child.
1769
+ * @private
1126
1770
  * @see https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity
1127
1771
  * @see https://dom.spec.whatwg.org/#concept-node-replace
1128
1772
  */
@@ -1135,12 +1779,12 @@ function assertPreInsertionValidityInDocument(parent, node, child) {
1135
1779
  var nodeChildElements = nodeChildNodes.filter(isElementNode);
1136
1780
  // If node has more than one element child or has a Text node child.
1137
1781
  if (nodeChildElements.length > 1 || find(nodeChildNodes, isTextNode)) {
1138
- throw new DOMException(HIERARCHY_REQUEST_ERR, 'More than one element or text in fragment');
1782
+ throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, 'More than one element or text in fragment');
1139
1783
  }
1140
1784
  // Otherwise, if `node` has one element child and either `parent` has an element child,
1141
1785
  // `child` is a doctype, or `child` is non-null and a doctype is following `child`.
1142
1786
  if (nodeChildElements.length === 1 && !isElementInsertionPossible(parent, child)) {
1143
- throw new DOMException(HIERARCHY_REQUEST_ERR, 'Element in fragment can not be inserted before doctype');
1787
+ throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, 'Element in fragment can not be inserted before doctype');
1144
1788
  }
1145
1789
  }
1146
1790
  // Element
@@ -1148,37 +1792,40 @@ function assertPreInsertionValidityInDocument(parent, node, child) {
1148
1792
  // `parent` has an element child, `child` is a doctype,
1149
1793
  // or `child` is non-null and a doctype is following `child`.
1150
1794
  if (!isElementInsertionPossible(parent, child)) {
1151
- throw new DOMException(HIERARCHY_REQUEST_ERR, 'Only one element can be added and only after doctype');
1795
+ throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, 'Only one element can be added and only after doctype');
1152
1796
  }
1153
1797
  }
1154
1798
  // DocumentType
1155
1799
  if (isDocTypeNode(node)) {
1156
1800
  // `parent` has a doctype child,
1157
1801
  if (find(parentChildNodes, isDocTypeNode)) {
1158
- throw new DOMException(HIERARCHY_REQUEST_ERR, 'Only one doctype is allowed');
1802
+ throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, 'Only one doctype is allowed');
1159
1803
  }
1160
1804
  var parentElementChild = find(parentChildNodes, isElementNode);
1161
1805
  // `child` is non-null and an element is preceding `child`,
1162
1806
  if (child && parentChildNodes.indexOf(parentElementChild) < parentChildNodes.indexOf(child)) {
1163
- throw new DOMException(HIERARCHY_REQUEST_ERR, 'Doctype can only be inserted before an element');
1807
+ throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, 'Doctype can only be inserted before an element');
1164
1808
  }
1165
1809
  // or `child` is null and `parent` has an element child.
1166
1810
  if (!child && parentElementChild) {
1167
- throw new DOMException(HIERARCHY_REQUEST_ERR, 'Doctype can not be appended since element is present');
1811
+ throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, 'Doctype can not be appended since element is present');
1168
1812
  }
1169
1813
  }
1170
1814
  }
1171
1815
 
1172
1816
  /**
1173
- * @private
1174
- * Step 6 of the checks before inserting and before replacing a child are different.
1175
- *
1176
- * @param {Document} parent the parent node to insert `node` into
1177
- * @param {Node} node the node to insert
1178
- * @param {Node | undefined} child the node that should become the `nextSibling` of `node`
1817
+ * @param {Document} parent
1818
+ * The parent node to insert `node` into.
1819
+ * @param {Node} node
1820
+ * The node to insert.
1821
+ * @param {Node | undefined} child
1822
+ * the node that should become the `nextSibling` of `node`
1179
1823
  * @returns {Node}
1180
- * @throws DOMException for several node combinations that would create a DOM that is not well-formed.
1181
- * @throws DOMException if `child` is provided but is not a child of `parent`.
1824
+ * @throws {DOMException}
1825
+ * For several node combinations that would create a DOM that is not well-formed.
1826
+ * @throws {DOMException}
1827
+ * If `child` is provided but is not a child of `parent`.
1828
+ * @private
1182
1829
  * @see https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity
1183
1830
  * @see https://dom.spec.whatwg.org/#concept-node-replace
1184
1831
  */
@@ -1191,18 +1838,18 @@ function assertPreReplacementValidityInDocument(parent, node, child) {
1191
1838
  var nodeChildElements = nodeChildNodes.filter(isElementNode);
1192
1839
  // If `node` has more than one element child or has a Text node child.
1193
1840
  if (nodeChildElements.length > 1 || find(nodeChildNodes, isTextNode)) {
1194
- throw new DOMException(HIERARCHY_REQUEST_ERR, 'More than one element or text in fragment');
1841
+ throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, 'More than one element or text in fragment');
1195
1842
  }
1196
1843
  // Otherwise, if `node` has one element child and either `parent` has an element child that is not `child` or a doctype is following `child`.
1197
1844
  if (nodeChildElements.length === 1 && !isElementReplacementPossible(parent, child)) {
1198
- throw new DOMException(HIERARCHY_REQUEST_ERR, 'Element in fragment can not be inserted before doctype');
1845
+ throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, 'Element in fragment can not be inserted before doctype');
1199
1846
  }
1200
1847
  }
1201
1848
  // Element
1202
1849
  if (isElementNode(node)) {
1203
1850
  // `parent` has an element child that is not `child` or a doctype is following `child`.
1204
1851
  if (!isElementReplacementPossible(parent, child)) {
1205
- throw new DOMException(HIERARCHY_REQUEST_ERR, 'Only one element can be added and only after doctype');
1852
+ throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, 'Only one element can be added and only after doctype');
1206
1853
  }
1207
1854
  }
1208
1855
  // DocumentType
@@ -1213,24 +1860,39 @@ function assertPreReplacementValidityInDocument(parent, node, child) {
1213
1860
 
1214
1861
  // `parent` has a doctype child that is not `child`,
1215
1862
  if (find(parentChildNodes, hasDoctypeChildThatIsNotChild)) {
1216
- throw new DOMException(HIERARCHY_REQUEST_ERR, 'Only one doctype is allowed');
1863
+ throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, 'Only one doctype is allowed');
1217
1864
  }
1218
1865
  var parentElementChild = find(parentChildNodes, isElementNode);
1219
1866
  // or an element is preceding `child`.
1220
1867
  if (child && parentChildNodes.indexOf(parentElementChild) < parentChildNodes.indexOf(child)) {
1221
- throw new DOMException(HIERARCHY_REQUEST_ERR, 'Doctype can only be inserted before an element');
1868
+ throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, 'Doctype can only be inserted before an element');
1222
1869
  }
1223
1870
  }
1224
1871
  }
1225
1872
 
1226
1873
  /**
1227
- * @private
1228
- * @param {Node} parent the parent node to insert `node` into
1229
- * @param {Node} node the node to insert
1230
- * @param {Node=} child the node that should become the `nextSibling` of `node`
1874
+ * Inserts a node into a parent node before a child node.
1875
+ *
1876
+ * @param {Node} parent
1877
+ * The parent node to insert the node into.
1878
+ * @param {Node} node
1879
+ * The node to insert into the parent.
1880
+ * @param {Node | null} child
1881
+ * The node that should become the next sibling of the node.
1882
+ * If null, the function inserts the node at the end of the children of the parent node.
1883
+ * @param {Function} [_inDocumentAssertion]
1884
+ * An optional function to check pre-insertion validity if parent is a document node.
1885
+ * Defaults to {@link assertPreInsertionValidityInDocument}
1231
1886
  * @returns {Node}
1232
- * @throws DOMException for several node combinations that would create a DOM that is not well-formed.
1233
- * @throws DOMException if `child` is provided but is not a child of `parent`.
1887
+ * Returns the inserted node.
1888
+ * @throws {DOMException}
1889
+ * Throws a DOMException if inserting the node would result in a DOM tree that is not
1890
+ * well-formed. See {@link assertPreInsertionValidity1to5},
1891
+ * {@link assertPreInsertionValidityInDocument}.
1892
+ * @throws {DOMException}
1893
+ * Throws a DOMException if child is provided but is not a child of the parent. See
1894
+ * {@link Node.removeChild}
1895
+ * @private
1234
1896
  * @see https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity
1235
1897
  */
1236
1898
  function _insertBefore(parent, node, child, _inDocumentAssertion) {
@@ -1282,39 +1944,12 @@ function _insertBefore(parent, node, child, _inDocumentAssertion) {
1282
1944
  return node;
1283
1945
  }
1284
1946
 
1285
- /**
1286
- * Appends `newChild` to `parentNode`.
1287
- * If `newChild` is already connected to a `parentNode` it is first removed from it.
1288
- *
1289
- * @see https://github.com/xmldom/xmldom/issues/135
1290
- * @see https://github.com/xmldom/xmldom/issues/145
1291
- * @param {Node} parentNode
1292
- * @param {Node} newChild
1293
- * @returns {Node}
1294
- * @private
1295
- */
1296
- function _appendSingleChild(parentNode, newChild) {
1297
- if (newChild.parentNode) {
1298
- newChild.parentNode.removeChild(newChild);
1299
- }
1300
- newChild.parentNode = parentNode;
1301
- newChild.previousSibling = parentNode.lastChild;
1302
- newChild.nextSibling = null;
1303
- if (newChild.previousSibling) {
1304
- newChild.previousSibling.nextSibling = newChild;
1305
- } else {
1306
- parentNode.firstChild = newChild;
1307
- }
1308
- parentNode.lastChild = newChild;
1309
- _onUpdateChild(parentNode.ownerDocument, parentNode, newChild);
1310
- return newChild;
1311
- }
1312
-
1313
1947
  Document.prototype = {
1314
1948
  /**
1315
- * The implementation that created this document
1316
- * @readonly
1949
+ * The implementation that created this document.
1950
+ *
1317
1951
  * @type DOMImplementation
1952
+ * @readonly
1318
1953
  */
1319
1954
  implementation: null,
1320
1955
  nodeName: '#document',
@@ -1322,8 +1957,8 @@ Document.prototype = {
1322
1957
  /**
1323
1958
  * The DocumentType node of the document.
1324
1959
  *
1325
- * @readonly
1326
1960
  * @type DocumentType
1961
+ * @readonly
1327
1962
  */
1328
1963
  doctype: null,
1329
1964
  documentElement: null,
@@ -1385,19 +2020,20 @@ Document.prototype = {
1385
2020
  },
1386
2021
 
1387
2022
  /**
1388
- * The `getElementsByClassName` method of `Document` interface returns an array-like object
1389
- * of all child elements which have **all** of the given class name(s).
1390
- *
1391
- * Returns an empty list if `classeNames` is an empty string or only contains HTML white space characters.
2023
+ * The `getElementsByClassName` method of `Document` interface returns an array-like object of
2024
+ * all child elements which have **all** of the given class name(s).
1392
2025
  *
2026
+ * Returns an empty list if `classeNames` is an empty string or only contains HTML white space
2027
+ * characters.
1393
2028
  *
1394
2029
  * Warning: This is a live LiveNodeList.
1395
2030
  * Changes in the DOM will reflect in the array as the changes occur.
1396
2031
  * If an element selected by this array no longer qualifies for the selector,
1397
2032
  * it will automatically be removed. Be aware of this for iteration purposes.
1398
2033
  *
1399
- * @param {string} classNames is a string representing the class name(s) to match; multiple class names are separated by (ASCII-)whitespace
1400
- *
2034
+ * @param {string} classNames
2035
+ * Is a string representing the class name(s) to match; multiple class names are separated by
2036
+ * (ASCII-)whitespace.
1401
2037
  * @see https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName
1402
2038
  * @see https://dom.spec.whatwg.org/#concept-getelementsbyclassname
1403
2039
  */
@@ -1434,26 +2070,25 @@ Document.prototype = {
1434
2070
  * otherwise no transformation is being applied.
1435
2071
  * When `contentType` implies the HTML namespace, it will be set as `namespaceURI`.
1436
2072
  *
1437
- * __This implementation differs from the specification:__
1438
- * - The provided name is not checked against the `Name` production,
1439
- * so no related error will be thrown.
2073
+ * __This implementation differs from the specification:__ - The provided name is not checked
2074
+ * against the `Name` production,
2075
+ * so no related error will be thrown.
1440
2076
  * - There is no interface `HTMLElement`, it is always an `Element`.
1441
2077
  * - There is no support for a second argument to indicate using custom elements.
1442
2078
  *
1443
2079
  * @param {string} tagName
1444
- * @return {Element}
1445
- *
2080
+ * @returns {Element}
1446
2081
  * @see https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement
1447
2082
  * @see https://dom.spec.whatwg.org/#dom-document-createelement
1448
2083
  * @see https://dom.spec.whatwg.org/#concept-create-element
1449
2084
  */
1450
2085
  createElement: function (tagName) {
1451
- var node = new Element();
2086
+ var node = new Element(PDC);
1452
2087
  node.ownerDocument = this;
1453
2088
  if (this.type === 'html') {
1454
2089
  tagName = tagName.toLowerCase();
1455
2090
  }
1456
- if (MIME_TYPE.hasDefaultHTMLNamespace(this.contentType)) {
2091
+ if (hasDefaultHTMLNamespace(this.contentType)) {
1457
2092
  node.namespaceURI = NAMESPACE.HTML;
1458
2093
  }
1459
2094
  node.nodeName = tagName;
@@ -1465,33 +2100,33 @@ Document.prototype = {
1465
2100
  return node;
1466
2101
  },
1467
2102
  createDocumentFragment: function () {
1468
- var node = new DocumentFragment();
2103
+ var node = new DocumentFragment(PDC);
1469
2104
  node.ownerDocument = this;
1470
2105
  node.childNodes = new NodeList();
1471
2106
  return node;
1472
2107
  },
1473
2108
  createTextNode: function (data) {
1474
- var node = new Text();
2109
+ var node = new Text(PDC);
1475
2110
  node.ownerDocument = this;
1476
2111
  node.appendData(data);
1477
2112
  return node;
1478
2113
  },
1479
2114
  createComment: function (data) {
1480
- var node = new Comment();
2115
+ var node = new Comment(PDC);
1481
2116
  node.ownerDocument = this;
1482
2117
  node.appendData(data);
1483
2118
  return node;
1484
2119
  },
1485
2120
  createCDATASection: function (data) {
1486
- var node = new CDATASection();
2121
+ var node = new CDATASection(PDC);
1487
2122
  node.ownerDocument = this;
1488
2123
  node.appendData(data);
1489
2124
  return node;
1490
2125
  },
1491
2126
  createProcessingInstruction: function (target, data) {
1492
- var node = new ProcessingInstruction();
2127
+ var node = new ProcessingInstruction(PDC);
1493
2128
  node.ownerDocument = this;
1494
- node.tagName = node.target = target;
2129
+ node.nodeName = node.target = target;
1495
2130
  node.nodeValue = node.data = data;
1496
2131
  return node;
1497
2132
  },
@@ -1500,19 +2135,18 @@ Document.prototype = {
1500
2135
  * In HTML Documents `localName` is the lower cased `name`,
1501
2136
  * otherwise no transformation is being applied.
1502
2137
  *
1503
- * __This implementation differs from the specification:__
1504
- * - The provided name is not checked against the `Name` production,
1505
- * so no related error will be thrown.
2138
+ * __This implementation differs from the specification:__ - The provided name is not checked
2139
+ * against the `Name` production,
2140
+ * so no related error will be thrown.
1506
2141
  *
1507
2142
  * @param {string} name
1508
- * @return {Attr}
1509
- *
2143
+ * @returns {Attr}
1510
2144
  * @see https://developer.mozilla.org/en-US/docs/Web/API/Document/createAttribute
1511
2145
  * @see https://dom.spec.whatwg.org/#dom-document-createattribute
1512
2146
  */
1513
2147
  createAttribute: function (name) {
1514
- if (!conventions.QNAME.test(name)) {
1515
- throw new DOMException(INVALID_CHARACTER_ERR, 'invalid character in name "' + name + '"');
2148
+ if (!g.QName_exact.test(name)) {
2149
+ throw new DOMException(DOMException.INVALID_CHARACTER_ERR, 'invalid character in name "' + name + '"');
1516
2150
  }
1517
2151
  if (this.type === 'html') {
1518
2152
  name = name.toLowerCase();
@@ -1520,7 +2154,7 @@ Document.prototype = {
1520
2154
  return this._createAttribute(name);
1521
2155
  },
1522
2156
  _createAttribute: function (name) {
1523
- var node = new Attr();
2157
+ var node = new Attr(PDC);
1524
2158
  node.ownerDocument = this;
1525
2159
  node.name = name;
1526
2160
  node.nodeName = name;
@@ -1529,7 +2163,7 @@ Document.prototype = {
1529
2163
  return node;
1530
2164
  },
1531
2165
  createEntityReference: function (name) {
1532
- var node = new EntityReference();
2166
+ var node = new EntityReference(PDC);
1533
2167
  node.ownerDocument = this;
1534
2168
  node.nodeName = name;
1535
2169
  return node;
@@ -1537,7 +2171,7 @@ Document.prototype = {
1537
2171
  // Introduced in DOM Level 2:
1538
2172
  createElementNS: function (namespaceURI, qualifiedName) {
1539
2173
  var validated = validateAndExtract(namespaceURI, qualifiedName);
1540
- var node = new Element();
2174
+ var node = new Element(PDC);
1541
2175
  var attrs = (node.attributes = new NamedNodeMap());
1542
2176
  node.childNodes = new NodeList();
1543
2177
  node.ownerDocument = this;
@@ -1552,8 +2186,7 @@ Document.prototype = {
1552
2186
  // Introduced in DOM Level 2:
1553
2187
  createAttributeNS: function (namespaceURI, qualifiedName) {
1554
2188
  var validated = validateAndExtract(namespaceURI, qualifiedName);
1555
- var node = new Attr();
1556
- var pl = qualifiedName.split(':');
2189
+ var node = new Attr(PDC);
1557
2190
  node.ownerDocument = this;
1558
2191
  node.nodeName = qualifiedName;
1559
2192
  node.name = qualifiedName;
@@ -1566,8 +2199,10 @@ Document.prototype = {
1566
2199
  };
1567
2200
  _extends(Document, Node);
1568
2201
 
1569
- function Element() {
1570
- this._nsMap = {};
2202
+ function Element(symbol) {
2203
+ checkSymbol(symbol);
2204
+
2205
+ this._nsMap = Object.create(null);
1571
2206
  }
1572
2207
  Element.prototype = {
1573
2208
  nodeType: ELEMENT_NODE,
@@ -1581,10 +2216,11 @@ Element.prototype = {
1581
2216
  return !!this.getAttributeNode(name);
1582
2217
  },
1583
2218
  /**
1584
- * Returns element’s first attribute whose qualified name is `name`, and `null` if there is no such attribute.
2219
+ * Returns element’s first attribute whose qualified name is `name`, and `null`
2220
+ * if there is no such attribute.
1585
2221
  *
1586
2222
  * @param {string} name
1587
- * @return {string | null}
2223
+ * @returns {string | null}
1588
2224
  */
1589
2225
  getAttribute: function (name) {
1590
2226
  var attr = this.getAttributeNode(name);
@@ -1619,15 +2255,6 @@ Element.prototype = {
1619
2255
  var attr = this.getAttributeNode(name);
1620
2256
  attr && this.removeAttributeNode(attr);
1621
2257
  },
1622
-
1623
- // four real operation method
1624
- appendChild: function (newChild) {
1625
- if (newChild.nodeType === DOCUMENT_FRAGMENT_NODE) {
1626
- return this.insertBefore(newChild, null);
1627
- } else {
1628
- return _appendSingleChild(this, newChild);
1629
- }
1630
- },
1631
2258
  setAttributeNode: function (newAttr) {
1632
2259
  return this.attributes.setNamedItem(newAttr);
1633
2260
  },
@@ -1648,24 +2275,25 @@ Element.prototype = {
1648
2275
  return this.getAttributeNodeNS(namespaceURI, localName) != null;
1649
2276
  },
1650
2277
  /**
1651
- * Returns element’s attribute whose namespace is `namespaceURI` and local name is `localName`,
2278
+ * Returns element’s attribute whose namespace is `namespaceURI` and local name is
2279
+ * `localName`,
1652
2280
  * or `null` if there is no such attribute.
1653
2281
  *
1654
2282
  * @param {string} namespaceURI
1655
2283
  * @param {string} localName
1656
- * @return {string | null}
2284
+ * @returns {string | null}
1657
2285
  */
1658
2286
  getAttributeNS: function (namespaceURI, localName) {
1659
2287
  var attr = this.getAttributeNodeNS(namespaceURI, localName);
1660
2288
  return attr ? attr.value : null;
1661
2289
  },
1662
2290
  /**
1663
- * Sets the value of element’s attribute whose namespace is `namespaceURI` and local name is `localName` to value.
2291
+ * Sets the value of element’s attribute whose namespace is `namespaceURI` and local name is
2292
+ * `localName` to value.
1664
2293
  *
1665
2294
  * @param {string} namespaceURI
1666
2295
  * @param {string} qualifiedName
1667
2296
  * @param {string} value
1668
- *
1669
2297
  * @see https://dom.spec.whatwg.org/#dom-element-setattributens
1670
2298
  */
1671
2299
  setAttributeNS: function (namespaceURI, qualifiedName, value) {
@@ -1695,8 +2323,8 @@ Element.prototype = {
1695
2323
  *
1696
2324
  * When called on an HTML element in an HTML document,
1697
2325
  * `getElementsByTagName` lower-cases the argument before searching for it.
1698
- * This is undesirable when trying to match camel-cased SVG elements
1699
- * (such as `<linearGradient>`) in an HTML document.
2326
+ * This is undesirable when trying to match camel-cased SVG elements (such as
2327
+ * `<linearGradient>`) in an HTML document.
1700
2328
  * Instead, use `Element.getElementsByTagNameNS()`,
1701
2329
  * which preserves the capitalization of the tag name.
1702
2330
  *
@@ -1704,8 +2332,7 @@ Element.prototype = {
1704
2332
  * except that it only searches for elements that are descendants of the specified element.
1705
2333
  *
1706
2334
  * @param {string} qualifiedName
1707
- * @return {LiveNodeList}
1708
- *
2335
+ * @returns {LiveNodeList}
1709
2336
  * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/getElementsByTagName
1710
2337
  * @see https://dom.spec.whatwg.org/#concept-getelementsbytagname
1711
2338
  */
@@ -1752,7 +2379,9 @@ Document.prototype.getElementsByTagName = Element.prototype.getElementsByTagName
1752
2379
  Document.prototype.getElementsByTagNameNS = Element.prototype.getElementsByTagNameNS;
1753
2380
 
1754
2381
  _extends(Element, Node);
1755
- function Attr() {
2382
+ function Attr(symbol) {
2383
+ checkSymbol(symbol);
2384
+
1756
2385
  this.namespaceURI = null;
1757
2386
  this.prefix = null;
1758
2387
  this.ownerElement = null;
@@ -1760,7 +2389,9 @@ function Attr() {
1760
2389
  Attr.prototype.nodeType = ATTRIBUTE_NODE;
1761
2390
  _extends(Attr, Node);
1762
2391
 
1763
- function CharacterData() {}
2392
+ function CharacterData(symbol) {
2393
+ checkSymbol(symbol);
2394
+ }
1764
2395
  CharacterData.prototype = {
1765
2396
  data: '',
1766
2397
  substringData: function (offset, count) {
@@ -1774,9 +2405,6 @@ CharacterData.prototype = {
1774
2405
  insertData: function (offset, text) {
1775
2406
  this.replaceData(offset, 0, text);
1776
2407
  },
1777
- appendChild: function (newChild) {
1778
- throw new Error(ExceptionMessage[HIERARCHY_REQUEST_ERR]);
1779
- },
1780
2408
  deleteData: function (offset, count) {
1781
2409
  this.replaceData(offset, count, '');
1782
2410
  },
@@ -1789,7 +2417,9 @@ CharacterData.prototype = {
1789
2417
  },
1790
2418
  };
1791
2419
  _extends(CharacterData, Node);
1792
- function Text() {}
2420
+ function Text(symbol) {
2421
+ checkSymbol(symbol);
2422
+ }
1793
2423
  Text.prototype = {
1794
2424
  nodeName: '#text',
1795
2425
  nodeType: TEXT_NODE,
@@ -1807,42 +2437,58 @@ Text.prototype = {
1807
2437
  },
1808
2438
  };
1809
2439
  _extends(Text, CharacterData);
1810
- function Comment() {}
2440
+ function Comment(symbol) {
2441
+ checkSymbol(symbol);
2442
+ }
1811
2443
  Comment.prototype = {
1812
2444
  nodeName: '#comment',
1813
2445
  nodeType: COMMENT_NODE,
1814
2446
  };
1815
2447
  _extends(Comment, CharacterData);
1816
2448
 
1817
- function CDATASection() {}
2449
+ function CDATASection(symbol) {
2450
+ checkSymbol(symbol);
2451
+ }
1818
2452
  CDATASection.prototype = {
1819
2453
  nodeName: '#cdata-section',
1820
2454
  nodeType: CDATA_SECTION_NODE,
1821
2455
  };
1822
2456
  _extends(CDATASection, CharacterData);
1823
2457
 
1824
- function DocumentType() {}
2458
+ function DocumentType(symbol) {
2459
+ checkSymbol(symbol);
2460
+ }
1825
2461
  DocumentType.prototype.nodeType = DOCUMENT_TYPE_NODE;
1826
2462
  _extends(DocumentType, Node);
1827
2463
 
1828
- function Notation() {}
2464
+ function Notation(symbol) {
2465
+ checkSymbol(symbol);
2466
+ }
1829
2467
  Notation.prototype.nodeType = NOTATION_NODE;
1830
2468
  _extends(Notation, Node);
1831
2469
 
1832
- function Entity() {}
2470
+ function Entity(symbol) {
2471
+ checkSymbol(symbol);
2472
+ }
1833
2473
  Entity.prototype.nodeType = ENTITY_NODE;
1834
2474
  _extends(Entity, Node);
1835
2475
 
1836
- function EntityReference() {}
2476
+ function EntityReference(symbol) {
2477
+ checkSymbol(symbol);
2478
+ }
1837
2479
  EntityReference.prototype.nodeType = ENTITY_REFERENCE_NODE;
1838
2480
  _extends(EntityReference, Node);
1839
2481
 
1840
- function DocumentFragment() {}
2482
+ function DocumentFragment(symbol) {
2483
+ checkSymbol(symbol);
2484
+ }
1841
2485
  DocumentFragment.prototype.nodeName = '#document-fragment';
1842
2486
  DocumentFragment.prototype.nodeType = DOCUMENT_FRAGMENT_NODE;
1843
2487
  _extends(DocumentFragment, Node);
1844
2488
 
1845
- function ProcessingInstruction() {}
2489
+ function ProcessingInstruction(symbol) {
2490
+ checkSymbol(symbol);
2491
+ }
1846
2492
  ProcessingInstruction.prototype.nodeType = PROCESSING_INSTRUCTION_NODE;
1847
2493
  _extends(ProcessingInstruction, Node);
1848
2494
  function XMLSerializer() {}
@@ -1897,17 +2543,19 @@ function needNamespaceDefine(node, isHTML, visibleNamespaces) {
1897
2543
  return true;
1898
2544
  }
1899
2545
  /**
1900
- * Well-formed constraint: No < in Attribute Values
2546
+ * Literal whitespace other than space that appear in attribute values are serialized as
2547
+ * their entity references, so they will be preserved.
2548
+ * (In contrast to whitespace literals in the input which are normalized to spaces).
2549
+ *
2550
+ * Well-formed constraint: No < in Attribute Values:
1901
2551
  * > The replacement text of any entity referred to directly or indirectly
1902
2552
  * > in an attribute value must not contain a <.
2553
+ *
1903
2554
  * @see https://www.w3.org/TR/xml11/#CleanAttrVals
1904
2555
  * @see https://www.w3.org/TR/xml11/#NT-AttValue
1905
- *
1906
- * Literal whitespace other than space that appear in attribute values
1907
- * are serialized as their entity references, so they will be preserved.
1908
- * (In contrast to whitespace literals in the input which are normalized to spaces)
1909
2556
  * @see https://www.w3.org/TR/xml11/#AVNormalize
1910
2557
  * @see https://w3c.github.io/DOM-Parsing/#serializing-an-element-s-attributes
2558
+ * @prettierignore
1911
2559
  */
1912
2560
  function addSerializedAttribute(buf, qualifiedName, value) {
1913
2561
  buf.push(' ', qualifiedName, '="', value.replace(/[<>&"\t\n\r]/g, _xmlEncoder), '"');
@@ -2008,7 +2656,7 @@ function serializeToString(node, buf, nodeFilter, visibleNamespaces) {
2008
2656
  }
2009
2657
  // in XML elements can be closed when they have no children
2010
2658
  var canCloseTag = !child;
2011
- if (canCloseTag && (isHTML || NAMESPACE.isHTML(node.namespaceURI))) {
2659
+ if (canCloseTag && (isHTML || node.namespaceURI === NAMESPACE.HTML)) {
2012
2660
  // in HTML (doc or ns) only void elements can be closed right away
2013
2661
  canCloseTag = isHTMLVoidElement(nodeName);
2014
2662
  }
@@ -2048,46 +2696,45 @@ function serializeToString(node, buf, nodeFilter, visibleNamespaces) {
2048
2696
  case ATTRIBUTE_NODE:
2049
2697
  return addSerializedAttribute(buf, node.name, node.value);
2050
2698
  case TEXT_NODE:
2051
- /**
2699
+ /*
2052
2700
  * The ampersand character (&) and the left angle bracket (<) must not appear in their literal form,
2053
- * except when used as markup delimiters, or within a comment, a processing instruction, or a CDATA section.
2054
- * If they are needed elsewhere, they must be escaped using either numeric character references or the strings
2055
- * `&amp;` and `&lt;` respectively.
2056
- * The right angle bracket (>) may be represented using the string " &gt; ", and must, for compatibility,
2057
- * be escaped using either `&gt;` or a character reference when it appears in the string `]]>` in content,
2701
+ * except when used as markup delimiters, or within a comment, a processing instruction,
2702
+ * or a CDATA section.
2703
+ * If they are needed elsewhere, they must be escaped using either numeric character
2704
+ * references or the strings `&amp;` and `&lt;` respectively.
2705
+ * The right angle bracket (>) may be represented using the string " &gt; ",
2706
+ * and must, for compatibility, be escaped using either `&gt;`,
2707
+ * or a character reference when it appears in the string `]]>` in content,
2058
2708
  * when that string is not marking the end of a CDATA section.
2059
2709
  *
2060
- * In the content of elements, character data is any string of characters
2061
- * which does not contain the start-delimiter of any markup
2062
- * and does not include the CDATA-section-close delimiter, `]]>`.
2710
+ * In the content of elements, character data is any string of characters which does not
2711
+ * contain the start-delimiter of any markup and does not include the CDATA-section-close
2712
+ * delimiter, `]]>`.
2063
2713
  *
2064
2714
  * @see https://www.w3.org/TR/xml/#NT-CharData
2065
2715
  * @see https://w3c.github.io/DOM-Parsing/#xml-serializing-a-text-node
2066
2716
  */
2067
2717
  return buf.push(node.data.replace(/[<&>]/g, _xmlEncoder));
2068
2718
  case CDATA_SECTION_NODE:
2069
- return buf.push('<![CDATA[', node.data, ']]>');
2719
+ return buf.push(g.CDATA_START, node.data, g.CDATA_END);
2070
2720
  case COMMENT_NODE:
2071
- return buf.push('<!--', node.data, '-->');
2721
+ return buf.push(g.COMMENT_START, node.data, g.COMMENT_END);
2072
2722
  case DOCUMENT_TYPE_NODE:
2073
2723
  var pubid = node.publicId;
2074
2724
  var sysid = node.systemId;
2075
- buf.push('<!DOCTYPE ', node.name);
2725
+ buf.push(g.DOCTYPE_DECL_START, ' ', node.name);
2076
2726
  if (pubid) {
2077
- buf.push(' PUBLIC ', pubid);
2078
- if (sysid && sysid != '.') {
2727
+ buf.push(' ', g.PUBLIC, ' ', pubid);
2728
+ if (sysid && sysid !== '.') {
2079
2729
  buf.push(' ', sysid);
2080
2730
  }
2081
- buf.push('>');
2082
- } else if (sysid && sysid != '.') {
2083
- buf.push(' SYSTEM ', sysid, '>');
2084
- } else {
2085
- var sub = node.internalSubset;
2086
- if (sub) {
2087
- buf.push(' [', sub, ']');
2088
- }
2089
- buf.push('>');
2731
+ } else if (sysid && sysid !== '.') {
2732
+ buf.push(' ', g.SYSTEM, ' ', sysid);
2733
+ }
2734
+ if (node.internalSubset) {
2735
+ buf.push(' [', node.internalSubset, ']');
2090
2736
  }
2737
+ buf.push('>');
2091
2738
  return;
2092
2739
  case PROCESSING_INSTRUCTION_NODE:
2093
2740
  return buf.push('<?', node.target, ' ', node.data, '?>');
@@ -2144,13 +2791,27 @@ function importNode(doc, node, deep) {
2144
2791
  }
2145
2792
  return node2;
2146
2793
  }
2147
- //
2148
- //var _relationMap = {firstChild:1,lastChild:1,previousSibling:1,nextSibling:1,
2149
- // attributes:1,childNodes:1,parentNode:1,documentElement:1,doctype,};
2794
+
2795
+ /**
2796
+ * Creates a copy of a node from an existing one.
2797
+ *
2798
+ * @param {Document} doc
2799
+ * The Document object representing the document that the new node will belong to.
2800
+ * @param {Node} node
2801
+ * The node to clone.
2802
+ * @param {boolean} deep
2803
+ * If true, the contents of the node are recursively copied.
2804
+ * If false, only the node itself (and its attributes, if it is an element) are copied.
2805
+ * @returns {Node}
2806
+ * Returns the newly created copy of the node.
2807
+ * @throws {DOMException}
2808
+ * May throw a DOMException if operations within setAttributeNode or appendChild (which are
2809
+ * potentially invoked in this function) do not meet their specific constraints.
2810
+ */
2150
2811
  function cloneNode(doc, node, deep) {
2151
- var node2 = new node.constructor();
2812
+ var node2 = new node.constructor(PDC);
2152
2813
  for (var n in node) {
2153
- if (Object.prototype.hasOwnProperty.call(node, n)) {
2814
+ if (hasOwn(node, n)) {
2154
2815
  var v = node[n];
2155
2816
  if (typeof v != 'object') {
2156
2817
  if (v != node2[n]) {
@@ -2251,13 +2912,23 @@ try {
2251
2912
  //ie8
2252
2913
  }
2253
2914
 
2915
+ exports._updateLiveList = _updateLiveList;
2254
2916
  exports.Attr = Attr;
2917
+ exports.CDATASection = CDATASection;
2918
+ exports.CharacterData = CharacterData;
2919
+ exports.Comment = Comment;
2255
2920
  exports.Document = Document;
2921
+ exports.DocumentFragment = DocumentFragment;
2256
2922
  exports.DocumentType = DocumentType;
2257
- exports.DOMException = DOMException;
2258
2923
  exports.DOMImplementation = DOMImplementation;
2259
2924
  exports.Element = Element;
2925
+ exports.Entity = Entity;
2926
+ exports.EntityReference = EntityReference;
2927
+ exports.LiveNodeList = LiveNodeList;
2260
2928
  exports.NamedNodeMap = NamedNodeMap;
2261
2929
  exports.Node = Node;
2262
2930
  exports.NodeList = NodeList;
2931
+ exports.Notation = Notation;
2932
+ exports.Text = Text;
2263
2933
  exports.XMLSerializer = XMLSerializer;
2934
+ exports.ProcessingInstruction = ProcessingInstruction;