Repository: capricorn86/happy-dom
Pull request #769 (2023-02-21 01:25:01)

#768@patch: Corrects the name Window.HTMLIframeElement to Window.HTML…
…IFrameElement.


Patch:
diff --git a/packages/happy-dom/README.md b/packages/happy-dom/README.md
index 3da7a153..5368b817 100644
--- a/packages/happy-dom/README.md
+++ b/packages/happy-dom/README.md
@@ -289,7 +289,7 @@ Set it to "true" to disable CSS file loading in HTMLLinkElement. Defaults to "fa
 
 **disableIframePageLoading**
 
-Set it to "true" to disable page loading in HTMLIframeElement. Defaults to "false".
+Set it to "true" to disable page loading in HTMLIFrameElement. Defaults to "false".
 
 **enableFileSystemHttpRequests**
 
diff --git a/packages/happy-dom/src/config/ElementTag.ts b/packages/happy-dom/src/config/ElementTag.ts
index 034c460d..6253d833 100644
--- a/packages/happy-dom/src/config/ElementTag.ts
+++ b/packages/happy-dom/src/config/ElementTag.ts
@@ -21,7 +21,7 @@ import HTMLButtonElement from '../nodes/html-button-element/HTMLButtonElement';
 import HTMLAudioElement from '../nodes/html-audio-element/HTMLAudioElement';
 import HTMLVideoElement from '../nodes/html-video-element/HTMLVideoElement';
 import HTMLAnchorElement from '../nodes/html-anchor-element/HTMLAnchorElement';
