playwright-core
Advanced tools
Comparing version 0.11.1-next.1583367207652 to 0.11.1-next.1583444645828
@@ -34,2 +34,3 @@ /** | ||
extraHTTPHeaders?: network.Headers; | ||
offline?: boolean; | ||
}; | ||
@@ -48,2 +49,3 @@ export interface BrowserContext { | ||
setExtraHTTPHeaders(headers: network.Headers): Promise<void>; | ||
setOffline(offline: boolean): Promise<void>; | ||
addInitScript(script: Function | string | { | ||
@@ -50,0 +52,0 @@ path?: string; |
@@ -37,3 +37,3 @@ /** | ||
private _tracingClient; | ||
static connect(transport: ConnectionTransport, slowMo?: number): Promise<CRBrowser>; | ||
static connect(transport: ConnectionTransport, isPersistent: boolean, slowMo?: number): Promise<CRBrowser>; | ||
constructor(connection: CRConnection); | ||
@@ -43,3 +43,4 @@ newContext(options?: BrowserContextOptions): Promise<BrowserContext>; | ||
newPage(options?: BrowserContextOptions): Promise<Page>; | ||
_targetCreated(event: Protocol.Target.targetCreatedPayload): Promise<void>; | ||
_onAttachedToTarget(event: Protocol.Target.attachedToTargetPayload): Promise<void>; | ||
_targetCreated({ targetInfo }: Protocol.Target.targetCreatedPayload): Promise<void>; | ||
_targetDestroyed(event: { | ||
@@ -84,2 +85,3 @@ targetId: string; | ||
setExtraHTTPHeaders(headers: network.Headers): Promise<void>; | ||
setOffline(offline: boolean): Promise<void>; | ||
addInitScript(script: Function | string | { | ||
@@ -86,0 +88,0 @@ path?: string; |
@@ -50,7 +50,26 @@ "use strict"; | ||
this._client.on('Target.targetInfoChanged', this._targetInfoChanged.bind(this)); | ||
this._client.on('Target.attachedToTarget', this._onAttachedToTarget.bind(this)); | ||
} | ||
static async connect(transport, slowMo) { | ||
static async connect(transport, isPersistent, slowMo) { | ||
const connection = new crConnection_1.CRConnection(transport_1.SlowMoTransport.wrap(transport, slowMo)); | ||
const browser = new CRBrowser(connection); | ||
await connection.rootSession.send('Target.setDiscoverTargets', { discover: true }); | ||
const session = connection.rootSession; | ||
const promises = [ | ||
session.send('Target.setDiscoverTargets', { discover: true }), | ||
session.send('Target.setAutoAttach', { autoAttach: true, waitForDebuggerOnStart: true, flatten: true }), | ||
]; | ||
const existingPageAttachPromises = []; | ||
if (isPersistent) { | ||
// First page and background pages in the persistent context are created automatically | ||
// and may be initialized before we enable auto-attach. | ||
function attachToExistingPage({ targetInfo }) { | ||
if (!crTarget_1.CRTarget.isPageType(targetInfo.type)) | ||
return; | ||
existingPageAttachPromises.push(session.send('Target.attachToTarget', { targetId: targetInfo.targetId, flatten: true })); | ||
} | ||
session.on('Target.targetCreated', attachToExistingPage); | ||
Promise.all(promises).then(() => session.off('Target.targetCreated', attachToExistingPage)).catch(helper_1.debugError); | ||
} | ||
await Promise.all(promises); | ||
await Promise.all(existingPageAttachPromises); | ||
return browser; | ||
@@ -72,9 +91,15 @@ } | ||
} | ||
async _targetCreated(event) { | ||
const targetInfo = event.targetInfo; | ||
async _onAttachedToTarget(event) { | ||
if (!crTarget_1.CRTarget.isPageType(event.targetInfo.type)) | ||
return; | ||
const target = this._targets.get(event.targetInfo.targetId); | ||
const session = this._connection.session(event.sessionId); | ||
await target.initializePageSession(session).catch(helper_1.debugError); | ||
} | ||
async _targetCreated({ targetInfo }) { | ||
const { browserContextId } = targetInfo; | ||
const context = (browserContextId && this._contexts.has(browserContextId)) ? this._contexts.get(browserContextId) : this._defaultContext; | ||
const target = new crTarget_1.CRTarget(this, targetInfo, context, () => this._connection.createSession(targetInfo)); | ||
helper_1.assert(!this._targets.has(event.targetInfo.targetId), 'Target should not exist before targetCreated'); | ||
this._targets.set(event.targetInfo.targetId, target); | ||
helper_1.assert(!this._targets.has(targetInfo.targetId), 'Target should not exist before targetCreated'); | ||
this._targets.set(targetInfo.targetId, target); | ||
try { | ||
@@ -108,3 +133,2 @@ switch (targetInfo.type) { | ||
const target = this._targets.get(event.targetId); | ||
target._initializedCallback(false); | ||
this._targets.delete(event.targetId); | ||
@@ -122,3 +146,3 @@ target._didClose(); | ||
_allTargets() { | ||
return Array.from(this._targets.values()).filter(target => target._isInitialized); | ||
return Array.from(this._targets.values()); | ||
} | ||
@@ -188,2 +212,4 @@ async close() { | ||
await this.setGeolocation(this._options.geolocation); | ||
if (this._options.offline) | ||
await this.setOffline(this._options.offline); | ||
} | ||
@@ -213,3 +239,2 @@ _existingPages() { | ||
const target = this._browser._targets.get(targetId); | ||
helper_1.assert(await target._initializedPromise, 'Failed to create target for page'); | ||
const page = await target.page(); | ||
@@ -275,2 +300,7 @@ return page; | ||
} | ||
async setOffline(offline) { | ||
this._options.offline = offline; | ||
for (const page of this._existingPages()) | ||
await page._delegate._networkManager.setOffline(offline); | ||
} | ||
async addInitScript(script, ...args) { | ||
@@ -277,0 +307,0 @@ const source = await helper_1.helper.evaluationScript(script, args); |
@@ -30,3 +30,2 @@ /** | ||
private _requestIdToRequestWillBeSentEvent; | ||
private _offline; | ||
private _credentials; | ||
@@ -36,3 +35,2 @@ private _attemptedAuthentications; | ||
private _protocolRequestInterceptionEnabled; | ||
private _userCacheDisabled; | ||
private _requestIdToInterceptionId; | ||
@@ -45,7 +43,5 @@ private _eventListeners; | ||
authenticate(credentials: Credentials | null): Promise<void>; | ||
setOfflineMode(value: boolean): Promise<void>; | ||
setCacheEnabled(enabled: boolean): Promise<void>; | ||
setOffline(offline: boolean): Promise<void>; | ||
setRequestInterception(value: boolean): Promise<void>; | ||
_updateProtocolRequestInterception(): Promise<void>; | ||
_updateProtocolCacheDisabled(): Promise<void>; | ||
_onRequestWillBeSent(event: Protocol.Network.requestWillBeSentPayload): void; | ||
@@ -52,0 +48,0 @@ _onAuthRequired(event: Protocol.Fetch.authRequiredPayload): void; |
@@ -26,3 +26,2 @@ "use strict"; | ||
this._requestIdToRequestWillBeSentEvent = new Map(); | ||
this._offline = false; | ||
this._credentials = null; | ||
@@ -32,3 +31,2 @@ this._attemptedAuthentications = new Set(); | ||
this._protocolRequestInterceptionEnabled = false; | ||
this._userCacheDisabled = false; | ||
this._requestIdToInterceptionId = new Map(); | ||
@@ -59,6 +57,5 @@ this._client = client; | ||
} | ||
async setOfflineMode(value) { | ||
this._offline = value; | ||
async setOffline(offline) { | ||
await this._client.send('Network.emulateNetworkConditions', { | ||
offline: this._offline, | ||
offline, | ||
// values of 0 remove any active throttling. crbug.com/456324#c9 | ||
@@ -70,6 +67,2 @@ latency: 0, | ||
} | ||
async setCacheEnabled(enabled) { | ||
this._userCacheDisabled = !enabled; | ||
await this._updateProtocolCacheDisabled(); | ||
} | ||
async setRequestInterception(value) { | ||
@@ -86,3 +79,3 @@ this._userRequestInterceptionEnabled = value; | ||
await Promise.all([ | ||
this._updateProtocolCacheDisabled(), | ||
this._client.send('Network.setCacheDisabled', { cacheDisabled: true }), | ||
this._client.send('Fetch.enable', { | ||
@@ -96,3 +89,3 @@ handleAuthRequests: true, | ||
await Promise.all([ | ||
this._updateProtocolCacheDisabled(), | ||
this._client.send('Network.setCacheDisabled', { cacheDisabled: false }), | ||
this._client.send('Fetch.disable') | ||
@@ -102,7 +95,2 @@ ]); | ||
} | ||
async _updateProtocolCacheDisabled() { | ||
await this._client.send('Network.setCacheDisabled', { | ||
cacheDisabled: this._userCacheDisabled || this._protocolRequestInterceptionEnabled | ||
}); | ||
} | ||
_onRequestWillBeSent(event) { | ||
@@ -109,0 +97,0 @@ // Request interception doesn't happen for data URLs with Network Service. |
@@ -52,2 +52,3 @@ /** | ||
_onFrameNavigated(framePayload: Protocol.Page.Frame, initial: boolean): void; | ||
_onFrameRequestedNavigation(payload: Protocol.Page.frameRequestedNavigationPayload): void; | ||
_ensureIsolatedWorld(name: string): Promise<void>; | ||
@@ -74,5 +75,3 @@ _onFrameNavigatedWithinDocument(frameId: string, url: string): void; | ||
setEmulateMedia(mediaType: types.MediaType | null, colorScheme: types.ColorScheme | null): Promise<void>; | ||
setCacheEnabled(enabled: boolean): Promise<void>; | ||
setRequestInterception(enabled: boolean): Promise<void>; | ||
setOfflineMode(value: boolean): Promise<void>; | ||
authenticate(credentials: types.Credentials | null): Promise<void>; | ||
@@ -79,0 +78,0 @@ setFileChooserIntercepted(enabled: boolean): Promise<void>; |
@@ -53,28 +53,28 @@ "use strict"; | ||
async initialize() { | ||
const [, { frameTree }] = await Promise.all([ | ||
const promises = [ | ||
this._client.send('Page.enable'), | ||
this._client.send('Page.getFrameTree'), | ||
]); | ||
this._handleFrameTree(frameTree); | ||
this._eventListeners = [ | ||
helper_1.helper.addEventListener(this._client, 'Inspector.targetCrashed', event => this._onTargetCrashed()), | ||
helper_1.helper.addEventListener(this._client, 'Log.entryAdded', event => this._onLogEntryAdded(event)), | ||
helper_1.helper.addEventListener(this._client, 'Page.fileChooserOpened', event => this._onFileChooserOpened(event)), | ||
helper_1.helper.addEventListener(this._client, 'Page.frameAttached', event => this._onFrameAttached(event.frameId, event.parentFrameId)), | ||
helper_1.helper.addEventListener(this._client, 'Page.frameDetached', event => this._onFrameDetached(event.frameId)), | ||
helper_1.helper.addEventListener(this._client, 'Page.frameNavigated', event => this._onFrameNavigated(event.frame, false)), | ||
helper_1.helper.addEventListener(this._client, 'Page.frameStoppedLoading', event => this._onFrameStoppedLoading(event.frameId)), | ||
helper_1.helper.addEventListener(this._client, 'Page.javascriptDialogOpening', event => this._onDialog(event)), | ||
helper_1.helper.addEventListener(this._client, 'Page.lifecycleEvent', event => this._onLifecycleEvent(event)), | ||
helper_1.helper.addEventListener(this._client, 'Page.navigatedWithinDocument', event => this._onFrameNavigatedWithinDocument(event.frameId, event.url)), | ||
helper_1.helper.addEventListener(this._client, 'Runtime.bindingCalled', event => this._onBindingCalled(event)), | ||
helper_1.helper.addEventListener(this._client, 'Runtime.consoleAPICalled', event => this._onConsoleAPI(event)), | ||
helper_1.helper.addEventListener(this._client, 'Runtime.exceptionThrown', exception => this._handleException(exception.exceptionDetails)), | ||
helper_1.helper.addEventListener(this._client, 'Runtime.executionContextCreated', event => this._onExecutionContextCreated(event.context)), | ||
helper_1.helper.addEventListener(this._client, 'Runtime.executionContextDestroyed', event => this._onExecutionContextDestroyed(event.executionContextId)), | ||
helper_1.helper.addEventListener(this._client, 'Runtime.executionContextsCleared', event => this._onExecutionContextsCleared()), | ||
helper_1.helper.addEventListener(this._client, 'Target.attachedToTarget', event => this._onAttachedToTarget(event)), | ||
helper_1.helper.addEventListener(this._client, 'Target.detachedFromTarget', event => this._onDetachedFromTarget(event)), | ||
]; | ||
const promises = [ | ||
this._client.send('Page.getFrameTree').then(({ frameTree }) => { | ||
this._handleFrameTree(frameTree); | ||
this._eventListeners = [ | ||
helper_1.helper.addEventListener(this._client, 'Inspector.targetCrashed', event => this._onTargetCrashed()), | ||
helper_1.helper.addEventListener(this._client, 'Log.entryAdded', event => this._onLogEntryAdded(event)), | ||
helper_1.helper.addEventListener(this._client, 'Page.fileChooserOpened', event => this._onFileChooserOpened(event)), | ||
helper_1.helper.addEventListener(this._client, 'Page.frameAttached', event => this._onFrameAttached(event.frameId, event.parentFrameId)), | ||
helper_1.helper.addEventListener(this._client, 'Page.frameDetached', event => this._onFrameDetached(event.frameId)), | ||
helper_1.helper.addEventListener(this._client, 'Page.frameNavigated', event => this._onFrameNavigated(event.frame, false)), | ||
helper_1.helper.addEventListener(this._client, 'Page.frameRequestedNavigation', event => this._onFrameRequestedNavigation(event)), | ||
helper_1.helper.addEventListener(this._client, 'Page.frameStoppedLoading', event => this._onFrameStoppedLoading(event.frameId)), | ||
helper_1.helper.addEventListener(this._client, 'Page.javascriptDialogOpening', event => this._onDialog(event)), | ||
helper_1.helper.addEventListener(this._client, 'Page.lifecycleEvent', event => this._onLifecycleEvent(event)), | ||
helper_1.helper.addEventListener(this._client, 'Page.navigatedWithinDocument', event => this._onFrameNavigatedWithinDocument(event.frameId, event.url)), | ||
helper_1.helper.addEventListener(this._client, 'Runtime.bindingCalled', event => this._onBindingCalled(event)), | ||
helper_1.helper.addEventListener(this._client, 'Runtime.consoleAPICalled', event => this._onConsoleAPI(event)), | ||
helper_1.helper.addEventListener(this._client, 'Runtime.exceptionThrown', exception => this._handleException(exception.exceptionDetails)), | ||
helper_1.helper.addEventListener(this._client, 'Runtime.executionContextCreated', event => this._onExecutionContextCreated(event.context)), | ||
helper_1.helper.addEventListener(this._client, 'Runtime.executionContextDestroyed', event => this._onExecutionContextDestroyed(event.executionContextId)), | ||
helper_1.helper.addEventListener(this._client, 'Runtime.executionContextsCleared', event => this._onExecutionContextsCleared()), | ||
helper_1.helper.addEventListener(this._client, 'Target.attachedToTarget', event => this._onAttachedToTarget(event)), | ||
helper_1.helper.addEventListener(this._client, 'Target.detachedFromTarget', event => this._onDetachedFromTarget(event)), | ||
]; | ||
}), | ||
this._client.send('Log.enable', {}), | ||
@@ -105,2 +105,4 @@ this._client.send('Page.setLifecycleEventsEnabled', { enabled: true }), | ||
promises.push(this.updateExtraHTTPHeaders()); | ||
if (options.offline) | ||
promises.push(this._networkManager.setOffline(options.offline)); | ||
for (const binding of this._browserContext._pageBindings.values()) | ||
@@ -110,2 +112,3 @@ promises.push(this._initBinding(binding)); | ||
promises.push(this.evaluateOnNewDocument(source)); | ||
promises.push(this._client.send('Runtime.runIfWaitingForDebugger')); | ||
await Promise.all(promises); | ||
@@ -150,2 +153,5 @@ } | ||
} | ||
_onFrameRequestedNavigation(payload) { | ||
this._page._frameManager.frameRequestedNavigation(payload.frameId); | ||
} | ||
async _ensureIsolatedWorld(name) { | ||
@@ -319,11 +325,5 @@ if (this._isolatedWorlds.has(name)) | ||
} | ||
setCacheEnabled(enabled) { | ||
return this._networkManager.setCacheEnabled(enabled); | ||
} | ||
async setRequestInterception(enabled) { | ||
await this._networkManager.setRequestInterception(enabled); | ||
} | ||
async setOfflineMode(value) { | ||
await this._networkManager.setOfflineMode(value); | ||
} | ||
async authenticate(credentials) { | ||
@@ -421,3 +421,3 @@ await this._networkManager.authenticate(credentials); | ||
nodeInfo.node.frameId : null; | ||
await documentElement.dispose(); | ||
documentElement.dispose(); | ||
return frameId; | ||
@@ -424,0 +424,0 @@ } |
@@ -59,7 +59,3 @@ "use strict"; | ||
return; | ||
await client.send('Runtime.releaseObject', { objectId: remoteObject.objectId }).catch(error => { | ||
// Exceptions might happen in case of a page been navigated or closed. | ||
// Swallow these since they are harmless and we don't leak anything in this case. | ||
helper_1.debugError(error); | ||
}); | ||
await client.send('Runtime.releaseObject', { objectId: remoteObject.objectId }).catch(error => { }); | ||
} | ||
@@ -66,0 +62,0 @@ exports.releaseObject = releaseObject; |
@@ -28,12 +28,13 @@ /** | ||
readonly sessionFactory: () => Promise<CRSession>; | ||
private _pagePromiseFulfill; | ||
private _pagePromiseReject; | ||
private _pagePromise; | ||
_crPage: CRPage | null; | ||
private _workerPromise; | ||
readonly _initializedPromise: Promise<boolean>; | ||
_initializedCallback: (success: boolean) => void; | ||
_isInitialized: boolean; | ||
static fromPage(page: Page): CRTarget; | ||
static isPageType(type: string): boolean; | ||
constructor(browser: CRBrowser, targetInfo: Protocol.Target.TargetInfo, browserContext: CRBrowserContext, sessionFactory: () => Promise<CRSession>); | ||
_didClose(): void; | ||
page(): Promise<Page | null>; | ||
initializePageSession(session: CRSession): Promise<void>; | ||
serviceWorker(): Promise<Worker | null>; | ||
@@ -40,0 +41,0 @@ url(): string; |
@@ -28,6 +28,7 @@ "use strict"; | ||
constructor(browser, targetInfo, browserContext, sessionFactory) { | ||
this._pagePromiseFulfill = null; | ||
this._pagePromiseReject = null; | ||
this._pagePromise = null; | ||
this._crPage = null; | ||
this._workerPromise = null; | ||
this._initializedCallback = () => { }; | ||
this._targetInfo = targetInfo; | ||
@@ -38,18 +39,8 @@ this._browser = browser; | ||
this.sessionFactory = sessionFactory; | ||
this._initializedPromise = new Promise(fulfill => this._initializedCallback = fulfill).then(async (success) => { | ||
if (!success) | ||
return false; | ||
const opener = this.opener(); | ||
if (!opener || !opener._pagePromise || this.type() !== 'page') | ||
return true; | ||
const openerPage = await opener._pagePromise; | ||
if (!openerPage.listenerCount(events_1.Events.Page.Popup)) | ||
return true; | ||
const popupPage = await this.page(); | ||
openerPage.emit(events_1.Events.Page.Popup, popupPage); | ||
return true; | ||
}); | ||
this._isInitialized = this._targetInfo.type !== 'page' || this._targetInfo.url !== ''; | ||
if (this._isInitialized) | ||
this._initializedCallback(true); | ||
if (CRTarget.isPageType(targetInfo.type)) { | ||
this._pagePromise = new Promise((fulfill, reject) => { | ||
this._pagePromiseFulfill = fulfill; | ||
this._pagePromiseReject = reject; | ||
}); | ||
} | ||
} | ||
@@ -59,2 +50,5 @@ static fromPage(page) { | ||
} | ||
static isPageType(type) { | ||
return type === 'page' || type === 'background_page'; | ||
} | ||
_didClose() { | ||
@@ -65,14 +59,26 @@ if (this._crPage) | ||
async page() { | ||
if ((this._targetInfo.type === 'page' || this._targetInfo.type === 'background_page') && !this._pagePromise) { | ||
this._pagePromise = this.sessionFactory().then(async (client) => { | ||
this._crPage = new crPage_1.CRPage(client, this._browser, this._browserContext); | ||
const page = this._crPage.page(); | ||
page[targetSymbol] = this; | ||
client.once(crConnection_1.CRSessionEvents.Disconnected, () => page._didDisconnect()); | ||
await this._crPage.initialize(); | ||
return page; | ||
}); | ||
} | ||
return this._pagePromise; | ||
} | ||
async initializePageSession(session) { | ||
this._crPage = new crPage_1.CRPage(session, this._browser, this._browserContext); | ||
const page = this._crPage.page(); | ||
page[targetSymbol] = this; | ||
session.once(crConnection_1.CRSessionEvents.Disconnected, () => page._didDisconnect()); | ||
try { | ||
await this._crPage.initialize(); | ||
this._pagePromiseFulfill(page); | ||
} | ||
catch (error) { | ||
this._pagePromiseReject(error); | ||
} | ||
if (this.type() !== 'page') | ||
return; | ||
const opener = this.opener(); | ||
if (!opener) | ||
return; | ||
const openerPage = await opener.page(); | ||
if (!openerPage) | ||
return; | ||
openerPage.emit(events_1.Events.Page.Popup, page); | ||
} | ||
async serviceWorker() { | ||
@@ -115,7 +121,2 @@ if (this._targetInfo.type !== 'service_worker') | ||
this._targetInfo = targetInfo; | ||
if (!this._isInitialized && (this._targetInfo.type !== 'page' || this._targetInfo.url !== '')) { | ||
this._isInitialized = true; | ||
this._initializedCallback(true); | ||
return; | ||
} | ||
} | ||
@@ -122,0 +123,0 @@ } |
@@ -35,3 +35,5 @@ "use strict"; | ||
// Only go through asynchronous calls if required. | ||
return this._delegate.evaluate(this, returnByValue, pageFunction, ...args); | ||
return await this.frame._page._frameManager.waitForNavigationsCreatedBy(async () => { | ||
return this._delegate.evaluate(this, returnByValue, pageFunction, ...args); | ||
}); | ||
} | ||
@@ -48,6 +50,8 @@ const toDispose = []; | ||
try { | ||
result = await this._delegate.evaluate(this, returnByValue, pageFunction, ...adopted); | ||
result = await this.frame._page._frameManager.waitForNavigationsCreatedBy(async () => { | ||
return this._delegate.evaluate(this, returnByValue, pageFunction, ...adopted); | ||
}); | ||
} | ||
finally { | ||
await Promise.all(toDispose.map(handlePromise => handlePromise.then(handle => handle.dispose()))); | ||
toDispose.map(handlePromise => handlePromise.then(handle => handle.dispose())); | ||
} | ||
@@ -84,3 +88,3 @@ return result; | ||
if (!handle.asElement()) | ||
await handle.dispose(); | ||
handle.dispose(); | ||
return handle.asElement(); | ||
@@ -95,3 +99,3 @@ } | ||
const properties = await arrayHandle.getProperties(); | ||
await arrayHandle.dispose(); | ||
arrayHandle.dispose(); | ||
const result = []; | ||
@@ -103,3 +107,3 @@ for (const property of properties.values()) { | ||
else | ||
await property.dispose(); | ||
property.dispose(); | ||
} | ||
@@ -122,3 +126,3 @@ return result; | ||
const result = await elementHandle.evaluate(pageFunction, ...args); | ||
await elementHandle.dispose(); | ||
elementHandle.dispose(); | ||
return result; | ||
@@ -129,3 +133,3 @@ }; | ||
const result = await arrayHandle.evaluate(pageFunction, ...args); | ||
await arrayHandle.dispose(); | ||
arrayHandle.dispose(); | ||
return result; | ||
@@ -226,8 +230,10 @@ }; | ||
await this._waitForHitTargetAt(point, options); | ||
let restoreModifiers; | ||
if (options && options.modifiers) | ||
restoreModifiers = await this._page.keyboard._ensureModifiers(options.modifiers); | ||
await action(point); | ||
if (restoreModifiers) | ||
await this._page.keyboard._ensureModifiers(restoreModifiers); | ||
await this._page._frameManager.waitForNavigationsCreatedBy(async () => { | ||
let restoreModifiers; | ||
if (options && options.modifiers) | ||
restoreModifiers = await this._page.keyboard._ensureModifiers(options.modifiers); | ||
await action(point); | ||
if (restoreModifiers) | ||
await this._page.keyboard._ensureModifiers(restoreModifiers); | ||
}); | ||
} | ||
@@ -258,13 +264,17 @@ hover(options) { | ||
} | ||
return this._evaluateInUtility((injected, node, ...optionsToSelect) => injected.selectOptions(node, optionsToSelect), ...options); | ||
return await this._page._frameManager.waitForNavigationsCreatedBy(async () => { | ||
return this._evaluateInUtility((injected, node, ...optionsToSelect) => injected.selectOptions(node, optionsToSelect), ...options); | ||
}); | ||
} | ||
async fill(value) { | ||
helper_1.assert(helper_1.helper.isString(value), 'Value must be string. Found value "' + value + '" of type "' + (typeof value) + '"'); | ||
const error = await this._evaluateInUtility((injected, node, value) => injected.fill(node, value), value); | ||
if (error) | ||
throw new Error(error); | ||
if (value) | ||
await this._page.keyboard.sendCharacters(value); | ||
else | ||
await this._page.keyboard.press('Delete'); | ||
await this._page._frameManager.waitForNavigationsCreatedBy(async () => { | ||
const error = await this._evaluateInUtility((injected, node, value) => injected.fill(node, value), value); | ||
if (error) | ||
throw new Error(error); | ||
if (value) | ||
await this._page.keyboard.sendCharacters(value); | ||
else | ||
await this._page.keyboard.press('Delete'); | ||
}); | ||
} | ||
@@ -290,3 +300,5 @@ async setInputFiles(...files) { | ||
})); | ||
await this._page._delegate.setInputFiles(this, filePayloads); | ||
await this._page._frameManager.waitForNavigationsCreatedBy(async () => { | ||
await this._page._delegate.setInputFiles(this, filePayloads); | ||
}); | ||
} | ||
@@ -304,8 +316,12 @@ async focus() { | ||
async type(text, options) { | ||
await this.focus(); | ||
await this._page.keyboard.type(text, options); | ||
await this._page._frameManager.waitForNavigationsCreatedBy(async () => { | ||
await this.focus(); | ||
await this._page.keyboard.type(text, options); | ||
}); | ||
} | ||
async press(key, options) { | ||
await this.focus(); | ||
await this._page.keyboard.press(key, options); | ||
await this._page._frameManager.waitForNavigationsCreatedBy(async () => { | ||
await this.focus(); | ||
await this._page.keyboard.press(key, options); | ||
}); | ||
} | ||
@@ -312,0 +328,0 @@ async check(options) { |
@@ -93,2 +93,3 @@ /** | ||
setExtraHTTPHeaders(headers: network.Headers): Promise<void>; | ||
setOffline(offline: boolean): Promise<void>; | ||
addInitScript(script: Function | string | { | ||
@@ -95,0 +96,0 @@ path?: string; |
@@ -240,2 +240,4 @@ "use strict"; | ||
await this.setExtraHTTPHeaders(this._options.extraHTTPHeaders); | ||
if (this._options.offline) | ||
await this.setOffline(this._options.offline); | ||
} | ||
@@ -308,2 +310,7 @@ _existingPages() { | ||
} | ||
async setOffline(offline) { | ||
if (offline) | ||
throw new Error('Offline mode is not implemented in Firefox'); | ||
this._options.offline = offline; | ||
} | ||
async addInitScript(script, ...args) { | ||
@@ -310,0 +317,0 @@ const source = await helper_1.helper.evaluationScript(script, args); |
@@ -116,7 +116,3 @@ "use strict"; | ||
objectId: handle._remoteObject.objectId, | ||
}).catch(error => { | ||
// Exceptions might happen in case of a page been navigated or closed. | ||
// Swallow these since they are harmless and we don't leak anything in this case. | ||
helper_1.debugError(error); | ||
}); | ||
}).catch(error => { }); | ||
} | ||
@@ -123,0 +119,0 @@ async handleJSONValue(handle) { |
@@ -64,5 +64,3 @@ /** | ||
setEmulateMedia(mediaType: types.MediaType | null, colorScheme: types.ColorScheme | null): Promise<void>; | ||
setCacheEnabled(enabled: boolean): Promise<void>; | ||
setRequestInterception(enabled: boolean): Promise<void>; | ||
setOfflineMode(enabled: boolean): Promise<void>; | ||
authenticate(credentials: types.Credentials | null): Promise<void>; | ||
@@ -69,0 +67,0 @@ setFileChooserIntercepted(enabled: boolean): Promise<void>; |
@@ -229,11 +229,5 @@ "use strict"; | ||
} | ||
async setCacheEnabled(enabled) { | ||
await this._session.send('Page.setCacheDisabled', { cacheDisabled: !enabled }); | ||
} | ||
async setRequestInterception(enabled) { | ||
await this._networkManager.setRequestInterception(enabled); | ||
} | ||
async setOfflineMode(enabled) { | ||
throw new Error('Offline mode not implemented in Firefox'); | ||
} | ||
async authenticate(credentials) { | ||
@@ -381,3 +375,3 @@ await this._session.send('Network.setAuthCredentials', credentials || { username: null, password: null }); | ||
const result = items.find(item => item.frame === frame); | ||
await Promise.all(items.map(item => item === result ? Promise.resolve() : item.handle.dispose())); | ||
items.map(item => item === result ? Promise.resolve() : item.handle.dispose()); | ||
if (!result) | ||
@@ -384,0 +378,0 @@ throw new Error('Frame has been detached.'); |
@@ -46,2 +46,3 @@ /** | ||
readonly _consoleMessageTags: Map<string, ConsoleTagHandler>; | ||
private _navigationRequestCollectors; | ||
constructor(page: Page); | ||
@@ -52,2 +53,5 @@ mainFrame(): Frame; | ||
frameAttached(frameId: string, parentFrameId: string | null | undefined): Frame; | ||
waitForNavigationsCreatedBy<T>(action: () => Promise<T>): Promise<T>; | ||
frameRequestedNavigation(frameId: string): void; | ||
_cancelFrameRequestedNavigation(frameId: string): void; | ||
frameCommittedNewDocumentNavigation(frameId: string, url: string, name: string, documentId: string, initial: boolean): void; | ||
@@ -54,0 +58,0 @@ frameCommittedSameDocumentNavigation(frameId: string, url: string): void; |
@@ -30,2 +30,3 @@ "use strict"; | ||
this._consoleMessageTags = new Map(); | ||
this._navigationRequestCollectors = new Set(); | ||
this._page = page; | ||
@@ -73,3 +74,28 @@ this._mainFrame = undefined; | ||
} | ||
async waitForNavigationsCreatedBy(action) { | ||
const frameIds = new Set(); | ||
this._navigationRequestCollectors.add(frameIds); | ||
try { | ||
const result = await action(); | ||
if (!frameIds.size) | ||
return result; | ||
const frames = Array.from(frameIds.values()).map(frameId => this._frames.get(frameId)); | ||
await Promise.all(frames.map(frame => frame.waitForNavigation({ waitUntil: [] }))).catch(e => { }); | ||
await new Promise(platform.makeWaitForNextTask()); | ||
return result; | ||
} | ||
finally { | ||
this._navigationRequestCollectors.delete(frameIds); | ||
} | ||
} | ||
frameRequestedNavigation(frameId) { | ||
for (const frameIds of this._navigationRequestCollectors) | ||
frameIds.add(frameId); | ||
} | ||
_cancelFrameRequestedNavigation(frameId) { | ||
for (const frameIds of this._navigationRequestCollectors) | ||
frameIds.delete(frameId); | ||
} | ||
frameCommittedNewDocumentNavigation(frameId, url, name, documentId, initial) { | ||
this._cancelFrameRequestedNavigation(frameId); | ||
const frame = this._frames.get(frameId); | ||
@@ -88,2 +114,3 @@ for (const child of frame.childFrames()) | ||
frameCommittedSameDocumentNavigation(frameId, url) { | ||
this._cancelFrameRequestedNavigation(frameId); | ||
const frame = this._frames.get(frameId); | ||
@@ -165,2 +192,3 @@ if (!frame) | ||
if (!isCurrentDocument) { | ||
this._cancelFrameRequestedNavigation(frame._id); | ||
let errorText = request.failure().errorText; | ||
@@ -177,2 +205,3 @@ if (canceled) | ||
provisionalLoadFailed(frame, documentId, error) { | ||
this._cancelFrameRequestedNavigation(frame._id); | ||
for (const watcher of frame._documentWatchers) | ||
@@ -182,2 +211,3 @@ watcher(documentId, new Error(error)); | ||
_removeFramesRecursively(frame) { | ||
this._cancelFrameRequestedNavigation(frame._id); | ||
for (const child of frame.childFrames()) | ||
@@ -267,3 +297,3 @@ this._removeFramesRecursively(child); | ||
const result = await elementHandle.evaluate(pageFunction, ...args); | ||
await elementHandle.dispose(); | ||
elementHandle.dispose(); | ||
return result; | ||
@@ -275,3 +305,3 @@ }; | ||
const result = await arrayHandle.evaluate(pageFunction, ...args); | ||
await arrayHandle.dispose(); | ||
arrayHandle.dispose(); | ||
return result; | ||
@@ -487,3 +517,3 @@ }; | ||
const adopted = this._page._delegate.adoptElementHandle(handle, mainContext); | ||
await handle.dispose(); | ||
handle.dispose(); | ||
return adopted; | ||
@@ -499,3 +529,3 @@ } | ||
const adopted = this._page._delegate.adoptElementHandle(handle, mainContext); | ||
await handle.dispose(); | ||
handle.dispose(); | ||
return adopted; | ||
@@ -670,3 +700,3 @@ } | ||
await handle.click(options); | ||
await handle.dispose(); | ||
handle.dispose(); | ||
} | ||
@@ -676,3 +706,3 @@ async dblclick(selector, options) { | ||
await handle.dblclick(options); | ||
await handle.dispose(); | ||
handle.dispose(); | ||
} | ||
@@ -682,3 +712,3 @@ async tripleclick(selector, options) { | ||
await handle.tripleclick(options); | ||
await handle.dispose(); | ||
handle.dispose(); | ||
} | ||
@@ -688,3 +718,3 @@ async fill(selector, value, options) { | ||
await handle.fill(value); | ||
await handle.dispose(); | ||
handle.dispose(); | ||
} | ||
@@ -694,3 +724,3 @@ async focus(selector, options) { | ||
await handle.focus(); | ||
await handle.dispose(); | ||
handle.dispose(); | ||
} | ||
@@ -700,3 +730,3 @@ async hover(selector, options) { | ||
await handle.hover(options); | ||
await handle.dispose(); | ||
handle.dispose(); | ||
} | ||
@@ -707,3 +737,3 @@ async select(selector, value, options) { | ||
const result = await handle.select(...values); | ||
await handle.dispose(); | ||
handle.dispose(); | ||
return result; | ||
@@ -714,3 +744,3 @@ } | ||
await handle.type(text, options); | ||
await handle.dispose(); | ||
handle.dispose(); | ||
} | ||
@@ -720,3 +750,3 @@ async check(selector, options) { | ||
await handle.check(options); | ||
await handle.dispose(); | ||
handle.dispose(); | ||
} | ||
@@ -726,3 +756,3 @@ async uncheck(selector, options) { | ||
await handle.uncheck(options); | ||
await handle.dispose(); | ||
handle.dispose(); | ||
} | ||
@@ -766,3 +796,3 @@ async waitFor(selectorOrFunctionOrTimeout, options = {}, ...args) { | ||
if (!result.asElement()) { | ||
await result.dispose(); | ||
result.dispose(); | ||
return null; | ||
@@ -867,3 +897,3 @@ } | ||
if (success) | ||
await success.dispose(); | ||
success.dispose(); | ||
return; | ||
@@ -875,3 +905,3 @@ } | ||
if (!error && await context.evaluate(s => !s, success).catch(e => true)) { | ||
await success.dispose(); | ||
success.dispose(); | ||
return; | ||
@@ -878,0 +908,0 @@ } |
@@ -56,3 +56,3 @@ "use strict"; | ||
const result = properties.get(propertyName) || null; | ||
await objectHandle.dispose(); | ||
objectHandle.dispose(); | ||
return result; | ||
@@ -59,0 +59,0 @@ } |
@@ -43,5 +43,3 @@ /** | ||
setEmulateMedia(mediaType: types.MediaType | null, colorScheme: types.ColorScheme | null): Promise<void>; | ||
setCacheEnabled(enabled: boolean): Promise<void>; | ||
setRequestInterception(enabled: boolean): Promise<void>; | ||
setOfflineMode(enabled: boolean): Promise<void>; | ||
authenticate(credentials: types.Credentials | null): Promise<void>; | ||
@@ -83,5 +81,3 @@ setFileChooserIntercepted(enabled: boolean): Promise<void>; | ||
extraHTTPHeaders: network.Headers | null; | ||
cacheEnabled: boolean | null; | ||
interceptNetwork: boolean | null; | ||
offlineMode: boolean | null; | ||
credentials: types.Credentials | null; | ||
@@ -132,2 +128,6 @@ hasTouch: boolean | null; | ||
mainFrame(): frames.Frame; | ||
frame(options: { | ||
name?: string; | ||
url?: types.URLMatch; | ||
}): frames.Frame | null; | ||
frames(): frames.Frame[]; | ||
@@ -187,6 +187,4 @@ setDefaultNavigationTimeout(timeout: number): void; | ||
}, ...args: any[]): Promise<void>; | ||
setCacheEnabled(enabled?: boolean): Promise<void>; | ||
route(url: types.URLMatch, handler: (request: network.Request) => void): Promise<void>; | ||
_requestStarted(request: network.Request): void; | ||
setOfflineMode(enabled: boolean): Promise<void>; | ||
authenticate(credentials: types.Credentials | null): Promise<void>; | ||
@@ -193,0 +191,0 @@ screenshot(options?: types.ScreenshotOptions): Promise<platform.BufferType>; |
@@ -78,5 +78,3 @@ "use strict"; | ||
extraHTTPHeaders: null, | ||
cacheEnabled: null, | ||
interceptNetwork: null, | ||
offlineMode: null, | ||
credentials: null, | ||
@@ -115,3 +113,3 @@ hasTouch: null, | ||
if (!this.listenerCount(events_1.Events.Page.FileChooser)) { | ||
await handle.dispose(); | ||
handle.dispose(); | ||
return; | ||
@@ -131,2 +129,10 @@ } | ||
} | ||
frame(options) { | ||
helper_1.assert(options.name || options.url, 'Either name or url matcher should be specified'); | ||
return this.frames().find(f => { | ||
if (options.name) | ||
return f.name() === options.name; | ||
return platform.urlMatches(f.url(), options.url); | ||
}) || null; | ||
} | ||
frames() { | ||
@@ -265,8 +271,2 @@ return this._frameManager.frames(); | ||
} | ||
async setCacheEnabled(enabled = true) { | ||
if (this._state.cacheEnabled === enabled) | ||
return; | ||
this._state.cacheEnabled = enabled; | ||
await this._delegate.setCacheEnabled(enabled); | ||
} | ||
async route(url, handler) { | ||
@@ -291,8 +291,2 @@ if (!this._state.interceptNetwork) { | ||
} | ||
async setOfflineMode(enabled) { | ||
if (this._state.offlineMode === enabled) | ||
return; | ||
this._state.offlineMode = enabled; | ||
await this._delegate.setOfflineMode(enabled); | ||
} | ||
async authenticate(credentials) { | ||
@@ -299,0 +293,0 @@ this._state.credentials = credentials; |
@@ -47,3 +47,3 @@ "use strict"; | ||
const { browserServer, transport } = await this._launchServer(options, 'local'); | ||
const browser = await crBrowser_1.CRBrowser.connect(transport, options && options.slowMo); | ||
const browser = await crBrowser_1.CRBrowser.connect(transport, false, options && options.slowMo); | ||
// Hack: for typical launch scenario, ensure that close waits for actual process termination. | ||
@@ -60,3 +60,3 @@ browser.close = () => browserServer.close(); | ||
const { browserServer, transport } = await this._launchServer(options, 'persistent', userDataDir); | ||
const browser = await crBrowser_1.CRBrowser.connect(transport); | ||
const browser = await crBrowser_1.CRBrowser.connect(transport, true); | ||
const firstPage = new Promise(r => browser._defaultContext.once(events_1.Events.BrowserContext.Page, r)); | ||
@@ -132,3 +132,3 @@ await helper_1.helper.waitWithTimeout(firstPage, 'first page', timeout); | ||
return await platform.connectToWebsocket(options.wsEndpoint, transport => { | ||
return crBrowser_1.CRBrowser.connect(transport, options.slowMo); | ||
return crBrowser_1.CRBrowser.connect(transport, false, options.slowMo); | ||
}); | ||
@@ -135,0 +135,0 @@ } |
@@ -25,3 +25,3 @@ "use strict"; | ||
return await platform.connectToWebsocket(url, transport => { | ||
return crBrowser_1.CRBrowser.connect(transport); | ||
return crBrowser_1.CRBrowser.connect(transport, false); | ||
}); | ||
@@ -28,0 +28,0 @@ } |
@@ -75,2 +75,3 @@ /** | ||
setExtraHTTPHeaders(headers: network.Headers): Promise<void>; | ||
setOffline(offline: boolean): Promise<void>; | ||
addInitScript(script: Function | string | { | ||
@@ -77,0 +78,0 @@ path?: string; |
@@ -172,2 +172,4 @@ "use strict"; | ||
await this.setGeolocation(this._options.geolocation); | ||
if (this._options.offline) | ||
await this.setOffline(this._options.offline); | ||
} | ||
@@ -244,2 +246,7 @@ _existingPages() { | ||
} | ||
async setOffline(offline) { | ||
this._options.offline = offline; | ||
for (const page of this._existingPages()) | ||
await page._delegate.updateOffline(); | ||
} | ||
async addInitScript(script, ...args) { | ||
@@ -246,0 +253,0 @@ const source = await helper_1.helper.evaluationScript(script, args); |
@@ -58,2 +58,3 @@ /** | ||
private _forAllSessions; | ||
private _onFrameScheduledNavigation; | ||
private _onFrameStoppedLoading; | ||
@@ -78,5 +79,4 @@ private _onLifecycleEvent; | ||
_updateViewport(updateTouch: boolean): Promise<void>; | ||
setCacheEnabled(enabled: boolean): Promise<void>; | ||
setRequestInterception(enabled: boolean): Promise<void>; | ||
setOfflineMode(offline: boolean): Promise<void>; | ||
updateOffline(): Promise<void>; | ||
authenticate(credentials: types.Credentials | null): Promise<void>; | ||
@@ -83,0 +83,0 @@ setFileChooserIntercepted(enabled: boolean): Promise<void>; |
@@ -107,6 +107,2 @@ "use strict"; | ||
promises.push(session.send('Network.setInterceptionEnabled', { enabled: true, interceptRequests: true })); | ||
if (this._page._state.offlineMode) | ||
promises.push(session.send('Network.setEmulateOfflineState', { offline: true })); | ||
if (this._page._state.cacheEnabled === false) | ||
promises.push(session.send('Network.setResourceCachingDisabled', { disabled: true })); | ||
const contextOptions = this._page.context()._options; | ||
@@ -123,2 +119,4 @@ if (contextOptions.userAgent) | ||
promises.push(session.send('Network.setExtraHTTPHeaders', { headers: this._calculateExtraHTTPHeaders() })); | ||
if (contextOptions.offline) | ||
promises.push(session.send('Network.setEmulateOfflineState', { offline: true })); | ||
if (this._page._state.hasTouch) | ||
@@ -174,2 +172,3 @@ promises.push(session.send('Page.setTouchEmulationEnabled', { enabled: true })); | ||
helper_1.helper.addEventListener(this._session, 'Page.frameDetached', event => this._onFrameDetached(event.frameId)), | ||
helper_1.helper.addEventListener(this._session, 'Page.frameScheduledNavigation', event => this._onFrameScheduledNavigation(event.frameId)), | ||
helper_1.helper.addEventListener(this._session, 'Page.frameStoppedLoading', event => this._onFrameStoppedLoading(event.frameId)), | ||
@@ -202,2 +201,5 @@ helper_1.helper.addEventListener(this._session, 'Page.loadEventFired', event => this._onLifecycleEvent(event.frameId, 'load')), | ||
} | ||
_onFrameScheduledNavigation(frameId) { | ||
this._page._frameManager.frameRequestedNavigation(frameId); | ||
} | ||
_onFrameStoppedLoading(frameId) { | ||
@@ -365,11 +367,7 @@ this._page._frameManager.frameStoppedLoading(frameId); | ||
} | ||
async setCacheEnabled(enabled) { | ||
const disabled = !enabled; | ||
await this._updateState('Network.setResourceCachingDisabled', { disabled }); | ||
} | ||
async setRequestInterception(enabled) { | ||
await this._updateState('Network.setInterceptionEnabled', { enabled, interceptRequests: enabled }); | ||
} | ||
async setOfflineMode(offline) { | ||
await this._updateState('Network.setEmulateOfflineState', { offline }); | ||
async updateOffline() { | ||
await this._updateState('Network.setEmulateOfflineState', { offline: !!this._page.context()._options.offline }); | ||
} | ||
@@ -549,3 +547,3 @@ async authenticate(credentials) { | ||
const result = items.find(item => item.frame === frame); | ||
await Promise.all(items.map(item => item === result ? Promise.resolve() : item.handle.dispose())); | ||
items.map(item => item === result ? Promise.resolve() : item.handle.dispose()); | ||
if (!result) | ||
@@ -552,0 +550,0 @@ throw new Error('Frame has been detached.'); |
@@ -48,9 +48,5 @@ "use strict"; | ||
return; | ||
await client.send('Runtime.releaseObject', { objectId: remoteObject.objectId }).catch(error => { | ||
// Exceptions might happen in case of a page been navigated or closed. | ||
// Swallow these since they are harmless and we don't leak anything in this case. | ||
helper_1.debugError(error); | ||
}); | ||
await client.send('Runtime.releaseObject', { objectId: remoteObject.objectId }).catch(error => { }); | ||
} | ||
exports.releaseObject = releaseObject; | ||
//# sourceMappingURL=wkProtocolHelper.js.map |
{ | ||
"name": "playwright-core", | ||
"version": "0.11.1-next.1583367207652", | ||
"version": "0.11.1-next.1583444645828", | ||
"description": "A high-level API to automate web browsers", | ||
@@ -11,3 +11,3 @@ "repository": "github:Microsoft/playwright", | ||
"playwright": { | ||
"chromium_revision": "745253", | ||
"chromium_revision": "747023", | ||
"firefox_revision": "1032", | ||
@@ -14,0 +14,0 @@ "webkit_revision": "1168" |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
2442334
57370