waybetter/dev-tools/native-stale-shortcut-check.mjs
CRT 5c64f2f6f8 dev-tools: the generic development harnesses (perf probes, close check, tab and webview stress)
Moved from wayBetter for X; an app passes its own origin, process name, scripts and fixtures.
2026-09-30 14:48:06 +07:00

52 lines
3 KiB
JavaScript

// In an isolated release flavor, verify a stale explicit tab ID never targets the active tab.
// Usage: node dev-tools/native-stale-shortcut-check.mjs <cdp-port> <a page of the site, e.g. https://x.com/home>
const port = Number(process.argv[2]);
if (!Number.isInteger(port)) throw new Error('Invalid CDP port');
const sitePage = process.argv[3] ?? process.env.SITE_PAGE;
if (!sitePage) throw new Error('A page of the site to open is required (argument 2 or SITE_PAGE)');
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);
await new Promise(resolve => { socket.onopen = resolve; });
let serial = 0;
const pending = new Map();
socket.onmessage = event => {
const message = JSON.parse(event.data);
if (message.id) { pending.get(message.id)?.(message); pending.delete(message.id); }
};
const evaluate = expression => new Promise((resolve, reject) => {
const id = ++serial;
const timer = setTimeout(() => { pending.delete(id); reject(new Error('Shell CDP timed out')); }, 30_000);
pending.set(id, message => {
clearTimeout(timer);
if (message.result?.exceptionDetails) reject(new Error(JSON.stringify(message.result.exceptionDetails).slice(0, 500)));
else resolve(message.result?.result?.value);
});
socket.send(JSON.stringify({ id, method: 'Runtime.evaluate', params: { expression, awaitPromise: true, returnByValue: true } }));
});
try {
const result = await evaluate(`(async () => {
const ids = () => [...document.querySelectorAll('.dv-tabs-container .dv-tab .bt-tab[data-panel-id]')]
.map(tab => tab.dataset.panelId);
const before = ids();
if (before.length !== 1) throw new Error('Expected one isolated initial tab');
await window.__TAURI__.event.emit('tab-open', { url: ${JSON.stringify(sitePage)}, background: true });
const waitFor = async count => {
const deadline = performance.now() + 10_000;
while (ids().length !== count && performance.now() < deadline) await new Promise(resolve => setTimeout(resolve, 50));
if (ids().length !== count) throw new Error('Timed out waiting for ' + count + ' tabs');
};
await waitFor(2);
const created = ids().find(id => !before.includes(id));
await window.__TAURI__.event.emit('tab-shortcut', { id: created, shortcut: 'close-tab' });
await waitFor(1);
for (const shortcut of ['close-tab', 'split-right', 'open-panel']) {
await window.__TAURI__.event.emit('tab-shortcut', { id: created, shortcut });
await new Promise(resolve => setTimeout(resolve, 200));
if (ids().join() !== before.join()) throw new Error('Stale ' + shortcut + ' changed live tabs');
}
return { before, created, after: ids(), staleShortcuts: ['close-tab', 'split-right', 'open-panel'] };
})()`);
console.log(JSON.stringify(result));
} finally { socket.close(); }