happy-dom 13.8.4 → 13.8.6

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 (38) hide show
  1. package/cjs/config/HTMLElementConfig.cjs +11 -11
  2. package/cjs/config/HTMLElementConfig.cjs.map +1 -1
  3. package/cjs/config/HTMLElementConfigContentModelEnum.cjs +1 -1
  4. package/cjs/config/HTMLElementConfigContentModelEnum.cjs.map +1 -1
  5. package/cjs/config/HTMLElementConfigContentModelEnum.d.ts +1 -1
  6. package/cjs/config/HTMLElementConfigContentModelEnum.d.ts.map +1 -1
  7. package/cjs/css/declaration/element-style/CSSStyleDeclarationElementStyle.cjs +2 -3
  8. package/cjs/css/declaration/element-style/CSSStyleDeclarationElementStyle.cjs.map +1 -1
  9. package/cjs/css/declaration/element-style/CSSStyleDeclarationElementStyle.d.ts.map +1 -1
  10. package/cjs/query-selector/SelectorItem.cjs +90 -76
  11. package/cjs/query-selector/SelectorItem.cjs.map +1 -1
  12. package/cjs/query-selector/SelectorItem.d.ts +9 -1
  13. package/cjs/query-selector/SelectorItem.d.ts.map +1 -1
  14. package/cjs/version.cjs +1 -1
  15. package/cjs/xml-parser/XMLParser.cjs +1 -1
  16. package/cjs/xml-parser/XMLParser.cjs.map +1 -1
  17. package/lib/config/HTMLElementConfig.js +11 -11
  18. package/lib/config/HTMLElementConfig.js.map +1 -1
  19. package/lib/config/HTMLElementConfigContentModelEnum.d.ts +1 -1
  20. package/lib/config/HTMLElementConfigContentModelEnum.d.ts.map +1 -1
  21. package/lib/config/HTMLElementConfigContentModelEnum.js +1 -1
  22. package/lib/config/HTMLElementConfigContentModelEnum.js.map +1 -1
  23. package/lib/css/declaration/element-style/CSSStyleDeclarationElementStyle.d.ts.map +1 -1
  24. package/lib/css/declaration/element-style/CSSStyleDeclarationElementStyle.js +2 -3
  25. package/lib/css/declaration/element-style/CSSStyleDeclarationElementStyle.js.map +1 -1
  26. package/lib/query-selector/SelectorItem.d.ts +9 -1
  27. package/lib/query-selector/SelectorItem.d.ts.map +1 -1
  28. package/lib/query-selector/SelectorItem.js +90 -76
  29. package/lib/query-selector/SelectorItem.js.map +1 -1
  30. package/lib/version.js +1 -1
  31. package/lib/xml-parser/XMLParser.js +1 -1
  32. package/lib/xml-parser/XMLParser.js.map +1 -1
  33. package/package.json +1 -1
  34. package/src/config/HTMLElementConfig.ts +11 -11
  35. package/src/config/HTMLElementConfigContentModelEnum.ts +1 -1
  36. package/src/css/declaration/element-style/CSSStyleDeclarationElementStyle.ts +2 -3
  37. package/src/query-selector/SelectorItem.ts +97 -80
  38. package/src/xml-parser/XMLParser.ts +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "happy-dom",
3
- "version": "13.8.4",
3
+ "version": "13.8.6",
4
4
  "license": "MIT",
5
5
  "homepage": "https://github.com/capricorn86/happy-dom",
6
6
  "repository": "https://github.com/capricorn86/happy-dom",
@@ -219,7 +219,7 @@ export default <{ [key: string]: IHTMLElementConfigEntity }>{
219
219
  className: 'HTMLElement',
220
220
  localName: 'dd',
221
221
  tagName: 'DD',
222
- contentModel: HTMLElementConfigContentModelEnum.noFirsLevelSelfDescendants
222
+ contentModel: HTMLElementConfigContentModelEnum.noFirstLevelSelfDescendants
223
223
  },
