Skip to content

Commit

Permalink
core(driver): fix protocol timeout being ignored for isolated eval (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
connorjclark authored Feb 26, 2024
1 parent 54e843a commit 034c0a1
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 9 deletions.
18 changes: 9 additions & 9 deletions core/gather/driver/execution-context.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,15 +80,10 @@ class ExecutionContext {
* page without isolation.
* @param {string} expression
* @param {number|undefined} contextId
* @param {number} timeout
* @return {Promise<*>}
*/
async _evaluateInContext(expression, contextId) {
// Use a higher than default timeout if the user hasn't specified a specific timeout.
// Otherwise, use whatever was requested.
const timeout = this._session.hasNextProtocolTimeout() ?
this._session.getNextProtocolTimeout() :
60000;

async _evaluateInContext(expression, contextId, timeout) {
// `__lighthouseExecutionContextUniqueIdentifier` is only used by the FullPageScreenshot gatherer.
// See `getNodeDetails` in page-functions.
const uniqueExecutionContextIdentifier = contextId === undefined ?
Expand Down Expand Up @@ -166,17 +161,22 @@ class ExecutionContext {
* @return {Promise<*>}
*/
async evaluateAsync(expression, options = {}) {
// Use a higher than default timeout if the user hasn't specified a specific timeout.
// Otherwise, use whatever was requested.
const timeout = this._session.hasNextProtocolTimeout() ?
this._session.getNextProtocolTimeout() :
60000;
const contextId = options.useIsolation ? await this._getOrCreateIsolatedContextId() : undefined;

try {
// `await` is not redundant here because we want to `catch` the async errors
return await this._evaluateInContext(expression, contextId);
return await this._evaluateInContext(expression, contextId, timeout);
} catch (err) {
// If we were using isolation and the context disappeared on us, retry one more time.
if (contextId && err.message.includes('Cannot find context')) {
this.clearContextId();
const freshContextId = await this._getOrCreateIsolatedContextId();
return this._evaluateInContext(expression, freshContextId);
return this._evaluateInContext(expression, freshContextId, timeout);
}

throw err;
Expand Down
21 changes: 21 additions & 0 deletions core/test/gather/driver/execution-context-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,27 @@ describe('.evaluateAsync', () => {
await expect(evaluatePromise).rejects.toBeTruthy();
});

it('uses the specific timeout given (isolation)', async () => {
const expectedTimeout = 5000;
const setNextProtocolTimeout = sessionMock.setNextProtocolTimeout = fnAny();
sessionMock.hasNextProtocolTimeout = fnAny().mockReturnValue(true);
sessionMock.getNextProtocolTimeout = fnAny().mockReturnValue(expectedTimeout);
sessionMock.sendCommand
.mockResponse('Page.enable')
.mockResponse('Runtime.enable')
.mockResponse('Page.getFrameTree', {frameTree: {frame: {id: '1337'}}})
.mockResponse('Page.createIsolatedWorld', {executionContextId: 1});

const evaluatePromise = makePromiseInspectable(executionContext.evaluateAsync('1 + 1', {
useIsolation: true,
}));

await flushAllTimersAndMicrotasks();
expect(setNextProtocolTimeout).toHaveBeenCalledWith(expectedTimeout);
expect(evaluatePromise).toBeDone();
await expect(evaluatePromise).rejects.toBeTruthy();
});

it('evaluates an expression in isolation', async () => {
sessionMock.sendCommand
.mockResponse('Page.enable')
Expand Down

0 comments on commit 034c0a1

Please sign in to comment.