From b9b24cf963a503ddeb9ff34ea74a40e40a265c2e Mon Sep 17 00:00:00 2001
From: jrandolf <101637635+jrandolf@users.noreply.github.com>
Date: Mon, 22 Aug 2022 14:03:45 +0200
Subject: [PATCH] chore: use deferred promises in web worker (#8824)
---
.../puppeteer.webworker.executioncontext.md | 4 +-
docs/api/puppeteer.webworker.md | 2 +-
src/common/WebWorker.ts | 61 ++++++++-----------
3 files changed, 30 insertions(+), 37 deletions(-)
diff --git a/docs/api/puppeteer.webworker.executioncontext.md b/docs/api/puppeteer.webworker.executioncontext.md
index 39b2a607..1db00f6c 100644
--- a/docs/api/puppeteer.webworker.executioncontext.md
+++ b/docs/api/puppeteer.webworker.executioncontext.md
@@ -4,7 +4,9 @@ sidebar_label: WebWorker.executionContext
# WebWorker.executionContext() method
-Returns the ExecutionContext the WebWorker runs in
+> Warning: This API is now obsolete.
+>
+> Do not use directly.
**Signature:**
diff --git a/docs/api/puppeteer.webworker.md b/docs/api/puppeteer.webworker.md
index 91d89fda..cc48ca04 100644
--- a/docs/api/puppeteer.webworker.md
+++ b/docs/api/puppeteer.webworker.md
@@ -42,5 +42,5 @@ for (const worker of page.workers()) {
| ----------------------------------------------------------------------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [evaluate(pageFunction, args)](./puppeteer.webworker.evaluate.md) | | If the function passed to the worker.evaluate
returns a Promise, then worker.evaluate
would wait for the promise to resolve and return its value. If the function passed to the worker.evaluate
returns a non-serializable value, then worker.evaluate
resolves to undefined
. DevTools Protocol also supports transferring some additional values that are not serializable by JSON
: -0
, NaN
, Infinity
, -Infinity
, and bigint literals. Shortcut for await worker.executionContext()).evaluate(pageFunction, ...args)
. |
| [evaluateHandle(pageFunction, args)](./puppeteer.webworker.evaluatehandle.md) | | The only difference between worker.evaluate
and worker.evaluateHandle
is that worker.evaluateHandle
returns in-page object (JSHandle). If the function passed to the worker.evaluateHandle
returns a Promise
, then worker.evaluateHandle
would wait for the promise to resolve and return its value. Shortcut for await worker.executionContext()).evaluateHandle(pageFunction, ...args)
|
-| [executionContext()](./puppeteer.webworker.executioncontext.md) | | Returns the ExecutionContext the WebWorker runs in |
+| [executionContext()](./puppeteer.webworker.executioncontext.md) | | |
| [url()](./puppeteer.webworker.url.md) | | |
diff --git a/src/common/WebWorker.ts b/src/common/WebWorker.ts
index 97d144c7..83495267 100644
--- a/src/common/WebWorker.ts
+++ b/src/common/WebWorker.ts
@@ -21,6 +21,7 @@ import {EventEmitter} from './EventEmitter.js';
import {ExecutionContext} from './ExecutionContext.js';
import {JSHandle} from './JSHandle.js';
import {debugError} from './util.js';
+import {createDeferredPromise} from '../util/DeferredPromise.js';
/**
* @internal
@@ -38,8 +39,6 @@ export type ExceptionThrownCallback = (
details: Protocol.Runtime.ExceptionDetails
) => void;
-type JSHandleFactory = (obj: Protocol.Runtime.RemoteObject) => JSHandle;
-
/**
* This class represents a
* {@link https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API | WebWorker}.
@@ -67,10 +66,10 @@ type JSHandleFactory = (obj: Protocol.Runtime.RemoteObject) => JSHandle;
* @public
*/
export class WebWorker extends EventEmitter {
+ #executionContext = createDeferredPromise();
+
#client: CDPSession;
#url: string;
- #executionContextPromise: Promise;
- #executionContextCallback!: (value: ExecutionContext) => void;
/**
* @internal
@@ -84,32 +83,36 @@ export class WebWorker extends EventEmitter {
super();
this.#client = client;
this.#url = url;
- this.#executionContextPromise = new Promise(x => {
- return (this.#executionContextCallback = x);
- });
- let jsHandleFactory: JSHandleFactory;
this.#client.once('Runtime.executionContextCreated', async event => {
- // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
- jsHandleFactory = remoteObject => {
- return new JSHandle(executionContext, client, remoteObject);
- };
- const executionContext = new ExecutionContext(client, event.context);
- this.#executionContextCallback(executionContext);
+ const context = new ExecutionContext(client, event.context);
+ this.#executionContext.resolve(context);
});
-
- // This might fail if the target is closed before we receive all execution contexts.
- this.#client.send('Runtime.enable').catch(debugError);
- this.#client.on('Runtime.consoleAPICalled', event => {
+ this.#client.on('Runtime.consoleAPICalled', async event => {
+ const context = await this.#executionContext;
return consoleAPICalled(
event.type,
- event.args.map(jsHandleFactory),
+ event.args.map((object: Protocol.Runtime.RemoteObject) => {
+ return new JSHandle(context, this.#client, object);
+ }),
event.stackTrace
);
});
this.#client.on('Runtime.exceptionThrown', exception => {
return exceptionThrown(exception.exceptionDetails);
});
+
+ // This might fail if the target is closed before we receive all execution contexts.
+ this.#client.send('Runtime.enable').catch(debugError);
+ }
+
+ /**
+ * @deprecated Do not use directly.
+ *
+ * @returns The ExecutionContext the web worker runs in.
+ */
+ async executionContext(): Promise {
+ return this.#executionContext;
}
/**
@@ -119,14 +122,6 @@ export class WebWorker extends EventEmitter {
return this.#url;
}
- /**
- * Returns the ExecutionContext the WebWorker runs in
- * @returns The ExecutionContext the web worker runs in.
- */
- async executionContext(): Promise {
- return this.#executionContextPromise;
- }
-
/**
* If the function passed to the `worker.evaluate` returns a Promise, then
* `worker.evaluate` would wait for the promise to resolve and return its
@@ -148,10 +143,8 @@ export class WebWorker extends EventEmitter {
pageFunction: Func | string,
...args: Params
): Promise>> {
- return (await this.#executionContextPromise).evaluate(
- pageFunction,
- ...args
- );
+ const context = await this.#executionContext;
+ return context.evaluate(pageFunction, ...args);
}
/**
@@ -173,9 +166,7 @@ export class WebWorker extends EventEmitter {
pageFunction: Func | string,
...args: Params
): Promise>>> {
- return (await this.#executionContextPromise).evaluateHandle(
- pageFunction,
- ...args
- );
+ const context = await this.#executionContext;
+ return context.evaluateHandle(pageFunction, ...args);
}
}