Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions docs/src/api/class-worker.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,16 @@ foreach(var pageWorker in page.Workers)

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

## event: Worker.console
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we dispatch it on the BrowserContext/Page instead and have a property indicating that it is from a service worker?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets defer that to API review.

* since: v1.56
- argument: <[ConsoleMessage]>

:::note
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.
:::

Emitted when JavaScript within the worker calls one of console API methods, e.g. `console.log` or `console.dir`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about browser warning/errors?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is copied from event: Page.console.


## async method: Worker.evaluate
* since: v1.8
- returns: <[Serializable]>
Expand Down
39 changes: 39 additions & 0 deletions packages/playwright-client/types/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10326,33 +10326,72 @@ export interface Worker {
*/
on(event: 'close', listener: (worker: Worker) => any): this;

/**
* **NOTE** 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.
*
* Emitted when JavaScript within the worker calls one of console API methods, e.g. `console.log` or `console.dir`.
*/
on(event: 'console', listener: (consoleMessage: ConsoleMessage) => any): this;

/**
* Adds an event listener that will be automatically removed after it is triggered once. See `addListener` for more information about this event.
*/
once(event: 'close', listener: (worker: Worker) => any): this;

/**
* Adds an event listener that will be automatically removed after it is triggered once. See `addListener` for more information about this event.
*/
once(event: 'console', listener: (consoleMessage: ConsoleMessage) => any): this;

/**
* Emitted when this dedicated [WebWorker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API) is
* terminated.
*/
addListener(event: 'close', listener: (worker: Worker) => any): this;

/**
* **NOTE** 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.
*
* Emitted when JavaScript within the worker calls one of console API methods, e.g. `console.log` or `console.dir`.
*/
addListener(event: 'console', listener: (consoleMessage: ConsoleMessage) => any): this;

/**
* Removes an event listener added by `on` or `addListener`.
*/
removeListener(event: 'close', listener: (worker: Worker) => any): this;

/**
* Removes an event listener added by `on` or `addListener`.
*/
removeListener(event: 'console', listener: (consoleMessage: ConsoleMessage) => any): this;

/**
* Removes an event listener added by `on` or `addListener`.
*/
off(event: 'close', listener: (worker: Worker) => any): this;

/**
* Removes an event listener added by `on` or `addListener`.
*/
off(event: 'console', listener: (consoleMessage: ConsoleMessage) => any): this;

/**
* Emitted when this dedicated [WebWorker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API) is
* terminated.
*/
prependListener(event: 'close', listener: (worker: Worker) => any): this;

/**
* **NOTE** 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.
*
* Emitted when JavaScript within the worker calls one of console API methods, e.g. `console.log` or `console.dir`.
*/
prependListener(event: 'console', listener: (consoleMessage: ConsoleMessage) => any): this;

url(): string;
}

Expand Down
1 change: 1 addition & 0 deletions packages/playwright-core/src/client/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ export const Events = {

Worker: {
Close: 'close',
Console: 'console',
},

ElectronApplication: {
Expand Down
7 changes: 7 additions & 0 deletions packages/playwright-core/src/client/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

import { ChannelOwner } from './channelOwner';
import { ConsoleMessage } from './consoleMessage';
import { TargetClosedError } from './errors';
import { Events } from './events';
import { JSHandle, assertMaxArguments, parseResult, serializeArgument } from './jsHandle';
Expand Down Expand Up @@ -45,7 +46,13 @@ export class Worker extends ChannelOwner<channels.WorkerChannel> implements api.
this._context._serviceWorkers.delete(this);
this.emit(Events.Worker.Close, this);
});
this._channel.on('console', event => {
this.emit(Events.Worker.Console, new ConsoleMessage(this._page?.context()._platform ?? this._context?._platform!, event));
});
this.once(Events.Worker.Close, () => this._closedScope.close(this._page?._closeErrorWithReason() || new TargetClosedError()));
this._setEventToSubscriptionMapping(new Map<string, channels.WorkerUpdateSubscriptionParams['event']>([
[Events.Worker.Console, 'console'],
]));
}

