puppeteer-core
Advanced tools
Comparing version
@@ -98,3 +98,3 @@ <!-- gen:toc --> | ||
- `chore` - build-related work, e.g. doclint changes / travis / appveyor. | ||
2. *namespace* is put in parenthesis after label and is optional. | ||
2. *namespace* is put in parenthesis after label and is optional. Must be lowercase. | ||
3. *title* is a brief summary of changes. | ||
@@ -108,3 +108,3 @@ 4. *description* is **optional**, new-line separated from title and is in present tense. | ||
``` | ||
fix(Page): fix page.pizza method | ||
fix(page): fix page.pizza method | ||
@@ -111,0 +111,0 @@ This patch fixes page.pizza so that it works with iframes. |
@@ -271,3 +271,3 @@ /** | ||
/** @type {Object} */ | ||
const options = URL.parse(url); | ||
let options = URL.parse(url); | ||
options.method = method; | ||
@@ -277,8 +277,17 @@ | ||
if (proxyURL) { | ||
/** @type {Object} */ | ||
const parsedProxyURL = URL.parse(proxyURL); | ||
parsedProxyURL.secureProxy = parsedProxyURL.protocol === 'https:'; | ||
if (url.startsWith('http:')) { | ||
const proxy = URL.parse(proxyURL); | ||
options = { | ||
path: options.href, | ||
host: proxy.hostname, | ||
port: proxy.port, | ||
}; | ||
} else { | ||
/** @type {Object} */ | ||
const parsedProxyURL = URL.parse(proxyURL); | ||
parsedProxyURL.secureProxy = parsedProxyURL.protocol === 'https:'; | ||
options.agent = new ProxyAgent(parsedProxyURL); | ||
options.rejectUnauthorized = false; | ||
options.agent = new ProxyAgent(parsedProxyURL); | ||
options.rejectUnauthorized = false; | ||
} | ||
} | ||
@@ -285,0 +294,0 @@ |
@@ -45,15 +45,6 @@ /** | ||
* @param {...*} args | ||
* @return {!Promise<(!Object|undefined)>} | ||
* @return {!Promise<*>} | ||
*/ | ||
async evaluate(pageFunction, ...args) { | ||
const handle = await this.evaluateHandle(pageFunction, ...args); | ||
const result = await handle.jsonValue().catch(error => { | ||
if (error.message.includes('Object reference chain is too long')) | ||
return; | ||
if (error.message.includes('Object couldn\'t be returned by value')) | ||
return; | ||
throw error; | ||
}); | ||
await handle.dispose(); | ||
return result; | ||
return await this._evaluateInternal(true /* returnByValue */, pageFunction, ...args); | ||
} | ||
@@ -67,2 +58,12 @@ | ||
async evaluateHandle(pageFunction, ...args) { | ||
return this._evaluateInternal(false /* returnByValue */, pageFunction, ...args); | ||
} | ||
/** | ||
* @param {boolean} returnByValue | ||
* @param {Function|string} pageFunction | ||
* @param {...*} args | ||
* @return {!Promise<*>} | ||
*/ | ||
async _evaluateInternal(returnByValue, pageFunction, ...args) { | ||
const suffix = `//# sourceURL=${EVALUATION_SCRIPT_URL}`; | ||
@@ -77,3 +78,3 @@ | ||
contextId, | ||
returnByValue: false, | ||
returnByValue, | ||
awaitPromise: true, | ||
@@ -84,3 +85,3 @@ userGesture: true | ||
throw new Error('Evaluation failed: ' + helper.getExceptionMessage(exceptionDetails)); | ||
return createJSHandle(this, remoteObject); | ||
return returnByValue ? helper.valueFromRemoteObject(remoteObject) : createJSHandle(this, remoteObject); | ||
} | ||
@@ -114,3 +115,3 @@ | ||
arguments: args.map(convertArgument.bind(this)), | ||
returnByValue: false, | ||
returnByValue, | ||
awaitPromise: true, | ||
@@ -127,3 +128,3 @@ userGesture: true | ||
throw new Error('Evaluation failed: ' + helper.getExceptionMessage(exceptionDetails)); | ||
return createJSHandle(this, remoteObject); | ||
return returnByValue ? helper.valueFromRemoteObject(remoteObject) : createJSHandle(this, remoteObject); | ||
@@ -166,2 +167,7 @@ /** | ||
function rewriteError(error) { | ||
if (error.message.includes('Object reference chain is too long')) | ||
return {result: {type: 'undefined'}}; | ||
if (error.message.includes('Object couldn\'t be returned by value')) | ||
return {result: {type: 'undefined'}}; | ||
if (error.message.endsWith('Cannot find context with specified id')) | ||
@@ -168,0 +174,0 @@ throw new Error('Execution context was destroyed, most likely because of a navigation.'); |
@@ -17,4 +17,4 @@ /** | ||
const {TimeoutError} = require('./Errors'); | ||
const debugError = require('debug')(`puppeteer:error`); | ||
const fs = require('fs'); | ||
@@ -111,3 +111,4 @@ class Helper { | ||
Reflect.set(classType.prototype, methodName, function(...args) { | ||
const syncStack = new Error(); | ||
const syncStack = {}; | ||
Error.captureStackTrace(syncStack); | ||
return method.call(this, ...args).catch(e => { | ||
@@ -225,4 +226,39 @@ const stack = syncStack.stack.substring(syncStack.stack.indexOf('\n') + 1); | ||
} | ||
/** | ||
* @param {!Puppeteer.CDPSession} client | ||
* @param {string} handle | ||
* @param {?string} path | ||
* @return {!Promise<!Buffer>} | ||
*/ | ||
static async readProtocolStream(client, handle, path) { | ||
let eof = false; | ||
let file; | ||
if (path) | ||
file = await openAsync(path, 'w'); | ||
const bufs = []; | ||
while (!eof) { | ||
const response = await client.send('IO.read', {handle}); | ||
eof = response.eof; | ||
const buf = Buffer.from(response.data, response.base64Encoded ? 'base64' : undefined); | ||
bufs.push(buf); | ||
if (path) | ||
await writeAsync(file, buf); | ||
} | ||
if (path) | ||
await closeAsync(file); | ||
await client.send('IO.close', {handle}); | ||
let resultBuffer = null; | ||
try { | ||
resultBuffer = Buffer.concat(bufs); | ||
} finally { | ||
return resultBuffer; | ||
} | ||
} | ||
} | ||
const openAsync = Helper.promisify(fs.open); | ||
const writeAsync = Helper.promisify(fs.write); | ||
const closeAsync = Helper.promisify(fs.close); | ||
/** | ||
@@ -229,0 +265,0 @@ * @param {*} value |
@@ -227,7 +227,16 @@ /** | ||
const {delay = null} = options; | ||
this.move(x, y); | ||
this.down(options); | ||
if (delay !== null) | ||
if (delay !== null) { | ||
await Promise.all([ | ||
this.move(x, y), | ||
this.down(options), | ||
]); | ||
await new Promise(f => setTimeout(f, delay)); | ||
await this.up(options); | ||
await this.up(options); | ||
} else { | ||
await Promise.all([ | ||
this.move(x, y), | ||
this.down(options), | ||
this.up(options), | ||
]); | ||
} | ||
} | ||
@@ -234,0 +243,0 @@ |
@@ -245,4 +245,2 @@ /** | ||
); | ||
if (os.platform() === 'win32') | ||
chromeArguments.push('--disable-gpu'); | ||
} | ||
@@ -249,0 +247,0 @@ if (args.every(arg => arg.startsWith('-'))) |
@@ -481,2 +481,3 @@ /** | ||
responseCode: response.status || 200, | ||
responsePhrase: STATUS_TEXTS[response.status || 200], | ||
responseHeaders: headersArray(responseHeaders), | ||
@@ -731,2 +732,69 @@ body: responseBody ? responseBody.toString('base64') : undefined, | ||
// List taken from https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml with extra 306 and 418 codes. | ||
const STATUS_TEXTS = { | ||
'100': 'Continue', | ||
'101': 'Switching Protocols', | ||
'102': 'Processing', | ||
'103': 'Early Hints', | ||
'200': 'OK', | ||
'201': 'Created', | ||
'202': 'Accepted', | ||
'203': 'Non-Authoritative Information', | ||
'204': 'No Content', | ||
'205': 'Reset Content', | ||
'206': 'Partial Content', | ||
'207': 'Multi-Status', | ||
'208': 'Already Reported', | ||
'226': 'IM Used', | ||
'300': 'Multiple Choices', | ||
'301': 'Moved Permanently', | ||
'302': 'Found', | ||
'303': 'See Other', | ||
'304': 'Not Modified', | ||
'305': 'Use Proxy', | ||
'306': 'Switch Proxy', | ||
'307': 'Temporary Redirect', | ||
'308': 'Permanent Redirect', | ||
'400': 'Bad Request', | ||
'401': 'Unauthorized', | ||
'402': 'Payment Required', | ||
'403': 'Forbidden', | ||
'404': 'Not Found', | ||
'405': 'Method Not Allowed', | ||
'406': 'Not Acceptable', | ||
'407': 'Proxy Authentication Required', | ||
'408': 'Request Timeout', | ||
'409': 'Conflict', | ||
'410': 'Gone', | ||
'411': 'Length Required', | ||
'412': 'Precondition Failed', | ||
'413': 'Payload Too Large', | ||
'414': 'URI Too Long', | ||
'415': 'Unsupported Media Type', | ||
'416': 'Range Not Satisfiable', | ||
'417': 'Expectation Failed', | ||
'418': 'I\'m a teapot', | ||
'421': 'Misdirected Request', | ||
'422': 'Unprocessable Entity', | ||
'423': 'Locked', | ||
'424': 'Failed Dependency', | ||
'425': 'Too Early', | ||
'426': 'Upgrade Required', | ||
'428': 'Precondition Required', | ||
'429': 'Too Many Requests', | ||
'431': 'Request Header Fields Too Large', | ||
'451': 'Unavailable For Legal Reasons', | ||
'500': 'Internal Server Error', | ||
'501': 'Not Implemented', | ||
'502': 'Bad Gateway', | ||
'503': 'Service Unavailable', | ||
'504': 'Gateway Timeout', | ||
'505': 'HTTP Version Not Supported', | ||
'506': 'Variant Also Negotiates', | ||
'507': 'Insufficient Storage', | ||
'508': 'Loop Detected', | ||
'510': 'Not Extended', | ||
'511': 'Network Authentication Required', | ||
}; | ||
module.exports = {Request, Response, NetworkManager, SecurityDetails}; |
@@ -927,2 +927,3 @@ /** | ||
const result = await this._client.send('Page.printToPDF', { | ||
transferMode: 'ReturnAsStream', | ||
landscape, | ||
@@ -943,6 +944,3 @@ displayHeaderFooter, | ||
}); | ||
const buffer = Buffer.from(result.data, 'base64'); | ||
if (path !== null) | ||
await writeFileAsync(path, buffer); | ||
return buffer; | ||
return await helper.readProtocolStream(this._client, result.stream, path); | ||
} | ||
@@ -1141,4 +1139,4 @@ | ||
a1: {width: 23.4, height: 33.1 }, | ||
a2: {width: 16.5, height: 23.4 }, | ||
a3: {width: 11.7, height: 16.5 }, | ||
a2: {width: 16.54, height: 23.4 }, | ||
a3: {width: 11.7, height: 16.54 }, | ||
a4: {width: 8.27, height: 11.7 }, | ||
@@ -1145,0 +1143,0 @@ a5: {width: 5.83, height: 8.27 }, |
@@ -17,8 +17,3 @@ /** | ||
const {helper, assert} = require('./helper'); | ||
const fs = require('fs'); | ||
const openAsync = helper.promisify(fs.open); | ||
const writeAsync = helper.promisify(fs.write); | ||
const closeAsync = helper.promisify(fs.close); | ||
class Tracing { | ||
@@ -70,3 +65,3 @@ /** | ||
this._client.once('Tracing.tracingComplete', event => { | ||
this._readStream(event.stream, this._path).then(fulfill); | ||
helper.readProtocolStream(this._client, event.stream, this._path).then(fulfill); | ||
}); | ||
@@ -77,32 +72,4 @@ await this._client.send('Tracing.end'); | ||
} | ||
/** | ||
* @param {string} handle | ||
* @param {?string} path | ||
*/ | ||
async _readStream(handle, path) { | ||
let eof = false; | ||
let file; | ||
if (path) | ||
file = await openAsync(path, 'w'); | ||
const bufs = []; | ||
while (!eof) { | ||
const response = await this._client.send('IO.read', {handle}); | ||
eof = response.eof; | ||
bufs.push(Buffer.from(response.data)); | ||
if (path) | ||
await writeAsync(file, response.data); | ||
} | ||
if (path) | ||
await closeAsync(file); | ||
await this._client.send('IO.close', {handle}); | ||
let resultBuffer = null; | ||
try { | ||
resultBuffer = Buffer.concat(bufs); | ||
} finally { | ||
return resultBuffer; | ||
} | ||
} | ||
} | ||
module.exports = Tracing; |
@@ -28,3 +28,6 @@ /** | ||
return new Promise((resolve, reject) => { | ||
const ws = new WebSocket(url, [], { perMessageDeflate: false }); | ||
const ws = new WebSocket(url, [], { | ||
perMessageDeflate: false, | ||
maxPayload: 256 * 1024 * 1024, // 256Mb | ||
}); | ||
ws.addEventListener('open', () => resolve(new WebSocketTransport(ws))); | ||
@@ -31,0 +34,0 @@ ws.addEventListener('error', reject); |
@@ -349,3 +349,3 @@ /** | ||
/** @type {Object} */ | ||
const options = URL.parse(url); | ||
let options = URL.parse(url); | ||
options.method = method; | ||
@@ -355,8 +355,17 @@ | ||
if (proxyURL) { | ||
/** @type {Object} */ | ||
const parsedProxyURL = URL.parse(proxyURL); | ||
parsedProxyURL.secureProxy = parsedProxyURL.protocol === 'https:'; | ||
if (url.startsWith('http:')) { | ||
const proxy = URL.parse(proxyURL); | ||
options = { | ||
path: options.href, | ||
host: proxy.hostname, | ||
port: proxy.port, | ||
}; | ||
} else { | ||
/** @type {Object} */ | ||
const parsedProxyURL = URL.parse(proxyURL); | ||
parsedProxyURL.secureProxy = parsedProxyURL.protocol === 'https:'; | ||
options.agent = new ProxyAgent(parsedProxyURL); | ||
options.rejectUnauthorized = false; | ||
options.agent = new ProxyAgent(parsedProxyURL); | ||
options.rejectUnauthorized = false; | ||
} | ||
} | ||
@@ -363,0 +372,0 @@ |
@@ -45,3 +45,3 @@ /** | ||
* @param {...*} args | ||
* @return {!Promise<(!Object|undefined)>} | ||
* @return {!Promise<*>} | ||
*/ | ||
@@ -75,12 +75,3 @@ /* async */ evaluate(pageFunction, ...args) {return (fn => { | ||
})(function*(){ | ||
const handle = (yield this.evaluateHandle(pageFunction, ...args)); | ||
const result = (yield handle.jsonValue().catch(error => { | ||
if (error.message.includes('Object reference chain is too long')) | ||
return; | ||
if (error.message.includes('Object couldn\'t be returned by value')) | ||
return; | ||
throw error; | ||
})); | ||
(yield handle.dispose()); | ||
return result; | ||
return (yield this._evaluateInternal(true /* returnByValue */, pageFunction, ...args)); | ||
});} | ||
@@ -120,2 +111,38 @@ | ||
})(function*(){ | ||
return this._evaluateInternal(false /* returnByValue */, pageFunction, ...args); | ||
});} | ||
/** | ||
* @param {boolean} returnByValue | ||
* @param {Function|string} pageFunction | ||
* @param {...*} args | ||
* @return {!Promise<*>} | ||
*/ | ||
/* async */ _evaluateInternal(returnByValue, pageFunction, ...args) {return (fn => { | ||
const gen = fn.call(this); | ||
return new Promise((resolve, reject) => { | ||
function step(key, arg) { | ||
let info, value; | ||
try { | ||
info = gen[key](arg); | ||
value = info.value; | ||
} catch (error) { | ||
reject(error); | ||
return; | ||
} | ||
if (info.done) { | ||
resolve(value); | ||
} else { | ||
return Promise.resolve(value).then( | ||
value => { | ||
step('next', value); | ||
}, | ||
err => { | ||
step('throw', err); | ||
}); | ||
} | ||
} | ||
return step('next'); | ||
}); | ||
})(function*(){ | ||
const suffix = `//# sourceURL=${EVALUATION_SCRIPT_URL}`; | ||
@@ -130,3 +157,3 @@ | ||
contextId, | ||
returnByValue: false, | ||
returnByValue, | ||
awaitPromise: true, | ||
@@ -137,3 +164,3 @@ userGesture: true | ||
throw new Error('Evaluation failed: ' + helper.getExceptionMessage(exceptionDetails)); | ||
return createJSHandle(this, remoteObject); | ||
return returnByValue ? helper.valueFromRemoteObject(remoteObject) : createJSHandle(this, remoteObject); | ||
} | ||
@@ -167,3 +194,3 @@ | ||
arguments: args.map(convertArgument.bind(this)), | ||
returnByValue: false, | ||
returnByValue, | ||
awaitPromise: true, | ||
@@ -180,3 +207,3 @@ userGesture: true | ||
throw new Error('Evaluation failed: ' + helper.getExceptionMessage(exceptionDetails)); | ||
return createJSHandle(this, remoteObject); | ||
return returnByValue ? helper.valueFromRemoteObject(remoteObject) : createJSHandle(this, remoteObject); | ||
@@ -219,2 +246,7 @@ /** | ||
function rewriteError(error) { | ||
if (error.message.includes('Object reference chain is too long')) | ||
return {result: {type: 'undefined'}}; | ||
if (error.message.includes('Object couldn\'t be returned by value')) | ||
return {result: {type: 'undefined'}}; | ||
if (error.message.endsWith('Cannot find context with specified id')) | ||
@@ -221,0 +253,0 @@ throw new Error('Execution context was destroyed, most likely because of a navigation.'); |
@@ -17,4 +17,4 @@ /** | ||
const {TimeoutError} = require('./Errors'); | ||
const debugError = require('debug')(`puppeteer:error`); | ||
const fs = require('fs'); | ||
@@ -137,3 +137,4 @@ class Helper { | ||
Reflect.set(classType.prototype, methodName, function(...args) { | ||
const syncStack = new Error(); | ||
const syncStack = {}; | ||
Error.captureStackTrace(syncStack); | ||
return method.call(this, ...args).catch(e => { | ||
@@ -277,4 +278,65 @@ const stack = syncStack.stack.substring(syncStack.stack.indexOf('\n') + 1); | ||
});} | ||
/** | ||
* @param {!Puppeteer.CDPSession} client | ||
* @param {string} handle | ||
* @param {?string} path | ||
* @return {!Promise<!Buffer>} | ||
*/ | ||
static /* async */ readProtocolStream(client, handle, path) {return (fn => { | ||
const gen = fn.call(this); | ||
return new Promise((resolve, reject) => { | ||
function step(key, arg) { | ||
let info, value; | ||
try { | ||
info = gen[key](arg); | ||
value = info.value; | ||
} catch (error) { | ||
reject(error); | ||
return; | ||
} | ||
if (info.done) { | ||
resolve(value); | ||
} else { | ||
return Promise.resolve(value).then( | ||
value => { | ||
step('next', value); | ||
}, | ||
err => { | ||
step('throw', err); | ||
}); | ||
} | ||
} | ||
return step('next'); | ||
}); | ||
})(function*(){ | ||
let eof = false; | ||
let file; | ||
if (path) | ||
file = (yield openAsync(path, 'w')); | ||
const bufs = []; | ||
while (!eof) { | ||
const response = (yield client.send('IO.read', {handle})); | ||
eof = response.eof; | ||
const buf = Buffer.from(response.data, response.base64Encoded ? 'base64' : undefined); | ||
bufs.push(buf); | ||
if (path) | ||
(yield writeAsync(file, buf)); | ||
} | ||
if (path) | ||
(yield closeAsync(file)); | ||
(yield client.send('IO.close', {handle})); | ||
let resultBuffer = null; | ||
try { | ||
resultBuffer = Buffer.concat(bufs); | ||
} finally { | ||
return resultBuffer; | ||
} | ||
});} | ||
} | ||
const openAsync = Helper.promisify(fs.open); | ||
const writeAsync = Helper.promisify(fs.write); | ||
const closeAsync = Helper.promisify(fs.close); | ||
/** | ||
@@ -281,0 +343,0 @@ * @param {*} value |
@@ -409,7 +409,16 @@ /** | ||
const {delay = null} = options; | ||
this.move(x, y); | ||
this.down(options); | ||
if (delay !== null) | ||
if (delay !== null) { | ||
(yield Promise.all([ | ||
this.move(x, y), | ||
this.down(options), | ||
])); | ||
(yield new Promise(f => setTimeout(f, delay))); | ||
(yield this.up(options)); | ||
(yield this.up(options)); | ||
} else { | ||
(yield Promise.all([ | ||
this.move(x, y), | ||
this.down(options), | ||
this.up(options), | ||
])); | ||
} | ||
});} | ||
@@ -416,0 +425,0 @@ |
@@ -271,4 +271,2 @@ /** | ||
); | ||
if (os.platform() === 'win32') | ||
chromeArguments.push('--disable-gpu'); | ||
} | ||
@@ -275,0 +273,0 @@ if (args.every(arg => arg.startsWith('-'))) |
@@ -767,2 +767,3 @@ /** | ||
responseCode: response.status || 200, | ||
responsePhrase: STATUS_TEXTS[response.status || 200], | ||
responseHeaders: headersArray(responseHeaders), | ||
@@ -1121,2 +1122,69 @@ body: responseBody ? responseBody.toString('base64') : undefined, | ||
// List taken from https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml with extra 306 and 418 codes. | ||
const STATUS_TEXTS = { | ||
'100': 'Continue', | ||
'101': 'Switching Protocols', | ||
'102': 'Processing', | ||
'103': 'Early Hints', | ||
'200': 'OK', | ||
'201': 'Created', | ||
'202': 'Accepted', | ||
'203': 'Non-Authoritative Information', | ||
'204': 'No Content', | ||
'205': 'Reset Content', | ||
'206': 'Partial Content', | ||
'207': 'Multi-Status', | ||
'208': 'Already Reported', | ||
'226': 'IM Used', | ||
'300': 'Multiple Choices', | ||
'301': 'Moved Permanently', | ||
'302': 'Found', | ||
'303': 'See Other', | ||
'304': 'Not Modified', | ||
'305': 'Use Proxy', | ||
'306': 'Switch Proxy', | ||
'307': 'Temporary Redirect', | ||
'308': 'Permanent Redirect', | ||
'400': 'Bad Request', | ||
'401': 'Unauthorized', | ||
'402': 'Payment Required', | ||
'403': 'Forbidden', | ||
'404': 'Not Found', | ||
'405': 'Method Not Allowed', | ||
'406': 'Not Acceptable', | ||
'407': 'Proxy Authentication Required', | ||
'408': 'Request Timeout', | ||
'409': 'Conflict', | ||
'410': 'Gone', | ||
'411': 'Length Required', | ||
'412': 'Precondition Failed', | ||
'413': 'Payload Too Large', | ||
'414': 'URI Too Long', | ||
'415': 'Unsupported Media Type', | ||
'416': 'Range Not Satisfiable', | ||
'417': 'Expectation Failed', | ||
'418': 'I\'m a teapot', | ||
'421': 'Misdirected Request', | ||
'422': 'Unprocessable Entity', | ||
'423': 'Locked', | ||
'424': 'Failed Dependency', | ||
'425': 'Too Early', | ||
'426': 'Upgrade Required', | ||
'428': 'Precondition Required', | ||
'429': 'Too Many Requests', | ||
'431': 'Request Header Fields Too Large', | ||
'451': 'Unavailable For Legal Reasons', | ||
'500': 'Internal Server Error', | ||
'501': 'Not Implemented', | ||
'502': 'Bad Gateway', | ||
'503': 'Service Unavailable', | ||
'504': 'Gateway Timeout', | ||
'505': 'HTTP Version Not Supported', | ||
'506': 'Variant Also Negotiates', | ||
'507': 'Insufficient Storage', | ||
'508': 'Loop Detected', | ||
'510': 'Not Extended', | ||
'511': 'Network Authentication Required', | ||
}; | ||
module.exports = {Request, Response, NetworkManager, SecurityDetails}; |
@@ -17,8 +17,3 @@ /** | ||
const {helper, assert} = require('./helper'); | ||
const fs = require('fs'); | ||
const openAsync = helper.promisify(fs.open); | ||
const writeAsync = helper.promisify(fs.write); | ||
const closeAsync = helper.promisify(fs.close); | ||
class Tracing { | ||
@@ -122,3 +117,3 @@ /** | ||
this._client.once('Tracing.tracingComplete', event => { | ||
this._readStream(event.stream, this._path).then(fulfill); | ||
helper.readProtocolStream(this._client, event.stream, this._path).then(fulfill); | ||
}); | ||
@@ -129,58 +124,4 @@ (yield this._client.send('Tracing.end')); | ||
});} | ||
/** | ||
* @param {string} handle | ||
* @param {?string} path | ||
*/ | ||
/* async */ _readStream(handle, path) {return (fn => { | ||
const gen = fn.call(this); | ||
return new Promise((resolve, reject) => { | ||
function step(key, arg) { | ||
let info, value; | ||
try { | ||
info = gen[key](arg); | ||
value = info.value; | ||
} catch (error) { | ||
reject(error); | ||
return; | ||
} | ||
if (info.done) { | ||
resolve(value); | ||
} else { | ||
return Promise.resolve(value).then( | ||
value => { | ||
step('next', value); | ||
}, | ||
err => { | ||
step('throw', err); | ||
}); | ||
} | ||
} | ||
return step('next'); | ||
}); | ||
})(function*(){ | ||
let eof = false; | ||
let file; | ||
if (path) | ||
file = (yield openAsync(path, 'w')); | ||
const bufs = []; | ||
while (!eof) { | ||
const response = (yield this._client.send('IO.read', {handle})); | ||
eof = response.eof; | ||
bufs.push(Buffer.from(response.data)); | ||
if (path) | ||
(yield writeAsync(file, response.data)); | ||
} | ||
if (path) | ||
(yield closeAsync(file)); | ||
(yield this._client.send('IO.close', {handle})); | ||
let resultBuffer = null; | ||
try { | ||
resultBuffer = Buffer.concat(bufs); | ||
} finally { | ||
return resultBuffer; | ||
} | ||
});} | ||
} | ||
module.exports = Tracing; |
@@ -28,3 +28,6 @@ /** | ||
return new Promise((resolve, reject) => { | ||
const ws = new WebSocket(url, [], { perMessageDeflate: false }); | ||
const ws = new WebSocket(url, [], { | ||
perMessageDeflate: false, | ||
maxPayload: 256 * 1024 * 1024, // 256Mb | ||
}); | ||
ws.addEventListener('open', () => resolve(new WebSocketTransport(ws))); | ||
@@ -31,0 +34,0 @@ ws.addEventListener('error', reject); |
{ | ||
"name": "puppeteer-core", | ||
"version": "1.17.0", | ||
"version": "1.18.0", | ||
"description": "A high-level API to control headless Chrome over the DevTools Protocol", | ||
@@ -11,3 +11,3 @@ "main": "index.js", | ||
"puppeteer": { | ||
"chromium_revision": "662092" | ||
"chromium_revision": "669486" | ||
}, | ||
@@ -14,0 +14,0 @@ "scripts": { |
@@ -9,3 +9,3 @@ # Puppeteer | ||
###### [API](https://github.com/GoogleChrome/puppeteer/blob/v1.17.0/docs/api.md) | [FAQ](#faq) | [Contributing](https://github.com/GoogleChrome/puppeteer/blob/master/CONTRIBUTING.md) | [Troubleshooting](https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md) | ||
###### [API](https://github.com/GoogleChrome/puppeteer/blob/v1.18.0/docs/api.md) | [FAQ](#faq) | [Contributing](https://github.com/GoogleChrome/puppeteer/blob/master/CONTRIBUTING.md) | [Troubleshooting](https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md) | ||
@@ -41,3 +41,3 @@ > Puppeteer is a Node library which provides a high-level API to control Chrome or Chromium over the [DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/). Puppeteer runs [headless](https://developers.google.com/web/updates/2017/04/headless-chrome) by default, but can be configured to run full (non-headless) Chrome or Chromium. | ||
Note: When you install Puppeteer, it downloads a recent version of Chromium (~170MB Mac, ~282MB Linux, ~280MB Win) that is guaranteed to work with the API. To skip the download, see [Environment variables](https://github.com/GoogleChrome/puppeteer/blob/v1.17.0/docs/api.md#environment-variables). | ||
Note: When you install Puppeteer, it downloads a recent version of Chromium (~170MB Mac, ~282MB Linux, ~280MB Win) that is guaranteed to work with the API. To skip the download, see [Environment variables](https://github.com/GoogleChrome/puppeteer/blob/v1.18.0/docs/api.md#environment-variables). | ||
@@ -65,3 +65,3 @@ | ||
Puppeteer will be familiar to people using other browser testing frameworks. You create an instance | ||
of `Browser`, open pages, and then manipulate them with [Puppeteer's API](https://github.com/GoogleChrome/puppeteer/blob/v1.17.0/docs/api.md#). | ||
of `Browser`, open pages, and then manipulate them with [Puppeteer's API](https://github.com/GoogleChrome/puppeteer/blob/v1.18.0/docs/api.md#). | ||
@@ -91,3 +91,3 @@ **Example** - navigating to https://example.com and saving a screenshot as *example.png*: | ||
Puppeteer sets an initial page size to 800px x 600px, which defines the screenshot size. The page size can be customized with [`Page.setViewport()`](https://github.com/GoogleChrome/puppeteer/blob/v1.17.0/docs/api.md#pagesetviewportviewport). | ||
Puppeteer sets an initial page size to 800px x 600px, which defines the screenshot size. The page size can be customized with [`Page.setViewport()`](https://github.com/GoogleChrome/puppeteer/blob/v1.18.0/docs/api.md#pagesetviewportviewport). | ||
@@ -117,3 +117,3 @@ **Example** - create a PDF. | ||
See [`Page.pdf()`](https://github.com/GoogleChrome/puppeteer/blob/v1.17.0/docs/api.md#pagepdfoptions) for more information about creating pdfs. | ||
See [`Page.pdf()`](https://github.com/GoogleChrome/puppeteer/blob/v1.18.0/docs/api.md#pagepdfoptions) for more information about creating pdfs. | ||
@@ -153,3 +153,3 @@ **Example** - evaluate script in the context of the page | ||
See [`Page.evaluate()`](https://github.com/GoogleChrome/puppeteer/blob/v1.17.0/docs/api.md#pageevaluatepagefunction-args) for more information on `evaluate` and related methods like `evaluateOnNewDocument` and `exposeFunction`. | ||
See [`Page.evaluate()`](https://github.com/GoogleChrome/puppeteer/blob/v1.18.0/docs/api.md#pageevaluatepagefunction-args) for more information on `evaluate` and related methods like `evaluateOnNewDocument` and `exposeFunction`. | ||
@@ -163,3 +163,3 @@ <!-- [END getstarted] --> | ||
Puppeteer launches Chromium in [headless mode](https://developers.google.com/web/updates/2017/04/headless-chrome). To launch a full version of Chromium, set the ['headless' option](https://github.com/GoogleChrome/puppeteer/blob/v1.17.0/docs/api.md#puppeteerlaunchoptions) when launching a browser: | ||
Puppeteer launches Chromium in [headless mode](https://developers.google.com/web/updates/2017/04/headless-chrome). To launch a full version of Chromium, set the ['headless' option](https://github.com/GoogleChrome/puppeteer/blob/v1.18.0/docs/api.md#puppeteerlaunchoptions) when launching a browser: | ||
@@ -180,3 +180,3 @@ ```js | ||
See [`Puppeteer.launch()`](https://github.com/GoogleChrome/puppeteer/blob/v1.17.0/docs/api.md#puppeteerlaunchoptions) for more information. | ||
See [`Puppeteer.launch()`](https://github.com/GoogleChrome/puppeteer/blob/v1.18.0/docs/api.md#puppeteerlaunchoptions) for more information. | ||
@@ -193,3 +193,3 @@ See [`this article`](https://www.howtogeek.com/202825/what%E2%80%99s-the-difference-between-chromium-and-chrome/) for a description of the differences between Chromium and Chrome. [`This article`](https://chromium.googlesource.com/chromium/src/+/master/docs/chromium_browser_vs_google_chrome.md) describes some differences for Linux users. | ||
- [API Documentation](https://github.com/GoogleChrome/puppeteer/blob/v1.17.0/docs/api.md) | ||
- [API Documentation](https://github.com/GoogleChrome/puppeteer/blob/v1.18.0/docs/api.md) | ||
- [Examples](https://github.com/GoogleChrome/puppeteer/tree/master/examples/) | ||
@@ -384,3 +384,3 @@ - [Community list of Puppeteer resources](https://github.com/transitive-bullshit/awesome-puppeteer) | ||
* Puppeteer is bundled with Chromium--not Chrome--and so by default, it inherits all of [Chromium's media-related limitations](https://www.chromium.org/audio-video). This means that Puppeteer does not support licensed formats such as AAC or H.264. (However, it is possible to force Puppeteer to use a separately-installed version Chrome instead of Chromium via the [`executablePath` option to `puppeteer.launch`](https://github.com/GoogleChrome/puppeteer/blob/v1.17.0/docs/api.md#puppeteerlaunchoptions). You should only use this configuration if you need an official release of Chrome that supports these media formats.) | ||
* Puppeteer is bundled with Chromium--not Chrome--and so by default, it inherits all of [Chromium's media-related limitations](https://www.chromium.org/audio-video). This means that Puppeteer does not support licensed formats such as AAC or H.264. (However, it is possible to force Puppeteer to use a separately-installed version Chrome instead of Chromium via the [`executablePath` option to `puppeteer.launch`](https://github.com/GoogleChrome/puppeteer/blob/v1.18.0/docs/api.md#puppeteerlaunchoptions). You should only use this configuration if you need an official release of Chrome that supports these media formats.) | ||
* Since Puppeteer (in all configurations) controls a desktop version of Chromium/Chrome, features that are only supported by the mobile version of Chrome are not supported. This means that Puppeteer [does not support HTTP Live Streaming (HLS)](https://caniuse.com/#feat=http-live-streaming). | ||
@@ -405,3 +405,3 @@ | ||
- [bugtracker](https://github.com/GoogleChrome/puppeteer/issues) | ||
- [stackoverflow](https://stackoverflow.com/questions/tagged/puppeteer) | ||
- [Stack Overflow](https://stackoverflow.com/questions/tagged/puppeteer) | ||
- [slack channel](https://join.slack.com/t/puppeteer/shared_invite/enQtMzU4MjIyMDA5NTM4LTM1OTdkNDhlM2Y4ZGUzZDdjYjM5ZWZlZGFiZjc4MTkyYTVlYzIzYjU5NDIyNzgyMmFiNDFjN2UzNWU0N2ZhZDc) | ||
@@ -408,0 +408,0 @@ |
Sorry, the diff of this file is too big to display
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
751408
0.86%22546
0.94%