Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#466@trivial: Adds support for BrowserFrame.viewport. #1197

Merged
merged 1 commit into from
Jan 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/happy-dom/src/PropertySymbol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,6 @@ export const width = Symbol('width');
export const window = Symbol('window');
export const windowResizeListener = Symbol('windowResizeListener');
export const mutationObservers = Symbol('mutationObservers');
export const openerFrame = Symbol('openerFrame');
export const openerWindow = Symbol('openerFrame');
export const popup = Symbol('popup');
6 changes: 2 additions & 4 deletions packages/happy-dom/src/browser/Browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import IOptionalBrowserSettings from './types/IOptionalBrowserSettings.js';
import BrowserSettingsFactory from './BrowserSettingsFactory.js';
import BrowserPage from './BrowserPage.js';
import IBrowser from './types/IBrowser.js';
import BrowserFrame from './BrowserFrame.js';

/**
* Browser.
Expand Down Expand Up @@ -94,13 +93,12 @@ export default class Browser implements IBrowser {
/**
* Creates a new page.
*
* @param [opener] Opener.
* @returns Page.
*/
public newPage(opener?: BrowserFrame): BrowserPage {
public newPage(): BrowserPage {
if (this.contexts.length === 0) {
throw new Error('No default context. The browser has been closed.');
}
return this.contexts[0].newPage(opener);
return this.contexts[0].newPage();
}
}
5 changes: 1 addition & 4 deletions packages/happy-dom/src/browser/BrowserContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import ICookieContainer from '../cookie/types/ICookieContainer.js';
import ResponseCache from '../fetch/cache/response/ResponseCache.js';
import IResponseCache from '../fetch/cache/response/IResponseCache.js';
import Browser from './Browser.js';
import BrowserFrame from './BrowserFrame.js';
import BrowserPage from './BrowserPage.js';
import IBrowserContext from './types/IBrowserContext.js';
import IPreflightResponseCache from '../fetch/cache/preflight/IPreflightResponseCache.js';
Expand Down Expand Up @@ -80,12 +79,10 @@ export default class BrowserContext implements IBrowserContext {
/**
* Creates a new page.
*
* @param [opener] Opener.
* @returns Page.
*/
public newPage(opener?: BrowserFrame): BrowserPage {
public newPage(): BrowserPage {
const page = new BrowserPage(this);
(<BrowserFrame | null>(<unknown>page.mainFrame.opener)) = opener || null;
this.pages.push(page);
return page;
}
Expand Down
6 changes: 5 additions & 1 deletion packages/happy-dom/src/browser/BrowserFrame.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import * as PropertySymbol from '../PropertySymbol.js';
import AsyncTaskManager from '../async-task-manager/AsyncTaskManager.js';
import IBrowserFrame from './types/IBrowserFrame.js';
import BrowserWindow from '../window/BrowserWindow.js';
import IBrowserWindow from '../window/IBrowserWindow.js';
import ICrossOriginBrowserWindow from '../window/ICrossOriginBrowserWindow.js';
import Location from '../location/Location.js';
import IResponse from '../fetch/types/IResponse.js';
import IGoToOptions from './types/IGoToOptions.js';
Expand All @@ -21,12 +23,14 @@ import IDocument from '../nodes/document/IDocument.js';
export default class BrowserFrame implements IBrowserFrame {
public readonly childFrames: BrowserFrame[] = [];
public readonly parentFrame: BrowserFrame | null = null;
public readonly opener: BrowserFrame | null = null;
public readonly page: BrowserPage;
public readonly window: BrowserWindow;
public [PropertySymbol.asyncTaskManager] = new AsyncTaskManager();
public [PropertySymbol.exceptionObserver]: BrowserFrameExceptionObserver | null = null;
public [PropertySymbol.listeners]: { navigation: Array<() => void> } = { navigation: [] };
public [PropertySymbol.openerFrame]: IBrowserFrame | null = null;
public [PropertySymbol.openerWindow]: IBrowserWindow | ICrossOriginBrowserWindow | null = null;
public [PropertySymbol.popup] = false;

/**
* Constructor.
Expand Down
18 changes: 15 additions & 3 deletions packages/happy-dom/src/browser/BrowserPage.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import VirtualConsolePrinter from '../console/VirtualConsolePrinter.js';
import IBrowserPageViewport from './types/IBrowserPageViewport.js';
import BrowserFrame from './BrowserFrame.js';
import BrowserContext from './BrowserContext.js';
import VirtualConsole from '../console/VirtualConsole.js';
Expand All @@ -9,6 +8,10 @@ import { Script } from 'vm';
import IGoToOptions from './types/IGoToOptions.js';
import IResponse from '../fetch/types/IResponse.js';
import IReloadOptions from './types/IReloadOptions.js';
import IBrowserPageViewport from './types/IBrowserPageViewport.js';
import IOptionalBrowserPageViewport from './types/IOptionalBrowserPageViewport.js';
import DefaultBrowserPageViewport from './DefaultBrowserPageViewport.js';
import Event from '../event/Event.js';

/**
* Browser page.
Expand All @@ -18,6 +21,7 @@ export default class BrowserPage implements IBrowserPage {
public readonly mainFrame: BrowserFrame;
public readonly context: BrowserContext;
public readonly console: Console;
public readonly viewport: IBrowserPageViewport = Object.assign({}, DefaultBrowserPageViewport);

/**
* Constructor.
Expand Down Expand Up @@ -114,8 +118,16 @@ export default class BrowserPage implements IBrowserPage {
*
* @param viewport Viewport.
*/
public setViewport(viewport: IBrowserPageViewport): void {
BrowserPageUtility.setViewport(this, viewport);
public setViewport(viewport: IOptionalBrowserPageViewport): void {
const previousViewport = Object.assign({}, this.viewport);
Object.assign(this.viewport, viewport);
if (
previousViewport.width !== this.viewport.width ||
previousViewport.height !== this.viewport.height ||
previousViewport.devicePixelRatio !== this.viewport.devicePixelRatio
) {
this.mainFrame.window.dispatchEvent(new Event('resize'));
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import IBrowserPageViewport from './types/IBrowserPageViewport.js';

export default <IBrowserPageViewport>{
width: 1024,
height: 768,
devicePixelRatio: 1
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import BrowserSettingsFactory from '../BrowserSettingsFactory.js';
import DetachedBrowserPage from './DetachedBrowserPage.js';
import IBrowser from '../types/IBrowser.js';
import IBrowserFrame from '../types/IBrowserFrame.js';
import DetachedBrowserFrame from './DetachedBrowserFrame.js';
import IBrowserWindow from '../../window/IBrowserWindow.js';

/**
Expand Down Expand Up @@ -101,13 +100,12 @@ export default class DetachedBrowser implements IBrowser {
/**
* Creates a new page.
*
* @param [opener] Opener.
* @returns Page.
*/
public newPage(opener?: DetachedBrowserFrame): DetachedBrowserPage {
public newPage(): DetachedBrowserPage {
if (this.contexts.length === 0) {
throw new Error('No default context. The browser has been closed.');
}
return this.contexts[0].newPage(opener);
return this.contexts[0].newPage();
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import DetachedBrowser from './DetachedBrowser.js';
import DetachedBrowserPage from './DetachedBrowserPage.js';
import IBrowserContext from '../types/IBrowserContext.js';
import DetachedBrowserFrame from './DetachedBrowserFrame.js';
import ICookieContainer from '../../cookie/types/ICookieContainer.js';
import CookieContainer from '../../cookie/CookieContainer.js';
import ResponseCache from '../../fetch/cache/response/ResponseCache.js';
Expand Down Expand Up @@ -85,9 +84,8 @@ export default class DetachedBrowserContext implements IBrowserContext {
* @param [opener] Opener.
* @returns Page.
*/
public newPage(opener?: DetachedBrowserFrame): DetachedBrowserPage {
public newPage(): DetachedBrowserPage {
const page = new DetachedBrowserPage(this);
(<DetachedBrowserFrame | null>(<unknown>page.mainFrame.opener)) = opener || null;
this.pages.push(page);
return page;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,23 @@ import IReloadOptions from '../types/IReloadOptions.js';
import BrowserErrorCaptureEnum from '../enums/BrowserErrorCaptureEnum.js';
import BrowserFrameExceptionObserver from '../utilities/BrowserFrameExceptionObserver.js';
import IDocument from '../../nodes/document/IDocument.js';
import ICrossOriginBrowserWindow from '../../window/ICrossOriginBrowserWindow.js';

/**
* Browser frame used when constructing a Window instance without a browser.
*/
export default class DetachedBrowserFrame implements IBrowserFrame {
public readonly childFrames: DetachedBrowserFrame[] = [];
public readonly parentFrame: DetachedBrowserFrame | null = null;
public readonly opener: DetachedBrowserFrame | null = null;
public readonly page: DetachedBrowserPage;
// Needs to be injected from the outside when the browser frame is constructed.
public window: IBrowserWindow;
public [PropertySymbol.asyncTaskManager] = new AsyncTaskManager();
public [PropertySymbol.exceptionObserver]: BrowserFrameExceptionObserver | null = null;
public [PropertySymbol.listeners]: { navigation: Array<() => void> } = { navigation: [] };
public [PropertySymbol.openerFrame]: IBrowserFrame | null = null;
public [PropertySymbol.openerWindow]: IBrowserWindow | ICrossOriginBrowserWindow | null = null;
public [PropertySymbol.popup] = false;

/**
* Constructor.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import VirtualConsolePrinter from '../../console/VirtualConsolePrinter.js';
import IBrowserPageViewport from '../types/IBrowserPageViewport.js';
import DetachedBrowserFrame from './DetachedBrowserFrame.js';
import DetachedBrowserContext from './DetachedBrowserContext.js';
import VirtualConsole from '../../console/VirtualConsole.js';
Expand All @@ -9,6 +8,10 @@ import IGoToOptions from '../types/IGoToOptions.js';
import IResponse from '../../fetch/types/IResponse.js';
import BrowserPageUtility from '../utilities/BrowserPageUtility.js';
import IReloadOptions from '../types/IReloadOptions.js';
import DefaultBrowserPageViewport from '../DefaultBrowserPageViewport.js';
import IOptionalBrowserPageViewport from '../types/IOptionalBrowserPageViewport.js';
import IBrowserPageViewport from '../types/IBrowserPageViewport.js';
import Event from '../../event/Event.js';

/**
* Detached browser page used when constructing a Window instance without a browser.
Expand All @@ -18,6 +21,7 @@ export default class DetachedBrowserPage implements IBrowserPage {
public readonly mainFrame: DetachedBrowserFrame;
public readonly context: DetachedBrowserContext;
public readonly console: Console;
public readonly viewport: IBrowserPageViewport = Object.assign({}, DefaultBrowserPageViewport);

/**
* Constructor.
Expand Down Expand Up @@ -126,8 +130,16 @@ export default class DetachedBrowserPage implements IBrowserPage {
*
* @param viewport Viewport.
*/
public setViewport(viewport: IBrowserPageViewport): void {
BrowserPageUtility.setViewport(this, viewport);
public setViewport(viewport: IOptionalBrowserPageViewport): void {
const previousViewport = Object.assign({}, this.viewport);
Object.assign(this.viewport, viewport);
if (
previousViewport.width !== this.viewport.width ||
previousViewport.height !== this.viewport.height ||
previousViewport.devicePixelRatio !== this.viewport.devicePixelRatio
) {
this.mainFrame.window.dispatchEvent(new Event('resize'));
}
}

/**
Expand Down
4 changes: 1 addition & 3 deletions packages/happy-dom/src/browser/types/IBrowser.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import IBrowserContext from './IBrowserContext.js';
import IBrowserFrame from './IBrowserFrame.js';
import IBrowserPage from './IBrowserPage.js';
import IBrowserSettings from './IBrowserSettings.js';

Expand Down Expand Up @@ -41,8 +40,7 @@ export default interface IBrowser {
/**
* Creates a new page.
*
* @param [opener] Opener.
* @returns Page.
*/
newPage(opener?: IBrowserFrame): IBrowserPage;
newPage(): IBrowserPage;
}
4 changes: 1 addition & 3 deletions packages/happy-dom/src/browser/types/IBrowserContext.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import ICookieContainer from '../../cookie/types/ICookieContainer.js';
import IResponseCache from '../../fetch/cache/response/IResponseCache.js';
import IBrowser from './IBrowser.js';
import IBrowserFrame from './IBrowserFrame.js';
import IBrowserPage from './IBrowserPage.js';
import IPreflightResponseCache from '../../fetch/cache/preflight/IPreflightResponseCache.js';

Expand Down Expand Up @@ -35,8 +34,7 @@ export default interface IBrowserContext {
/**
* Creates a new page.
*
* @param [opener] Opener.
* @returns Page.
*/
newPage(opener?: IBrowserFrame): IBrowserPage;
newPage(): IBrowserPage;
}
5 changes: 4 additions & 1 deletion packages/happy-dom/src/browser/types/IBrowserFrame.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ import IGoToOptions from './IGoToOptions.js';
import { Script } from 'vm';
import IReloadOptions from './IReloadOptions.js';
import BrowserFrameExceptionObserver from '../utilities/BrowserFrameExceptionObserver.js';
import ICrossOriginBrowserWindow from '../../window/ICrossOriginBrowserWindow.js';

/**
* Browser frame.
*/
export default interface IBrowserFrame {
readonly childFrames: IBrowserFrame[];
readonly parentFrame: IBrowserFrame | null;
readonly opener: IBrowserFrame | null;
readonly page: IBrowserPage;
readonly window: IBrowserWindow;
readonly document: IDocument;
Expand All @@ -24,6 +24,9 @@ export default interface IBrowserFrame {
[PropertySymbol.asyncTaskManager]: AsyncTaskManager;
[PropertySymbol.exceptionObserver]: BrowserFrameExceptionObserver | null;
[PropertySymbol.listeners]: { navigation: Array<() => void> };
[PropertySymbol.openerFrame]: IBrowserFrame | null;
[PropertySymbol.openerWindow]: IBrowserWindow | ICrossOriginBrowserWindow | null;
[PropertySymbol.popup]: boolean;

/**
* Returns a promise that is resolved when all resources has been loaded, fetch has completed, and all async tasks such as timers are complete.
Expand Down
6 changes: 4 additions & 2 deletions packages/happy-dom/src/browser/types/IBrowserPage.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import IBrowserPageViewport from './IBrowserPageViewport.js';
import IBrowserPageViewport from '../types/IBrowserPageViewport.js';
import VirtualConsolePrinter from '../../console/VirtualConsolePrinter.js';
import IBrowserFrame from './IBrowserFrame.js';
import IBrowserContext from './IBrowserContext.js';
import { Script } from 'vm';
import IGoToOptions from './IGoToOptions.js';
import IResponse from '../../fetch/types/IResponse.js';
import IReloadOptions from './IReloadOptions.js';
import IOptionalBrowserPageViewport from './IOptionalBrowserPageViewport.js';

/**
* Browser page.
Expand All @@ -16,6 +17,7 @@ export default interface IBrowserPage {
readonly context: IBrowserContext;
readonly console: Console;
readonly frames: IBrowserFrame[];
readonly viewport: IBrowserPageViewport;
content: string;
url: string;

Expand Down Expand Up @@ -49,7 +51,7 @@ export default interface IBrowserPage {
*
* @param viewport Viewport.
*/
setViewport(viewport: IBrowserPageViewport): void;
setViewport(viewport: IOptionalBrowserPageViewport): void;

/**
* Go to a page.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export default interface IBrowserPageViewport {
width?: number;
height?: number;
devicePixelRatio?: number;
width: number;
height: number;
devicePixelRatio: number;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export default interface IOptionalBrowserPageViewport {
width?: number;
height?: number;
devicePixelRatio?: number;
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ export default class BrowserFrameFactory {
frame.window[PropertySymbol.destroy]();
(<IBrowserPage | null>frame.page) = null;
(<IBrowserWindow | null>frame.window) = null;
(<IBrowserFrame | null>frame.opener) = null;
frame[PropertySymbol.openerFrame] = null;
frame[PropertySymbol.openerWindow] = null;

if (!frame.childFrames.length) {
return frame[PropertySymbol.asyncTaskManager]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import IBrowserFrame from '../types/IBrowserFrame.js';
import { URL } from 'url';
import BrowserNavigationCrossOriginPolicyEnum from '../enums/BrowserNavigationCrossOriginPolicyEnum.js';
import DetachedBrowserFrame from '../detached-browser/DetachedBrowserFrame.js';
import * as PropertySymbol from '../../PropertySymbol.js';

/**
* Browser frame validator.
Expand All @@ -18,10 +19,9 @@ export default class BrowserFrameValidator {
const settings = frame.page.context.browser.settings;
let fromURL = frame.page.mainFrame.window.location;

if (frame.opener) {
fromURL = frame.opener.window.location;
}
if (frame.parentFrame) {
if (frame[PropertySymbol.openerFrame]) {
fromURL = frame[PropertySymbol.openerFrame].window.location;
} else if (frame.parentFrame) {
fromURL = frame.parentFrame.window.location;
}

Expand Down Expand Up @@ -74,7 +74,7 @@ export default class BrowserFrameValidator {
return false;
}

if (settings.navigation.disableChildPageNavigation && !!frame.opener) {
if (settings.navigation.disableChildPageNavigation && !!frame[PropertySymbol.openerFrame]) {
return false;
}

Expand Down
Loading