Inline helper eval functions

This commit is contained in:
Pavel Feldman 2017-06-19 18:03:01 -07:00
parent 84bc09bce1
commit 4761f13740
2 changed files with 36 additions and 87 deletions

View File

@ -16,7 +16,6 @@
var fs = require('fs');
var EventEmitter = require('events');
var helpers = require('./helpers');
var mime = require('mime');
var Request = require('./Request');
var Dialog = require('./Dialog');
@ -34,7 +33,7 @@ class Page extends EventEmitter {
client.send('Runtime.enable', {}),
client.send('Security.enable', {}),
]);
var expression = helpers.evaluationString(() => window.devicePixelRatio, []);
var expression = Page._evaluationString(() => window.devicePixelRatio);
var {result:{value: screenDPI}} = await client.send('Runtime.evaluate', { expression, returnByValue: true });
var frameManager = await FrameManager.create(client);
var page = new Page(client, frameManager, screenDPI);
@ -127,8 +126,11 @@ class Page extends EventEmitter {
* @return {!Promise}
*/
async injectFile(filePath) {
var expression = fs.readFileSync(filePath, 'utf8');
await this._client.send('Runtime.evaluate', { expression, returnByValue: true });
var callback;
var promise = new Promise(fulfill => callback = fulfill);
var expression = fs.readFile(filePath, 'utf8', (err, data) => callback({err, data}));
await promise;
return this._client.send('Runtime.evaluate', { expression, returnByValue: true });
}
/**
@ -140,7 +142,7 @@ class Page extends EventEmitter {
throw new Error(`Failed to set in-page callback with name ${name}: window['${name}'] already exists!`);
this._inPageCallbacks[name] = callback;
var expression = helpers.evaluationString(inPageCallback, [name]);
var expression = Page._evaluationString(inPageCallback, name);
await this._client.send('Page.addScriptToEvaluateOnLoad', { scriptSource: expression });
await this._client.send('Runtime.evaluate', { expression, returnByValue: true });
@ -209,7 +211,7 @@ class Page extends EventEmitter {
if (event.type === 'debug' && event.args.length && event.args[0].value === 'driver:InPageCallback') {
var {name, seq, args} = JSON.parse(event.args[1].value);
var result = await this._inPageCallbacks[name](...args);
var expression = helpers.evaluationString(deliverResult, [name, seq, result]);
var expression = Page._evaluationString(deliverResult, name, seq, result);
this._client.send('Runtime.evaluate', { expression });
function deliverResult(name, seq, result) {
@ -241,9 +243,7 @@ class Page extends EventEmitter {
* @return {!Promise<string>}
*/
async url() {
return this.evaluate(function() {
return window.location.href;
});
return this.evaluate(() => window.location.href);
}
/**
@ -251,11 +251,11 @@ class Page extends EventEmitter {
* @return {!Promise}
*/
async setContent(html) {
var resourceTree = await this._client.send('Page.getResourceTree', {});
await this._client.send('Page.setDocumentContent', {
frameId: resourceTree.frameTree.frame.id,
html: html
});
this.evaluate(() => {
document.open();
document.write(html);
document.close();
}, html);
}
/**
@ -280,7 +280,7 @@ class Page extends EventEmitter {
* @return {!Promise}
*/
async setViewportSize(size) {
this._size = size;
this._viewportSize = size;
var width = size.width;
var height = size.height;
var zoom = this._screenDPI;
@ -304,7 +304,7 @@ class Page extends EventEmitter {
* @return {!{width: number, height: number}}
*/
viewportSize() {
return this._size;
return this._viewportSize;
}
/**
@ -313,34 +313,14 @@ class Page extends EventEmitter {
* @return {!Promise<(!Object|undefined)>}
*/
async evaluate(fun, ...args) {
var code = helpers.evaluationString(fun, args, false /* wrapInPromise */);
var response = await this._client.send('Runtime.evaluate', {
expression: code
});
if (response.exceptionDetails) {
var message = await this._getExceptionMessage(response.exceptionDetails);
var syncExpression = Page._evaluationString(fun, ...args);
var expression = `Promise.resolve(${syncExpression})`;
var { exceptionDetails, result: remoteObject } = await this._client.send('Runtime.evaluate', { expression, returnByValue: true, awaitPromise: true });
if (exceptionDetails) {
var message = await this._getExceptionMessage(exceptionDetails);
throw new Error('Evaluation failed: ' + message);
}
var remoteObject = response.result;
if (remoteObject.type !== 'object')
return remoteObject.value;
var isPromise = remoteObject.type === 'object' && remoteObject.subtype === 'promise';
var response = await this._client.send('Runtime.callFunctionOn', {
objectId: remoteObject.objectId,
functionDeclaration: 'function() { return this; }',
returnByValue: true,
awaitPromise: isPromise
});
await this._client.send('Runtime.releaseObject', {
objectId: remoteObject.objectId
});
if (response.exceptionDetails) {
var message = await this._getExceptionMessage(response.exceptionDetails);
throw new Error('Evaluation failed with ' + message);
}
return response.result.value;
}
/**
@ -360,6 +340,7 @@ class Page extends EventEmitter {
} else {
message = exceptionDetails.text;
}
if (exceptionDetails.stackTrace) {
for (var callframe of exceptionDetails.stackTrace.callFrames) {
var location = callframe.url + ':' + callframe.lineNumber + ':' + callframe.columnNumber;
@ -376,10 +357,17 @@ class Page extends EventEmitter {
* @return {!Promise}
*/
async evaluateOnInitialized(fun, ...args) {
var code = helpers.evaluationString(fun, args, false /* wrapInPromise */);
await this._client.send('Page.addScriptToEvaluateOnLoad', {
scriptSource: code
});
var scriptSource = Page._evaluationString(fun, ...args);
await this._client.send('Page.addScriptToEvaluateOnLoad', { scriptSource });
}
/**
* @param {function()} fun
* @param {!Array<*>} args
* @return {string}
*/
static _evaluationString(fun, ...args) {
return `(${fun})(${args.map(x => JSON.stringify(x)).join(',')})`;
}
/**
@ -524,18 +512,14 @@ class Page extends EventEmitter {
* @return {!Promise<string>}
*/
async plainText() {
return this.evaluate(function() {
return document.body.innerText;
});
return this.evaluate(() => document.body.innerText);
}
/**
* @return {!Promise<string>}
*/
async title() {
return this.evaluate(function() {
return document.title;
});
return this.evaluate(() => document.title);
}
/**

View File

@ -1,35 +0,0 @@
/**
* Copyright 2017 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.
*/
module.exports = {
/**
* @param {function()} fun
* @param {!Array<*>} args
* @param {boolean=} wrapInPromise
* @param {string=} sourceURL
* @return {string}
*/
evaluationString: function(fun, args, wrapInPromise, sourceURL) {
var argsString = args.map(x => JSON.stringify(x)).join(',');
var code = `(${fun.toString()})(${argsString})`;
if (wrapInPromise)
code = `Promise.resolve(${code})`;
if (sourceURL)
code += `\n//# sourceURL=${sourceURL}`;
return code;
}
};