feat(sim): F4.2 the sim protocol, the simulation room and LocalSimHost; M9 measured
packages/protocol holds the one list of /sim messages and checks every field, naming what is wrong. packages/sim has the simulation room for F and the web worker: the document's snapshot at start, the engine's clock on the wall clock with Java's speed as cable delay, subscriptions to cable activity, a card's new frames and a program's new window lines, capture and clock kept over a stop, the command line as first action, a core failure told to every client. LocalSimHost mirrors the document into the worker and back without echo. M9 in Chromium: 17 examples give the same capture as in Node, character for character; the room runs in a real worker. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
// The page's side of the worker test: a document, a LocalSimHost on a real
|
||||
// Worker, a ping from the command line, the frames that come back.
|
||||
|
||||
import * as Y from 'yjs';
|
||||
import { readProject, writeProject } from '@mdg-filius/doc';
|
||||
import { openProjectArchive } from '@mdg-filius/fls';
|
||||
import type { HostMessage } from '@mdg-filius/protocol';
|
||||
import { LocalSimHost } from '../src/localSimHost.js';
|
||||
|
||||
async function run(archive: Uint8Array, workerUrl: string): Promise<{ icmpRows: number; mode: string }> {
|
||||
let counter = 0;
|
||||
const doc = new Y.Doc();
|
||||
writeProject(doc, openProjectArchive(archive, () => `00000000-0000-0000-0000-${(++counter).toString(16).padStart(12, '0')}`));
|
||||
const notebook = readProject(doc).graph.nodes.find((node) => node.displayName === 'Notebook 1.10')!;
|
||||
const worker = new Worker(workerUrl);
|
||||
const host = new LocalSimHost(doc, worker, () => worker.terminate());
|
||||
const got: HostMessage[] = [];
|
||||
host.onMessage((message) => got.push(message));
|
||||
host.send({ v: 1, kind: 'sub', topics: [`trace:${notebook.ports[0]!.id}`] });
|
||||
host.send({ v: 1, kind: 'start' });
|
||||
host.send({ v: 1, kind: 'speed', value: 100 });
|
||||
host.send({ v: 1, kind: 'input', node: notebook.id, app: 'terminal', action: 'enter', args: { line: 'ping 141.99.5.10' }, reqId: 'r1' });
|
||||
const icmpRows = () => got.flatMap((message) => (message.kind === 'trace' ? message.frames : [])).filter((frame) => frame.rows.some((row) => row.protocol === 'ICMP')).length;
|
||||
for (let waited = 0; waited < 15_000 && icmpRows() < 8; waited += 100) await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
const mode = got.filter((message) => message.kind === 'state').at(-1);
|
||||
host.close();
|
||||
return { icmpRows: icmpRows(), mode: mode?.kind === 'state' ? mode.mode : 'none' };
|
||||
}
|
||||
|
||||
(globalThis as unknown as { filiusLocal: unknown }).filiusLocal = { run };
|
||||
Reference in New Issue
Block a user