fix(wasm): load native assets from a real directory in compiled binaries - #449
Conversation
Inside a compiled single binary (bun build --compile), import.meta.url points into the binary's embedded filesystem; dynamic import() resolves against it exclusively, so the binding's relative asset URLs can never reach assets installed on disk and getBinding() fails even when dist/native/ is present next to the binary. STLL_ANONYMIZE_ASSET_DIR now overrides the asset base (absolute POSIX path or file: URL). Browsers never define process, so the override is inert there; the default path is unchanged. smoke-wasm-compiled.mjs guards both directions: a compiled consumer must fail without the override (proving the guard exercises the embedded filesystem class) and must redact end to end with it — glue, wasm, and prepared package all resolve through the override.
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
|
Warning Review limit reached
Next review available in: 39 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughThe WebAssembly loader now supports ChangesCompiled WebAssembly asset loading
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant CI
participant SmokeTest
participant Bun
participant CompiledConsumer
participant wasm_ts
CI->>SmokeTest: run smoke:wasm-compiled
SmokeTest->>Bun: compile temporary consumer
SmokeTest->>CompiledConsumer: run without asset override
CompiledConsumer->>wasm_ts: load WebAssembly entry point
wasm_ts-->>CompiledConsumer: fail to resolve native assets
SmokeTest->>CompiledConsumer: run with copied assets and STLL_ANONYMIZE_ASSET_DIR
CompiledConsumer->>wasm_ts: load engine and redact entity
wasm_ts-->>SmokeTest: return redacted output
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 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.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3ce95a8a74
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
packages/anonymize/scripts/smoke-wasm-compiled.mjs (1)
80-95: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winExercise the
file:URL override.Line 84 tests only the absolute POSIX-path form. The loader also accepts a
file:URL, but CI does not execute that branch.Run the compiled consumer once more with
STLL_ANONYMIZE_ASSET_DIRset tonew URL(assetDir, "file:///").href. Require the same successful redaction result.🤖 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 `@packages/anonymize/scripts/smoke-wasm-compiled.mjs` around lines 80 - 95, Extend the smoke test after the existing withOverride validation to run the compiled consumer again with STLL_ANONYMIZE_ASSET_DIR set to the file URL derived from assetDir via new URL(assetDir, "file:///").href. Validate that this invocation exits successfully and produces the same JSON redaction result, reusing the existing output parsing and failure checks where appropriate.
🤖 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.
Inline comments:
In `@packages/anonymize/src/wasm.ts`:
- Around line 193-196: Update the override handling in the asset-directory URL
logic to reject relative filesystem paths and non-local file URLs, then convert
valid filesystem paths with pathToFileURL so characters such as # and ? remain
encoded as path data. Preserve the existing trailing-slash URL behavior and
ASSET_DIR_ENV override handling.
---
Nitpick comments:
In `@packages/anonymize/scripts/smoke-wasm-compiled.mjs`:
- Around line 80-95: Extend the smoke test after the existing withOverride
validation to run the compiled consumer again with STLL_ANONYMIZE_ASSET_DIR set
to the file URL derived from assetDir via new URL(assetDir, "file:///").href.
Validate that this invocation exits successfully and produces the same JSON
redaction result, reusing the existing output parsing and failure checks where
appropriate.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 3f816279-64eb-41f8-beab-977f0e2f12df
📒 Files selected for processing (5)
.changeset/compiled-binary-asset-loading.md.github/workflows/ci.ymlpackages/anonymize/package.jsonpackages/anonymize/scripts/smoke-wasm-compiled.mjspackages/anonymize/src/wasm.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx,md,json,yaml,yml}
📄 CodeRabbit inference engine (AGENTS.md)
Do not publish private user, customer, infrastructure, incident, pricing, roadmap, competitive, or internal security context in repository artifacts, comments, PRs, or generated instructions.
Files:
packages/anonymize/package.jsonpackages/anonymize/src/wasm.ts
**/*.{ts,tsx,js,jsx,rs,py}
📄 CodeRabbit inference engine (AGENTS.md)
Treat legal data, personal data, repository secrets, and raw anonymization inputs as sensitive; never log or publish them unless intentionally public and minimal.
Files:
packages/anonymize/src/wasm.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Prefer explicit discriminator values throughout the stack; model mutually exclusive states with discriminated unions rather than boolean flags and optional payloads.
Useas constobjects or union types instead of TypeScript enums.
Avoid unnecessary casts and annotations; preserve compiler inference, avoid explicit generic arguments to inference-driven hooks, and fix type mismatches at their source.
Useas const satisfies Tfor large object-literal unions instead of a widening: Tannotation.
Use.at(0)when an element may be absent; use[0]only after existence is established or with a documented// SAFETY:invariant.
Prefer arrow functions, parameter destructuring when the intermediate value is not reused, and discriminated-union checks overinchecks when a discriminator exists.
Use options/args/params objects for three or more function arguments or interchangeable same-type arguments; reservePropsfor React component props.
Reuse library utility types, keep helper-local types near their helpers, and hoist noisy return types into nearby aliases.
Do not assign directly todocument.cookie.
Avoid spread syntax in loop accumulators; use.push()instead.
Never import test-only types into production code; use structural constraints when production code must accept test instances.
Keep language-dependent vocabulary and ambiguity rules in per-language reproducible data; never fix one language by unioning another language's words, and provide coverage matrices or explicit scope rationale for cross-language concepts.
Files:
packages/anonymize/src/wasm.ts
**/*.{ts,tsx,rs}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,rs}: Fail fast: validate at boundaries, return or throw early, minimize brace nesting, and use named constants for domain values instead of string literals.
Do not introduce unnecessary module-level side effects; split reusable utilities from side-effecting singletons and defer dependent initialization through lazy getters.
Prefer vertical end-to-end feature slices, preserve standard formats and self-hosting, batch operations, minimize round trips, and lazy-load aggressively.
Prepared-package schema versions describe payload schema only; represent compression and digest choices with explicit tagged fields, and prefer clean fail-closed breaks for unreleased formats.
Files:
packages/anonymize/src/wasm.ts
**/*.{rs,ts,py}
📄 CodeRabbit inference engine (AGENTS.md)
Keep binding layers thin; business logic belongs in the Rust core, while TypeScript, Python, WASM, and NAPI layers translate types and call shared logic.
Files:
packages/anonymize/src/wasm.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use oxlint with the ultracite preset and oxfmt; suppress a rule only with
// eslint-disable-next-line rule-name.
Files:
packages/anonymize/src/wasm.ts
**/*.{rs,ts}
📄 CodeRabbit inference engine (AGENTS.md)
Runtime parity must compare complete structural configuration, reject unknown DTO members except open language-keyed maps, assign every capability to a parity profile, and run each profile through all applicable runtimes.
Files:
packages/anonymize/src/wasm.ts
🔇 Additional comments (5)
packages/anonymize/src/wasm.ts (1)
128-128: LGTM!Also applies to: 164-167
packages/anonymize/scripts/smoke-wasm-compiled.mjs (1)
1-78: LGTM!Also applies to: 97-101
packages/anonymize/package.json (1)
95-95: LGTM!.github/workflows/ci.yml (1)
381-382: LGTM!.changeset/compiled-binary-asset-loading.md (1)
1-5: LGTM!
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f82a999d40
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
- The override rejects relative paths, keeps file: URLs as-is, and encodes path segments (pathToFileURL semantics without importing node:url, since this module also ships to browsers), so #, ?, and % stay path data. - The default asset base stays one verbatim expression and the Vite plugin anchors on its exact emitted text, re-pointing it at the emitted anchor asset; new URL(fileName, <anchor URL>) keeps the last-segment replacement behavior.
Summary
Inside a compiled single binary (
bun build --compile),import.meta.urlpoints into the binary's embedded filesystem and dynamicimport()resolves against it exclusively. The binding's asset URLs (glue module, wasm, prepared packages) derive fromimport.meta.url, so they can never reach assets installed on disk —getBinding()fails in compiled binaries even whendist/native/is copied next to the binary. Filesystem APIs do fall back to disk; ESMimport()does not, which is why only the glue import breaks.Changes
STLL_ANONYMIZE_ASSET_DIRoverrides the native-asset base directory (absolute POSIX path orfile:URL). Deployments that compile a consumer to a single binary copydist/native/to a real directory and point the variable at it. Browsers never defineprocess, so the override is inert there; the default resolution path is byte-for-byte unchanged.smoke-wasm-compiled.mjs(wired into CI next to the runtime-matrix smoke) compiles a minimal consumer of the builtwasm/dist/wasm.mjsand asserts both directions: without the override the engine load must fail — if it ever starts succeeding, the embedded-filesystem constraint changed and the guard demands re-evaluation — and with the override a default redaction resolves entities end to end, covering glue, wasm module, and the prepared pipeline package.Validation
Local run of the new smoke: the compiled consumer fails without the override and redacts with it (
{"event":"smoke-wasm-compiled","ok":true,"entities":2}). Package typecheck passes.Summary by CodeRabbit
New Features
STLL_ANONYMIZE_ASSET_DIR.Bug Fixes
Tests