mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
Move inner evaluate helpers into frame class. (#128)
This commit is contained in:
committed by
Andrey Lushnikov
parent
4f5f1f6d77
commit
0007809305
@@ -42,9 +42,6 @@ class FrameManager extends EventEmitter {
|
||||
this._frames = new Map();
|
||||
this._mainFrame = this._addFramesRecursively(null, frameTree);
|
||||
|
||||
/** @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));
|
||||
@@ -73,14 +70,9 @@ class FrameManager extends EventEmitter {
|
||||
_onFrameAttached(frameId, parentFrameId) {
|
||||
if (this._frames.has(frameId))
|
||||
return;
|
||||
|
||||
if (!parentFrameId) {
|
||||
// Navigation to the new backend process.
|
||||
this._navigateFrame(this._mainFrame, frameId, null);
|
||||
return;
|
||||
}
|
||||
console.assert(parentFrameId);
|
||||
let parentFrame = this._frames.get(parentFrameId);
|
||||
let frame = new Frame(this, parentFrame, frameId, null);
|
||||
let frame = new Frame(this._client, this._mouse, parentFrame, frameId, null);
|
||||
this._frames.set(frame._id, frame);
|
||||
this.emit(FrameManager.Events.FrameAttached, frame);
|
||||
}
|
||||
@@ -108,8 +100,11 @@ class FrameManager extends EventEmitter {
|
||||
}
|
||||
|
||||
_onExecutionContextCreated(context) {
|
||||
if (context.auxData && context.auxData.isDefault && context.auxData.frameId)
|
||||
this._frameIdToExecutionContextId.set(context.auxData.frameId, context.id);
|
||||
const frameId = context.auxData && context.auxData.isDefault ? context.auxData.frameId : null;
|
||||
const frame = this._frames.get(frameId);
|
||||
if (!frame)
|
||||
return;
|
||||
frame._defaultContextId = context.id;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -122,7 +117,6 @@ class FrameManager extends EventEmitter {
|
||||
for (let child of frame.childFrames())
|
||||
this._removeFramesRecursively(child);
|
||||
this._frames.delete(frame._id, frame);
|
||||
this._frameIdToExecutionContextId.delete(frame._id);
|
||||
frame._id = newFrameId;
|
||||
frame._adoptPayload(newFramePayload);
|
||||
this._frames.set(newFrameId, frame);
|
||||
@@ -136,7 +130,7 @@ class FrameManager extends EventEmitter {
|
||||
*/
|
||||
_addFramesRecursively(parentFrame, frameTreePayload) {
|
||||
let framePayload = frameTreePayload.frame;
|
||||
let frame = new Frame(this, parentFrame, framePayload.id, framePayload);
|
||||
let frame = new Frame(this._client, this._mouse, parentFrame, framePayload.id, framePayload);
|
||||
this._frames.set(frame._id, frame);
|
||||
|
||||
for (let i = 0; frameTreePayload.childFrames && i < frameTreePayload.childFrames.length; ++i)
|
||||
@@ -152,49 +146,8 @@ class FrameManager extends EventEmitter {
|
||||
this._removeFramesRecursively(child);
|
||||
frame._detach();
|
||||
this._frames.delete(frame._id);
|
||||
this._frameIdToExecutionContextId.delete(frame._id);
|
||||
this.emit(FrameManager.Events.FrameDetached, frame);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {!Frame} frame
|
||||
* @return {number}
|
||||
*/
|
||||
_contextIdForFrame(frame) {
|
||||
let contextId = undefined;
|
||||
if (frame !== this._mainFrame) {
|
||||
contextId = this._frameIdToExecutionContextId.get(frame._id);
|
||||
console.assert(contextId, 'Frame does not have default context to evaluate in!');
|
||||
}
|
||||
return contextId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {!Frame} frame
|
||||
* @param {string} expression
|
||||
* @return {!Promise<(!Object|undefined)>}
|
||||
*/
|
||||
async _evaluateOnFrame(frame, expression) {
|
||||
let contextId = this._contextIdForFrame(frame);
|
||||
expression = `Promise.resolve(${expression})`;
|
||||
let { exceptionDetails, result: remoteObject } = await this._client.send('Runtime.evaluate', { expression, contextId, returnByValue: false, awaitPromise: true });
|
||||
if (exceptionDetails)
|
||||
throw new Error('Evaluation failed: ' + helper.getExceptionMessage(exceptionDetails));
|
||||
return await helper.serializeRemoteObject(this._client, remoteObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {!Frame} frame
|
||||
* @param {string} expression
|
||||
* @return {!Promise<(!Object|undefined)>}
|
||||
*/
|
||||
async _rawEvaluateOnFrame(frame, expression) {
|
||||
let contextId = this._contextIdForFrame(frame);
|
||||
let { exceptionDetails, result: remoteObject } = await this._client.send('Runtime.evaluate', { expression, contextId, returnByValue: false });
|
||||
if (exceptionDetails)
|
||||
throw new Error('Evaluation failed: ' + helper.getExceptionMessage(exceptionDetails));
|
||||
return await helper.serializeRemoteObject(this._client, remoteObject);
|
||||
}
|
||||
}
|
||||
|
||||
/** @enum {string} */
|
||||
@@ -209,16 +162,19 @@ FrameManager.Events = {
|
||||
*/
|
||||
class Frame {
|
||||
/**
|
||||
* @param {!FrameManager} frameManager
|
||||
* @param {!Connection} client
|
||||
* @param {!Mouse} mouse
|
||||
* @param {?Frame} parentFrame
|
||||
* @param {string} frameId
|
||||
* @param {?Object} payload
|
||||
*/
|
||||
constructor(frameManager, parentFrame, frameId, payload) {
|
||||
this._frameManager = frameManager;
|
||||
constructor(client, mouse, parentFrame, frameId, payload) {
|
||||
this._client = client;
|
||||
this._mouse = mouse;
|
||||
this._parentFrame = parentFrame;
|
||||
this._url = '';
|
||||
this._id = frameId;
|
||||
this._defaultContextId = '<not-initialized>';
|
||||
/** @type {!Set<!WaitTask>} */
|
||||
this._waitTasks = new Set();
|
||||
|
||||
@@ -236,7 +192,22 @@ class Frame {
|
||||
* @return {!Promise<(!Object|undefined)>}
|
||||
*/
|
||||
async evaluate(pageFunction, ...args) {
|
||||
return this._frameManager._evaluateOnFrame(this, helper.evaluationString(pageFunction, ...args));
|
||||
return this._evaluateExpression(helper.evaluationString(pageFunction, ...args), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} expression
|
||||
* @param {boolean} awaitPromise
|
||||
* @return {!Promise<(!Object|undefined)>}
|
||||
*/
|
||||
async _evaluateExpression(expression, awaitPromise) {
|
||||
const contextId = this._defaultContextId;
|
||||
if (awaitPromise)
|
||||
expression = `Promise.resolve(${expression})`;
|
||||
let { exceptionDetails, result: remoteObject } = await this._client.send('Runtime.evaluate', { expression, contextId, returnByValue: false, awaitPromise});
|
||||
if (exceptionDetails)
|
||||
throw new Error('Evaluation failed: ' + helper.getExceptionMessage(exceptionDetails));
|
||||
return await helper.serializeRemoteObject(this._client, remoteObject);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -286,7 +257,7 @@ class Frame {
|
||||
});
|
||||
});
|
||||
contents += `//# sourceURL=` + filePath.replace(/\n/g,'');
|
||||
return this._frameManager._rawEvaluateOnFrame(this, contents);
|
||||
return this._evaluateExpression(contents, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -330,7 +301,7 @@ class Frame {
|
||||
const timeout = options.timeout || 30000;
|
||||
const waitForVisible = !!options.visible;
|
||||
const pageScript = helper.evaluationString(waitForSelectorPageFunction, selector, waitForVisible, timeout);
|
||||
const waitTask = new WaitTask(this._frameManager, this, pageScript, timeout);
|
||||
const waitTask = new WaitTask(this, pageScript, timeout);
|
||||
|
||||
this._waitTasks.add(waitTask);
|
||||
let cleanup = () => this._waitTasks.delete(waitTask);
|
||||
@@ -352,7 +323,7 @@ class Frame {
|
||||
return null;
|
||||
return (${pageFunction})(${argsString});
|
||||
})()`;
|
||||
return this._frameManager._evaluateOnFrame(this, expression);
|
||||
return this._evaluateExpression(expression, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -367,7 +338,7 @@ class Frame {
|
||||
let nodes = document.querySelectorAll(${JSON.stringify(selector)});
|
||||
return Array.prototype.map.call(nodes, (node, index) => (${pageFunction})(${argsString}));
|
||||
})()`;
|
||||
return this._frameManager._evaluateOnFrame(this, expression);
|
||||
return this._evaluateExpression(expression, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -395,7 +366,7 @@ class Frame {
|
||||
}, selector);
|
||||
if (!center)
|
||||
throw new Error('No node found for selector: ' + selector);
|
||||
await this._frameManager._mouse.move(center.x, center.y);
|
||||
await this._mouse.move(center.x, center.y);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -405,7 +376,7 @@ class Frame {
|
||||
*/
|
||||
async click(selector, options) {
|
||||
await this.hover(selector);
|
||||
await this._frameManager._mouse.press(options);
|
||||
await this._mouse.press(options);
|
||||
// This is a hack for now, to make clicking less race-prone
|
||||
await this.evaluate(() => new Promise(f => requestAnimationFrame(f)));
|
||||
}
|
||||
@@ -453,13 +424,11 @@ helper.tracePublicAPI(Frame);
|
||||
|
||||
class WaitTask {
|
||||
/**
|
||||
* @param {!FrameManager} frameManager
|
||||
* @param {!Frame} frame
|
||||
* @param {string} pageScript
|
||||
* @param {number} timeout
|
||||
*/
|
||||
constructor(frameManager, frame, pageScript, timeout) {
|
||||
this._frameManager = frameManager;
|
||||
constructor(frame, pageScript, timeout) {
|
||||
this._frame = frame;
|
||||
this._pageScript = pageScript;
|
||||
this._runningTask = null;
|
||||
@@ -482,7 +451,7 @@ class WaitTask {
|
||||
}
|
||||
|
||||
run() {
|
||||
let runningTask = this._frameManager._evaluateOnFrame(this._frame, this._pageScript).then(finish.bind(this), finish.bind(this, false));
|
||||
let runningTask = this._frame._evaluateExpression(this._pageScript, true).then(finish.bind(this), finish.bind(this, false));
|
||||
this._runningTask = runningTask;
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user