// Native shell stress for a wayBetter app through WebView2 CDP. Run only against an app started with // WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS=--remote-debugging-port=. // Opens 24 shell start tabs, measures responsiveness, then closes those tabs. const port = process.argv[2] ?? '9344'; const count = Number(process.argv[3] ?? 24); const list = await (await fetch(`http://127.0.0.1:${port}/json/list`)).json(); const target = list.find(item => item.type === 'page' && item.url.startsWith('http://tauri.localhost/')); if (!target) throw new Error('Shell CDP target not found'); const socket = new WebSocket(target.webSocketDebuggerUrl); const ready = new Promise(resolve => { socket.onopen = resolve; }); const pending = new Map(); let serial = 0; socket.onmessage = event => { const message = JSON.parse(event.data); if (message.id) { pending.get(message.id)?.(message); pending.delete(message.id); } }; await ready; const send = (method, params = {}) => new Promise(resolve => { const id = ++serial; pending.set(id, resolve); socket.send(JSON.stringify({ id, method, params })); }); const evaluate = async expression => { let timeout; const result = await Promise.race([ send('Runtime.evaluate', { expression, awaitPromise: true, returnByValue: true }), new Promise((_, reject) => { timeout = setTimeout(() => reject(new Error('Shell unresponsive for 20 s')), 20_000); }), ]).finally(() => clearTimeout(timeout)); if (result.result?.exceptionDetails) throw new Error(JSON.stringify(result.result.exceptionDetails)); return result.result?.result?.value; }; const expression = `\n(async () => { const count = ${count}; const before = document.querySelectorAll('.dv-tab').length; const delays = []; const longTasks = []; const observer = new PerformanceObserver(list => { for (const entry of list.getEntries()) longTasks.push(entry.duration); }); observer.observe({ entryTypes: ['longtask'] }); let expected = performance.now() + 50; const interval = setInterval(() => { const now = performance.now(); delays.push(Math.max(0, now - expected)); expected = now + 50; }, 50); const key = key => window.dispatchEvent(new KeyboardEvent('keydown', { key, ctrlKey: true, bubbles: true })); const start = performance.now(); for (let i = 0; i < count; i++) key('t'); const dispatchMs = performance.now() - start; await new Promise(resolve => setTimeout(resolve, 1500)); const opened = document.querySelectorAll('.dv-tab').length; for (let i = 0; i < count; i++) key('w'); await new Promise(resolve => setTimeout(resolve, 300)); clearInterval(interval); observer.disconnect(); return { before, opened, afterCleanup: document.querySelectorAll('.dv-tab').length, dispatchMs: Math.round(dispatchMs), maxDelayMs: Math.round(Math.max(0, ...delays)), maxLongTaskMs: Math.round(Math.max(0, ...longTasks)), }; })()`; try { const result = await evaluate(expression); console.log(JSON.stringify(result, null, 2)); if (result.opened !== result.before + count || result.afterCleanup !== result.before) process.exitCode = 1; } finally { socket.close(); }