Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

deps: upgrade puppeteer to 21.7.0 #15724

Merged
merged 7 commits into from
Jan 5, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion core/gather/driver/wait-for-condition.js
Original file line number Diff line number Diff line change
Expand Up @@ -540,7 +540,7 @@ function waitForUserToContinue(driver) {
}
/* c8 ignore stop */

driver.defaultSession.setNextProtocolTimeout(2 ** 31 - 1);
driver.defaultSession.setNextProtocolTimeout(Infinity);
return driver.executionContext.evaluate(createInPagePromise, {args: []});
}

Expand Down
23 changes: 20 additions & 3 deletions core/gather/session.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ import {LighthouseError} from '../lib/lh-error.js';

// Controls how long to wait for a response after sending a DevTools protocol command.
const DEFAULT_PROTOCOL_TIMEOUT = 30000;
const PPTR_BUFFER = 50;

/**
* Defined as the max int32 minus the buffer we use for Puppeteer timeouts.
*
* This is ~50 days which is as good as infinity for all practical purposes.
*/
const MAX_TIMEOUT = (2 ** 32 - 1) - PPTR_BUFFER;

Copy link
Collaborator

@connorjclark connorjclark Jan 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(my previous comment still applies here - why the buffer)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it because of test fake timers shenanigans?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Puppeteer timeouts need to fit into an int32. We add PPTR_BUFFER to the timeout later on so this is actually the largest number the user can provide without breaking Puppeteer.

Now that I think about it, we should probably make the condition for using MAX_TIMEOUT to be timeout > MAX_TIMEOUT not Number.isFinite(timeout)

Copy link
Collaborator

@connorjclark connorjclark Jan 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for explaining. those constraints (esp the "we add this number later") should be clarified in a comment. Or, we can just cap to max int just before giving to puppeteer (in which case we could just use infinity here)

currently it's minusing a small magic constant from a number that is a really long time, so it comes off as unnecessary precision (50 days vs 50 days minus a 20th a second...)

