Skip to content

Commit 2a5d83a

Browse files
authored
chore: introduce Page.viewportSizeChanged event (#35994)
1 parent 6e8c67a commit 2a5d83a

File tree

12 files changed

+54
-29
lines changed

12 files changed

+54
-29
lines changed

packages/playwright-core/src/client/page.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ export class Page extends ChannelOwner<channels.PageChannel> implements api.Page
8484
_workers = new Set<Worker>();
8585
private _closed = false;
8686
readonly _closedOrCrashedScope = new LongStandingScope();
87-
private _viewportSize: Size | null;
87+
private _viewportSize: Size | undefined;
8888
_routes: RouteHandler[] = [];
8989
_webSocketRoutes: WebSocketRouteHandler[] = [];
9090

@@ -130,7 +130,7 @@ export class Page extends ChannelOwner<channels.PageChannel> implements api.Page
130130
this._mainFrame = Frame.from(initializer.mainFrame);
131131
this._mainFrame._page = this;
132132
this._frames.add(this._mainFrame);
133-
this._viewportSize = initializer.viewportSize || null;
133+
this._viewportSize = initializer.viewportSize;
134134
this._closed = initializer.isClosed;
135135
this._opener = Page.fromNullable(initializer.opener);
136136

@@ -151,6 +151,7 @@ export class Page extends ChannelOwner<channels.PageChannel> implements api.Page
151151
const artifactObject = Artifact.from(artifact);
152152
this._forceVideo()._artifactReady(artifactObject);
153153
});
154+
this._channel.on('viewportSizeChanged', ({ viewportSize }) => this._viewportSize = viewportSize);
154155
this._channel.on('webSocket', ({ webSocket }) => this.emit(Events.Page.WebSocket, WebSocket.from(webSocket)));
155156
this._channel.on('worker', ({ worker }) => this._onWorker(Worker.from(worker)));
156157

@@ -506,7 +507,7 @@ export class Page extends ChannelOwner<channels.PageChannel> implements api.Page
506507
}
507508

508509
viewportSize(): Size | null {
509-
return this._viewportSize;
510+
return this._viewportSize || null;
510511
}
511512

