happy-dom 9.9.1 → 9.10.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.

Potentially problematic release.


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

Files changed (59) hide show
  1. package/lib/css/declaration/utilities/CSSStyleDeclarationElementStyle.js +1 -1
  2. package/lib/css/declaration/utilities/CSSStyleDeclarationElementStyle.js.map +1 -1
  3. package/lib/nodes/document/Document.d.ts.map +1 -1
  4. package/lib/nodes/document/Document.js +3 -0
  5. package/lib/nodes/document/Document.js.map +1 -1
  6. package/lib/nodes/document-fragment/DocumentFragment.d.ts.map +1 -1
  7. package/lib/nodes/document-fragment/DocumentFragment.js +3 -0
  8. package/lib/nodes/document-fragment/DocumentFragment.js.map +1 -1
  9. package/lib/nodes/element/Element.d.ts.map +1 -1
  10. package/lib/nodes/element/Element.js +5 -15
  11. package/lib/nodes/element/Element.js.map +1 -1
  12. package/lib/nodes/element/ElementUtility.d.ts.map +1 -1
  13. package/lib/nodes/element/ElementUtility.js +18 -22
  14. package/lib/nodes/element/ElementUtility.js.map +1 -1
  15. package/lib/nodes/node/Node.d.ts +0 -8
  16. package/lib/nodes/node/Node.d.ts.map +1 -1
  17. package/lib/nodes/node/Node.js +4 -23
  18. package/lib/nodes/node/Node.js.map +1 -1
  19. package/lib/nodes/node/NodeUtility.d.ts.map +1 -1
  20. package/lib/nodes/node/NodeUtility.js +3 -4
  21. package/lib/nodes/node/NodeUtility.js.map +1 -1
  22. package/lib/query-selector/ISelectorAttribute.d.ts +6 -0
  23. package/lib/query-selector/ISelectorAttribute.d.ts.map +1 -0
  24. package/lib/query-selector/ISelectorAttribute.js +3 -0
  25. package/lib/query-selector/ISelectorAttribute.js.map +1 -0
  26. package/lib/query-selector/ISelectorMatch.d.ts +4 -0
  27. package/lib/query-selector/ISelectorMatch.d.ts.map +1 -0
  28. package/lib/query-selector/ISelectorMatch.js +3 -0
  29. package/lib/query-selector/ISelectorMatch.js.map +1 -0
  30. package/lib/query-selector/QuerySelector.d.ts +21 -31
  31. package/lib/query-selector/QuerySelector.d.ts.map +1 -1
  32. package/lib/query-selector/QuerySelector.js +123 -131
  33. package/lib/query-selector/QuerySelector.js.map +1 -1
  34. package/lib/query-selector/SelectorCombinatorEnum.d.ts +7 -0
  35. package/lib/query-selector/SelectorCombinatorEnum.d.ts.map +1 -0
  36. package/lib/query-selector/SelectorCombinatorEnum.js +10 -0
  37. package/lib/query-selector/SelectorCombinatorEnum.js.map +1 -0
  38. package/lib/query-selector/SelectorItem.d.ts +41 -56
  39. package/lib/query-selector/SelectorItem.d.ts.map +1 -1
  40. package/lib/query-selector/SelectorItem.js +194 -220
  41. package/lib/query-selector/SelectorItem.js.map +1 -1
  42. package/lib/query-selector/SelectorParser.d.ts +21 -0
  43. package/lib/query-selector/SelectorParser.d.ts.map +1 -0
  44. package/lib/query-selector/SelectorParser.js +154 -0
  45. package/lib/query-selector/SelectorParser.js.map +1 -0
  46. package/package.json +1 -1
  47. package/src/css/declaration/utilities/CSSStyleDeclarationElementStyle.ts +2 -2
  48. package/src/nodes/document/Document.ts +6 -0
  49. package/src/nodes/document-fragment/DocumentFragment.ts +6 -0
  50. package/src/nodes/element/Element.ts +9 -17
  51. package/src/nodes/element/ElementUtility.ts +20 -25
  52. package/src/nodes/node/Node.ts +6 -25
  53. package/src/nodes/node/NodeUtility.ts +3 -8
  54. package/src/query-selector/ISelectorAttribute.ts +5 -0
  55. package/src/query-selector/ISelectorMatch.ts +3 -0
  56. package/src/query-selector/QuerySelector.ts +187 -170
  57. package/src/query-selector/SelectorCombinatorEnum.ts +7 -0
  58. package/src/query-selector/SelectorItem.ts +238 -264
  59. package/src/query-selector/SelectorParser.ts +148 -0
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const SelectorItem_1 = __importDefault(require("./SelectorItem"));
7
+ const SelectorCombinatorEnum_1 = __importDefault(require("./SelectorCombinatorEnum"));
8
+ const DOMException_1 = __importDefault(require("../exception/DOMException"));
9
+ /**
10
+ * Selector RegExp.
11
+ *
12
+ * Group 1: All (e.g. "*")
13
+ * Group 2: Tag name (e.g. "div")
14
+ * Group 3: ID (e.g. "#id")
15
+ * Group 4: Class (e.g. ".class")
16
+ * Group 5: Attribute name when no value (e.g. "attr1")
17
+ * Group 6: Attribute name when there is a value (e.g. "attr1")
18
+ * Group 7: Attribute operator (e.g. "~")
19
+ * Group 8: Attribute value (e.g. "value1")
20
+ * Group 9: Pseudo (e.g. "nth-child")
21
+ * Group 10: Arguments of pseudo (e.g. "2n + 1")
22
+ * Group 11: Combinator.
23
+ */
24
+ const SELECTOR_REGEXP = /(\*)|([a-zA-Z0-9-]+)|#([a-zA-Z0-9-_]+)|\.((?:[a-zA-Z0-9-_]|\\.)+)|\[([a-zA-Z0-9-_]+)\]|\[([a-zA-Z0-9-_]+)([~|^$*]{0,1}) *= *["']{0,1}([^"']+)["']{0,1}\]|:([a-zA-Z-:]+)|\(([^)]+)\)|([ ,+>]*)/g;
25
+ /**
26
+ * Escaped Character RegExp.
27
+ */
28
+ const CLASS_ESCAPED_CHARACTER_REGEXP = /\\/g;
29
+ /**
30
+ * Simple Selector RegExp.
31
+ *
32
+ * Group 1: Tag name (e.g. "div")
33
+ * Group 2: Class (e.g. ".classA.classB")
34
+ * Group 3: ID (e.g. "#id")
35
+ */
36
+ const SIMPLE_SELECTOR_REGEXP = /(^[a-zA-Z0-9-]+$)|(^\.[a-zA-Z0-9-_.]+$)|(^#[a-zA-Z0-9-_]+$)/;
37
+ /**
38
+ * Utility for parsing a selection string.
39
+ */
40
+ class SelectorParser {
41
+ /**
42
+ * Parses a selector string and returns an instance of SelectorItem.
43
+ *
44
+ * @param selector Selector.
45
+ * @returns Selector itme.
46
+ */
47
+ static getSelectorItem(selector) {
48
+ return this.getSelectorGroups(selector)[0][0];
49
+ }
50
+ /**
51
+ * Parses a selector string and returns groups with SelectorItem instances.
52
+ *
53
+ * @param selector Selector.
54
+ * @returns Selector groups.
55
+ */
56
+ static getSelectorGroups(selector) {
57
+ const simpleMatch = selector.match(SIMPLE_SELECTOR_REGEXP);
58
+ if (simpleMatch) {
59
+ if (simpleMatch[1]) {
60
+ return [[new SelectorItem_1.default({ tagName: selector.toUpperCase() })]];
61
+ }
62
+ else if (simpleMatch[2]) {
63
+ return [[new SelectorItem_1.default({ classNames: selector.replace('.', '').split('.') })]];
64
+ }
65
+ else if (simpleMatch[3]) {
66
+ return [[new SelectorItem_1.default({ id: selector.replace('#', '') })]];
67
+ }
68
+ }
69
+ const regexp = new RegExp(SELECTOR_REGEXP);
70
+ let currentSelectorItem = new SelectorItem_1.default({
71
+ combinator: SelectorCombinatorEnum_1.default.descendant
72
+ });
73
+ let currentGroup = [currentSelectorItem];
74
+ const groups = [currentGroup];
75
+ let isValid = false;
76
+ let match;
77
+ while ((match = regexp.exec(selector))) {
78
+ if (match[0]) {
79
+ isValid = true;
80
+ if (match[1]) {
81
+ currentSelectorItem.all = '*';
82
+ }
83
+ else if (match[2]) {
84
+ currentSelectorItem.tagName = match[2].toUpperCase();
85
+ }
86
+ else if (match[3]) {
87
+ currentSelectorItem.id = match[3];
88
+ }
89
+ else if (match[4]) {
90
+ currentSelectorItem.classNames = currentSelectorItem.classNames || [];
91
+ currentSelectorItem.classNames.push(match[4].replace(CLASS_ESCAPED_CHARACTER_REGEXP, ''));
92
+ }
93
+ else if (match[5]) {
94
+ currentSelectorItem.attributes = currentSelectorItem.attributes || [];
95
+ currentSelectorItem.attributes.push({
96
+ name: match[5].toLowerCase(),
97
+ operator: null,
98
+ value: null
99
+ });
100
+ }
101
+ else if (match[6] && match[8]) {
102
+ currentSelectorItem.attributes = currentSelectorItem.attributes || [];
103
+ currentSelectorItem.attributes.push({
104
+ name: match[6].toLowerCase(),
105
+ operator: match[7] || null,
106
+ value: match[8]
107
+ });
108
+ }
109
+ else if (match[9]) {
110
+ currentSelectorItem.pseudoClass = match[9].toLowerCase();
111
+ }
112
+ else if (match[10]) {
113
+ currentSelectorItem.pseudoArguments = match[10];
114
+ }
115
+ else if (match[11]) {
116
+ switch (match[11].trim()) {
117
+ case ',':
118
+ currentSelectorItem = new SelectorItem_1.default({
119
+ combinator: SelectorCombinatorEnum_1.default.descendant
120
+ });
121
+ currentGroup = [currentSelectorItem];
122
+ groups.push(currentGroup);
123
+ break;
124
+ case '>':
125
+ currentSelectorItem = new SelectorItem_1.default({ combinator: SelectorCombinatorEnum_1.default.child });
126
+ currentGroup.push(currentSelectorItem);
127
+ break;
128
+ case '+':
129
+ currentSelectorItem = new SelectorItem_1.default({
130
+ combinator: SelectorCombinatorEnum_1.default.adjacentSibling
131
+ });
132
+ currentGroup.push(currentSelectorItem);
133
+ break;
134
+ case '':
135
+ currentSelectorItem = new SelectorItem_1.default({
136
+ combinator: SelectorCombinatorEnum_1.default.descendant
137
+ });
138
+ currentGroup.push(currentSelectorItem);
139
+ break;
140
+ }
141
+ }
142
+ }
143
+ else {
144
+ break;
145
+ }
146
+ }
147
+ if (!isValid) {
148
+ throw new DOMException_1.default(`Invalid selector: "${selector}"`);
149
+ }
150
+ return groups;
151
+ }
152
+ }
153
+ exports.default = SelectorParser;
154
+ //# sourceMappingURL=SelectorParser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SelectorParser.js","sourceRoot":"","sources":["../../src/query-selector/SelectorParser.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.9.1",
3
+ "version": "9.10.0",
4
4
  "license": "MIT",
5
5
  "homepage": "https://github.com/capricorn86/happy-dom",
6
6
  "repository": "https://github.com/capricorn86/happy-dom",
@@ -289,8 +289,8 @@ export default class CSSStyleDeclarationElementStyle {
289
289
  }
290
290
  } else {
291
291
  for (const element of options.elements) {
292
- const matchResult = QuerySelector.match(element.element, selectorText);
293
- if (matchResult.matches) {
292
+ const matchResult = QuerySelector.match(<IElement>element.element, selectorText);
293
+ if (matchResult) {
294
294
  element.cssTexts.push({
295
295
  cssText: (<CSSStyleRule>rule)._cssText,
296
296
  priorityWeight: matchResult.priorityWeight
@@ -637,6 +637,12 @@ export default class Document extends Node implements IDocument {
637
637
  * @override
638
638
  */
639
639
  public override insertBefore(newNode: INode, referenceNode: INode | null): INode {
640
+ if (arguments.length < 2) {
641
+ throw new TypeError(
642
+ `Failed to execute 'insertBefore' on 'Node': 2 arguments required, but only ${arguments.length} present.`
643
+ );
644
+ }
645
+
640
646
  // We do not call super here as this will be handled by ElementUtility to improve performance by avoiding validation and other checks.
641
647
  return ElementUtility.insertBefore(this, newNode, referenceNode);
642
648
  }
@@ -171,6 +171,12 @@ export default class DocumentFragment extends Node implements IDocumentFragment
171
171
  * @override
172
172
  */
173
173
  public override insertBefore(newNode: INode, referenceNode: INode | null): INode {
174
+ if (arguments.length < 2) {
175
+ throw new TypeError(
176
+ `Failed to execute 'insertBefore' on 'Node': 2 arguments required, but only ${arguments.length} present.`
177
+ );
178
+ }
179
+
174
180
  // We do not call super here as this will be handled by ElementUtility to improve performance by avoiding validation and other checks.
175
181
  return ElementUtility.insertBefore(this, newNode, referenceNode);
176
182
  }
@@ -386,6 +386,12 @@ export default class Element extends Node implements IElement {
386
386
  * @override
387
387
  */
388
388
  public override insertBefore(newNode: INode, referenceNode: INode | null): INode {
389
+ if (arguments.length < 2) {
390
+ throw new TypeError(
391
+ `Failed to execute 'insertBefore' on 'Node': 2 arguments required, but only ${arguments.length} present.`
392
+ );
393
+ }
394
+
389
395
  // We do not call super here as this will be handled by ElementUtility to improve performance by avoiding validation and other checks.
390
396
  return ElementUtility.insertBefore(this, newNode, referenceNode);
391
397
  }
@@ -717,7 +723,7 @@ export default class Element extends Node implements IElement {
717
723
  * @returns "true" if matching.
718
724
  */
719
725
  public matches(selector: string): boolean {
720
- return QuerySelector.match(this, selector).matches;
726
+ return !!QuerySelector.match(this, selector);
721
727
  }
722
728
 
723
729
  /**
@@ -727,30 +733,16 @@ export default class Element extends Node implements IElement {
727
733
  * @returns Closest matching element.
728
734
  */
729
735
  public closest(selector: string): IElement {
730
- let rootElement: IElement = this.ownerDocument.documentElement;
731
- if (!this.isConnected) {
732
- rootElement = this;
733
- while (rootElement.parentNode) {
734
- rootElement = <IElement>rootElement.parentNode;
735
- }
736
- }
737
- const elements = rootElement.querySelectorAll(selector);
738
-
739
736
  // eslint-disable-next-line
740
737
  let parent: IElement = this;
738
+
741
739
  while (parent) {
742
- if (elements.includes(parent)) {
740
+ if (QuerySelector.match(parent, selector)) {
743
741
  return parent;
744
742
  }
745
743
  parent = parent.parentElement;
746
744
  }
747
745
 
748
- // QuerySelectorAll() will not match the element it is looking in when searched for
749
- // Therefore we need to check if it matches the root
750
- if (rootElement.matches(selector)) {
751
- return rootElement;
752
- }
753
-
754
746
  return null;
755
747
  }
756
748
 
@@ -123,7 +123,8 @@ export default class ElementUtility {
123
123
  referenceNode: INode | null,
124
124
  options?: { disableAncestorValidation?: boolean }
125
125
  ): INode {
126
- if (newNode.nodeType === NodeTypeEnum.elementNode) {
126
+ // NodeUtility.insertBefore() will call appendChild() for the scenario where "referenceNode" is "null" or "undefined"
127
+ if (newNode.nodeType === NodeTypeEnum.elementNode && referenceNode) {
127
128
  if (
128
129
  !options?.disableAncestorValidation &&
129
130
  NodeUtility.isInclusiveAncestor(newNode, ancestorNode)
@@ -152,36 +153,30 @@ export default class ElementUtility {
152
153
  }
153
154
  }
154
155
 
155
- // Node.ts will call appendChild() for the scenario where "referenceNode" is "null"
156
+ if (referenceNode.nodeType === NodeTypeEnum.elementNode) {
157
+ const index = ancestorNode.children.indexOf(<IElement>referenceNode);
158
+ if (index !== -1) {
159
+ ancestorNode.children.splice(index, 0, <IElement>newNode);
160
+ }
161
+ } else {
162
+ ancestorNode.children.length = 0;
156
163
 
157
- if (referenceNode) {
158
- if (referenceNode.nodeType === NodeTypeEnum.elementNode) {
159
- const index = ancestorNode.children.indexOf(<IElement>referenceNode);
160
- if (index !== -1) {
161
- ancestorNode.children.splice(index, 0, <IElement>newNode);
164
+ for (const node of ancestorNode.childNodes) {
165
+ if (node === referenceNode) {
166
+ ancestorNode.children.push(<IElement>newNode);
162
167
  }
163
- } else {
164
- ancestorNode.children.length = 0;
165
-
166
- for (const node of ancestorNode.childNodes) {
167
- if (node === referenceNode) {
168
- ancestorNode.children.push(<IElement>newNode);
169
- }
170
- if (node.nodeType === NodeTypeEnum.elementNode) {
171
- ancestorNode.children.push(<IElement>node);
172
- }
168
+ if (node.nodeType === NodeTypeEnum.elementNode) {
169
+ ancestorNode.children.push(<IElement>node);
173
170
  }
174
171
  }
175
172
  }
176
173
 
177
- if (referenceNode || referenceNode === null) {
178
- for (const attribute of NAMED_ITEM_ATTRIBUTES) {
179
- if ((<Element>newNode)._attributes[attribute]) {
180
- (<HTMLCollection<IHTMLElement>>ancestorNode.children)._appendNamedItem(
181
- <IHTMLElement>newNode,
182
- (<Element>newNode)._attributes[attribute].value
183
- );
184
- }
174
+ for (const attribute of NAMED_ITEM_ATTRIBUTES) {
175
+ if ((<Element>newNode)._attributes[attribute]) {
176
+ (<HTMLCollection<IHTMLElement>>ancestorNode.children)._appendNamedItem(
177
+ <IHTMLElement>newNode,
178
+ (<Element>newNode)._attributes[attribute].value
179
+ );
185
180
  }
186
181
  }
187
182
 
@@ -11,17 +11,6 @@ import IAttr from '../attr/IAttr';
11
11
  import NodeList from './NodeList';
12
12
  import INodeList from './INodeList';
13
13
 
14
- const JSON_CIRCULAR_PROPERTIES = [
15
- 'ownerDocument',
16
- 'parentNode',
17
- 'ownerElement',
18
- 'defaultView',
19
- '_rootNode',
20
- '_formNode',
21
- '_selectNode',
22
- '_textAreaNode'
23
- ];
24
-
25
14
  /**
26
15
  * Node.
27
16
  */
@@ -198,7 +187,7 @@ export default class Node extends EventTarget implements INode {
198
187
  */
199
188
  public get parentElement(): IElement {
200
189
  let parent = this.parentNode;
201
- while (parent && parent.nodeType !== Node.ELEMENT_NODE) {
190
+ while (parent && parent.nodeType !== NodeTypeEnum.elementNode) {
202
191
  parent = parent.parentNode;
203
192
  }
204
193
  return <IElement>parent;
@@ -322,6 +311,11 @@ export default class Node extends EventTarget implements INode {
322
311
  * @returns Inserted node.
323
312
  */
324
313
  public insertBefore(newNode: INode, referenceNode: INode | null): INode {
314
+ if (arguments.length < 2) {
315
+ throw new TypeError(
316
+ `Failed to execute 'insertBefore' on 'Node': 2 arguments required, but only ${arguments.length} present.`
317
+ );
318
+ }
325
319
  return NodeUtility.insertBefore(this, newNode, referenceNode);
326
320
  }
327
321
 
@@ -643,17 +637,4 @@ export default class Node extends EventTarget implements INode {
643
637
  child = child.nextSibling;
644
638
  }
645
639
  }
646
-
647
- /**
648
- * This will be called by JSON.stringify() when serializing this node.
649
- *
650
- * @returns Object without circular references.
651
- */
652
- public toJSON(): { [key: string]: unknown } {
653
- const result = {};
654
- for (const key of Object.keys(this)) {
655
- result[key] = !JSON_CIRCULAR_PROPERTIES.includes(key) ? this[key] : null;
656
- }
657
- return result;
658
- }
659
640
  }
@@ -164,18 +164,13 @@ export default class NodeUtility {
164
164
  return newNode;
165
165
  }
166
166
 
167
- if (referenceNode === null) {
167
+ // If the referenceNode is null or undefined, then the newNode should be appended to the ancestorNode.
168
+ // According to spec only null is valid, but browsers support undefined as well.
169
+ if (!referenceNode) {
168
170
  ancestorNode.appendChild(newNode);
169
171
  return newNode;
170
172
  }
171
173
 
172
- if (!referenceNode) {
173
- throw new DOMException(
174
- "Failed to execute 'insertBefore' on 'Node': 2 arguments required, but only 1 present.",
175
- 'TypeError'
176
- );
177
- }
178
-
179
174
  if (ancestorNode.childNodes.indexOf(referenceNode) === -1) {
180
175
  throw new DOMException(
181
176
  "Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node."
@@ -0,0 +1,5 @@
1
+ export default interface ISelectorAttribute {
2
+ name: string;
3
+ operator: string | null;
4
+ value: string | null;
5
+ }
@@ -0,0 +1,3 @@
1
+ export default interface ISelectorMatch {
2
+ priorityWeight: number;
3
+ }