mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
fix(page): do evaluations with one roundtrip (#4539)
This patch teaches page.evaluate to do 1 hop instead of 2 hops. As a result, things such as `page.select` will not throw an unfortunate exception when they schedule a navigation. Fix #4537
This commit is contained in:
@@ -45,16 +45,15 @@ class ExecutionContext {
|
||||
* @return {!Promise<(!Object|undefined)>}
|
||||
*/
|
||||
async evaluate(pageFunction, ...args) {
|
||||
const handle = await this.evaluateHandle(pageFunction, ...args);
|
||||
const result = await handle.jsonValue().catch(error => {
|
||||
try {
|
||||
return await this._evaluateInternal(true /* returnByValue */, pageFunction, ...args);
|
||||
} catch (error) {
|
||||
if (error.message.includes('Object reference chain is too long'))
|
||||
return;
|
||||
if (error.message.includes('Object couldn\'t be returned by value'))
|
||||
return;
|
||||
throw error;
|
||||
});
|
||||
await handle.dispose();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,6 +62,15 @@ class ExecutionContext {
|
||||
* @return {!Promise<!JSHandle>}
|
||||
*/
|
||||
async evaluateHandle(pageFunction, ...args) {
|
||||
return this._evaluateInternal(false /* returnByValue */, pageFunction, ...args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Function|string} pageFunction
|
||||
* @param {...*} args
|
||||
* @return {!Promise<!JSHandle>}
|
||||
*/
|
||||
async _evaluateInternal(returnByValue, pageFunction, ...args) {
|
||||
const suffix = `//# sourceURL=${EVALUATION_SCRIPT_URL}`;
|
||||
|
||||
if (helper.isString(pageFunction)) {
|
||||
@@ -72,13 +80,13 @@ class ExecutionContext {
|
||||
const {exceptionDetails, result: remoteObject} = await this._client.send('Runtime.evaluate', {
|
||||
expression: expressionWithSourceUrl,
|
||||
contextId,
|
||||
returnByValue: false,
|
||||
returnByValue,
|
||||
awaitPromise: true,
|
||||
userGesture: true
|
||||
}).catch(rewriteError);
|
||||
if (exceptionDetails)
|
||||
throw new Error('Evaluation failed: ' + helper.getExceptionMessage(exceptionDetails));
|
||||
return createJSHandle(this, remoteObject);
|
||||
return returnByValue ? helper.valueFromRemoteObject(remoteObject) : createJSHandle(this, remoteObject);
|
||||
}
|
||||
|
||||
if (typeof pageFunction !== 'function')
|
||||
@@ -107,7 +115,7 @@ class ExecutionContext {
|
||||
functionDeclaration: functionText + '\n' + suffix + '\n',
|
||||
executionContextId: this._contextId,
|
||||
arguments: args.map(convertArgument.bind(this)),
|
||||
returnByValue: false,
|
||||
returnByValue,
|
||||
awaitPromise: true,
|
||||
userGesture: true
|
||||
});
|
||||
@@ -119,7 +127,7 @@ class ExecutionContext {
|
||||
const { exceptionDetails, result: remoteObject } = await callFunctionOnPromise.catch(rewriteError);
|
||||
if (exceptionDetails)
|
||||
throw new Error('Evaluation failed: ' + helper.getExceptionMessage(exceptionDetails));
|
||||
return createJSHandle(this, remoteObject);
|
||||
return returnByValue ? helper.valueFromRemoteObject(remoteObject) : createJSHandle(this, remoteObject);
|
||||
|
||||
/**
|
||||
* @param {*} arg
|
||||
|
||||
Reference in New Issue
Block a user