chore: checkpoint web Blender feature-gap work, docs and tests
- update native web_engine sources and rebuilt wasm artifacts - add task cards, status notes and tooling scripts - add web e2e specs, tutorial UI sources and tutorial assets - sync golden task manifests and audit records Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
76
tools/web/qa/opfs-sync-worker.js
Normal file
76
tools/web/qa/opfs-sync-worker.js
Normal file
@@ -0,0 +1,76 @@
|
||||
/* QA-only Dedicated Worker: exercises OPFS createSyncAccessHandle modes. */
|
||||
const handles = new Map();
|
||||
|
||||
function reply(requestId, payload) {
|
||||
self.postMessage({ requestId, ...payload });
|
||||
}
|
||||
|
||||
async function resolveFile(path) {
|
||||
const segments = String(path).split("/").filter(Boolean);
|
||||
if (!segments.length) throw new Error("empty OPFS path");
|
||||
let directory = await navigator.storage.getDirectory();
|
||||
for (const segment of segments.slice(0, -1)) {
|
||||
directory = await directory.getDirectoryHandle(segment, { create: true });
|
||||
}
|
||||
return directory.getFileHandle(segments[segments.length - 1], { create: true });
|
||||
}
|
||||
|
||||
self.onmessage = async (event) => {
|
||||
const data = event.data ?? {};
|
||||
const requestId = data.requestId ?? "";
|
||||
try {
|
||||
if (data.op === "capability") {
|
||||
reply(requestId, {
|
||||
ok: true,
|
||||
hasSyncMethod: typeof FileSystemFileHandle !== "undefined" &&
|
||||
typeof FileSystemFileHandle.prototype.createSyncAccessHandle === "function",
|
||||
isDedicatedWorker: typeof DedicatedWorkerGlobalScope !== "undefined",
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (data.op === "acquire") {
|
||||
const file = await resolveFile(data.path);
|
||||
const mode = data.mode ?? "readwrite";
|
||||
let handle;
|
||||
try {
|
||||
handle = await file.createSyncAccessHandle({ mode });
|
||||
}
|
||||
catch (error) {
|
||||
if (mode === "readwrite-unsafe" && error instanceof TypeError) {
|
||||
reply(requestId, { ok: false, unsupportedMode: true, mode, name: error.name, message: error.message });
|
||||
return;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
handles.set(data.id ?? requestId, handle);
|
||||
let written = 0;
|
||||
if (data.write !== undefined) {
|
||||
written = handle.write(new Uint8Array(data.write), { at: 0 });
|
||||
handle.flush();
|
||||
}
|
||||
reply(requestId, { ok: true, mode, size: handle.getSize(), written });
|
||||
return;
|
||||
}
|
||||
if (data.op === "close") {
|
||||
const handle = handles.get(data.id ?? requestId);
|
||||
if (handle) { handle.close(); handles.delete(data.id ?? requestId); }
|
||||
reply(requestId, { ok: true, closed: Boolean(handle) });
|
||||
return;
|
||||
}
|
||||
if (data.op === "close-all") {
|
||||
for (const handle of handles.values()) handle.close();
|
||||
handles.clear();
|
||||
reply(requestId, { ok: true });
|
||||
return;
|
||||
}
|
||||
reply(requestId, { ok: false, name: "QA_OPERATION_INVALID", message: String(data.op) });
|
||||
}
|
||||
catch (error) {
|
||||
reply(requestId, {
|
||||
ok: false,
|
||||
name: error?.name ?? "Error",
|
||||
message: error?.message ?? String(error),
|
||||
stack: String(error?.stack ?? "").slice(0, 1200),
|
||||
});
|
||||
}
|
||||
};
|
||||
1000
tools/web/qa/run-web-blender-qa-20261111.mjs
Normal file
1000
tools/web/qa/run-web-blender-qa-20261111.mjs
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user