Spaces:
Sleeping
Sleeping
| // Launch a headed Chrome via --remote-debugging-pipe (CDP over stdio fds 3/4, | |
| // NO TCP port — so the IDE's preview/live-reload can't discover and hijack it) | |
| // and run the fluidity harness. Fully isolated + real GPU (headed on macOS). | |
| import { spawn } from 'child_process'; | |
| import { openSync } from 'fs'; | |
| const CHROME = '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'; | |
| const URL = process.env.URL || 'http://127.0.0.1:8901/real.html'; | |
| const EXPR = process.env.EXPR || `window.__runSuite(${+(process.env.DUR || 2500)}, ${+(process.env.REPS || 3)})`; | |
| const sleep = (ms) => new Promise(r => setTimeout(r, ms)); | |
| const log = openSync('/tmp/cs4g_pipe_chrome.log', 'a'); | |
| const child = spawn(CHROME, [ | |
| '--user-data-dir=/tmp/cs4g-bench-pipe', | |
| '--remote-debugging-pipe', | |
| '--no-first-run', '--no-default-browser-check', '--no-startup-window=false', | |
| '--disable-backgrounding-occluded-windows', '--disable-renderer-backgrounding', | |
| '--disable-background-timer-throttling', '--disable-features=CalculateNativeWinOcclusion', | |
| '--window-size=1500,1000', URL, | |
| ], { stdio: ['ignore', log, log, 'pipe', 'pipe'] }); | |
| const wr = child.stdio[3], rd = child.stdio[4]; | |
| let id = 0; const pending = new Map(); | |
| const events = []; | |
| let buf = Buffer.alloc(0); | |
| rd.on('data', (chunk) => { | |
| buf = Buffer.concat([buf, chunk]); | |
| let i; | |
| while ((i = buf.indexOf(0)) !== -1) { | |
| const msg = JSON.parse(buf.slice(0, i).toString('utf8')); | |
| buf = buf.slice(i + 1); | |
| if (msg.id && pending.has(msg.id)) { const { res, rej } = pending.get(msg.id); pending.delete(msg.id); msg.error ? rej(new Error(JSON.stringify(msg.error))) : res(msg.result); } | |
| else if (msg.method) events.push(msg); | |
| } | |
| }); | |
| const send = (method, params = {}, sessionId) => new Promise((res, rej) => { | |
| const mid = ++id; pending.set(mid, { res, rej }); | |
| const m = { id: mid, method, params }; if (sessionId) m.sessionId = sessionId; | |
| wr.write(JSON.stringify(m) + '\0'); | |
| }); | |
| // Discover the page target and attach (flattened sessions). | |
| await send('Target.setDiscoverTargets', { discover: true }); | |
| let targetId = null; | |
| for (let i = 0; i < 80 && !targetId; i++) { | |
| const { targetInfos } = await send('Target.getTargets'); | |
| const t = targetInfos.find(x => x.type === 'page' && /^https?:/.test(x.url)); | |
| if (t) targetId = t.targetId; else await sleep(250); | |
| } | |
| if (!targetId) { console.error('no page target'); child.kill(); process.exit(1); } | |
| const { sessionId } = await send('Target.attachToTarget', { targetId, flatten: true }); | |
| const evalJs = async (expr, awaitPromise = false) => { | |
| const r = await send('Runtime.evaluate', { expression: expr, returnByValue: true, awaitPromise }, sessionId); | |
| if (r.exceptionDetails) throw new Error('eval: ' + JSON.stringify(r.exceptionDetails).slice(0, 400)); | |
| return r.result.value; | |
| }; | |
| await send('Runtime.enable', {}, sessionId); | |
| // If the page isn't on our URL yet (fresh profile may show a default), navigate once. | |
| const cur = await evalJs('location.href'); | |
| if (!cur.includes(URL.split('/').pop())) { await send('Page.enable', {}, sessionId); await send('Page.navigate', { url: URL }, sessionId); await sleep(2500); } | |
| for (let i = 0; i < 80; i++) { | |
| const ready = await evalJs(`(typeof window.__runSuite==='function' && typeof window.__runExtra==='function' && document.getElementById('out') && document.getElementById('out').textContent.startsWith('ready'))`).catch(() => false); | |
| if (ready) break; await sleep(500); | |
| } | |
| const env = await evalJs(`(()=>{const gl=document.createElement('canvas').getContext('webgl');const d=gl&&gl.getExtension('WEBGL_debug_renderer_info');return {visibility:document.visibilityState,dpr:window.devicePixelRatio,gpu:d?gl.getParameter(d.UNMASKED_RENDERER_WEBGL):'n/a',svgChildren:document.querySelectorAll('#c svg *').length, url:location.href};})()`); | |
| console.error('ENV', JSON.stringify(env)); | |
| const result = await evalJs(EXPR, true); | |
| console.log(JSON.stringify(result)); | |
| child.kill(); | |
| process.exit(0); | |