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 type {BidiConnection} from './Connection.js';
|
||||
import {BidiDeserializer} from './Deserializer.js';
|
||||
import type {BidiFrame} from './Frame.js';
|
||||
import {BidiSerializer} from './Serializer.js';
|
||||
|
||||
@ -142,7 +143,7 @@ export class ExposeableFunction<Args extends unknown[], Ret> {
|
||||
const args = remoteValue.value?.[1];
|
||||
assert(args);
|
||||
try {
|
||||
const result = await this.#apply(...BidiSerializer.deserialize(args));
|
||||
const result = await this.#apply(...BidiDeserializer.deserialize(args));
|
||||
await connection.send('script.callFunction', {
|
||||
functionDeclaration: stringifyFunction(([_, resolve]: any, 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 {JSHandle} from '../api/JSHandle.js';
|
||||
|
||||
import {BidiDeserializer} from './Deserializer.js';
|
||||
import type {BidiRealm} from './Realm.js';
|
||||
import type {Sandbox} from './Sandbox.js';
|
||||
import {BidiSerializer} from './Serializer.js';
|
||||
import {releaseReference} from './util.js';
|
||||
|
||||
/**
|
||||
@ -90,7 +90,7 @@ export class BidiJSHandle<T = unknown> extends JSHandle<T> {
|
||||
|
||||
override toString(): string {
|
||||
if (this.isPrimitiveValue) {
|
||||
return 'JSHandle:' + BidiSerializer.deserialize(this.#remoteValue);
|
||||
return 'JSHandle:' + BidiDeserializer.deserialize(this.#remoteValue);
|
||||
}
|
||||
|
||||
return 'JSHandle@' + this.#remoteValue.type;
|
||||
|
@ -70,6 +70,7 @@ import {
|
||||
type BrowsingContext,
|
||||
} from './BrowsingContext.js';
|
||||
import type {BidiConnection} from './Connection.js';
|
||||
import {BidiDeserializer} from './Deserializer.js';
|
||||
import {BidiDialog} from './Dialog.js';
|
||||
import {BidiElementHandle} from './ElementHandle.js';
|
||||
import {EmulationManager} from './EmulationManager.js';
|
||||
@ -80,7 +81,6 @@ import {BidiKeyboard, BidiMouse, BidiTouchscreen} from './Input.js';
|
||||
import type {BidiJSHandle} from './JSHandle.js';
|
||||
import {BidiNetworkManager} from './NetworkManager.js';
|
||||
import {createBidiHandle} from './Realm.js';
|
||||
import {BidiSerializer} from './Serializer.js';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
@ -399,7 +399,7 @@ export class BidiPage extends Page {
|
||||
const text = args
|
||||
.reduce((value, arg) => {
|
||||
const parsedValue = arg.isPrimitiveValue
|
||||
? BidiSerializer.deserialize(arg.remoteValue())
|
||||
? BidiDeserializer.deserialize(arg.remoteValue())
|
||||
: arg.toString();
|
||||
return `${value} ${parsedValue}`;
|
||||
}, '')
|
||||
|
@ -15,6 +15,7 @@ import {disposeSymbol} from '../util/disposable.js';
|
||||
import {stringifyFunction} from '../util/Function.js';
|
||||
|
||||
import type {BidiConnection} from './Connection.js';
|
||||
import {BidiDeserializer} from './Deserializer.js';
|
||||
import {BidiElementHandle} from './ElementHandle.js';
|
||||
import {BidiJSHandle} from './JSHandle.js';
|
||||
import type {Sandbox} from './Sandbox.js';
|
||||
@ -195,7 +196,7 @@ export class BidiRealm extends EventEmitter<Record<EventType, any>> {
|
||||
}
|
||||
|
||||
return returnByValue
|
||||
? BidiSerializer.deserialize(result.result)
|
||||
? BidiDeserializer.deserialize(result.result)
|
||||
: createBidiHandle(sandbox, result.result);
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
import type * as Bidi from 'chromium-bidi/lib/cjs/protocol/protocol.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 {BidiJSHandle} from './JSHandle.js';
|
||||
@ -172,108 +172,4 @@ export class BidiSerializer {
|
||||
|
||||
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 {BidiDeserializer} from './Deserializer.js';
|
||||
import type {BidiRealm} from './Realm.js';
|
||||
import {BidiSerializer} from './Serializer.js';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
@ -50,7 +50,7 @@ export function createEvaluationError(
|
||||
details: Bidi.Script.ExceptionDetails
|
||||
): unknown {
|
||||
if (details.exception.type !== 'error') {
|
||||
return BidiSerializer.deserialize(details.exception);
|
||||
return BidiDeserializer.deserialize(details.exception);
|
||||
}
|
||||
const [name = '', ...parts] = details.text.split(': ');
|
||||
const message = parts.join(': ');
|
||||
|
Loading…
Reference in New Issue
Block a user