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