129 lines
4.5 KiB
JavaScript
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}`);
|