mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
Implement Frame.evaluate
This patch implements Frame.evaluate method. References #4.
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
let EventEmitter = require('events');
|
||||
let helper = require('./helper');
|
||||
|
||||
class FrameManager extends EventEmitter {
|
||||
/**
|
||||
@@ -37,9 +38,14 @@ class FrameManager extends EventEmitter {
|
||||
this._frames = new Map();
|
||||
this._mainFrame = this._addFramesRecursively(null, frameTree);
|
||||
|
||||
this._client.on('Page.frameAttached', event => this._frameAttached(event.frameId, event.parentFrameId));
|
||||
this._client.on('Page.frameNavigated', event => this._frameNavigated(event.frame));
|
||||
this._client.on('Page.frameDetached', event => this._frameDetached(event.frameId));
|
||||
/** @type {!Map<string, string>} */
|
||||
this._frameIdToExecutionContextId = new Map();
|
||||
|
||||
this._client.on('Page.frameAttached', event => this._onFrameAttached(event.frameId, event.parentFrameId));
|
||||
this._client.on('Page.frameNavigated', event => this._onFrameNavigated(event.frame));
|
||||
this._client.on('Page.frameDetached', event => this._onFrameDetached(event.frameId));
|
||||
this._client.on('Runtime.executionContextCreated', event => this._onExecutionContextCreated(event.context));
|
||||
this._client.on('Runtime.executionContextDestroyed', event => this._onExecutionContextDestroyed(event.executionContextId));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,7 +67,7 @@ class FrameManager extends EventEmitter {
|
||||
* @param {?string} parentFrameId
|
||||
* @return {?Frame}
|
||||
*/
|
||||
_frameAttached(frameId, parentFrameId) {
|
||||
_onFrameAttached(frameId, parentFrameId) {
|
||||
if (this._frames.has(frameId))
|
||||
return;
|
||||
|
||||
@@ -71,7 +77,7 @@ class FrameManager extends EventEmitter {
|
||||
return;
|
||||
}
|
||||
let parentFrame = this._frames.get(parentFrameId);
|
||||
let frame = new Frame(parentFrame, frameId, null);
|
||||
let frame = new Frame(this, parentFrame, frameId, null);
|
||||
this._frames.set(frame._id, frame);
|
||||
this.emit(FrameManager.Events.FrameAttached, frame);
|
||||
}
|
||||
@@ -79,7 +85,7 @@ class FrameManager extends EventEmitter {
|
||||
/**
|
||||
* @param {!Object} framePayload
|
||||
*/
|
||||
_frameNavigated(framePayload) {
|
||||
_onFrameNavigated(framePayload) {
|
||||
let frame = this._frames.get(framePayload.id);
|
||||
if (!frame) {
|
||||
// Simulate missed "frameAttached" for a main frame navigation to the new backend process.
|
||||
@@ -92,12 +98,21 @@ class FrameManager extends EventEmitter {
|
||||
/**
|
||||
* @param {string} frameId
|
||||
*/
|
||||
_frameDetached(frameId) {
|
||||
_onFrameDetached(frameId) {
|
||||
let frame = this._frames.get(frameId);
|
||||
if (frame)
|
||||
this._removeFramesRecursively(frame);
|
||||
}
|
||||
|
||||
_onExecutionContextCreated(context) {
|
||||
if (context.auxData && context.auxData.isDefault && context.auxData.frameId)
|
||||
this._frameIdToExecutionContextId.set(context.auxData.frameId, context.id);
|
||||
}
|
||||
|
||||
_onExecutionContextDestroyed(executionContextId) {
|
||||
this._frameIdToExecutionContextId.delete(executionContextId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {!Frame} frame
|
||||
* @param {string} newFrameId
|
||||
@@ -121,7 +136,7 @@ class FrameManager extends EventEmitter {
|
||||
*/
|
||||
_addFramesRecursively(parentFrame, frameTreePayload) {
|
||||
let framePayload = frameTreePayload.frame;
|
||||
let frame = new Frame(parentFrame, framePayload.id, framePayload);
|
||||
let frame = new Frame(this, parentFrame, framePayload.id, framePayload);
|
||||
this._frames.set(frame._id, frame);
|
||||
|
||||
for (let i = 0; frameTreePayload.childFrames && i < frameTreePayload.childFrames.length; ++i)
|
||||
@@ -139,6 +154,28 @@ class FrameManager extends EventEmitter {
|
||||
this._frames.delete(frame._id);
|
||||
this.emit(FrameManager.Events.FrameDetached, frame);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {!Frame} frame
|
||||
* @param {function()} fun
|
||||
* @param {!Array<*>} args
|
||||
* @return {!Promise<(!Object|undefined)>}
|
||||
*/
|
||||
async _evaluateOnFrame(frame, fun, ...args) {
|
||||
let contextId = undefined;
|
||||
if (!frame.isMainFrame()) {
|
||||
contextId = this._frameIdToExecutionContextId.get(frame._id);
|
||||
console.assert(contextId, 'Frame does not have default context to evaluate in!');
|
||||
}
|
||||
let syncExpression = helper.evaluationString(fun, ...args);
|
||||
let expression = `Promise.resolve(${syncExpression})`;
|
||||
let { exceptionDetails, result: remoteObject } = await this._client.send('Runtime.evaluate', { expression, contextId, returnByValue: true, awaitPromise: true });
|
||||
if (exceptionDetails) {
|
||||
let message = await helper.getExceptionMessage(this._client, exceptionDetails);
|
||||
throw new Error('Evaluation failed: ' + message);
|
||||
}
|
||||
return remoteObject.value;
|
||||
}
|
||||
}
|
||||
|
||||
/** @enum {string} */
|
||||
@@ -153,11 +190,13 @@ FrameManager.Events = {
|
||||
*/
|
||||
class Frame {
|
||||
/**
|
||||
* @param {!FrameManager} frameManager
|
||||
* @param {?Frame} parentFrame
|
||||
* @param {string} frameId
|
||||
* @param {?Object} payload
|
||||
*/
|
||||
constructor(parentFrame, frameId, payload) {
|
||||
constructor(frameManager, parentFrame, frameId, payload) {
|
||||
this._frameManager = frameManager;
|
||||
this._parentFrame = parentFrame;
|
||||
this._url = '';
|
||||
this._id = frameId;
|
||||
@@ -169,6 +208,15 @@ class Frame {
|
||||
this._parentFrame._childFrames.add(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {function()} fun
|
||||
* @param {!Array<*>} args
|
||||
* @return {!Promise<(!Object|undefined)>}
|
||||
*/
|
||||
async evaluate(fun, ...args) {
|
||||
return this._frameManager._evaluateOnFrame(this, fun, ...args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user