happy-dom 9.8.2 → 9.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of happy-dom might be problematic. Click here for more details.

Files changed (35) hide show
  1. package/lib/event/EventTarget.d.ts.map +1 -1
  2. package/lib/event/EventTarget.js +9 -0
  3. package/lib/event/EventTarget.js.map +1 -1
  4. package/lib/nodes/document/Document.d.ts +1 -1
  5. package/lib/nodes/document/Document.d.ts.map +1 -1
  6. package/lib/nodes/document/Document.js +6 -6
  7. package/lib/nodes/document/Document.js.map +1 -1
  8. package/lib/nodes/document-fragment/DocumentFragment.d.ts +1 -1
  9. package/lib/nodes/document-fragment/DocumentFragment.d.ts.map +1 -1
  10. package/lib/nodes/document-fragment/DocumentFragment.js +6 -6
  11. package/lib/nodes/document-fragment/DocumentFragment.js.map +1 -1
  12. package/lib/nodes/element/Element.js +6 -6
  13. package/lib/nodes/element/Element.js.map +1 -1
  14. package/lib/nodes/element/ElementUtility.d.ts +20 -9
  15. package/lib/nodes/element/ElementUtility.d.ts.map +1 -1
  16. package/lib/nodes/element/ElementUtility.js +54 -22
  17. package/lib/nodes/element/ElementUtility.js.map +1 -1
  18. package/lib/nodes/html-select-element/HTMLOptionsCollection.js.map +1 -1
  19. package/lib/nodes/node/Node.d.ts +1 -1
  20. package/lib/nodes/node/Node.d.ts.map +1 -1
  21. package/lib/nodes/node/Node.js +4 -111
  22. package/lib/nodes/node/Node.js.map +1 -1
  23. package/lib/nodes/node/NodeUtility.d.ts +37 -12
  24. package/lib/nodes/node/NodeUtility.d.ts.map +1 -1
  25. package/lib/nodes/node/NodeUtility.js +174 -30
  26. package/lib/nodes/node/NodeUtility.js.map +1 -1
  27. package/package.json +1 -1
  28. package/src/event/EventTarget.ts +9 -1
  29. package/src/nodes/document/Document.ts +9 -9
  30. package/src/nodes/document-fragment/DocumentFragment.ts +9 -9
  31. package/src/nodes/element/Element.ts +6 -6
  32. package/src/nodes/element/ElementUtility.ts +77 -27
  33. package/src/nodes/html-select-element/HTMLOptionsCollection.ts +1 -1
  34. package/src/nodes/node/Node.ts +5 -142
  35. package/src/nodes/node/NodeUtility.ts +239 -37
@@ -4,50 +4,172 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const NodeTypeEnum_1 = __importDefault(require("./NodeTypeEnum"));
7
+ const DOMException_1 = __importDefault(require("../../exception/DOMException"));
8
+ const DOMExceptionNameEnum_1 = __importDefault(require("../../exception/DOMExceptionNameEnum"));
9
+ const Node_1 = __importDefault(require("./Node"));
10
+ const MutationRecord_1 = __importDefault(require("../../mutation-observer/MutationRecord"));
11
+ const MutationTypeEnum_1 = __importDefault(require("../../mutation-observer/MutationTypeEnum"));
7
12
  /**
8
13
  * Node utility.
9
14
  */
