Moved from wayBetter for X; an app passes its own origin, process name, scripts and fixtures.
52 lines
3 KiB
JavaScript
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(); }
|