Files
effectcraft/apps/effectcraft-web/tests/workers.mjs
T
Claude a2f22bb35b Web: a replaced file goes to reused workers again, even at the same size (#218)
Job workers remembered the files they were sent by path and byte
length, so footage replaced by different bytes of the same length at
the same path was never resent: a Render Queue export through a reused
worker rendered the old image while the page showed the new one.
Frame workers remembered paths only, so they never got a replacement
at all.

Every write of a stored file now gets a version, and both kinds of
worker remember the version they were sent.

Tests: versions_change_with_every_write (store) and
apps/effectcraft-web/tests/workers.mjs (Node, fake Worker: the
replacement is sent once, an unchanged file not again).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018gnTnH3Jmk5zr4tMq1Mc9f
2026-10-07 22:33:04 +00:00

57 lines
2.1 KiB
JavaScript

// Job-worker plumbing of the web app (js/host.js) under Node with a fake Worker,
// no browser or Wasm build needed:
//
// node apps/effectcraft-web/tests/workers.mjs
//
// - A reused worker is sent a file again when it was replaced, even by one of the same size
// (#218), and not when it is unchanged.
// Exits non-zero on failure.
import assert from "node:assert/strict";
import { dirname, join } from "node:path";
import { fileURLToPath, pathToFileURL } from "node:url";
const here = dirname(fileURLToPath(import.meta.url));
globalThis.self = globalThis;
// A Worker that starts on "init" and finishes each job at once.
let failStart = false;
const workers = [];
class FakeWorker {
constructor() {
this.posted = [];
this.terminated = false;
workers.push(this);
}
postMessage(m) {
this.posted.push(m);
setTimeout(() => {
if (m.type === "init") {
if (failStart) this.onerror?.({ message: "worker failed to start" });
else this.onmessage?.({ data: { type: "ready" } });
} else if (m.type === "job") {
this.onmessage?.({ data: { type: "reply", json: "{}", done: true } });
}
});
}
terminate() {
this.terminated = true;
}
}
globalThis.Worker = FakeWorker;
const host = await import(pathToFileURL(join(here, "../js/host.js")));
const run = (id, files) =>
new Promise((resolve) => host.workerRun(id, "{}", files, "http://localhost/", (kind, json) => kind !== "file" && resolve({ kind, json })));
const sent = (w) => w.posted.filter((m) => m.type === "file").map((m) => m.bytes[0]);
// #218: equal-length replacement.
const red = new Uint8Array(512).fill(1);
const blue = new Uint8Array(512).fill(2);
assert.equal((await run(1, [["/collision.png", red, 1]])).kind, "reply");
assert.equal((await run(2, [["/collision.png", blue, 2]])).kind, "reply");
assert.equal((await run(3, [["/collision.png", blue, 2]])).kind, "reply");
assert.equal(workers.length, 1, "the worker is reused");
assert.deepEqual(sent(workers[0]), [1, 2], "the replacement is sent once, the unchanged file not again");
console.log("workers: ok");