happy-dom 14.3.10 → 14.5.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 (40) hide show
  1. package/cjs/PropertySymbol.cjs +2 -1
  2. package/cjs/PropertySymbol.cjs.map +1 -1
  3. package/cjs/PropertySymbol.d.ts +1 -0
  4. package/cjs/PropertySymbol.d.ts.map +1 -1
  5. package/cjs/fetch/Request.cjs +28 -14
  6. package/cjs/fetch/Request.cjs.map +1 -1
  7. package/cjs/fetch/Request.d.ts.map +1 -1
  8. package/cjs/fetch/Response.cjs +26 -19
  9. package/cjs/fetch/Response.cjs.map +1 -1
  10. package/cjs/fetch/Response.d.ts.map +1 -1
  11. package/cjs/nodes/html-iframe-element/HTMLIFrameElement.cjs +9 -6
  12. package/cjs/nodes/html-iframe-element/HTMLIFrameElement.cjs.map +1 -1
  13. package/cjs/nodes/html-iframe-element/HTMLIFrameElement.d.ts +4 -4
  14. package/cjs/nodes/html-iframe-element/HTMLIFrameElement.d.ts.map +1 -1
  15. package/cjs/nodes/html-iframe-element/HTMLIFrameElementNamedNodeMap.cjs +43 -2
  16. package/cjs/nodes/html-iframe-element/HTMLIFrameElementNamedNodeMap.cjs.map +1 -1
  17. package/cjs/nodes/html-iframe-element/HTMLIFrameElementNamedNodeMap.d.ts.map +1 -1
  18. package/lib/PropertySymbol.d.ts +1 -0
  19. package/lib/PropertySymbol.d.ts.map +1 -1
  20. package/lib/PropertySymbol.js +1 -0
  21. package/lib/PropertySymbol.js.map +1 -1
  22. package/lib/fetch/Request.d.ts.map +1 -1
  23. package/lib/fetch/Request.js +28 -14
  24. package/lib/fetch/Request.js.map +1 -1
  25. package/lib/fetch/Response.d.ts.map +1 -1
  26. package/lib/fetch/Response.js +26 -19
  27. package/lib/fetch/Response.js.map +1 -1
  28. package/lib/nodes/html-iframe-element/HTMLIFrameElement.d.ts +4 -4
  29. package/lib/nodes/html-iframe-element/HTMLIFrameElement.d.ts.map +1 -1
  30. package/lib/nodes/html-iframe-element/HTMLIFrameElement.js +9 -6
  31. package/lib/nodes/html-iframe-element/HTMLIFrameElement.js.map +1 -1
  32. package/lib/nodes/html-iframe-element/HTMLIFrameElementNamedNodeMap.d.ts.map +1 -1
  33. package/lib/nodes/html-iframe-element/HTMLIFrameElementNamedNodeMap.js +43 -2
  34. package/lib/nodes/html-iframe-element/HTMLIFrameElementNamedNodeMap.js.map +1 -1
  35. package/package.json +1 -1
  36. package/src/PropertySymbol.ts +1 -0
  37. package/src/fetch/Request.ts +38 -17
  38. package/src/fetch/Response.ts +36 -21
  39. package/src/nodes/html-iframe-element/HTMLIFrameElement.ts +8 -6
  40. package/src/nodes/html-iframe-element/HTMLIFrameElementNamedNodeMap.ts +60 -0
