2019-01-16 01:21:23 +00:00
|
|
|
/**
|
|
|
|
* Copyright 2019 Google Inc. All rights reserved.
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
2023-09-15 11:00:20 +00:00
|
|
|
import {type Protocol} from 'devtools-protocol';
|
2023-02-15 23:09:31 +00:00
|
|
|
|
2023-09-15 11:00:20 +00:00
|
|
|
import {type CDPSession} from '../api/CDPSession.js';
|
|
|
|
import {type JSHandle} from '../api/JSHandle.js';
|
2023-08-30 10:24:38 +00:00
|
|
|
import {Realm} from '../api/Realm.js';
|
2023-09-16 20:56:40 +00:00
|
|
|
import {type TimeoutSettings} from '../common/TimeoutSettings.js';
|
2023-09-15 11:00:20 +00:00
|
|
|
import {
|
|
|
|
type BindingPayload,
|
|
|
|
type EvaluateFunc,
|
|
|
|
type HandleFor,
|
2023-09-16 20:56:40 +00:00
|
|
|
} from '../common/types.js';
|
2023-03-22 09:49:39 +00:00
|
|
|
import {
|
2023-09-16 20:56:40 +00:00
|
|
|
Mutex,
|
2023-03-22 09:49:39 +00:00
|
|
|
addPageBinding,
|
|
|
|
debugError,
|
2023-05-10 08:23:29 +00:00
|
|
|
withSourcePuppeteerURLIfNone,
|
2023-09-16 20:56:40 +00:00
|
|
|
} from '../common/util.js';
|
|
|
|
import {Deferred} from '../util/Deferred.js';
|
2023-09-19 16:13:51 +00:00
|
|
|
import {disposeSymbol} from '../util/disposable.js';
|
2022-11-10 16:11:18 +00:00
|
|
|
|
2023-09-16 20:56:40 +00:00
|
|
|
import {type Binding} from './Binding.js';
|
|
|
|
import {type ExecutionContext, createCdpHandle} from './ExecutionContext.js';
|
|
|
|
import {CdpFrame} from './Frame.js';
|
|
|
|
import {type MAIN_WORLD, type PUPPETEER_WORLD} from './IsolatedWorlds.js';
|
|
|
|
import {type WebWorker} from './WebWorker.js';
|
2020-04-28 14:35:43 +00:00
|
|
|
|
2020-11-03 10:39:31 +00:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*/
|
|
|
|
export interface PageBinding {
|
|
|
|
name: string;
|
|
|
|
pptrFunction: Function;
|
|
|
|
}
|
|
|
|
|
2022-08-10 21:34:29 +00:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*/
|
|
|
|
export interface IsolatedWorldChart {
|
|
|
|
[key: string]: IsolatedWorld;
|
|
|
|
[MAIN_WORLD]: IsolatedWorld;
|
|
|
|
[PUPPETEER_WORLD]: IsolatedWorld;
|
|
|
|
}
|
|
|
|
|
2020-07-02 15:13:22 +00:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*/
|
2023-08-30 10:24:38 +00:00
|
|
|
export class IsolatedWorld extends Realm {
|
2023-05-31 21:36:19 +00:00
|
|
|
#context = Deferred.create<ExecutionContext>();
|
2020-04-28 14:35:43 +00:00
|
|
|
|
2022-06-13 09:16:25 +00:00
|
|
|
// Set of bindings that have been registered in the current context.
|
2023-02-14 15:54:44 +00:00
|
|
|
#contextBindings = new Set<string>();
|
2022-06-13 09:16:25 +00:00
|
|
|
|
|
|
|
// Contains mapping from functions that should be bound to Puppeteer functions.
|
2023-02-14 15:54:44 +00:00
|
|
|
#bindings = new Map<string, Binding>();
|
2020-04-28 14:35:43 +00:00
|
|
|
|
2023-02-14 15:54:44 +00:00
|
|
|
get _bindings(): Map<string, Binding> {
|
|
|
|
return this.#bindings;
|
2022-06-13 09:16:25 +00:00
|
|
|
}
|
|
|
|
|
2023-09-13 19:57:26 +00:00
|
|
|
readonly #frameOrWorker: CdpFrame | WebWorker;
|
2023-09-01 12:12:29 +00:00
|
|
|
|
|
|
|
constructor(
|
2023-09-13 19:57:26 +00:00
|
|
|
frameOrWorker: CdpFrame | WebWorker,
|
2023-09-01 12:12:29 +00:00
|
|
|
timeoutSettings: TimeoutSettings
|
|
|
|
) {
|
|
|
|
super(timeoutSettings);
|
|
|
|
this.#frameOrWorker = frameOrWorker;
|
2023-08-28 06:20:57 +00:00
|
|
|
this.frameUpdated();
|
|
|
|
}
|
|
|
|
|
2023-09-13 19:57:26 +00:00
|
|
|
get environment(): CdpFrame | WebWorker {
|
2023-09-01 12:12:29 +00:00
|
|
|
return this.#frameOrWorker;
|
2019-01-16 01:21:23 +00:00
|
|
|
}
|
|
|
|
|
2023-09-01 12:12:29 +00:00
|
|
|
frameUpdated(): void {
|
|
|
|
this.client.on('Runtime.bindingCalled', this.#onBindingCalled);
|
2022-08-24 15:04:54 +00:00
|
|
|
}
|
|
|
|
|
2023-09-01 12:12:29 +00:00
|
|
|
get client(): CDPSession {
|
|
|
|
return this.#frameOrWorker.client;
|
2022-08-24 15:04:54 +00:00
|
|
|
}
|
|
|
|
|
2022-08-09 11:29:12 +00:00
|
|
|
clearContext(): void {
|
2023-05-31 21:36:19 +00:00
|
|
|
this.#context = Deferred.create();
|
2023-09-13 19:57:26 +00:00
|
|
|
if (this.#frameOrWorker instanceof CdpFrame) {
|
2023-09-11 12:07:52 +00:00
|
|
|
this.#frameOrWorker.clearDocumentHandle();
|
|
|
|
}
|
2022-08-09 11:29:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
setContext(context: ExecutionContext): void {
|
2023-02-14 15:54:44 +00:00
|
|
|
this.#contextBindings.clear();
|
2022-09-01 15:09:57 +00:00
|
|
|
this.#context.resolve(context);
|
2023-08-30 10:24:38 +00:00
|
|
|
void this.taskManager.rerunAll();
|
2022-09-13 12:06:40 +00:00
|
|
|
}
|
|
|
|
|
2022-08-09 11:29:12 +00:00
|
|
|
hasContext(): boolean {
|
2022-09-01 15:09:57 +00:00
|
|
|
return this.#context.resolved();
|
2019-04-11 20:26:18 +00:00
|
|
|
}
|
|
|
|
|
2023-09-01 12:12:29 +00:00
|
|
|
#executionContext(): Promise<ExecutionContext> {
|
2023-08-30 10:24:38 +00:00
|
|
|
if (this.disposed) {
|
2020-05-07 10:54:55 +00:00
|
|
|
throw new Error(
|
2023-09-01 12:12:29 +00:00
|
|
|
`Execution context is not available in detached frame "${this.environment.url()}" (are you trying to evaluate?)`
|
2020-05-07 10:54:55 +00:00
|
|
|
);
|
2022-06-14 11:55:35 +00:00
|
|
|
}
|
2022-09-01 15:09:57 +00:00
|
|
|
if (this.#context === null) {
|
2022-05-25 13:34:11 +00:00
|
|
|
throw new Error(`Execution content promise is missing`);
|
2022-06-14 11:55:35 +00:00
|
|
|
}
|
2023-05-26 06:02:17 +00:00
|
|
|
return this.#context.valueOrThrow();
|
2019-01-16 01:21:23 +00:00
|
|
|
}
|
|
|
|
|
feat!: type inference for evaluation types (#8547)
This PR greatly improves the types within Puppeteer:
- **Almost everything** is auto-deduced.
- Parameters don't need to be specified in the function. They are deduced from the spread.
- Return types don't need to be specified. They are deduced from the function. (More on this below)
- Selections based on tag names correctly deduce element type, similar to TypeScript's mechanism for `getElementByTagName`.
- [**BREAKING CHANGE**] We've removed the ability to declare return types in type arguments for the following reasons:
1. Setting them will indubitably break auto-deduction.
2. You can just use `as ...` in TypeScript to coerce the correct type (given it makes sense).
- [**BREAKING CHANGE**] `waitFor` is officially gone.
To migrate to these changes, there are only four things you may need to change:
- If you set a return type using the `ReturnType` type parameter, remove it and use `as ...` and `HandleFor` (if necessary).
⛔ `evaluate<ReturnType>(a: number, b: number) => {...}, a, b)`
✅ `(await evaluate(a, b) => {...}, a, b)) as ReturnType`
⛔ `evaluateHandle<ReturnType>(a: number, b: number) => {...}, a, b)`
✅ `(await evaluateHandle(a, b) => {...}, a, b)) as HandleFor<ReturnType>`
- If you set any type parameters in the *parameters* of an evaluation function, remove them.
⛔ `evaluate(a: number, b: number) => {...}, a, b)`
✅ `evaluate(a, b) => {...}, a, b)`
- If you set any type parameters in the method's declaration, remove them.
⛔ `evaluate<(a: number, b: number) => void>((a, b) => {...}, a, b)`
✅ `evaluate(a, b) => {...}, a, b)`
2022-06-23 09:29:46 +00:00
|
|
|
async evaluateHandle<
|
|
|
|
Params extends unknown[],
|
2023-07-17 08:52:54 +00:00
|
|
|
Func extends EvaluateFunc<Params> = EvaluateFunc<Params>,
|
feat!: type inference for evaluation types (#8547)
This PR greatly improves the types within Puppeteer:
- **Almost everything** is auto-deduced.
- Parameters don't need to be specified in the function. They are deduced from the spread.
- Return types don't need to be specified. They are deduced from the function. (More on this below)
- Selections based on tag names correctly deduce element type, similar to TypeScript's mechanism for `getElementByTagName`.
- [**BREAKING CHANGE**] We've removed the ability to declare return types in type arguments for the following reasons:
1. Setting them will indubitably break auto-deduction.
2. You can just use `as ...` in TypeScript to coerce the correct type (given it makes sense).
- [**BREAKING CHANGE**] `waitFor` is officially gone.
To migrate to these changes, there are only four things you may need to change:
- If you set a return type using the `ReturnType` type parameter, remove it and use `as ...` and `HandleFor` (if necessary).
⛔ `evaluate<ReturnType>(a: number, b: number) => {...}, a, b)`
✅ `(await evaluate(a, b) => {...}, a, b)) as ReturnType`
⛔ `evaluateHandle<ReturnType>(a: number, b: number) => {...}, a, b)`
✅ `(await evaluateHandle(a, b) => {...}, a, b)) as HandleFor<ReturnType>`
- If you set any type parameters in the *parameters* of an evaluation function, remove them.
⛔ `evaluate(a: number, b: number) => {...}, a, b)`
✅ `evaluate(a, b) => {...}, a, b)`
- If you set any type parameters in the method's declaration, remove them.
⛔ `evaluate<(a: number, b: number) => void>((a, b) => {...}, a, b)`
✅ `evaluate(a, b) => {...}, a, b)`
2022-06-23 09:29:46 +00:00
|
|
|
>(
|
|
|
|
pageFunction: Func | string,
|
2022-06-24 06:40:08 +00:00
|
|
|
...args: Params
|
feat!: type inference for evaluation types (#8547)
This PR greatly improves the types within Puppeteer:
- **Almost everything** is auto-deduced.
- Parameters don't need to be specified in the function. They are deduced from the spread.
- Return types don't need to be specified. They are deduced from the function. (More on this below)
- Selections based on tag names correctly deduce element type, similar to TypeScript's mechanism for `getElementByTagName`.
- [**BREAKING CHANGE**] We've removed the ability to declare return types in type arguments for the following reasons:
1. Setting them will indubitably break auto-deduction.
2. You can just use `as ...` in TypeScript to coerce the correct type (given it makes sense).
- [**BREAKING CHANGE**] `waitFor` is officially gone.
To migrate to these changes, there are only four things you may need to change:
- If you set a return type using the `ReturnType` type parameter, remove it and use `as ...` and `HandleFor` (if necessary).
⛔ `evaluate<ReturnType>(a: number, b: number) => {...}, a, b)`
✅ `(await evaluate(a, b) => {...}, a, b)) as ReturnType`
⛔ `evaluateHandle<ReturnType>(a: number, b: number) => {...}, a, b)`
✅ `(await evaluateHandle(a, b) => {...}, a, b)) as HandleFor<ReturnType>`
- If you set any type parameters in the *parameters* of an evaluation function, remove them.
⛔ `evaluate(a: number, b: number) => {...}, a, b)`
✅ `evaluate(a, b) => {...}, a, b)`
- If you set any type parameters in the method's declaration, remove them.
⛔ `evaluate<(a: number, b: number) => void>((a, b) => {...}, a, b)`
✅ `evaluate(a, b) => {...}, a, b)`
2022-06-23 09:29:46 +00:00
|
|
|
): Promise<HandleFor<Awaited<ReturnType<Func>>>> {
|
2023-05-10 08:23:29 +00:00
|
|
|
pageFunction = withSourcePuppeteerURLIfNone(
|
|
|
|
this.evaluateHandle.name,
|
|
|
|
pageFunction
|
|
|
|
);
|
2023-09-01 12:12:29 +00:00
|
|
|
const context = await this.#executionContext();
|
2023-09-01 07:49:33 +00:00
|
|
|
return await context.evaluateHandle(pageFunction, ...args);
|
2019-01-16 01:21:23 +00:00
|
|
|
}
|
|
|
|
|
feat!: type inference for evaluation types (#8547)
This PR greatly improves the types within Puppeteer:
- **Almost everything** is auto-deduced.
- Parameters don't need to be specified in the function. They are deduced from the spread.
- Return types don't need to be specified. They are deduced from the function. (More on this below)
- Selections based on tag names correctly deduce element type, similar to TypeScript's mechanism for `getElementByTagName`.
- [**BREAKING CHANGE**] We've removed the ability to declare return types in type arguments for the following reasons:
1. Setting them will indubitably break auto-deduction.
2. You can just use `as ...` in TypeScript to coerce the correct type (given it makes sense).
- [**BREAKING CHANGE**] `waitFor` is officially gone.
To migrate to these changes, there are only four things you may need to change:
- If you set a return type using the `ReturnType` type parameter, remove it and use `as ...` and `HandleFor` (if necessary).
⛔ `evaluate<ReturnType>(a: number, b: number) => {...}, a, b)`
✅ `(await evaluate(a, b) => {...}, a, b)) as ReturnType`
⛔ `evaluateHandle<ReturnType>(a: number, b: number) => {...}, a, b)`
✅ `(await evaluateHandle(a, b) => {...}, a, b)) as HandleFor<ReturnType>`
- If you set any type parameters in the *parameters* of an evaluation function, remove them.
⛔ `evaluate(a: number, b: number) => {...}, a, b)`
✅ `evaluate(a, b) => {...}, a, b)`
- If you set any type parameters in the method's declaration, remove them.
⛔ `evaluate<(a: number, b: number) => void>((a, b) => {...}, a, b)`
✅ `evaluate(a, b) => {...}, a, b)`
2022-06-23 09:29:46 +00:00
|
|
|
async evaluate<
|
|
|
|
Params extends unknown[],
|
2023-07-17 08:52:54 +00:00
|
|
|
Func extends EvaluateFunc<Params> = EvaluateFunc<Params>,
|
feat!: type inference for evaluation types (#8547)
This PR greatly improves the types within Puppeteer:
- **Almost everything** is auto-deduced.
- Parameters don't need to be specified in the function. They are deduced from the spread.
- Return types don't need to be specified. They are deduced from the function. (More on this below)
- Selections based on tag names correctly deduce element type, similar to TypeScript's mechanism for `getElementByTagName`.
- [**BREAKING CHANGE**] We've removed the ability to declare return types in type arguments for the following reasons:
1. Setting them will indubitably break auto-deduction.
2. You can just use `as ...` in TypeScript to coerce the correct type (given it makes sense).
- [**BREAKING CHANGE**] `waitFor` is officially gone.
To migrate to these changes, there are only four things you may need to change:
- If you set a return type using the `ReturnType` type parameter, remove it and use `as ...` and `HandleFor` (if necessary).
⛔ `evaluate<ReturnType>(a: number, b: number) => {...}, a, b)`
✅ `(await evaluate(a, b) => {...}, a, b)) as ReturnType`
⛔ `evaluateHandle<ReturnType>(a: number, b: number) => {...}, a, b)`
✅ `(await evaluateHandle(a, b) => {...}, a, b)) as HandleFor<ReturnType>`
- If you set any type parameters in the *parameters* of an evaluation function, remove them.
⛔ `evaluate(a: number, b: number) => {...}, a, b)`
✅ `evaluate(a, b) => {...}, a, b)`
- If you set any type parameters in the method's declaration, remove them.
⛔ `evaluate<(a: number, b: number) => void>((a, b) => {...}, a, b)`
✅ `evaluate(a, b) => {...}, a, b)`
2022-06-23 09:29:46 +00:00
|
|
|
>(
|
|
|
|
pageFunction: Func | string,
|
2022-06-24 06:40:08 +00:00
|
|
|
...args: Params
|
feat!: type inference for evaluation types (#8547)
This PR greatly improves the types within Puppeteer:
- **Almost everything** is auto-deduced.
- Parameters don't need to be specified in the function. They are deduced from the spread.
- Return types don't need to be specified. They are deduced from the function. (More on this below)
- Selections based on tag names correctly deduce element type, similar to TypeScript's mechanism for `getElementByTagName`.
- [**BREAKING CHANGE**] We've removed the ability to declare return types in type arguments for the following reasons:
1. Setting them will indubitably break auto-deduction.
2. You can just use `as ...` in TypeScript to coerce the correct type (given it makes sense).
- [**BREAKING CHANGE**] `waitFor` is officially gone.
To migrate to these changes, there are only four things you may need to change:
- If you set a return type using the `ReturnType` type parameter, remove it and use `as ...` and `HandleFor` (if necessary).
⛔ `evaluate<ReturnType>(a: number, b: number) => {...}, a, b)`
✅ `(await evaluate(a, b) => {...}, a, b)) as ReturnType`
⛔ `evaluateHandle<ReturnType>(a: number, b: number) => {...}, a, b)`
✅ `(await evaluateHandle(a, b) => {...}, a, b)) as HandleFor<ReturnType>`
- If you set any type parameters in the *parameters* of an evaluation function, remove them.
⛔ `evaluate(a: number, b: number) => {...}, a, b)`
✅ `evaluate(a, b) => {...}, a, b)`
- If you set any type parameters in the method's declaration, remove them.
⛔ `evaluate<(a: number, b: number) => void>((a, b) => {...}, a, b)`
✅ `evaluate(a, b) => {...}, a, b)`
2022-06-23 09:29:46 +00:00
|
|
|
): Promise<Awaited<ReturnType<Func>>> {
|
2023-05-10 08:23:29 +00:00
|
|
|
pageFunction = withSourcePuppeteerURLIfNone(
|
|
|
|
this.evaluate.name,
|
|
|
|
pageFunction
|
|
|
|
);
|
2023-09-01 12:12:29 +00:00
|
|
|
const context = await this.#executionContext();
|
2023-09-01 07:49:33 +00:00
|
|
|
return await context.evaluate(pageFunction, ...args);
|
2019-01-16 01:21:23 +00:00
|
|
|
}
|
|
|
|
|
2020-10-07 08:49:11 +00:00
|
|
|
// If multiple waitFor are set up asynchronously, we need to wait for the
|
|
|
|
// first one to set up the binding in the page before running the others.
|
2023-02-14 15:54:44 +00:00
|
|
|
#mutex = new Mutex();
|
2022-06-13 09:16:25 +00:00
|
|
|
async _addBindingToContext(
|
2020-11-03 10:39:31 +00:00
|
|
|
context: ExecutionContext,
|
|
|
|
name: string
|
|
|
|
): Promise<void> {
|
2023-02-14 15:54:44 +00:00
|
|
|
if (this.#contextBindings.has(name)) {
|
2020-11-03 10:39:31 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-10-07 08:49:11 +00:00
|
|
|
|
2023-08-30 13:06:19 +00:00
|
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
|
|
using _ = await this.#mutex.acquire();
|
2023-02-14 15:54:44 +00:00
|
|
|
try {
|
2023-06-13 08:17:48 +00:00
|
|
|
await context._client.send(
|
|
|
|
'Runtime.addBinding',
|
|
|
|
context._contextName
|
|
|
|
? {
|
|
|
|
name,
|
|
|
|
executionContextName: context._contextName,
|
|
|
|
}
|
|
|
|
: {
|
|
|
|
name,
|
|
|
|
executionContextId: context._contextId,
|
|
|
|
}
|
|
|
|
);
|
2022-09-15 06:22:20 +00:00
|
|
|
|
2023-02-14 15:54:44 +00:00
|
|
|
await context.evaluate(addPageBinding, 'internal', name);
|
|
|
|
|
|
|
|
this.#contextBindings.add(name);
|
|
|
|
} catch (error) {
|
|
|
|
// We could have tried to evaluate in a context which was already
|
|
|
|
// destroyed. This happens, for example, if the page is navigated while
|
|
|
|
// we are trying to add the binding
|
|
|
|
if (error instanceof Error) {
|
|
|
|
// Destroyed context.
|
|
|
|
if (error.message.includes('Execution context was destroyed')) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Missing context.
|
|
|
|
if (error.message.includes('Cannot find context with specified id')) {
|
|
|
|
return;
|
|
|
|
}
|
2020-10-07 08:49:11 +00:00
|
|
|
}
|
|
|
|
|
2023-02-14 15:54:44 +00:00
|
|
|
debugError(error);
|
|
|
|
}
|
2020-10-07 08:49:11 +00:00
|
|
|
}
|
|
|
|
|
2022-06-13 09:16:25 +00:00
|
|
|
#onBindingCalled = async (
|
2020-10-07 08:49:11 +00:00
|
|
|
event: Protocol.Runtime.BindingCalledEvent
|
2022-06-13 09:16:25 +00:00
|
|
|
): Promise<void> => {
|
2023-02-14 15:54:44 +00:00
|
|
|
let payload: BindingPayload;
|
2020-10-23 10:45:47 +00:00
|
|
|
try {
|
|
|
|
payload = JSON.parse(event.payload);
|
|
|
|
} catch {
|
|
|
|
// The binding was either called by something in the page or it was
|
|
|
|
// called before our wrapper was initialized.
|
|
|
|
return;
|
|
|
|
}
|
2023-02-14 15:54:44 +00:00
|
|
|
const {type, name, seq, args, isTrivial} = payload;
|
|
|
|
if (type !== 'internal') {
|
2020-11-03 10:39:31 +00:00
|
|
|
return;
|
2022-06-14 11:55:35 +00:00
|
|
|
}
|
2023-02-14 15:54:44 +00:00
|
|
|
if (!this.#contextBindings.has(name)) {
|
2022-06-14 11:55:35 +00:00
|
|
|
return;
|
|
|
|
}
|
2023-02-14 15:54:44 +00:00
|
|
|
|
2023-05-26 06:02:17 +00:00
|
|
|
try {
|
|
|
|
const context = await this.#context.valueOrThrow();
|
|
|
|
if (event.executionContextId !== context._contextId) {
|
|
|
|
return;
|
|
|
|
}
|
2023-02-14 15:54:44 +00:00
|
|
|
|
2023-05-26 06:02:17 +00:00
|
|
|
const binding = this._bindings.get(name);
|
|
|
|
await binding?.run(context, seq, args, isTrivial);
|
|
|
|
} catch (err) {
|
|
|
|
debugError(err);
|
|
|
|
}
|
2022-06-13 09:16:25 +00:00
|
|
|
};
|
2020-10-07 08:49:11 +00:00
|
|
|
|
2023-09-20 12:11:21 +00:00
|
|
|
override async adoptBackendNode(
|
2022-08-09 12:55:18 +00:00
|
|
|
backendNodeId?: Protocol.DOM.BackendNodeId
|
|
|
|
): Promise<JSHandle<Node>> {
|
2023-09-01 12:12:29 +00:00
|
|
|
const executionContext = await this.#executionContext();
|
|
|
|
const {object} = await this.client.send('DOM.resolveNode', {
|
2022-08-09 12:55:18 +00:00
|
|
|
backendNodeId: backendNodeId,
|
|
|
|
executionContextId: executionContext._contextId,
|
|
|
|
});
|
2023-09-01 12:12:29 +00:00
|
|
|
return createCdpHandle(this, object) as JSHandle<Node>;
|
2022-08-09 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
async adoptHandle<T extends JSHandle<Node>>(handle: T): Promise<T> {
|
2023-09-01 12:12:29 +00:00
|
|
|
if (handle.realm === this) {
|
2023-08-24 12:36:24 +00:00
|
|
|
// If the context has already adopted this handle, clone it so downstream
|
|
|
|
// disposal doesn't become an issue.
|
|
|
|
return (await handle.evaluateHandle(value => {
|
|
|
|
return value;
|
|
|
|
})) as unknown as T;
|
|
|
|
}
|
2023-09-01 12:12:29 +00:00
|
|
|
const nodeInfo = await this.client.send('DOM.describeNode', {
|
2023-02-15 10:29:18 +00:00
|
|
|
objectId: handle.id,
|
2022-08-09 12:55:18 +00:00
|
|
|
});
|
|
|
|
return (await this.adoptBackendNode(nodeInfo.node.backendNodeId)) as T;
|
|
|
|
}
|
2022-08-26 10:55:30 +00:00
|
|
|
|
|
|
|
async transferHandle<T extends JSHandle<Node>>(handle: T): Promise<T> {
|
2023-09-01 12:12:29 +00:00
|
|
|
if (handle.realm === this) {
|
2023-02-14 21:31:30 +00:00
|
|
|
return handle;
|
|
|
|
}
|
2023-09-01 15:13:29 +00:00
|
|
|
// Implies it's a primitive value, probably.
|
|
|
|
if (handle.remoteObject().objectId === undefined) {
|
|
|
|
return handle;
|
|
|
|
}
|
2023-09-01 12:12:29 +00:00
|
|
|
const info = await this.client.send('DOM.describeNode', {
|
2023-02-14 21:31:30 +00:00
|
|
|
objectId: handle.remoteObject().objectId,
|
|
|
|
});
|
|
|
|
const newHandle = (await this.adoptBackendNode(
|
|
|
|
info.node.backendNodeId
|
|
|
|
)) as T;
|
2022-08-26 10:55:30 +00:00
|
|
|
await handle.dispose();
|
2023-02-14 21:31:30 +00:00
|
|
|
return newHandle;
|
2022-08-26 10:55:30 +00:00
|
|
|
}
|
2023-08-30 10:24:38 +00:00
|
|
|
|
2023-09-19 16:13:51 +00:00
|
|
|
[disposeSymbol](): void {
|
|
|
|
super[disposeSymbol]();
|
2023-09-01 12:12:29 +00:00
|
|
|
this.client.off('Runtime.bindingCalled', this.#onBindingCalled);
|
2023-08-30 10:24:38 +00:00
|
|
|
}
|
2019-01-16 01:21:23 +00:00
|
|
|
}
|