Spaces:
Sleeping
Sleeping
| // Drive the bench_fluidity.html harness in a headed Chrome via the DevTools | |
| // Protocol (Node 22 global WebSocket + fetch — no npm deps). Chrome must be | |
| // running with --remote-debugging-port=9333 and the no-throttle flags so the | |
| // page keeps rendering at full GPU speed even while occluded. | |
| const PORT = process.env.CDP_PORT || 9333; | |
| const URLMATCH = 'bench_fluidity.html'; | |
| const DURATION = +(process.env.DUR || 2500); | |
| const REPS = +(process.env.REPS || 3); | |
| const sleep = (ms) => new Promise(r => setTimeout(r, ms)); | |
| async function findTarget() { | |
| const wantAny = !!process.env.NAV || process.env.ANYPAGE === '1'; | |
| for (let i = 0; i < 60; i++) { | |
| try { | |
| const list = await (await fetch(`http://127.0.0.1:${PORT}/json/list`)).json(); | |
| const t = wantAny | |
| ? list.find(x => x.type === 'page' && /^https?:|^about:|chrome:\/\/newtab/.test(x.url)) | |
| : list.find(x => x.type === 'page' && x.url.includes(URLMATCH)); | |
| if (t && t.webSocketDebuggerUrl) return t; | |
| } catch { /* port not up yet */ } | |
| await sleep(500); | |
| } | |
| throw new Error('no page target found (wantAny=' + wantAny + ')'); | |
| } | |
| function connect(wsUrl) { | |
| return new Promise((resolve, reject) => { | |
| const ws = new WebSocket(wsUrl); | |
| let id = 0; | |
| const pending = new Map(); | |
| ws.addEventListener('message', (ev) => { | |
| const msg = JSON.parse(ev.data); | |
| if (msg.id && pending.has(msg.id)) { | |
| const { resolve: r, reject: j } = pending.get(msg.id); | |
| pending.delete(msg.id); | |
| if (msg.error) j(new Error(JSON.stringify(msg.error))); else r(msg.result); | |
| } | |
| }); | |
| ws.addEventListener('error', (e) => reject(new Error('ws error ' + (e.message || '')))); | |
| ws.addEventListener('open', () => { | |
| const send = (method, params = {}) => new Promise((r, j) => { | |
| const mid = ++id; pending.set(mid, { resolve: r, reject: j }); | |
| ws.send(JSON.stringify({ id: mid, method, params })); | |
| }); | |
| const evalJs = async (expr, awaitPromise = false) => { | |
| const res = await send('Runtime.evaluate', { expression: expr, returnByValue: true, awaitPromise }); | |
| if (res.exceptionDetails) throw new Error('eval: ' + JSON.stringify(res.exceptionDetails)); | |
| return res.result.value; | |
| }; | |
| resolve({ send, evalJs, ws }); | |
| }); | |
| }); | |
| } | |
| const EXPR = process.env.EXPR || `window.__runSuite(${DURATION}, ${REPS})`; | |
| const { evalJs, send } = await connect((await findTarget()).webSocketDebuggerUrl); | |
| await send('Runtime.enable'); | |
| await send('Page.enable'); | |
| if (process.env.NAV) { await send('Page.navigate', { url: process.env.NAV }); await sleep(2500); } | |
| else if (process.env.RELOAD === '1') { await send('Page.reload', { ignoreCache: true }); await sleep(1500); } | |
| // Wait for harness readiness. | |
| for (let i = 0; i < 60 && process.env.SKIPREADY !== '1'; i++) { | |
| const ready = await evalJs(`(typeof window.__runSuite === 'function' && typeof window.__runExtra === 'function' && document.getElementById('out') && document.getElementById('out').textContent.startsWith('ready'))`); | |
| if (ready) break; | |
| await sleep(500); | |
| } | |
| const env = await evalJs(`(()=>{return {visibility:document.visibilityState, dpr:window.devicePixelRatio, url:location.href};})()`); | |
| console.error('ENV', JSON.stringify(env)); | |
| if (env.visibility !== 'visible') console.error('WARNING: visibility=' + env.visibility + ' — rAF may be throttled. Anti-throttle flags should keep it running anyway.'); | |
| const result = await evalJs(EXPR, true); | |
| console.log(JSON.stringify(result)); | |
| process.exit(0); | |