|
const { app, BrowserWindow, crashReporter } = require('electron'); |
|
|
|
const FAIL_COUNT = 100; |
|
const WAVE_COUNT = 10; |
|
const WAVE_GAP_MS = 100; |
|
const CLOSED_PORT = 59999; |
|
|
|
crashReporter.start({ |
|
productName: 'electron-fetch-crash-repro', |
|
companyName: 'repro', |
|
submitURL: '', |
|
uploadToServer: false, |
|
}); |
|
|
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); |
|
|
|
app.whenReady().then(async () => { |
|
console.log('ready pid=', process.pid); |
|
const win = new BrowserWindow({ |
|
width: 800, height: 600, show: true, |
|
webPreferences: { nodeIntegration: false, contextIsolation: true }, |
|
}); |
|
const wc = win.webContents; |
|
await wc.loadURL('about:blank'); |
|
|
|
const dbg = wc.debugger; |
|
dbg.attach('1.3'); |
|
let paused = 0, continued = 0; |
|
dbg.on('message', async (_e, method, params) => { |
|
if (method !== 'Fetch.requestPaused') return; |
|
paused++; |
|
const { requestId } = params; |
|
try { |
|
try { await dbg.sendCommand('Fetch.getResponseBody', { requestId }); } catch (_) {} |
|
await dbg.sendCommand('Fetch.continueResponse', { requestId }); |
|
continued++; |
|
} catch (_) { |
|
try { await dbg.sendCommand('Fetch.continueRequest', { requestId }); continued++; } catch (_) {} |
|
} |
|
}); |
|
|
|
await dbg.sendCommand('Network.enable'); |
|
await dbg.sendCommand('Fetch.enable', { |
|
patterns: [ |
|
{ requestStage: 'Response', resourceType: 'Fetch' }, |
|
{ requestStage: 'Response', resourceType: 'XHR' }, |
|
{ requestStage: 'Response' }, |
|
], |
|
}); |
|
console.log('Fetch.enable active'); |
|
|
|
// POST with body → RequestBodyCollector path (matches crash stack) |
|
const html = `<!doctype html><body>go</body><script> |
|
(async () => { |
|
const body = new Uint8Array(64 * 1024); // 64KiB |
|
for (let i = 0; i < body.length; i++) body[i] = i & 255; |
|
for (let w = 0; w < ${WAVE_COUNT}; w++) { |
|
await Promise.allSettled(Array.from({length:${FAIL_COUNT}}, (_, i) => |
|
fetch('http://127.0.0.1:${CLOSED_PORT}/w'+w+'-'+i, { |
|
method: 'POST', |
|
headers: { 'content-type': 'application/octet-stream' }, |
|
body, |
|
}).catch(() => null) |
|
)); |
|
document.body.textContent = 'wave '+(w+1); |
|
await new Promise(r => setTimeout(r, ${WAVE_GAP_MS})); |
|
} |
|
document.body.textContent = 'done-no-crash'; |
|
})(); |
|
</script>`; |
|
|
|
await wc.loadURL('data:text/html;charset=utf-8,' + encodeURIComponent(html)); |
|
console.log('fail page loaded (POST bodies)'); |
|
await sleep(WAVE_COUNT * WAVE_GAP_MS + 25000); |
|
console.log('STILL_ALIVE paused=', paused, 'continued=', continued); |
|
app.exit(2); |
|
}); |