grep ships as its own standalone WASM module (not part of the coreutils
multicall binary) and depends on the Oniguruma C library, so the website
workflow now checks out uutils/grep, installs the WASI SDK to provide a
wasm sysroot for the onig_sys C sources, builds grep.wasm, and appends
"grep" to the generated command list.
The terminal loads grep.wasm as an optional second module and dispatches
grep directly (argv[0] = "grep"). grep defaults to --color=never since the
WASI shim reports stdout as a TTY, which would otherwise emit match-
highlight escapes that corrupt piped output; explicit --color is honored.
Adds a grep emoji example and grep WASM integration tests.
Previously the list of WASM-bundled utilities was hardcoded in
wasm-terminal.js and playground.md, which drifted from the actual
feat_wasm feature in coreutils/Cargo.toml (e.g. dd, tty, yes were
missing). The website workflow now parses feat_wasm at build time
and emits static/wasm/commands.js, which the terminal prefers over
its built-in fallback list.
Emit a version.js alongside the WASM binary in CI recording the
coreutils commit used for the build, and display it under the
terminal with a link to the commit on GitHub.
Upstream coreutils-l10n updated the French translation of arch-about
from "Afficher l'architecture de la machine" to "Affiche l'architecture
de la machine", which was causing the WASM terminal test to fail in CI.
Remove the jsFallback function and its tests. Commands now require
the WASM binary to be loaded. If WASM is still loading, a "please
wait" message is shown instead of running JS approximations.
Prevent the browser from closing the tab when Ctrl+W is pressed
while the terminal is focused. Instead, handle it as the standard
terminal "delete previous word" action.
Parse < (stdin from file), > (stdout to file), and >> (append) in
the command line. Files are read from and written to the persistent
virtual filesystem, so redirected output persists across commands.
browser_wasi_shim's Filestat.write_bytes() uses setUint8 for the
1-byte filetype field at offset 16, leaving bytes 17-23 unwritten.
Since Rust allocates the stat buffer with MaybeUninit, those padding
bytes contain stack garbage that corrupts the struct.
Fix by replacing write_bytes with a version that writes filetype as
a full 8-byte BigUint64 (zero-extended), clearing the padding.
Also add a test asserting file sizes are reasonable.
Patch browser_wasi_shim File/Directory stat() to return current
timestamps instead of epoch 0 (which showed Jan 1 1970).
Patch path_filestat_get and path_open to resolve ".." at the
preopened root to "." instead of failing with NOTCAPABLE, matching
real filesystem behavior.
- Clone WASM response before compileStreaming so fallback doesn't re-fetch
- Guard against concurrent ensureRuntime() calls with a promise cache
- Replace inline onclick with event delegation for CSP compatibility
- Add SRI note for WASI shim dynamic import
- Skip l10n tests that require French translations in WASM binary
- Replace uninteresting fmt example with printf sheep | nl
- Hide Playground link from top navigation for now
- Browser-based unit tests (111 tests) covering parsing, builtins,
pipes, UTF-8, l10n, virtual filesystem, and WASM integration
- Headless Puppeteer test runner (scripts/run-tests.js)
- CI workflow step to build WASM and run tests
A browser-based terminal that runs real Rust coreutils compiled to
WebAssembly (wasm32-wasip1) using @bjorn3/browser_wasi_shim.
Features:
- xterm.js terminal with command history and line editing
- Pipe support (cmd1 | cmd2 | cmd3), file redirects (>)
- Persistent virtual filesystem across commands
- cd/pwd builtins with virtual working directory
- Locale support (locale builtin + selector)
- UTF-8/multibyte correct output (raw ConsoleStdout, fixed args_sizes_get)
- Click-to-run example buttons
- Inline wasm_example shortcode for blog posts