1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | import type {Protocol} from 'devtools-protocol';
|
7 |
|
8 | import {CDPSessionEvent, type CDPSession} from '../api/CDPSession.js';
|
9 | import type {Realm} from '../api/Realm.js';
|
10 | import {TargetType} from '../api/Target.js';
|
11 | import {WebWorker} from '../api/WebWorker.js';
|
12 | import {TimeoutSettings} from '../common/TimeoutSettings.js';
|
13 | import {debugError} from '../common/util.js';
|
14 |
|
15 | import {ExecutionContext} from './ExecutionContext.js';
|
16 | import {IsolatedWorld} from './IsolatedWorld.js';
|
17 | import {CdpJSHandle} from './JSHandle.js';
|
18 |
|
19 |
|
20 |
|
21 |
|
22 | export type ConsoleAPICalledCallback = (
|
23 | eventType: string,
|
24 | handles: CdpJSHandle[],
|
25 | trace?: Protocol.Runtime.StackTrace,
|
26 | ) => void;
|
27 |
|
28 |
|
29 |
|
30 |
|
31 | export type ExceptionThrownCallback = (
|
32 | event: Protocol.Runtime.ExceptionThrownEvent,
|
33 | ) => void;
|
34 |
|
35 |
|
36 |
|
37 |
|
38 | export class CdpWebWorker extends WebWorker {
|
39 | #world: IsolatedWorld;
|
40 | #client: CDPSession;
|
41 | readonly #id: string;
|
42 | readonly #targetType: TargetType;
|
43 |
|
44 | constructor(
|
45 | client: CDPSession,
|
46 | url: string,
|
47 | targetId: string,
|
48 | targetType: TargetType,
|
49 | consoleAPICalled: ConsoleAPICalledCallback,
|
50 | exceptionThrown: ExceptionThrownCallback,
|
51 | ) {
|
52 | super(url);
|
53 | this.#id = targetId;
|
54 | this.#client = client;
|
55 | this.#targetType = targetType;
|
56 | this.#world = new IsolatedWorld(this, new TimeoutSettings());
|
57 |
|
58 | this.#client.once('Runtime.executionContextCreated', async event => {
|
59 | this.#world.setContext(
|
60 | new ExecutionContext(client, event.context, this.#world),
|
61 | );
|
62 | });
|
63 | this.#world.emitter.on('consoleapicalled', async event => {
|
64 | try {
|
65 | return consoleAPICalled(
|
66 | event.type,
|
67 | event.args.map((object: Protocol.Runtime.RemoteObject) => {
|
68 | return new CdpJSHandle(this.#world, object);
|
69 | }),
|
70 | event.stackTrace,
|
71 | );
|
72 | } catch (err) {
|
73 | debugError(err);
|
74 | }
|
75 | });
|
76 | this.#client.on('Runtime.exceptionThrown', exceptionThrown);
|
77 | this.#client.once(CDPSessionEvent.Disconnected, () => {
|
78 | this.#world.dispose();
|
79 | });
|
80 |
|
81 |
|
82 | this.#client.send('Runtime.enable').catch(debugError);
|
83 | }
|
84 |
|
85 | mainRealm(): Realm {
|
86 | return this.#world;
|
87 | }
|
88 |
|
89 | get client(): CDPSession {
|
90 | return this.#client;
|
91 | }
|
92 |
|
93 | override async close(): Promise<void> {
|
94 | switch (this.#targetType) {
|
95 | case TargetType.SERVICE_WORKER:
|
96 | case TargetType.SHARED_WORKER: {
|
97 |
|
98 |
|
99 | await this.client.connection()?.send('Target.closeTarget', {
|
100 | targetId: this.#id,
|
101 | });
|
102 | await this.client.connection()?.send('Target.detachFromTarget', {
|
103 | sessionId: this.client.id(),
|
104 | });
|
105 | break;
|
106 | }
|
107 | default:
|
108 | await this.evaluate(() => {
|
109 | self.close();
|
110 | });
|
111 | }
|
112 | }
|
113 | }
|