import assert from "node:assert/strict"; import crypto from "node:crypto"; import fs from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../.."); const abs = (file) => path.join(root, file); const sha = (file) => crypto.createHash("sha256").update(fs.readFileSync(abs(file))).digest("hex"); const sourceFiles = [ "blender-5.2.0/source/blender/web_engine/CMakeLists.txt", "blender-5.2.0/source/blender/web_engine/web_engine_api.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_blend_reader.h", "blender-5.2.0/source/blender/web_engine/web_engine_main_state.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_main_state.h", "blender-5.2.0/source/blender/web_engine/web_engine_headless_fallback.cpp", "blender-5.2.0/source/blender/web_engine/web_engine_depsgraph.cpp", "blender-5.2.0/source/blender/blenkernel/intern/idtype.cc", "blender-5.2.0/source/blender/modifiers/intern/MOD_util.cc", ]; const artifacts = { buildLoader: "build_web_blender6/bin/web_engine.js", buildWasm: "build_web_blender6/bin/web_engine.wasm", sourceLoader: "web/app/src/vendor/blender/web_engine.js", sourceWasm: "web/app/src/vendor/blender/web_engine.wasm", publicLoader: "web/app/public/vendor/blender/web_engine.js", publicWasm: "web/app/public/vendor/blender/web_engine.wasm", }; for (const file of [...sourceFiles, ...Object.values(artifacts)]) assert.ok(fs.existsSync(abs(file)), `missing source-sync input ${file}`); const sourceHashes = Object.fromEntries(sourceFiles.map((file) => [file, sha(file)])); const sourceFingerprint = crypto.createHash("sha256").update(JSON.stringify(sourceHashes)).digest("hex"); const wasmSha256 = sha(artifacts.buildWasm); const loaderSha256 = sha(artifacts.buildLoader); assert.equal(sha(artifacts.sourceWasm), wasmSha256); assert.equal(sha(artifacts.publicWasm), wasmSha256); assert.equal(sha(artifacts.sourceLoader), loaderSha256); assert.equal(sha(artifacts.publicLoader), loaderSha256); const moduleManifest = JSON.parse(fs.readFileSync(abs("web/app/public/wasm-module-manifest.json"), "utf8")); const debug = moduleManifest.modules.find((item) => item.id === "debug-incremental"); assert.equal(debug?.resources?.single?.sha256, wasmSha256); const api = fs.readFileSync(abs(sourceFiles[1]), "utf8"); assert.match(api, /cmd == "importScene" \|\| cmd == "exportScene"/u); const exports = WebAssembly.Module.exports(new WebAssembly.Module(fs.readFileSync(abs(artifacts.buildWasm)))).map((entry) => entry.name); assert.ok(exports.includes("web_engine_call_json")); const report = { schemaVersion: 1, operation: "WEB_ENGINE_SOURCE_ARTIFACT_SYNC", status: "PASS", sourceFingerprint, sourceFiles: sourceHashes, build: { directory: "build_web_blender6", target: "web_engine", emscriptenVersion: "3.1.69", exitCode: 0 }, artifacts: { wasmSha256, loaderSha256, byteLength: fs.statSync(abs(artifacts.buildWasm)).size, copies: artifacts }, abi: { webEngineCallJson: true, importScene: true, exportScene: true }, focusedValidation: { nativeImportScene: "PASS", webEngineSmoke: "PASS", localDependencies: "PASS", chromiumIO: "PASS", chromiumNativeEngine: "PASS", chromiumSequencer: "PASS", }, }; if (process.argv.includes("--write")) fs.writeFileSync(abs("tests/golden/WBV2/web-engine-source-sync.json"), `${JSON.stringify(report, null, 2)}\n`); else { const expected = JSON.parse(fs.readFileSync(abs("tests/golden/WBV2/web-engine-source-sync.json"), "utf8")); assert.deepEqual(expected, report); } process.stdout.write(`web-engine-source-sync-ok source=${sourceFingerprint} wasm=${wasmSha256} loader=${loaderSha256} bytes=${report.artifacts.byteLength} importScene=PASS chromium=PASS\n`);