chore: split a cycle in BiDi (#11229)
This commit is contained in:
parent
525f13cd18
commit
20eb38d61b
133
packages/puppeteer-core/src/bidi/Deserializer.ts
Normal file
133
packages/puppeteer-core/src/bidi/Deserializer.ts
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
/**
|
||||||
|
* 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 * as Bidi from 'chromium-bidi/lib/cjs/protocol/protocol.js';
|
||||||
|
|
||||||
|
import {debugError} from '../common/util.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
class UnsupportedTypeError extends Error {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export class BidiDeserializer {
|
||||||
|
static deserializeNumber(value: Bidi.Script.SpecialNumber | number): number {
|
||||||
|
switch (value) {
|
||||||
|
case '-0':
|
||||||
|
return -0;
|
||||||
|
case 'NaN':
|
||||||
|
return NaN;
|
||||||
|
case 'Infinity':
|
||||||
|
return Infinity;
|
||||||
|
case '-Infinity':
|
||||||
|
return -Infinity;
|
||||||
|
default:
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static deserializeLocalValue(result: Bidi.Script.RemoteValue): unknown {
|
||||||
|
switch (result.type) {
|
||||||
|
case 'array':
|
||||||
|
if (result.value) {
|
||||||
|
return result.value.map(value => {
|
||||||
|
return BidiDeserializer.deserializeLocalValue(value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'set':
|
||||||
|
if (result.value) {
|
||||||
|
return result.value.reduce((acc: Set<unknown>, value) => {
|
||||||
|
return acc.add(BidiDeserializer.deserializeLocalValue(value));
|
||||||
|
}, new Set());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'object':
|
||||||
|
if (result.value) {
|
||||||
|
return result.value.reduce((acc: Record<any, unknown>, tuple) => {
|
||||||
|
const {key, value} = BidiDeserializer.deserializeTuple(tuple);
|
||||||
|
acc[key as any] = value;
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'map':
|
||||||
|
if (result.value) {
|
||||||
|
return result.value?.reduce((acc: Map<unknown, unknown>, tuple) => {
|
||||||
|
const {key, value} = BidiDeserializer.deserializeTuple(tuple);
|
||||||
|
return acc.set(key, value);
|
||||||
|
}, new Map());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'promise':
|
||||||
|
return {};
|
||||||
|
case 'regexp':
|
||||||
|
return new RegExp(result.value.pattern, result.value.flags);
|
||||||
|
case 'date':
|
||||||
|
return new Date(result.value);
|
||||||
|
|
||||||
|
case 'undefined':
|
||||||
|
return undefined;
|
||||||
|
case 'null':
|
||||||
|
return null;
|
||||||
|
case 'number':
|
||||||
|
return BidiDeserializer.deserializeNumber(result.value);
|
||||||
|
case 'bigint':
|
||||||
|
return BigInt(result.value);
|
||||||
|
case 'boolean':
|
||||||
|
return Boolean(result.value);
|
||||||
|
case 'string':
|
||||||
|
return result.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new UnsupportedTypeError(
|
||||||
|
`Deserialization of type ${result.type} not supported.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static deserializeTuple([serializedKey, serializedValue]: [
|
||||||
|
Bidi.Script.RemoteValue | string,
|
||||||
|
Bidi.Script.RemoteValue,
|
||||||
|
]): {key: unknown; value: unknown} {
|
||||||
|
const key =
|
||||||
|
typeof serializedKey === 'string'
|
||||||
|
? serializedKey
|
||||||
|
: BidiDeserializer.deserializeLocalValue(serializedKey);
|
||||||
|
const value = BidiDeserializer.deserializeLocalValue(serializedValue);
|
||||||
|
|
||||||
|
return {key, value};
|
||||||
|
}
|
||||||
|
|
||||||
|
static deserialize(result: Bidi.Script.RemoteValue): any {
|
||||||
|
if (!result) {
|
||||||
|
debugError('Service did not produce a result.');
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return BidiDeserializer.deserializeLocalValue(result);
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof UnsupportedTypeError) {
|
||||||
|
debugError(error.message);
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -23,6 +23,7 @@ import {Deferred} from '../util/Deferred.js';
|
|||||||
import {interpolateFunction, stringifyFunction} from '../util/Function.js';
|
import {interpolateFunction, stringifyFunction} from '../util/Function.js';
|
||||||
|
|
||||||
import type {BidiConnection} from './Connection.js';
|
import type {BidiConnection} from './Connection.js';
|
||||||
|
import {BidiDeserializer} from './Deserializer.js';
|
||||||
import type {BidiFrame} from './Frame.js';
|
import type {BidiFrame} from './Frame.js';
|
||||||
import {BidiSerializer} from './Serializer.js';
|
import {BidiSerializer} from './Serializer.js';
|
||||||
|
|
||||||
@ -142,7 +143,7 @@ export class ExposeableFunction<Args extends unknown[], Ret> {
|
|||||||
const args = remoteValue.value?.[1];
|
const args = remoteValue.value?.[1];
|
||||||
assert(args);
|
assert(args);
|
||||||
try {
|
try {
|
||||||
const result = await this.#apply(...BidiSerializer.deserialize(args));
|
const result = await this.#apply(...BidiDeserializer.deserialize(args));
|
||||||
await connection.send('script.callFunction', {
|
await connection.send('script.callFunction', {
|
||||||
functionDeclaration: stringifyFunction(([_, resolve]: any, result) => {
|
functionDeclaration: stringifyFunction(([_, resolve]: any, result) => {
|
||||||
resolve(result);
|
resolve(result);
|
||||||
|
@ -19,9 +19,9 @@ import type * as Bidi from 'chromium-bidi/lib/cjs/protocol/protocol.js';
|
|||||||
import type {ElementHandle} from '../api/ElementHandle.js';
|
import type {ElementHandle} from '../api/ElementHandle.js';
|
||||||
import {JSHandle} from '../api/JSHandle.js';
|
import {JSHandle} from '../api/JSHandle.js';
|
||||||
|
|
||||||
|
import {BidiDeserializer} from './Deserializer.js';
|
||||||
import type {BidiRealm} from './Realm.js';
|
import type {BidiRealm} from './Realm.js';
|
||||||
import type {Sandbox} from './Sandbox.js';
|
import type {Sandbox} from './Sandbox.js';
|
||||||
import {BidiSerializer} from './Serializer.js';
|
|
||||||
import {releaseReference} from './util.js';
|
import {releaseReference} from './util.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -90,7 +90,7 @@ export class BidiJSHandle<T = unknown> extends JSHandle<T> {
|
|||||||
|
|
||||||
override toString(): string {
|
override toString(): string {
|
||||||
if (this.isPrimitiveValue) {
|
if (this.isPrimitiveValue) {
|
||||||
return 'JSHandle:' + BidiSerializer.deserialize(this.#remoteValue);
|
return 'JSHandle:' + BidiDeserializer.deserialize(this.#remoteValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 'JSHandle@' + this.#remoteValue.type;
|
return 'JSHandle@' + this.#remoteValue.type;
|
||||||
|
@ -70,6 +70,7 @@ import {
|
|||||||
type BrowsingContext,
|
type BrowsingContext,
|
||||||
} from './BrowsingContext.js';
|
} from './BrowsingContext.js';
|
||||||
import type {BidiConnection} from './Connection.js';
|
import type {BidiConnection} from './Connection.js';
|
||||||
|
import {BidiDeserializer} from './Deserializer.js';
|
||||||
import {BidiDialog} from './Dialog.js';
|
import {BidiDialog} from './Dialog.js';
|
||||||
import {BidiElementHandle} from './ElementHandle.js';
|
import {BidiElementHandle} from './ElementHandle.js';
|
||||||
import {EmulationManager} from './EmulationManager.js';
|
import {EmulationManager} from './EmulationManager.js';
|
||||||
@ -80,7 +81,6 @@ import {BidiKeyboard, BidiMouse, BidiTouchscreen} from './Input.js';
|
|||||||
import type {BidiJSHandle} from './JSHandle.js';
|
import type {BidiJSHandle} from './JSHandle.js';
|
||||||
import {BidiNetworkManager} from './NetworkManager.js';
|
import {BidiNetworkManager} from './NetworkManager.js';
|
||||||
import {createBidiHandle} from './Realm.js';
|
import {createBidiHandle} from './Realm.js';
|
||||||
import {BidiSerializer} from './Serializer.js';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
@ -399,7 +399,7 @@ export class BidiPage extends Page {
|
|||||||
const text = args
|
const text = args
|
||||||
.reduce((value, arg) => {
|
.reduce((value, arg) => {
|
||||||
const parsedValue = arg.isPrimitiveValue
|
const parsedValue = arg.isPrimitiveValue
|
||||||
? BidiSerializer.deserialize(arg.remoteValue())
|
? BidiDeserializer.deserialize(arg.remoteValue())
|
||||||
: arg.toString();
|
: arg.toString();
|
||||||
return `${value} ${parsedValue}`;
|
return `${value} ${parsedValue}`;
|
||||||
}, '')
|
}, '')
|
||||||
|
@ -15,6 +15,7 @@ import {disposeSymbol} from '../util/disposable.js';
|
|||||||
import {stringifyFunction} from '../util/Function.js';
|
import {stringifyFunction} from '../util/Function.js';
|
||||||
|
|
||||||
import type {BidiConnection} from './Connection.js';
|
import type {BidiConnection} from './Connection.js';
|
||||||
|
import {BidiDeserializer} from './Deserializer.js';
|
||||||
import {BidiElementHandle} from './ElementHandle.js';
|
import {BidiElementHandle} from './ElementHandle.js';
|
||||||
import {BidiJSHandle} from './JSHandle.js';
|
import {BidiJSHandle} from './JSHandle.js';
|
||||||
import type {Sandbox} from './Sandbox.js';
|
import type {Sandbox} from './Sandbox.js';
|
||||||
@ -195,7 +196,7 @@ export class BidiRealm extends EventEmitter<Record<EventType, any>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return returnByValue
|
return returnByValue
|
||||||
? BidiSerializer.deserialize(result.result)
|
? BidiDeserializer.deserialize(result.result)
|
||||||
: createBidiHandle(sandbox, result.result);
|
: createBidiHandle(sandbox, result.result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
import type * as Bidi from 'chromium-bidi/lib/cjs/protocol/protocol.js';
|
import type * as Bidi from 'chromium-bidi/lib/cjs/protocol/protocol.js';
|
||||||
|
|
||||||
import {LazyArg} from '../common/LazyArg.js';
|
import {LazyArg} from '../common/LazyArg.js';
|
||||||
import {debugError, isDate, isPlainObject, isRegExp} from '../common/util.js';
|
import {isDate, isPlainObject, isRegExp} from '../common/util.js';
|
||||||
|
|
||||||
import {BidiElementHandle} from './ElementHandle.js';
|
import {BidiElementHandle} from './ElementHandle.js';
|
||||||
import {BidiJSHandle} from './JSHandle.js';
|
import {BidiJSHandle} from './JSHandle.js';
|
||||||
@ -172,108 +172,4 @@ export class BidiSerializer {
|
|||||||
|
|
||||||
return BidiSerializer.serializeRemoteValue(arg);
|
return BidiSerializer.serializeRemoteValue(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static deserializeNumber(value: Bidi.Script.SpecialNumber | number): number {
|
|
||||||
switch (value) {
|
|
||||||
case '-0':
|
|
||||||
return -0;
|
|
||||||
case 'NaN':
|
|
||||||
return NaN;
|
|
||||||
case 'Infinity':
|
|
||||||
return Infinity;
|
|
||||||
case '-Infinity':
|
|
||||||
return -Infinity;
|
|
||||||
default:
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static deserializeLocalValue(result: Bidi.Script.RemoteValue): unknown {
|
|
||||||
switch (result.type) {
|
|
||||||
case 'array':
|
|
||||||
if (result.value) {
|
|
||||||
return result.value.map(value => {
|
|
||||||
return BidiSerializer.deserializeLocalValue(value);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'set':
|
|
||||||
if (result.value) {
|
|
||||||
return result.value.reduce((acc: Set<unknown>, value) => {
|
|
||||||
return acc.add(BidiSerializer.deserializeLocalValue(value));
|
|
||||||
}, new Set());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'object':
|
|
||||||
if (result.value) {
|
|
||||||
return result.value.reduce((acc: Record<any, unknown>, tuple) => {
|
|
||||||
const {key, value} = BidiSerializer.deserializeTuple(tuple);
|
|
||||||
acc[key as any] = value;
|
|
||||||
return acc;
|
|
||||||
}, {});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'map':
|
|
||||||
if (result.value) {
|
|
||||||
return result.value?.reduce((acc: Map<unknown, unknown>, tuple) => {
|
|
||||||
const {key, value} = BidiSerializer.deserializeTuple(tuple);
|
|
||||||
return acc.set(key, value);
|
|
||||||
}, new Map());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'promise':
|
|
||||||
return {};
|
|
||||||
case 'regexp':
|
|
||||||
return new RegExp(result.value.pattern, result.value.flags);
|
|
||||||
case 'date':
|
|
||||||
return new Date(result.value);
|
|
||||||
|
|
||||||
case 'undefined':
|
|
||||||
return undefined;
|
|
||||||
case 'null':
|
|
||||||
return null;
|
|
||||||
case 'number':
|
|
||||||
return BidiSerializer.deserializeNumber(result.value);
|
|
||||||
case 'bigint':
|
|
||||||
return BigInt(result.value);
|
|
||||||
case 'boolean':
|
|
||||||
return Boolean(result.value);
|
|
||||||
case 'string':
|
|
||||||
return result.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new UnserializableError(
|
|
||||||
`Deserialization of type ${result.type} not supported.`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static deserializeTuple([serializedKey, serializedValue]: [
|
|
||||||
Bidi.Script.RemoteValue | string,
|
|
||||||
Bidi.Script.RemoteValue,
|
|
||||||
]): {key: unknown; value: unknown} {
|
|
||||||
const key =
|
|
||||||
typeof serializedKey === 'string'
|
|
||||||
? serializedKey
|
|
||||||
: BidiSerializer.deserializeLocalValue(serializedKey);
|
|
||||||
const value = BidiSerializer.deserializeLocalValue(serializedValue);
|
|
||||||
|
|
||||||
return {key, value};
|
|
||||||
}
|
|
||||||
|
|
||||||
static deserialize(result: Bidi.Script.RemoteValue): any {
|
|
||||||
if (!result) {
|
|
||||||
debugError('Service did not produce a result.');
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
return BidiSerializer.deserializeLocalValue(result);
|
|
||||||
} catch (error) {
|
|
||||||
if (error instanceof UnserializableError) {
|
|
||||||
debugError(error.message);
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,8 @@ import type * as Bidi from 'chromium-bidi/lib/cjs/protocol/protocol.js';
|
|||||||
|
|
||||||
import {PuppeteerURL, debugError} from '../common/util.js';
|
import {PuppeteerURL, debugError} from '../common/util.js';
|
||||||
|
|
||||||
|
import {BidiDeserializer} from './Deserializer.js';
|
||||||
import type {BidiRealm} from './Realm.js';
|
import type {BidiRealm} from './Realm.js';
|
||||||
import {BidiSerializer} from './Serializer.js';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
@ -50,7 +50,7 @@ export function createEvaluationError(
|
|||||||
details: Bidi.Script.ExceptionDetails
|
details: Bidi.Script.ExceptionDetails
|
||||||
): unknown {
|
): unknown {
|
||||||
if (details.exception.type !== 'error') {
|
if (details.exception.type !== 'error') {
|
||||||
return BidiSerializer.deserialize(details.exception);
|
return BidiDeserializer.deserialize(details.exception);
|
||||||
}
|
}
|
||||||
const [name = '', ...parts] = details.text.split(': ');
|
const [name = '', ...parts] = details.text.split(': ');
|
||||||
const message = parts.join(': ');
|
const message = parts.join(': ');
|
||||||
|
Loading…
Reference in New Issue
Block a user