122 lines
4.4 KiB
JavaScript
122 lines
4.4 KiB
JavaScript
/**
|
|
* Dev-only: live CDP PROBE of the Phaser 4.2.1 Graphics `commandBuffer`
|
|
* shape (this build has no `.commands`) — one-shot.
|
|
*
|
|
* node dev/graphics-probe.mjs
|
|
*/
|
|
const CDP = process.env.CDP_PORT ? `127.0.0.1:${process.env.CDP_PORT}` : '127.0.0.1:9333';
|
|
const BASE = process.env.BASE_URL ?? 'http://127.0.0.1:8080';
|
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
|
|
function connect(target) {
|
|
const ws = new WebSocket(target.webSocketDebuggerUrl);
|
|
let id = 0;
|
|
const pending = new Map();
|
|
ws.onmessage = (x) => {
|
|
const m = JSON.parse(x.data);
|
|
if (m.id && pending.has(m.id)) {
|
|
const { res, rej } = pending.get(m.id);
|
|
pending.delete(m.id);
|
|
m.error ? rej(new Error(m.error.message)) : res(m.result);
|
|
}
|
|
};
|
|
const open = new Promise((r) => {
|
|
ws.onopen = r;
|
|
ws.onerror = () => r();
|
|
});
|
|
const send = (method, params = {}) =>
|
|
new Promise((res, rej) => {
|
|
const mid = ++id;
|
|
pending.set(mid, { res, rej });
|
|
ws.send(JSON.stringify({ id: mid, method, params }));
|
|
});
|
|
return { ws, send, open };
|
|
}
|
|
|
|
async function evalJs(c, expression, awaitPromise = true) {
|
|
const r = await c.send('Runtime.evaluate', { expression, returnByValue: true, awaitPromise });
|
|
if (r.exceptionDetails) throw new Error(JSON.stringify(r.exceptionDetails, null, 2));
|
|
return r.result?.value;
|
|
}
|
|
|
|
async function openPage(path) {
|
|
const url = `${BASE}${path}`;
|
|
let target;
|
|
try {
|
|
target = await (await fetch(`http://${CDP}/json/new?${encodeURIComponent(url)}`, { method: 'PUT' })).json();
|
|
} catch {
|
|
target = await (await fetch(`http://${CDP}/json/new?${encodeURIComponent(url)}`, { method: 'POST' })).json();
|
|
}
|
|
const c = connect(target);
|
|
await c.open;
|
|
await c.send('Runtime.enable');
|
|
return { c, target };
|
|
}
|
|
|
|
const PROBE = `(() => {
|
|
const gs = window.game && window.game.scene ? window.game.scene.getScene('GameScene') : null;
|
|
if (!gs) return 'no scene';
|
|
const g = gs.add.graphics();
|
|
const desc = (v) => {
|
|
if (v === null || v === undefined) return v;
|
|
if (Array.isArray(v)) return v.slice(0, 12).map((x) => desc(x));
|
|
if (typeof v === 'object') {
|
|
const o = {};
|
|
for (const k of Object.keys(v).slice(0, 14)) o[k] = desc(v[k]);
|
|
return o;
|
|
}
|
|
return v;
|
|
};
|
|
const out = { before: desc(g.commandBuffer) };
|
|
try { g.fillStyle('#ff2d6f', 1); out.fillStyle = 'ok'; } catch (e) { out.fillStyle = 'ERR:' + e.message; }
|
|
try { g.fillCircle(100, 100, 8); out.fillCircle = 'ok'; } catch (e) { out.fillCircle = 'ERR:' + e.message; }
|
|
try { g.fillTriangle(0, 0, 10, 0, 5, 10); out.fillTriangle = 'ok'; } catch (e) { out.fillTriangle = 'ERR:' + e.message; }
|
|
out.after = desc(g.commandBuffer);
|
|
try { g.clear(); out.afterClear = desc(g.commandBuffer); } catch (e) { out.afterClear = 'ERR:' + e.message; }
|
|
try { if (g && typeof g.destroy === 'function') g.destroy(); } catch (e) {}
|
|
return out;
|
|
})()`;
|
|
|
|
async function main() {
|
|
const { c, target } = await openPage('/index.html');
|
|
try {
|
|
for (let i = 0; i < 80; i++) {
|
|
await sleep(500);
|
|
let ok = false;
|
|
try { ok = await evalJs(c, 'Boolean(window.game)', false); } catch { ok = false; }
|
|
if (ok) break;
|
|
}
|
|
const started = await evalJs(c, `(async () => {
|
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
for (let i = 0; i < 120; i++) {
|
|
const m = window.game && window.game.scene && window.game.scene.getScene('MenuScene');
|
|
if (m && typeof m.seedValue === 'string') { m.startNewGame(); return 'started'; }
|
|
await sleep(500);
|
|
}
|
|
return 'menu never ready';
|
|
})()`);
|
|
if (started !== 'started') throw new Error(`start: ${started}`);
|
|
for (let i = 0; i < 60; i++) {
|
|
await sleep(500);
|
|
let ok = false;
|
|
try { ok = await evalJs(c, 'Boolean(window.__ORBIT_COMBAT__ && window.game.scene.getScene("GameScene").ship)', false); } catch { ok = false; }
|
|
if (ok) break;
|
|
}
|
|
await sleep(800);
|
|
const out = await evalJs(c, PROBE);
|
|
console.log(typeof out === 'string' ? out : JSON.stringify(out, null, 1));
|
|
return true;
|
|
} catch (err) {
|
|
console.error(`graphics-probe: FAIL — ${err.message}`);
|
|
return false;
|
|
} finally {
|
|
try { await fetch(`http://${CDP}/json/close/${target.id}`).catch(() => {}); } catch { /* ignore */ }
|
|
c.ws.close();
|
|
}
|
|
}
|
|
|
|
main().then((ok) => process.exit(ok ? 0 : 1)).catch((e) => {
|
|
console.error('graphics-probe error:', e.message);
|
|
process.exit(2);
|
|
});
|