@@ -225,37 +225,52 @@ export default class Response implements Response {
225
225
  */
226
226
  public async formData(): Promise<FormData> {
227
227
  const contentType = this.headers.get('Content-Type');
228
+ const asyncTaskManager = this.#browserFrame[PropertySymbol.asyncTaskManager];
229
+
230
+ if (/multipart/i.test(contentType)) {
231
+ if (this.bodyUsed) {
232
+ throw new DOMException(
233
+ `Body has already been used for "${this.url}".`,
234
+ DOMExceptionNameEnum.invalidStateError
235
+ );
236
+ }
228
237
 
229
- if (contentType?.startsWith('application/x-www-form-urlencoded')) {
230
- const formData = new FormData();
231
- const text = await this.text();
232
- const parameters = new URLSearchParams(text);
238
+ (<boolean>this.bodyUsed) = true;
233
239
 
234
- for (const [name, value] of parameters) {
235
- formData.append(name, value);
240
+ const taskID = asyncTaskManager.startTask();
241
+ let formData: FormData;
242
+ let buffer: Buffer;
243
+
244
+ try {
245
+ const result = await MultipartFormDataParser.streamToFormData(this.body, contentType);
246
+ formData = result.formData;
247
+ buffer = result.buffer;
248
+ } catch (error) {
249
+ asyncTaskManager.endTask(taskID);
250
+ throw error;
236
251
  }
237
252
 
253
+ this.#storeBodyInCache(buffer);
254
+ asyncTaskManager.endTask(taskID);
255
+
238
256
  return formData;
239
257
  }
240
258
 
241
- const taskID = this.#browserFrame[PropertySymbol.asyncTaskManager].startTask();
242
- let formData: FormData;
243
- let buffer: Buffer;
244
-
245
- try {
246
- const result = await MultipartFormDataParser.streamToFormData(this.body, contentType);
247
- formData = result.formData;
248
- buffer = result.buffer;
249
- } catch (error) {
250
- this.#browserFrame[PropertySymbol.asyncTaskManager].endTask(taskID);
251
- throw error;
252
- }
259
+ if (contentType?.startsWith('application/x-www-form-urlencoded')) {
260
+ const parameters = new URLSearchParams(await this.text());
261
+ const formData = new FormData();
253
262
 
254
- this.#storeBodyInCache(buffer);
263
+ for (const [key, value] of parameters) {
264
+ formData.append(key, value);
265
+ }
255
266
 
256
- this.#browserFrame[PropertySymbol.asyncTaskManager].endTask(taskID);
267
+ return formData;
268
+ }
257
269
 
258
- return formData;
270
+ throw new DOMException(
271
+ `Failed to build FormData object: The "content-type" header is neither "application/x-www-form-urlencoded" nor "multipart/form-data".`,
272
+ DOMExceptionNameEnum.invalidStateError
273
+ );
259
274
  }
260
275
 
261
276
  /**
@@ -9,6 +9,7 @@ import HTMLIFrameElementNamedNodeMap from './HTMLIFrameElementNamedNodeMap.js';
9
9
  import CrossOriginBrowserWindow from '../../window/CrossOriginBrowserWindow.js';
10
10
  import IBrowserFrame from '../../browser/types/IBrowserFrame.js';
11
11
  import HTMLIFrameElementPageLoader from './HTMLIFrameElementPageLoader.js';
12
+ import DOMTokenList from '../../dom-token-list/DOMTokenList.js';
12
13
 
13
14
  /**
14
15
  * HTML Iframe Element.
@@ -23,7 +24,7 @@ export default class HTMLIFrameElement extends HTMLElement {
23
24
 
24
25
  // Internal properties
25
26
  public override [PropertySymbol.attributes]: NamedNodeMap;
26
-
27
+ public [PropertySymbol.sandbox]: DOMTokenList = null;
27
28
  // Private properties
28
29
  #contentWindowContainer: { window: BrowserWindow | CrossOriginBrowserWindow | null } = {
29
30
  window: null
@@ -140,14 +141,15 @@ export default class HTMLIFrameElement extends HTMLElement {
140
141
  *
141
142
  * @returns Sandbox.
142
143
  */
143
- public get sandbox(): string {
144
- return this.getAttribute('sandbox') || '';
144
+ public get sandbox(): DOMTokenList {
145
+ if (!this[PropertySymbol.sandbox]) {
146
+ this[PropertySymbol.sandbox] = new DOMTokenList(this, 'sandbox');
147
+ }
148
+ return <DOMTokenList>this[PropertySymbol.sandbox];
145
149
  }
146
150
 
147
151
  /**
148
152
  * Sets sandbox.
149
- *
150
- * @param sandbox Sandbox.
151
153
  */
152
154
  public set sandbox(sandbox: string) {
153
155
  this.setAttribute('sandbox', sandbox);
@@ -163,7 +165,7 @@ export default class HTMLIFrameElement extends HTMLElement {
163
165
  }
164
166
 
165
167
  /**
166
- * Sets sandbox.
168
+ * Sets srcdoc.
167
169
  *
168
170
  * @param srcdoc Srcdoc.
169
171
  */
@@ -3,6 +3,23 @@ import Element from '../element/Element.js';
3
3
  import HTMLElementNamedNodeMap from '../html-element/HTMLElementNamedNodeMap.js';
4
4
  import HTMLIFrameElementPageLoader from './HTMLIFrameElementPageLoader.js';
5
5
  import * as PropertySymbol from '../../PropertySymbol.js';
6
+ import DOMTokenList from '../../dom-token-list/DOMTokenList.js';
7
+
8
+ const SANDBOX_FLAGS = [
9
+ 'allow-downloads',
10
+ 'allow-forms',
11
+ 'allow-modals',
12
+ 'allow-orientation-lock',
13
+ 'allow-pointer-lock',
14
+ 'allow-popups',
15
+ 'allow-popups-to-escape-sandbox',
16
+ 'allow-presentation',
17
+ 'allow-same-origin',
18
+ 'allow-scripts',
19
+ 'allow-top-navigation',
20
+ 'allow-top-navigation-by-user-activation',
21
+ 'allow-top-navigation-to-custom-protocols'
22
+ ];
6
23
 
7
24
  /**
8
25
  * Named Node Map.
@@ -37,6 +54,49 @@ export default class HTMLIFrameElementNamedNodeMap extends HTMLElementNamedNodeM
37
54
  this.#pageLoader.loadPage();
38
55
  }
39
56
 
57
+ if (item[PropertySymbol.name] === 'sandbox') {
58
+ if (!this[PropertySymbol.ownerElement][PropertySymbol.sandbox]) {
59
+ this[PropertySymbol.ownerElement][PropertySymbol.sandbox] = new DOMTokenList(
60
+ this[PropertySymbol.ownerElement],
61
+ 'sandbox'
62
+ );
63
+ } else {
64
+ this[PropertySymbol.ownerElement][PropertySymbol.sandbox][PropertySymbol.updateIndices]();
65
+ }
66
+
67
+ this.#validateSandboxFlags();
68
+ }
69
+
40
70
  return replacedAttribute || null;
41
71
  }
72
+
73
+ /**
74
+ *
75
+ * @param tokens
76
+ * @param vconsole
77
+ */
78
+ #validateSandboxFlags(): void {
79
+ const window =
80
+ this[PropertySymbol.ownerElement][PropertySymbol.ownerDocument][PropertySymbol.ownerWindow];
81
+ const values = this[PropertySymbol.ownerElement][PropertySymbol.sandbox].values();
82
+ const invalidFlags: string[] = [];
83
+
84
+ for (const token of values) {
85
+ if (!SANDBOX_FLAGS.includes(token)) {
86
+ invalidFlags.push(token);
87
+ }
88
+ }
89
+
90
+ if (invalidFlags.length === 1) {
91
+ window.console.error(
92
+ `Error while parsing the 'sandbox' attribute: '${invalidFlags[0]}' is an invalid sandbox flag.`
93
+ );
94
+ } else if (invalidFlags.length > 1) {
95
+ window.console.error(
96
+ `Error while parsing the 'sandbox' attribute: '${invalidFlags.join(
97
+ `', '`
98
+ )}' are invalid sandbox flags.`
99
+ );
100
+ }
101
+ }
42
102
  }