fix(core): resolve new URL() and wasm from on-disk source (#1455)#1464
Conversation
Deploying rstest with
|
| Latest commit: |
cc5cd9c
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://634b88c2.rstest.pages.dev |
| Branch Preview URL: | https://fix-core-wasm-url-loading.rstest.pages.dev |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a3e7464b4c
ℹ️ 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".
fc45e25 to
edb7c77
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: edb7c77aca
ℹ️ 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".
edb7c77 to
73fc3c4
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 73fc3c4e80
ℹ️ 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".
1a5cf59 to
383855e
Compare
59416a4 to
48e436c
Compare
`new URL('./file', import.meta.url)` was rewritten by rspack into a hashed
bundled asset path, which does not exist at runtime in the vm worker -> ENOENT.
Set `module.parser.javascript.url = false` so these expressions stay
source-relative, matching Node.js and Vitest.
Rework wasm handling on top of that: disable rspack's `webassembly/async` and
turn each `.wasm` into a self-contained JS module via a build-time loader that
reads its on-disk source bytes and instantiates them. This removes the
hardcoded string-replace of rspack's generated `async_wasm_loading` runtime
(`readFile(` -> `readWasmFile(`) and transparently supports import-bearing wasm
(wasm-bindgen `--target bundler`) by wiring an importObject from statically
imported glue modules. Wasm namespaces no longer carry a synthetic `default`,
matching Node's WebAssembly ESM namespace.
Claude-Session: https://claude.ai/code/session_01DWZvBGqkLP4X21iMa9Rhsq
48e436c to
cc5cd9c
Compare
Summary
new URL('./file', import.meta.url)was rewritten by rspack into a hashed bundled asset path, which the vm worker cannot find at runtime →ENOENT(#1455). Settingmodule.parser.javascript.url = falsekeeps these expressions source-relative, matching Node.js and Vitest.Building on that, this reworks how
.wasmis loaded. The old path leaned on rspack'swebassembly/asyncruntime and string-replaced the generated runtime code to redirect its byte read into rstest's in-memory bundle. That is now gone:experiments.asyncWebAssemblyis disabled and a build-time loader turns each.wasminto a self-contained JS module that reads its on-disk source and instantiates it. This also transparently supports import-bearing wasm (wasm-bindgen--target bundler, whosefoo_bg.wasm⇄foo_bg.jsglue is circular) by wiring an importObject from statically imported glue modules.Removed: hardcoded patch of rspack's generated runtime
The previous implementation reached into rspack's
async_wasm_loadingruntime module and string-replaced its source —readFile(→readWasmFile((import.meta.readWasmFile(for ESM) — so it could feed bytes from the in-memoryassetFilesinstead of disk:This was coupled to the exact text of rspack's Rust-generated runtime template and broke silently if that template changed. It is deleted, along with the paired
readWasmFileruntime callbacks, the in-memoryassetFileswasm path, and the now-dead base64 asset encoding / wasm-asset filtering inrsbuild.ts.wasm load branches — before / after
Before — one path, dependent on patching generated runtime code:
After — two explicit branches, no generated-code patching:
Each wasm import-module is wired only if it resolves through rspack's normal-module resolver, so relative, bare, and aliased glue specifiers all work uniformly. Synthetic host modules that do not resolve (emscripten
env,wasi_snapshot_preview1,GOT.*) are omitted from the importObject, so the build stays green; such a wasm only errors at runtime if it truly needs them — import the toolchain's JS glue instead (emscripten / wasm-bindgen--target web|nodejs).Why the generated module is safe to review
The loader emits code by string templating, so it is worth stating what bounds it:
WebAssembly.Module.imports/exports(...)and re-exports it; the on-disk.wasmbytes run unchanged. This non-invasiveness is exactly what makes the [Bug]: new URL('./file', import.meta.url) is rewritten to a bundled asset path, breaking runtime file resolution #1455 "run the source" guarantee hold. (Contrast: webpack's async-wasm rewrites the wasm's import section via@webassemblyjs/wasm-edit.)(wasm bytes, resolution results, resource path)— verified byte-identical across repeated runs.JSON.stringify; export names bind to positional locals (__rstest_wasm_0__ as "exp"), so wasm export names that are not valid JS identifiers cannot break the emitted syntax.A typical emitted module is small (glue import +
instantiate+ named re-exports); over a third ofwasmLoader.mjsis explanatory comments, not generating logic.Behavior notes
new URL(..., import.meta.url)now resolves against on-disk source for all asset types, not just wasm (the old rewrite was already broken at runtime, so this is a fix, not a regression). Theurl: falsedefault is placed before the user-config spread, so user overrides still win.default('default' in ns === false), matching Node's WebAssembly ESM namespace and Vitest.import init from './x.wasm'users should switch to named/namespace imports.url: falsekeepsnew URL(...)targets out of rspack's dependency graph, editing such a sibling asset in watch mode does not rerun the test that reads it. Wasm files, by contrast, stay in the graph (the loader emits a content-hash), so wasm byte edits do rerun.Related Links
Checklist
e2e/new-url— [Bug]: new URL('./file', import.meta.url) is rewritten to a bundled asset path, breaking runtime file resolution #1455 regression:new URL(..., import.meta.url)resolves a sibling on disk.e2e/wasm— named exports, no syntheticdefault, and the P2 runtimenew URL(...).hrefpath.e2e/wasm-imports— import-bearing wasm: circular wasm-bindgen-bundlershape links transparently; direct import resolves its importObject; non-resolvableenvbuilds and only LinkErrors at runtime; alias/bare specifier resolves its glue viathis.getResolve(); the glue the wasm links is the same instance the test holds (guards against a native auto-link "split-brain").https://claude.ai/code/session_01DWZvBGqkLP4X21iMa9Rhsq