happy-dom 17.0.4 → 17.1.1

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.
Files changed (130) hide show
  1. package/cjs/browser/DefaultBrowserSettings.cjs +3 -1
  2. package/cjs/browser/DefaultBrowserSettings.cjs.map +1 -1
  3. package/cjs/browser/DefaultBrowserSettings.d.ts.map +1 -1
  4. package/cjs/browser/types/IBrowserSettings.d.ts +2 -0
  5. package/cjs/browser/types/IBrowserSettings.d.ts.map +1 -1
  6. package/cjs/browser/types/IOptionalBrowserSettings.d.ts +2 -0
  7. package/cjs/browser/types/IOptionalBrowserSettings.d.ts.map +1 -1
  8. package/cjs/css/CSSRule.cjs.map +1 -1
  9. package/cjs/css/CSSRule.d.ts +1 -1
  10. package/cjs/css/CSSRule.d.ts.map +1 -1
  11. package/cjs/css/CSSStyleSheet.cjs +16 -7
  12. package/cjs/css/CSSStyleSheet.cjs.map +1 -1
  13. package/cjs/css/CSSStyleSheet.d.ts.map +1 -1
  14. package/cjs/css/rules/CSSContainerRule.cjs +2 -1
  15. package/cjs/css/rules/CSSContainerRule.cjs.map +1 -1
  16. package/cjs/css/rules/CSSContainerRule.d.ts +2 -1
  17. package/cjs/css/rules/CSSContainerRule.d.ts.map +1 -1
  18. package/cjs/css/rules/CSSFontFaceRule.cjs +2 -1
  19. package/cjs/css/rules/CSSFontFaceRule.cjs.map +1 -1
  20. package/cjs/css/rules/CSSFontFaceRule.d.ts +2 -1
  21. package/cjs/css/rules/CSSFontFaceRule.d.ts.map +1 -1
  22. package/cjs/css/rules/CSSKeyframeRule.cjs +2 -1
  23. package/cjs/css/rules/CSSKeyframeRule.cjs.map +1 -1
  24. package/cjs/css/rules/CSSKeyframeRule.d.ts +2 -1
  25. package/cjs/css/rules/CSSKeyframeRule.d.ts.map +1 -1
  26. package/cjs/css/rules/CSSKeyframesRule.cjs +2 -1
  27. package/cjs/css/rules/CSSKeyframesRule.cjs.map +1 -1
  28. package/cjs/css/rules/CSSKeyframesRule.d.ts +2 -1
  29. package/cjs/css/rules/CSSKeyframesRule.d.ts.map +1 -1
  30. package/cjs/css/rules/CSSMediaRule.cjs +2 -1
  31. package/cjs/css/rules/CSSMediaRule.cjs.map +1 -1
  32. package/cjs/css/rules/CSSMediaRule.d.ts +2 -1
  33. package/cjs/css/rules/CSSMediaRule.d.ts.map +1 -1
  34. package/cjs/css/rules/CSSStyleRule.cjs +2 -1
  35. package/cjs/css/rules/CSSStyleRule.cjs.map +1 -1
  36. package/cjs/css/rules/CSSStyleRule.d.ts +2 -1
  37. package/cjs/css/rules/CSSStyleRule.d.ts.map +1 -1
  38. package/cjs/css/rules/CSSSupportsRule.cjs +2 -1
  39. package/cjs/css/rules/CSSSupportsRule.cjs.map +1 -1
  40. package/cjs/css/rules/CSSSupportsRule.d.ts +2 -1
  41. package/cjs/css/rules/CSSSupportsRule.d.ts.map +1 -1
  42. package/cjs/css/utilities/CSSParser.cjs +106 -56
  43. package/cjs/css/utilities/CSSParser.cjs.map +1 -1
  44. package/cjs/css/utilities/CSSParser.d.ts.map +1 -1
  45. package/cjs/match-media/MediaQueryItem.cjs +14 -2
  46. package/cjs/match-media/MediaQueryItem.cjs.map +1 -1
  47. package/cjs/match-media/MediaQueryItem.d.ts.map +1 -1
  48. package/cjs/nodes/html-link-element/HTMLLinkElement.cjs +1 -2
  49. package/cjs/nodes/html-link-element/HTMLLinkElement.cjs.map +1 -1
  50. package/cjs/nodes/html-link-element/HTMLLinkElement.d.ts.map +1 -1
  51. package/cjs/nodes/html-style-element/HTMLStyleElement.cjs +1 -2
  52. package/cjs/nodes/html-style-element/HTMLStyleElement.cjs.map +1 -1
  53. package/cjs/nodes/html-style-element/HTMLStyleElement.d.ts.map +1 -1
  54. package/cjs/nodes/svg-style-element/SVGStyleElement.cjs +1 -2
  55. package/cjs/nodes/svg-style-element/SVGStyleElement.cjs.map +1 -1
  56. package/cjs/nodes/svg-style-element/SVGStyleElement.d.ts.map +1 -1
  57. package/lib/browser/DefaultBrowserSettings.d.ts.map +1 -1
  58. package/lib/browser/DefaultBrowserSettings.js +3 -1
  59. package/lib/browser/DefaultBrowserSettings.js.map +1 -1
  60. package/lib/browser/types/IBrowserSettings.d.ts +2 -0
  61. package/lib/browser/types/IBrowserSettings.d.ts.map +1 -1
  62. package/lib/browser/types/IOptionalBrowserSettings.d.ts +2 -0
  63. package/lib/browser/types/IOptionalBrowserSettings.d.ts.map +1 -1
  64. package/lib/css/CSSRule.d.ts +1 -1
  65. package/lib/css/CSSRule.d.ts.map +1 -1
  66. package/lib/css/CSSRule.js.map +1 -1
  67. package/lib/css/CSSStyleSheet.d.ts.map +1 -1
  68. package/lib/css/CSSStyleSheet.js +16 -7
  69. package/lib/css/CSSStyleSheet.js.map +1 -1
  70. package/lib/css/rules/CSSContainerRule.d.ts +2 -1
  71. package/lib/css/rules/CSSContainerRule.d.ts.map +1 -1
  72. package/lib/css/rules/CSSContainerRule.js +2 -1
  73. package/lib/css/rules/CSSContainerRule.js.map +1 -1
  74. package/lib/css/rules/CSSFontFaceRule.d.ts +2 -1
  75. package/lib/css/rules/CSSFontFaceRule.d.ts.map +1 -1
  76. package/lib/css/rules/CSSFontFaceRule.js +2 -1
  77. package/lib/css/rules/CSSFontFaceRule.js.map +1 -1
  78. package/lib/css/rules/CSSKeyframeRule.d.ts +2 -1
  79. package/lib/css/rules/CSSKeyframeRule.d.ts.map +1 -1
  80. package/lib/css/rules/CSSKeyframeRule.js +2 -1
  81. package/lib/css/rules/CSSKeyframeRule.js.map +1 -1
  82. package/lib/css/rules/CSSKeyframesRule.d.ts +2 -1
  83. package/lib/css/rules/CSSKeyframesRule.d.ts.map +1 -1
  84. package/lib/css/rules/CSSKeyframesRule.js +2 -1
  85. package/lib/css/rules/CSSKeyframesRule.js.map +1 -1
  86. package/lib/css/rules/CSSMediaRule.d.ts +2 -1
  87. package/lib/css/rules/CSSMediaRule.d.ts.map +1 -1
  88. package/lib/css/rules/CSSMediaRule.js +2 -1
  89. package/lib/css/rules/CSSMediaRule.js.map +1 -1
  90. package/lib/css/rules/CSSStyleRule.d.ts +2 -1
  91. package/lib/css/rules/CSSStyleRule.d.ts.map +1 -1
  92. package/lib/css/rules/CSSStyleRule.js +2 -1
  93. package/lib/css/rules/CSSStyleRule.js.map +1 -1
  94. package/lib/css/rules/CSSSupportsRule.d.ts +2 -1
  95. package/lib/css/rules/CSSSupportsRule.d.ts.map +1 -1
  96. package/lib/css/rules/CSSSupportsRule.js +2 -1
  97. package/lib/css/rules/CSSSupportsRule.js.map +1 -1
  98. package/lib/css/utilities/CSSParser.d.ts.map +1 -1
  99. package/lib/css/utilities/CSSParser.js +106 -56
  100. package/lib/css/utilities/CSSParser.js.map +1 -1
  101. package/lib/match-media/MediaQueryItem.d.ts.map +1 -1
  102. package/lib/match-media/MediaQueryItem.js +14 -2
  103. package/lib/match-media/MediaQueryItem.js.map +1 -1
  104. package/lib/nodes/html-link-element/HTMLLinkElement.d.ts.map +1 -1
  105. package/lib/nodes/html-link-element/HTMLLinkElement.js +1 -2
  106. package/lib/nodes/html-link-element/HTMLLinkElement.js.map +1 -1
  107. package/lib/nodes/html-style-element/HTMLStyleElement.d.ts.map +1 -1
  108. package/lib/nodes/html-style-element/HTMLStyleElement.js +1 -2
  109. package/lib/nodes/html-style-element/HTMLStyleElement.js.map +1 -1
  110. package/lib/nodes/svg-style-element/SVGStyleElement.d.ts.map +1 -1
  111. package/lib/nodes/svg-style-element/SVGStyleElement.js +1 -2
  112. package/lib/nodes/svg-style-element/SVGStyleElement.js.map +1 -1
  113. package/package.json +1 -1
  114. package/src/browser/DefaultBrowserSettings.ts +3 -1
  115. package/src/browser/types/IBrowserSettings.ts +2 -0
  116. package/src/browser/types/IOptionalBrowserSettings.ts +2 -0
  117. package/src/css/CSSRule.ts +1 -1
  118. package/src/css/CSSStyleSheet.ts +26 -10
  119. package/src/css/rules/CSSContainerRule.ts +2 -1
  120. package/src/css/rules/CSSFontFaceRule.ts +2 -1
  121. package/src/css/rules/CSSKeyframeRule.ts +2 -1
  122. package/src/css/rules/CSSKeyframesRule.ts +2 -1
  123. package/src/css/rules/CSSMediaRule.ts +2 -1
  124. package/src/css/rules/CSSStyleRule.ts +2 -1
  125. package/src/css/rules/CSSSupportsRule.ts +2 -1
  126. package/src/css/utilities/CSSParser.ts +121 -64
  127. package/src/match-media/MediaQueryItem.ts +16 -2
  128. package/src/nodes/html-link-element/HTMLLinkElement.ts +3 -1
  129. package/src/nodes/html-style-element/HTMLStyleElement.ts +3 -1
  130. package/src/nodes/svg-style-element/SVGStyleElement.ts +3 -1
