163 lines
6.6 KiB
JavaScript
163 lines
6.6 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.puppeteerEvaluateWithCatchAndTimeout = puppeteerEvaluateWithCatchAndTimeout;
|
|
exports.puppeteerEvaluateWithCatch = puppeteerEvaluateWithCatch;
|
|
const JSHandle_1 = require("./browser/JSHandle");
|
|
const symbolicateable_error_1 = require("./error-handling/symbolicateable-error");
|
|
const parse_browser_error_stack_1 = require("./parse-browser-error-stack");
|
|
const EVALUATION_SCRIPT_URL = '__puppeteer_evaluation_script__';
|
|
function valueFromRemoteObject(remoteObject) {
|
|
if (remoteObject.unserializableValue) {
|
|
if (remoteObject.type === 'bigint' && typeof BigInt !== 'undefined')
|
|
return BigInt(remoteObject.unserializableValue.replace('n', ''));
|
|
switch (remoteObject.unserializableValue) {
|
|
case '-0':
|
|
return -0;
|
|
case 'NaN':
|
|
return NaN;
|
|
case 'Infinity':
|
|
return Infinity;
|
|
case '-Infinity':
|
|
return -Infinity;
|
|
default:
|
|
throw new Error('Unsupported unserializable value: ' +
|
|
remoteObject.unserializableValue);
|
|
}
|
|
}
|
|
return remoteObject.value;
|
|
}
|
|
function puppeteerEvaluateWithCatchAndTimeout({ args, frame, page, pageFunction, timeoutInMilliseconds, }) {
|
|
let timeout = null;
|
|
return Promise.race([
|
|
new Promise((_, reject) => {
|
|
timeout = setTimeout(() => {
|
|
reject(new Error(
|
|
// This means the page is not responding anymore
|
|
// This error message is retryable - sync it with packages/lambda/src/shared/is-flaky-error.ts
|
|
`Timed out evaluating page function "${pageFunction.toString()}"`));
|
|
}, timeoutInMilliseconds);
|
|
}),
|
|
puppeteerEvaluateWithCatch({
|
|
args,
|
|
frame,
|
|
page,
|
|
pageFunction,
|
|
timeoutInMilliseconds,
|
|
}),
|
|
]).then((data) => {
|
|
if (timeout !== null) {
|
|
clearTimeout(timeout);
|
|
}
|
|
return data;
|
|
});
|
|
}
|
|
async function puppeteerEvaluateWithCatch({ page, pageFunction, frame, args, }) {
|
|
var _a, _b, _c, _d, _e, _f;
|
|
const contextId = (await page.mainFrame().executionContext())._contextId;
|
|
const client = page._client();
|
|
const suffix = `//# sourceURL=${EVALUATION_SCRIPT_URL}`;
|
|
if (typeof pageFunction !== 'function')
|
|
throw new Error(`Expected to get |string| or |function| as the first argument, but got "${pageFunction}" instead.`);
|
|
let functionText = pageFunction.toString();
|
|
try {
|
|
// eslint-disable-next-line no-new-func
|
|
new Function('(' + functionText + ')');
|
|
}
|
|
catch (_g) {
|
|
// This means we might have a function shorthand. Try another
|
|
// time prefixing 'function '.
|
|
if (functionText.startsWith('async '))
|
|
functionText =
|
|
'async function ' + functionText.substring('async '.length);
|
|
else
|
|
functionText = 'function ' + functionText;
|
|
try {
|
|
// eslint-disable-next-line no-new-func
|
|
new Function('(' + functionText + ')');
|
|
}
|
|
catch (_h) {
|
|
// We tried hard to serialize, but there's a weird beast here.
|
|
throw new Error('Passed function is not well-serializable!');
|
|
}
|
|
}
|
|
let callFunctionOnPromise;
|
|
try {
|
|
callFunctionOnPromise = client.send('Runtime.callFunctionOn', {
|
|
functionDeclaration: functionText + '\n' + suffix + '\n',
|
|
executionContextId: contextId,
|
|
arguments: args.map((a) => convertArgument(a)),
|
|
returnByValue: true,
|
|
awaitPromise: true,
|
|
userGesture: true,
|
|
});
|
|
}
|
|
catch (error) {
|
|
if (error instanceof TypeError &&
|
|
error.message.startsWith('Converting circular structure to JSON')) {
|
|
error.message += ' Are you passing a nested JSHandle?';
|
|
}
|
|
throw error;
|
|
}
|
|
try {
|
|
const { value: { exceptionDetails, result: remoteObject }, size, } = await callFunctionOnPromise;
|
|
if (exceptionDetails) {
|
|
const err = new symbolicateable_error_1.SymbolicateableError({
|
|
stack: (_a = exceptionDetails.exception) === null || _a === void 0 ? void 0 : _a.description,
|
|
name: (_b = exceptionDetails.exception) === null || _b === void 0 ? void 0 : _b.className,
|
|
message: (_d = (_c = exceptionDetails.exception) === null || _c === void 0 ? void 0 : _c.description) === null || _d === void 0 ? void 0 : _d.split('\n')[0],
|
|
frame,
|
|
stackFrame: (0, parse_browser_error_stack_1.parseStack)(((_e = exceptionDetails.exception) === null || _e === void 0 ? void 0 : _e.description).split('\n')),
|
|
chunk: null,
|
|
});
|
|
page.close();
|
|
throw err;
|
|
}
|
|
return { size, value: valueFromRemoteObject(remoteObject) };
|
|
}
|
|
catch (error) {
|
|
if ((_f = error === null || error === void 0 ? void 0 : error.originalMessage) === null || _f === void 0 ? void 0 : _f.startsWith("Object couldn't be returned by value")) {
|
|
throw new Error('Could not serialize the return value of the function. Did you pass non-serializable values to defaultProps?');
|
|
}
|
|
throw error;
|
|
}
|
|
}
|
|
/**
|
|
* @param {*} arg
|
|
* @returns {*}
|
|
* @this {ExecutionContext}
|
|
*/
|
|
function convertArgument(arg) {
|
|
if (typeof arg === 'number') {
|
|
return { value: arg };
|
|
}
|
|
if (typeof arg === 'string') {
|
|
return { value: arg };
|
|
}
|
|
if (typeof arg === 'boolean') {
|
|
return { value: arg };
|
|
}
|
|
if (typeof arg === 'bigint')
|
|
return { unserializableValue: `${arg.toString()}n` };
|
|
if (Object.is(arg, -0))
|
|
return { unserializableValue: '-0' };
|
|
if (Object.is(arg, Infinity))
|
|
return { unserializableValue: 'Infinity' };
|
|
if (Object.is(arg, -Infinity))
|
|
return { unserializableValue: '-Infinity' };
|
|
if (Object.is(arg, NaN))
|
|
return { unserializableValue: 'NaN' };
|
|
const objectHandle = arg && arg instanceof JSHandle_1.JSHandle ? arg : null;
|
|
if (objectHandle) {
|
|
if (objectHandle._disposed)
|
|
throw new Error('JSHandle is disposed!');
|
|
if (objectHandle._remoteObject.unserializableValue)
|
|
return {
|
|
unserializableValue: objectHandle._remoteObject.unserializableValue,
|
|
};
|
|
if (!objectHandle._remoteObject.objectId)
|
|
return { value: objectHandle._remoteObject.value };
|
|
return { objectId: objectHandle._remoteObject.objectId };
|
|
}
|
|
return { value: arg };
|
|
}
|