10
15
  class NodeUtility {
11
16
  /**
12
- * Returns whether the passed node is a text node, and narrows its type.
17
+ * Append a child node to childNodes.
13
18
  *
14
- * @param node The node to be tested.
15
- * @returns "true" if the node is a text node.
19
+ * @param ancestorNode Ancestor node.
20
+ * @param node Node to append.
21
+ * @param [options] Options.
22
+ * @param [options.disableAncestorValidation] Disables validation for checking if the node is an ancestor of the ancestorNode.
23
+ * @returns Appended node.
16
24
  */
17
- static isTextNode(node) {
18
- return node?.nodeType === NodeTypeEnum_1.default.textNode;
25
+ static appendChild(ancestorNode, node, options) {
26
+ if (node === ancestorNode) {
27
+ throw new DOMException_1.default("Failed to execute 'appendChild' on 'Node': Not possible to append a node as a child of itself.");
28
+ }
29
+ if (!options?.disableAncestorValidation && this.isInclusiveAncestor(node, ancestorNode, true)) {
30
+ throw new DOMException_1.default("Failed to execute 'appendChild' on 'Node': The new node is a parent of the node to insert to.", DOMExceptionNameEnum_1.default.domException);
31
+ }
32
+ // If the type is DocumentFragment, then the child nodes of if it should be moved instead of the actual node.
33
+ // See: https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment
34
+ if (node.nodeType === NodeTypeEnum_1.default.documentFragmentNode) {
35
+ for (const child of node.childNodes.slice()) {
36
+ ancestorNode.appendChild(child);
37
+ }
38
+ return node;
39
+ }
40
+ // Remove the node from its previous parent if it has any.
41
+ if (node.parentNode) {
42
+ const index = node.parentNode.childNodes.indexOf(node);
43
+ if (index !== -1) {
44
+ node.parentNode.childNodes.splice(index, 1);
45
+ }
46
+ }
47
+ if (ancestorNode.isConnected) {
48
+ (ancestorNode.ownerDocument || this)['_cacheID']++;
49
+ }
50
+ ancestorNode.childNodes.push(node);
51
+ node._connectToNode(ancestorNode);
52
+ // MutationObserver
53
+ if (ancestorNode._observers.length > 0) {
54
+ const record = new MutationRecord_1.default();
55
+ record.target = ancestorNode;
56
+ record.type = MutationTypeEnum_1.default.childList;
57
+ record.addedNodes = [node];
58
+ for (const observer of ancestorNode._observers) {
59
+ if (observer.options.subtree) {
60
+ node._observe(observer);
61
+ }
62
+ if (observer.options.childList) {
63
+ observer.callback([record]);
64
+ }
65
+ }
66
+ }
67
+ return node;
19
68
  }
20
69
  /**
21
- * Returns "true" if this node contains the other node.
70
+ * Remove Child element from childNodes array.
22
71
  *
23
- * @param rootNode Root node.
24
- * @param otherNode Node to test with.
25
- * @param [includeShadowRoots = false] Include shadow roots.
26
- * @returns "true" if this node contains the other node.
72
+ * @param ancestorNode Ancestor node.
73
+ * @param node Node to remove.
74
+ * @returns Removed node.
27
75
  */
28
- static contains(rootNode, otherNode, includeShadowRoots = false) {
29
- if (otherNode === null) {
30
- return false;
76
+ static removeChild(ancestorNode, node) {
77
+ const index = ancestorNode.childNodes.indexOf(node);
78
+ if (index === -1) {
79
+ throw new DOMException_1.default('Failed to remove node. Node is not child of parent.');
31
80
  }
32
- if (rootNode === otherNode) {
33
- return true;
81
+ if (ancestorNode.isConnected) {
82
+ (ancestorNode.ownerDocument || this)['_cacheID']++;
34
83
  }
35
- if (includeShadowRoots && rootNode === otherNode.ownerDocument && otherNode.isConnected) {
36
- return true;
84
+ ancestorNode.childNodes.splice(index, 1);
85
+ node._connectToNode(null);
86
+ // MutationObserver
87
+ if (ancestorNode._observers.length > 0) {
88
+ const record = new MutationRecord_1.default();
89
+ record.target = ancestorNode;
90
+ record.type = MutationTypeEnum_1.default.childList;
91
+ record.removedNodes = [node];
92
+ for (const observer of ancestorNode._observers) {
93
+ node._unobserve(observer);
94
+ if (observer.options.childList) {
95
+ observer.callback([record]);
96
+ }
97
+ }
37
98
  }
38
- for (const childNode of rootNode.childNodes) {
39
- if (childNode === otherNode ||
40
- this.contains(childNode, otherNode, includeShadowRoots) ||
41
- (includeShadowRoots &&
42
- childNode.shadowRoot &&
43
- childNode.shadowRoot.contains(otherNode))) {
44
- return true;
99
+ return node;
100
+ }
101
+ /**
102
+ * Inserts a node before another.
103
+ *
104
+ * @param ancestorNode Ancestor node.
105
+ * @param newNode Node to insert.
106
+ * @param referenceNode Node to insert before.
107
+ * @param [options] Options.
108
+ * @param [options.disableAncestorValidation] Disables validation for checking if the node is an ancestor of the ancestorNode.
109
+ * @returns Inserted node.
110
+ */
111
+ static insertBefore(ancestorNode, newNode, referenceNode, options) {
112
+ if (!options?.disableAncestorValidation &&
113
+ this.isInclusiveAncestor(newNode, ancestorNode, true)) {
114
+ throw new DOMException_1.default("Failed to execute 'insertBefore' on 'Node': The new node is a parent of the node to insert to.", DOMExceptionNameEnum_1.default.domException);
115
+ }
116
+ // If the type is DocumentFragment, then the child nodes of if it should be moved instead of the actual node.
117
+ // See: https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment
118
+ if (newNode.nodeType === Node_1.default.DOCUMENT_FRAGMENT_NODE) {
119
+ for (const child of newNode.childNodes.slice()) {
120
+ ancestorNode.insertBefore(child, referenceNode);
45
121
  }
122
+ return newNode;
46
123
  }
47
- return false;
124
+ if (referenceNode === null) {
125
+ ancestorNode.appendChild(newNode);
126
+ return newNode;
127
+ }
128
+ if (!referenceNode) {
129
+ throw new DOMException_1.default("Failed to execute 'insertBefore' on 'Node': 2 arguments required, but only 1 present.", 'TypeError');
130
+ }
131
+ if (ancestorNode.childNodes.indexOf(referenceNode) === -1) {
132
+ throw new DOMException_1.default("Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node.");
133
+ }
134
+ if (ancestorNode.isConnected) {
135
+ (ancestorNode.ownerDocument || this)['_cacheID']++;
136
+ }
137
+ if (newNode.parentNode) {
138
+ const index = newNode.parentNode.childNodes.indexOf(newNode);
139
+ if (index !== -1) {
140
+ newNode.parentNode.childNodes.splice(index, 1);
141
+ }
142
+ }
143
+ ancestorNode.childNodes.splice(ancestorNode.childNodes.indexOf(referenceNode), 0, newNode);
144
+ newNode._connectToNode(ancestorNode);
145
+ // MutationObserver
146
+ if (ancestorNode._observers.length > 0) {
147
+ const record = new MutationRecord_1.default();
148
+ record.target = ancestorNode;
149
+ record.type = MutationTypeEnum_1.default.childList;
150
+ record.addedNodes = [newNode];
151
+ for (const observer of ancestorNode._observers) {
152
+ if (observer.options.subtree) {
153
+ newNode._observe(observer);
154
+ }
155
+ if (observer.options.childList) {
156
+ observer.callback([record]);
157
+ }
158
+ }
159
+ }
160
+ return newNode;
48
161
  }
49
162
  /**
50
- * Returns boolean indicating if nodeB is an inclusive ancestor of nodeA.
163
+ * Returns whether the passed node is a text node, and narrows its type.
164
+ *
165
+ * @param node The node to be tested.
166
+ * @returns "true" if the node is a text node.
167
+ */
168
+ static isTextNode(node) {
169
+ return node?.nodeType === NodeTypeEnum_1.default.textNode;
170
+ }
171
+ /**
172
+ * Returns boolean indicating if "ancestorNode" is an inclusive ancestor of "referenceNode".
51
173
  *
52
174
  * Based on:
53
175
  * https://github.com/jsdom/jsdom/blob/master/lib/jsdom/living/helpers/node.js
@@ -55,15 +177,37 @@ class NodeUtility {
55
177
  * @see https://dom.spec.whatwg.org/#concept-tree-inclusive-ancestor
56
178
  * @param ancestorNode Ancestor node.
57
179
  * @param referenceNode Reference node.
58
- * @returns "true" if following.
180
+ * @param [includeShadowRoots = false] Include shadow roots.
181
+ * @returns "true" if inclusive ancestor.
59
182
  */
60
- static isInclusiveAncestor(ancestorNode, referenceNode) {
61
- let parent = referenceNode;
183
+ static isInclusiveAncestor(ancestorNode, referenceNode, includeShadowRoots = false) {
184
+ if (ancestorNode === null || referenceNode === null) {
185
+ return false;
186
+ }
187
+ if (ancestorNode === referenceNode) {
188
+ return true;
189
+ }
190
+ if (!ancestorNode.childNodes.length) {
191
+ return false;
192
+ }
193
+ if (includeShadowRoots && referenceNode.isConnected !== ancestorNode.isConnected) {
194
+ return false;
195
+ }
196
+ if (includeShadowRoots &&
197
+ ancestorNode === referenceNode.ownerDocument &&
198
+ referenceNode.isConnected) {
199
+ return true;
200
+ }
201
+ let parent = referenceNode.parentNode;
62
202
  while (parent) {
63
203
  if (ancestorNode === parent) {
64
204
  return true;
65
205
  }
66
- parent = parent.parentNode;
206
+ parent = parent.parentNode
207
+ ? parent.parentNode
208
+ : includeShadowRoots && parent.host
209
+ ? parent.host
210
+ : null;
67
211
  }
68
212
  return false;
69
213
  }
@@ -1 +1 @@
1
- {"version":3,"file":"NodeUtility.js","sourceRoot":"","sources":["../../../src/nodes/node/NodeUtility.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"NodeUtility.js","sourceRoot":"","sources":["../../../src/nodes/node/NodeUtility.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "happy-dom",
3
- "version": "9.8.2",
3
+ "version": "9.8.4",
4
4
  "license": "MIT",
5
5
  "homepage": "https://github.com/capricorn86/happy-dom",
6
6
  "repository": "https://github.com/capricorn86/happy-dom",
@@ -35,7 +35,9 @@ export default abstract class EventTarget implements IEventTarget {
35
35
 
36
36
  this._listeners[type] = this._listeners[type] || [];
37
37
  this._listenerOptions[type] = this._listenerOptions[type] || [];
38
-
38
+ if (this._listeners[type].includes(listener)) {
39
+ return;
40
+ }
39
41
  this._listeners[type].push(listener);
40
42
  this._listenerOptions[type].push(listenerOptions);
41
43
 
@@ -168,7 +170,13 @@ export default abstract class EventTarget implements IEventTarget {
168
170
  event._isInPassiveEventListener = false;
169
171
 
170
172
  if (options?.once) {
173
+ // At this time, listeners and listenersOptions are cloned arrays. When the original value is deleted,
174
+ // The value corresponding to the cloned array is not deleted. So we need to delete the value in the cloned array.
175
+ listeners.splice(i, 1);
176
+ listenerOptions.splice(i, 1);
171
177
  this.removeEventListener(event.type, listener);
178
+ i--;
179
+ max--;
172
180
  }
173
181
 
174
182
  if (event._immediatePropagationStopped) {
@@ -620,25 +620,25 @@ export default class Document extends Node implements IDocument {
620
620
  /**
621
621
  * @override
622
622
  */
623
- public appendChild(node: INode): INode {
624
- ElementUtility.appendChild(this, node);
625
- return super.appendChild(node);
623
+ public override appendChild(node: INode): INode {
624
+ // We do not call super here as this will be handled by ElementUtility to improve performance by avoiding validation and other checks.
625
+ return ElementUtility.appendChild(this, node);
626
626
  }
627
627
 
628
628
  /**
629
629
  * @override
630
630
  */
631
- public removeChild(node: INode): INode {
632
- ElementUtility.removeChild(this, node);
633
- return super.removeChild(node);
631
+ public override removeChild(node: INode): INode {
632
+ // We do not call super here as this will be handled by ElementUtility to improve performance by avoiding validation and other checks.
633
+ return ElementUtility.removeChild(this, node);
634
634
  }
635
635
 
636
636
  /**
637
637
  * @override
638
638
  */
639
- public insertBefore(newNode: INode, referenceNode?: INode): INode {
640
- ElementUtility.insertBefore(this, newNode, referenceNode);
641
- return super.insertBefore(newNode, referenceNode);
639
+ public override insertBefore(newNode: INode, referenceNode: INode | null): INode {
640
+ // We do not call super here as this will be handled by ElementUtility to improve performance by avoiding validation and other checks.
641
+ return ElementUtility.insertBefore(this, newNode, referenceNode);
642
642
  }
643
643
 
644
644
  /**
@@ -154,24 +154,24 @@ export default class DocumentFragment extends Node implements IDocumentFragment
154
154
  /**
155
155
  * @override
156
156
  */
157
- public appendChild(node: INode): INode {
158
- ElementUtility.appendChild(this, node);
159
- return super.appendChild(<INode>node);
157
+ public override appendChild(node: INode): INode {
158
+ // We do not call super here as this will be handled by ElementUtility to improve performance by avoiding validation and other checks.
159
+ return ElementUtility.appendChild(this, node);
160
160
  }
161
161
 
162
162
  /**
163
163
  * @override
164
164
  */
165
- public removeChild(node: INode): INode {
166
- ElementUtility.removeChild(this, node);
167
- return super.removeChild(<Node>node);
165
+ public override removeChild(node: INode): INode {
166
+ // We do not call super here as this will be handled by ElementUtility to improve performance by avoiding validation and other checks.
167
+ return ElementUtility.removeChild(this, node);
168
168
  }
169
169
 
170
170
  /**
171
171
  * @override
172
172
  */
173
- public insertBefore(newNode: INode, referenceNode?: INode): INode {
174
- ElementUtility.insertBefore(this, newNode, referenceNode);
175
- return super.insertBefore(newNode, referenceNode);
173
+ public override insertBefore(newNode: INode, referenceNode: INode | null): INode {
174
+ // We do not call super here as this will be handled by ElementUtility to improve performance by avoiding validation and other checks.
175
+ return ElementUtility.insertBefore(this, newNode, referenceNode);
176
176
  }
177
177
  }
@@ -370,24 +370,24 @@ export default class Element extends Node implements IElement {
370
370
  * @override
371
371
  */
372
372
  public override appendChild(node: INode): INode {
373
- ElementUtility.appendChild(this, node);
374
- return super.appendChild(node);
373
+ // We do not call super here as this will be handled by ElementUtility to improve performance by avoiding validation and other checks.
374
+ return ElementUtility.appendChild(this, node);
375
375
  }
376
376
 
377
377
  /**
378
378
  * @override
379
379
  */
380
380
  public override removeChild(node: INode): INode {
381
- ElementUtility.removeChild(this, node);
382
- return super.removeChild(node);
381
+ // We do not call super here as this will be handled by ElementUtility to improve performance by avoiding validation and other checks.
382
+ return ElementUtility.removeChild(this, node);
383
383
  }
384
384
 
385
385
  /**
386
386
  * @override
387
387
  */
388
388
  public override insertBefore(newNode: INode, referenceNode: INode | null): INode {
389
- ElementUtility.insertBefore(this, newNode, referenceNode);
390
- return super.insertBefore(newNode, referenceNode);
389
+ // We do not call super here as this will be handled by ElementUtility to improve performance by avoiding validation and other checks.
390
+ return ElementUtility.insertBefore(this, newNode, referenceNode);
391
391
  }
392
392
 
393
393
  /**
@@ -6,6 +6,9 @@ import IDocument from '../document/IDocument';
6
6
  import IDocumentFragment from '../document-fragment/IDocumentFragment';
7
7
  import IHTMLElement from '../html-element/IHTMLElement';
8
8
  import Element from './Element';
9
+ import NodeUtility from '../node/NodeUtility';
10
+ import DOMException from '../../exception/DOMException';
11
+ import DOMExceptionNameEnum from '../../exception/DOMExceptionNameEnum';
9
12
 
10
13
  const NAMED_ITEM_ATTRIBUTES = ['id', 'name'];
11
14
 
@@ -16,14 +19,28 @@ export default class ElementUtility {
16
19
  /**
17
20
  * Handles appending a child element to the "children" property.
18
21
  *
19
- * @param parentElement Parent element.
20
- * @param node Node.
22
+ * @param ancestorNode Ancestor node.
23
+ * @param node Node to append.
24
+ * @param [options] Options.
25
+ * @param [options.disableAncestorValidation] Disables validation for checking if the node is an ancestor of the ancestorNode.
26
+ * @returns Appended node.
21
27
  */
22
28
  public static appendChild(
23
- parentElement: IElement | IDocument | IDocumentFragment,
24
- node: INode
25
- ): void {
26
- if (node.nodeType === NodeTypeEnum.elementNode && node !== parentElement) {
29
+ ancestorNode: IElement | IDocument | IDocumentFragment,
30
+ node: INode,
31
+ options?: { disableAncestorValidation?: boolean }
32
+ ): INode {
33
+ if (node.nodeType === NodeTypeEnum.elementNode && node !== ancestorNode) {
34
+ if (
35
+ !options?.disableAncestorValidation &&
36
+ NodeUtility.isInclusiveAncestor(node, ancestorNode)
37
+ ) {
38
+ throw new DOMException(
39
+ "Failed to execute 'appendChild' on 'Node': The new node is a parent of the node to insert to.",
40
+ DOMExceptionNameEnum.domException
41
+ );
42
+ }
43
+
27
44
  if (node.parentNode && (<IHTMLElement>node.parentNode).children) {
28
45
  const index = (<IHTMLElement>node.parentNode).children.indexOf(<IHTMLElement>node);
29
46
  if (index !== -1) {
@@ -41,57 +58,82 @@ export default class ElementUtility {
41
58
 
42
59
  for (const attribute of NAMED_ITEM_ATTRIBUTES) {
43
60
  if ((<Element>node)._attributes[attribute]) {
44
- (<HTMLCollection<IHTMLElement>>parentElement.children)._appendNamedItem(
61
+ (<HTMLCollection<IHTMLElement>>ancestorNode.children)._appendNamedItem(
45
62
  <IHTMLElement>node,
46
63
  (<Element>node)._attributes[attribute].value
47
64
  );
48
65
  }
49
66
  }
50
67
 
51
- parentElement.children.push(<IElement>node);
68
+ ancestorNode.children.push(<IElement>node);
69
+
70
+ NodeUtility.appendChild(ancestorNode, node, { disableAncestorValidation: true });
71
+ } else {
72
+ NodeUtility.appendChild(ancestorNode, node, options);
52
73
  }
74
+
75
+ return node;
53
76
  }
54
77
 
55
78
  /**
56
79
  * Handles removing a child element from the "children" property.
57
80
  *
58
- * @param parentElement Parent element.
81
+ * @param ancestorNode Ancestor node.
59
82
  * @param node Node.
83
+ * @returns Removed node.
60
84
  */
61
85
  public static removeChild(
62
- parentElement: IElement | IDocument | IDocumentFragment,
86
+ ancestorNode: IElement | IDocument | IDocumentFragment,
63
87
  node: INode
64
- ): void {
88
+ ): INode {
65
89
  if (node.nodeType === NodeTypeEnum.elementNode) {
66
- const index = parentElement.children.indexOf(<IElement>node);
90
+ const index = ancestorNode.children.indexOf(<IElement>node);
67
91
  if (index !== -1) {
68
92
  for (const attribute of NAMED_ITEM_ATTRIBUTES) {
69
93
  if ((<Element>node)._attributes[attribute]) {
70
- (<HTMLCollection<IHTMLElement>>parentElement.children)._removeNamedItem(
94
+ (<HTMLCollection<IHTMLElement>>ancestorNode.children)._removeNamedItem(
71
95
  <IHTMLElement>node,
72
96
  (<Element>node)._attributes[attribute].value
73
97
  );
74
98
  }
75
99
  }
76
- parentElement.children.splice(index, 1);
100
+ ancestorNode.children.splice(index, 1);
77
101
  }
78
102
  }
103
+
104
+ NodeUtility.removeChild(ancestorNode, node);
105
+
106
+ return node;
79
107
  }
80
108
 
81
109
  /**
82
110
  *
83
111
  * Handles inserting a child element to the "children" property.
84
112
  *
85
- * @param parentElement Parent element.
86
- * @param newNode
87
- * @param referenceNode
113
+ * @param ancestorNode Ancestor node.
114
+ * @param newNode Node to insert.
115
+ * @param referenceNode Node to insert before.
116
+ * @param [options] Options.
117
+ * @param [options.disableAncestorValidation] Disables validation for checking if the node is an ancestor of the ancestorNode.
118
+ * @returns Inserted node.
88
119
  */
89
120
  public static insertBefore(
90
- parentElement: IElement | IDocument | IDocumentFragment,
121
+ ancestorNode: IElement | IDocument | IDocumentFragment,
91
122
  newNode: INode,
92
- referenceNode: INode | null
93
- ): void {
123
+ referenceNode: INode | null,
124
+ options?: { disableAncestorValidation?: boolean }
125
+ ): INode {
94
126
  if (newNode.nodeType === NodeTypeEnum.elementNode) {
127
+ if (
128
+ !options?.disableAncestorValidation &&
129
+ NodeUtility.isInclusiveAncestor(newNode, ancestorNode)
130
+ ) {
131
+ throw new DOMException(
132
+ "Failed to execute 'insertBefore' on 'Node': The new node is a parent of the node to insert to.",
133
+ DOMExceptionNameEnum.domException
134
+ );
135
+ }
136
+
95
137
  if (newNode.parentNode && (<IHTMLElement>newNode.parentNode).children) {
96
138
  const index = (<IHTMLElement>newNode.parentNode).children.indexOf(<IHTMLElement>newNode);
97
139
  if (index !== -1) {
@@ -114,19 +156,19 @@ export default class ElementUtility {
114
156
 
115
157
  if (referenceNode) {
116
158
  if (referenceNode.nodeType === NodeTypeEnum.elementNode) {
117
- const index = parentElement.children.indexOf(<IElement>referenceNode);
159
+ const index = ancestorNode.children.indexOf(<IElement>referenceNode);
118
160
  if (index !== -1) {
119
- parentElement.children.splice(index, 0, <IElement>newNode);
161
+ ancestorNode.children.splice(index, 0, <IElement>newNode);
120
162
  }
121
163
  } else {
122
- parentElement.children.length = 0;
164
+ ancestorNode.children.length = 0;
123
165
 
124
- for (const node of parentElement.childNodes) {
166
+ for (const node of ancestorNode.childNodes) {
125
167
  if (node === referenceNode) {
126
- parentElement.children.push(<IElement>newNode);
168
+ ancestorNode.children.push(<IElement>newNode);
127
169
  }
128
170
  if (node.nodeType === NodeTypeEnum.elementNode) {
129
- parentElement.children.push(<IElement>node);
171
+ ancestorNode.children.push(<IElement>node);
130
172
  }
131
173
  }
132
174
  }
@@ -135,13 +177,21 @@ export default class ElementUtility {
135
177
  if (referenceNode || referenceNode === null) {
136
178
  for (const attribute of NAMED_ITEM_ATTRIBUTES) {
137
179
  if ((<Element>newNode)._attributes[attribute]) {
138
- (<HTMLCollection<IHTMLElement>>parentElement.children)._appendNamedItem(
180
+ (<HTMLCollection<IHTMLElement>>ancestorNode.children)._appendNamedItem(
139
181
  <IHTMLElement>newNode,
140
182
  (<Element>newNode)._attributes[attribute].value
141
183
  );
142
184
  }
143
185
  }
144
186
  }
187
+
188
+ NodeUtility.insertBefore(ancestorNode, newNode, referenceNode, {
189
+ disableAncestorValidation: true
190
+ });
191
+ } else {
192
+ NodeUtility.insertBefore(ancestorNode, newNode, referenceNode, options);
145
193
  }
194
+
195
+ return newNode;
146
196
  }
147
197
  }
@@ -65,7 +65,7 @@ export default class HTMLOptionsCollection
65
65
  }
66
66
 
67
67
  if (!Number.isNaN(Number(before))) {
68
- if (before < 0) {
68
+ if (<number>before < 0) {
69
69
  return;
70
70
  }
71
71