NODEDC_MISSION_CORE/apps/control-station/scripts/transform-rerun-web-viewer-...

129 lines
4.5 KiB
JavaScript

import { createHash } from "node:crypto";
import { readFileSync, writeFileSync } from "node:fs";
import { resolve } from "node:path";
const [inputArgument, outputArgument] = process.argv.slice(2);
if (!inputArgument || !outputArgument) {
throw new Error("Usage: node transform-rerun-web-viewer-glue.mjs INPUT OUTPUT");
}
const inputPath = resolve(inputArgument);
const outputPath = resolve(outputArgument);
const expectedGeneratedSha256 =
"cc196a93c5be972c801d46be4dc9934f7f042eb62941f0aa0678f1c8416c6874";
const sha256 = (value) => createHash("sha256").update(value).digest("hex");
let code = readFileSync(inputPath, "utf8");
if (sha256(code) !== expectedGeneratedSha256) {
throw new Error(`Refusing to transform unexpected wasm-bindgen output: ${inputPath}`);
}
// This is the same no-modules-base transformation used by Rerun 0.34.1's
// rerun_js/web-viewer/build-wasm.mjs. Each factory call gets isolated closure state.
const wrapperStart = "let wasm_bindgen = (function(exports) {";
const wrapperEnd = `return Object.assign(__wbg_init, { initSync }, exports);
})({ __proto__: null });`;
if (!code.includes(wrapperStart) || !code.includes(wrapperEnd)) {
throw new Error("Rerun wasm-bindgen wrapper markers no longer match");
}
code = code.replace(wrapperStart, "").replace(wrapperEnd, "");
code = `
export default function() {
const exports = { __proto__: null };
${code}
function deinit() {
__wbg_init.__wbindgen_wasm_module = null;
wasmModule = null;
wasm = null;
cachedDataViewMemory0 = null;
cachedFloat32ArrayMemory0 = null;
cachedInt16ArrayMemory0 = null;
cachedInt32ArrayMemory0 = null;
cachedInt8ArrayMemory0 = null;
cachedUint16ArrayMemory0 = null;
cachedUint32ArrayMemory0 = null;
cachedUint8ArrayMemory0 = null;
}
return Object.assign(__wbg_init, { initSync, deinit }, exports);
}
`;
const closureDtorsOriginal = `const CLOSURE_DTORS = (typeof FinalizationRegistry === 'undefined')
? { register: () => {}, unregister: () => {} }
: new FinalizationRegistry(state => wasm.__wbindgen_destroy_closure(state.a, state.b));`;
const closureDtorsPatch = `const CLOSURE_DTORS = (typeof FinalizationRegistry === 'undefined')
? { register: () => {}, unregister: () => {} }
: new FinalizationRegistry(state => {
if (wasm) wasm.__wbindgen_destroy_closure(state.a, state.b);
});`;
if (!code.includes(closureDtorsOriginal)) {
throw new Error("Rerun CLOSURE_DTORS block no longer matches");
}
code = code.replace(closureDtorsOriginal, closureDtorsPatch);
const makeMutClosureOriginal = `function makeMutClosure(arg0, arg1, f) {
const state = { a: arg0, b: arg1, cnt: 1 };
const real = (...args) => {
// First up with a closure we increment the internal reference
// count. This ensures that the Rust closure environment won't
// be deallocated while we're invoking it.
state.cnt++;
const a = state.a;
state.a = 0;
try {
return f(a, state.b, ...args);
} finally {
state.a = a;
real._wbg_cb_unref();
}
};
real._wbg_cb_unref = () => {
if (--state.cnt === 0) {
wasm.__wbindgen_destroy_closure(state.a, state.b);
state.a = 0;
CLOSURE_DTORS.unregister(state);
}
};
CLOSURE_DTORS.register(real, state, state);
return real;
}`;
const makeMutClosurePatch = `function makeMutClosure(arg0, arg1, f) {
const state = { a: arg0, b: arg1, cnt: 1 };
const real = (...args) => {
state.cnt++;
const a = state.a;
state.a = 0;
try {
if (!wasm) return;
return f(a, state.b, ...args);
} finally {
state.a = a;
real._wbg_cb_unref();
}
};
real._wbg_cb_unref = () => {
if (--state.cnt === 0) {
if (wasm) wasm.__wbindgen_destroy_closure(state.a, state.b);
state.a = 0;
CLOSURE_DTORS.unregister(state);
}
};
CLOSURE_DTORS.register(real, state, state);
return real;
}`;
if (!code.includes(makeMutClosureOriginal)) {
throw new Error("Rerun makeMutClosure block no longer matches");
}
code = code.replace(makeMutClosureOriginal, makeMutClosurePatch);
writeFileSync(outputPath, code);
console.log(`Transformed Rerun wasm glue: ${sha256(code)} ${outputPath}`);