Skip to content

Commit 60bf27c

Browse files
authored
feat(chromium): add ConsoleMessage support for service workers (#37368)
1 parent e331e56 commit 60bf27c

File tree

13 files changed

+249
-1
lines changed

13 files changed

+249
-1
lines changed

docs/src/api/class-worker.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,16 @@ foreach(var pageWorker in page.Workers)
5858

5959
Emitted when this dedicated [WebWorker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API) is terminated.
6060

61+
## event: Worker.console
62+
* since: v1.56
63+
- argument: <[ConsoleMessage]>
64+
65+
:::note
66+
Console events from Web Workers are dispatched on the page object. Note that console events are only supported on Chromium-based browsers and within Service Workers.
67+
:::
68+
69+
Emitted when JavaScript within the worker calls one of console API methods, e.g. `console.log` or `console.dir`.
70+
6171
## async method: Worker.evaluate
6272
* since: v1.8
6373
- returns: <[Serializable]>

packages/playwright-client/types/types.d.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10326,33 +10326,72 @@ export interface Worker {
1032610326
*/
1032710327
on(event: 'close', listener: (worker: Worker) => any): this;
1032810328

10329+
/**
10330+
* **NOTE** Console events from Web Workers are dispatched on the page object. Note that console events are only
10331+
* supported on Chromium-based browsers and within Service Workers.
10332+
*
10333+
* Emitted when JavaScript within the worker calls one of console API methods, e.g. `console.log` or `console.dir`.
10334+
*/
10335+
on(event: 'console', listener: (consoleMessage: ConsoleMessage) => any): this;
10336+
1032910337
/**
1033010338
* Adds an event listener that will be automatically removed after it is triggered once. See `addListener` for more information about this event.
1033110339
*/
1033210340
once(event: 'close', listener: (worker: Worker) => any): this;
1033310341

10342+
/**
10343+
* Adds an event listener that will be automatically removed after it is triggered once. See `addListener` for more information about this event.
10344+
*/
10345+
once(event: 'console', listener: (consoleMessage: ConsoleMessage) => any): this;
10346+
1033410347
/**
1033510348
* Emitted when this dedicated [WebWorker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API) is
1033610349
* terminated.
1033710350
*/
1033810351
addListener(event: 'close', listener: (worker: Worker) => any): this;
1033910352

10353+
/**
10354+
* **NOTE** Console events from Web Workers are dispatched on the page object. Note that console events are only
10355+
* supported on Chromium-based browsers and within Service Workers.
10356+
*
10357+
* Emitted when JavaScript within the worker calls one of console API methods, e.g. `console.log` or `console.dir`.
10358+
*/
10359+
addListener(event: 'console', listener: (consoleMessage: ConsoleMessage) => any): this;
10360+
1034010361
/**
1034110362
* Removes an event listener added by `on` or `addListener`.
1034210363
*/
1034310364
removeListener(event: 'close', listener: (worker: Worker) => any): this;
1034410365

10366+
/**
10367+
* Removes an event listener added by `on` or `addListener`.
10368+
*/
10369+
removeListener(event: 'console', listener: (consoleMessage: ConsoleMessage) => any): this;
10370+
1034510371
/**
1034610372
* Removes an event listener added by `on` or `addListener`.
1034710373
*/
1034810374
off(event: 'close', listener: (worker: Worker) => any): this;
1034910375

10376+
/**
10377+
* Removes an event listener added by `on` or `addListener`.
10378+
*/
10379+
off(event: 'console', listener: (consoleMessage: ConsoleMessage) => any): this;
10380+
1035010381
/**
1035110382
* Emitted when this dedicated [WebWorker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API) is
1035210383
* terminated.
1035310384
*/
1035410385
prependListener(event: 'close', listener: (worker: Worker) => any): this;
1035510386

10387+
/**
10388+
* **NOTE** Console events from Web Workers are dispatched on the page object. Note that console events are only
10389+
* supported on Chromium-based browsers and within Service Workers.
10390+
*
10391+
* Emitted when JavaScript within the worker calls one of console API methods, e.g. `console.log` or `console.dir`.
10392+
*/
10393+
prependListener(event: 'console', listener: (consoleMessage: ConsoleMessage) => any): this;
10394+
1035610395
url(): string;
1035710396
}
1035810397

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ export const Events = {
8787

8888
Worker: {
8989
Close: 'close',
90+
Console: 'console',
9091
},
9192

9293
ElectronApplication: {

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616

1717
import { ChannelOwner } from './channelOwner';
18+
import { ConsoleMessage } from './consoleMessage';
1819
import { TargetClosedError } from './errors';
1920
import { Events } from './events';
2021
import { JSHandle, assertMaxArguments, parseResult, serializeArgument } from './jsHandle';
@@ -45,7 +46,13 @@ export class Worker extends ChannelOwner<channels.WorkerChannel> implements api.
4546
this._context._serviceWorkers.delete(this);
4647
this.emit(Events.Worker.Close, this);
4748
});
49+
this._channel.on('console', event => {
50+
this.emit(Events.Worker.Console, new ConsoleMessage(this._page?.context()._platform ?? this._context?._platform!, event));
51+
});
4852
this.once(Events.Worker.Close, () => this._closedScope.close(this._page?._closeErrorWithReason() || new TargetClosedError()));
53+
this._setEventToSubscriptionMapping(new Map<string, channels.WorkerUpdateSubscriptionParams['event']>([
54+
[Events.Worker.Console, 'console'],
55+
]));
4956
}
5057

