Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,10 @@ export class Tracing extends SdkObject implements InstrumentationListener, Snaps
if (this._snapshotter?.started()) {
// Node references are only reset by the first snapshot of the action.
const resetTargets = phase === 'before';
await this._snapshotter?.captureSnapshot(page, progress.metadata.id, phase, resetTargets).catch(() => {});
try {
await progress.race(this._snapshotter.captureSnapshot(page, progress.metadata.id, phase, resetTargets));
} catch {
}
}

const options = this._state?.options;
Expand Down
5 changes: 3 additions & 2 deletions packages/trace-viewer/src/ui/workbench.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ const PartitionedWorkbench: React.FunctionComponent<WorkbenchProps & { partition
}, [model]);

const playback = usePlayback(actions || [], selectedAction, onActionSelected, selectedTime, boundaries);
const { showSelectedAction } = playback;

const selectPropertiesTab = React.useCallback((tab: string) => {
setSelectedPropertiesTab(tab);
Expand All @@ -180,9 +181,9 @@ const PartitionedWorkbench: React.FunctionComponent<WorkbenchProps & { partition
selectPropertiesTab('inspector');
// Inspecting works against the DOM snapshot, not the screencast frame.
if (value)
playback.showSelectedAction();
showSelectedAction();
setIsInspectingState(value);
}, [setIsInspectingState, selectPropertiesTab, isInspecting, playback.showSelectedAction]);
}, [setIsInspectingState, selectPropertiesTab, isInspecting, showSelectedAction]);

const elementPicked = React.useCallback((element: HighlightedElement) => {
setHighlightedElement(element);
Expand Down
17 changes: 17 additions & 0 deletions tests/library/tracing.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,23 @@ test('should not crash when browser closes mid-trace', async ({ browserType, ser
await new Promise(f => setTimeout(f, 1000)); // Give it some time to throw errors
});

test('should not hang when page is unresponsive', async ({ browserType, server }) => {
test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/42903' });
const browser = await browserType.launch();
const page = await browser.newPage();
await page.context().tracing.start({ snapshots: true });
await page.goto(server.EMPTY_PAGE);
await page.evaluate(() => {
setTimeout(() => {
while (true) {}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nothing works on these pages, this test and change do not make sense.

}, 0);
});
// All bets are off with a tight loop in the page, but an explicit timeout should still fire.
const error = await page.goto(server.EMPTY_PAGE, { timeout: 1000 }).catch(e => e);
expect(error.message).toContain('Timeout 1000ms exceeded');
await browser.close();
});

test('should survive browser.close with auto-created traces dir', async ({ browserType }, testInfo) => {
const oldTracesDir = (browserType as any)._playwright._defaultTracesDir;
(browserType as any)._playwright._defaultTracesDir = undefined;
Expand Down
11 changes: 10 additions & 1 deletion utils/eslint-plugin-progress/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

// @ts-check

const crypto = require('crypto');
const fs = require('fs');
const { ESLintUtils } = require('@typescript-eslint/utils');

const createRule = ESLintUtils.RuleCreator(name => name);
Expand Down Expand Up @@ -156,7 +158,9 @@ const rule = createRule({
if (!isInProgressFunction())
return;

const awaited = node.argument;
let awaited = node.argument;
if (awaited.type === 'ChainExpression')
awaited = awaited.expression;

// await progress.anything(...) is always fine — calls on the progress object itself.
if (awaited.type === 'CallExpression' &&
Expand Down Expand Up @@ -195,6 +199,11 @@ const rule = createRule({
});

module.exports = {
meta: {
name: 'eslint-plugin-progress',
// ESLint cache key includes plugin version, so edits to this file invalidate cached results.
version: crypto.createHash('sha1').update(fs.readFileSync(__filename)).digest('hex'),
},
rules: {
'await-must-use-progress': rule,
},
Expand Down
Loading