url(): string {
Expand Down
15 changes: 15 additions & 0 deletions packages/playwright-core/src/protocol/validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1929,6 +1929,16 @@ scheme.WorkerInitializer = tObject({
url: tString,
});
scheme.WorkerCloseEvent = tOptional(tObject({}));
scheme.WorkerConsoleEvent = tObject({
type: tString,
text: tString,
args: tArray(tChannel(['ElementHandle', 'JSHandle'])),
location: tObject({
url: tString,
lineNumber: tInt,
columnNumber: tInt,
}),
});
scheme.WorkerEvaluateExpressionParams = tObject({
expression: tString,
isFunction: tOptional(tBoolean),
Expand All @@ -1945,6 +1955,11 @@ scheme.WorkerEvaluateExpressionHandleParams = tObject({
scheme.WorkerEvaluateExpressionHandleResult = tObject({
handle: tChannel(['ElementHandle', 'JSHandle']),
});
scheme.WorkerUpdateSubscriptionParams = tObject({
event: tEnum(['console']),
enabled: tBoolean,
});
scheme.WorkerUpdateSubscriptionResult = tOptional(tObject({}));
scheme.JSHandleInitializer = tObject({
preview: tString,
});
Expand Down
11 changes: 10 additions & 1 deletion packages/playwright-core/src/server/chromium/crServiceWorker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@
* limitations under the License.
*/
import { Worker } from '../page';
import { CRExecutionContext } from './crExecutionContext';
import { createHandle, CRExecutionContext } from './crExecutionContext';
import { CRNetworkManager } from './crNetworkManager';
import { BrowserContext } from '../browserContext';
import { ConsoleMessage } from '../console';
import * as network from '../network';
import { toConsoleMessageLocation } from './crProtocolHelper';

import type { CRBrowserContext } from './crBrowser';
import type { CRSession } from './crConnection';
Expand Down Expand Up @@ -51,6 +53,13 @@ export class CRServiceWorker extends Worker {
// Resume service worker after restart.
session._sendMayFail('Runtime.runIfWaitingForDebugger', {});
});
session.on('Runtime.consoleAPICalled', event => {
if (!this.existingExecutionContext)
return;
const args = event.args.map(o => createHandle(this.existingExecutionContext!, o));
const message = new ConsoleMessage(null, event.type, undefined, args, toConsoleMessageLocation(event.stackTrace));
this.emit(Worker.Events.Console, message);
});
}

override didClose() {
Expand Down
19 changes: 19 additions & 0 deletions packages/playwright-core/src/server/dispatchers/pageDispatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import { urlMatches } from '../../utils/isomorphic/urlMatch';
import type { Artifact } from '../artifact';
import type { BrowserContext } from '../browserContext';
import type { CRCoverage } from '../chromium/crCoverage';
import type { ConsoleMessage } from '../console';
import type { Download } from '../download';
import type { FileChooser } from '../fileChooser';
import type { JSHandle } from '../javascript';
Expand Down Expand Up @@ -387,6 +388,7 @@ export class PageDispatcher extends Dispatcher<Page, channels.PageChannel, Brows

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

static fromNullable(scope: PageDispatcher | BrowserContextDispatcher, worker: Worker | null): WorkerDispatcher | undefined {
if (!worker)
Expand All @@ -400,6 +402,23 @@ export class WorkerDispatcher extends Dispatcher<Worker, channels.WorkerChannel,
url: worker.url
});
this.addObjectListener(Worker.Events.Close, () => this._dispatchEvent('close'));
this.addObjectListener(Worker.Events.Console, (message: ConsoleMessage) => {
if (!this._subscriptions.has('console'))
return;
this._dispatchEvent('console', {
type: message.type(),
text: message.text(),
args: message.args().map(a => JSHandleDispatcher.fromJSHandle(this, a)),
location: message.location(),
});
});
}

async updateSubscription(params: channels.WorkerUpdateSubscriptionParams, progress: Progress): Promise<void> {
if (params.enabled)
this._subscriptions.add(params.event);
else
this._subscriptions.delete(params.event);
}

async evaluateExpression(params: channels.WorkerEvaluateExpressionParams, progress: Progress): Promise<channels.WorkerEvaluateExpressionResult> {
Expand Down
1 change: 1 addition & 0 deletions packages/playwright-core/src/server/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -841,6 +841,7 @@ export class Page extends SdkObject {
export class Worker extends SdkObject {
static Events = {
Close: 'close',
Console: 'console',
};

readonly url: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ export const methodMetainfo = new Map<string, { internal?: boolean, title?: stri
['Frame.expect', { title: 'Expect "{expression}"', snapshot: true, pausesBeforeAction: true, }],
['Worker.evaluateExpression', { title: 'Evaluate', }],
['Worker.evaluateExpressionHandle', { title: 'Evaluate', }],
['Worker.updateSubscription', { internal: true, }],
['JSHandle.dispose', { internal: true, }],
['ElementHandle.dispose', { internal: true, }],
['JSHandle.evaluateExpression', { title: 'Evaluate', snapshot: true, pausesBeforeAction: true, }],
Expand Down
39 changes: 39 additions & 0 deletions packages/playwright-core/types/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10326,33 +10326,72 @@ export interface Worker {
*/
on(event: 'close', listener: (worker: Worker) => any): this;

/**
* **NOTE** 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.
*
* Emitted when JavaScript within the worker calls one of console API methods, e.g. `console.log` or `console.dir`.
*/
on(event: 'console', listener: (consoleMessage: ConsoleMessage) => any): this;

/**
* Adds an event listener that will be automatically removed after it is triggered once. See `addListener` for more information about this event.
*/
once(event: 'close', listener: (worker: Worker) => any): this;

/**
* Adds an event listener that will be automatically removed after it is triggered once. See `addListener` for more information about this event.
*/
once(event: 'console', listener: (consoleMessage: ConsoleMessage) => any): this;

/**
* Emitted when this dedicated [WebWorker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API) is
* terminated.
*/
addListener(event: 'close', listener: (worker: Worker) => any): this;

/**
* **NOTE** 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.
*
* Emitted when JavaScript within the worker calls one of console API methods, e.g. `console.log` or `console.dir`.
*/
addListener(event: 'console', listener: (consoleMessage: ConsoleMessage) => any): this;

/**
* Removes an event listener added by `on` or `addListener`.
*/
removeListener(event: 'close', listener: (worker: Worker) => any): this;

/**
* Removes an event listener added by `on` or `addListener`.
*/
removeListener(event: 'console', listener: (consoleMessage: ConsoleMessage) => any): this;

/**
* Removes an event listener added by `on` or `addListener`.
*/
off(event: 'close', listener: (worker: Worker) => any): this;

/**
* Removes an event listener added by `on` or `addListener`.
*/
off(event: 'console', listener: (consoleMessage: ConsoleMessage) => any): this;

/**
* Emitted when this dedicated [WebWorker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API) is
* terminated.
*/
prependListener(event: 'close', listener: (worker: Worker) => any): this;

/**
* **NOTE** 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.
*
* Emitted when JavaScript within the worker calls one of console API methods, e.g. `console.log` or `console.dir`.
*/
prependListener(event: 'console', listener: (consoleMessage: ConsoleMessage) => any): this;

url(): string;
}

Expand Down
21 changes: 21 additions & 0 deletions packages/protocol/src/channels.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3311,13 +3311,25 @@ export type WorkerInitializer = {
};
export interface WorkerEventTarget {
on(event: 'close', callback: (params: WorkerCloseEvent) => void): this;
on(event: 'console', callback: (params: WorkerConsoleEvent) => void): this;
}
export interface WorkerChannel extends WorkerEventTarget, Channel {
_type_Worker: boolean;
evaluateExpression(params: WorkerEvaluateExpressionParams, progress?: Progress): Promise<WorkerEvaluateExpressionResult>;
evaluateExpressionHandle(params: WorkerEvaluateExpressionHandleParams, progress?: Progress): Promise<WorkerEvaluateExpressionHandleResult>;
updateSubscription(params: WorkerUpdateSubscriptionParams, progress?: Progress): Promise<WorkerUpdateSubscriptionResult>;
}
export type WorkerCloseEvent = {};
export type WorkerConsoleEvent = {
type: string,
text: string,
args: JSHandleChannel[],
location: {
url: string,
lineNumber: number,
columnNumber: number,
},
};
export type WorkerEvaluateExpressionParams = {
expression: string,
isFunction?: boolean,
Expand All @@ -3340,9 +3352,18 @@ export type WorkerEvaluateExpressionHandleOptions = {
export type WorkerEvaluateExpressionHandleResult = {
handle: JSHandleChannel,
};
export type WorkerUpdateSubscriptionParams = {
event: 'console',
enabled: boolean,
};
export type WorkerUpdateSubscriptionOptions = {

};
export type WorkerUpdateSubscriptionResult = void;

export interface WorkerEvents {
'close': WorkerCloseEvent;
'console': WorkerConsoleEvent;
}

// ----------- JSHandle -----------
Expand Down
13 changes: 13 additions & 0 deletions packages/protocol/src/protocol.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2856,10 +2856,23 @@ Worker:
returns:
handle: JSHandle

updateSubscription:
internal: true
parameters:
event:
type: enum
literals:
- console
enabled: boolean

events:

close:

console:
parameters:
$mixin: ConsoleMessage


JSHandle:
type: interface
Expand Down
Loading
Loading