diff --git a/packages/playwright-core/src/server/bidi/bidiPage.ts b/packages/playwright-core/src/server/bidi/bidiPage.ts index 2ec693768ff19..5e1e53c6b1d6f 100644 --- a/packages/playwright-core/src/server/bidi/bidiPage.ts +++ b/packages/playwright-core/src/server/bidi/bidiPage.ts @@ -126,6 +126,7 @@ export class BidiPage implements PageDelegate { const delegate = new BidiExecutionContext(this._session, realmInfo); const worker = new Worker(this._page, realmInfo.origin); this._realmToWorkerContext.set(realmInfo.realm, worker.createExecutionContext(delegate)); + worker.workerScriptLoaded(); this._page.addWorker(realmInfo.realm, worker); return; } diff --git a/packages/playwright-core/src/server/chromium/crBrowser.ts b/packages/playwright-core/src/server/chromium/crBrowser.ts index a81e3d88b9beb..52ac6ff7a58b7 100644 --- a/packages/playwright-core/src/server/chromium/crBrowser.ts +++ b/packages/playwright-core/src/server/chromium/crBrowser.ts @@ -49,6 +49,7 @@ export class CRBrowser extends Browser { _serviceWorkers = new Map(); _devtools?: CRDevTools; private _version = ''; + private _majorVersion = 0; private _tracingRecording = false; private _tracingClient: CRSession | undefined; @@ -68,6 +69,10 @@ export class CRBrowser extends Browser { const version = await session.send('Browser.getVersion'); browser._version = version.product.substring(version.product.indexOf('/') + 1); + try { + browser._majorVersion = +browser._version.split('.')[0]; + } catch { + } browser._userAgent = version.userAgent; // We don't trust the option as it may lie in case of connectOverCDP where remote browser // may have been launched with different options. @@ -130,6 +135,10 @@ export class CRBrowser extends Browser { return this._version; } + majorVersion() { + return this._majorVersion; + } + userAgent(): string { return this._userAgent; } diff --git a/packages/playwright-core/src/server/chromium/crPage.ts b/packages/playwright-core/src/server/chromium/crPage.ts index 43f810ebd6df4..6d0a1b087e7ac 100644 --- a/packages/playwright-core/src/server/chromium/crPage.ts +++ b/packages/playwright-core/src/server/chromium/crPage.ts @@ -750,6 +750,10 @@ class FrameSession { session.once('Runtime.executionContextCreated', async event => { worker.createExecutionContext(new CRExecutionContext(session, event.context)); }); + if (this._crPage._browserContext._browser.majorVersion() >= 143) + session.on('Inspector.workerScriptLoaded', () => worker.workerScriptLoaded()); + else + worker.workerScriptLoaded(); // This might fail if the target is closed before we initialize. session._sendMayFail('Runtime.enable'); // TODO: attribute workers to the right frame. diff --git a/packages/playwright-core/src/server/chromium/crServiceWorker.ts b/packages/playwright-core/src/server/chromium/crServiceWorker.ts index 31cd981582fdd..3ef163e43de28 100644 --- a/packages/playwright-core/src/server/chromium/crServiceWorker.ts +++ b/packages/playwright-core/src/server/chromium/crServiceWorker.ts @@ -36,6 +36,10 @@ export class CRServiceWorker extends Worker { session.once('Runtime.executionContextCreated', event => { this.createExecutionContext(new CRExecutionContext(session, event.context)); }); + if (this.browserContext._browser.majorVersion() >= 143) + session.on('Inspector.workerScriptLoaded', () => this.workerScriptLoaded()); + else + this.workerScriptLoaded(); if (this._networkManager && this._isNetworkInspectionEnabled()) { this.updateRequestInterception(); diff --git a/packages/playwright-core/src/server/firefox/ffPage.ts b/packages/playwright-core/src/server/firefox/ffPage.ts index 16dd3186e7e73..bc7d917b72657 100644 --- a/packages/playwright-core/src/server/firefox/ffPage.ts +++ b/packages/playwright-core/src/server/firefox/ffPage.ts @@ -280,6 +280,7 @@ export class FFPage implements PageDelegate { this._page.addWorker(workerId, worker); workerSession.once('Runtime.executionContextCreated', event => { worker.createExecutionContext(new FFExecutionContext(workerSession, event.executionContextId)); + worker.workerScriptLoaded(); }); workerSession.on('Runtime.console', event => { const { type, args, location } = event; diff --git a/packages/playwright-core/src/server/page.ts b/packages/playwright-core/src/server/page.ts index 86392fd7fa532..2d829e4e8444e 100644 --- a/packages/playwright-core/src/server/page.ts +++ b/packages/playwright-core/src/server/page.ts @@ -870,24 +870,29 @@ export class Worker extends SdkObject { }; readonly url: string; - private _executionContextPromise: Promise; - private _executionContextCallback: (value: js.ExecutionContext) => void; + private _executionContextPromise = new ManualPromise(); + private _workerScriptLoaded = false; existingExecutionContext: js.ExecutionContext | null = null; readonly openScope = new LongStandingScope(); constructor(parent: SdkObject, url: string) { super(parent, 'worker'); 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); + if (this._workerScriptLoaded) + this._executionContextPromise.resolve(this.existingExecutionContext); return this.existingExecutionContext; } + workerScriptLoaded() { + this._workerScriptLoaded = true; + if (this.existingExecutionContext) + this._executionContextPromise.resolve(this.existingExecutionContext); + } + didClose() { if (this.existingExecutionContext) this.existingExecutionContext.contextDestroyed('Worker was closed'); diff --git a/packages/playwright-core/src/server/webkit/wkWorkers.ts b/packages/playwright-core/src/server/webkit/wkWorkers.ts index 689ca95ccc15b..71f06e2c9f424 100644 --- a/packages/playwright-core/src/server/webkit/wkWorkers.ts +++ b/packages/playwright-core/src/server/webkit/wkWorkers.ts @@ -49,6 +49,7 @@ export class WKWorkers { }); this._workerSessions.set(event.workerId, workerSession); worker.createExecutionContext(new WKExecutionContext(workerSession, undefined)); + worker.workerScriptLoaded(); this._page.addWorker(event.workerId, worker); workerSession.on('Console.messageAdded', event => this._onConsoleMessage(worker, event)); Promise.all([