5158
url(): string {

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1929,6 +1929,16 @@ scheme.WorkerInitializer = tObject({
19291929
url: tString,
19301930
});
19311931
scheme.WorkerCloseEvent = tOptional(tObject({}));
1932+
scheme.WorkerConsoleEvent = tObject({
1933+
type: tString,
1934+
text: tString,
1935+
args: tArray(tChannel(['ElementHandle', 'JSHandle'])),
1936+
location: tObject({
1937+
url: tString,
1938+
lineNumber: tInt,
1939+
columnNumber: tInt,
1940+
}),
1941+
});
19321942
scheme.WorkerEvaluateExpressionParams = tObject({
19331943
expression: tString,
19341944
isFunction: tOptional(tBoolean),
@@ -1945,6 +1955,11 @@ scheme.WorkerEvaluateExpressionHandleParams = tObject({
19451955
scheme.WorkerEvaluateExpressionHandleResult = tObject({
19461956
handle: tChannel(['ElementHandle', 'JSHandle']),
19471957
});
1958+
scheme.WorkerUpdateSubscriptionParams = tObject({
1959+
event: tEnum(['console']),
1960+
enabled: tBoolean,
1961+
});
1962+
scheme.WorkerUpdateSubscriptionResult = tOptional(tObject({}));
19481963
scheme.JSHandleInitializer = tObject({
19491964
preview: tString,
19501965
});

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@
1414
* limitations under the License.
1515
*/
1616
import { Worker } from '../page';
17-
import { CRExecutionContext } from './crExecutionContext';
17+
import { createHandle, CRExecutionContext } from './crExecutionContext';
1818
import { CRNetworkManager } from './crNetworkManager';
1919
import { BrowserContext } from '../browserContext';
20+
import { ConsoleMessage } from '../console';
2021
import * as network from '../network';
22+
import { toConsoleMessageLocation } from './crProtocolHelper';
2123

2224
import type { CRBrowserContext } from './crBrowser';
2325
import type { CRSession } from './crConnection';
@@ -51,6 +53,13 @@ export class CRServiceWorker extends Worker {
5153
// Resume service worker after restart.
5254
session._sendMayFail('Runtime.runIfWaitingForDebugger', {});
5355
});
56+
session.on('Runtime.consoleAPICalled', event => {
57+
if (!this.existingExecutionContext)
58+
return;
59+
const args = event.args.map(o => createHandle(this.existingExecutionContext!, o));
60+
const message = new ConsoleMessage(null, event.type, undefined, args, toConsoleMessageLocation(event.stackTrace));
61+
this.emit(Worker.Events.Console, message);
62+
});
5463
}
5564

5665
override didClose() {

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import { urlMatches } from '../../utils/isomorphic/urlMatch';
3131
import type { Artifact } from '../artifact';
3232
import type { BrowserContext } from '../browserContext';
3333
import type { CRCoverage } from '../chromium/crCoverage';
34+
import type { ConsoleMessage } from '../console';
3435
import type { Download } from '../download';
3536
import type { FileChooser } from '../fileChooser';
3637
import type { JSHandle } from '../javascript';
@@ -387,6 +388,7 @@ export class PageDispatcher extends Dispatcher<Page, channels.PageChannel, Brows
387388

388389
export class WorkerDispatcher extends Dispatcher<Worker, channels.WorkerChannel, PageDispatcher | BrowserContextDispatcher> implements channels.WorkerChannel {
389390
_type_Worker = true;
391+
private readonly _subscriptions = new Set<channels.WorkerUpdateSubscriptionParams['event']>();
390392

391393
static fromNullable(scope: PageDispatcher | BrowserContextDispatcher, worker: Worker | null): WorkerDispatcher | undefined {
392394
if (!worker)
@@ -400,6 +402,23 @@ export class WorkerDispatcher extends Dispatcher<Worker, channels.WorkerChannel,
400402
url: worker.url
401403
});
402404
this.addObjectListener(Worker.Events.Close, () => this._dispatchEvent('close'));
405+
this.addObjectListener(Worker.Events.Console, (message: ConsoleMessage) => {
406+
if (!this._subscriptions.has('console'))
407+
return;
408+
this._dispatchEvent('console', {
409+
type: message.type(),
410+
text: message.text(),
411+
args: message.args().map(a => JSHandleDispatcher.fromJSHandle(this, a)),
412+
location: message.location(),
413+
});
414+
});
415+
}
416+
417+
async updateSubscription(params: channels.WorkerUpdateSubscriptionParams, progress: Progress): Promise<void> {
418+
if (params.enabled)
419+
this._subscriptions.add(params.event);
420+
else
421+
this._subscriptions.delete(params.event);
403422
}
404423

405424
async evaluateExpression(params: channels.WorkerEvaluateExpressionParams, progress: Progress): Promise<channels.WorkerEvaluateExpressionResult> {

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -841,6 +841,7 @@ export class Page extends SdkObject {
841841
export class Worker extends SdkObject {
842842
static Events = {
843843
Close: 'close',
844+
Console: 'console',
844845
};
845846

846847
readonly url: string;

packages/playwright-core/src/utils/isomorphic/protocolMetainfo.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ export const methodMetainfo = new Map<string, { internal?: boolean, title?: stri
185185
['Frame.expect', { title: 'Expect "{expression}"', snapshot: true, pausesBeforeAction: true, }],
186186
['Worker.evaluateExpression', { title: 'Evaluate', }],
187187
['Worker.evaluateExpressionHandle', { title: 'Evaluate', }],
188+
['Worker.updateSubscription', { internal: true, }],
188189
['JSHandle.dispose', { internal: true, }],
189190
['ElementHandle.dispose', { internal: true, }],
190191
['JSHandle.evaluateExpression', { title: 'Evaluate', snapshot: true, pausesBeforeAction: true, }],

packages/playwright-core/types/types.d.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10326,33 +10326,72 @@ export interface Worker {
1032610326
*/
1032710327
on(event: 'close', listener: (worker: Worker) => any): this;
1032810328

10329+
/**
10330+
* **NOTE** Console events from Web Workers are dispatched on the page object. Note that console events are only
10331+
* supported on Chromium-based browsers and within Service Workers.
10332+
*
10333+
* Emitted when JavaScript within the worker calls one of console API methods, e.g. `console.log` or `console.dir`.
10334+
*/
10335+
on(event: 'console', listener: (consoleMessage: ConsoleMessage) => any): this;
10336+
1032910337
/**
1033010338
* Adds an event listener that will be automatically removed after it is triggered once. See `addListener` for more information about this event.
1033110339
*/
1033210340
once(event: 'close', listener: (worker: Worker) => any): this;
1033310341

10342+
/**
10343+
* Adds an event listener that will be automatically removed after it is triggered once. See `addListener` for more information about this event.
10344+
*/
10345+
once(event: 'console', listener: (consoleMessage: ConsoleMessage) => any): this;
10346+
1033410347
/**
1033510348
* Emitted when this dedicated [WebWorker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API) is
1033610349
* terminated.
1033710350
*/
1033810351
addListener(event: 'close', listener: (worker: Worker) => any): this;
1033910352

10353+
/**
10354+
* **NOTE** Console events from Web Workers are dispatched on the page object. Note that console events are only
10355+
* supported on Chromium-based browsers and within Service Workers.
10356+
*
10357+
* Emitted when JavaScript within the worker calls one of console API methods, e.g. `console.log` or `console.dir`.
10358+
*/
10359+
addListener(event: 'console', listener: (consoleMessage: ConsoleMessage) => any): this;
10360+
1034010361
/**
1034110362
* Removes an event listener added by `on` or `addListener`.
1034210363
*/
1034310364
removeListener(event: 'close', listener: (worker: Worker) => any): this;
1034410365

10366+
/**
10367+
* Removes an event listener added by `on` or `addListener`.
10368+
*/
10369+
removeListener(event: 'console', listener: (consoleMessage: ConsoleMessage) => any): this;
10370+
1034510371
/**
1034610372
* Removes an event listener added by `on` or `addListener`.
1034710373
*/
1034810374
off(event: 'close', listener: (worker: Worker) => any): this;
1034910375

10376+
/**
10377+
* Removes an event listener added by `on` or `addListener`.
10378+
*/
10379+
off(event: 'console', listener: (consoleMessage: ConsoleMessage) => any): this;
10380+
1035010381
/**
1035110382
* Emitted when this dedicated [WebWorker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API) is
1035210383
* terminated.
1035310384
*/
1035410385
prependListener(event: 'close', listener: (worker: Worker) => any): this;
1035510386

10387+
/**
10388+
* **NOTE** Console events from Web Workers are dispatched on the page object. Note that console events are only
10389+
* supported on Chromium-based browsers and within Service Workers.
10390+
*
10391+
* Emitted when JavaScript within the worker calls one of console API methods, e.g. `console.log` or `console.dir`.
10392+
*/
10393+
prependListener(event: 'console', listener: (consoleMessage: ConsoleMessage) => any): this;
10394+
1035610395
url(): string;
1035710396
}
1035810397

0 commit comments

Comments
 (0)