Rename Page.setInPageCallback into Page.addBinding (#236)
This seems to be a much better name which is actually used for a similar purposes in chromium/v8.
This commit is contained in:
parent
25465525c1
commit
6347a049ba
88
docs/api.md
88
docs/api.md
@ -25,6 +25,7 @@
|
||||
+ [event: 'requestfailed'](#event-requestfailed)
|
||||
+ [event: 'requestfinished'](#event-requestfinished)
|
||||
+ [event: 'response'](#event-response)
|
||||
+ [page.addBinding(name, puppeteerFunction)](#pageaddbindingname-puppeteerfunction)
|
||||
+ [page.addScriptTag(url)](#pageaddscripttagurl)
|
||||
+ [page.click(selector[, options])](#pageclickselector-options)
|
||||
+ [page.close()](#pageclose)
|
||||
@ -48,7 +49,6 @@
|
||||
+ [page.screenshot([options])](#pagescreenshotoptions)
|
||||
+ [page.setContent(html)](#pagesetcontenthtml)
|
||||
+ [page.setExtraHTTPHeaders(headers)](#pagesetextrahttpheadersheaders)
|
||||
+ [page.setInPageCallback(name, callback)](#pagesetinpagecallbackname-callback)
|
||||
+ [page.setRequestInterceptor(interceptor)](#pagesetrequestinterceptorinterceptor)
|
||||
+ [page.setUserAgent(userAgent)](#pagesetuseragentuseragent)
|
||||
+ [page.setViewport(viewport)](#pagesetviewportviewport)
|
||||
@ -313,6 +313,69 @@ Emitted when a request is successfully finished.
|
||||
|
||||
Emitted when a [response] is received.
|
||||
|
||||
|
||||
#### page.addBinding(name, puppeteerFunction)
|
||||
- `name` <[string]> Name of the binding on window object
|
||||
- `puppeteerFunction` <[function]> Callback function which will be called in puppeteer's context.
|
||||
- returns: <[Promise]> Promise which resolves with the result of `puppeteerFunction`.
|
||||
|
||||
The method adds a function called `name` on `window` object.
|
||||
When called, the function executes `puppeteerFunction` function in puppeteer context and returns
|
||||
a promise that resolves with the puppeteer's result.
|
||||
|
||||
If the `puppeteerFunction` returns a promise, it would be awaited.
|
||||
|
||||
> **NOTE** All the bindings installed via the `page.addBinding` survive navigations.
|
||||
|
||||
An example of adding `window.md5` binding to the page:
|
||||
```js
|
||||
const {Browser} = require('puppeteer');
|
||||
const browser = new Browser();
|
||||
const crypto = require('crypto');
|
||||
|
||||
browser.newPage().then(async page => {
|
||||
page.on('console', console.log);
|
||||
await page.setInPageCallback('md5', text => crypto.createHash('md5').update(text).digest('hex'));
|
||||
await page.evaluate(async () => {
|
||||
// use window.md5 to compute hashes
|
||||
let myString = 'PUPPETEER';
|
||||
let myHash = await window.md5(myString);
|
||||
console.log(`md5 of ${myString} is ${myHash}`);
|
||||
});
|
||||
browser.close();
|
||||
});
|
||||
```
|
||||
|
||||
An example of adding `window.readfile` binding to the page:
|
||||
|
||||
```js
|
||||
const {Browser} = require('puppeteer');
|
||||
const browser = new Browser();
|
||||
const fs = require('fs');
|
||||
|
||||
browser.newPage().then(async page => {
|
||||
page.on('console', console.log);
|
||||
await page.setInPageCallback('readfile', async filePath => {
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.readFile(filePath, 'utf8', (err, text) => {
|
||||
if (err)
|
||||
reject(err);
|
||||
else
|
||||
resolve(text);
|
||||
});
|
||||
});
|
||||
});
|
||||
await page.evaluate(async () => {
|
||||
// use window.readfile to read contents of a file
|
||||
let content = await window.readfile('/etc/hosts');
|
||||
console.log(content);
|
||||
});
|
||||
browser.close();
|
||||
});
|
||||
|
||||
```
|
||||
|
||||
|
||||
#### page.addScriptTag(url)
|
||||
- `url` <[string]> Url of a script to be added
|
||||
- returns: <[Promise]> Promise which resolves as the script gets added and loads.
|
||||
@ -554,27 +617,6 @@ The extra HTTP headers will be sent with every request the page initiates.
|
||||
> **NOTE** page.setExtraHTTPHeaders does not guarantee the order of headers in the outgoing requests.
|
||||
|
||||
|
||||
#### page.setInPageCallback(name, callback)
|
||||
- `name` <[string]> Name of the callback to be assigned on window object
|
||||
- `callback` <[function]> Callback function which will be called in puppeteer's context.
|
||||
- returns: <[Promise]> Promise which resolves when callback is successfully initialized
|
||||
|
||||
The in-page callback allows page to asynchronously reach back to the Puppeteer.
|
||||
An example of a page showing amount of CPU's:
|
||||
```js
|
||||
const os = require('os');
|
||||
const {Browser} = require('puppeteer');
|
||||
const browser = new Browser();
|
||||
|
||||
browser.newPage().then(async page =>
|
||||
await page.setInPageCallback('getCPUCount', () => os.cpus().length);
|
||||
await page.evaluate(async () => {
|
||||
alert(await window.getCPUCount());
|
||||
});
|
||||
browser.close();
|
||||
});
|
||||
```
|
||||
|
||||
#### page.setRequestInterceptor(interceptor)
|
||||
- `interceptor` <[function]> Callback function which accepts a single argument of type <[InterceptedRequest]>.
|
||||
- returns: <[Promise]> Promise which resolves when request interceptor is successfully installed on the page.
|
||||
@ -966,7 +1008,7 @@ Returns frame's name attribute as specified in the tag.
|
||||
|
||||
If the name is empty, returns the id attribute instead.
|
||||
|
||||
Note: This value is calculated once when the frame is created, and will not update if the attribute is changed later.
|
||||
> **NOTE** This value is calculated once when the frame is created, and will not update if the attribute is changed later.
|
||||
|
||||
#### frame.parentFrame()
|
||||
- returns: <[Frame]> Returns parent frame, if any. Detached frames and main frames return `null`.
|
||||
|
26
lib/Page.js
26
lib/Page.js
@ -65,7 +65,7 @@ class Page extends EventEmitter {
|
||||
this._emulationManager = new EmulationManager(client);
|
||||
this._tracing = new Tracing(client);
|
||||
/** @type {!Map<string, function>} */
|
||||
this._inPageCallbacks = new Map();
|
||||
this._pageBindings = new Map();
|
||||
this._ignoreHTTPSErrors = ignoreHTTPSErrors;
|
||||
|
||||
this._screenshotTaskQueue = screenshotTaskQueue;
|
||||
@ -152,20 +152,20 @@ class Page extends EventEmitter {
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
* @param {function(?)} callback
|
||||
* @param {function(?)} puppeteerFunction
|
||||
*/
|
||||
async setInPageCallback(name, callback) {
|
||||
if (this._inPageCallbacks[name])
|
||||
throw new Error(`Failed to set in-page callback with name ${name}: window['${name}'] already exists!`);
|
||||
this._inPageCallbacks[name] = callback;
|
||||
async addBinding(name, puppeteerFunction) {
|
||||
if (this._pageBindings[name])
|
||||
throw new Error(`Failed to add page binding with name ${name}: window['${name}'] already exists!`);
|
||||
this._pageBindings[name] = puppeteerFunction;
|
||||
|
||||
let expression = helper.evaluationString(inPageCallback, name);
|
||||
let expression = helper.evaluationString(addPageBinding, name);
|
||||
await this._client.send('Page.addScriptToEvaluateOnNewDocument', { source: expression });
|
||||
await this._client.send('Runtime.evaluate', { expression, returnByValue: true });
|
||||
|
||||
function inPageCallback(callbackName) {
|
||||
window[callbackName] = async(...args) => {
|
||||
const me = window[callbackName];
|
||||
function addPageBinding(bindingName) {
|
||||
window[bindingName] = async(...args) => {
|
||||
const me = window[bindingName];
|
||||
let callbacks = me['callbacks'];
|
||||
if (!callbacks) {
|
||||
callbacks = new Map();
|
||||
@ -175,7 +175,7 @@ class Page extends EventEmitter {
|
||||
me['lastSeq'] = seq;
|
||||
const promise = new Promise(fulfill => callbacks.set(seq, fulfill));
|
||||
// eslint-disable-next-line no-console
|
||||
console.debug('driver:InPageCallback', JSON.stringify({name: callbackName, seq, args}));
|
||||
console.debug('driver:page-binding', JSON.stringify({name: bindingName, seq, args}));
|
||||
return promise;
|
||||
};
|
||||
}
|
||||
@ -206,9 +206,9 @@ class Page extends EventEmitter {
|
||||
}
|
||||
|
||||
async _onConsoleAPI(event) {
|
||||
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:page-binding') {
|
||||
let {name, seq, args} = JSON.parse(event.args[1].value);
|
||||
let result = await this._inPageCallbacks[name](...args);
|
||||
let result = await this._pageBindings[name](...args);
|
||||
let expression = helper.evaluationString(deliverResult, name, seq, result);
|
||||
this._client.send('Runtime.evaluate', { expression });
|
||||
|
||||
|
16
test/test.js
16
test/test.js
@ -166,7 +166,7 @@ describe('Page', function() {
|
||||
}));
|
||||
it('should work from-inside inPageCallback', SX(async function() {
|
||||
// Setup inpage callback, which calls Page.evaluate
|
||||
await page.setInPageCallback('callController', async function(a, b) {
|
||||
await page.addBinding('callController', async function(a, b) {
|
||||
return await page.evaluate((a, b) => a * b, a, b);
|
||||
});
|
||||
let result = await page.evaluate(async function() {
|
||||
@ -713,34 +713,34 @@ describe('Page', function() {
|
||||
}));
|
||||
});
|
||||
|
||||
describe('Page.setInPageCallback', function() {
|
||||
describe('Page.addBinding', function() {
|
||||
it('should work', SX(async function() {
|
||||
await page.setInPageCallback('callController', function(a, b) {
|
||||
await page.addBinding('compute', function(a, b) {
|
||||
return a * b;
|
||||
});
|
||||
let result = await page.evaluate(async function() {
|
||||
return await callController(9, 4);
|
||||
return await compute(9, 4);
|
||||
});
|
||||
expect(result).toBe(36);
|
||||
}));
|
||||
it('should survive navigation', SX(async function() {
|
||||
await page.setInPageCallback('callController', function(a, b) {
|
||||
await page.addBinding('compute', function(a, b) {
|
||||
return a * b;
|
||||
});
|
||||
|
||||
await page.goto(EMPTY_PAGE);
|
||||
let result = await page.evaluate(async function() {
|
||||
return await callController(9, 4);
|
||||
return await compute(9, 4);
|
||||
});
|
||||
expect(result).toBe(36);
|
||||
}));
|
||||
it('should await returned promise', SX(async function() {
|
||||
await page.setInPageCallback('callController', function(a, b) {
|
||||
await page.addBinding('compute', function(a, b) {
|
||||
return Promise.resolve(a * b);
|
||||
});
|
||||
|
||||
let result = await page.evaluate(async function() {
|
||||
return await callController(3, 5);
|
||||
return await compute(3, 5);
|
||||
});
|
||||
expect(result).toBe(15);
|
||||
}));
|
||||
|
Loading…
Reference in New Issue
Block a user