/** * Copyright 2023 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. */ import type {JSHandle} from '../api/JSHandle.js'; import {Realm} from '../api/Realm.js'; import type {TimeoutSettings} from '../common/TimeoutSettings.js'; import type {EvaluateFunc, HandleFor} from '../common/types.js'; import {withSourcePuppeteerURLIfNone} from '../common/util.js'; import type {BrowsingContext} from './BrowsingContext.js'; import {BidiElementHandle} from './ElementHandle.js'; import type {BidiFrame} from './Frame.js'; import type {BidiRealm as BidiRealm} from './Realm.js'; /** * A unique key for {@link SandboxChart} to denote the default world. * Realms are automatically created in the default sandbox. * * @internal */ export const MAIN_SANDBOX = Symbol('mainSandbox'); /** * A unique key for {@link SandboxChart} to denote the puppeteer sandbox. * This world contains all puppeteer-internal bindings/code. * * @internal */ export const PUPPETEER_SANDBOX = Symbol('puppeteerSandbox'); /** * @internal */ export interface SandboxChart { [key: string]: Sandbox; [MAIN_SANDBOX]: Sandbox; [PUPPETEER_SANDBOX]: Sandbox; } /** * @internal */ export class Sandbox extends Realm { readonly name: string | undefined; readonly realm: BidiRealm; #frame: BidiFrame; constructor( name: string | undefined, frame: BidiFrame, // TODO: We should split the Realm and BrowsingContext realm: BidiRealm | BrowsingContext, timeoutSettings: TimeoutSettings ) { super(timeoutSettings); this.name = name; this.realm = realm; this.#frame = frame; this.realm.setSandbox(this); } override get environment(): BidiFrame { return this.#frame; } async evaluateHandle< Params extends unknown[], Func extends EvaluateFunc = EvaluateFunc, >( pageFunction: Func | string, ...args: Params ): Promise>>> { pageFunction = withSourcePuppeteerURLIfNone( this.evaluateHandle.name, pageFunction ); return await this.realm.evaluateHandle(pageFunction, ...args); } async evaluate< Params extends unknown[], Func extends EvaluateFunc = EvaluateFunc, >( pageFunction: Func | string, ...args: Params ): Promise>> { pageFunction = withSourcePuppeteerURLIfNone( this.evaluate.name, pageFunction ); return await this.realm.evaluate(pageFunction, ...args); } async adoptHandle>(handle: T): Promise { return (await this.evaluateHandle(node => { return node; }, handle)) as unknown as T; } async transferHandle>(handle: T): Promise { if (handle.realm === this) { return handle; } const transferredHandle = await this.evaluateHandle(node => { return node; }, handle); await handle.dispose(); return transferredHandle as unknown as T; } override async adoptBackendNode( backendNodeId?: number ): Promise> { const {object} = await this.environment.client.send('DOM.resolveNode', { backendNodeId: backendNodeId, }); return new BidiElementHandle(this, { handle: object.objectId, type: 'node', }); } }