@@ -9,6 +9,7 @@ import CSSContainerRule from '../rules/CSSContainerRule.js';
9
9
  import CSSSupportsRule from '../rules/CSSSupportsRule.js';
10
10
  import CSSFontFaceRule from '../rules/CSSFontFaceRule.js';
11
11
  import SelectorParser from '../../query-selector/SelectorParser.js';
12
+ import CSSRuleTypeEnum from '../CSSRuleTypeEnum.js';
12
13
 
13
14
  const COMMENT_REGEXP = /\/\*[\s\S]*?\*\//gm;
14
15
 
@@ -29,7 +30,7 @@ export default class CSSParser {
29
30
  const cssRules = [];
30
31
  const regExp = /{|}/gm;
31
32
  const stack: CSSRule[] = [];
32
- let parentRule: CSSRule = null;
33
+ let parentRule: CSSRule | null = null;
33
34
  let lastIndex = 0;
34
35
  let match: RegExpMatchArray;
35
36
 
@@ -37,64 +38,120 @@ export default class CSSParser {
37
38
  if (match[0] === '{') {
38
39
  const selectorText = css.substring(lastIndex, match.index).trim();
39
40
 
40
- if (
41
- selectorText.startsWith('@keyframes') ||
42
- selectorText.startsWith('@-webkit-keyframes')
43
- ) {
44
- const newRule = new CSSKeyframesRule(PropertySymbol.illegalConstructor, window);
45
-
46
- (<string>newRule.name) = selectorText.replace(/@(-webkit-){0,1}keyframes +/, '');
47
- newRule.parentStyleSheet = parentStyleSheet;
48
- cssRules.push(newRule);
49
- parentRule = newRule;
50
- } else if (selectorText.startsWith('@media')) {
51
- const mediums = selectorText.replace('@media', '').split(',');
52
- const newRule = new CSSMediaRule(PropertySymbol.illegalConstructor, window);
53
-
54
- for (const medium of mediums) {
55
- newRule.media.appendMedium(medium.trim());
41
+ if (selectorText[0] === '@') {
42
+ const ruleParts = selectorText.split(' ');
43
+ const ruleType = ruleParts[0];
44
+ const ruleParameters = ruleParts.slice(1).join(' ').trim();
45
+
46
+ switch (ruleType) {
47
+ case '@keyframes':
48
+ case '@-webkit-keyframes':
49
+ const keyframesRule = new CSSKeyframesRule(PropertySymbol.illegalConstructor, window);
50
+
51
+ (<string>keyframesRule.name) = ruleParameters;
52
+ keyframesRule.parentStyleSheet = parentStyleSheet;
53
+ if (parentRule) {
54
+ if (
55
+ parentRule.type === CSSRuleTypeEnum.mediaRule ||
56
+ parentRule.type === CSSRuleTypeEnum.containerRule ||
57
+ parentRule.type === CSSRuleTypeEnum.supportsRule
58
+ ) {
59
+ (<CSSMediaRule>parentRule).cssRules.push(keyframesRule);
60
+ }
61
+ } else {
62
+ cssRules.push(keyframesRule);
63
+ }
64
+ parentRule = keyframesRule;
65
+ break;
66
+ case '@media':
67
+ const mediums = ruleParameters.split(',');
68
+ const mediaRule = new CSSMediaRule(PropertySymbol.illegalConstructor, window);
69
+
70
+ for (const medium of mediums) {
71
+ mediaRule.media.appendMedium(medium.trim());
72
+ }
73
+
74
+ mediaRule.parentStyleSheet = parentStyleSheet;
75
+ if (parentRule) {
76
+ if (
77
+ parentRule.type === CSSRuleTypeEnum.mediaRule ||
78
+ parentRule.type === CSSRuleTypeEnum.containerRule ||
79
+ parentRule.type === CSSRuleTypeEnum.supportsRule
80
+ ) {
81
+ (<CSSMediaRule>parentRule).cssRules.push(mediaRule);
82
+ }
83
+ } else {
84
+ cssRules.push(mediaRule);
85
+ }
86
+ parentRule = mediaRule;
87
+ break;
88
+ case '@container':
89
+ case '@-webkit-container':
90
+ const containerRule = new CSSContainerRule(PropertySymbol.illegalConstructor, window);
91
+
92
+ (<string>containerRule.conditionText) = ruleParameters;
93
+ containerRule.parentStyleSheet = parentStyleSheet;
94
+
95
+ if (parentRule) {
96
+ if (
97
+ parentRule.type === CSSRuleTypeEnum.mediaRule ||
98
+ parentRule.type === CSSRuleTypeEnum.containerRule ||
99
+ parentRule.type === CSSRuleTypeEnum.supportsRule
100
+ ) {
101
+ (<CSSMediaRule>parentRule).cssRules.push(containerRule);
102
+ }
103
+ } else {
104
+ cssRules.push(containerRule);
105
+ }
106
+
107
+ parentRule = containerRule;
108
+ break;
109
+ case '@supports':
110
+ case '@-webkit-supports':
111
+ const supportsRule = new CSSSupportsRule(PropertySymbol.illegalConstructor, window);
112
+
113
+ (<string>supportsRule.conditionText) = ruleParameters;
114
+ supportsRule.parentStyleSheet = parentStyleSheet;
115
+ if (parentRule) {
116
+ if (
117
+ parentRule.type === CSSRuleTypeEnum.mediaRule ||
118
+ parentRule.type === CSSRuleTypeEnum.containerRule ||
119
+ parentRule.type === CSSRuleTypeEnum.supportsRule
120
+ ) {
121
+ (<CSSMediaRule>parentRule).cssRules.push(supportsRule);
122
+ }
123
+ } else {
124
+ cssRules.push(supportsRule);
125
+ }
126
+ parentRule = supportsRule;
127
+ break;
128
+ case '@font-face':
129
+ const fontFaceRule = new CSSFontFaceRule(PropertySymbol.illegalConstructor, window);
130
+
131
+ fontFaceRule[PropertySymbol.cssText] = ruleParameters;
132
+ fontFaceRule.parentStyleSheet = parentStyleSheet;
133
+ if (parentRule) {
134
+ if (
135
+ parentRule.type === CSSRuleTypeEnum.mediaRule ||
136
+ parentRule.type === CSSRuleTypeEnum.containerRule ||
137
+ parentRule.type === CSSRuleTypeEnum.supportsRule
138
+ ) {
139
+ (<CSSMediaRule>parentRule).cssRules.push(fontFaceRule);
140
+ }
141
+ } else {
142
+ cssRules.push(fontFaceRule);
143
+ }
144
+ parentRule = fontFaceRule;
145
+ break;
146
+ default:
147
+ // Unknown rule.
148
+ // We will create a new rule to let it grab its content, but we will not add it to the cssRules array.
149
+ const newRule = new CSSRule(PropertySymbol.illegalConstructor, window);
150
+ newRule.parentStyleSheet = parentStyleSheet;
151
+ parentRule = newRule;
152
+ break;
56
153
  }
57
-
58
- newRule.parentStyleSheet = parentStyleSheet;
59
- cssRules.push(newRule);
60
- parentRule = newRule;
61
- } else if (
62
- selectorText.startsWith('@container') ||
63
- selectorText.startsWith('@-webkit-container')
64
- ) {
65
- const conditionText = selectorText.replace(/@(-webkit-){0,1}container +/, '');
66
- const newRule = new CSSContainerRule(PropertySymbol.illegalConstructor, window);
67
-
68
- (<string>newRule.conditionText) = conditionText;
69
- newRule.parentStyleSheet = parentStyleSheet;
70
- cssRules.push(newRule);
71
- parentRule = newRule;
72
- } else if (
73
- selectorText.startsWith('@supports') ||
74
- selectorText.startsWith('@-webkit-supports')
75
- ) {
76
- const conditionText = selectorText.replace(/@(-webkit-){0,1}supports +/, '');
77
- const newRule = new CSSSupportsRule(PropertySymbol.illegalConstructor, window);
78
-
79
- (<string>newRule.conditionText) = conditionText;
80
- newRule.parentStyleSheet = parentStyleSheet;
81
- cssRules.push(newRule);
82
- parentRule = newRule;
83
- } else if (selectorText.startsWith('@font-face')) {
84
- const conditionText = selectorText.replace('@font-face', '');
85
- const newRule = new CSSFontFaceRule(PropertySymbol.illegalConstructor, window);
86
-
87
- newRule[PropertySymbol.cssText] = conditionText;
88
- newRule.parentStyleSheet = parentStyleSheet;
89
- cssRules.push(newRule);
90
- parentRule = newRule;
91
- } else if (selectorText[0] === '@') {
92
- // Unknown rule.
93
- // We will create a new rule to let it grab its content, but we will not add it to the cssRules array.
94
- const newRule = new CSSRule(PropertySymbol.illegalConstructor, window);
95
- newRule.parentStyleSheet = parentStyleSheet;
96
- parentRule = newRule;
97
- } else if (parentRule && parentRule.type === CSSRule.KEYFRAMES_RULE) {
154
+ } else if (parentRule && parentRule.type === CSSRuleTypeEnum.keyframesRule) {
98
155
  const newRule = new CSSKeyframeRule(PropertySymbol.illegalConstructor, window);
99
156
  (<string>newRule.keyText) = selectorText.trim();
100
157
  newRule.parentStyleSheet = parentStyleSheet;
@@ -104,9 +161,9 @@ export default class CSSParser {
104
161
  parentRule = newRule;
105
162
  } else if (
106
163
  parentRule &&
107
- (parentRule.type === CSSRule.MEDIA_RULE ||
108
- parentRule.type === CSSRule.CONTAINER_RULE ||
109
- parentRule.type === CSSRule.SUPPORTS_RULE)
164
+ (parentRule.type === CSSRuleTypeEnum.mediaRule ||
165
+ parentRule.type === CSSRuleTypeEnum.containerRule ||
166
+ parentRule.type === CSSRuleTypeEnum.supportsRule)
110
167
  ) {
111
168
  if (this.validateSelectorText(selectorText)) {
112
169
  const newRule = new CSSStyleRule(PropertySymbol.illegalConstructor, window);
@@ -139,9 +196,9 @@ export default class CSSParser {
139
196
  .trim()
140
197
  .replace(/([^;])$/, '$1;'); // Ensure last semicolon
141
198
  switch (parentRule.type) {
142
- case CSSRule.FONT_FACE_RULE:
143
- case CSSRule.KEYFRAME_RULE:
144
- case CSSRule.STYLE_RULE:
199
+ case CSSRuleTypeEnum.fontFaceRule:
200
+ case CSSRuleTypeEnum.keyframeRule:
201
+ case CSSRuleTypeEnum.styleRule:
145
202
  (<CSSStyleRule>parentRule)[PropertySymbol.cssText] = cssText;
146
203
  break;
147
204
  }
@@ -199,6 +199,12 @@ export default class MediaQueryItem {
199
199
  * @returns "true" if the rule matches.
200
200
  */
201
201
  private matchesRule(rule: IMediaQueryRule): boolean {
202
+ const settings = new WindowBrowserContext(this.window).getSettings();
203
+
204
+ if (!settings) {
205
+ return false;
206
+ }
207
+
202
208
  if (!rule.value) {
203
209
  switch (rule.name) {
204
210
  case 'min-width':
@@ -218,6 +224,10 @@ export default class MediaQueryItem {
218
224
  case 'max-aspect-ratio':
219
225
  case 'aspect-ratio':
220
226
  return true;
227
+ case 'prefers-reduced-motion':
228
+ return settings.device.prefersReducedMotion === 'reduce';
229
+ case 'forced-colors':
230
+ return settings.device.forcedColors === 'active';
221
231
  }
222
232
  return false;
223
233
  }
@@ -246,9 +256,13 @@ export default class MediaQueryItem {
246
256
  ? this.window.innerWidth > this.window.innerHeight
247
257
  : this.window.innerWidth < this.window.innerHeight;
248
258
  case 'prefers-color-scheme':
259
+ return rule.value === settings.device.prefersColorScheme;
260
+ case 'prefers-reduced-motion':
261
+ return rule.value === settings.device.prefersReducedMotion;
262
+ case 'forced-colors':
249
263
  return (
250
- rule.value ===
251
- new WindowBrowserContext(this.window).getSettings().device.prefersColorScheme
264
+ (rule.value === 'none' || rule.value === 'active') &&
265
+ rule.value === settings.device.forcedColors
252
266
  );
253
267
  case 'any-hover':
254
268
  case 'hover':
@@ -455,7 +455,9 @@ export default class HTMLLinkElement extends HTMLElement {
455
455
  browserFrame.page?.console.error(error);
456
456
  this.dispatchEvent(new Event('error'));
457
457
  } else {
458
- const styleSheet = new CSSStyleSheet();
458
+ const styleSheet = new this[PropertySymbol.ownerDocument][
459
+ PropertySymbol.window
460
+ ].CSSStyleSheet();
459
461
  styleSheet.replaceSync(code);
460
462
  this[PropertySymbol.sheet] = styleSheet;
461
463
 
@@ -79,7 +79,9 @@ export default class HTMLStyleElement extends HTMLElement {
79
79
  return null;
80
80
  }
81
81
  if (!this[PropertySymbol.sheet]) {
82
- this[PropertySymbol.sheet] = new CSSStyleSheet();
82
+ this[PropertySymbol.sheet] = new this[PropertySymbol.ownerDocument][
83
+ PropertySymbol.window
84
+ ].CSSStyleSheet();
83
85
  this[PropertySymbol.sheet].replaceSync(this.textContent);
84
86
  }
85
87
  return this[PropertySymbol.sheet];
@@ -97,7 +97,9 @@ export default class SVGStyleElement extends SVGElement {
97
97
  return null;
98
98
  }
99
99
  if (!this[PropertySymbol.sheet]) {
100
- this[PropertySymbol.sheet] = new CSSStyleSheet();
100
+ this[PropertySymbol.sheet] = new this[PropertySymbol.ownerDocument][
101
+ PropertySymbol.window
102
+ ].CSSStyleSheet();
101
103
  this[PropertySymbol.sheet].replaceSync(this.textContent);
102
104
  }
103
105
  return this[PropertySymbol.sheet];