512513
async evaluate<R, Arg>(pageFunction: structs.PageFunction<Arg, R>, arg?: Arg): Promise<R> {

packages/playwright-core/src/protocol/validator.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,6 +1122,12 @@ scheme.PageDownloadEvent = tObject({
11221122
suggestedFilename: tString,
11231123
artifact: tChannel(['Artifact']),
11241124
});
1125+
scheme.PageViewportSizeChangedEvent = tObject({
1126+
viewportSize: tOptional(tObject({
1127+
width: tNumber,
1128+
height: tNumber,
1129+
})),
1130+
});
11251131
scheme.PageFileChooserEvent = tObject({
11261132
element: tChannel(['ElementHandle']),
11271133
isMultiple: tBoolean,

packages/playwright-core/src/server/bidi/bidiPage.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -268,10 +268,10 @@ export class BidiPage implements PageDelegate {
268268

269269
async updateEmulatedViewportSize(): Promise<void> {
270270
const options = this._browserContext._options;
271-
const deviceSize = this._page.emulatedSize();
272-
if (deviceSize === null)
271+
const emulatedSize = this._page.emulatedSize();
272+
if (!emulatedSize)
273273
return;
274-
const viewportSize = deviceSize.viewport;
274+
const viewportSize = emulatedSize.viewport;
275275
await this._session.send('browsingContext.setViewport', {
276276
context: this._session.sessionId,
277277
viewport: {

packages/playwright-core/src/server/chromium/crPage.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ export class CRPage implements PageDelegate {
108108
const features = opener._nextWindowOpenPopupFeatures.shift() || [];
109109
const viewportSize = helper.getViewportSizeFromWindowFeatures(features);
110110
if (viewportSize)
111-
this._page.setEmulatedSize({ viewport: viewportSize, screen: viewportSize });
111+
this._page.setEmulatedSizeFromWindowOpen({ viewport: viewportSize, screen: viewportSize });
112112
}
113113

114114
const createdEvent = this._isBackgroundPage ? CRBrowserContext.CREvents.BackgroundPage : BrowserContext.Events.Page;
@@ -953,7 +953,7 @@ class FrameSession {
953953
assert(this._isMainFrame());
954954
const options = this._crPage._browserContext._options;
955955
const emulatedSize = this._page.emulatedSize();
956-
if (emulatedSize === null)
956+
if (!emulatedSize)
957957
return;
958958
const viewportSize = emulatedSize.viewport;
959959
const screenSize = emulatedSize.screen;

packages/playwright-core/src/server/dispatchers/pageDispatcher.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ export class PageDispatcher extends Dispatcher<Page, channels.PageChannel, Brows
6666

6767
super(parentScope, page, 'Page', {
6868
mainFrame,
69-
viewportSize: page.viewportSize() || undefined,
69+
viewportSize: page.emulatedSize()?.viewport,
7070
isClosed: page.isClosed(),
7171
opener: PageDispatcher.fromNullable(parentScope, page.opener())
7272
});
@@ -83,6 +83,7 @@ export class PageDispatcher extends Dispatcher<Page, channels.PageChannel, Brows
8383
// Artifact can outlive the page, so bind to the context scope.
8484
this._dispatchEvent('download', { url: download.url, suggestedFilename: download.suggestedFilename(), artifact: ArtifactDispatcher.from(parentScope, download.artifact) });
8585
});
86+
this.addObjectListener(Page.Events.EmulatedSizeChanged, () => this._dispatchEvent('viewportSizeChanged', { viewportSize: page.emulatedSize()?.viewport }));
8687
this.addObjectListener(Page.Events.FileChooser, (fileChooser: FileChooser) => this._dispatchEvent('fileChooser', {
8788
element: ElementHandleDispatcher.from(mainFrame, fileChooser.element()),
8889
isMultiple: fileChooser.isMultiple()

packages/playwright-core/src/server/firefox/ffPage.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ export class FFPage implements PageDelegate {
334334
}
335335

336336
async updateEmulatedViewportSize(): Promise<void> {
337-
const viewportSize = this._page.viewportSize();
337+
const viewportSize = this._page.emulatedSize()?.viewport ?? null;
338338
await this._session.send('Page.setViewportSize', { viewportSize });
339339
}
340340

packages/playwright-core/src/server/page.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ export class Page extends SdkObject {
125125
Close: 'close',
126126
Crash: 'crash',
127127
Download: 'download',
128+
EmulatedSizeChanged: 'emulatedsizechanged',
128129
FileChooser: 'filechooser',
129130
FrameAttached: 'frameattached',
130131
FrameDetached: 'framedetached',
@@ -546,23 +547,24 @@ export class Page extends SdkObject {
546547
}
547548

548549
async setViewportSize(viewportSize: types.Size) {
549-
this._emulatedSize = { viewport: { ...viewportSize }, screen: { ...viewportSize } };
550+
this._setEmulatedSize({ viewport: { ...viewportSize }, screen: { ...viewportSize } });
550551
await this.delegate.updateEmulatedViewportSize();
551552
}
552553

553-
viewportSize(): types.Size | null {
554-
return this.emulatedSize()?.viewport || null;
554+
setEmulatedSizeFromWindowOpen(emulatedSize: EmulatedSize) {
555+
this._setEmulatedSize(emulatedSize);
555556
}
556557

557-
setEmulatedSize(emulatedSize: EmulatedSize) {
558+
private _setEmulatedSize(emulatedSize: EmulatedSize) {
558559
this._emulatedSize = emulatedSize;
560+
this.emit(Page.Events.EmulatedSizeChanged);
559561
}
560562

561-
emulatedSize(): EmulatedSize | null {
563+
emulatedSize(): EmulatedSize | undefined {
562564
if (this._emulatedSize)
563565
return this._emulatedSize;
564566
const contextOptions = this.browserContext._options;
565-
return contextOptions.viewport ? { viewport: contextOptions.viewport, screen: contextOptions.screen || contextOptions.viewport } : null;
567+
return contextOptions.viewport ? { viewport: contextOptions.viewport, screen: contextOptions.screen || contextOptions.viewport } : undefined;
566568
}
567569

568570
async bringToFront(): Promise<void> {

packages/playwright-core/src/server/screenshotter.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -173,12 +173,11 @@ export class Screenshotter {
173173
this._queue = new TaskQueue();
174174
}
175175

176-
private async _originalViewportSize(progress: Progress): Promise<{ viewportSize: types.Size, originalViewportSize: types.Size | null }> {
177-
const originalViewportSize = this._page.viewportSize();
178-
let viewportSize = originalViewportSize;
176+
private async _originalViewportSize(progress: Progress): Promise<types.Size> {
177+
let viewportSize = this._page.emulatedSize()?.viewport;
179178
if (!viewportSize)
180179
viewportSize = await this._page.mainFrame().waitForFunctionValueInUtility(progress, () => ({ width: window.innerWidth, height: window.innerHeight }));
181-
return { viewportSize, originalViewportSize };
180+
return viewportSize;
182181
}
183182

184183
private async _fullPageSize(progress: Progress): Promise<types.Size> {
@@ -205,7 +204,7 @@ export class Screenshotter {
205204
const format = validateScreenshotOptions(options);
206205
return this._queue.postTask(async () => {
207206
progress.log('taking page screenshot');
208-
const { viewportSize } = await this._originalViewportSize(progress);
207+
const viewportSize = await this._originalViewportSize(progress);
209208
await this._preparePageForScreenshot(progress, this._page.mainFrame(), options.style, options.caret !== 'initial', options.animations === 'disabled');
210209
progress.throwIfAborted(); // Avoid restoring after failure - should be done by cleanup.
211210

@@ -233,7 +232,7 @@ export class Screenshotter {
233232
const format = validateScreenshotOptions(options);
234233
return this._queue.postTask(async () => {
235234
progress.log('taking element screenshot');
236-
const { viewportSize } = await this._originalViewportSize(progress);
235+
const viewportSize = await this._originalViewportSize(progress);
237236

238237
await this._preparePageForScreenshot(progress, handle._frame, options.style, options.caret !== 'initial', options.animations === 'disabled');
239238
progress.throwIfAborted(); // Do not do extra work.

packages/playwright-core/src/server/webkit/wkBrowser.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ export class WKBrowserContext extends BrowserContext {
358358
await this._browser._browserSession.send('Playwright.cancelDownload', { uuid });
359359
}
360360

361-
_validateEmulatedViewport(viewportSize?: types.Size | null) {
361+
_validateEmulatedViewport(viewportSize: types.Size | undefined) {
362362
if (!viewportSize)
363363
return;
364364
if (process.platform === 'win32' && this._browser.options.headful && (viewportSize.width < 250 || viewportSize.height < 240))

packages/playwright-core/src/server/webkit/wkPage.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ export class WKPage implements PageDelegate {
109109
const viewportSize = helper.getViewportSizeFromWindowFeatures(opener._nextWindowOpenPopupFeatures);
110110
opener._nextWindowOpenPopupFeatures = undefined;
111111
if (viewportSize)
112-
this._page.setEmulatedSize({ viewport: viewportSize, screen: viewportSize });
112+
this._page.setEmulatedSizeFromWindowOpen({ viewport: viewportSize, screen: viewportSize });
113113
}
114114
}
115115

@@ -677,7 +677,7 @@ export class WKPage implements PageDelegate {
677677
}
678678

679679
async updateEmulatedViewportSize(): Promise<void> {
680-
this._browserContext._validateEmulatedViewport(this._page.viewportSize());
680+
this._browserContext._validateEmulatedViewport(this._page.emulatedSize()?.viewport);
681681
await this._updateViewport();
682682
}
683683

@@ -694,11 +694,11 @@ export class WKPage implements PageDelegate {
694694

695695
async _updateViewport(): Promise<void> {
696696
const options = this._browserContext._options;
697-
const deviceSize = this._page.emulatedSize();
698-
if (deviceSize === null)
697+
const emulatedSize = this._page.emulatedSize();
698+
if (!emulatedSize)
699699
return;
700-
const viewportSize = deviceSize.viewport;
701-
const screenSize = deviceSize.screen;
700+
const viewportSize = emulatedSize.viewport;
701+
const screenSize = emulatedSize.screen;
702702
const promises: Promise<any>[] = [
703703
this._pageProxySession.send('Emulation.setDeviceMetricsOverride', {
704704
width: viewportSize.width,

0 commit comments

Comments
 (0)