parent
ef426b5721
commit
8e0a3ac6d9
@ -19,14 +19,26 @@ var browser = new Browser();
|
|||||||
|
|
||||||
browser.newPage().then(async page => {
|
browser.newPage().then(async page => {
|
||||||
page.on('consolemessage', console.log);
|
page.on('consolemessage', console.log);
|
||||||
|
|
||||||
|
|
||||||
await page.setInPageCallback('callPhantom', msg => {
|
await page.setInPageCallback('callPhantom', msg => {
|
||||||
console.log("Received by the 'phantom' main context: "+msg);
|
console.log("Page is saying: '" + msg + "'");
|
||||||
return "Hello there, I'm coming to you from the 'phantom' context instead";
|
return "Hello, page";
|
||||||
});
|
});
|
||||||
await page.evaluate(function() {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
await page.evaluate(async function() {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Return-value of the "onCallback" handler arrive here
|
// Return-value of the "onCallback" handler arrive here
|
||||||
var callbackResponse = window.callPhantom("Hello, I'm coming to you from the 'page' context");
|
var callbackResponse = await window.callPhantom("Hello, driver");
|
||||||
console.log("Received by the 'page' context: "+callbackResponse);
|
console.log("Driver is saying: '" + callbackResponse + "'");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
browser.close();
|
browser.close();
|
||||||
});
|
});
|
||||||
|
@ -38,7 +38,7 @@ class Browser {
|
|||||||
options = options || {};
|
options = options || {};
|
||||||
++browserId;
|
++browserId;
|
||||||
this._userDataDir = CHROME_PROFILE_PATH + browserId;
|
this._userDataDir = CHROME_PROFILE_PATH + browserId;
|
||||||
this._remoteDebuggingPort = 9229;
|
this._remoteDebuggingPort = 9227;
|
||||||
if (typeof options.remoteDebuggingPort === 'number')
|
if (typeof options.remoteDebuggingPort === 'number')
|
||||||
this._remoteDebuggingPort = options.remoteDebuggingPort;
|
this._remoteDebuggingPort = options.remoteDebuggingPort;
|
||||||
this._chromeArguments = DEFAULT_ARGS.concat([
|
this._chromeArguments = DEFAULT_ARGS.concat([
|
||||||
|
94
lib/Page.js
94
lib/Page.js
@ -50,17 +50,13 @@ class Page extends EventEmitter {
|
|||||||
this._client = client;
|
this._client = client;
|
||||||
this._screenDPI = screenDPI;
|
this._screenDPI = screenDPI;
|
||||||
this._extraHeaders = {};
|
this._extraHeaders = {};
|
||||||
/** @type {!Map<string, !InPageCallback>} */
|
/** @type {!Map<string, function>} */
|
||||||
this._sourceURLToPageCallback = new Map();
|
this._inPageCallbacks = new Map();
|
||||||
/** @type {!Map<string, !InPageCallback>} */
|
|
||||||
this._scriptIdToPageCallback = new Map();
|
|
||||||
/** @type {?function(!Request)} */
|
/** @type {?function(!Request)} */
|
||||||
this._requestInterceptor = null;
|
this._requestInterceptor = null;
|
||||||
|
|
||||||
this._screenshotTaskChain = Promise.resolve();
|
this._screenshotTaskChain = Promise.resolve();
|
||||||
|
|
||||||
client.on('Debugger.paused', event => this._onDebuggerPaused(event));
|
|
||||||
client.on('Debugger.scriptParsed', event => this._onScriptParsed(event));
|
|
||||||
client.on('Network.responseReceived', event => this.emit(Page.Events.ResponseReceived, event.response));
|
client.on('Network.responseReceived', event => this.emit(Page.Events.ResponseReceived, event.response));
|
||||||
client.on('Network.loadingFailed', event => this.emit(Page.Events.ResourceLoadingFailed, event));
|
client.on('Network.loadingFailed', event => this.emit(Page.Events.ResourceLoadingFailed, event));
|
||||||
client.on('Network.requestIntercepted', event => this._onRequestIntercepted(event));
|
client.on('Network.requestIntercepted', event => this._onRequestIntercepted(event));
|
||||||
@ -118,69 +114,31 @@ class Page extends EventEmitter {
|
|||||||
* @param {function(?)} callback
|
* @param {function(?)} callback
|
||||||
*/
|
*/
|
||||||
async setInPageCallback(name, callback) {
|
async setInPageCallback(name, callback) {
|
||||||
var hasCallback = await this.evaluate(function(name) {
|
if (this._inPageCallbacks[name])
|
||||||
return !!window[name];
|
|
||||||
}, name);
|
|
||||||
if (hasCallback)
|
|
||||||
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;
|
||||||
|
|
||||||
var sourceURL = '__in_page_callback__' + name;
|
var expression = helpers.evaluationString(inPageCallback, [name]);
|
||||||
this._sourceURLToPageCallback.set(sourceURL, new InPageCallback(name, callback));
|
await this._client.send('Page.addScriptToEvaluateOnLoad', { scriptSource: expression });
|
||||||
var expression = helpers.evaluationString(inPageCallback, [name], false /* wrapInPromise */, sourceURL);
|
await this._client.send('Runtime.evaluate', { expression, returnByValue: true });
|
||||||
await Promise.all([
|
|
||||||
this._client.send('Debugger.enable', {}),
|
|
||||||
this._client.send('Page.addScriptToEvaluateOnLoad', { scriptSource: expression }),
|
|
||||||
this._client.send('Runtime.evaluate', { expression, returnByValue: true })
|
|
||||||
]);
|
|
||||||
|
|
||||||
function inPageCallback(callbackName) {
|
function inPageCallback(callbackName) {
|
||||||
window[callbackName] = (...args) => {
|
window[callbackName] = async (...args) => {
|
||||||
window[callbackName].__args = args;
|
const me = window[callbackName];
|
||||||
debugger;
|
let callbacks = me['callbacks'];
|
||||||
var result = window[callbackName].__result;
|
if (!callbacks) {
|
||||||
delete window[callbackName].__result;
|
callbacks = new Map();
|
||||||
delete window[callbackName].__args;
|
me['callbacks'] = callbacks;
|
||||||
return result;
|
}
|
||||||
|
const seq = (me['lastSeq'] || 0) + 1;
|
||||||
|
me['lastSeq'] = seq;
|
||||||
|
const promise = new Promise(fulfill => callbacks.set(seq, fulfill));
|
||||||
|
console.debug('driver:InPageCallback', JSON.stringify({name: callbackName, seq, args}));
|
||||||
|
return promise;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {!InPageCallback} inPageCallback
|
|
||||||
*/
|
|
||||||
async _handleInPageCallback(inPageCallback) {
|
|
||||||
var name = inPageCallback.name;
|
|
||||||
var callback = inPageCallback.callback;
|
|
||||||
var args = await this.evaluate(callbackName => window[callbackName].__args, name);
|
|
||||||
var result = await Promise.resolve(callback.apply(null, args));
|
|
||||||
await this.evaluate(assignResult, name, result);
|
|
||||||
this._client.send('Debugger.resume');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} callbackName
|
|
||||||
* @param {string} callbackResult
|
|
||||||
*/
|
|
||||||
function assignResult(callbackName, callbackResult) {
|
|
||||||
window[callbackName].__result = callbackResult;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_onDebuggerPaused(event) {
|
|
||||||
var location = event.callFrames[0] ? event.callFrames[0].location : null;
|
|
||||||
var inPageCallback = location ? this._scriptIdToPageCallback.get(location.scriptId) : null;
|
|
||||||
if (inPageCallback) {
|
|
||||||
this._handleInPageCallback(inPageCallback);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this._client.send('Debugger.resume');
|
|
||||||
}
|
|
||||||
|
|
||||||
_onScriptParsed(event) {
|
|
||||||
var inPageCallback = this._sourceURLToPageCallback.get(event.url);
|
|
||||||
if (inPageCallback)
|
|
||||||
this._scriptIdToPageCallback.set(event.scriptId, inPageCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {!Object} headers
|
* @param {!Object} headers
|
||||||
* @return {!Promise}
|
* @return {!Promise}
|
||||||
@ -224,7 +182,19 @@ class Page extends EventEmitter {
|
|||||||
this.emit(Page.Events.Error, new Error(message));
|
this.emit(Page.Events.Error, new Error(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
_onConsoleAPI(event) {
|
async _onConsoleAPI(event) {
|
||||||
|
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]);
|
||||||
|
this._client.send('Runtime.evaluate', { expression });
|
||||||
|
|
||||||
|
function deliverResult(name, seq, result) {
|
||||||
|
window[name]['callbacks'].get(seq)(result);
|
||||||
|
window[name]['callbacks'].delete(seq);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
var values = event.args.map(arg => arg.value || arg.description || '');
|
var values = event.args.map(arg => arg.value || arg.description || '');
|
||||||
this.emit(Page.Events.ConsoleMessage, values.join(' '));
|
this.emit(Page.Events.ConsoleMessage, values.join(' '));
|
||||||
}
|
}
|
||||||
|
@ -39,10 +39,7 @@ class WebPage {
|
|||||||
if (options.viewportSize)
|
if (options.viewportSize)
|
||||||
await(this._page.setViewportSize(options.viewportSize));
|
await(this._page.setViewportSize(options.viewportSize));
|
||||||
|
|
||||||
await(this._page.setInPageCallback('callPhantom', (...args) => this.onCallback.apply(null, args)));
|
|
||||||
|
|
||||||
this.clipRect = options.clipRect || {left: 0, top: 0, width: 0, height: 0};
|
this.clipRect = options.clipRect || {left: 0, top: 0, width: 0, height: 0};
|
||||||
this.onCallback = null;
|
|
||||||
this.onConsoleMessage = null;
|
this.onConsoleMessage = null;
|
||||||
this.onLoadFinished = null;
|
this.onLoadFinished = null;
|
||||||
this.onResourceError = null;
|
this.onResourceError = null;
|
||||||
|
17
test/test.js
17
test/test.js
@ -70,8 +70,8 @@ describe('Puppeteer', function() {
|
|||||||
await page.setInPageCallback('callController', async function(a, b) {
|
await page.setInPageCallback('callController', async function(a, b) {
|
||||||
return await page.evaluate((a, b) => a * b, a, b);
|
return await page.evaluate((a, b) => a * b, a, b);
|
||||||
});
|
});
|
||||||
var result = await page.evaluate(function() {
|
var result = await page.evaluate(async function() {
|
||||||
return callController(9, 3);
|
return await callController(9, 3);
|
||||||
});
|
});
|
||||||
expect(result).toBe(27);
|
expect(result).toBe(27);
|
||||||
}));
|
}));
|
||||||
@ -110,9 +110,8 @@ describe('Puppeteer', function() {
|
|||||||
await page.setInPageCallback('callController', function(a, b) {
|
await page.setInPageCallback('callController', function(a, b) {
|
||||||
return a * b;
|
return a * b;
|
||||||
});
|
});
|
||||||
|
var result = await page.evaluate(async function() {
|
||||||
var result = await page.evaluate(function() {
|
return await callController(9, 4);
|
||||||
return callController(9, 4);
|
|
||||||
});
|
});
|
||||||
expect(result).toBe(36);
|
expect(result).toBe(36);
|
||||||
}));
|
}));
|
||||||
@ -122,8 +121,8 @@ describe('Puppeteer', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
await page.navigate(EMPTY_PAGE);
|
await page.navigate(EMPTY_PAGE);
|
||||||
var result = await page.evaluate(function() {
|
var result = await page.evaluate(async function() {
|
||||||
return callController(9, 4);
|
return await callController(9, 4);
|
||||||
});
|
});
|
||||||
expect(result).toBe(36);
|
expect(result).toBe(36);
|
||||||
}));
|
}));
|
||||||
@ -132,8 +131,8 @@ describe('Puppeteer', function() {
|
|||||||
return Promise.resolve(a * b);
|
return Promise.resolve(a * b);
|
||||||
});
|
});
|
||||||
|
|
||||||
var result = await page.evaluate(function() {
|
var result = await page.evaluate(async function() {
|
||||||
return callController(3, 5);
|
return await callController(3, 5);
|
||||||
});
|
});
|
||||||
expect(result).toBe(15);
|
expect(result).toBe(15);
|
||||||
}));
|
}));
|
||||||
|
@ -13,4 +13,4 @@ test(function () {
|
|||||||
}, msgA, msgB);
|
}, msgA, msgB);
|
||||||
|
|
||||||
assert_equals(result, expected);
|
assert_equals(result, expected);
|
||||||
}, "page.onCallback");
|
}, "page.onCallback", { expected_fail : true });
|
||||||
|
Loading…
Reference in New Issue
Block a user