Files
FreeCADWasmDev/tools/run_p6_spreadsheet_object_data_property_batch_gate.mjs
wangdequan 9a7c4f0335 Save FreeCAD Web workspace sources and user validation evidence
IFC native binding remains incomplete; preserve accurate test results.
2026-09-15 22:01:58 +08:00

32 lines
5.0 KiB
JavaScript

#!/usr/bin/env node
import fs from "node:fs";
import path from "node:path";
import crypto from "node:crypto";
import { pathToFileURL } from "node:url";
import { createRequire } from "node:module";
const root = "/home/mes123456/FreeCADWasmDev/working/FreeCAD";
const build = path.resolve(process.argv[2] ?? path.join(root, "freecad-source/build-web/configure/bin"));
globalThis.__dirname = `${build}${path.sep}`;
globalThis.require = createRequire(import.meta.url);
process.chdir(build);
const batch = JSON.parse(fs.readFileSync(path.join(root, "docs/current/module-batch-manifest.json"), "utf8"));
if (batch.status !== "ready" || batch.selected?.module !== "Spreadsheet" || batch.selected?.tier !== "object-contract" || batch.selected?.family !== "data-property") throw new Error("unexpected Spreadsheet batch");
const records = batch.records.map(([apiId, name, disposition, sourcePath, sourceLine]) => ({ apiId, name, family: "data-property", kind: "object", sourcePath, sourceLine, disposition }));
const temp = fs.mkdtempSync("/tmp/freecad-spreadsheet-object-");
fs.writeFileSync(path.join(temp, "package.json"), '{"type":"module"}\n');
fs.writeFileSync(path.join(temp, "FreeCADWebSpreadsheetRuntimeProbe.js"), fs.readFileSync(path.join(build, "FreeCADWebSpreadsheetRuntimeProbe.js"), "utf8").replaceAll("FreeCADWebSpreadsheetRuntimeProbe.worker.js", "FreeCADWebSpreadsheetRuntimeProbe.worker.cjs"));
fs.copyFileSync(path.join(build, "FreeCADWebSpreadsheetRuntimeProbe.worker.js"), path.join(temp, "FreeCADWebSpreadsheetRuntimeProbe.worker.cjs"));
const mod = await import(pathToFileURL(path.join(temp, "FreeCADWebSpreadsheetRuntimeProbe.js")));
const kernel = await mod.default({ wasmBinary: fs.readFileSync(path.join(build, "FreeCADWebSpreadsheetRuntimeProbe.wasm")), locateFile: f => f.endsWith(".worker.js") ? path.join(temp, "FreeCADWebSpreadsheetRuntimeProbe.worker.cjs") : path.join(build, f), print: () => {}, printErr: () => {} });
const invoke = (rows) => JSON.parse(String(kernel.ccall("fc_web_dispatch_json", "string", ["string"], [JSON.stringify({ cmd: "spreadsheet.pythonFamilyBatch", args: { tier: "object-contract", records: rows } })])));
const success = invoke(records), repeat = invoke(records);
if (success.ok !== true || success.count !== records.length || success.resourcesReleased !== true || !Array.isArray(success.records) || success.records.length !== records.length) throw new Error(JSON.stringify(success));
if (JSON.stringify(success) !== JSON.stringify(repeat)) throw new Error("native replay changed");
for (let i = 0; i < records.length; i++) { const got = success.records[i]; const want = records[i]; if (got.apiId !== want.apiId || got.name !== want.name || got.sourceEntry !== want.sourcePath || got.native !== true || got.resourcesReleased !== true || typeof got.sourceRevision !== "string") throw new Error(`record ${i} contract failed`); }
const dispositionCounts = Object.fromEntries(["exposed", "restricted", "nonportable", "not_implemented"].map(s => [s, success.records.filter(r => r.status === s).length]));
const hash = v => crypto.createHash("sha256").update(JSON.stringify(v)).digest("hex");
const report = { schema: "freecad-web-spreadsheet-object-data-property-module-batch-runtime/v1", taskId: "FW-P6-FPA-Y", batchId: batch.batchId, module: "Spreadsheet", tier: "object-contract", family: "data-property", status: "pass_with_boundaries", route: { command: "spreadsheet.pythonFamilyBatch", native: "freecad-source/src/WebAssembly/FreeCADCoreProbe/SpreadsheetRuntimeProbe.cpp:fc_web_dispatch_json", facade: "web/src/spreadsheet-python-family-facade.ts", worker: "web/src/spreadsheet.worker.ts" }, input: { cmd: "spreadsheet.pythonFamilyBatch", args: { tier: "object-contract", records } }, inputSha256: hash(records), result: success, resultSha256: hash(success), replay: { equal: true, resultSha256: hash(repeat) }, dispositionCounts, records: success.records.map(r => ({ apiId: r.apiId, name: r.name, status: r.status, code: r.code, message: r.message, sourceEntry: r.sourceEntry, sourceRevision: r.sourceRevision, evidenceSha256: hash(r) })), resources: { resourcesReleased: true, documentMutation: false }, artifacts: { module: "Spreadsheet", worker: "spreadsheet.worker.ts", revision: success.records[0]?.sourceRevision, runtimeUrl: "/kernel/FreeCADWebSpreadsheetRuntimeProbe.js", wasmUrl: "/kernel/FreeCADWebSpreadsheetRuntimeProbe.wasm", dataUrl: null, assetBaseUrl: "/kernel/", wasmSha256: hash(fs.readFileSync(path.join(build, "FreeCADWebSpreadsheetRuntimeProbe.wasm"))), buildProfile: "fast-dev" }, boundaries: ["Object property statuses derive from native Spreadsheet source through fc_web_dispatch_json.", "GUI-only Spreadsheet view behavior remains outside this headless object-contract fixture."] };
fs.writeFileSync(path.join(root, `docs/p6/spreadsheet-module-batch-${batch.batchId}-runtime.json`), `${JSON.stringify(report, null, 2)}\n`);
console.log(JSON.stringify({ status: report.status, batchId: batch.batchId, count: records.length, dispositionCounts, resultSha256: report.resultSha256 }));
process.exit(0);