Load wasm files at runtime instead of inlining as base64#16
Conversation
The previous loader used a Bun build-time macro to embed both wasm variants as base64 string constants in the bundled `dist/index.js`, roughly tripling the JS bundle and keeping ~1.4 MB of base64 strings permanently resident in the JS heap (constants don't get collected). Switch to runtime loading: the build emits `simd.wasm` / `nosimd.wasm` straight into `dist/`, and `ts/index.ts` reads whichever variant the SIMD probe selects via `readFileSync(new URL(name, import.meta.url))`. After `WebAssembly.Module` compiles the bytes, the Buffer becomes GC-eligible, so the steady-state JS heap drops by the size of the chosen wasm. Other effects: - `dist/index.js` shrinks from ~2.0 MB to ~71 KB (28x smaller) - npm tarball: 837 KB → 668 KB compressed; 2.04 MB → 1.6 MB unpacked - `ts/macro.ts` and the `assets/wasm/` staging dir are gone - `bun build` now needs `--target=node` so it doesn't stub `node:fs` - consumer side requires Node/Bun (no browser support, same as before since the previous code already relied on `process.env`)
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
ts/index.ts (1)
11-19: ⚡ Quick winSurface the underlying error when WASM initialization fails.
tryInitcatches and discards every error, so a missing/corruptdist/whatsapp_rust_bridge_bg.simd.wasm(e.g., a packaging regression) silently falls back to the non-SIMD variant, and when both variants fail the thrown error carries no diagnostic context (nocause, no path, no originalError.message). For a published library this makes field debugging materially harder. Consider capturing the last error and threading it into the thrownError, and optionally warning when SIMD was supported but its variant failed to load.♻️ Proposed refactor preserving error context
-function tryInit(filename: string): boolean { - try { - const url = new URL(filename, import.meta.url); - initSync({ module: readFileSync(url) }); - return true; - } catch { - return false; - } -} +function tryInit(filename: string): Error | null { + try { + const url = new URL(filename, import.meta.url); + initSync({ module: readFileSync(url) }); + return null; + } catch (err) { + return err instanceof Error ? err : new Error(String(err)); + } +} @@ -let simdUsed = false; -if (simdSupported && tryInit("whatsapp_rust_bridge_bg.simd.wasm")) { - simdUsed = true; -} else if (!tryInit("whatsapp_rust_bridge_bg.nosimd.wasm")) { - throw new Error( - "whatsapp-rust-bridge: failed to load WASM module (neither SIMD nor non-SIMD variant could be initialized)", - ); -} +let simdUsed = false; +let simdErr: Error | null = null; +if (simdSupported) { + simdErr = tryInit("whatsapp_rust_bridge_bg.simd.wasm"); + if (simdErr === null) { + simdUsed = true; + } else { + console.warn( + `whatsapp-rust-bridge: SIMD variant failed to initialize, falling back to non-SIMD: ${simdErr.message}`, + ); + } +} +if (!simdUsed) { + const nosimdErr = tryInit("whatsapp_rust_bridge_bg.nosimd.wasm"); + if (nosimdErr !== null) { + throw new Error( + "whatsapp-rust-bridge: failed to load WASM module (neither SIMD nor non-SIMD variant could be initialized)", + { cause: simdErr ?? nosimdErr }, + ); + } +}Also applies to: 28-34
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@ts/index.ts` around lines 11 - 19, The tryInit function currently swallows all exceptions; change it to capture and preserve underlying errors: when calling new URL/readFileSync/initSync inside tryInit, catch the thrown error into a local variable (e.g., lastError) and rethrow or return with context instead of discarding it—specifically, if you still want a boolean API, record lastError and expose it (or throw a new Error that sets lastError as the cause) so callers get the original message and stack; also, when a SIMD variant fails but SIMD is supported, emit a warning via the existing logger mentioning the failed wasm filename and lastError; update both tryInit occurrences (lines shown) to follow this pattern and reference initSync, readFileSync, and new URL to locate the code to modify.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@ts/index.ts`:
- Around line 11-19: The tryInit function currently swallows all exceptions;
change it to capture and preserve underlying errors: when calling new
URL/readFileSync/initSync inside tryInit, catch the thrown error into a local
variable (e.g., lastError) and rethrow or return with context instead of
discarding it—specifically, if you still want a boolean API, record lastError
and expose it (or throw a new Error that sets lastError as the cause) so callers
get the original message and stack; also, when a SIMD variant fails but SIMD is
supported, emit a warning via the existing logger mentioning the failed wasm
filename and lastError; update both tryInit occurrences (lines shown) to follow
this pattern and reference initSync, readFileSync, and new URL to locate the
code to modify.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 78521ceb-265d-46a7-ba02-f098fb77ccab
📒 Files selected for processing (6)
.gitignorepackage.jsonscripts/build-wasm.mjsts/index.tsts/macro.tstsconfig.json
💤 Files with no reviewable changes (2)
- .gitignore
- ts/macro.ts
Summary
Drops the
bun buildmacro that embedded both wasm variants as base64 string constants indist/index.js. Wasms are now emitted straight intodist/and loaded at startup viareadFileSync(new URL(name, import.meta.url)).Why
WebAssembly.Modulecompiles raw bytes, the Buffer is collectable.Numbers
dist/index.jsTest plan
bun test— 163 pass / 0 failcargo fmt --check,cargo clippy -D warnings— cleanSummary by CodeRabbit
Refactor
Chores