224
224
  del: {
225
225
  className: 'HTMLElement',
@@ -261,7 +261,7 @@ export default <{ [key: string]: IHTMLElementConfigEntity }>{
261
261
  className: 'HTMLElement',
262
262
  localName: 'dt',
263
263
  tagName: 'DT',
264
- contentModel: HTMLElementConfigContentModelEnum.noFirsLevelSelfDescendants
264
+ contentModel: HTMLElementConfigContentModelEnum.noFirstLevelSelfDescendants
265
265
  },
266
266
  em: {
267
267
  className: 'HTMLElement',
@@ -303,37 +303,37 @@ export default <{ [key: string]: IHTMLElementConfigEntity }>{
303
303
  className: 'HTMLElement',
304
304
  localName: 'h1',
305
305
  tagName: 'H1',
306
- contentModel: HTMLElementConfigContentModelEnum.noFirsLevelSelfDescendants
306
+ contentModel: HTMLElementConfigContentModelEnum.noFirstLevelSelfDescendants
307
307
  },
308
308
  h2: {
309
309
  className: 'HTMLElement',
310
310
  localName: 'h2',
311
311
  tagName: 'H2',
312
- contentModel: HTMLElementConfigContentModelEnum.noFirsLevelSelfDescendants
312
+ contentModel: HTMLElementConfigContentModelEnum.noFirstLevelSelfDescendants
313
313
  },
314
314
  h3: {
315
315
  className: 'HTMLElement',
316
316
  localName: 'h3',
317
317
  tagName: 'H3',
318
- contentModel: HTMLElementConfigContentModelEnum.noFirsLevelSelfDescendants
318
+ contentModel: HTMLElementConfigContentModelEnum.noFirstLevelSelfDescendants
319
319
  },
320
320
  h4: {
321
321
  className: 'HTMLElement',
322
322
  localName: 'h4',
323
323
  tagName: 'H4',
324
- contentModel: HTMLElementConfigContentModelEnum.noFirsLevelSelfDescendants
324
+ contentModel: HTMLElementConfigContentModelEnum.noFirstLevelSelfDescendants
325
325
  },
326
326
  h5: {
327
327
  className: 'HTMLElement',
328
328
  localName: 'h5',
329
329
  tagName: 'H5',
330
- contentModel: HTMLElementConfigContentModelEnum.noFirsLevelSelfDescendants
330
+ contentModel: HTMLElementConfigContentModelEnum.noFirstLevelSelfDescendants
331
331
  },
332
332
  h6: {
333
333
  className: 'HTMLElement',
334
334
  localName: 'h6',
335
335
  tagName: 'H6',
336
- contentModel: HTMLElementConfigContentModelEnum.noFirsLevelSelfDescendants
336
+ contentModel: HTMLElementConfigContentModelEnum.noFirstLevelSelfDescendants
337
337
  },
338
338
  head: {
339
339
  className: 'HTMLElement',
@@ -399,7 +399,7 @@ export default <{ [key: string]: IHTMLElementConfigEntity }>{
399
399
  className: 'HTMLElement',
400
400
  localName: 'li',
401
401
  tagName: 'LI',
402
- contentModel: HTMLElementConfigContentModelEnum.noFirsLevelSelfDescendants
402
+ contentModel: HTMLElementConfigContentModelEnum.noFirstLevelSelfDescendants
403
403
  },
404
404
  main: {
405
405
  className: 'HTMLElement',
@@ -477,7 +477,7 @@ export default <{ [key: string]: IHTMLElementConfigEntity }>{
477
477
  className: 'HTMLOptionElement',
478
478
  localName: 'option',
479
479
  tagName: 'OPTION',
480
- contentModel: HTMLElementConfigContentModelEnum.noFirsLevelSelfDescendants
480
+ contentModel: HTMLElementConfigContentModelEnum.noFirstLevelSelfDescendants
481
481
  },
482
482
  output: {
483
483
  className: 'HTMLElement',
@@ -621,7 +621,7 @@ export default <{ [key: string]: IHTMLElementConfigEntity }>{
621
621
  className: 'HTMLElement',
622
622
  localName: 'table',
623
623
  tagName: 'TABLE',
624
- contentModel: HTMLElementConfigContentModelEnum.noFirsLevelSelfDescendants
624
+ contentModel: HTMLElementConfigContentModelEnum.noFirstLevelSelfDescendants
625
625
  },
626
626
  tbody: {
627
627
  className: 'HTMLElement',
@@ -1,7 +1,7 @@
1
1
  enum HTMLElementConfigContentModelEnum {
2
2
  rawText = 'rawText',
3
3
  noSelfDescendants = 'noSelfDescendants',
4
- noFirsLevelSelfDescendants = 'noFirsLevelSelfDescendants',
4
+ noFirstLevelSelfDescendants = 'noFirstLevelSelfDescendants',
5
5
  noDescendants = 'noDescendants',
6
6
  anyDescendants = 'anyDescendants'
7
7
  }
@@ -19,7 +19,7 @@ import CSSMeasurementConverter from '../measurement-converter/CSSMeasurementConv
19
19
  import MediaQueryList from '../../../match-media/MediaQueryList.js';
20
20
  import WindowBrowserSettingsReader from '../../../window/WindowBrowserSettingsReader.js';
21
21
 
22
- const CSS_VARIABLE_REGEXP = /var\( *(--[^), ]+)\)|var\( *(--[^), ]+), *([^), ]+)\)/g;
22
+ const CSS_VARIABLE_REGEXP = /var\( *(--[^), ]+)\)|var\( *(--[^), ]+), *([^), ]+)\)/;
23
23
  const CSS_MEASUREMENT_REGEXP = /[0-9.]+(px|rem|em|vw|vh|%|vmin|vmax|cm|mm|in|pt|pc|Q)/g;
