chore: remove underscore from public members in page (#35820)

This commit is contained in:
Yury Semikhatsky 2025-04-30 18:57:59 -07:00 committed by GitHub
parent eda5a9efeb
commit baeb065e9e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
37 changed files with 410 additions and 428 deletions

View File

@ -16,7 +16,7 @@
import { eventsHelper } from '../utils/eventsHelper';
import { Browser } from '../browser';
import { BrowserContext, assertBrowserContextIsNotOwned, verifyGeolocation } from '../browserContext';
import { BrowserContext, verifyGeolocation } from '../browserContext';
import * as network from '../network';
import { BidiConnection } from './bidiConnection';
import { bidiBytesValueToString } from './bidiNetworkManager';
@ -151,12 +151,12 @@ export class BidiBrowser extends Browser {
if (event.parent) {
const parentFrameId = event.parent;
for (const page of this._bidiPages.values()) {
const parentFrame = page._page._frameManager.frame(parentFrameId);
const parentFrame = page._page.frameManager.frame(parentFrameId);
if (!parentFrame)
continue;
page._session.addFrameBrowsingContext(event.context);
page._page._frameManager.frameAttached(event.context, parentFrameId);
const frame = page._page._frameManager.frame(event.context);
page._page.frameManager.frameAttached(event.context, parentFrameId);
const frame = page._page.frameManager.frame(event.context);
if (frame)
frame._url = event.url;
return;
@ -180,10 +180,10 @@ export class BidiBrowser extends Browser {
this._browserSession.removeFrameBrowsingContext(event.context);
const parentFrameId = event.parent;
for (const page of this._bidiPages.values()) {
const parentFrame = page._page._frameManager.frame(parentFrameId);
const parentFrame = page._page.frameManager.frame(parentFrameId);
if (!parentFrame)
continue;
page._page._frameManager.frameDetached(event.context);
page._page.frameManager.frameDetached(event.context);
return;
}
return;
@ -266,7 +266,6 @@ export class BidiBrowserContext extends BrowserContext {
}
override async doCreateNewPage(): Promise<Page> {
assertBrowserContextIsNotOwned(this);
const { context } = await this._browser._browserSession.send('browsingContext.create', {
type: bidi.BrowsingContext.CreateType.Window,
userContext: this._browserContextId,
@ -368,7 +367,7 @@ export class BidiBrowserContext extends BrowserContext {
async doSetHTTPCredentials(httpCredentials?: types.Credentials): Promise<void> {
this._options.httpCredentials = httpCredentials;
for (const page of this.pages())
await (page._delegate as BidiPage).updateHttpCredentials();
await (page.delegate as BidiPage).updateHttpCredentials();
}
async doAddInitScript(initScript: InitScript) {

View File

@ -59,7 +59,7 @@ export class BidiNetworkManager {
if (param.request.url.startsWith('data:'))
return;
const redirectedFrom = param.redirectCount ? (this._requests.get(param.request.request) || null) : null;
const frame = redirectedFrom ? redirectedFrom.request.frame() : (param.context ? this._page._frameManager.frame(param.context) : null);
const frame = redirectedFrom ? redirectedFrom.request.frame() : (param.context ? this._page.frameManager.frame(param.context) : null);
if (!frame)
return;
if (redirectedFrom)
@ -82,7 +82,7 @@ export class BidiNetworkManager {
}
const request = new BidiRequest(frame, redirectedFrom, param, route);
this._requests.set(request._id, request);
this._page._frameManager.requestStarted(request.request, route);
this._page.frameManager.requestStarted(request.request, route);
}
private _onResponseStarted(params: bidi.Network.ResponseStartedParameters) {
@ -115,7 +115,7 @@ export class BidiNetworkManager {
// "raw" headers are the same as "provisional" headers in Bidi.
response.setRawResponseHeaders(null);
response.setResponseHeadersSize(params.response.headersSize);
this._page._frameManager.requestReceivedResponse(response);
this._page.frameManager.requestReceivedResponse(response);
if (params.navigation)
this._onNavigationResponseStarted(params);
}
@ -139,7 +139,7 @@ export class BidiNetworkManager {
response._requestFinished(responseEndTime);
}
response._setHttpVersion(params.response.protocol);
this._page._frameManager.reportRequestFinished(request.request, response);
this._page.frameManager.reportRequestFinished(request.request, response);
}
@ -156,12 +156,12 @@ export class BidiNetworkManager {
}
request.request._setFailureText(params.errorText);
// TODO: support canceled flag
this._page._frameManager.requestFailed(request.request, params.errorText === 'NS_BINDING_ABORTED');
this._page.frameManager.requestFailed(request.request, params.errorText === 'NS_BINDING_ABORTED');
}
private _onAuthRequired(params: bidi.Network.AuthRequiredParameters) {
const isBasic = params.response.authChallenges?.some(challenge => challenge.scheme.startsWith('Basic'));
const credentials = this._page._browserContext._options.httpCredentials;
const credentials = this._page.browserContext._options.httpCredentials;
if (isBasic && credentials) {
this._session.sendMayFail('network.continueWithAuth', {
request: params.request.request,
@ -230,7 +230,7 @@ class BidiRequest {
redirectedFrom._redirectedTo = this;
// TODO: missing in the spec?
const postDataBuffer = null;
this.request = new network.Request(frame._page._browserContext, frame, null, redirectedFrom ? redirectedFrom.request : null, payload.navigation ?? undefined,
this.request = new network.Request(frame._page.browserContext, frame, null, redirectedFrom ? redirectedFrom.request : null, payload.navigation ?? undefined,
payload.request.url, 'other', payload.request.method, postDataBuffer, fromBidiHeaders(payload.request.headers));
// "raw" headers are the same as "provisional" headers in Bidi.
this.request.setRawRequestHeaders(null);

View File

@ -103,7 +103,7 @@ export class BidiPage implements PageDelegate {
}
private _onFrameAttached(frameId: string, parentFrameId: string | null): frames.Frame {
return this._page._frameManager.frameAttached(frameId, parentFrameId);
return this._page.frameManager.frameAttached(frameId, parentFrameId);
}
private _removeContextsForFrame(frame: frames.Frame, notifyFrame: boolean) {
@ -121,7 +121,7 @@ export class BidiPage implements PageDelegate {
return;
if (realmInfo.type !== 'window')
return;
const frame = this._page._frameManager.frame(realmInfo.context);
const frame = this._page.frameManager.frame(realmInfo.context);
if (!frame)
return;
let worldName: types.World;
@ -172,47 +172,47 @@ export class BidiPage implements PageDelegate {
private _onNavigationStarted(params: bidi.BrowsingContext.NavigationInfo) {
const frameId = params.context;
this._page._frameManager.frameRequestedNavigation(frameId, params.navigation!);
this._page.frameManager.frameRequestedNavigation(frameId, params.navigation!);
const url = params.url.toLowerCase();
if (url.startsWith('file:') || url.startsWith('data:') || url === 'about:blank') {
// Navigation to file urls doesn't emit network events, so we fire 'commit' event right when navigation is started.
// Doing it in domcontentload would be too late as we'd clear frame tree.
const frame = this._page._frameManager.frame(frameId)!;
const frame = this._page.frameManager.frame(frameId)!;
if (frame)
this._page._frameManager.frameCommittedNewDocumentNavigation(frameId, params.url, '', params.navigation!, /* initial */ false);
this._page.frameManager.frameCommittedNewDocumentNavigation(frameId, params.url, '', params.navigation!, /* initial */ false);
}
}
// TODO: there is no separate event for committed navigation, so we approximate it with responseStarted.
private _onNavigationResponseStarted(params: bidi.Network.ResponseStartedParameters) {
const frameId = params.context!;
const frame = this._page._frameManager.frame(frameId);
const frame = this._page.frameManager.frame(frameId);
assert(frame);
this._page._frameManager.frameCommittedNewDocumentNavigation(frameId, params.response.url, '', params.navigation!, /* initial */ false);
this._page.frameManager.frameCommittedNewDocumentNavigation(frameId, params.response.url, '', params.navigation!, /* initial */ false);
// if (!initial)
// this._firstNonInitialNavigationCommittedFulfill();
}
private _onDomContentLoaded(params: bidi.BrowsingContext.NavigationInfo) {
const frameId = params.context;
this._page._frameManager.frameLifecycleEvent(frameId, 'domcontentloaded');
this._page.frameManager.frameLifecycleEvent(frameId, 'domcontentloaded');
}
private _onLoad(params: bidi.BrowsingContext.NavigationInfo) {
this._page._frameManager.frameLifecycleEvent(params.context, 'load');
this._page.frameManager.frameLifecycleEvent(params.context, 'load');
}
private _onNavigationAborted(params: bidi.BrowsingContext.NavigationInfo) {
this._page._frameManager.frameAbortedNavigation(params.context, 'Navigation aborted', params.navigation || undefined);
this._page.frameManager.frameAbortedNavigation(params.context, 'Navigation aborted', params.navigation || undefined);
}
private _onNavigationFailed(params: bidi.BrowsingContext.NavigationInfo) {
this._page._frameManager.frameAbortedNavigation(params.context, 'Navigation failed', params.navigation || undefined);
this._page.frameManager.frameAbortedNavigation(params.context, 'Navigation failed', params.navigation || undefined);
}
private _onFragmentNavigated(params: bidi.BrowsingContext.NavigationInfo) {
this._page._frameManager.frameCommittedSameDocumentNavigation(params.context, params.url);
this._page.frameManager.frameCommittedSameDocumentNavigation(params.context, params.url);
}
private _onUserPromptOpened(event: bidi.BrowsingContext.UserPromptOpenedParameters) {
@ -235,7 +235,7 @@ export class BidiPage implements PageDelegate {
return;
const callFrame = params.stackTrace?.callFrames[0];
const location = callFrame ?? { url: '', lineNumber: 1, columnNumber: 1 };
this._page._addConsoleMessage(entry.method, entry.args.map(arg => createHandle(context, arg)), location, params.text || undefined);
this._page.addConsoleMessage(entry.method, entry.args.map(arg => createHandle(context, arg)), location, params.text || undefined);
}
async navigateFrame(frame: frames.Frame, url: string, referrer: string | undefined): Promise<frames.GotoResult> {
@ -328,7 +328,7 @@ export class BidiPage implements PageDelegate {
return;
if (event.data.type !== 'string')
return;
await this._page._onBindingCalled(event.data.value, context);
await this._page.onBindingCalled(event.data.value, context);
}
async addInitScript(initScript: InitScript): Promise<void> {
@ -380,7 +380,7 @@ export class BidiPage implements PageDelegate {
const frameId = await executionContext.contentFrameIdForFrame(handle);
if (!frameId)
return null;
return this._page._frameManager.frame(frameId);
return this._page.frameManager.frame(frameId);
}
async getOwnerFrame(handle: dom.ElementHandle): Promise<string | null> {

View File

@ -146,7 +146,7 @@ export abstract class Browser extends SdkObject {
this._idToVideo.set(videoId, { context, artifact });
pageOrError.then(page => {
if (page instanceof Page) {
page._video = artifact;
page.video = artifact;
page.emitOnContext(BrowserContext.Events.VideoStarted, artifact);
page.emit(Page.Events.Video, artifact);
}

View File

@ -216,11 +216,11 @@ export abstract class BrowserContext extends SdkObject {
}
// Unless dialogs are dismissed, setting extra http headers below does not respond.
page?._frameManager.setCloseAllOpeningDialogs(true);
await page?._frameManager.closeOpenDialogs();
page?.frameManager.setCloseAllOpeningDialogs(true);
await page?.frameManager.closeOpenDialogs();
// Navigate to about:blank first to ensure no page scripts are running after this point.
await page?.mainFrame().goto(metadata, 'about:blank', { timeout: 0 });
page?._frameManager.setCloseAllOpeningDialogs(false);
page?.frameManager.setCloseAllOpeningDialogs(false);
await this._resetStorage();
await this._removeExposedBindings();
@ -544,7 +544,7 @@ export abstract class BrowserContext extends SdkObject {
if (originsToSave.size) {
const internalMetadata = serverSideCallMetadata();
const page = await this.newPage(internalMetadata);
await page._setServerRequestInterceptor(handler => {
await page.setServerRequestInterceptor(handler => {
handler.fulfill({ body: '<html></html>' }).catch(() => {});
return true;
});
@ -574,7 +574,7 @@ export abstract class BrowserContext extends SdkObject {
// as a user-visible page.
isServerSide: false,
});
await page._setServerRequestInterceptor(handler => {
await page.setServerRequestInterceptor(handler => {
handler.fulfill({ body: '<html></html>' }).catch(() => {});
return true;
});
@ -585,7 +585,7 @@ export abstract class BrowserContext extends SdkObject {
await frame.resetStorageForCurrentOriginBestEffort(newOrigins.get(origin));
}
await page._setServerRequestInterceptor(undefined);
await page.setServerRequestInterceptor(undefined);
this._origins = new Set([...newOrigins.keys()]);
// It is safe to not restore the URL to about:blank since we are doing it in Page::resetForReuse.
@ -609,7 +609,7 @@ export abstract class BrowserContext extends SdkObject {
if (state.origins && state.origins.length) {
const internalMetadata = serverSideCallMetadata();
const page = await this.newPage(internalMetadata);
await page._setServerRequestInterceptor(handler => {
await page.setServerRequestInterceptor(handler => {
handler.fulfill({ body: '<html></html>' }).catch(() => {});
return true;
});
@ -670,13 +670,6 @@ export abstract class BrowserContext extends SdkObject {
}
}
export function assertBrowserContextIsNotOwned(context: BrowserContext) {
for (const page of context.pages()) {
if (page._ownedContext)
throw new Error('Please use browser.newContext() for multi-page scripts that share the context.');
}
}
export function validateBrowserContextOptions(options: types.BrowserContextOptions, browserOptions: BrowserOptions) {
if (options.noDefaultViewport && options.deviceScaleFactor !== undefined)
throw new Error(`"deviceScaleFactor" option is not supported with null "viewport"`);

View File

@ -21,7 +21,7 @@ import { assert } from '../../utils/isomorphic/assert';
import { createGuid } from '../utils/crypto';
import { Artifact } from '../artifact';
import { Browser } from '../browser';
import { BrowserContext, assertBrowserContextIsNotOwned, verifyGeolocation } from '../browserContext';
import { BrowserContext, verifyGeolocation } from '../browserContext';
import { Frame } from '../frames';
import * as network from '../network';
import { Page } from '../page';
@ -245,7 +245,7 @@ export class CRBrowser extends Browser {
private _findOwningPage(frameId: string) {
for (const crPage of this._crPages.values()) {
const frame = crPage._page._frameManager.frame(frameId);
const frame = crPage._page.frameManager.frame(frameId);
if (frame)
return crPage;
}
@ -288,7 +288,7 @@ export class CRBrowser extends Browser {
async startTracing(page?: Page, options: { screenshots?: boolean; categories?: string[]; } = {}) {
assert(!this._tracingRecording, 'Cannot start recording trace while already recording trace.');
this._tracingClient = page ? (page._delegate as CRPage)._mainFrameSession._client : this._session;
this._tracingClient = page ? (page.delegate as CRPage)._mainFrameSession._client : this._session;
const defaultCategories = [
'-*', 'devtools.timeline', 'v8.execute', 'disabled-by-default-devtools.timeline',
@ -372,7 +372,6 @@ export class CRBrowserContext extends BrowserContext {
}
override async doCreateNewPage(): Promise<Page> {
assertBrowserContextIsNotOwned(this);
const { targetId } = await this._browser._session.send('Target.createTarget', { url: 'about:blank', browserContextId: this._browserContextId });
return this._browser._crPages.get(targetId)!._page;
}
@ -435,13 +434,13 @@ export class CRBrowserContext extends BrowserContext {
verifyGeolocation(geolocation);
this._options.geolocation = geolocation;
for (const page of this.pages())
await (page._delegate as CRPage).updateGeolocation();
await (page.delegate as CRPage).updateGeolocation();
}
async setExtraHTTPHeaders(headers: types.HeadersArray): Promise<void> {
this._options.extraHTTPHeaders = headers;
for (const page of this.pages())
await (page._delegate as CRPage).updateExtraHTTPHeaders();
await (page.delegate as CRPage).updateExtraHTTPHeaders();
for (const sw of this.serviceWorkers())
await (sw as CRServiceWorker).updateExtraHTTPHeaders();
}
@ -449,14 +448,14 @@ export class CRBrowserContext extends BrowserContext {
async setUserAgent(userAgent: string | undefined): Promise<void> {
this._options.userAgent = userAgent;
for (const page of this.pages())
await (page._delegate as CRPage).updateUserAgent();
await (page.delegate as CRPage).updateUserAgent();
// TODO: service workers don't have Emulation domain?
}
async setOffline(offline: boolean): Promise<void> {
this._options.offline = offline;
for (const page of this.pages())
await (page._delegate as CRPage).updateOffline();
await (page.delegate as CRPage).updateOffline();
for (const sw of this.serviceWorkers())
await (sw as CRServiceWorker).updateOffline();
}
@ -464,24 +463,24 @@ export class CRBrowserContext extends BrowserContext {
async doSetHTTPCredentials(httpCredentials?: types.Credentials): Promise<void> {
this._options.httpCredentials = httpCredentials;
for (const page of this.pages())
await (page._delegate as CRPage).updateHttpCredentials();
await (page.delegate as CRPage).updateHttpCredentials();
for (const sw of this.serviceWorkers())
await (sw as CRServiceWorker).updateHttpCredentials();
}
async doAddInitScript(initScript: InitScript) {
for (const page of this.pages())
await (page._delegate as CRPage).addInitScript(initScript);
await (page.delegate as CRPage).addInitScript(initScript);
}
async doRemoveNonInternalInitScripts() {
for (const page of this.pages())
await (page._delegate as CRPage).removeNonInternalInitScripts();
await (page.delegate as CRPage).removeNonInternalInitScripts();
}
async doUpdateRequestInterception(): Promise<void> {
for (const page of this.pages())
await (page._delegate as CRPage).updateRequestInterception();
await (page.delegate as CRPage).updateRequestInterception();
for (const sw of this.serviceWorkers())
await (sw as CRServiceWorker).updateRequestInterception();
}
@ -493,7 +492,7 @@ export class CRBrowserContext extends BrowserContext {
// beforeunload.
const openedBeforeUnloadDialogs: Dialog[] = [];
for (const crPage of this._crPages()) {
const dialogs = [...crPage._page._frameManager._openedDialogs].filter(dialog => dialog.type() === 'beforeunload');
const dialogs = [...crPage._page.frameManager._openedDialogs].filter(dialog => dialog.type() === 'beforeunload');
openedBeforeUnloadDialogs.push(...dialogs);
}
await Promise.all(openedBeforeUnloadDialogs.map(dialog => dialog.dismiss()));
@ -508,7 +507,7 @@ export class CRBrowserContext extends BrowserContext {
await this._browser._session.send('Target.disposeBrowserContext', { browserContextId: this._browserContextId });
this._browser._contexts.delete(this._browserContextId);
for (const [targetId, serviceWorker] of this._browser._serviceWorkers) {
if (serviceWorker._browserContext !== this)
if (serviceWorker.browserContext !== this)
continue;
// When closing a browser context, service workers are shutdown
// asynchronously and we get detached from them later.
@ -559,15 +558,15 @@ export class CRBrowserContext extends BrowserContext {
}
serviceWorkers(): Worker[] {
return Array.from(this._browser._serviceWorkers.values()).filter(serviceWorker => serviceWorker._browserContext === this);
return Array.from(this._browser._serviceWorkers.values()).filter(serviceWorker => serviceWorker.browserContext === this);
}
async newCDPSession(page: Page | Frame): Promise<CDPSession> {
let targetId: string | null = null;
if (page instanceof Page) {
targetId = (page._delegate as CRPage)._targetId;
targetId = (page.delegate as CRPage)._targetId;
} else if (page instanceof Frame) {
const session = (page._page._delegate as CRPage)._sessions.get(page._id);
const session = (page._page.delegate as CRPage)._sessions.get(page._id);
if (!session)
throw new Error(`This frame does not have a separate CDP session, it is a part of the parent frame's session`);
targetId = session._targetId;

View File

@ -74,13 +74,13 @@ export class CRNetworkManager {
];
if (this._page) {
sessionInfo.eventListeners.push(...[
eventsHelper.addEventListener(session, 'Network.webSocketCreated', e => this._page!._frameManager.onWebSocketCreated(e.requestId, e.url)),
eventsHelper.addEventListener(session, 'Network.webSocketWillSendHandshakeRequest', e => this._page!._frameManager.onWebSocketRequest(e.requestId)),
eventsHelper.addEventListener(session, 'Network.webSocketHandshakeResponseReceived', e => this._page!._frameManager.onWebSocketResponse(e.requestId, e.response.status, e.response.statusText)),
eventsHelper.addEventListener(session, 'Network.webSocketFrameSent', e => e.response.payloadData && this._page!._frameManager.onWebSocketFrameSent(e.requestId, e.response.opcode, e.response.payloadData)),
eventsHelper.addEventListener(session, 'Network.webSocketFrameReceived', e => e.response.payloadData && this._page!._frameManager.webSocketFrameReceived(e.requestId, e.response.opcode, e.response.payloadData)),
eventsHelper.addEventListener(session, 'Network.webSocketClosed', e => this._page!._frameManager.webSocketClosed(e.requestId)),
eventsHelper.addEventListener(session, 'Network.webSocketFrameError', e => this._page!._frameManager.webSocketError(e.requestId, e.errorMessage)),
eventsHelper.addEventListener(session, 'Network.webSocketCreated', e => this._page!.frameManager.onWebSocketCreated(e.requestId, e.url)),
eventsHelper.addEventListener(session, 'Network.webSocketWillSendHandshakeRequest', e => this._page!.frameManager.onWebSocketRequest(e.requestId)),
eventsHelper.addEventListener(session, 'Network.webSocketHandshakeResponseReceived', e => this._page!.frameManager.onWebSocketResponse(e.requestId, e.response.status, e.response.statusText)),
eventsHelper.addEventListener(session, 'Network.webSocketFrameSent', e => e.response.payloadData && this._page!.frameManager.onWebSocketFrameSent(e.requestId, e.response.opcode, e.response.payloadData)),
eventsHelper.addEventListener(session, 'Network.webSocketFrameReceived', e => e.response.payloadData && this._page!.frameManager.webSocketFrameReceived(e.requestId, e.response.opcode, e.response.payloadData)),
eventsHelper.addEventListener(session, 'Network.webSocketClosed', e => this._page!.frameManager.webSocketClosed(e.requestId)),
eventsHelper.addEventListener(session, 'Network.webSocketFrameError', e => this._page!.frameManager.webSocketError(e.requestId, e.errorMessage)),
]);
}
this._sessions.set(session, sessionInfo);
@ -287,19 +287,19 @@ export class CRNetworkManager {
redirectedFrom = request;
}
}
let frame = requestWillBeSentEvent.frameId ? this._page?._frameManager.frame(requestWillBeSentEvent.frameId) : requestWillBeSentSessionInfo.workerFrame;
let frame = requestWillBeSentEvent.frameId ? this._page?.frameManager.frame(requestWillBeSentEvent.frameId) : requestWillBeSentSessionInfo.workerFrame;
// Requests from workers lack frameId, because we receive Network.requestWillBeSent
// on the worker target. However, we receive Fetch.requestPaused on the page target,
// and lack workerFrame there. Luckily, Fetch.requestPaused provides a frameId.
if (!frame && this._page && requestPausedEvent && requestPausedEvent.frameId)
frame = this._page._frameManager.frame(requestPausedEvent.frameId);
frame = this._page.frameManager.frame(requestPausedEvent.frameId);
// Check if it's main resource request interception (targetId === main frame id).
if (!frame && this._page && requestWillBeSentEvent.frameId === (this._page?._delegate as CRPage)._targetId) {
if (!frame && this._page && requestWillBeSentEvent.frameId === (this._page?.delegate as CRPage)._targetId) {
// Main resource request for the page is being intercepted so the Frame is not created
// yet. Precreate it here for the purposes of request interception. It will be updated
// later as soon as the request continues and we receive frame tree from the page.
frame = this._page._frameManager.frameAttached(requestWillBeSentEvent.frameId, null);
frame = this._page.frameManager.frameAttached(requestWillBeSentEvent.frameId, null);
}
// CORS options preflight request is generated by the network stack. If interception is enabled,
@ -349,7 +349,7 @@ export class CRNetworkManager {
const documentId = isNavigationRequest ? requestWillBeSentEvent.loaderId : undefined;
const request = new InterceptableRequest({
session: requestWillBeSentSessionInfo.session,
context: (this._page || this._serviceWorker)!._browserContext,
context: (this._page || this._serviceWorker)!.browserContext,
frame: frame || null,
serviceWorker: this._serviceWorker || null,
documentId,
@ -367,7 +367,7 @@ export class CRNetworkManager {
// right away, so that client can call it from the route handler.
request.request.setRawRequestHeaders(headersObjectToArray(requestPausedEvent!.request.headers, '\n'));
}
(this._page?._frameManager || this._serviceWorker)!.requestStarted(request.request, route || undefined);
(this._page?.frameManager || this._serviceWorker)!.requestStarted(request.request, route || undefined);
}
_createResponse(request: InterceptableRequest, responsePayload: Protocol.Network.Response, hasExtraInfo: boolean): network.Response {
@ -454,8 +454,8 @@ export class CRNetworkManager {
response.setEncodedBodySize(null);
response._requestFinished((timestamp - request._timestamp) * 1000);
this._deleteRequest(request);
(this._page?._frameManager || this._serviceWorker)!.requestReceivedResponse(response);
(this._page?._frameManager || this._serviceWorker)!.reportRequestFinished(request.request, response);
(this._page?.frameManager || this._serviceWorker)!.requestReceivedResponse(response);
(this._page?.frameManager || this._serviceWorker)!.reportRequestFinished(request.request, response);
}
_onResponseReceivedExtraInfo(event: Protocol.Network.responseReceivedExtraInfoPayload) {
@ -479,7 +479,7 @@ export class CRNetworkManager {
if (!request)
return;
const response = this._createResponse(request, event.response, event.hasExtraInfo);
(this._page?._frameManager || this._serviceWorker)!.requestReceivedResponse(response);
(this._page?.frameManager || this._serviceWorker)!.requestReceivedResponse(response);
}
_onLoadingFinished(sessionInfo: SessionInfo, event: Protocol.Network.loadingFinishedPayload) {
@ -501,7 +501,7 @@ export class CRNetworkManager {
response._requestFinished(helper.secondsToRoundishMillis(event.timestamp - request._timestamp));
}
this._deleteRequest(request);
(this._page?._frameManager || this._serviceWorker)!.reportRequestFinished(request.request, response);
(this._page?.frameManager || this._serviceWorker)!.reportRequestFinished(request.request, response);
}
_onLoadingFailed(sessionInfo: SessionInfo, event: Protocol.Network.loadingFailedPayload) {
@ -537,7 +537,7 @@ export class CRNetworkManager {
}
this._deleteRequest(request);
request.request._setFailureText(event.errorText || event.blockedReason || '');
(this._page?._frameManager || this._serviceWorker)!.requestFailed(request.request, !!event.canceled);
(this._page?.frameManager || this._serviceWorker)!.requestFailed(request.request, !!event.canceled);
}
private _maybeUpdateRequestSession(sessionInfo: SessionInfo, request: InterceptableRequest) {

View File

@ -79,7 +79,7 @@ export class CRPage implements PageDelegate {
readonly _nextWindowOpenPopupFeatures: string[][] = [];
static mainFrameSession(page: Page): FrameSession {
const crPage = page._delegate as CRPage;
const crPage = page.delegate as CRPage;
return crPage._mainFrameSession;
}
@ -108,7 +108,7 @@ export class CRPage implements PageDelegate {
const features = opener._nextWindowOpenPopupFeatures.shift() || [];
const viewportSize = helper.getViewportSizeFromWindowFeatures(features);
if (viewportSize)
this._page._emulatedSize = { viewport: viewportSize, screen: viewportSize };
this._page.setEmulatedSize({ viewport: viewportSize, screen: viewportSize });
}
const createdEvent = this._isBackgroundPage ? CRBrowserContext.CREvents.BackgroundPage : BrowserContext.Events.Page;
@ -441,7 +441,7 @@ class FrameSession {
}
async _initialize(hasUIWindow: boolean) {
const isSettingStorageState = this._page._browserContext.isSettingStorageState();
const isSettingStorageState = this._page.browserContext.isSettingStorageState();
if (!isSettingStorageState && hasUIWindow &&
!this._crPage._browserContext._browser.isClank() &&
!this._crPage._browserContext._options.noDefaultViewport) {
@ -480,7 +480,7 @@ class FrameSession {
this._addRendererListeners();
}
const localFrames = this._isMainFrame() ? this._page.frames() : [this._page._frameManager.frame(this._targetId)!];
const localFrames = this._isMainFrame() ? this._page.frames() : [this._page.frameManager.frame(this._targetId)!];
for (const frame of localFrames) {
// Note: frames might be removed before we send these.
this._client._sendMayFail('Page.createIsolatedWorld', {
@ -574,9 +574,9 @@ class FrameSession {
if (this._eventBelongsToStaleFrame(event.frameId))
return;
if (event.name === 'load')
this._page._frameManager.frameLifecycleEvent(event.frameId, 'load');
this._page.frameManager.frameLifecycleEvent(event.frameId, 'load');
else if (event.name === 'DOMContentLoaded')
this._page._frameManager.frameLifecycleEvent(event.frameId, 'domcontentloaded');
this._page.frameManager.frameLifecycleEvent(event.frameId, 'domcontentloaded');
}
_handleFrameTree(frameTree: Protocol.Page.FrameTree) {
@ -590,7 +590,7 @@ class FrameSession {
}
private _eventBelongsToStaleFrame(frameId: string) {
const frame = this._page._frameManager.frame(frameId);
const frame = this._page.frameManager.frame(frameId);
// Subtree may be already gone because some ancestor navigation destroyed the oopif.
if (!frame)
return true;
@ -607,26 +607,26 @@ class FrameSession {
if (frameSession && frameId !== this._targetId) {
// This is a remote -> local frame transition.
frameSession._swappedIn = true;
const frame = this._page._frameManager.frame(frameId);
const frame = this._page.frameManager.frame(frameId);
// Frame or even a whole subtree may be already gone, because some ancestor did navigate.
if (frame)
this._page._frameManager.removeChildFramesRecursively(frame);
this._page.frameManager.removeChildFramesRecursively(frame);
return;
}
if (parentFrameId && !this._page._frameManager.frame(parentFrameId)) {
if (parentFrameId && !this._page.frameManager.frame(parentFrameId)) {
// Parent frame may be gone already because some ancestor frame navigated and
// destroyed the whole subtree of some oopif, while oopif's process is still sending us events.
// Be careful to not confuse this with "main frame navigated cross-process" scenario
// where parentFrameId is null.
return;
}
this._page._frameManager.frameAttached(frameId, parentFrameId);
this._page.frameManager.frameAttached(frameId, parentFrameId);
}
_onFrameNavigated(framePayload: Protocol.Page.Frame, initial: boolean) {
if (this._eventBelongsToStaleFrame(framePayload.id))
return;
this._page._frameManager.frameCommittedNewDocumentNavigation(framePayload.id, framePayload.url + (framePayload.urlFragment || ''), framePayload.name || '', framePayload.loaderId, initial);
this._page.frameManager.frameCommittedNewDocumentNavigation(framePayload.id, framePayload.url + (framePayload.urlFragment || ''), framePayload.name || '', framePayload.loaderId, initial);
if (!initial)
this._firstNonInitialNavigationCommittedFulfill();
}
@ -635,13 +635,13 @@ class FrameSession {
if (this._eventBelongsToStaleFrame(payload.frameId))
return;
if (payload.disposition === 'currentTab')
this._page._frameManager.frameRequestedNavigation(payload.frameId);
this._page.frameManager.frameRequestedNavigation(payload.frameId);
}
_onFrameNavigatedWithinDocument(frameId: string, url: string) {
if (this._eventBelongsToStaleFrame(frameId))
return;
this._page._frameManager.frameCommittedSameDocumentNavigation(frameId, url);
this._page.frameManager.frameCommittedSameDocumentNavigation(frameId, url);
}
_onFrameDetached(frameId: string, reason: 'remove' | 'swap') {
@ -655,17 +655,17 @@ class FrameSession {
// This is a local -> remote frame transition, where
// Page.frameDetached arrives before Target.attachedToTarget.
// We should keep the frame in the tree, and it will be used for the new target.
const frame = this._page._frameManager.frame(frameId);
const frame = this._page.frameManager.frame(frameId);
if (frame)
this._page._frameManager.removeChildFramesRecursively(frame);
this._page.frameManager.removeChildFramesRecursively(frame);
return;
}
// Just a regular frame detach.
this._page._frameManager.frameDetached(frameId);
this._page.frameManager.frameDetached(frameId);
}
_onExecutionContextCreated(contextPayload: Protocol.Runtime.ExecutionContextDescription) {
const frame = contextPayload.auxData ? this._page._frameManager.frame(contextPayload.auxData.frameId) : null;
const frame = contextPayload.auxData ? this._page.frameManager.frame(contextPayload.auxData.frameId) : null;
if (!frame || this._eventBelongsToStaleFrame(frame._id))
return;
const delegate = new CRExecutionContext(this._client, contextPayload);
@ -699,10 +699,10 @@ class FrameSession {
if (event.targetInfo.type === 'iframe') {
// Frame id equals target id.
const targetId = event.targetInfo.targetId;
const frame = this._page._frameManager.frame(targetId);
const frame = this._page.frameManager.frame(targetId);
if (!frame)
return; // Subtree may be already gone due to renderer/browser race.
this._page._frameManager.removeChildFramesRecursively(frame);
this._page.frameManager.removeChildFramesRecursively(frame);
for (const [contextId, context] of this._contextIdToContext) {
if (context.frame === frame)
this._onExecutionContextDestroyed(contextId);
@ -720,22 +720,22 @@ class FrameSession {
const url = event.targetInfo.url;
const worker = new Worker(this._page, url);
this._page._addWorker(event.sessionId, worker);
this._page.addWorker(event.sessionId, worker);
this._workerSessions.set(event.sessionId, session);
session.once('Runtime.executionContextCreated', async event => {
worker._createExecutionContext(new CRExecutionContext(session, event.context));
worker.createExecutionContext(new CRExecutionContext(session, event.context));
});
// This might fail if the target is closed before we initialize.
session._sendMayFail('Runtime.enable');
// TODO: attribute workers to the right frame.
this._crPage._networkManager.addSession(session, this._page._frameManager.frame(this._targetId) ?? undefined).catch(() => {});
this._crPage._networkManager.addSession(session, this._page.frameManager.frame(this._targetId) ?? undefined).catch(() => {});
session._sendMayFail('Runtime.runIfWaitingForDebugger');
session._sendMayFail('Target.setAutoAttach', { autoAttach: true, waitForDebuggerOnStart: true, flatten: true });
session.on('Target.attachedToTarget', event => this._onAttachedToTarget(event));
session.on('Target.detachedFromTarget', event => this._onDetachedFromTarget(event));
session.on('Runtime.consoleAPICalled', event => {
const args = event.args.map(o => createHandle(worker._existingExecutionContext!, o));
this._page._addConsoleMessage(event.type, args, toConsoleMessageLocation(event.stackTrace));
const args = event.args.map(o => createHandle(worker.existingExecutionContext!, o));
this._page.addConsoleMessage(event.type, args, toConsoleMessageLocation(event.stackTrace));
});
session.on('Runtime.exceptionThrown', exception => this._page.emitOnContextOnceInitialized(BrowserContext.Events.PageError, exceptionToError(exception.exceptionDetails), this._page));
}
@ -745,7 +745,7 @@ class FrameSession {
const workerSession = this._workerSessions.get(event.sessionId);
if (workerSession) {
workerSession.dispose();
this._page._removeWorker(event.sessionId);
this._page.removeWorker(event.sessionId);
return;
}
@ -768,7 +768,7 @@ class FrameSession {
// Child was not swapped in - that means frameAttached did not happen and
// this is remote detach rather than remote -> local swap.
if (!childFrameSession._swappedIn)
this._page._frameManager.frameDetached(event.targetId!);
this._page.frameManager.frameDetached(event.targetId!);
childFrameSession.dispose();
});
}
@ -798,7 +798,7 @@ class FrameSession {
if (!context)
return;
const values = event.args.map(arg => createHandle(context, arg));
this._page._addConsoleMessage(event.type, values, toConsoleMessageLocation(event.stackTrace));
this._page.addConsoleMessage(event.type, values, toConsoleMessageLocation(event.stackTrace));
}
async _onBindingCalled(event: Protocol.Runtime.bindingCalledPayload) {
@ -806,12 +806,12 @@ class FrameSession {
if (!(pageOrError instanceof Error)) {
const context = this._contextIdToContext.get(event.executionContextId);
if (context)
await this._page._onBindingCalled(event.payload, context);
await this._page.onBindingCalled(event.payload, context);
}
}
_onDialog(event: Protocol.Page.javascriptDialogOpeningPayload) {
if (!this._page._frameManager.frame(this._targetId))
if (!this._page.frameManager.frame(this._targetId))
return; // Our frame/subtree may be gone already.
this._page.emitOnContext(BrowserContext.Events.Dialog, new dialog.Dialog(
this._page,
@ -820,7 +820,7 @@ class FrameSession {
async (accept: boolean, promptText?: string) => {
// TODO: this should actually be a CDP event that notifies about a cancelled navigation attempt.
if (this._isMainFrame() && event.type === 'beforeunload' && !accept)
this._page._frameManager.frameAbortedNavigation(this._page.mainFrame()._id, 'navigation cancelled by beforeunload dialog');
this._page.frameManager.frameAbortedNavigation(this._page.mainFrame()._id, 'navigation cancelled by beforeunload dialog');
await this._client.send('Page.handleJavaScriptDialog', { accept, promptText });
},
event.defaultPrompt));
@ -845,14 +845,14 @@ class FrameSession {
lineNumber: lineNumber || 0,
columnNumber: 0,
};
this._page._addConsoleMessage(level, [], location, text);
this._page.addConsoleMessage(level, [], location, text);
}
}
async _onFileChooserOpened(event: Protocol.Page.fileChooserOpenedPayload) {
if (!event.backendNodeId)
return;
const frame = this._page._frameManager.frame(event.frameId);
const frame = this._page.frameManager.frame(event.frameId);
if (!frame)
return;
let handle;
@ -1070,7 +1070,7 @@ class FrameSession {
});
if (!nodeInfo || typeof nodeInfo.node.frameId !== 'string')
return null;
return this._page._frameManager.frame(nodeInfo.node.frameId);
return this._page.frameManager.frame(nodeInfo.node.frameId);
}
async _getOwnerFrame(handle: dom.ElementHandle): Promise<string | null> {
@ -1112,7 +1112,7 @@ class FrameSession {
}
private async _framePosition(): Promise<types.Point | null> {
const frame = this._page._frameManager.frame(this._targetId);
const frame = this._page.frameManager.frame(this._targetId);
if (!frame)
return null;
if (frame === this._page.mainFrame())

View File

@ -23,18 +23,18 @@ import type { CRBrowserContext } from './crBrowser';
import type { CRSession } from './crConnection';
export class CRServiceWorker extends Worker {
readonly _browserContext: CRBrowserContext;
readonly _networkManager?: CRNetworkManager;
readonly browserContext: CRBrowserContext;
private readonly _networkManager?: CRNetworkManager;
private _session: CRSession;
constructor(browserContext: CRBrowserContext, session: CRSession, url: string) {
super(browserContext, url);
this._session = session;
this._browserContext = browserContext;
this.browserContext = browserContext;
if (!!process.env.PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS)
this._networkManager = new CRNetworkManager(null, this);
session.once('Runtime.executionContextCreated', event => {
this._createExecutionContext(new CRExecutionContext(session, event.context));
this.createExecutionContext(new CRExecutionContext(session, event.context));
});
if (this._networkManager && this._isNetworkInspectionEnabled()) {
@ -62,19 +62,19 @@ export class CRServiceWorker extends Worker {
async updateOffline(): Promise<void> {
if (!this._isNetworkInspectionEnabled())
return;
await this._networkManager?.setOffline(!!this._browserContext._options.offline).catch(() => {});
await this._networkManager?.setOffline(!!this.browserContext._options.offline).catch(() => {});
}
async updateHttpCredentials(): Promise<void> {
if (!this._isNetworkInspectionEnabled())
return;
await this._networkManager?.authenticate(this._browserContext._options.httpCredentials || null).catch(() => {});
await this._networkManager?.authenticate(this.browserContext._options.httpCredentials || null).catch(() => {});
}
async updateExtraHTTPHeaders(): Promise<void> {
if (!this._isNetworkInspectionEnabled())
return;
await this._networkManager?.setExtraHTTPHeaders(this._browserContext._options.extraHTTPHeaders || []).catch(() => {});
await this._networkManager?.setExtraHTTPHeaders(this.browserContext._options.extraHTTPHeaders || []).catch(() => {});
}
async updateRequestInterception(): Promise<void> {
@ -84,32 +84,32 @@ export class CRServiceWorker extends Worker {
}
needsRequestInterception(): boolean {
return this._isNetworkInspectionEnabled() && !!this._browserContext._requestInterceptor;
return this._isNetworkInspectionEnabled() && !!this.browserContext._requestInterceptor;
}
reportRequestFinished(request: network.Request, response: network.Response | null) {
this._browserContext.emit(BrowserContext.Events.RequestFinished, { request, response });
this.browserContext.emit(BrowserContext.Events.RequestFinished, { request, response });
}
requestFailed(request: network.Request, _canceled: boolean) {
this._browserContext.emit(BrowserContext.Events.RequestFailed, request);
this.browserContext.emit(BrowserContext.Events.RequestFailed, request);
}
requestReceivedResponse(response: network.Response) {
this._browserContext.emit(BrowserContext.Events.Response, response);
this.browserContext.emit(BrowserContext.Events.Response, response);
}
requestStarted(request: network.Request, route?: network.RouteDelegate) {
this._browserContext.emit(BrowserContext.Events.Request, request);
this.browserContext.emit(BrowserContext.Events.Request, request);
if (route) {
const r = new network.Route(request, route);
if (this._browserContext._requestInterceptor?.(r, request))
if (this.browserContext._requestInterceptor?.(r, request))
return;
r.continue({ isFallback: true }).catch(() => {});
}
}
private _isNetworkInspectionEnabled(): boolean {
return this._browserContext._options.serviceWorkers !== 'block';
return this.browserContext._options.serviceWorkers !== 'block';
}
}

View File

@ -77,7 +77,7 @@ export class DebugController extends SdkObject {
async resetForReuse() {
const contexts = new Set<BrowserContext>();
for (const page of this._playwright.allPages())
contexts.add(page.context());
contexts.add(page.browserContext);
for (const context of contexts)
await context.resetForReuse(internalMetadata, null);
}
@ -111,7 +111,7 @@ export class DebugController extends SdkObject {
// Update test id attribute.
if (params.testIdAttributeName) {
for (const page of this._playwright.allPages())
page.context().selectors().setTestIdAttributeName(params.testIdAttributeName);
page.browserContext.selectors().setTestIdAttributeName(params.testIdAttributeName);
}
// Toggle the mode.
for (const recorder of await this._allRecorders()) {
@ -170,7 +170,7 @@ export class DebugController extends SdkObject {
private async _allRecorders(): Promise<Recorder[]> {
const contexts = new Set<BrowserContext>();
for (const page of this._playwright.allPages())
contexts.add(page.context());
contexts.add(page.browserContext);
const result = await Promise.all([...contexts].map(c => Recorder.showInspector(c, { omitCallTracking: true }, () => Promise.resolve(new InspectingRecorderApp(this)))));
return result.filter(Boolean) as Recorder[];
}

View File

@ -39,7 +39,7 @@ export class Dialog extends SdkObject {
this._message = message;
this._onHandle = onHandle;
this._defaultValue = defaultValue || '';
this._page._frameManager.dialogDidOpen(this);
this._page.frameManager.dialogDidOpen(this);
this.instrumentation.onDialog(this);
}
@ -62,14 +62,14 @@ export class Dialog extends SdkObject {
async accept(promptText?: string) {
assert(!this._handled, 'Cannot accept dialog which is already handled!');
this._handled = true;
this._page._frameManager.dialogWillClose(this);
this._page.frameManager.dialogWillClose(this);
await this._onHandle(true, promptText);
}
async dismiss() {
assert(!this._handled, 'Cannot dismiss dialog which is already handled!');
this._handled = true;
this._page._frameManager.dialogWillClose(this);
this._page.frameManager.dialogWillClose(this);
await this._onHandle(false);
}

View File

@ -385,7 +385,7 @@ export class DispatcherConnection {
}
function closeReason(sdkObject: SdkObject): string | undefined {
return sdkObject.attribution.page?._closeReason ||
return sdkObject.attribution.page?.closeReason ||
sdkObject.attribution.context?._closeReason ||
sdkObject.attribution.browser?._closeReason;
}

View File

@ -93,10 +93,10 @@ export class PageDispatcher extends Dispatcher<Page, channels.PageChannel, Brows
this.addObjectListener(Page.Events.WebSocket, webSocket => this._dispatchEvent('webSocket', { webSocket: new WebSocketDispatcher(this, webSocket) }));
this.addObjectListener(Page.Events.Worker, worker => this._dispatchEvent('worker', { worker: new WorkerDispatcher(this, worker) }));
this.addObjectListener(Page.Events.Video, (artifact: Artifact) => this._dispatchEvent('video', { artifact: ArtifactDispatcher.from(parentScope, artifact) }));
if (page._video)
this._dispatchEvent('video', { artifact: ArtifactDispatcher.from(this.parentScope(), page._video) });
if (page.video)
this._dispatchEvent('video', { artifact: ArtifactDispatcher.from(this.parentScope(), page.video) });
// Ensure client knows about all frames.
const frames = page._frameManager.frames();
const frames = page.frameManager.frames();
for (let i = 1; i < frames.length; i++)
this._onFrameAttached(frames[i]);
}
@ -183,7 +183,7 @@ export class PageDispatcher extends Dispatcher<Page, channels.PageChannel, Brows
}
const urlMatchers = params.patterns.map(pattern => pattern.regexSource ? new RegExp(pattern.regexSource, pattern.regexFlags!) : pattern.glob!);
await this._page.setClientRequestInterceptor((route, request) => {
const matchesSome = urlMatchers.some(urlMatch => urlMatches(this._page._browserContext._options.baseURL, request.url(), urlMatch));
const matchesSome = urlMatchers.some(urlMatch => urlMatches(this._page.browserContext._options.baseURL, request.url(), urlMatch));
if (!matchesSome)
return false;
this._dispatchEvent('route', { route: RouteDispatcher.from(RequestDispatcher.from(this.parentScope(), request), route) });
@ -347,7 +347,7 @@ export class WorkerDispatcher extends Dispatcher<Worker, channels.WorkerChannel,
constructor(scope: PageDispatcher | BrowserContextDispatcher, worker: Worker) {
super(scope, worker, 'Worker', {
url: worker.url()
url: worker.url
});
this.addObjectListener(Worker.Events.Close, () => this._dispatchEvent('close'));
}

View File

@ -59,7 +59,7 @@ export class WebSocketRouteDispatcher extends Dispatcher<{ guid: string }, chann
static async installIfNeeded(target: Page | BrowserContext) {
const kBindingName = '__pwWebSocketBinding';
const context = target instanceof Page ? target.context() : target;
const context = target instanceof Page ? target.browserContext : target;
if (!context.hasBinding(kBindingName)) {
await context.exposeBinding(kBindingName, false, (source, payload: ws.BindingPayload) => {
if (payload.type === 'onCreate') {

View File

@ -62,7 +62,7 @@ export class FrameExecutionContext extends js.ExecutionContext {
override adoptIfNeeded(handle: js.JSHandle): Promise<js.JSHandle> | null {
if (handle instanceof ElementHandle && handle._context !== this)
return this.frame._page._delegate.adoptElementHandle(handle, this);
return this.frame._page.delegate.adoptElementHandle(handle, this);
return null;
}
@ -85,15 +85,15 @@ export class FrameExecutionContext extends js.ExecutionContext {
injectedScript(): Promise<js.JSHandle<InjectedScript>> {
if (!this._injectedScriptPromise) {
const customEngines: InjectedScriptOptions['customEngines'] = [];
const selectorsRegistry = this.frame._page.context().selectors();
const selectorsRegistry = this.frame._page.browserContext.selectors();
for (const [name, { source }] of selectorsRegistry._engines)
customEngines.push({ name, source });
const sdkLanguage = this.frame.attribution.playwright.options.sdkLanguage;
const options: InjectedScriptOptions = {
sdkLanguage,
testIdAttributeName: selectorsRegistry.testIdAttributeName(),
stableRafCount: this.frame._page._delegate.rafCountForStablePosition(),
browserName: this.frame._page._browserContext._browser.options.name,
stableRafCount: this.frame._page.delegate.rafCountForStablePosition(),
browserName: this.frame._page.browserContext._browser.options.name,
inputFileRoleTextbox: process.env.PLAYWRIGHT_INPUT_FILE_TEXTBOX ? true : false,
customEngines,
};
@ -160,14 +160,14 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
}
async ownerFrame(): Promise<frames.Frame | null> {
const frameId = await this._page._delegate.getOwnerFrame(this);
const frameId = await this._page.delegate.getOwnerFrame(this);
if (!frameId)
return null;
const frame = this._page._frameManager.frame(frameId);
const frame = this._page.frameManager.frame(frameId);
if (frame)
return frame;
for (const page of this._page._browserContext.pages()) {
const frame = page._frameManager.frame(frameId);
for (const page of this._page.browserContext.pages()) {
const frame = page.frameManager.frame(frameId);
if (frame)
return frame;
}
@ -182,7 +182,7 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
const isFrameElement = throwRetargetableDOMError(await this.isIframeElement());
if (!isFrameElement)
return null;
return this._page._delegate.getContentFrame(this);
return this._page.delegate.getContentFrame(this);
}
async generateLocatorString(): Promise<string | undefined> {
@ -219,7 +219,7 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
}
async _scrollRectIntoViewIfNeeded(rect?: types.Rect): Promise<'error:notvisible' | 'error:notconnected' | 'done'> {
return await this._page._delegate.scrollRectIntoViewIfNeeded(this, rect);
return await this._page.delegate.scrollRectIntoViewIfNeeded(this, rect);
}
async _waitAndScrollIntoViewIfNeeded(progress: Progress, waitForVisible: boolean): Promise<void> {
@ -239,7 +239,7 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
const controller = new ProgressController(metadata, this);
return controller.run(
progress => this._waitAndScrollIntoViewIfNeeded(progress, false /* waitForVisible */),
this._page._timeoutSettings.timeout(options));
this._page.timeoutSettings.timeout(options));
}
private async _clickablePoint(): Promise<types.Point | 'error:notvisible' | 'error:notinviewport' | 'error:notconnected'> {
@ -263,7 +263,7 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
};
const [quads, metrics] = await Promise.all([
this._page._delegate.getContentQuads(this),
this._page.delegate.getContentQuads(this),
this._page.mainFrame()._utilityContext().then(utility => utility.evaluate(() => ({ width: innerWidth, height: innerHeight }))),
] as const);
if (quads === 'error:notconnected')
@ -275,7 +275,7 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
const filtered = quads.map(quad => intersectQuadWithViewport(quad)).filter(quad => computeQuadArea(quad) > 0.99);
if (!filtered.length)
return 'error:notinviewport';
if (this._page._browserContext._browser.options.name === 'firefox') {
if (this._page.browserContext._browser.options.name === 'firefox') {
// Firefox internally uses integer coordinates, so 8.x is converted to 8 or 9 when clicking.
//
// This does not work nicely for small elements. For example, 1x1 square with corners
@ -470,7 +470,7 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
});
}
const actionResult = await this._page._frameManager.waitForSignalsCreatedBy(progress, options.waitAfter === true, async () => {
const actionResult = await this._page.frameManager.waitForSignalsCreatedBy(progress, options.waitAfter === true, async () => {
if ((options as any).__testHookBeforePointerAction)
await (options as any).__testHookBeforePointerAction();
progress.throwIfAborted(); // Avoid action that has side-effects.
@ -522,7 +522,7 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
await this._markAsTargetElement(metadata);
const result = await this._hover(progress, options);
return assertDone(throwRetargetableDOMError(result));
}, this._page._timeoutSettings.timeout(options));
}, this._page.timeoutSettings.timeout(options));
}
_hover(progress: Progress, options: types.PointerActionOptions & types.PointerActionWaitOptions): Promise<'error:notconnected' | 'done'> {
@ -535,7 +535,7 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
await this._markAsTargetElement(metadata);
const result = await this._click(progress, { ...options, waitAfter: !options.noWaitAfter });
return assertDone(throwRetargetableDOMError(result));
}, this._page._timeoutSettings.timeout(options));
}, this._page.timeoutSettings.timeout(options));
}
_click(progress: Progress, options: { waitAfter: boolean | 'disabled' } & types.MouseClickOptions & types.PointerActionWaitOptions): Promise<'error:notconnected' | 'done'> {
@ -548,7 +548,7 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
await this._markAsTargetElement(metadata);
const result = await this._dblclick(progress, options);
return assertDone(throwRetargetableDOMError(result));
}, this._page._timeoutSettings.timeout(options));
}, this._page.timeoutSettings.timeout(options));
}
_dblclick(progress: Progress, options: types.MouseMultiClickOptions & types.PointerActionWaitOptions): Promise<'error:notconnected' | 'done'> {
@ -561,7 +561,7 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
await this._markAsTargetElement(metadata);
const result = await this._tap(progress, options);
return assertDone(throwRetargetableDOMError(result));
}, this._page._timeoutSettings.timeout(options));
}, this._page.timeoutSettings.timeout(options));
}
_tap(progress: Progress, options: types.PointerActionWaitOptions): Promise<'error:notconnected' | 'done'> {
@ -574,7 +574,7 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
await this._markAsTargetElement(metadata);
const result = await this._selectOption(progress, elements, values, options);
return throwRetargetableDOMError(result);
}, this._page._timeoutSettings.timeout(options));
}, this._page.timeoutSettings.timeout(options));
}
async _selectOption(progress: Progress, elements: ElementHandle[], values: types.SelectOption[], options: types.CommonActionOptions): Promise<string[] | 'error:notconnected'> {
@ -610,7 +610,7 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
await this._markAsTargetElement(metadata);
const result = await this._fill(progress, value, options);
assertDone(throwRetargetableDOMError(result));
}, this._page._timeoutSettings.timeout(options));
}, this._page.timeoutSettings.timeout(options));
}
async _fill(progress: Progress, value: string, options: types.CommonActionOptions): Promise<'error:notconnected' | 'done'> {
@ -656,7 +656,7 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
}, { force: options.force });
}, options);
assertDone(throwRetargetableDOMError(result));
}, this._page._timeoutSettings.timeout(options));
}, this._page.timeoutSettings.timeout(options));
}
async setInputFiles(metadata: CallMetadata, params: channels.ElementHandleSetInputFilesParams) {
@ -666,7 +666,7 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
await this._markAsTargetElement(metadata);
const result = await this._setInputFiles(progress, inputFileItems);
return assertDone(throwRetargetableDOMError(result));
}, this._page._timeoutSettings.timeout(params));
}, this._page.timeoutSettings.timeout(params));
}
async _setInputFiles(progress: Progress, items: InputFilesItems): Promise<'error:notconnected' | 'done'> {
@ -701,7 +701,7 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
const waitForInputEvent = localDirectory ? this.evaluate(node => new Promise<any>(fulfill => {
node.addEventListener('input', fulfill, { once: true });
})).catch(() => {}) : Promise.resolve();
await this._page._delegate.setInputFilePaths(retargeted, localPathsOrDirectory);
await this._page.delegate.setInputFilePaths(retargeted, localPathsOrDirectory);
await waitForInputEvent;
} else {
await retargeted.evaluateInUtility(([injected, node, files]) =>
@ -735,7 +735,7 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
await this._markAsTargetElement(metadata);
const result = await this._type(progress, text, options);
return assertDone(throwRetargetableDOMError(result));
}, this._page._timeoutSettings.timeout(options));
}, this._page.timeoutSettings.timeout(options));
}
async _type(progress: Progress, text: string, options: { delay?: number } & types.TimeoutOptions & types.StrictOptions): Promise<'error:notconnected' | 'done'> {
@ -755,13 +755,13 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
await this._markAsTargetElement(metadata);
const result = await this._press(progress, key, options);
return assertDone(throwRetargetableDOMError(result));
}, this._page._timeoutSettings.timeout(options));
}, this._page.timeoutSettings.timeout(options));
}
async _press(progress: Progress, key: string, options: { delay?: number, noWaitAfter?: boolean } & types.TimeoutOptions & types.StrictOptions): Promise<'error:notconnected' | 'done'> {
progress.log(`elementHandle.press("${key}")`);
await this.instrumentation.onBeforeInputAction(this, progress.metadata);
return this._page._frameManager.waitForSignalsCreatedBy(progress, !options.noWaitAfter, async () => {
return this._page.frameManager.waitForSignalsCreatedBy(progress, !options.noWaitAfter, async () => {
const result = await this._focus(progress, true /* resetSelectionIfNotFocused */);
if (result !== 'done')
return result;
@ -776,7 +776,7 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
return controller.run(async progress => {
const result = await this._setChecked(progress, true, options);
return assertDone(throwRetargetableDOMError(result));
}, this._page._timeoutSettings.timeout(options));
}, this._page.timeoutSettings.timeout(options));
}
async uncheck(metadata: CallMetadata, options: { position?: types.Point } & types.PointerActionWaitOptions) {
@ -784,7 +784,7 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
return controller.run(async progress => {
const result = await this._setChecked(progress, false, options);
return assertDone(throwRetargetableDOMError(result));
}, this._page._timeoutSettings.timeout(options));
}, this._page.timeoutSettings.timeout(options));
}
async _setChecked(progress: Progress, state: boolean, options: { position?: types.Point } & types.PointerActionWaitOptions): Promise<'error:notconnected' | 'done'> {
@ -808,7 +808,7 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
}
async boundingBox(): Promise<types.Rect | null> {
return this._page._delegate.getBoundingBox(this);
return this._page.delegate.getBoundingBox(this);
}
async ariaSnapshot(options: { ref?: boolean, emitGeneric?: boolean, mode?: 'raw' | 'regex' }): Promise<string> {
@ -818,8 +818,8 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
async screenshot(metadata: CallMetadata, options: ScreenshotOptions & TimeoutOptions = {}): Promise<Buffer> {
const controller = new ProgressController(metadata, this);
return controller.run(
progress => this._page._screenshotter.screenshotElement(progress, this, options),
this._page._timeoutSettings.timeout(options));
progress => this._page.screenshotter.screenshotElement(progress, this, options),
this._page.timeoutSettings.timeout(options));
}
async querySelector(selector: string, options: types.StrictOptions): Promise<ElementHandle | null> {
@ -872,7 +872,7 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
}, state);
}, {});
assertDone(throwRetargetableDOMError(result));
}, this._page._timeoutSettings.timeout(options));
}, this._page.timeoutSettings.timeout(options));
}
async waitForSelector(metadata: CallMetadata, selector: string, options: types.WaitForElementOptions = {}): Promise<ElementHandle<Element> | null> {
@ -881,7 +881,7 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
async _adoptTo(context: FrameExecutionContext): Promise<ElementHandle<T>> {
if (this._context !== context) {
const adopted = await this._page._delegate.adoptElementHandle(this, context);
const adopted = await this._page.delegate.adoptElementHandle(this, context);
this.dispose();
return adopted;
}

View File

@ -27,14 +27,14 @@ export class Download {
private _suggestedFilename: string | undefined;
constructor(page: Page, downloadsPath: string, uuid: string, url: string, suggestedFilename?: string) {
const unaccessibleErrorMessage = page._browserContext._options.acceptDownloads === 'deny' ? 'Pass { acceptDownloads: true } when you are creating your browser context.' : undefined;
const unaccessibleErrorMessage = page.browserContext._options.acceptDownloads === 'deny' ? 'Pass { acceptDownloads: true } when you are creating your browser context.' : undefined;
this.artifact = new Artifact(page, path.join(downloadsPath, uuid), unaccessibleErrorMessage, () => {
return this._page._browserContext.cancelDownload(uuid);
return this._page.browserContext.cancelDownload(uuid);
});
this._page = page;
this.url = url;
this._suggestedFilename = suggestedFilename;
page._browserContext._downloads.add(this);
page.browserContext._downloads.add(this);
if (suggestedFilename !== undefined)
this._fireDownloadEvent();
}

View File

@ -142,7 +142,7 @@ export class ElectronApplication extends SdkObject {
async browserWindow(page: Page): Promise<js.JSHandle<BrowserWindow>> {
// Assume CRPage as Electron is always Chromium.
const targetId = (page._delegate as CRPage)._targetId;
const targetId = (page.delegate as CRPage)._targetId;
const electronHandle = await this._nodeElectronHandlePromise;
return await electronHandle.evaluateHandle(({ BrowserWindow, webContents }, targetId) => {
const wc = webContents.fromDevToolsTargetId(targetId);

View File

@ -58,7 +58,7 @@ export async function prepareFilesForUpload(frame: Frame, params: channels.Eleme
lastModifiedMs?: number,
}[] | undefined = payloads;
if (!frame._page._browserContext._browser._isCollocatedWithServer) {
if (!frame._page.browserContext._browser._isCollocatedWithServer) {
// If the browser is on a different machine read files into buffers.
if (localPaths) {
if (await filesExceedUploadLimit(localPaths))

View File

@ -17,7 +17,7 @@
import { assert } from '../../utils';
import { Browser } from '../browser';
import { BrowserContext, assertBrowserContextIsNotOwned, verifyGeolocation } from '../browserContext';
import { BrowserContext, verifyGeolocation } from '../browserContext';
import { TargetClosedError } from '../errors';
import { kPlaywrightBinding } from '../javascript';
import * as network from '../network';
@ -137,7 +137,7 @@ export class FFBrowser extends Browser {
return;
// Abort the navigation that turned into download.
ffPage._page._frameManager.frameAbortedNavigation(payload.frameId, 'Download is starting');
ffPage._page.frameManager.frameAbortedNavigation(payload.frameId, 'Download is starting');
let originPage = ffPage._page.initializedOrUndefined();
// If it's a new window download, report it on the opener page.
@ -282,7 +282,6 @@ export class FFBrowserContext extends BrowserContext {
}
override async doCreateNewPage(): Promise<Page> {
assertBrowserContextIsNotOwned(this);
const { targetId } = await this._browser.session.send('Browser.newPage', {
browserContextId: this._browserContextId
}).catch(e => {

View File

@ -59,7 +59,7 @@ export class FFNetworkManager {
_onRequestWillBeSent(event: Protocol.Network.requestWillBeSentPayload) {
const redirectedFrom = event.redirectedFrom ? (this._requests.get(event.redirectedFrom) || null) : null;
const frame = redirectedFrom ? redirectedFrom.request.frame() : (event.frameId ? this._page._frameManager.frame(event.frameId) : null);
const frame = redirectedFrom ? redirectedFrom.request.frame() : (event.frameId ? this._page.frameManager.frame(event.frameId) : null);
if (!frame)
return;
if (redirectedFrom)
@ -69,7 +69,7 @@ export class FFNetworkManager {
if (event.isIntercepted)
route = new FFRouteImpl(this._session, request);
this._requests.set(request._id, request);
this._page._frameManager.requestStarted(request.request, route);
this._page.frameManager.requestStarted(request.request, route);
}
_onResponseReceived(event: Protocol.Network.responseReceivedPayload) {
@ -121,7 +121,7 @@ export class FFNetworkManager {
response.setRawResponseHeaders(null);
// Headers size are not available in Firefox.
response.setResponseHeadersSize(null);
this._page._frameManager.requestReceivedResponse(response);
this._page.frameManager.requestReceivedResponse(response);
}
_onRequestFinished(event: Protocol.Network.requestFinishedPayload) {
@ -143,7 +143,7 @@ export class FFNetworkManager {
}
if (event.protocolVersion)
response._setHttpVersion(event.protocolVersion);
this._page._frameManager.reportRequestFinished(request.request, response);
this._page.frameManager.reportRequestFinished(request.request, response);
}
_onRequestFailed(event: Protocol.Network.requestFailedPayload) {
@ -158,7 +158,7 @@ export class FFNetworkManager {
response._requestFinished(-1);
}
request.request._setFailureText(event.errorCode);
this._page._frameManager.requestFailed(request.request, event.errorCode === 'NS_BINDING_ABORTED');
this._page.frameManager.requestFailed(request.request, event.errorCode === 'NS_BINDING_ABORTED');
}
}
@ -204,7 +204,7 @@ class InterceptableRequest {
let postDataBuffer = null;
if (payload.postData)
postDataBuffer = Buffer.from(payload.postData, 'base64');
this.request = new network.Request(frame._page._browserContext, frame, null, redirectedFrom ? redirectedFrom.request : null, payload.navigationId,
this.request = new network.Request(frame._page.browserContext, frame, null, redirectedFrom ? redirectedFrom.request : null, payload.navigationId,
payload.url, internalCauseToResourceType[payload.internalCause] || causeToResourceType[payload.cause] || 'other', payload.method, postDataBuffer, payload.headers);
// "raw" headers are the same as "provisional" headers in Firefox.
this.request.setRawRequestHeaders(null);

View File

@ -120,27 +120,27 @@ export class FFPage implements PageDelegate {
}
_onWebSocketCreated(event: Protocol.Page.webSocketCreatedPayload) {
this._page._frameManager.onWebSocketCreated(webSocketId(event.frameId, event.wsid), event.requestURL);
this._page._frameManager.onWebSocketRequest(webSocketId(event.frameId, event.wsid));
this._page.frameManager.onWebSocketCreated(webSocketId(event.frameId, event.wsid), event.requestURL);
this._page.frameManager.onWebSocketRequest(webSocketId(event.frameId, event.wsid));
}
_onWebSocketClosed(event: Protocol.Page.webSocketClosedPayload) {
if (event.error)
this._page._frameManager.webSocketError(webSocketId(event.frameId, event.wsid), event.error);
this._page._frameManager.webSocketClosed(webSocketId(event.frameId, event.wsid));
this._page.frameManager.webSocketError(webSocketId(event.frameId, event.wsid), event.error);
this._page.frameManager.webSocketClosed(webSocketId(event.frameId, event.wsid));
}
_onWebSocketFrameReceived(event: Protocol.Page.webSocketFrameReceivedPayload) {
this._page._frameManager.webSocketFrameReceived(webSocketId(event.frameId, event.wsid), event.opcode, event.data);
this._page.frameManager.webSocketFrameReceived(webSocketId(event.frameId, event.wsid), event.opcode, event.data);
}
_onWebSocketFrameSent(event: Protocol.Page.webSocketFrameSentPayload) {
this._page._frameManager.onWebSocketFrameSent(webSocketId(event.frameId, event.wsid), event.opcode, event.data);
this._page.frameManager.onWebSocketFrameSent(webSocketId(event.frameId, event.wsid), event.opcode, event.data);
}
_onExecutionContextCreated(payload: Protocol.Runtime.executionContextCreatedPayload) {
const { executionContextId, auxData } = payload;
const frame = this._page._frameManager.frame(auxData.frameId!);
const frame = this._page.frameManager.frame(auxData.frameId!);
if (!frame)
return;
const delegate = new FFExecutionContext(this._session, executionContextId);
@ -178,17 +178,17 @@ export class FFPage implements PageDelegate {
_onLinkClicked(phase: 'before' | 'after') {
if (phase === 'before')
this._page._frameManager.frameWillPotentiallyRequestNavigation();
this._page.frameManager.frameWillPotentiallyRequestNavigation();
else
this._page._frameManager.frameDidPotentiallyRequestNavigation();
this._page.frameManager.frameDidPotentiallyRequestNavigation();
}
_onNavigationStarted(params: Protocol.Page.navigationStartedPayload) {
this._page._frameManager.frameRequestedNavigation(params.frameId, params.navigationId);
this._page.frameManager.frameRequestedNavigation(params.frameId, params.navigationId);
}
_onNavigationAborted(params: Protocol.Page.navigationAbortedPayload) {
this._page._frameManager.frameAbortedNavigation(params.frameId, params.errorText, params.navigationId);
this._page.frameManager.frameAbortedNavigation(params.frameId, params.errorText, params.navigationId);
}
_onNavigationCommitted(params: Protocol.Page.navigationCommittedPayload) {
@ -196,27 +196,27 @@ export class FFPage implements PageDelegate {
if (worker.frameId === params.frameId)
this._onWorkerDestroyed({ workerId });
}
this._page._frameManager.frameCommittedNewDocumentNavigation(params.frameId, params.url, params.name || '', params.navigationId || '', false);
this._page.frameManager.frameCommittedNewDocumentNavigation(params.frameId, params.url, params.name || '', params.navigationId || '', false);
}
_onSameDocumentNavigation(params: Protocol.Page.sameDocumentNavigationPayload) {
this._page._frameManager.frameCommittedSameDocumentNavigation(params.frameId, params.url);
this._page.frameManager.frameCommittedSameDocumentNavigation(params.frameId, params.url);
}
_onFrameAttached(params: Protocol.Page.frameAttachedPayload) {
this._page._frameManager.frameAttached(params.frameId, params.parentFrameId);
this._page.frameManager.frameAttached(params.frameId, params.parentFrameId);
}
_onFrameDetached(params: Protocol.Page.frameDetachedPayload) {
this._page._frameManager.frameDetached(params.frameId);
this._page.frameManager.frameDetached(params.frameId);
}
_onEventFired(payload: Protocol.Page.eventFiredPayload) {
const { frameId, name } = payload;
if (name === 'load')
this._page._frameManager.frameLifecycleEvent(frameId, 'load');
this._page.frameManager.frameLifecycleEvent(frameId, 'load');
if (name === 'DOMContentLoaded')
this._page._frameManager.frameLifecycleEvent(frameId, 'domcontentloaded');
this._page.frameManager.frameLifecycleEvent(frameId, 'domcontentloaded');
}
_onUncaughtError(params: Protocol.Page.uncaughtErrorPayload) {
@ -233,7 +233,7 @@ export class FFPage implements PageDelegate {
if (!context)
return;
// Juggler reports 'warn' for some internal messages generated by the browser.
this._page._addConsoleMessage(type === 'warn' ? 'warning' : type, args.map(arg => createHandle(context, arg)), location);
this._page.addConsoleMessage(type === 'warn' ? 'warning' : type, args.map(arg => createHandle(context, arg)), location);
}
_onDialogOpened(params: Protocol.Page.dialogOpenedPayload) {
@ -252,7 +252,7 @@ export class FFPage implements PageDelegate {
if (!(pageOrError instanceof Error)) {
const context = this._contextIdToContext.get(event.executionContextId);
if (context)
await this._page._onBindingCalled(event.payload, context);
await this._page.onBindingCalled(event.payload, context);
}
}
@ -278,14 +278,14 @@ export class FFPage implements PageDelegate {
});
});
this._workers.set(workerId, { session: workerSession, frameId: event.frameId });
this._page._addWorker(workerId, worker);
this._page.addWorker(workerId, worker);
workerSession.once('Runtime.executionContextCreated', event => {
worker._createExecutionContext(new FFExecutionContext(workerSession, event.executionContextId));
worker.createExecutionContext(new FFExecutionContext(workerSession, event.executionContextId));
});
workerSession.on('Runtime.console', event => {
const { type, args, location } = event;
const context = worker._existingExecutionContext!;
this._page._addConsoleMessage(type, args.map(arg => createHandle(context, arg)), location);
const context = worker.existingExecutionContext!;
this._page.addConsoleMessage(type, args.map(arg => createHandle(context, arg)), location);
});
// Note: we receive worker exceptions directly from the page.
}
@ -297,7 +297,7 @@ export class FFPage implements PageDelegate {
return;
worker.session.dispose();
this._workers.delete(workerId);
this._page._removeWorker(workerId);
this._page.removeWorker(workerId);
}
async _onDispatchMessageFromWorker(event: Protocol.Page.dispatchMessageFromWorkerPayload) {
@ -431,7 +431,7 @@ export class FFPage implements PageDelegate {
});
if (!contentFrameId)
return null;
return this._page._frameManager.frame(contentFrameId);
return this._page.frameManager.frame(contentFrameId);
}
async getOwnerFrame(handle: dom.ElementHandle): Promise<string | null> {

View File

@ -45,8 +45,8 @@ export class FrameSelectors {
}
private _parseSelector(selector: string | ParsedSelector, options?: types.StrictOptions): SelectorInfo {
const strict = typeof options?.strict === 'boolean' ? options.strict : !!this.frame._page.context()._options.strictSelectors;
return this.frame._page.context().selectors().parseSelector(selector, strict);
const strict = typeof options?.strict === 'boolean' ? options.strict : !!this.frame._page.browserContext._options.strictSelectors;
return this.frame._page.browserContext.selectors().parseSelector(selector, strict);
}
async query(selector: string, options?: types.StrictOptions, scope?: ElementHandle): Promise<ElementHandle<Element> | null> {
@ -137,7 +137,7 @@ export class FrameSelectors {
const element = handle.asElement() as ElementHandle<Element> | null;
if (!element)
return null;
const maybeFrame = await frame._page._delegate.getContentFrame(element);
const maybeFrame = await frame._page.delegate.getContentFrame(element);
element.dispose();
if (!maybeFrame)
return null;
@ -163,7 +163,7 @@ export class FrameSelectors {
async function adoptIfNeeded<T extends Node>(handle: ElementHandle<T>, context: FrameExecutionContext): Promise<ElementHandle<T>> {
if (handle._context === context)
return handle;
const adopted = await handle._page._delegate.adoptElementHandle(handle, context);
const adopted = await handle._page.delegate.adoptElementHandle(handle, context);
handle.dispose();
return adopted;
}

View File

@ -171,7 +171,7 @@ export class FrameManager {
if (progress)
progress.cleanupWhenAborted(() => this._signalBarriers.delete(barrier));
const result = await action();
await this._page._delegate.inputActionEpilogue();
await this._page.delegate.inputActionEpilogue();
await barrier.waitFor();
this._signalBarriers.delete(barrier);
// Resolve in the next task, after all waitForNavigations.
@ -306,11 +306,11 @@ export class FrameManager {
this._page.emitOnContext(BrowserContext.Events.Request, request);
if (route) {
const r = new network.Route(request, route);
if (this._page._serverRequestInterceptor?.(r, request))
if (this._page.serverRequestInterceptor?.(r, request))
return;
if (this._page._clientRequestInterceptor?.(r, request))
if (this._page.clientRequestInterceptor?.(r, request))
return;
if (this._page._browserContext._requestInterceptor?.(r, request))
if (this._page.browserContext._requestInterceptor?.(r, request))
return;
r.continue({ isFallback: true }).catch(() => {});
}
@ -563,7 +563,7 @@ export class Frame extends SdkObject {
async raceAgainstEvaluationStallingEvents<T>(cb: () => Promise<T>): Promise<T> {
if (this._pendingDocument)
throw new Error('Frame is currently attempting a navigation');
if (this._page._frameManager._openedDialogs.size)
if (this._page.frameManager._openedDialogs.size)
throw new Error('Open JavaScript dialog prevents evaluation');
const promise = new ManualPromise<T>();
@ -645,9 +645,9 @@ export class Frame extends SdkObject {
}
async goto(metadata: CallMetadata, url: string, options: types.GotoOptions = {}): Promise<network.Response | null> {
const constructedNavigationURL = constructURLBasedOnBaseURL(this._page._browserContext._options.baseURL, url);
const constructedNavigationURL = constructURLBasedOnBaseURL(this._page.browserContext._options.baseURL, url);
const controller = new ProgressController(metadata, this);
return controller.run(progress => this._goto(progress, constructedNavigationURL, options), this._page._timeoutSettings.navigationTimeout(options));
return controller.run(progress => this._goto(progress, constructedNavigationURL, options), this._page.timeoutSettings.navigationTimeout(options));
}
private async _goto(progress: Progress, url: string, options: types.GotoOptions): Promise<network.Response | null> {
@ -670,7 +670,7 @@ export class Frame extends SdkObject {
const navigationEvents: NavigationEvent[] = [];
const collectNavigations = (arg: NavigationEvent) => navigationEvents.push(arg);
this.on(Frame.Events.InternalNavigation, collectNavigations);
const navigateResult = await this._page._delegate.navigateFrame(this, url, referer).finally(
const navigateResult = await this._page.delegate.navigateFrame(this, url, referer).finally(
() => this.off(Frame.Events.InternalNavigation, collectNavigations));
let event: NavigationEvent;
@ -740,7 +740,7 @@ export class Frame extends SdkObject {
}
async frameElement(): Promise<dom.ElementHandle> {
return this._page._delegate.getFrameElement(this);
return this._page.delegate.getFrameElement(this);
}
_context(world: types.World): Promise<dom.FrameExecutionContext> {
@ -792,7 +792,7 @@ export class Frame extends SdkObject {
return controller.run(async progress => {
progress.log(`waiting for ${this._asLocator(selector)}${state === 'attached' ? '' : ' to be ' + state}`);
return await this.waitForSelectorInternal(progress, selector, true, options, scope);
}, this._page._timeoutSettings.timeout(options));
}, this._page.timeoutSettings.timeout(options));
}
async waitForSelectorInternal(progress: Progress, selector: string, performActionPreChecks: boolean, options: types.WaitForElementOptions, scope?: dom.ElementHandle): Promise<dom.ElementHandle<Element> | null> {
@ -916,7 +916,7 @@ export class Frame extends SdkObject {
const tag = `--playwright--set--content--${this._id}--${++this._setContentCounter}--`;
const context = await this._utilityContext();
const lifecyclePromise = new Promise((resolve, reject) => {
this._page._frameManager._consoleMessageTags.set(tag, () => {
this._page.frameManager._consoleMessageTags.set(tag, () => {
// Clear lifecycle right after document.open() - see 'tag' below.
this._onClearLifecycle();
this._waitForLoadState(progress, waitUntil).then(resolve).catch(reject);
@ -931,7 +931,7 @@ export class Frame extends SdkObject {
await Promise.all([contentPromise, lifecyclePromise]);
return null;
});
}, this._page._timeoutSettings.navigationTimeout(options));
}, this._page.timeoutSettings.navigationTimeout(options));
}
name(): string {
@ -976,7 +976,7 @@ export class Frame extends SdkObject {
const result = (await context.evaluateHandle(addScriptContent, { content: content!, type })).asElement()!;
// Another round trip to the browser to ensure that we receive CSP error messages
// (if any) logged asynchronously in a separate task on the content main thread.
if (this._page._delegate.cspErrorsAsynchronousForInlineScripts)
if (this._page.delegate.cspErrorsAsynchronousForInlineScripts)
await context.evaluate(() => true);
return result;
});
@ -1057,7 +1057,7 @@ export class Frame extends SdkObject {
let cspMessage: ConsoleMessage | undefined;
const actionPromise = func().then(r => result = r).catch(e => error = e);
const errorPromise = new Promise<void>(resolve => {
listeners.push(eventsHelper.addEventListener(this._page._browserContext, BrowserContext.Events.Console, (message: ConsoleMessage) => {
listeners.push(eventsHelper.addEventListener(this._page.browserContext, BrowserContext.Events.Console, (message: ConsoleMessage) => {
if (message.page() !== this._page || message.type() !== 'error')
return;
if (message.text().includes('Content-Security-Policy') || message.text().includes('Content Security Policy')) {
@ -1175,7 +1175,7 @@ export class Frame extends SdkObject {
async rafrafTimeoutScreenshotElementWithProgress(progress: Progress, selector: string, timeout: number, options: ScreenshotOptions): Promise<Buffer> {
return await this._retryWithProgressIfNotConnected(progress, selector, true /* strict */, true /* performActionPreChecks */, async handle => {
await handle._frame.rafrafTimeout(timeout);
return await this._page._screenshotter.screenshotElement(progress, handle, options);
return await this._page.screenshotter.screenshotElement(progress, handle, options);
});
}
@ -1183,14 +1183,14 @@ export class Frame extends SdkObject {
const controller = new ProgressController(metadata, this);
return controller.run(async progress => {
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force /* performActionPreChecks */, handle => handle._click(progress, { ...options, waitAfter: !options.noWaitAfter })));
}, this._page._timeoutSettings.timeout(options));
}, this._page.timeoutSettings.timeout(options));
}
async dblclick(metadata: CallMetadata, selector: string, options: types.MouseMultiClickOptions & types.PointerActionWaitOptions = {}) {
const controller = new ProgressController(metadata, this);
return controller.run(async progress => {
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force /* performActionPreChecks */, handle => handle._dblclick(progress, options)));
}, this._page._timeoutSettings.timeout(options));
}, this._page.timeoutSettings.timeout(options));
}
async dragAndDrop(metadata: CallMetadata, source: string, target: string, options: types.DragActionOptions & types.PointerActionWaitOptions = {}) {
@ -1219,37 +1219,37 @@ export class Frame extends SdkObject {
timeout: progress.timeUntilDeadline(),
});
}));
}, this._page._timeoutSettings.timeout(options));
}, this._page.timeoutSettings.timeout(options));
}
async tap(metadata: CallMetadata, selector: string, options: types.PointerActionWaitOptions) {
if (!this._page._browserContext._options.hasTouch)
if (!this._page.browserContext._options.hasTouch)
throw new Error('The page does not support tap. Use hasTouch context option to enable touch support.');
const controller = new ProgressController(metadata, this);
return controller.run(async progress => {
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force /* performActionPreChecks */, handle => handle._tap(progress, options)));
}, this._page._timeoutSettings.timeout(options));
}, this._page.timeoutSettings.timeout(options));
}
async fill(metadata: CallMetadata, selector: string, value: string, options: types.TimeoutOptions & types.StrictOptions & { force?: boolean }) {
const controller = new ProgressController(metadata, this);
return controller.run(async progress => {
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force /* performActionPreChecks */, handle => handle._fill(progress, value, options)));
}, this._page._timeoutSettings.timeout(options));
}, this._page.timeoutSettings.timeout(options));
}
async focus(metadata: CallMetadata, selector: string, options: types.TimeoutOptions & types.StrictOptions = {}) {
const controller = new ProgressController(metadata, this);
await controller.run(async progress => {
dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, true /* performActionPreChecks */, handle => handle._focus(progress)));
}, this._page._timeoutSettings.timeout(options));
}, this._page.timeoutSettings.timeout(options));
}
async blur(metadata: CallMetadata, selector: string, options: types.TimeoutOptions & types.StrictOptions = {}) {
const controller = new ProgressController(metadata, this);
await controller.run(async progress => {
dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, true /* performActionPreChecks */, handle => handle._blur(progress)));
}, this._page._timeoutSettings.timeout(options));
}, this._page.timeoutSettings.timeout(options));
}
async textContent(metadata: CallMetadata, selector: string, options: types.QueryOnSelectorOptions = {}, scope?: dom.ElementHandle): Promise<string | null> {
@ -1314,7 +1314,7 @@ export class Frame extends SdkObject {
return controller.run(async progress => {
progress.log(` checking visibility of ${this._asLocator(selector)}`);
return await this.isVisibleInternal(selector, options, scope);
}, this._page._timeoutSettings.timeout({}));
}, this._page.timeoutSettings.timeout({}));
}
async isVisibleInternal(selector: string, options: types.StrictOptions = {}, scope?: dom.ElementHandle): Promise<boolean> {
@ -1358,14 +1358,14 @@ export class Frame extends SdkObject {
const controller = new ProgressController(metadata, this);
return controller.run(async progress => {
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force /* performActionPreChecks */, handle => handle._hover(progress, options)));
}, this._page._timeoutSettings.timeout(options));
}, this._page.timeoutSettings.timeout(options));
}
async selectOption(metadata: CallMetadata, selector: string, elements: dom.ElementHandle[], values: types.SelectOption[], options: types.CommonActionOptions = {}): Promise<string[]> {
const controller = new ProgressController(metadata, this);
return controller.run(async progress => {
return await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force /* performActionPreChecks */, handle => handle._selectOption(progress, elements, values, options));
}, this._page._timeoutSettings.timeout(options));
}, this._page.timeoutSettings.timeout(options));
}
async setInputFiles(metadata: CallMetadata, selector: string, params: channels.FrameSetInputFilesParams): Promise<channels.FrameSetInputFilesResult> {
@ -1373,35 +1373,35 @@ export class Frame extends SdkObject {
const controller = new ProgressController(metadata, this);
return controller.run(async progress => {
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, params.strict, true /* performActionPreChecks */, handle => handle._setInputFiles(progress, inputFileItems)));
}, this._page._timeoutSettings.timeout(params));
}, this._page.timeoutSettings.timeout(params));
}
async type(metadata: CallMetadata, selector: string, text: string, options: { delay?: number } & types.TimeoutOptions & types.StrictOptions = {}) {
const controller = new ProgressController(metadata, this);
return controller.run(async progress => {
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, true /* performActionPreChecks */, handle => handle._type(progress, text, options)));
}, this._page._timeoutSettings.timeout(options));
}, this._page.timeoutSettings.timeout(options));
}
async press(metadata: CallMetadata, selector: string, key: string, options: { delay?: number, noWaitAfter?: boolean } & types.TimeoutOptions & types.StrictOptions = {}) {
const controller = new ProgressController(metadata, this);
return controller.run(async progress => {
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, true /* performActionPreChecks */, handle => handle._press(progress, key, options)));
}, this._page._timeoutSettings.timeout(options));
}, this._page.timeoutSettings.timeout(options));
}
async check(metadata: CallMetadata, selector: string, options: types.PointerActionWaitOptions = {}) {
const controller = new ProgressController(metadata, this);
return controller.run(async progress => {
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force /* performActionPreChecks */, handle => handle._setChecked(progress, true, options)));
}, this._page._timeoutSettings.timeout(options));
}, this._page.timeoutSettings.timeout(options));
}
async uncheck(metadata: CallMetadata, selector: string, options: types.PointerActionWaitOptions = {}) {
const controller = new ProgressController(metadata, this);
return controller.run(async progress => {
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force /* performActionPreChecks */, handle => handle._setChecked(progress, false, options)));
}, this._page._timeoutSettings.timeout(options));
}, this._page.timeoutSettings.timeout(options));
}
async waitForTimeout(metadata: CallMetadata, timeout: number) {
@ -1415,7 +1415,7 @@ export class Frame extends SdkObject {
const controller = new ProgressController(metadata, this);
return controller.run(async progress => {
return await this._retryWithProgressIfNotConnected(progress, selector, true /* strict */, true /* performActionPreChecks */, handle => handle.ariaSnapshot(options));
}, this._page._timeoutSettings.timeout(options));
}, this._page.timeoutSettings.timeout(options));
}
async expect(metadata: CallMetadata, selector: string, options: FrameExpectParams): Promise<{ matches: boolean, received?: any, log?: string[], timedOut?: boolean }> {
@ -1429,7 +1429,7 @@ export class Frame extends SdkObject {
private async _expectImpl(metadata: CallMetadata, selector: string, options: FrameExpectParams): Promise<{ matches: boolean, received?: any, log?: string[], timedOut?: boolean }> {
const lastIntermediateResult: { received?: any, isSet: boolean } = { isSet: false };
try {
let timeout = this._page._timeoutSettings.timeout(options);
let timeout = this._page.timeoutSettings.timeout(options);
const start = timeout > 0 ? monotonicTime() : 0;
// Step 1: perform locator handlers checkpoint with a specified timeout.
@ -1581,7 +1581,7 @@ export class Frame extends SdkObject {
progress.cleanupWhenAborted(() => handle.evaluate(h => h.abort()).catch(() => {}));
return handle.evaluateHandle(h => h.result);
});
}, this._page._timeoutSettings.timeout(options));
}, this._page.timeoutSettings.timeout(options));
}
async waitForFunctionValueInUtility<R>(progress: Progress, pageFunction: js.Func1<any, R>) {
@ -1656,7 +1656,7 @@ export class Frame extends SdkObject {
return value!;
});
return scope ? scope._context._raceAgainstContextDestroyed(promise) : promise;
}, this._page._timeoutSettings.timeout(options));
}, this._page.timeoutSettings.timeout(options));
}
private _setContext(world: types.World, context: dom.FrameExecutionContext | null) {

View File

@ -322,7 +322,7 @@ export class Touchscreen {
async tap(x: number, y: number, metadata?: CallMetadata) {
if (metadata)
metadata.point = { x, y };
if (!this._page._browserContext._options.hasTouch)
if (!this._page.browserContext._options.hasTouch)
throw new Error('hasTouch must be enabled on the browser context before using the touchscreen.');
await this._raw.tap(x, y, this._page.keyboard._modifiers());
}

View File

@ -75,7 +75,7 @@ export async function launchApp(browserType: BrowserType, options: {
async function installAppIcon(page: Page) {
const icon = await fs.promises.readFile(require.resolve('./chromium/appIcon.png'));
const crPage = page._delegate as CRPage;
const crPage = page.delegate as CRPage;
await crPage._mainFrameSession._client.send('Browser.setDockTile', {
image: icon.toString('base64')
});

View File

@ -144,29 +144,28 @@ export class Page extends SdkObject {
private _eventsToEmitAfterInitialized: { event: string | symbol, args: any[] }[] = [];
private _crashed = false;
readonly openScope = new LongStandingScope();
readonly _browserContext: BrowserContext;
readonly browserContext: BrowserContext;
readonly keyboard: input.Keyboard;
readonly mouse: input.Mouse;
readonly touchscreen: input.Touchscreen;
readonly _timeoutSettings: TimeoutSettings;
readonly _delegate: PageDelegate;
_emulatedSize: EmulatedSize | undefined;
readonly timeoutSettings: TimeoutSettings;
readonly delegate: PageDelegate;
private _emulatedSize: EmulatedSize | undefined;
private _extraHTTPHeaders: types.HeadersArray | undefined;
private _emulatedMedia: Partial<EmulatedMedia> = {};
private _interceptFileChooser = false;
private readonly _pageBindings = new Map<string, PageBinding>();
initScripts: InitScript[] = [];
readonly _screenshotter: Screenshotter;
readonly _frameManager: frames.FrameManager;
readonly screenshotter: Screenshotter;
readonly frameManager: frames.FrameManager;
readonly accessibility: accessibility.Accessibility;
private _workers = new Map<string, Worker>();
readonly pdf: ((options: channels.PagePdfParams) => Promise<Buffer>) | undefined;
readonly coverage: any;
_clientRequestInterceptor: network.RouteHandler | undefined;
_serverRequestInterceptor: network.RouteHandler | undefined;
_ownedContext: BrowserContext | undefined;
_video: Artifact | null = null;
_opener: Page | undefined;
clientRequestInterceptor: network.RouteHandler | undefined;
serverRequestInterceptor: network.RouteHandler | undefined;
video: Artifact | null = null;
private _opener: Page | undefined;
private _isServerSideOnly = false;
private _locatorHandlers = new Map<number, { selector: string, noWaitAfter?: boolean, resolved?: ManualPromise<void> }>();
private _lastLocatorHandlerUid = 0;
@ -175,20 +174,20 @@ export class Page extends SdkObject {
// Aiming at 25 fps by default - each frame is 40ms, but we give some slack with 35ms.
// When throttling for tracing, 200ms between frames, except for 10 frames around the action.
private _frameThrottler = new FrameThrottler(10, 35, 200);
_closeReason: string | undefined;
closeReason: string | undefined;
constructor(delegate: PageDelegate, browserContext: BrowserContext) {
super(browserContext, 'page');
this.attribution.page = this;
this._delegate = delegate;
this._browserContext = browserContext;
this.delegate = delegate;
this.browserContext = browserContext;
this.accessibility = new accessibility.Accessibility(delegate.getAccessibilityTree.bind(delegate));
this.keyboard = new input.Keyboard(delegate.rawKeyboard);
this.mouse = new input.Mouse(delegate.rawMouse, this);
this.touchscreen = new input.Touchscreen(delegate.rawTouchscreen, this);
this._timeoutSettings = new TimeoutSettings(browserContext._timeoutSettings);
this._screenshotter = new Screenshotter(this);
this._frameManager = new frames.FrameManager(this);
this.timeoutSettings = new TimeoutSettings(browserContext._timeoutSettings);
this.screenshotter = new Screenshotter(this);
this.frameManager = new frames.FrameManager(this);
if (delegate.pdf)
this.pdf = delegate.pdf.bind(delegate);
this.coverage = delegate.coverage ? delegate.coverage() : null;
@ -207,15 +206,15 @@ export class Page extends SdkObject {
if (error) {
// Initialization error could have happened because of
// context/browser closure. Just ignore the page.
if (this._browserContext.isClosingOrClosed())
if (this.browserContext.isClosingOrClosed())
return;
this._frameManager.createDummyMainFrameIfNeeded();
this.frameManager.createDummyMainFrameIfNeeded();
}
this._initialized = error || this;
this.emitOnContext(contextEvent, this);
for (const { event, args } of this._eventsToEmitAfterInitialized)
this._browserContext.emit(event, ...args);
this.browserContext.emit(event, ...args);
this._eventsToEmitAfterInitialized = [];
// It may happen that page initialization finishes after Close event has already been sent,
@ -242,7 +241,7 @@ export class Page extends SdkObject {
emitOnContext(event: string | symbol, ...args: any[]) {
if (this._isServerSideOnly)
return;
this._browserContext.emit(event, ...args);
this.browserContext.emit(event, ...args);
}
emitOnContextOnceInitialized(event: string | symbol, ...args: any[]) {
@ -253,7 +252,7 @@ export class Page extends SdkObject {
// and dispatch it to the client later, either on the live Page,
// or on the "errored" Page.
if (this._initialized)
this._browserContext.emit(event, ...args);
this.browserContext.emit(event, ...args);
else
this._eventsToEmitAfterInitialized.push({ event, args });
}
@ -266,7 +265,7 @@ export class Page extends SdkObject {
await this._removeExposedBindings();
await this._removeInitScripts();
await this.setClientRequestInterceptor(undefined);
await this._setServerRequestInterceptor(undefined);
await this.setServerRequestInterceptor(undefined);
await this.setFileChooserIntercepted(false);
// Re-navigate once init scripts are gone.
await this.mainFrame().goto(metadata, 'about:blank');
@ -276,16 +275,16 @@ export class Page extends SdkObject {
this._interceptFileChooser = false;
await Promise.all([
this._delegate.updateEmulatedViewportSize(),
this._delegate.updateEmulateMedia(),
this._delegate.updateFileChooserInterception(),
this.delegate.updateEmulatedViewportSize(),
this.delegate.updateEmulateMedia(),
this.delegate.updateFileChooserInterception(),
]);
await this._delegate.resetForReuse();
await this.delegate.resetForReuse();
}
_didClose() {
this._frameManager.dispose();
this.frameManager.dispose();
this._frameThrottler.dispose();
assert(this._closedState !== 'closed', 'Page closed twice');
this._closedState = 'closed';
@ -296,7 +295,7 @@ export class Page extends SdkObject {
}
_didCrash() {
this._frameManager.dispose();
this.frameManager.dispose();
this._frameThrottler.dispose();
this.emit(Page.Events.Crash);
this._crashed = true;
@ -320,42 +319,38 @@ export class Page extends SdkObject {
this.emit(Page.Events.FileChooser, fileChooser);
}
context(): BrowserContext {
return this._browserContext;
}
opener(): Page | undefined {
return this._opener;
}
mainFrame(): frames.Frame {
return this._frameManager.mainFrame();
return this.frameManager.mainFrame();
}
frames(): frames.Frame[] {
return this._frameManager.frames();
return this.frameManager.frames();
}
setDefaultNavigationTimeout(timeout: number | undefined) {
this._timeoutSettings.setDefaultNavigationTimeout(timeout);
this.timeoutSettings.setDefaultNavigationTimeout(timeout);
}
setDefaultTimeout(timeout: number | undefined) {
this._timeoutSettings.setDefaultTimeout(timeout);
this.timeoutSettings.setDefaultTimeout(timeout);
}
async exposeBinding(name: string, needsHandle: boolean, playwrightBinding: frames.FunctionWithSource) {
if (this._pageBindings.has(name))
throw new Error(`Function "${name}" has been already registered`);
if (this._browserContext._pageBindings.has(name))
if (this.browserContext._pageBindings.has(name))
throw new Error(`Function "${name}" has been already registered in the browser context`);
const binding = new PageBinding(name, playwrightBinding, needsHandle);
this._pageBindings.set(name, binding);
await this._delegate.addInitScript(binding.initScript);
await this.delegate.addInitScript(binding.initScript);
await Promise.all(this.frames().map(frame => frame.evaluateExpression(binding.initScript.source).catch(e => {})));
}
async _removeExposedBindings() {
private async _removeExposedBindings() {
for (const [key, binding] of this._pageBindings) {
if (!binding.internal)
this._pageBindings.delete(key);
@ -364,22 +359,22 @@ export class Page extends SdkObject {
setExtraHTTPHeaders(headers: types.HeadersArray) {
this._extraHTTPHeaders = headers;
return this._delegate.updateExtraHTTPHeaders();
return this.delegate.updateExtraHTTPHeaders();
}
extraHTTPHeaders(): types.HeadersArray | undefined {
return this._extraHTTPHeaders;
}
async _onBindingCalled(payload: string, context: dom.FrameExecutionContext) {
async onBindingCalled(payload: string, context: dom.FrameExecutionContext) {
if (this._closedState === 'closed')
return;
await PageBinding.dispatch(this, payload, context);
}
_addConsoleMessage(type: string, args: js.JSHandle[], location: types.ConsoleMessageLocation, text?: string) {
addConsoleMessage(type: string, args: js.JSHandle[], location: types.ConsoleMessageLocation, text?: string) {
const message = new ConsoleMessage(this, type, text, args, location);
const intercepted = this._frameManager.interceptConsoleMessage(message);
const intercepted = this.frameManager.interceptConsoleMessage(message);
if (intercepted) {
args.forEach(arg => arg.dispose());
return;
@ -395,10 +390,10 @@ export class Page extends SdkObject {
const [response] = await Promise.all([
// Reload must be a new document, and should not be confused with a stray pushState.
this.mainFrame()._waitForNavigation(progress, true /* requiresNewDocument */, options),
this._delegate.reload(),
this.delegate.reload(),
]);
return response;
}), this._timeoutSettings.navigationTimeout(options));
}), this.timeoutSettings.navigationTimeout(options));
}
async goBack(metadata: CallMetadata, options: types.NavigateOptions): Promise<network.Response | null> {
@ -411,14 +406,14 @@ export class Page extends SdkObject {
error = e;
return null;
});
const result = await this._delegate.goBack();
const result = await this.delegate.goBack();
if (!result)
return null;
const response = await waitPromise;
if (error)
throw error;
return response;
}), this._timeoutSettings.navigationTimeout(options));
}), this.timeoutSettings.navigationTimeout(options));
}
async goForward(metadata: CallMetadata, options: types.NavigateOptions): Promise<network.Response | null> {
@ -431,18 +426,18 @@ export class Page extends SdkObject {
error = e;
return null;
});
const result = await this._delegate.goForward();
const result = await this.delegate.goForward();
if (!result)
return null;
const response = await waitPromise;
if (error)
throw error;
return response;
}), this._timeoutSettings.navigationTimeout(options));
}), this.timeoutSettings.navigationTimeout(options));
}
requestGC(): Promise<void> {
return this._delegate.requestGC();
return this.delegate.requestGC();
}
registerLocatorHandler(selector: string, noWaitAfter: boolean | undefined) {
@ -477,7 +472,7 @@ export class Page extends SdkObject {
private async _performWaitForNavigationCheck(progress: Progress) {
if (process.env.PLAYWRIGHT_SKIP_NAVIGATION_CHECK)
return;
const mainFrame = this._frameManager.mainFrame();
const mainFrame = this.frameManager.mainFrame();
if (!mainFrame || !mainFrame.pendingDocument())
return;
const url = mainFrame.pendingDocument()?.request?.url();
@ -535,11 +530,11 @@ export class Page extends SdkObject {
if (options.contrast !== undefined)
this._emulatedMedia.contrast = options.contrast;
await this._delegate.updateEmulateMedia();
await this.delegate.updateEmulateMedia();
}
emulatedMedia(): EmulatedMedia {
const contextOptions = this._browserContext._options;
const contextOptions = this.browserContext._options;
return {
media: this._emulatedMedia.media || 'no-override',
colorScheme: this._emulatedMedia.colorScheme !== undefined ? this._emulatedMedia.colorScheme : contextOptions.colorScheme ?? 'light',
@ -551,47 +546,51 @@ export class Page extends SdkObject {
async setViewportSize(viewportSize: types.Size) {
this._emulatedSize = { viewport: { ...viewportSize }, screen: { ...viewportSize } };
await this._delegate.updateEmulatedViewportSize();
await this.delegate.updateEmulatedViewportSize();
}
viewportSize(): types.Size | null {
return this.emulatedSize()?.viewport || null;
}
setEmulatedSize(emulatedSize: EmulatedSize) {
this._emulatedSize = emulatedSize;
}
emulatedSize(): EmulatedSize | null {
if (this._emulatedSize)
return this._emulatedSize;
const contextOptions = this._browserContext._options;
const contextOptions = this.browserContext._options;
return contextOptions.viewport ? { viewport: contextOptions.viewport, screen: contextOptions.screen || contextOptions.viewport } : null;
}
async bringToFront(): Promise<void> {
await this._delegate.bringToFront();
await this.delegate.bringToFront();
}
async addInitScript(source: string, name?: string) {
const initScript = new InitScript(source, false /* internal */, name);
this.initScripts.push(initScript);
await this._delegate.addInitScript(initScript);
await this.delegate.addInitScript(initScript);
}
async _removeInitScripts() {
private async _removeInitScripts() {
this.initScripts = this.initScripts.filter(script => script.internal);
await this._delegate.removeNonInternalInitScripts();
await this.delegate.removeNonInternalInitScripts();
}
needsRequestInterception(): boolean {
return !!this._clientRequestInterceptor || !!this._serverRequestInterceptor || !!this._browserContext._requestInterceptor;
return !!this.clientRequestInterceptor || !!this.serverRequestInterceptor || !!this.browserContext._requestInterceptor;
}
async setClientRequestInterceptor(handler: network.RouteHandler | undefined): Promise<void> {
this._clientRequestInterceptor = handler;
await this._delegate.updateRequestInterception();
this.clientRequestInterceptor = handler;
await this.delegate.updateRequestInterception();
}
async _setServerRequestInterceptor(handler: network.RouteHandler | undefined): Promise<void> {
this._serverRequestInterceptor = handler;
await this._delegate.updateRequestInterception();
async setServerRequestInterceptor(handler: network.RouteHandler | undefined): Promise<void> {
this.serverRequestInterceptor = handler;
await this.delegate.updateRequestInterception();
}
async expectScreenshot(metadata: CallMetadata, options: ExpectScreenshotOptions = {}): Promise<{ actual?: Buffer, previous?: Buffer, diff?: Buffer, errorMessage?: string, log?: string[] }> {
@ -601,7 +600,7 @@ export class Page extends SdkObject {
} : async (progress: Progress, timeout: number) => {
await this.performActionPreChecks(progress);
await this.mainFrame().rafrafTimeout(timeout);
return await this._screenshotter.screenshotPage(progress, options || {});
return await this.screenshotter.screenshotPage(progress, options || {});
};
const comparator = getComparator('image/png');
@ -629,7 +628,7 @@ export class Page extends SdkObject {
intermediateResult = { errorMessage: comparatorResult.errorMessage, diff: comparatorResult.diff, actual, previous };
return false;
};
const callTimeout = this._timeoutSettings.timeout(options);
const callTimeout = this.timeoutSettings.timeout(options);
return controller.run(async progress => {
let actual: Buffer | undefined;
let previous: Buffer | undefined;
@ -699,26 +698,24 @@ export class Page extends SdkObject {
async screenshot(metadata: CallMetadata, options: ScreenshotOptions & TimeoutOptions = {}): Promise<Buffer> {
const controller = new ProgressController(metadata, this);
return controller.run(
progress => this._screenshotter.screenshotPage(progress, options),
this._timeoutSettings.timeout(options));
progress => this.screenshotter.screenshotPage(progress, options),
this.timeoutSettings.timeout(options));
}
async close(metadata: CallMetadata, options: { runBeforeUnload?: boolean, reason?: string } = {}) {
if (this._closedState === 'closed')
return;
if (options.reason)
this._closeReason = options.reason;
this.closeReason = options.reason;
const runBeforeUnload = !!options.runBeforeUnload;
if (this._closedState !== 'closing') {
this._closedState = 'closing';
// This might throw if the browser context containing the page closes
// while we are trying to close the page.
await this._delegate.closePage(runBeforeUnload).catch(e => debugLogger.log('error', e));
await this.delegate.closePage(runBeforeUnload).catch(e => debugLogger.log('error', e));
}
if (!runBeforeUnload)
await this._closedPromise;
if (this._ownedContext)
await this._ownedContext.close(options);
}
isClosed(): boolean {
@ -733,12 +730,12 @@ export class Page extends SdkObject {
return this._closedState !== 'open' || this._crashed;
}
_addWorker(workerId: string, worker: Worker) {
addWorker(workerId: string, worker: Worker) {
this._workers.set(workerId, worker);
this.emit(Page.Events.Worker, worker);
}
_removeWorker(workerId: string) {
removeWorker(workerId: string) {
const worker = this._workers.get(workerId);
if (!worker)
return;
@ -746,7 +743,7 @@ export class Page extends SdkObject {
this._workers.delete(workerId);
}
_clearWorkers() {
clearWorkers() {
for (const [workerId, worker] of this._workers) {
worker.didClose();
this._workers.delete(workerId);
@ -755,7 +752,7 @@ export class Page extends SdkObject {
async setFileChooserIntercepted(enabled: boolean): Promise<void> {
this._interceptFileChooser = enabled;
await this._delegate.updateFileChooserInterception();
await this.delegate.updateFileChooserInterception();
}
fileChooserIntercepted() {
@ -766,20 +763,20 @@ export class Page extends SdkObject {
this.emit(Page.Events.InternalFrameNavigatedToNewDocument, frame);
const origin = frame.origin();
if (origin)
this._browserContext.addVisitedOrigin(origin);
this.browserContext.addVisitedOrigin(origin);
}
allInitScripts() {
const bindings = [...this._browserContext._pageBindings.values(), ...this._pageBindings.values()];
return [kUtilityInitScript, ...bindings.map(binding => binding.initScript), ...this._browserContext.initScripts, ...this.initScripts];
const bindings = [...this.browserContext._pageBindings.values(), ...this._pageBindings.values()];
return [kUtilityInitScript, ...bindings.map(binding => binding.initScript), ...this.browserContext.initScripts, ...this.initScripts];
}
getBinding(name: string) {
return this._pageBindings.get(name) || this._browserContext._pageBindings.get(name);
return this._pageBindings.get(name) || this.browserContext._pageBindings.get(name);
}
setScreencastOptions(options: { width: number, height: number, quality: number } | null) {
this._delegate.setScreencastOptions(options).catch(e => debugLogger.log('error', e));
this.delegate.setScreencastOptions(options).catch(e => debugLogger.log('error', e));
this._frameThrottler.setThrottlingEnabled(!!options);
}
@ -817,32 +814,28 @@ export class Worker extends SdkObject {
Close: 'close',
};
private _url: string;
readonly url: string;
private _executionContextPromise: Promise<js.ExecutionContext>;
private _executionContextCallback: (value: js.ExecutionContext) => void;
_existingExecutionContext: js.ExecutionContext | null = null;
existingExecutionContext: js.ExecutionContext | null = null;
readonly openScope = new LongStandingScope();
constructor(parent: SdkObject, url: string) {
super(parent, 'worker');
this._url = url;
this.url = url;
this._executionContextCallback = () => {};
this._executionContextPromise = new Promise(x => this._executionContextCallback = x);
}
_createExecutionContext(delegate: js.ExecutionContextDelegate) {
this._existingExecutionContext = new js.ExecutionContext(this, delegate, 'worker');
this._executionContextCallback(this._existingExecutionContext);
return this._existingExecutionContext;
}
url(): string {
return this._url;
createExecutionContext(delegate: js.ExecutionContextDelegate) {
this.existingExecutionContext = new js.ExecutionContext(this, delegate, 'worker');
this._executionContextCallback(this.existingExecutionContext);
return this.existingExecutionContext;
}
didClose() {
if (this._existingExecutionContext)
this._existingExecutionContext.contextDestroyed('Worker was closed');
if (this.existingExecutionContext)
this.existingExecutionContext.contextDestroyed('Worker was closed');
this.emit(Worker.Events.Close, this);
this.openScope.close(new Error('Worker closed'));
}
@ -882,12 +875,12 @@ export class PageBinding {
let result: any;
if (binding.needsHandle) {
const handle = await context.evaluateExpressionHandle(`arg => ${js.accessUtilityScript()}.takeBindingHandle(arg)`, { isFunction: true }, { name, seq }).catch(e => null);
result = await binding.playwrightFunction({ frame: context.frame, page, context: page._browserContext }, handle);
result = await binding.playwrightFunction({ frame: context.frame, page, context: page.browserContext }, handle);
} else {
if (!Array.isArray(serializedArgs))
throw new Error(`serializedArgs is not an array. This can happen when Array.prototype.toJSON is defined incorrectly`);
const args = serializedArgs!.map(a => parseEvaluationResultValue(a));
result = await binding.playwrightFunction({ frame: context.frame, page, context: page._browserContext }, ...args);
result = await binding.playwrightFunction({ frame: context.frame, page, context: page.browserContext }, ...args);
}
context.evaluateExpressionHandle(`arg => ${js.accessUtilityScript()}.deliverBindingResult(arg)`, { isFunction: true }, { name, seq, result }).catch(e => debugLogger.log('error', e));
} catch (error) {

View File

@ -57,13 +57,13 @@ export class RecorderApp extends EventEmitter implements IRecorderApp {
}
async close() {
await this._page.context().close({ reason: 'Recorder window closed' });
await this._page.browserContext.close({ reason: 'Recorder window closed' });
}
private async _init() {
await syncLocalStorageWithSettings(this._page, 'recorder');
await this._page._setServerRequestInterceptor(route => {
await this._page.setServerRequestInterceptor(route => {
if (!route.request().url().startsWith('https://playwright/'))
return false;
@ -86,7 +86,7 @@ export class RecorderApp extends EventEmitter implements IRecorderApp {
this._page.once('close', () => {
this.emit('close');
this._page.context().close({ reason: 'Recorder window closed' }).catch(() => {});
this._page.browserContext.close({ reason: 'Recorder window closed' }).catch(() => {});
});
const mainFrame = this._page.mainFrame();

View File

@ -262,7 +262,7 @@ export class Screenshotter {
async _preparePageForScreenshot(progress: Progress, frame: Frame, screenshotStyle: string | undefined, hideCaret: boolean, disableAnimations: boolean) {
if (disableAnimations)
progress.log(' disabled all CSS animations');
const syncAnimations = this._page._delegate.shouldToggleStyleSheetToSyncAnimations();
const syncAnimations = this._page.delegate.shouldToggleStyleSheetToSyncAnimations();
await this._page.safeNonStallingEvaluateInAllFrames('(' + inPagePrepareForScreenshots.toString() + `)(${JSON.stringify(screenshotStyle)}, ${hideCaret}, ${disableAnimations}, ${syncAnimations})`, 'utility');
if (!process.env.PW_TEST_SCREENSHOT_NO_FONTS_READY) {
progress.log('waiting for fonts to load...');
@ -308,8 +308,8 @@ export class Screenshotter {
progress.throwIfAborted(); // Screenshotting is expensive - avoid extra work.
const shouldSetDefaultBackground = options.omitBackground && format === 'png';
if (shouldSetDefaultBackground) {
await this._page._delegate.setBackgroundColor({ r: 0, g: 0, b: 0, a: 0 });
progress.cleanupWhenAborted(() => this._page._delegate.setBackgroundColor());
await this._page.delegate.setBackgroundColor({ r: 0, g: 0, b: 0, a: 0 });
progress.cleanupWhenAborted(() => this._page.delegate.setBackgroundColor());
}
progress.throwIfAborted(); // Avoid extra work.
@ -317,14 +317,14 @@ export class Screenshotter {
progress.throwIfAborted(); // Avoid extra work.
const quality = format === 'jpeg' ? options.quality ?? 80 : undefined;
const buffer = await this._page._delegate.takeScreenshot(progress, format, documentRect, viewportRect, quality, fitsViewport, options.scale || 'device');
const buffer = await this._page.delegate.takeScreenshot(progress, format, documentRect, viewportRect, quality, fitsViewport, options.scale || 'device');
progress.throwIfAborted(); // Avoid restoring after failure - should be done by cleanup.
await cleanupHighlight();
progress.throwIfAborted(); // Avoid restoring after failure - should be done by cleanup.
if (shouldSetDefaultBackground)
await this._page._delegate.setBackgroundColor();
await this._page.delegate.setBackgroundColor();
progress.throwIfAborted(); // Avoid side effects.
if ((options as any).__testHookAfterScreenshot)
await (options as any).__testHookAfterScreenshot();

View File

@ -17,7 +17,7 @@
import { assert } from '../../utils';
import { Browser } from '../browser';
import { BrowserContext, assertBrowserContextIsNotOwned, verifyGeolocation } from '../browserContext';
import { BrowserContext, verifyGeolocation } from '../browserContext';
import * as network from '../network';
import { WKConnection, WKSession, kPageProxyMessageReceived } from './wkConnection';
import { WKPage } from './wkPage';
@ -121,7 +121,7 @@ export class WKBrowser extends Browser {
// TODO: this is racy, because download might be unrelated any navigation, and we will
// abort navigation that is still running. We should be able to fix this by
// instrumenting policy decision start/proceed/cancel.
page._page._frameManager.frameAbortedNavigation(payload.frameId, 'Download is starting');
page._page.frameManager.frameAbortedNavigation(payload.frameId, 'Download is starting');
let originPage = page._page.initializedOrUndefined();
// If it's a new window download, report it on the opener page.
if (!originPage) {
@ -245,7 +245,6 @@ export class WKBrowserContext extends BrowserContext {
}
override async doCreateNewPage(): Promise<Page> {
assertBrowserContextIsNotOwned(this);
const { pageProxyId } = await this._browser._browserSession.send('Playwright.createPage', { browserContextId: this._browserContextId });
return this._browser._wkPages.get(pageProxyId)!._page;
}
@ -274,11 +273,11 @@ export class WKBrowserContext extends BrowserContext {
}
async doGrantPermissions(origin: string, permissions: string[]) {
await Promise.all(this.pages().map(page => (page._delegate as WKPage)._grantPermissions(origin, permissions)));
await Promise.all(this.pages().map(page => (page.delegate as WKPage)._grantPermissions(origin, permissions)));
}
async doClearPermissions() {
await Promise.all(this.pages().map(page => (page._delegate as WKPage)._clearPermissions()));
await Promise.all(this.pages().map(page => (page.delegate as WKPage)._clearPermissions()));
}
async setGeolocation(geolocation?: types.Geolocation): Promise<void> {
@ -291,40 +290,40 @@ export class WKBrowserContext extends BrowserContext {
async setExtraHTTPHeaders(headers: types.HeadersArray): Promise<void> {
this._options.extraHTTPHeaders = headers;
for (const page of this.pages())
await (page._delegate as WKPage).updateExtraHTTPHeaders();
await (page.delegate as WKPage).updateExtraHTTPHeaders();
}
async setUserAgent(userAgent: string | undefined): Promise<void> {
this._options.userAgent = userAgent;
for (const page of this.pages())
await (page._delegate as WKPage).updateUserAgent();
await (page.delegate as WKPage).updateUserAgent();
}
async setOffline(offline: boolean): Promise<void> {
this._options.offline = offline;
for (const page of this.pages())
await (page._delegate as WKPage).updateOffline();
await (page.delegate as WKPage).updateOffline();
}
async doSetHTTPCredentials(httpCredentials?: types.Credentials): Promise<void> {
this._options.httpCredentials = httpCredentials;
for (const page of this.pages())
await (page._delegate as WKPage).updateHttpCredentials();
await (page.delegate as WKPage).updateHttpCredentials();
}
async doAddInitScript(initScript: InitScript) {
for (const page of this.pages())
await (page._delegate as WKPage)._updateBootstrapScript();
await (page.delegate as WKPage)._updateBootstrapScript();
}
async doRemoveNonInternalInitScripts() {
for (const page of this.pages())
await (page._delegate as WKPage)._updateBootstrapScript();
await (page.delegate as WKPage)._updateBootstrapScript();
}
async doUpdateRequestInterception(): Promise<void> {
for (const page of this.pages())
await (page._delegate as WKPage).updateRequestInterception();
await (page.delegate as WKPage).updateRequestInterception();
}
onClosePersistent() {}

View File

@ -152,7 +152,7 @@ export class RawMouseImpl implements input.RawMouse {
}
async wheel(x: number, y: number, buttons: Set<types.MouseButton>, modifiers: Set<types.KeyboardModifier>, deltaX: number, deltaY: number): Promise<void> {
if (this._page?._browserContext._options.isMobile)
if (this._page?.browserContext._options.isMobile)
throw new Error('Mouse wheel is not supported in mobile WebKit');
await this._session!.send('Page.updateScrollingState');
// Wheel events hit the compositor first, so wait one frame for it to be synced.

View File

@ -57,7 +57,7 @@ export class WKInterceptableRequest {
this._wallTime = event.walltime * 1000;
if (event.request.postData)
postDataBuffer = Buffer.from(event.request.postData, 'base64');
this.request = new network.Request(frame._page._browserContext, frame, null, redirectedFrom?.request || null, documentId, event.request.url,
this.request = new network.Request(frame._page.browserContext, frame, null, redirectedFrom?.request || null, documentId, event.request.url,
resourceType, event.request.method, postDataBuffer, headersObjectToArray(event.request.headers));
}

View File

@ -109,12 +109,12 @@ export class WKPage implements PageDelegate {
const viewportSize = helper.getViewportSizeFromWindowFeatures(opener._nextWindowOpenPopupFeatures);
opener._nextWindowOpenPopupFeatures = undefined;
if (viewportSize)
this._page._emulatedSize = { viewport: viewportSize, screen: viewportSize };
this._page.setEmulatedSize({ viewport: viewportSize, screen: viewportSize });
}
}
private async _initializePageProxySession() {
if (this._page._browserContext.isSettingStorageState())
if (this._page.browserContext.isSettingStorageState())
return;
const promises: Promise<any>[] = [
this._pageProxySession.send('Dialog.enable'),
@ -187,7 +187,7 @@ export class WKPage implements PageDelegate {
promises.push(session.send('Network.setResourceCachingDisabled', { disabled: true }));
promises.push(session.send('Network.addInterception', { url: '.*', stage: 'request', isRegex: true }));
}
if (this._page._browserContext.isSettingStorageState()) {
if (this._page.browserContext.isSettingStorageState()) {
await Promise.all(promises);
return;
}
@ -290,7 +290,7 @@ export class WKPage implements PageDelegate {
let errorText = event.error;
if (errorText.includes('cancelled'))
errorText += '; maybe frame was detached?';
this._page._frameManager.frameAbortedNavigation(this._page.mainFrame()._id, errorText, event.loaderId);
this._page.frameManager.frameAbortedNavigation(this._page.mainFrame()._id, errorText, event.loaderId);
}
handleWindowOpen(event: Protocol.Playwright.windowOpenPayload) {
@ -368,8 +368,8 @@ export class WKPage implements PageDelegate {
eventsHelper.addEventListener(this._session, 'Page.willCheckNavigationPolicy', event => this._onWillCheckNavigationPolicy(event.frameId)),
eventsHelper.addEventListener(this._session, 'Page.didCheckNavigationPolicy', event => this._onDidCheckNavigationPolicy(event.frameId, event.cancel)),
eventsHelper.addEventListener(this._session, 'Page.frameScheduledNavigation', event => this._onFrameScheduledNavigation(event.frameId, event.delay, event.targetIsCurrentFrame)),
eventsHelper.addEventListener(this._session, 'Page.loadEventFired', event => this._page._frameManager.frameLifecycleEvent(event.frameId, 'load')),
eventsHelper.addEventListener(this._session, 'Page.domContentEventFired', event => this._page._frameManager.frameLifecycleEvent(event.frameId, 'domcontentloaded')),
eventsHelper.addEventListener(this._session, 'Page.loadEventFired', event => this._page.frameManager.frameLifecycleEvent(event.frameId, 'load')),
eventsHelper.addEventListener(this._session, 'Page.domContentEventFired', event => this._page.frameManager.frameLifecycleEvent(event.frameId, 'domcontentloaded')),
eventsHelper.addEventListener(this._session, 'Runtime.executionContextCreated', event => this._onExecutionContextCreated(event.context)),
eventsHelper.addEventListener(this._session, 'Runtime.bindingCalled', event => this._onBindingCalled(event.contextId, event.argument)),
eventsHelper.addEventListener(this._session, 'Console.messageAdded', event => this._onConsoleMessage(event)),
@ -381,13 +381,13 @@ export class WKPage implements PageDelegate {
eventsHelper.addEventListener(this._session, 'Network.responseReceived', e => this._onResponseReceived(this._session, e)),
eventsHelper.addEventListener(this._session, 'Network.loadingFinished', e => this._onLoadingFinished(e)),
eventsHelper.addEventListener(this._session, 'Network.loadingFailed', e => this._onLoadingFailed(this._session, e)),
eventsHelper.addEventListener(this._session, 'Network.webSocketCreated', e => this._page._frameManager.onWebSocketCreated(e.requestId, e.url)),
eventsHelper.addEventListener(this._session, 'Network.webSocketWillSendHandshakeRequest', e => this._page._frameManager.onWebSocketRequest(e.requestId)),
eventsHelper.addEventListener(this._session, 'Network.webSocketHandshakeResponseReceived', e => this._page._frameManager.onWebSocketResponse(e.requestId, e.response.status, e.response.statusText)),
eventsHelper.addEventListener(this._session, 'Network.webSocketFrameSent', e => e.response.payloadData && this._page._frameManager.onWebSocketFrameSent(e.requestId, e.response.opcode, e.response.payloadData)),
eventsHelper.addEventListener(this._session, 'Network.webSocketFrameReceived', e => e.response.payloadData && this._page._frameManager.webSocketFrameReceived(e.requestId, e.response.opcode, e.response.payloadData)),
eventsHelper.addEventListener(this._session, 'Network.webSocketClosed', e => this._page._frameManager.webSocketClosed(e.requestId)),
eventsHelper.addEventListener(this._session, 'Network.webSocketFrameError', e => this._page._frameManager.webSocketError(e.requestId, e.errorMessage)),
eventsHelper.addEventListener(this._session, 'Network.webSocketCreated', e => this._page.frameManager.onWebSocketCreated(e.requestId, e.url)),
eventsHelper.addEventListener(this._session, 'Network.webSocketWillSendHandshakeRequest', e => this._page.frameManager.onWebSocketRequest(e.requestId)),
eventsHelper.addEventListener(this._session, 'Network.webSocketHandshakeResponseReceived', e => this._page.frameManager.onWebSocketResponse(e.requestId, e.response.status, e.response.statusText)),
eventsHelper.addEventListener(this._session, 'Network.webSocketFrameSent', e => e.response.payloadData && this._page.frameManager.onWebSocketFrameSent(e.requestId, e.response.opcode, e.response.payloadData)),
eventsHelper.addEventListener(this._session, 'Network.webSocketFrameReceived', e => e.response.payloadData && this._page.frameManager.webSocketFrameReceived(e.requestId, e.response.opcode, e.response.payloadData)),
eventsHelper.addEventListener(this._session, 'Network.webSocketClosed', e => this._page.frameManager.webSocketClosed(e.requestId)),
eventsHelper.addEventListener(this._session, 'Network.webSocketFrameError', e => this._page.frameManager.webSocketError(e.requestId, e.errorMessage)),
];
}
private async _updateState<T extends keyof Protocol.CommandParameters>(
@ -420,7 +420,7 @@ export class WKPage implements PageDelegate {
// one.
if (this._provisionalPage)
return;
this._page._frameManager.frameRequestedNavigation(frameId);
this._page.frameManager.frameRequestedNavigation(frameId);
}
private _onDidCheckNavigationPolicy(frameId: string, cancel?: boolean) {
@ -430,19 +430,19 @@ export class WKPage implements PageDelegate {
// the provisional page. Bail out as we are tracking it.
if (this._provisionalPage)
return;
this._page._frameManager.frameAbortedNavigation(frameId, 'Navigation canceled by policy check');
this._page.frameManager.frameAbortedNavigation(frameId, 'Navigation canceled by policy check');
}
private _onFrameScheduledNavigation(frameId: string, delay: number, targetIsCurrentFrame: boolean) {
if (targetIsCurrentFrame)
this._page._frameManager.frameRequestedNavigation(frameId);
this._page.frameManager.frameRequestedNavigation(frameId);
}
private _handleFrameTree(frameTree: Protocol.Page.FrameResourceTree) {
this._onFrameAttached(frameTree.frame.id, frameTree.frame.parentId || null);
this._onFrameNavigated(frameTree.frame, true);
this._page._frameManager.frameLifecycleEvent(frameTree.frame.id, 'domcontentloaded');
this._page._frameManager.frameLifecycleEvent(frameTree.frame.id, 'load');
this._page.frameManager.frameLifecycleEvent(frameTree.frame.id, 'domcontentloaded');
this._page.frameManager.frameLifecycleEvent(frameTree.frame.id, 'load');
if (!frameTree.childFrames)
return;
@ -451,26 +451,26 @@ export class WKPage implements PageDelegate {
}
_onFrameAttached(frameId: string, parentFrameId: string | null): frames.Frame {
return this._page._frameManager.frameAttached(frameId, parentFrameId);
return this._page.frameManager.frameAttached(frameId, parentFrameId);
}
private _onFrameNavigated(framePayload: Protocol.Page.Frame, initial: boolean) {
const frame = this._page._frameManager.frame(framePayload.id);
const frame = this._page.frameManager.frame(framePayload.id);
assert(frame);
this._removeContextsForFrame(frame, true);
if (!framePayload.parentId)
this._workers.clear();
this._page._frameManager.frameCommittedNewDocumentNavigation(framePayload.id, framePayload.url, framePayload.name || '', framePayload.loaderId, initial);
this._page.frameManager.frameCommittedNewDocumentNavigation(framePayload.id, framePayload.url, framePayload.name || '', framePayload.loaderId, initial);
if (!initial)
this._firstNonInitialNavigationCommittedFulfill();
}
private _onFrameNavigatedWithinDocument(frameId: string, url: string) {
this._page._frameManager.frameCommittedSameDocumentNavigation(frameId, url);
this._page.frameManager.frameCommittedSameDocumentNavigation(frameId, url);
}
private _onFrameDetached(frameId: string) {
this._page._frameManager.frameDetached(frameId);
this._page.frameManager.frameDetached(frameId);
}
private _removeContextsForFrame(frame: frames.Frame, notifyFrame: boolean) {
@ -486,7 +486,7 @@ export class WKPage implements PageDelegate {
private _onExecutionContextCreated(contextPayload: Protocol.Runtime.ExecutionContextDescription) {
if (this._contextIdToContext.has(contextPayload.id))
return;
const frame = this._page._frameManager.frame(contextPayload.frameId);
const frame = this._page.frameManager.frame(contextPayload.frameId);
if (!frame)
return;
const delegate = new WKExecutionContext(this._session, contextPayload.id);
@ -506,7 +506,7 @@ export class WKPage implements PageDelegate {
if (!(pageOrError instanceof Error)) {
const context = this._contextIdToContext.get(contextId);
if (context)
await this._page._onBindingCalled(argument, context);
await this._page.onBindingCalled(argument, context);
}
}
@ -587,7 +587,7 @@ export class WKPage implements PageDelegate {
location
} = this._lastConsoleMessage;
for (let i = count; i < event.count; ++i)
this._page._addConsoleMessage(derivedType, handles, location, handles.length ? undefined : text);
this._page.addConsoleMessage(derivedType, handles, location, handles.length ? undefined : text);
this._lastConsoleMessage.count = event.count;
}
}
@ -600,7 +600,7 @@ export class WKPage implements PageDelegate {
async (accept: boolean, promptText?: string) => {
// TODO: this should actually be a RDP event that notifies about a cancelled navigation attempt.
if (event.type === 'beforeunload' && !accept)
this._page._frameManager.frameAbortedNavigation(this._page.mainFrame()._id, 'navigation cancelled by beforeunload dialog');
this._page.frameManager.frameAbortedNavigation(this._page.mainFrame()._id, 'navigation cancelled by beforeunload dialog');
await this._pageProxySession.send('Dialog.handleJavaScriptDialog', { accept, promptText });
},
event.defaultPrompt));
@ -609,7 +609,7 @@ export class WKPage implements PageDelegate {
private async _onFileChooserOpened(event: {frameId: Protocol.Network.FrameId, element: Protocol.Runtime.RemoteObject}) {
let handle;
try {
const context = await this._page._frameManager.frame(event.frameId)!._mainContext();
const context = await this._page.frameManager.frame(event.frameId)!._mainContext();
handle = createHandle(context, event.element).asElement()!;
} catch (e) {
// During async processing, frame/context may go away. We should not throw.
@ -774,7 +774,7 @@ export class WKPage implements PageDelegate {
private _calculateBootstrapScript(): string {
const scripts: string[] = [];
if (!this._page.context()._options.isMobile) {
if (!this._page.browserContext._options.isMobile) {
scripts.push('delete window.orientation');
scripts.push('delete window.ondevicemotion');
scripts.push('delete window.ondeviceorientation');
@ -802,7 +802,7 @@ export class WKPage implements PageDelegate {
}
private _toolbarHeight(): number {
if (this._page._browserContext._browser?.options.headful)
if (this._page.browserContext._browser?.options.headful)
return hostPlatform === 'mac10.15' ? 55 : 59;
return 0;
}
@ -831,8 +831,8 @@ export class WKPage implements PageDelegate {
// (see https://github.com/microsoft/playwright/issues/16727).
if (process.platform === 'darwin')
return;
if (!omitDeviceScaleFactor && this._page._browserContext._options.deviceScaleFactor)
side = Math.ceil(side * this._page._browserContext._options.deviceScaleFactor);
if (!omitDeviceScaleFactor && this._page.browserContext._options.deviceScaleFactor)
side = Math.ceil(side * this._page.browserContext._options.deviceScaleFactor);
if (side > 32767)
throw new Error('Cannot take screenshot larger than 32767 pixels on any dimension');
}
@ -856,7 +856,7 @@ export class WKPage implements PageDelegate {
});
if (!nodeInfo.contentFrameId)
return null;
return this._page._frameManager.frame(nodeInfo.contentFrameId);
return this._page.frameManager.frame(nodeInfo.contentFrameId);
}
async getOwnerFrame(handle: dom.ElementHandle): Promise<string | null> {
@ -1035,7 +1035,7 @@ export class WKPage implements PageDelegate {
redirectedFrom = request;
}
}
const frame = redirectedFrom ? redirectedFrom.request.frame() : this._page._frameManager.frame(event.frameId);
const frame = redirectedFrom ? redirectedFrom.request.frame() : this._page.frameManager.frame(event.frameId);
// sometimes we get stray network events for detached frames
// TODO(einbinder) why?
if (!frame)
@ -1053,7 +1053,7 @@ export class WKPage implements PageDelegate {
request.request.setRawRequestHeaders(null);
}
this._requestIdToRequest.set(event.requestId, request);
this._page._frameManager.requestStarted(request.request, route);
this._page.frameManager.requestStarted(request.request, route);
}
private _handleRequestRedirect(request: WKInterceptableRequest, requestId: string, responsePayload: Protocol.Network.Response, timestamp: number) {
@ -1064,8 +1064,8 @@ export class WKPage implements PageDelegate {
response.setEncodedBodySize(null);
response._requestFinished(responsePayload.timing ? helper.secondsToRoundishMillis(timestamp - request._timestamp) : -1);
this._requestIdToRequest.delete(requestId);
this._page._frameManager.requestReceivedResponse(response);
this._page._frameManager.reportRequestFinished(request.request, response);
this._page.frameManager.requestReceivedResponse(response);
this._page.frameManager.reportRequestFinished(request.request, response);
}
_onRequestIntercepted(session: WKSession, event: Protocol.Network.requestInterceptedPayload) {
@ -1095,7 +1095,7 @@ export class WKPage implements PageDelegate {
this._requestIdToResponseReceivedPayloadEvent.set(event.requestId, event);
const response = request.createResponse(event.response);
this._page._frameManager.requestReceivedResponse(response);
this._page.frameManager.requestReceivedResponse(response);
if (response.status() === 204 && request.request.isNavigationRequest()) {
this._onLoadingFailed(session, {
@ -1138,7 +1138,7 @@ export class WKPage implements PageDelegate {
this._requestIdToResponseReceivedPayloadEvent.delete(event.requestId);
this._requestIdToRequest.delete(event.requestId);
this._page._frameManager.reportRequestFinished(request.request, response);
this._page.frameManager.reportRequestFinished(request.request, response);
}
_onLoadingFailed(session: WKSession, event: Protocol.Network.loadingFailedPayload) {
@ -1169,7 +1169,7 @@ export class WKPage implements PageDelegate {
}
this._requestIdToRequest.delete(event.requestId);
request.request._setFailureText(event.errorText);
this._page._frameManager.requestFailed(request.request, event.errorText.includes('cancelled'));
this._page.frameManager.requestFailed(request.request, event.errorText.includes('cancelled'));
}
async _grantPermissions(origin: string, permissions: string[]) {

View File

@ -49,7 +49,7 @@ export class WKProvisionalPage {
return (payload: any) => {
// Pretend that the events happened in the same process.
if (payload.frameId)
payload.frameId = this._wkPage._page._frameManager.mainFrame()._id;
payload.frameId = this._wkPage._page.frameManager.mainFrame()._id;
handler(payload);
};
};

View File

@ -48,8 +48,8 @@ export class WKWorkers {
});
});
this._workerSessions.set(event.workerId, workerSession);
worker._createExecutionContext(new WKExecutionContext(workerSession, undefined));
this._page._addWorker(event.workerId, worker);
worker.createExecutionContext(new WKExecutionContext(workerSession, undefined));
this._page.addWorker(event.workerId, worker);
workerSession.on('Console.messageAdded', event => this._onConsoleMessage(worker, event));
Promise.all([
workerSession.send('Runtime.enable'),
@ -57,7 +57,7 @@ export class WKWorkers {
session.send('Worker.initialized', { workerId: event.workerId })
]).catch(e => {
// Worker can go as we are initializing it.
this._page._removeWorker(event.workerId);
this._page.removeWorker(event.workerId);
});
}),
eventsHelper.addEventListener(session, 'Worker.dispatchMessageFromWorker', (event: Protocol.Worker.dispatchMessageFromWorkerPayload) => {
@ -72,13 +72,13 @@ export class WKWorkers {
return;
workerSession.dispose();
this._workerSessions.delete(event.workerId);
this._page._removeWorker(event.workerId);
this._page.removeWorker(event.workerId);
})
];
}
clear() {
this._page._clearWorkers();
this._page.clearWorkers();
this._workerSessions.clear();
}
@ -95,13 +95,13 @@ export class WKWorkers {
derivedType = 'timeEnd';
const handles = (parameters || []).map(p => {
return createHandle(worker._existingExecutionContext!, p);
return createHandle(worker.existingExecutionContext!, p);
});
const location: types.ConsoleMessageLocation = {
url: url || '',
lineNumber: (lineNumber || 1) - 1,
columnNumber: (columnNumber || 1) - 1
};
this._page._addConsoleMessage(derivedType, handles, location, handles.length ? undefined : text);
this._page.addConsoleMessage(derivedType, handles, location, handles.length ? undefined : text);
}
}

View File

@ -142,7 +142,7 @@ export const traceViewerFixtures: Fixtures<TraceViewerFixtures, {}, BaseTestFixt
const contextImpls: any[] = [];
await use(async (traces: string[], { host, port } = {}) => {
const pageImpl = await runTraceViewerApp(traces, browserName, { headless, host, port });
const contextImpl = pageImpl.context();
const contextImpl = pageImpl.browserContext;
const browser = await playwright.chromium.connectOverCDP(contextImpl._browser.options.wsEndpoint);
browsers.push(browser);
contextImpls.push(contextImpl);

View File

@ -23,9 +23,9 @@ const test = testBase.extend<{ crash: () => void }, { dummy: string }>({
if (browserName === 'chromium')
page.goto('chrome://crash').catch(e => {});
else if (browserName === 'webkit')
toImpl(page)._delegate._session.send('Page.crash', {}).catch(e => {});
toImpl(page).delegate._session.send('Page.crash', {}).catch(e => {});
else if (browserName === 'firefox')
toImpl(page)._delegate._session.send('Page.crash', {}).catch(e => {});
toImpl(page).delegate._session.send('Page.crash', {}).catch(e => {});
});
},
// Force a separate worker to avoid messing up with other tests.

View File

@ -37,9 +37,9 @@ it('should have correct execution contexts @smoke', async ({ page, server }) =>
function expectContexts(pageImpl, count, browserName) {
if (browserName === 'chromium')
expect(pageImpl._delegate._mainFrameSession._contextIdToContext.size).toBe(count);
expect(pageImpl.delegate._mainFrameSession._contextIdToContext.size).toBe(count);
else
expect(pageImpl._delegate._contextIdToContext.size).toBe(count);
expect(pageImpl.delegate._contextIdToContext.size).toBe(count);
}
it('should dispose context on navigation', async ({ page, server, toImpl, browserName, isElectron }) => {