Skip to content
Open
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
3 changes: 1 addition & 2 deletions src/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2442,8 +2442,7 @@ async function handleWaitForDownload(
command: WaitForDownloadCommand,
browser: BrowserManager
): Promise<Response> {
const page = browser.getPage();
const download = await page.waitForEvent('download', { timeout: command.timeout });
const download = await browser.waitForDownload(command.timeout);

let filePath: string;
if (command.path) {
Expand Down
19 changes: 19 additions & 0 deletions src/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
type Frame,
type Dialog,
type Request,
type Download,
type Route,
type Locator,
type CDPSession,
Expand Down Expand Up @@ -118,6 +119,7 @@ export class BrowserManager {
private scopedHeaderRoutes: Map<string, (route: Route) => Promise<void>> = new Map();
private colorScheme: 'light' | 'dark' | 'no-preference' | null = null;
private downloadPath: string | null = null;
private pendingDownloads: Download[] = [];
private allowedDomains: string[] = [];

/**
Expand Down Expand Up @@ -478,6 +480,18 @@ export class BrowserManager {
this.trackedRequests = [];
}

/**
* Take a pending download from the queue, or wait for the next one.
*/
async waitForDownload(timeout?: number): Promise<Download> {
if (this.pendingDownloads.length > 0) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Race condition causes the same download event to be both returned from waitForDownload() and left in the pendingDownloads queue, leading to duplicate processing on subsequent calls.

Fix on Vercel

return this.pendingDownloads.shift()!;
}
const page = this.getPage();
const download = await page.waitForEvent('download', { timeout });
return download;
}

/**
* Add a route to intercept requests
*/
Expand Down Expand Up @@ -1736,6 +1750,11 @@ export class BrowserManager {
});
});

// Track downloads eagerly so wait --download works even after the event fired
page.on('download', (download: Download) => {
this.pendingDownloads.push(download);
});

page.on('close', () => {
const index = this.pages.indexOf(page);
if (index !== -1) {
Expand Down