24
24
 
25
25
  type IStyleAndElement = {
@@ -364,11 +364,10 @@ export default class CSSStyleDeclarationElementStyle {
364
364
  * @returns CSS value.
365
365
  */
366
366
  private parseCSSVariablesInValue(value: string, cssVariables: { [k: string]: string }): string {
367
- const regexp = new RegExp(CSS_VARIABLE_REGEXP);
368
367
  let newValue = value;
369
368
  let match;
370
369
 
371
- while ((match = regexp.exec(value)) !== null) {
370
+ while ((match = newValue.match(CSS_VARIABLE_REGEXP)) !== null) {
372
371
  // Fallback value - E.g. var(--my-var, #FFFFFF)
373
372
  if (match[2] !== undefined) {
374
373
  newValue = newValue.replace(match[0], cssVariables[match[2]] || match[3]);
@@ -106,7 +106,7 @@ export default class SelectorItem {
106
106
  }
107
107
 
108
108
  /**
109
- * Matches a psuedo selector.
109
+ * Matches a pseudo selector.
110
110
  *
111
111
  * @param element Element.
112
112
  * @returns Result.
@@ -121,15 +121,15 @@ export default class SelectorItem {
121
121
  return true;
122
122
  }
123
123
 
124
- for (const psuedo of this.pseudos) {
124
+ for (const pseudo of this.pseudos) {
125
125
  // Validation
126
- switch (psuedo.name) {
126
+ switch (pseudo.name) {
127
127
  case 'not':
128
128
  case 'nth-child':
129
129
  case 'nth-of-type':
130
130
  case 'nth-last-child':
131
131
  case 'nth-last-of-type':
132
- if (!psuedo.arguments) {
132
+ if (!pseudo.arguments) {
133
133
  throw new DOMException(`The selector "${this.getSelectorString()}" is not valid.`);
134
134
  }
135
135
  break;
@@ -137,7 +137,7 @@ export default class SelectorItem {
137
137
 
138
138
  // Check if parent exists
139
139
  if (!parent) {
140
- switch (psuedo.name) {
140
+ switch (pseudo.name) {
141
141
  case 'first-child':
142
142
  case 'last-child':
143
143
  case 'only-child':
@@ -152,86 +152,103 @@ export default class SelectorItem {
152
152
  }
153
153
  }
154
154
 
155
- switch (psuedo.name) {
156
- case 'first-child':
157
- return parentChildren[0] === element;
158
- case 'last-child':
159
- return parentChildren.length && parentChildren[parentChildren.length - 1] === element;
160
- case 'only-child':
161
- return parentChildren.length === 1 && parentChildren[0] === element;
162
- case 'first-of-type':
163
- for (const child of parentChildren) {
164
- if (child[PropertySymbol.tagName] === element[PropertySymbol.tagName]) {
165
- return child === element;
166
- }
155
+ if (!this.matchPseudoItem(element, parentChildren, pseudo)) {
156
+ return false;
157
+ }
158
+ }
159
+
160
+ return true;
161
+ }
162
+
163
+ /**
164
+ * Matches a pseudo selector.
165
+ *
166
+ * @param element Element.
167
+ * @param parentChildren Parent children.
168
+ * @param pseudo Pseudo.
169
+ */
170
+ private matchPseudoItem(
171
+ element: IElement,
172
+ parentChildren: IElement[],
173
+ pseudo: ISelectorPseudo
174
+ ): boolean {
175
+ switch (pseudo.name) {
176
+ case 'first-child':
177
+ return parentChildren[0] === element;
178
+ case 'last-child':
179
+ return parentChildren.length && parentChildren[parentChildren.length - 1] === element;
180
+ case 'only-child':
181
+ return parentChildren.length === 1 && parentChildren[0] === element;
182
+ case 'first-of-type':
183
+ for (const child of parentChildren) {
184
+ if (child[PropertySymbol.tagName] === element[PropertySymbol.tagName]) {
185
+ return child === element;
167
186
  }
168
- return false;
169
- case 'last-of-type':
170
- for (let i = parentChildren.length - 1; i >= 0; i--) {
171
- const child = parentChildren[i];
172
- if (child[PropertySymbol.tagName] === element[PropertySymbol.tagName]) {
173
- return child === element;
174
- }
187
+ }
188
+ return false;
189
+ case 'last-of-type':
190
+ for (let i = parentChildren.length - 1; i >= 0; i--) {
191
+ const child = parentChildren[i];
192
+ if (child[PropertySymbol.tagName] === element[PropertySymbol.tagName]) {
193
+ return child === element;
175
194
  }
176
- return false;
177
- case 'only-of-type':
178
- let isFound = false;
179
- for (const child of parentChildren) {
180
- if (child[PropertySymbol.tagName] === element[PropertySymbol.tagName]) {
181
- if (isFound || child !== element) {
182
- return false;
183
- }
184
- isFound = true;
195
+ }
196
+ return false;
197
+ case 'only-of-type':
198
+ let isFound = false;
199
+ for (const child of parentChildren) {
200
+ if (child[PropertySymbol.tagName] === element[PropertySymbol.tagName]) {
201
+ if (isFound || child !== element) {
202
+ return false;
185
203
  }
204
+ isFound = true;
186
205
  }
187
- return isFound;
188
- case 'checked':
189
- return (
190
- element[PropertySymbol.tagName] === 'INPUT' && (<IHTMLInputElement>element).checked
191
- );
192
- case 'empty':
193
- return !(<Element>element)[PropertySymbol.children].length;
194
- case 'root':
195
- return element[PropertySymbol.tagName] === 'HTML';
196
- case 'not':
197
- return !psuedo.selectorItem.match(element);
198
- case 'nth-child':
199
- const nthChildIndex = psuedo.selectorItem
200
- ? parentChildren.filter((child) => psuedo.selectorItem.match(child)).indexOf(element)
201
- : parentChildren.indexOf(element);
202
- return nthChildIndex !== -1 && psuedo.nthFunction(nthChildIndex + 1);
203
- case 'nth-of-type':
204
- if (!element[PropertySymbol.parentNode]) {
205
- return false;
206
- }
207
- const nthOfTypeIndex = parentChildren
208
- .filter((child) => child[PropertySymbol.tagName] === element[PropertySymbol.tagName])
209
- .indexOf(element);
210
- return nthOfTypeIndex !== -1 && psuedo.nthFunction(nthOfTypeIndex + 1);
211
- case 'nth-last-child':
212
- const nthLastChildIndex = psuedo.selectorItem
213
- ? parentChildren
214
- .filter((child) => psuedo.selectorItem.match(child))
215
- .reverse()
216
- .indexOf(element)
217
- : parentChildren.reverse().indexOf(element);
218
- return nthLastChildIndex !== -1 && psuedo.nthFunction(nthLastChildIndex + 1);
219
- case 'nth-last-of-type':
220
- const nthLastOfTypeIndex = parentChildren
221
- .filter((child) => child[PropertySymbol.tagName] === element[PropertySymbol.tagName])
222
- .reverse()
223
- .indexOf(element);
224
- return nthLastOfTypeIndex !== -1 && psuedo.nthFunction(nthLastOfTypeIndex + 1);
225
- case 'target':
226
- const hash = element[PropertySymbol.ownerDocument].location.hash;
227
- if (!hash) {
228
- return false;
229
- }
230
- return element.isConnected && element.id === hash.slice(1);
231
- }
206
+ }
207
+ return isFound;
208
+ case 'checked':
209
+ return element[PropertySymbol.tagName] === 'INPUT' && (<IHTMLInputElement>element).checked;
210
+ case 'empty':
211
+ return !(<Element>element)[PropertySymbol.children].length;
212
+ case 'root':
213
+ return element[PropertySymbol.tagName] === 'HTML';
214
+ case 'not':
215
+ return !pseudo.selectorItem.match(element);
216
+ case 'nth-child':
217
+ const nthChildIndex = pseudo.selectorItem
218
+ ? parentChildren.filter((child) => pseudo.selectorItem.match(child)).indexOf(element)
219
+ : parentChildren.indexOf(element);
220
+ return nthChildIndex !== -1 && pseudo.nthFunction(nthChildIndex + 1);
221
+ case 'nth-of-type':
222
+ if (!element[PropertySymbol.parentNode]) {
223
+ return false;
224
+ }
225
+ const nthOfTypeIndex = parentChildren
226
+ .filter((child) => child[PropertySymbol.tagName] === element[PropertySymbol.tagName])
227
+ .indexOf(element);
228
+ return nthOfTypeIndex !== -1 && pseudo.nthFunction(nthOfTypeIndex + 1);
229
+ case 'nth-last-child':
230
+ const nthLastChildIndex = pseudo.selectorItem
231
+ ? parentChildren
232
+ .filter((child) => pseudo.selectorItem.match(child))
233
+ .reverse()
234
+ .indexOf(element)
235
+ : parentChildren.reverse().indexOf(element);
236
+ return nthLastChildIndex !== -1 && pseudo.nthFunction(nthLastChildIndex + 1);
237
+ case 'nth-last-of-type':
238
+ const nthLastOfTypeIndex = parentChildren
239
+ .filter((child) => child[PropertySymbol.tagName] === element[PropertySymbol.tagName])
240
+ .reverse()
241
+ .indexOf(element);
242
+ return nthLastOfTypeIndex !== -1 && pseudo.nthFunction(nthLastOfTypeIndex + 1);
243
+ case 'target':
244
+ const hash = element[PropertySymbol.ownerDocument].location.hash;
245
+ if (!hash) {
246
+ return false;
247
+ }
248
+ return element.isConnected && element.id === hash.slice(1);
249
+ default:
250
+ return false;
232
251
  }
233
-
234
- return true;
235
252
  }
236
253
 
237
254
  /**
@@ -114,7 +114,7 @@ export default class XMLParser {
114
114
  // Therefore we need to auto-close the tag, so that it become valid (e.g. "<a></a><a></a>").
115
115
  if (
116
116
  config?.contentModel ===
117
- HTMLElementConfigContentModelEnum.noFirsLevelSelfDescendants &&
117
+ HTMLElementConfigContentModelEnum.noFirstLevelSelfDescendants &&
118
118
  stackTagNames[stackTagNames.length - 1] === tagName
119
119
  ) {
120
120
  stack.pop();