mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
chore: implement exposeFunction
(#10860)
This commit is contained in:
parent
acdd7d3cd5
commit
253d469515
@ -18,7 +18,7 @@ Functions installed via `page.exposeFunction` survive navigations.
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
class Page {
|
class Page {
|
||||||
exposeFunction(
|
abstract exposeFunction(
|
||||||
name: string,
|
name: string,
|
||||||
pptrFunction:
|
pptrFunction:
|
||||||
| Function
|
| Function
|
||||||
|
@ -15,7 +15,7 @@ One Browser instance might have multiple Page instances.
|
|||||||
#### Signature:
|
#### Signature:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
export declare class Page extends EventEmitter implements AsyncDisposable, Disposable
|
export declare abstract class Page extends EventEmitter implements AsyncDisposable, Disposable
|
||||||
```
|
```
|
||||||
|
|
||||||
**Extends:** [EventEmitter](./puppeteer.eventemitter.md)
|
**Extends:** [EventEmitter](./puppeteer.eventemitter.md)
|
||||||
|
16
package-lock.json
generated
16
package-lock.json
generated
@ -3434,9 +3434,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/chromium-bidi": {
|
"node_modules/chromium-bidi": {
|
||||||
"version": "0.4.25",
|
"version": "0.4.26",
|
||||||
"resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.25.tgz",
|
"resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.26.tgz",
|
||||||
"integrity": "sha512-wQOIgYulshTLpZtuDO/eKFfKqVtpS2UwFVVqi/9q5rX/VXVkYNb/0mZ5l479W24A5ogYKBKEIb6BxMlhMcpXFw==",
|
"integrity": "sha512-lukBGfogAI4T0y3acc86RaacqgKQve47/8pV2c+Hr1PjcICj2K4OkL3qfX3qrqxxnd4ddurFC0WBA3VCQqYeUQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"mitt": "3.0.1"
|
"mitt": "3.0.1"
|
||||||
},
|
},
|
||||||
@ -11115,7 +11115,7 @@
|
|||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@puppeteer/browsers": "1.7.0",
|
"@puppeteer/browsers": "1.7.0",
|
||||||
"chromium-bidi": "0.4.25",
|
"chromium-bidi": "0.4.26",
|
||||||
"cross-fetch": "4.0.0",
|
"cross-fetch": "4.0.0",
|
||||||
"debug": "4.3.4",
|
"debug": "4.3.4",
|
||||||
"devtools-protocol": "0.0.1159816",
|
"devtools-protocol": "0.0.1159816",
|
||||||
@ -13466,9 +13466,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"chromium-bidi": {
|
"chromium-bidi": {
|
||||||
"version": "0.4.25",
|
"version": "0.4.26",
|
||||||
"resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.25.tgz",
|
"resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.26.tgz",
|
||||||
"integrity": "sha512-wQOIgYulshTLpZtuDO/eKFfKqVtpS2UwFVVqi/9q5rX/VXVkYNb/0mZ5l479W24A5ogYKBKEIb6BxMlhMcpXFw==",
|
"integrity": "sha512-lukBGfogAI4T0y3acc86RaacqgKQve47/8pV2c+Hr1PjcICj2K4OkL3qfX3qrqxxnd4ddurFC0WBA3VCQqYeUQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"mitt": "3.0.1"
|
"mitt": "3.0.1"
|
||||||
}
|
}
|
||||||
@ -17257,7 +17257,7 @@
|
|||||||
"version": "file:packages/puppeteer-core",
|
"version": "file:packages/puppeteer-core",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@puppeteer/browsers": "1.7.0",
|
"@puppeteer/browsers": "1.7.0",
|
||||||
"chromium-bidi": "0.4.25",
|
"chromium-bidi": "0.4.26",
|
||||||
"cross-fetch": "4.0.0",
|
"cross-fetch": "4.0.0",
|
||||||
"debug": "4.3.4",
|
"debug": "4.3.4",
|
||||||
"devtools-protocol": "0.0.1159816",
|
"devtools-protocol": "0.0.1159816",
|
||||||
|
@ -141,7 +141,7 @@
|
|||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@puppeteer/browsers": "1.7.0",
|
"@puppeteer/browsers": "1.7.0",
|
||||||
"chromium-bidi": "0.4.25",
|
"chromium-bidi": "0.4.26",
|
||||||
"cross-fetch": "4.0.0",
|
"cross-fetch": "4.0.0",
|
||||||
"debug": "4.3.4",
|
"debug": "4.3.4",
|
||||||
"devtools-protocol": "0.0.1159816",
|
"devtools-protocol": "0.0.1159816",
|
||||||
|
@ -1107,4 +1107,15 @@ export abstract class Frame extends EventEmitter {
|
|||||||
waitForDevicePrompt(): Promise<DeviceRequestPrompt> {
|
waitForDevicePrompt(): Promise<DeviceRequestPrompt> {
|
||||||
throw new Error('Not implemented');
|
throw new Error('Not implemented');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
exposeFunction<Args extends unknown[], Ret>(
|
||||||
|
name: string,
|
||||||
|
fn: (...args: Args) => Awaitable<Ret>
|
||||||
|
): Promise<void>;
|
||||||
|
exposeFunction(): Promise<void> {
|
||||||
|
throw new Error('Not implemented');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -478,7 +478,10 @@ export interface NewDocumentScriptEvaluation {
|
|||||||
*
|
*
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
export class Page extends EventEmitter implements AsyncDisposable, Disposable {
|
export abstract class Page
|
||||||
|
extends EventEmitter
|
||||||
|
implements AsyncDisposable, Disposable
|
||||||
|
{
|
||||||
#handlerMap = new WeakMap<Handler<any>, Handler<any>>();
|
#handlerMap = new WeakMap<Handler<any>, Handler<any>>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1327,13 +1330,10 @@ export class Page extends EventEmitter implements AsyncDisposable, Disposable {
|
|||||||
* @param pptrFunction - Callback function which will be called in Puppeteer's
|
* @param pptrFunction - Callback function which will be called in Puppeteer's
|
||||||
* context.
|
* context.
|
||||||
*/
|
*/
|
||||||
async exposeFunction(
|
abstract exposeFunction(
|
||||||
name: string,
|
name: string,
|
||||||
pptrFunction: Function | {default: Function}
|
pptrFunction: Function | {default: Function}
|
||||||
): Promise<void>;
|
): Promise<void>;
|
||||||
async exposeFunction(): Promise<void> {
|
|
||||||
throw new Error('Not implemented');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The method removes a previously added function via ${@link Page.exposeFunction}
|
* The method removes a previously added function via ${@link Page.exposeFunction}
|
||||||
|
276
packages/puppeteer-core/src/common/bidi/ExposedFunction.ts
Normal file
276
packages/puppeteer-core/src/common/bidi/ExposedFunction.ts
Normal file
@ -0,0 +1,276 @@
|
|||||||
|
/**
|
||||||
|
* 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 * as Bidi from 'chromium-bidi/lib/cjs/protocol/protocol.js';
|
||||||
|
|
||||||
|
import {assert} from '../../util/assert.js';
|
||||||
|
import {Deferred} from '../../util/Deferred.js';
|
||||||
|
import {interpolateFunction, stringifyFunction} from '../../util/Function.js';
|
||||||
|
import {Awaitable, FlattenHandle} from '../types.js';
|
||||||
|
|
||||||
|
import {Connection} from './Connection.js';
|
||||||
|
import {BidiFrame} from './Frame.js';
|
||||||
|
import {BidiSerializer} from './Serializer.js';
|
||||||
|
import {debugError} from './utils.js';
|
||||||
|
|
||||||
|
type SendArgsChannel<Args> = (value: [id: number, args: Args]) => void;
|
||||||
|
type SendResolveChannel<Ret> = (
|
||||||
|
value: [id: number, resolve: (ret: FlattenHandle<Awaited<Ret>>) => void]
|
||||||
|
) => void;
|
||||||
|
type SendRejectChannel = (
|
||||||
|
value: [id: number, reject: (error: unknown) => void]
|
||||||
|
) => void;
|
||||||
|
|
||||||
|
interface RemotePromiseCallbacks {
|
||||||
|
resolve: Deferred<Bidi.Script.RemoteValue>;
|
||||||
|
reject: Deferred<Bidi.Script.RemoteValue>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ExposeableFunction<Args extends unknown[], Ret> {
|
||||||
|
readonly #frame;
|
||||||
|
|
||||||
|
readonly name;
|
||||||
|
readonly #apply;
|
||||||
|
|
||||||
|
readonly #channels;
|
||||||
|
readonly #callerInfos = new Map<
|
||||||
|
string,
|
||||||
|
Map<number, RemotePromiseCallbacks>
|
||||||
|
>();
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
frame: BidiFrame,
|
||||||
|
name: string,
|
||||||
|
apply: (...args: Args) => Awaitable<Ret>
|
||||||
|
) {
|
||||||
|
this.#frame = frame;
|
||||||
|
this.name = name;
|
||||||
|
this.#apply = apply;
|
||||||
|
|
||||||
|
this.#channels = {
|
||||||
|
args: `__puppeteer__${this.#frame._id}_page_exposeFunction_${
|
||||||
|
this.name
|
||||||
|
}_args`,
|
||||||
|
resolve: `__puppeteer__${this.#frame._id}_page_exposeFunction_${
|
||||||
|
this.name
|
||||||
|
}_resolve`,
|
||||||
|
reject: `__puppeteer__${this.#frame._id}_page_exposeFunction_${
|
||||||
|
this.name
|
||||||
|
}_reject`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async expose(): Promise<void> {
|
||||||
|
const connection = this.#connection;
|
||||||
|
const channelArguments = this.#channelArguments;
|
||||||
|
const {name} = this;
|
||||||
|
|
||||||
|
// TODO(jrandolf): Implement cleanup with removePreloadScript.
|
||||||
|
connection.on(
|
||||||
|
Bidi.ChromiumBidi.Script.EventNames.Message,
|
||||||
|
this.#handleArgumentsMessage
|
||||||
|
);
|
||||||
|
connection.on(
|
||||||
|
Bidi.ChromiumBidi.Script.EventNames.Message,
|
||||||
|
this.#handleResolveMessage
|
||||||
|
);
|
||||||
|
connection.on(
|
||||||
|
Bidi.ChromiumBidi.Script.EventNames.Message,
|
||||||
|
this.#handleRejectMessage
|
||||||
|
);
|
||||||
|
|
||||||
|
const functionDeclaration = stringifyFunction(
|
||||||
|
interpolateFunction(
|
||||||
|
(
|
||||||
|
sendArgs: SendArgsChannel<Args>,
|
||||||
|
sendResolve: SendResolveChannel<Ret>,
|
||||||
|
sendReject: SendRejectChannel
|
||||||
|
) => {
|
||||||
|
let id = 0;
|
||||||
|
Object.assign(globalThis, {
|
||||||
|
[PLACEHOLDER('name') as string]: function (...args: Args) {
|
||||||
|
return new Promise<FlattenHandle<Awaited<Ret>>>(
|
||||||
|
(resolve, reject) => {
|
||||||
|
sendArgs([id, args]);
|
||||||
|
sendResolve([id, resolve]);
|
||||||
|
sendReject([id, reject]);
|
||||||
|
++id;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
{name: JSON.stringify(name)}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
await connection.send('script.addPreloadScript', {
|
||||||
|
functionDeclaration,
|
||||||
|
arguments: channelArguments,
|
||||||
|
});
|
||||||
|
|
||||||
|
await connection.send('script.callFunction', {
|
||||||
|
functionDeclaration,
|
||||||
|
arguments: channelArguments,
|
||||||
|
awaitPromise: false,
|
||||||
|
target: this.#frame.mainRealm().realm.target,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#handleArgumentsMessage = async (params: Bidi.Script.MessageParameters) => {
|
||||||
|
if (params.channel !== this.#channels.args) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const connection = this.#connection;
|
||||||
|
const {callbacks, remoteValue} = this.#getCallbacksAndRemoteValue(params);
|
||||||
|
const args = remoteValue.value?.[1];
|
||||||
|
assert(args);
|
||||||
|
try {
|
||||||
|
const result = await this.#apply(...BidiSerializer.deserialize(args));
|
||||||
|
await connection.send('script.callFunction', {
|
||||||
|
functionDeclaration: stringifyFunction(([_, resolve]: any, result) => {
|
||||||
|
resolve(result);
|
||||||
|
}),
|
||||||
|
arguments: [
|
||||||
|
(await callbacks.resolve.valueOrThrow()) as Bidi.Script.LocalValue,
|
||||||
|
BidiSerializer.serializeRemoteValue(result),
|
||||||
|
],
|
||||||
|
awaitPromise: false,
|
||||||
|
target: params.source,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
try {
|
||||||
|
if (error instanceof Error) {
|
||||||
|
await connection.send('script.callFunction', {
|
||||||
|
functionDeclaration: stringifyFunction(
|
||||||
|
(
|
||||||
|
[_, reject]: any,
|
||||||
|
name: string,
|
||||||
|
message: string,
|
||||||
|
stack?: string
|
||||||
|
) => {
|
||||||
|
const error = new Error(message);
|
||||||
|
error.name = name;
|
||||||
|
if (stack) {
|
||||||
|
error.stack = stack;
|
||||||
|
}
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
arguments: [
|
||||||
|
(await callbacks.reject.valueOrThrow()) as Bidi.Script.LocalValue,
|
||||||
|
BidiSerializer.serializeRemoteValue(error.name),
|
||||||
|
BidiSerializer.serializeRemoteValue(error.message),
|
||||||
|
BidiSerializer.serializeRemoteValue(error.stack),
|
||||||
|
],
|
||||||
|
awaitPromise: false,
|
||||||
|
target: params.source,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
await connection.send('script.callFunction', {
|
||||||
|
functionDeclaration: stringifyFunction(
|
||||||
|
([_, reject]: any, error: unknown) => {
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
arguments: [
|
||||||
|
(await callbacks.reject.valueOrThrow()) as Bidi.Script.LocalValue,
|
||||||
|
BidiSerializer.serializeRemoteValue(error),
|
||||||
|
],
|
||||||
|
awaitPromise: false,
|
||||||
|
target: params.source,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
debugError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
get #connection(): Connection {
|
||||||
|
return this.#frame.context().connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
get #channelArguments() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
type: 'channel' as const,
|
||||||
|
value: {
|
||||||
|
channel: this.#channels.args,
|
||||||
|
ownership: Bidi.Script.ResultOwnership.Root,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'channel' as const,
|
||||||
|
value: {
|
||||||
|
channel: this.#channels.resolve,
|
||||||
|
ownership: Bidi.Script.ResultOwnership.Root,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'channel' as const,
|
||||||
|
value: {
|
||||||
|
channel: this.#channels.reject,
|
||||||
|
ownership: Bidi.Script.ResultOwnership.Root,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
#handleResolveMessage = (params: Bidi.Script.MessageParameters) => {
|
||||||
|
if (params.channel !== this.#channels.resolve) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const {callbacks, remoteValue} = this.#getCallbacksAndRemoteValue(params);
|
||||||
|
callbacks.resolve.resolve(remoteValue);
|
||||||
|
};
|
||||||
|
|
||||||
|
#handleRejectMessage = (params: Bidi.Script.MessageParameters) => {
|
||||||
|
if (params.channel !== this.#channels.reject) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const {callbacks, remoteValue} = this.#getCallbacksAndRemoteValue(params);
|
||||||
|
callbacks.reject.resolve(remoteValue);
|
||||||
|
};
|
||||||
|
|
||||||
|
#getCallbacksAndRemoteValue(params: Bidi.Script.MessageParameters) {
|
||||||
|
const {data, source} = params;
|
||||||
|
assert(data.type === 'array');
|
||||||
|
assert(data.value);
|
||||||
|
|
||||||
|
const callerIdRemote = data.value[0];
|
||||||
|
assert(callerIdRemote);
|
||||||
|
assert(callerIdRemote.type === 'number');
|
||||||
|
assert(typeof callerIdRemote.value === 'number');
|
||||||
|
|
||||||
|
let bindingMap = this.#callerInfos.get(source.realm);
|
||||||
|
if (!bindingMap) {
|
||||||
|
bindingMap = new Map();
|
||||||
|
this.#callerInfos.set(source.realm, bindingMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
const callerId = callerIdRemote.value;
|
||||||
|
let callbacks = bindingMap.get(callerId);
|
||||||
|
if (!callbacks) {
|
||||||
|
callbacks = {
|
||||||
|
resolve: new Deferred(),
|
||||||
|
reject: new Deferred(),
|
||||||
|
};
|
||||||
|
bindingMap.set(callerId, callbacks);
|
||||||
|
}
|
||||||
|
return {callbacks, remoteValue: data};
|
||||||
|
}
|
||||||
|
}
|
@ -22,6 +22,7 @@ import {CDPSession} from '../Connection.js';
|
|||||||
import {UTILITY_WORLD_NAME} from '../FrameManager.js';
|
import {UTILITY_WORLD_NAME} from '../FrameManager.js';
|
||||||
import {PuppeteerLifeCycleEvent} from '../LifecycleWatcher.js';
|
import {PuppeteerLifeCycleEvent} from '../LifecycleWatcher.js';
|
||||||
import {TimeoutSettings} from '../TimeoutSettings.js';
|
import {TimeoutSettings} from '../TimeoutSettings.js';
|
||||||
|
import {Awaitable} from '../types.js';
|
||||||
import {waitForEvent} from '../util.js';
|
import {waitForEvent} from '../util.js';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -29,6 +30,7 @@ import {
|
|||||||
getWaitUntilSingle,
|
getWaitUntilSingle,
|
||||||
lifeCycleToSubscribedEvent,
|
lifeCycleToSubscribedEvent,
|
||||||
} from './BrowsingContext.js';
|
} from './BrowsingContext.js';
|
||||||
|
import {ExposeableFunction} from './ExposedFunction.js';
|
||||||
import {HTTPResponse} from './HTTPResponse.js';
|
import {HTTPResponse} from './HTTPResponse.js';
|
||||||
import {BidiPage} from './Page.js';
|
import {BidiPage} from './Page.js';
|
||||||
import {
|
import {
|
||||||
@ -207,4 +209,24 @@ export class BidiFrame extends Frame {
|
|||||||
this.sandboxes[MAIN_SANDBOX][Symbol.dispose]();
|
this.sandboxes[MAIN_SANDBOX][Symbol.dispose]();
|
||||||
this.sandboxes[PUPPETEER_SANDBOX][Symbol.dispose]();
|
this.sandboxes[PUPPETEER_SANDBOX][Symbol.dispose]();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#exposedFunctions = new Map<string, ExposeableFunction<never[], unknown>>();
|
||||||
|
override async exposeFunction<Args extends unknown[], Ret>(
|
||||||
|
name: string,
|
||||||
|
apply: (...args: Args) => Awaitable<Ret>
|
||||||
|
): Promise<void> {
|
||||||
|
if (this.#exposedFunctions.has(name)) {
|
||||||
|
throw new Error(
|
||||||
|
`Failed to add page binding with name ${name}: globalThis['${name}'] already exists!`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const exposeable = new ExposeableFunction(this, name, apply);
|
||||||
|
this.#exposedFunctions.set(name, exposeable);
|
||||||
|
try {
|
||||||
|
await exposeable.expose();
|
||||||
|
} catch (error) {
|
||||||
|
this.#exposedFunctions.delete(name);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,7 @@ import {PDFOptions} from '../PDFOptions.js';
|
|||||||
import {Viewport} from '../PuppeteerViewport.js';
|
import {Viewport} from '../PuppeteerViewport.js';
|
||||||
import {TimeoutSettings} from '../TimeoutSettings.js';
|
import {TimeoutSettings} from '../TimeoutSettings.js';
|
||||||
import {Tracing} from '../Tracing.js';
|
import {Tracing} from '../Tracing.js';
|
||||||
|
import {Awaitable} from '../types.js';
|
||||||
import {
|
import {
|
||||||
debugError,
|
debugError,
|
||||||
evaluationString,
|
evaluationString,
|
||||||
@ -674,6 +675,18 @@ export class BidiPage extends Page {
|
|||||||
script: id,
|
script: id,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override async exposeFunction<Args extends unknown[], Ret>(
|
||||||
|
name: string,
|
||||||
|
pptrFunction:
|
||||||
|
| ((...args: Args) => Awaitable<Ret>)
|
||||||
|
| {default: (...args: Args) => Awaitable<Ret>}
|
||||||
|
): Promise<void> {
|
||||||
|
return await this.mainFrame().exposeFunction(
|
||||||
|
name,
|
||||||
|
'default' in pptrFunction ? pptrFunction.default : pptrFunction
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function isConsoleLogEntry(
|
function isConsoleLogEntry(
|
||||||
|
@ -765,7 +765,7 @@
|
|||||||
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluate should work from-inside an exposed function",
|
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluate should work from-inside an exposed function",
|
||||||
"platforms": ["darwin", "linux", "win32"],
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
"parameters": ["webDriverBiDi"],
|
"parameters": ["webDriverBiDi"],
|
||||||
"expectations": ["FAIL"]
|
"expectations": ["PASS"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluateOnNewDocument *",
|
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluateOnNewDocument *",
|
||||||
@ -1367,6 +1367,12 @@
|
|||||||
"parameters": ["webDriverBiDi"],
|
"parameters": ["webDriverBiDi"],
|
||||||
"expectations": ["PASS"]
|
"expectations": ["PASS"]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"testIdPattern": "[page.spec] Page Page.exposeFunction *",
|
||||||
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
|
"parameters": ["chrome", "webDriverBiDi"],
|
||||||
|
"expectations": ["PASS"]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"testIdPattern": "[page.spec] Page Page.pdf should respect timeout",
|
"testIdPattern": "[page.spec] Page Page.pdf should respect timeout",
|
||||||
"platforms": ["darwin", "linux", "win32"],
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
@ -2099,6 +2105,12 @@
|
|||||||
"parameters": ["firefox", "webDriverBiDi"],
|
"parameters": ["firefox", "webDriverBiDi"],
|
||||||
"expectations": ["FAIL"]
|
"expectations": ["FAIL"]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"testIdPattern": "[elementhandle.spec] ElementHandle specs ElementHandle.click should return Point data",
|
||||||
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
|
"parameters": ["chrome", "webDriverBiDi"],
|
||||||
|
"expectations": ["PASS"]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"testIdPattern": "[elementhandle.spec] ElementHandle specs ElementHandle.click should return Point data",
|
"testIdPattern": "[elementhandle.spec] ElementHandle specs ElementHandle.click should return Point data",
|
||||||
"platforms": ["darwin", "linux", "win32"],
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
@ -2285,6 +2297,12 @@
|
|||||||
"parameters": ["cdp", "firefox"],
|
"parameters": ["cdp", "firefox"],
|
||||||
"expectations": ["SKIP"]
|
"expectations": ["SKIP"]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluate should work from-inside an exposed function",
|
||||||
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
|
"parameters": ["firefox", "webDriverBiDi"],
|
||||||
|
"expectations": ["FAIL", "TIMEOUT"]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluate should work from-inside an exposed function",
|
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluate should work from-inside an exposed function",
|
||||||
"platforms": ["darwin", "linux", "win32"],
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
@ -2979,7 +2997,7 @@
|
|||||||
"testIdPattern": "[navigation.spec] navigation Page.goto should return response when page changes its URL after load",
|
"testIdPattern": "[navigation.spec] navigation Page.goto should return response when page changes its URL after load",
|
||||||
"platforms": ["darwin", "linux", "win32"],
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
"parameters": ["firefox", "webDriverBiDi"],
|
"parameters": ["firefox", "webDriverBiDi"],
|
||||||
"expectations": ["PASS"]
|
"expectations": ["FAIL", "PASS"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"testIdPattern": "[navigation.spec] navigation Page.goto should send referer",
|
"testIdPattern": "[navigation.spec] navigation Page.goto should send referer",
|
||||||
@ -3701,6 +3719,12 @@
|
|||||||
"parameters": ["cdp", "firefox"],
|
"parameters": ["cdp", "firefox"],
|
||||||
"expectations": ["SKIP"]
|
"expectations": ["SKIP"]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"testIdPattern": "[page.spec] Page Page.exposeFunction should be callable from-inside evaluateOnNewDocument",
|
||||||
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
|
"parameters": ["chrome", "webDriverBiDi"],
|
||||||
|
"expectations": ["FAIL", "TIMEOUT"]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"testIdPattern": "[page.spec] Page Page.exposeFunction should be callable from-inside evaluateOnNewDocument",
|
"testIdPattern": "[page.spec] Page Page.exposeFunction should be callable from-inside evaluateOnNewDocument",
|
||||||
"platforms": ["darwin", "linux", "win32"],
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
|
Loading…
Reference in New Issue
Block a user