import assert from "node:assert/strict"; import { handleWorkerMessage } from "./opfs-worker-bridge.mjs"; import { loadUiState } from "./opfs-ui-state.mjs"; class File { constructor() { this.bytes = new Uint8Array(); } async getFile() { return { text: async () => new TextDecoder().decode(this.bytes) }; } async createSyncAccessHandle() { const file = this; return { truncate(size) { file.bytes = file.bytes.slice(0, size); }, write(bytes, { at = 0 } = {}) { const next = new Uint8Array(Math.max(file.bytes.length, at + bytes.byteLength)); next.set(file.bytes); next.set(bytes, at); file.bytes = next; return bytes.byteLength; }, flush() {}, close() {}, }; } } class Directory { constructor() { this.files = new Map(); this.directories = new Map(); } async getDirectoryHandle(name, { create = false } = {}) { if (!this.directories.has(name)) { if (!create) throw Object.assign(new Error("missing"), { name: "NotFoundError" }); this.directories.set(name, new Directory()); } return this.directories.get(name); } async getFileHandle(name, { create = false } = {}) { if (!this.files.has(name)) { if (!create) throw Object.assign(new Error("missing"), { name: "NotFoundError" }); this.files.set(name, new File()); } return this.files.get(name); } async removeEntry(name) { this.files.delete(name); this.directories.delete(name); } } const storage = { root: new Directory(), async getDirectory() { return this.root; } }; const previousNavigator = globalThis.navigator; Object.defineProperty(globalThis, "navigator", { configurable: true, value: { storage } }); const contextId = "linuxcnc-2.10.0-pre0-wasm-m1-py-c1"; const base = { schema_version: 1, context_id: contextId, session_id: "bridge-test" }; let accepted = 0; let lastAccepted = null; const session = { accept(input) { accepted += 1; lastAccepted = input; return { schema_version: 1, kind: "COMMAND_RESULT", context_id: input.context_id, session_id: input.session_id, seq: input.seq, payload: { status: "verified", command: input.kind, active: input.payload?.active, recovery_checkpoint: input.payload?.checkpoint ?? undefined } }; } }; const saved = await handleWorkerMessage(session, { ...base, kind: "UI_STATE_SAVE", seq: 2000000001, operation_id: "ui-save", payload: { key: "xyzac-trt", state: { view: "p", zoom: 1 } } }); assert.equal(saved.kind, "UI_STATE_RESULT"); assert.equal(saved.payload.storage, "opfs"); assert.equal(accepted, 0); const loaded = await handleWorkerMessage(session, { ...base, kind: "UI_STATE_LOAD", seq: 2000000002, operation_id: "ui-load", payload: { key: "xyzac-trt" } }); assert.equal(loaded.payload.state.view, "p"); assert.equal(accepted, 0); const checkpoint = { schema: "xyzac-power-off-checkpoint.v1", simulation_tick: 3, state: { program: { source_text: "G21\nM2\n" } }, state_hash: "test" }; const powerOff = await handleWorkerMessage(session, { ...base, kind: "POWER", seq: 1, operation_id: "power-off", payload: { active: false, checkpoint } }); assert.equal(powerOff.payload.recovery_persistence.storage, "opfs"); await handleWorkerMessage(session, { ...base, kind: "LOAD_WORKSPACE", seq: 2, operation_id: "load", payload: { root_path: "/workspace" } }); assert.deepEqual(lastAccepted.payload.recovery_checkpoint, checkpoint); assert.equal(accepted, 2); assert.equal((await loadUiState({ contextId, key: "xyzac-trt-power-off" })).status, "verified"); if (previousNavigator === undefined) delete globalThis.navigator; else Object.defineProperty(globalThis, "navigator", { configurable: true, value: previousNavigator }); console.log(JSON.stringify({ schema: "opfs-worker-bridge.v1", status: "verified", ui_commands_do_not_consume_wasm_sequence: true, poweroff_checkpoint_roundtrip: true }));