/** @typedef {LH.Protocol.StrictEventEmitterClass<LH.CrdpEvents>} CrdpEventMessageEmitter */
const CrdpEventEmitter = /** @type {CrdpEventMessageEmitter} */ (EventEmitter);
Expand Down Expand Up @@ -70,6 +78,8 @@ class ProtocolSession extends CrdpEventEmitter {
* @param {number} ms
*/
setNextProtocolTimeout(ms) {
// Infinity does not work with Puppeteer's timeout system so just use the max timeout instead.
if (!Number.isFinite(ms)) ms = MAX_TIMEOUT;
this._nextProtocolTimeout = ms;
}

Expand All @@ -86,15 +96,22 @@ class ProtocolSession extends CrdpEventEmitter {
/** @type {NodeJS.Timer|undefined} */
let timeout;
const timeoutPromise = new Promise((resolve, reject) => {
if (timeoutMs === Infinity) return;

// eslint-disable-next-line max-len
timeout = setTimeout(reject, timeoutMs, new LighthouseError(LighthouseError.errors.PROTOCOL_TIMEOUT, {
protocolMethod: method,
}));
});

const resultPromise = this._cdpSession.send(method, ...params);
const resultPromise = this._cdpSession.send(method, ...params, {
// Add 50ms to the Puppeteer timeout to ensure the Lighthouse timeout finishes first.
timeout: timeoutMs + PPTR_BUFFER,
}).catch(err => {
// We set up our own protocol timeout system, so we should ignore protocol timeouts emitted by puppeteer.
// https://github.com/GoogleChrome/lighthouse/issues/15510
if (/'protocolTimeout'/.test(err)) return;

throw err;
});
const resultWithTimeoutPromise = Promise.race([resultPromise, timeoutPromise]);

return resultWithTimeoutPromise.finally(() => {
Expand Down
38 changes: 20 additions & 18 deletions core/test/gather/session-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,13 @@ describe('ProtocolSession', () => {
let puppeteerSession;
/** @type {ProtocolSession} */
let session;
let rawSend = fnAny();

beforeEach(() => {
rawSend = fnAny().mockResolvedValue(Promise.resolve());

// @ts-expect-error - Individual mock functions are applied as necessary.
puppeteerSession = new CdpCDPSession({_rawSend: fnAny(), send: fnAny()}, '', 'root');
puppeteerSession = new CdpCDPSession({_rawSend: rawSend}, '', 'root');
session = new ProtocolSession(puppeteerSession);
});

Expand Down Expand Up @@ -127,7 +130,7 @@ describe('ProtocolSession', () => {

const result = await session.sendCommand('Page.navigate', {url: 'foo'});
expect(result).toEqual(123);
expect(send).toHaveBeenCalledWith('Page.navigate', {url: 'foo'});
expect(send).toHaveBeenCalledWith('Page.navigate', {url: 'foo'}, {timeout: 30050});
});

it('times out a request by default', async () => {
Expand Down Expand Up @@ -168,23 +171,16 @@ describe('ProtocolSession', () => {
});
});

it('respects a timeout of infinity', async () => {
const sendPromise = createDecomposedPromise();
puppeteerSession.send = fnAny().mockReturnValue(sendPromise.promise);

session.setNextProtocolTimeout(Infinity);
const resultPromise = makePromiseInspectable(session.sendCommand('Page.navigate', {url: ''}));

await timers.advanceTimersByTime(100_000);
await flushAllTimersAndMicrotasks();

expect(resultPromise).not.toBeDone();

sendPromise.resolve('result');
await flushAllTimersAndMicrotasks();
it('rejects on error from protocol', async () => {
rawSend.mockRejectedValue(new Error('Url is not valid'));
const resultPromise = session.sendCommand('Page.navigate', {url: ''});
await expect(resultPromise).rejects.toThrow('Url is not valid');
});

expect(resultPromise).toBeDone();
expect(await resultPromise).toBe('result');
it('ignores protocol timeouts from puppeteer', async () => {
rawSend.mockRejectedValue(new Error(`Increase 'protocolTimeout'`));
const resultPromise = session.sendCommand('Page.navigate', {url: ''});
await expect(resultPromise).resolves.toBeUndefined();
adamraine marked this conversation as resolved.
Show resolved Hide resolved
});
});

Expand Down Expand Up @@ -216,5 +212,11 @@ describe('ProtocolSession', () => {
expect(session.hasNextProtocolTimeout()).toBe(false);
expect(session.getNextProtocolTimeout()).toBe(DEFAULT_TIMEOUT);
});

it('should handle infinite timeout', () => {
session.setNextProtocolTimeout(Infinity);
expect(session.hasNextProtocolTimeout()).toBe(true);
expect(session.getNextProtocolTimeout()).toBe(4294967245);
});
});
});
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@
"pako": "^2.0.3",
"preact": "^10.7.2",
"pretty-json-stringify": "^0.0.2",
"puppeteer": "^21.5.2",
"puppeteer": "^21.7.0",
"resolve": "^1.22.1",
"rollup": "^2.52.7",
"rollup-plugin-polyfill-node": "^0.12.0",
Expand Down Expand Up @@ -200,7 +200,7 @@
"open": "^8.4.0",
"parse-cache-control": "1.0.1",
"ps-list": "^8.0.0",
"puppeteer-core": "^21.5.2",
"puppeteer-core": "^21.7.0",
"robots-parser": "^3.0.1",
"semver": "^5.3.0",
"speedline-core": "^1.4.3",
Expand Down
50 changes: 25 additions & 25 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1133,10 +1133,10 @@
resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570"
integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=

"@puppeteer/browsers@1.8.0":
version "1.8.0"
resolved "https://registry.yarnpkg.com/@puppeteer/browsers/-/browsers-1.8.0.tgz#fb6ee61de15e7f0e67737aea9f9bab1512dbd7d8"
integrity sha512-TkRHIV6k2D8OlUe8RtG+5jgOF/H98Myx0M6AOafC8DdNVOFiBSFa5cpRDtpm8LXOa9sVwe0+e6Q3FC56X/DZfg==
"@puppeteer/browsers@1.9.1":
version "1.9.1"
resolved "https://registry.yarnpkg.com/@puppeteer/browsers/-/browsers-1.9.1.tgz#384ee8b09786f0e8f62b1925e4c492424cb549ee"
integrity sha512-PuvK6xZzGhKPvlx3fpfdM2kYY3P/hB1URtK8wA7XUJ6prn6pp22zvJHu48th0SGcHL9SutbPHrFuQgfXTFobWA==
dependencies:
debug "4.3.4"
extract-zip "2.0.1"
Expand Down Expand Up @@ -2328,10 +2328,10 @@ chrome-launcher@^1.1.0:
is-wsl "^2.2.0"
lighthouse-logger "^2.0.1"

chromium-bidi@0.4.33:
version "0.4.33"
resolved "https://registry.yarnpkg.com/chromium-bidi/-/chromium-bidi-0.4.33.tgz#9a9aba5a5b07118c8e7d6405f8ee79f47418dd1d"
integrity sha512-IxoFM5WGQOIAd95qrSXzJUv4eXIrh+RvU3rwwqIiwYuvfE7U/Llj4fejbsJnjJMUYCuGtVQsY2gv7oGl4aTNSQ==
chromium-bidi@0.5.2:
version "0.5.2"
resolved "https://registry.yarnpkg.com/chromium-bidi/-/chromium-bidi-0.5.2.tgz#358b03bb7c53e0f8d0fd77d596ea67ee30f7ff06"
integrity sha512-PbVOSddxgKyj+JByqavWMNqWPCoCaT6XK5Z1EFe168sxnB/BM51LnZEPXSbFcFAJv/+u2B4XNTs9uXxy4GW3cQ==
dependencies:
mitt "3.0.1"
urlpattern-polyfill "9.0.0"
Expand Down Expand Up @@ -6023,26 +6023,26 @@ punycode@^2.1.0, punycode@^2.1.1:
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==

puppeteer-core@21.5.2, puppeteer-core@^21.5.2:
version "21.5.2"
resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-21.5.2.tgz#6d3de4efb2ae65f1ee072043787b75594e88035f"
integrity sha512-v4T0cWnujSKs+iEfmb8ccd7u4/x8oblEyKqplqKnJ582Kw8PewYAWvkH4qUWhitN3O2q9RF7dzkvjyK5HbzjLA==
puppeteer-core@21.7.0, puppeteer-core@^21.7.0:
version "21.7.0"
resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-21.7.0.tgz#c0abb98cbd17dbd7ee317b4257958337fa25d2c7"
integrity sha512-elPYPozrgiM3phSy7VDUJCVWQ07SPnOm78fpSaaSNFoQx5sur/MqhTSro9Wz8lOEjqCykGC6WRkwxDgmqcy1dQ==
dependencies:
"@puppeteer/browsers" "1.8.0"
chromium-bidi "0.4.33"
"@puppeteer/browsers" "1.9.1"
chromium-bidi "0.5.2"
cross-fetch "4.0.0"
debug "4.3.4"
devtools-protocol "0.0.1203626"
ws "8.14.2"
ws "8.16.0"

puppeteer@^21.5.2:
version "21.5.2"
resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-21.5.2.tgz#0a4a72175c0fd0944d6486f4734807e1671d527b"
integrity sha512-BaAGJOq8Fl6/cck6obmwaNLksuY0Bg/lIahCLhJPGXBFUD2mCffypa4A592MaWnDcye7eaHmSK9yot0pxctY8A==
puppeteer@^21.7.0:
version "21.7.0"
resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-21.7.0.tgz#c4b46ef28a2986f9c536eb086ab47c8dea80e4f9"
integrity sha512-Yy+UUy0b9siJezbhHO/heYUoZQUwyqDK1yOQgblTt0l97tspvDVFkcW9toBlnSvSfkDmMI3Dx9cZL6R8bDArHA==
dependencies:
"@puppeteer/browsers" "1.8.0"
"@puppeteer/browsers" "1.9.1"
cosmiconfig "8.3.6"
puppeteer-core "21.5.2"
puppeteer-core "21.7.0"

q@^1.5.1:
version "1.5.1"
Expand Down Expand Up @@ -7427,10 +7427,10 @@ write-file-atomic@^4.0.1:
imurmurhash "^0.1.4"
signal-exit "^3.0.7"

ws@8.14.2:
version "8.14.2"
resolved "https://registry.yarnpkg.com/ws/-/ws-8.14.2.tgz#6c249a806eb2db7a20d26d51e7709eab7b2e6c7f"
integrity sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==
ws@8.16.0:
version "8.16.0"
resolved "https://registry.yarnpkg.com/ws/-/ws-8.16.0.tgz#d1cd774f36fbc07165066a60e40323eab6446fd4"
integrity sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==

ws@>=7.4.6:
version "8.13.0"
Expand Down
Loading