Repository navigation
feat(ext/node): implement node:wasi - #34089
Merged
Merged
Conversation
Implements the `node:wasi` polyfill backed by Rust ops that talk directly to the host filesystem (the Deno permissions container still gates each path access with `OpenAccessKind`). The polyfill ships as a lazy-loaded IIFE script (`wasi.ts`) plus a thin synthetic ESM wrapper (`wasi_esm.ts`) — keeps node:wasi out of startup work for programs that never `import "node:wasi"`. Co-Authored-By: Divy Srivastava <[email protected]> Co-Authored-By: Kaju <[email protected]> Co-Authored-By: Bartek Iwańczuk <[email protected]> Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
bartlomieju
approved these changes
May 15, 2026
littledivy
added a commit
to crowlKats/deno
that referenced
this pull request
Jun 10, 2026
## Summary Implements the `node:wasi` polyfill, taking over [denoland#32413](denoland#32413). - Adds `ext/node/ops/wasi.rs`: a `WasiContext` cppgc object exposing the WASI preview1 ABI (args/env, clocks, random, fd_*, path_*, sched_yield) backed by `std::fs` + `std::io::stdin/stdout/stderr`. Path-based ops resolve against preopened directories and are gated by Deno's `PermissionsContainer` (`OpenAccessKind::Read|Write|ReadWrite`) on the canonicalized path, refusing to escape the preopen root. - Rewrites `ext/node/polyfills/wasi.ts` from a stub to a full `WASI` class (constructor option validation, `wasiImport`, `getImportObject`, `start`, `initialize`) that delegates to `WasiContext`. Cross-VM-context support uses `Object.prototype.toString` for `WebAssembly.Memory` checks. - Lazy loaded: `wasi.ts` is registered via `lazy_loaded_js`, fronted by the existing thin `wasi_esm.ts` synthetic-ESM wrapper. The Rust ops aren't reachable until something actually imports `node:wasi`. - Adds `ERR_WASI_NOT_STARTED` (Node parity). - Enables `wasi/test-wasi-options-validation.js`, `wasi/test-wasi-start-validation.js`, `wasi/test-wasi-initialize-validation.js` in the node_compat suite, and removes `wasi` from `IGNORED_TEST_DIRS` so they're discovered. - Adds `tests/unit_node/wasi_test.ts` with 14 cases covering the constructor, `getImportObject`, real WASM `start`/`initialize`, and the import-object surface area. Closes denoland#24289 Closes denoland#21025 Closes denoland/orchid#93 ## Notes - Other `tests/node_compat/runner/suite/test/wasi/*` tests aren't enabled because they go through `tests/node_compat/runner/suite/test/fixtures/wasi-preview-1.js`, which calls `common.expectWarning('ExperimentalWarning', ...)` for Node's WASI experimental warning. Deno doesn't emit that warning, so the fixture itself fails before the WASM runs. Enabling those tests is orthogonal to the WASI implementation and would require either a `expectWarning` shim or filtering at the fixture layer. - `poll_oneoff`, `sock_*`, `proc_raise`, `path_filestat_set_times`, `fd_filestat_set_times` return `ERRNO_NOSYS` — sufficient for the validation tests and the WASI interface surface, can be implemented incrementally as compat tests get enabled. ## Test plan - [x] `cargo test unit_node::wasi_test` — 14 tests pass - [x] `cargo test --test node_compat -- wasi-options-validation` — pass - [x] `cargo test --test node_compat -- wasi-start-validation` — pass - [x] `cargo test --test node_compat -- wasi-initialize-validation` — pass - [x] `./x lint` — clean - [x] `./x fmt` — clean Co-authored-by: divybot <[email protected]> Co-authored-by: Divy Srivastava <[email protected]> Co-authored-by: Kaju <[email protected]> Co-authored-by: Bartek Iwańczuk <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements the
node:wasipolyfill, taking over #32413.ext/node/ops/wasi.rs: aWasiContextcppgc object exposing the WASI preview1 ABI (args/env, clocks, random, fd_, path_, sched_yield) backed bystd::fs+std::io::stdin/stdout/stderr. Path-based ops resolve against preopened directories and are gated by Deno'sPermissionsContainer(OpenAccessKind::Read|Write|ReadWrite) on the canonicalized path, refusing to escape the preopen root.ext/node/polyfills/wasi.tsfrom a stub to a fullWASIclass (constructor option validation,wasiImport,getImportObject,start,initialize) that delegates toWasiContext. Cross-VM-context support usesObject.prototype.toStringforWebAssembly.Memorychecks.wasi.tsis registered vialazy_loaded_js, fronted by the existing thinwasi_esm.tssynthetic-ESM wrapper. The Rust ops aren't reachable until something actually importsnode:wasi.ERR_WASI_NOT_STARTED(Node parity).wasi/test-wasi-options-validation.js,wasi/test-wasi-start-validation.js,wasi/test-wasi-initialize-validation.jsin the node_compat suite, and removeswasifromIGNORED_TEST_DIRSso they're discovered.tests/unit_node/wasi_test.tswith 14 cases covering the constructor,getImportObject, real WASMstart/initialize, and the import-object surface area.Closes #24289
Closes #21025
Closes denoland/orchid#93
Notes
tests/node_compat/runner/suite/test/wasi/*tests aren't enabled because they go throughtests/node_compat/runner/suite/test/fixtures/wasi-preview-1.js, which callscommon.expectWarning('ExperimentalWarning', ...)for Node's WASI experimental warning. Deno doesn't emit that warning, so the fixture itself fails before the WASM runs. Enabling those tests is orthogonal to the WASI implementation and would require either aexpectWarningshim or filtering at the fixture layer.poll_oneoff,sock_*,proc_raise,path_filestat_set_times,fd_filestat_set_timesreturnERRNO_NOSYS— sufficient for the validation tests and the WASI interface surface, can be implemented incrementally as compat tests get enabled.Test plan
cargo test unit_node::wasi_test— 14 tests passcargo test --test node_compat -- wasi-options-validation— passcargo test --test node_compat -- wasi-start-validation— passcargo test --test node_compat -- wasi-initialize-validation— pass./x lint— clean./x fmt— clean🤖 Generated with Claude Code