-import HTMLIframeElement from '../nodes/html-iframe-element/HTMLIframeElement';
+import HTMLIFrameElement from '../nodes/html-iframe-element/HTMLIFrameElement';
 
 export default {
 	A: HTMLAnchorElement,
@@ -95,7 +95,7 @@ export default {
 	HR: HTMLElement,
 	HTML: HTMLElement,
 	I: HTMLElement,
-	IFRAME: HTMLIframeElement,
+	IFRAME: HTMLIFrameElement,
 	INS: HTMLElement,
 	KBD: HTMLElement,
 	LEGEND: HTMLElement,
diff --git a/packages/happy-dom/src/index.ts b/packages/happy-dom/src/index.ts
index 88491aa0..bc870ffd 100644
--- a/packages/happy-dom/src/index.ts
+++ b/packages/happy-dom/src/index.ts
@@ -82,6 +82,8 @@ import HTMLVideoElement from './nodes/html-video-element/HTMLVideoElement';
 import IHTMLVideoElement from './nodes/html-video-element/IHTMLVideoElement';
 import HTMLBaseElement from './nodes/html-base-element/HTMLBaseElement';
 import IHTMLBaseElement from './nodes/html-base-element/IHTMLBaseElement';
+import HTMLIFrameElement from './nodes/html-iframe-element/HTMLIFrameElement';
+import IHTMLIFrameElement from './nodes/html-iframe-element/IHTMLIFrameElement';
 import SVGElement from './nodes/svg-element/SVGElement';
 import ISVGElement from './nodes/svg-element/ISVGElement';
 import SVGGraphicsElement from './nodes/svg-element/SVGGraphicsElement';
@@ -211,6 +213,8 @@ export {
 	IHTMLVideoElement,
 	HTMLBaseElement,
 	IHTMLBaseElement,
+	HTMLIFrameElement,
+	IHTMLIFrameElement,
 	SVGElement,
 	ISVGElement,
 	SVGGraphicsElement,
diff --git a/packages/happy-dom/src/nodes/html-iframe-element/HTMLIframeElement.ts b/packages/happy-dom/src/nodes/html-iframe-element/HTMLIFrameElement.ts
similarity index 89%
rename from packages/happy-dom/src/nodes/html-iframe-element/HTMLIframeElement.ts
rename to packages/happy-dom/src/nodes/html-iframe-element/HTMLIFrameElement.ts
index 566a6a2b..baf24da8 100644
--- a/packages/happy-dom/src/nodes/html-iframe-element/HTMLIframeElement.ts
+++ b/packages/happy-dom/src/nodes/html-iframe-element/HTMLIFrameElement.ts
@@ -6,22 +6,22 @@ import Window from '../../window/Window';
 import IDocument from '../document/IDocument';
 import HTMLElement from '../html-element/HTMLElement';
 import INode from '../node/INode';
-import IframeCrossOriginWindow from './IframeCrossOriginWindow';
-import IHTMLIframeElement from './IHTMLIframeElement';
+import IFrameCrossOriginWindow from './IFrameCrossOriginWindow';
+import IHTMLIFrameElement from './IHTMLIFrameElement';
 
 /**
  * HTML Iframe Element.
  *
  * Reference:
- * https://developer.mozilla.org/en-US/docs/Web/API/HTMLIframeElement.
+ * https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement.
  */
-export default class HTMLIframeElement extends HTMLElement implements IHTMLIframeElement {
+export default class HTMLIFrameElement extends HTMLElement implements IHTMLIFrameElement {
 	// Events
 	public onload: (event: Event) => void | null = null;
 	public onerror: (event: Event) => void | null = null;
 
 	// Private
-	#contentWindow: IWindow | IframeCrossOriginWindow | null = null;
+	#contentWindow: IWindow | IFrameCrossOriginWindow | null = null;
 
 	/**
 	 * Returns source.
@@ -163,7 +163,7 @@ export default class HTMLIframeElement extends HTMLElement implements IHTMLIfram
 	 *
 	 * @returns Content window.
 	 */
-	public get contentWindow(): IWindow | IframeCrossOriginWindow | null {
+	public get contentWindow(): IWindow | IFrameCrossOriginWindow | null {
 		return this.#contentWindow || null;
 	}
 
@@ -241,7 +241,7 @@ export default class HTMLIframeElement extends HTMLElement implements IHTMLIfram
 							.text()
 							.then((text) => {
 								this.#contentWindow = isCORS
-									? new IframeCrossOriginWindow(this.ownerDocument.defaultView, contentWindow)
+									? new IFrameCrossOriginWindow(this.ownerDocument.defaultView, contentWindow)
 									: contentWindow;
 								contentWindow.document.write(text);
 								this.dispatchEvent(new Event('load'));
@@ -260,7 +260,7 @@ export default class HTMLIframeElement extends HTMLElement implements IHTMLIfram
 	 * @param [deep=false] "true" to clone deep.
 	 * @returns Cloned node.
 	 */
-	public cloneNode(deep = false): IHTMLIframeElement {
-		return <IHTMLIframeElement>super.cloneNode(deep);
+	public cloneNode(deep = false): IHTMLIFrameElement {
+		return <IHTMLIFrameElement>super.cloneNode(deep);
 	}
 }
diff --git a/packages/happy-dom/src/nodes/html-iframe-element/IframeCrossOriginWindow.ts b/packages/happy-dom/src/nodes/html-iframe-element/IFrameCrossOriginWindow.ts
similarity index 60%
rename from packages/happy-dom/src/nodes/html-iframe-element/IframeCrossOriginWindow.ts
rename to packages/happy-dom/src/nodes/html-iframe-element/IFrameCrossOriginWindow.ts
index 77821503..40ce7ddf 100644
--- a/packages/happy-dom/src/nodes/html-iframe-element/IframeCrossOriginWindow.ts
+++ b/packages/happy-dom/src/nodes/html-iframe-element/IFrameCrossOriginWindow.ts
@@ -1,15 +1,18 @@
-import Location from '../../location/Location';
 import EventTarget from '../../event/EventTarget';
 import IWindow from '../../window/IWindow';
+import DOMException from '../../exception/DOMException';
+import DOMExceptionNameEnum from '../../exception/DOMExceptionNameEnum';
+import Location from '../../location/Location';
 
 /**
  * Browser window with limited access due to CORS restrictions in iframes.
  */
-export default class IframeCrossOriginWindow extends EventTarget {
+export default class IFrameCrossOriginWindow extends EventTarget {
 	public readonly self = this;
 	public readonly window = this;
 	public readonly parent: IWindow;
 	public readonly top: IWindow;
+	public readonly location: Location;
 
 	private _targetWindow: IWindow;
 
@@ -24,18 +27,26 @@ export default class IframeCrossOriginWindow extends EventTarget {
 
 		this.parent = parent;
 		this.top = parent;
+		this.location = <Location>new Proxy(
+			{},
+			{
+				get: () => {
+					throw new DOMException(
+						`Blocked a frame with origin "${this.parent.location.origin}" from accessing a cross-origin frame.`,
+						DOMExceptionNameEnum.securityError
+					);
+				},
+				set: () => {
+					throw new DOMException(
+						`Blocked a frame with origin "${this.parent.location.origin}" from accessing a cross-origin frame.`,
+						DOMExceptionNameEnum.securityError
+					);
+				}
+			}
+		);
 		this._targetWindow = target;
 	}
 
-	/**
-	 * Returns location.
-	 *
-	 * @returns Location.
-	 */
-	public get location(): Location {
-		return this._targetWindow.location;
-	}
-
 	/**
 	 * Safely enables cross-origin communication between Window objects; e.g., between a page and a pop-up that it spawned, or between a page and an iframe embedded within it.
 	 *
diff --git a/packages/happy-dom/src/nodes/html-iframe-element/IHTMLIframeElement.ts b/packages/happy-dom/src/nodes/html-iframe-element/IHTMLIFrameElement.ts
similarity index 68%
rename from packages/happy-dom/src/nodes/html-iframe-element/IHTMLIframeElement.ts
rename to packages/happy-dom/src/nodes/html-iframe-element/IHTMLIFrameElement.ts
index 1c326cd4..5b9c111d 100644
--- a/packages/happy-dom/src/nodes/html-iframe-element/IHTMLIframeElement.ts
+++ b/packages/happy-dom/src/nodes/html-iframe-element/IHTMLIFrameElement.ts
@@ -2,15 +2,15 @@ import Event from '../../event/Event';
 import IWindow from '../../window/IWindow';
 import IDocument from '../document/IDocument';
 import IHTMLElement from '../html-element/IHTMLElement';
-import IframeCrossOriginWindow from './IframeCrossOriginWindow';
+import IFrameCrossOriginWindow from './IFrameCrossOriginWindow';
 
 /**
  * HTML Iframe Element.
  *
  * Reference:
- * https://developer.mozilla.org/en-US/docs/Web/API/HTMLIframeElement.
+ * https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement.
  */
-export default interface IHTMLIframeElement extends IHTMLElement {
+export default interface IHTMLIFrameElement extends IHTMLElement {
 	src: string | null;
 	allow: string | null;
 	height: string | null;
@@ -19,7 +19,7 @@ export default interface IHTMLIframeElement extends IHTMLElement {
 	sandbox: string | null;
 	srcdoc: string | null;
 	readonly contentDocument: IDocument | null;
-	readonly contentWindow: IWindow | IframeCrossOriginWindow | null;
+	readonly contentWindow: IWindow | IFrameCrossOriginWindow | null;
 
 	// Events
 	onload: (event: Event) => void | null;
diff --git a/packages/happy-dom/src/window/IWindow.ts b/packages/happy-dom/src/window/IWindow.ts
index 20820b2f..9d75971a 100644
--- a/packages/happy-dom/src/window/IWindow.ts
+++ b/packages/happy-dom/src/window/IWindow.ts
@@ -24,7 +24,7 @@ import HTMLMediaElement from '../nodes/html-media-element/HTMLMediaElement';
 import HTMLAudioElement from '../nodes/html-audio-element/HTMLAudioElement';
 import HTMLVideoElement from '../nodes/html-video-element/HTMLVideoElement';
 import HTMLBaseElement from '../nodes/html-base-element/HTMLBaseElement';
-import HTMLIframeElement from '../nodes/html-iframe-element/HTMLIframeElement';
+import HTMLIFrameElement from '../nodes/html-iframe-element/HTMLIFrameElement';
 import SVGSVGElement from '../nodes/svg-element/SVGSVGElement';
 import SVGElement from '../nodes/svg-element/SVGElement';
 import HTMLScriptElement from '../nodes/html-script-element/HTMLScriptElement';
@@ -145,7 +145,7 @@ export default interface IWindow extends IEventTarget, NodeJS.Global {
 	readonly HTMLAudioElement: typeof HTMLAudioElement;
 	readonly HTMLVideoElement: typeof HTMLVideoElement;
 	readonly HTMLBaseElement: typeof HTMLBaseElement;
-	readonly HTMLIframeElement: typeof HTMLIframeElement;
+	readonly HTMLIFrameElement: typeof HTMLIFrameElement;
 	readonly HTMLDialogElement: typeof HTMLDialogElement;
 	readonly Attr: typeof Attr;
 	readonly NamedNodeMap: typeof NamedNodeMap;
diff --git a/packages/happy-dom/src/window/Window.ts b/packages/happy-dom/src/window/Window.ts
index 5c7ce8f1..10f65d08 100644
--- a/packages/happy-dom/src/window/Window.ts
+++ b/packages/happy-dom/src/window/Window.ts
@@ -25,7 +25,7 @@ import HTMLMediaElement from '../nodes/html-media-element/HTMLMediaElement';
 import HTMLAudioElement from '../nodes/html-audio-element/HTMLAudioElement';
 import HTMLVideoElement from '../nodes/html-video-element/HTMLVideoElement';
 import HTMLBaseElement from '../nodes/html-base-element/HTMLBaseElement';
-import HTMLIframeElement from '../nodes/html-iframe-element/HTMLIframeElement';
+import HTMLIFrameElement from '../nodes/html-iframe-element/HTMLIFrameElement';
 import HTMLDialogElement from '../nodes/html-dialog-element/HTMLDialogElement';
 import SVGSVGElement from '../nodes/svg-element/SVGSVGElement';
 import SVGElement from '../nodes/svg-element/SVGElement';
@@ -188,7 +188,7 @@ export default class Window extends EventTarget implements IWindow {
 	public readonly HTMLAudioElement = HTMLAudioElement;
 	public readonly HTMLVideoElement = HTMLVideoElement;
 	public readonly HTMLBaseElement = HTMLBaseElement;
-	public readonly HTMLIframeElement = HTMLIframeElement;
+	public readonly HTMLIFrameElement = HTMLIFrameElement;
 	public readonly HTMLDialogElement = HTMLDialogElement;
 	public readonly Attr = Attr;
 	public readonly NamedNodeMap = NamedNodeMap;


Test patch:
diff --git a/packages/happy-dom/test/nodes/html-iframe-element/HTMLIframeElement.test.ts b/packages/happy-dom/test/nodes/html-iframe-element/HTMLIFrameElement.test.ts
similarity index 84%
rename from packages/happy-dom/test/nodes/html-iframe-element/HTMLIframeElement.test.ts
rename to packages/happy-dom/test/nodes/html-iframe-element/HTMLIFrameElement.test.ts
index bae297f1..bd4d0b20 100644
--- a/packages/happy-dom/test/nodes/html-iframe-element/HTMLIframeElement.test.ts
+++ b/packages/happy-dom/test/nodes/html-iframe-element/HTMLIFrameElement.test.ts
@@ -1,26 +1,28 @@
 import Window from '../../../src/window/Window';
 import IWindow from '../../../src/window/IWindow';
 import IDocument from '../../../src/nodes/document/IDocument';
-import IHTMLIframeElement from '../../../src/nodes/html-iframe-element/IHTMLIframeElement';
+import IHTMLIFrameElement from '../../../src/nodes/html-iframe-element/IHTMLIFrameElement';
 import IResponse from '../../../src/fetch/IResponse';
 import ErrorEvent from '../../../src/event/events/ErrorEvent';
-import IframeCrossOriginWindow from '../../../src/nodes/html-iframe-element/IframeCrossOriginWindow';
+import IFrameCrossOriginWindow from '../../../src/nodes/html-iframe-element/IFrameCrossOriginWindow';
 import MessageEvent from '../../../src/event/events/MessageEvent';
+import DOMExceptionNameEnum from '../../../src/exception/DOMExceptionNameEnum';
+import DOMException from '../../../src/exception/DOMException';
 
-describe('HTMLIframeElement', () => {
+describe('HTMLIFrameElement', () => {
 	let window: IWindow;
 	let document: IDocument;
-	let element: IHTMLIframeElement;
+	let element: IHTMLIFrameElement;
 
 	beforeEach(() => {
 		window = new Window();
 		document = window.document;
-		element = <IHTMLIframeElement>document.createElement('iframe');
+		element = <IHTMLIFrameElement>document.createElement('iframe');
 	});
 
 	describe('Object.prototype.toString', () => {
-		it('Returns `[object HTMLIframeElement]`', () => {
-			expect(Object.prototype.toString.call(element)).toBe('[object HTMLIframeElement]');
+		it('Returns `[object HTMLIFrameElement]`', () => {
+			expect(Object.prototype.toString.call(element)).toBe('[object HTMLIFrameElement]');
 		});
 	});
 
@@ -82,7 +84,7 @@ describe('HTMLIframeElement', () => {
 			document.body.appendChild(element);
 		});
 
-		it('Returns instance of IframeCrossOriginWindow for URL with different origin.', (done) => {
+		it('Returns instance of IFrameCrossOriginWindow for URL with different origin.', (done) => {
 			const iframeOrigin = 'https://other.origin.com';
 			const iframeSrc = iframeOrigin + '/iframe.html';
 			const documentOrigin = 'https://localhost:8080';
@@ -102,8 +104,13 @@ describe('HTMLIframeElement', () => {
 				const message = 'test';
 				let triggeredEvent: MessageEvent | null = null;
 				expect(fetchedURL).toBe(iframeSrc);
-				expect(element.contentWindow instanceof IframeCrossOriginWindow).toBe(true);
-				expect(element.contentWindow.location.href).toBe(iframeSrc);
+				expect(element.contentWindow instanceof IFrameCrossOriginWindow).toBe(true);
+				expect(() => element.contentWindow.location.href).toThrowError(
+					new DOMException(
+						`Blocked a frame with origin "${documentOrigin}" from accessing a cross-origin frame.`,
+						DOMExceptionNameEnum.securityError
+					)
+				);
 				expect(element.contentWindow.self === element.contentWindow).toBe(true);
 				expect(element.contentWindow.window === element.contentWindow).toBe(true);
 				expect(element.contentWindow.parent === window).toBe(true);