Skip to content

feat(p2-shim): add host-side write/read helpers for browser preopens - #2237

Merged
vados-cosmonic merged 1 commit into
bytecodealliance:mainfrom
eduardomourar:fix-browser-filesystem-write-file-at
Oct 13, 2026
Merged

vados-cosmonic merged 1 commit into
bytecodealliance:mainfrom
eduardomourar:fix-browser-filesystem-write-file-at

Conversation

@eduardomourar

@eduardomourar eduardomourar commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Hosts implementing shell-style redirection need to write bytes into a preopen's tree from JS without a guest, and had nothing adapter-agnostic to reach for — only the in-memory adapter's whole-tree _setFileData/_getFileData.

Changes

Adds two host-side filesystem helpers, built only on the public Descriptor interface so they work with any adapter:

  • writeFileAt(virtualPath, path, data, { append? }) — writes bytes into a preopen's tree, creating missing intermediate directories, truncating by default
  • readFileAt(virtualPath, path) — reads a file's full contents back out, in chunks

These are exposed from a new helpers/filesystem subpath export, keeping the convenience helpers separate from the shim's implementation and the underscore-prefixed configuration surface:

import { writeFileAt, readFileAt } from "@bytecodealliance/preview2-shim/helpers/filesystem";

The shared implementation lives in src/common/helpers/filesystem.ts (adapter-agnostic, preopens injected); thin per-build entries under src/browser/helpers/ and src/nodejs/helpers/ wire in each build's preopens so the import resolves under both the browser-default and node conditions.

The shared helper opens the file with write/read descriptor flags (the Node build maps empty flags to a read-only fd, so writes failed there), loops until every byte is written, and disposes the descriptors it opens. A Node test covers the node entry against a real host directory, alongside the browser in-memory tests. Both suites run concurrently: each test mounts its own preopen (a fresh in-memory tree in the browser, a fresh temp directory via fs/promises on Node) through a small helper and cleans up in a finally, so there are no beforeEach/afterEach hooks and no shared state between tests.

Documentation

The helpers are documented in the Jco book under the WASI support section, at Preview 2 shim → Filesystem helpers (docs/src/wasi/preview2-shim/helpers/filesystem.md). It covers which preopens the helpers see (the global set, not an isolated WASIShim's), each function, error behaviour, and a shell-style redirection example. The Preview 2 shim overview page gains a helpers/filesystem row in its subpath table and a Helpers bullet, and the package README's helper paragraph now mentions both helpers and links to both book pages.

Node consumers now get the Node typings

The . and ./* exports had a top-level types pointing at the browser .d.ts ahead of the node block. TypeScript under nodenext includes node in its condition set but stops at the first matching condition, so Node consumers were typed against the browser build (which is why _setPreopens appeared to reject host paths). The types entries are now nested under node and default with no top-level types key, which oxfmt's package.json sorting leaves alone. Verified with a consumer project: moduleResolution: nodenext resolves dist/nodejs/*.d.ts, moduleResolution: bundler resolves dist/browser/*.d.ts, and Node runtime resolution is unchanged. In-repo consumers pin the published 0.28.0 shim, so nothing else in the workspace changes until the next release.

@vados-cosmonic vados-cosmonic left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I really like the idea of having these helpers, but I think we need a different namespace for them. Up until now the helpers that have existed have been primarily to configure the p2-shim in some way that was necessary -- it's nice to have helper functions that make using WASI p2 (and p3) easier, but they may need to be in another package to be well contained.

I get that this should all be hopefully tree shaken away anyway, but I'd like to keep the intent of the underscore prefix helpers distinct.

Can we can add new export (...helpers/filesystem? ...helpers?) to preview2-shim and move the helper functions to a different file?

@eduardomourar
eduardomourar force-pushed the fix-browser-filesystem-write-file-at branch from 188de2c to 0d55149 Compare October 11, 2026 23:12
@eduardomourar

Copy link
Copy Markdown
Contributor Author

I completely agree with the approach. I pushed the helpers to a folder within the target platform. Those should be easy to migrate to a separate package whenever convenient.

@vados-cosmonic
vados-cosmonic force-pushed the fix-browser-filesystem-write-file-at branch 2 times, most recently from 5b6d9b2 to d773152 Compare October 13, 2026 14:57
@vados-cosmonic
vados-cosmonic force-pushed the fix-browser-filesystem-write-file-at branch from d773152 to b27f16d Compare October 13, 2026 14:59
vados-cosmonic
vados-cosmonic previously approved these changes Oct 13, 2026
@vados-cosmonic
vados-cosmonic force-pushed the fix-browser-filesystem-write-file-at branch 2 times, most recently from 6ef83ab to e22ab80 Compare October 13, 2026 15:55
@vados-cosmonic
vados-cosmonic force-pushed the fix-browser-filesystem-write-file-at branch 2 times, most recently from f15b0b7 to 924750c Compare October 13, 2026 16:19
@vados-cosmonic
vados-cosmonic force-pushed the fix-browser-filesystem-write-file-at branch from 924750c to b568751 Compare October 13, 2026 16:21
@vados-cosmonic
vados-cosmonic added this pull request to the merge queue Oct 13, 2026
Merged via the queue into bytecodealliance:main with commit 0bd2bed Oct 13, 2026
65 checks passed
@jco-release-bot

Copy link
Copy Markdown
Collaborator

🎉 The code in this PR was made available in the following release:
https://github.com/bytecodealliance/jco/releases/tag/preview2-shim-v0.29.0

@eduardomourar
eduardomourar deleted the fix-browser-filesystem-write-file-at branch October 13, 2026 18:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants