wasm-idle 1.1.0 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +140 -37
- package/dist/playground/assetBridge.js +106 -31
- package/dist/playground/assets.d.ts +2 -2
- package/dist/playground/c3.js +22 -0
- package/dist/playground/c3Memory.d.ts +19 -0
- package/dist/playground/c3Memory.js +117 -0
- package/dist/playground/cachedClang.js +143 -34
- package/dist/playground/clangAssetIntegrity.js +6 -6
- package/dist/playground/clangWorkerProtocol.d.ts +12 -1
- package/dist/playground/cobol.d.ts +3 -0
- package/dist/playground/cobol.js +10 -1
- package/dist/playground/commonlispAssets.d.ts +2 -2
- package/dist/playground/compiledArtifactCache.d.ts +3 -1
- package/dist/playground/compiledArtifactCache.js +31 -5
- package/dist/playground/container/ContainerExplorer.svelte +307 -0
- package/dist/playground/container/ContainerExplorer.svelte.d.ts +14 -0
- package/dist/playground/container/binding.d.ts +26 -0
- package/dist/playground/container/binding.js +247 -0
- package/dist/playground/container/clang-runtime.d.ts +38 -0
- package/dist/playground/container/clang-runtime.js +343 -0
- package/dist/playground/container/client.d.ts +15 -0
- package/dist/playground/container/client.js +189 -0
- package/dist/playground/container/explorer.d.ts +31 -0
- package/dist/playground/container/explorer.js +112 -0
- package/dist/playground/container/owner.worker.js +390 -0
- package/dist/playground/container/protocol.d.ts +73 -0
- package/dist/playground/container/protocol.js +28 -0
- package/dist/playground/container/release.d.ts +31 -0
- package/dist/playground/container/release.js +612 -0
- package/dist/playground/container/runtime-adapter.d.ts +73 -0
- package/dist/playground/container/runtime-adapter.js +474 -0
- package/dist/playground/container/shell-control.d.ts +49 -0
- package/dist/playground/container/shell-control.js +303 -0
- package/dist/playground/container/workspace.d.ts +8 -0
- package/dist/playground/container/workspace.js +29 -0
- package/dist/playground/d.d.ts +6 -1
- package/dist/playground/d.js +83 -5
- package/dist/playground/dotnet.js +6 -8
- package/dist/playground/fortran.d.ts +3 -0
- package/dist/playground/fortran.js +10 -1
- package/dist/playground/go.js +14 -3
- package/dist/playground/goDebugInstrumentation.js +184 -54
- package/dist/playground/java.js +3 -2
- package/dist/playground/javaRuntimeErrors.d.ts +9 -0
- package/dist/playground/javaRuntimeErrors.js +60 -0
- package/dist/playground/lean4Assets.d.ts +4 -4
- package/dist/playground/lfortran.js +10 -0
- package/dist/playground/lfortranAssets.d.ts +2 -2
- package/dist/playground/nim.js +22 -0
- package/dist/playground/objectivec.d.ts +3 -0
- package/dist/playground/objectivec.js +11 -2
- package/dist/playground/options.d.ts +2 -0
- package/dist/playground/python.js +8 -0
- package/dist/playground/runtimeAssetCache.d.ts +1 -32
- package/dist/playground/runtimeAssetCache.js +1 -193
- package/dist/playground/runtimeSession.d.ts +2 -2
- package/dist/playground/runtimeSession.js +11 -11
- package/dist/playground/rust.d.ts +6 -0
- package/dist/playground/rust.js +103 -6
- package/dist/playground/staticStdinRing.d.ts +2 -1
- package/dist/playground/staticStdinRing.js +21 -10
- package/dist/playground/staticWorkerRuntime.d.ts +15 -1
- package/dist/playground/staticWorkerRuntime.js +119 -17
- package/dist/playground/tinygo.d.ts +3 -0
- package/dist/playground/tinygo.js +81 -6
- package/dist/playground/v.d.ts +3 -0
- package/dist/playground/v.js +10 -1
- package/dist/playground/wasmAwkVersion.d.ts +13 -13
- package/dist/playground/wasmAwkVersion.js +4 -4
- package/dist/playground/wasmBqnVersion.d.ts +2 -2
- package/dist/playground/wasmBqnVersion.js +2 -2
- package/dist/playground/wasmC3Version.d.ts +2 -2
- package/dist/playground/wasmC3Version.js +2 -2
- package/dist/playground/wasmClojureScriptVersion.d.ts +2 -2
- package/dist/playground/wasmClojureScriptVersion.js +2 -2
- package/dist/playground/wasmCommonLispVersion.d.ts +2 -2
- package/dist/playground/wasmCommonLispVersion.js +2 -2
- package/dist/playground/wasmDIntegrity.d.ts +5 -5
- package/dist/playground/wasmDIntegrity.js +5 -5
- package/dist/playground/wasmDVersion.d.ts +16 -1
- package/dist/playground/wasmDVersion.js +16 -1
- package/dist/playground/wasmDebugVersion.d.ts +1 -1
- package/dist/playground/wasmDebugVersion.js +1 -1
- package/dist/playground/wasmForthVersion.d.ts +2 -2
- package/dist/playground/wasmForthVersion.js +2 -2
- package/dist/playground/wasmGleamVersion.d.ts +2 -2
- package/dist/playground/wasmGleamVersion.js +2 -2
- package/dist/playground/wasmGrainVersion.d.ts +2 -2
- package/dist/playground/wasmGrainVersion.js +2 -2
- package/dist/playground/wasmJVersion.d.ts +2 -2
- package/dist/playground/wasmJVersion.js +2 -2
- package/dist/playground/wasmJanetVersion.js +2 -2
- package/dist/playground/wasmJuliaVersion.js +2 -2
- package/dist/playground/wasmLean4Version.d.ts +5 -5
- package/dist/playground/wasmLean4Version.js +5 -5
- package/dist/playground/wasmLfortranVersion.d.ts +2 -2
- package/dist/playground/wasmLfortranVersion.js +2 -2
- package/dist/playground/wasmNimVersion.d.ts +9 -9
- package/dist/playground/wasmNimVersion.js +6 -6
- package/dist/playground/wasmOcamlVersion.d.ts +2 -2
- package/dist/playground/wasmOcamlVersion.js +1 -1
- package/dist/playground/wasmPascalVersion.js +2 -2
- package/dist/playground/wasmPerlVersion.js +2 -2
- package/dist/playground/wasmPrologVersion.d.ts +2 -2
- package/dist/playground/wasmPrologVersion.js +2 -2
- package/dist/playground/wasmReScriptVersion.d.ts +2 -2
- package/dist/playground/wasmReScriptVersion.js +2 -2
- package/dist/playground/wasmRustVersion.d.ts +8 -8
- package/dist/playground/wasmRustVersion.js +7 -7
- package/dist/playground/wasmTclVersion.d.ts +4 -4
- package/dist/playground/wasmTclVersion.js +2 -2
- package/dist/playground/wasmTinyGoVersion.d.ts +14 -14
- package/dist/playground/wasmTinyGoVersion.js +14 -14
- package/dist/playground/wasmTypeScriptVersion.d.ts +5 -5
- package/dist/playground/wasmTypeScriptVersion.js +5 -5
- package/dist/playground/worker/cachedClangCompile.js +52 -4
- package/dist/playground/worker/cachedClangExecute.js +6 -5
- package/dist/playground/worker/clang.js +32 -10
- package/dist/playground/worker/cobol.js +2 -2
- package/dist/playground/worker/d.js +12 -5
- package/dist/playground/worker/fortran.js +2 -2
- package/dist/playground/worker/go.js +16 -5
- package/dist/playground/worker/haskell.js +10 -7
- package/dist/playground/worker/java.js +75 -10
- package/dist/playground/worker/lua.js +2 -3
- package/dist/playground/worker/php.js +15 -9
- package/dist/playground/worker/python.js +46 -9
- package/dist/playground/worker/pythonExecution.js +17 -1
- package/dist/playground/worker/pythonWorkspaceFiles.d.ts +6 -0
- package/dist/playground/worker/pythonWorkspaceFiles.js +26 -0
- package/dist/playground/worker/pythonWorkspaceImports.d.ts +4 -0
- package/dist/playground/worker/pythonWorkspaceImports.js +129 -0
- package/dist/playground/worker/r.js +13 -6
- package/dist/playground/worker/rust.js +34 -2
- package/dist/playground/worker/sqlite.js +4 -3
- package/dist/playground/worker/tinygo.js +11 -3
- package/dist/playground/worker/typescript.js +2 -3
- package/dist/playground/worker/v.js +2 -2
- package/dist/playground/worker/wat.js +2 -3
- package/dist/playground/worker/zig.js +20 -6
- package/dist/playground/workerSession.d.ts +1 -28
- package/dist/playground/workerSession.js +1 -164
- package/package.json +20 -13
- package/dist/playground/worker/python.runtime.cases.js +0 -374
- /package/dist/playground/{worker/python.runtime.cases.d.ts → container/owner.worker.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -25,6 +25,33 @@ Verified downloads can be retained across reloads using a version-pinned, capaci
|
|
|
25
25
|
CacheStorage/IndexedDB cache. See [persistent asset cache configuration and coverage](docs/runtime-asset-cache.md)
|
|
26
26
|
for global/per-call opt-out, cleanup and prefetch APIs.
|
|
27
27
|
|
|
28
|
+
## Getting started
|
|
29
|
+
|
|
30
|
+
You need Node.js `^22.22.2`, `^24.15.0`, or `>=26.0.0`, and pnpm 12.9.1. These come from the root
|
|
31
|
+
`package.json` `engines` and `packageManager` fields, and `.npmrc` sets `engine-strict=true`.
|
|
32
|
+
`.tool-versions` pins Node.js 24.20.0 for asdf/mise.
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pnpm install
|
|
36
|
+
pnpm dev
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
`pnpm dev` builds the public workspace packages, then starts Vite with the cross-origin isolation
|
|
40
|
+
headers that `SharedArrayBuffer` requires. The app is served under the `/wasm-idle` base path, for
|
|
41
|
+
example `http://localhost:5173/wasm-idle/`.
|
|
42
|
+
|
|
43
|
+
Most runtime assets are checked in under `static/`. Some compiler payloads are gitignored and must
|
|
44
|
+
be prepared locally before those languages can run:
|
|
45
|
+
|
|
46
|
+
- `pnpm run prepare:test-assets` downloads the pinned Clang (with its matching clangd), OCaml,
|
|
47
|
+
C3, LFortran, Lean 4, and Common Lisp payloads. Pass group names, for example
|
|
48
|
+
`-- clang ocaml`, to prepare only some of them.
|
|
49
|
+
- `pnpm run prepare:wasm-debug-release` adds the LLDB debug runtime. Without it, C, C++, and
|
|
50
|
+
`wasm32-wasip1` Rust debug sessions use the trace fallback.
|
|
51
|
+
|
|
52
|
+
Other runtimes are refreshed from their producers with the `sync:*` scripts described under
|
|
53
|
+
[Monorepo layout](#monorepo-layout).
|
|
54
|
+
|
|
28
55
|
## Language support policy
|
|
29
56
|
|
|
30
57
|
wasm-idle language support must run user code through the real language implementation in the
|
|
@@ -218,6 +245,7 @@ multi-module guests, and Rust WASI Preview 2/3 debugging remain outside the supp
|
|
|
218
245
|
|
|
219
246
|
```sh
|
|
220
247
|
cd ../wasm-llvm
|
|
248
|
+
WASM_LLVM_CLANG_ARTIFACT_DIR=/path/to/verified-clang-artifacts \
|
|
221
249
|
WASM_LLVM_LLDB_ARTIFACT_DIR=/path/to/lldb-artifacts \
|
|
222
250
|
WASM_LLVM_WAMR_ARTIFACT_DIR=/path/to/wamr-artifacts \
|
|
223
251
|
pnpm prepare:clang-release
|
|
@@ -227,9 +255,16 @@ WASM_RUST_PRODUCER_OUTPUT_ROOT=/path/to/rust-producer-output \
|
|
|
227
255
|
pnpm --dir runtimes/wasm-rust build:producer
|
|
228
256
|
pnpm sync:wasm-rust
|
|
229
257
|
pnpm sync:wasm-debug ../wasm-llvm/out/clang-browser
|
|
230
|
-
|
|
258
|
+
pnpm test:browser:debug:lldb
|
|
231
259
|
```
|
|
232
260
|
|
|
261
|
+
The Clang artifact directory must contain the verified build receipt and its matching raw-input
|
|
262
|
+
identities. The producer rejects historical artifacts without that evidence when assembling a new
|
|
263
|
+
release. For the already reviewed bundled debugger, use `pnpm prepare:wasm-debug-release` in
|
|
264
|
+
`wasm-idle` to install the immutable release selected by the tracked profile.
|
|
265
|
+
The browser command uses the qualified preview path; development-server LLDB qualification is
|
|
266
|
+
tracked separately.
|
|
267
|
+
|
|
233
268
|
The synchronized manifest rejects missing hashes, incompatible Clang/LLDB revisions, and stale
|
|
234
269
|
worker sidecars. The strict browser test covers real C, C++, and Rust breakpoint, step, output, and
|
|
235
270
|
termination paths and rejects trace fallback or a missing debug asset. The Rust producer build is
|
|
@@ -257,10 +292,10 @@ variables or import SvelteKit modules.
|
|
|
257
292
|
| Malbolge<br>`MALBOLGE` | Original Ben Olmstead interpreter, TryItOnline/malbolge b0869870 (public domain), compiled with WASI SDK 33 | Runs the original 59049-cell ternary and self-modifying interpreter; source-file input is separate from byte stdin/stdout; EOF stores 59048; requires at least two non-whitespace source bytes | `runtimeAssets.rootUrl`, `stdin`, `activePath`, `workspaceFiles`; fixed interpreter argv; prepare compiles the runtime without executing or validating the source |
|
|
258
293
|
| Whitespace<br>`WHITESPACE` | koturn/Whitespace 22a57aab (MIT), compiled with WASI SDK 33 | Runs the upstream Whitespace 0.3 interpreter with a documented divisor-guard correction, copy/slide, heap, labels, calls and signed 32-bit integers; character/numeric stdin and exact stdout; character EOF is -1; source limit 65535 UTF-8 bytes | `runtimeAssets.rootUrl`, `stdin`, `activePath`, `workspaceFiles`; fixed interpreter argv; prepare compiles the runtime without executing or validating the source |
|
|
259
294
|
| C3<br>`C3` | wasm-llvm/c3-browser: C3 0.8.3 / LLVM 22.1.8 | Verified c3c and builtin LLD compile real C3 in a fresh browser Worker; UTF-8 env.readByte/env.writeByte ABI and exported main; std::io and WASI unavailable | `runtimeAssets.c3.baseUrl`, `stdin`, `activePath`, `workspaceFiles`; fixed compiler flags and bounded Wasm memories |
|
|
260
|
-
| C<br>`C` | @wasm-idle/llvm-core@1.
|
|
261
|
-
| C++<br>`CPP` | @wasm-idle/llvm-core@1.
|
|
262
|
-
| Objective-C<br>`OBJC` | GNUstep libobjc2 v2.3 assets from the `wasm-llvm` producer + @wasm-idle/llvm-core@1.
|
|
263
|
-
| Objective-C++<br>`OBJECTIVECXX` | Same GNUstep libobjc2 v2.3 + libc++ assets as Objective-C from the `wasm-llvm` producer + @wasm-idle/llvm-core@1.
|
|
295
|
+
| C<br>`C` | @wasm-idle/llvm-core@1.0.11 / Clang 22.1.8 WASI sysroot from the `wasm-llvm` producer | `clang` for `wasm32-wasi`; default `-std=gnu11`; LLDB mode compiles untouched source with embedded DWARF at `-g -O0` and runs it in WAMR; normal runs still use the browser WASI host; supports `stdin` and `programArgs` | `runtimeAssets.clang.baseUrl`/`loader` or `rootUrl`; `compileArgs`, `programArgs`, `cVersion`, `activePath`, `workspaceFiles`, `debugMode`, `breakpoints`, `pauseOnEntry` |
|
|
296
|
+
| C++<br>`CPP` | @wasm-idle/llvm-core@1.0.11 / Clang 22.1.8 WASI sysroot from the `wasm-llvm` producer | `clang++` for `wasm32-wasi`; default `-std=gnu++20`; LLDB mode compiles untouched source with embedded DWARF at `-g -O0` and runs it in WAMR; normal runs still use the browser WASI host; supports `stdin` and `programArgs` | `runtimeAssets.clang.baseUrl`/`loader` or `rootUrl`; `compileArgs`, `programArgs`, `cppVersion`, `activePath`, `workspaceFiles`, `debugMode`, `breakpoints`, `pauseOnEntry` |
|
|
297
|
+
| Objective-C<br>`OBJC` | GNUstep libobjc2 v2.3 assets from the `wasm-llvm` producer + @wasm-idle/llvm-core@1.0.11 | `clang -x objective-c -fobjc-runtime=gnustep-2.0 -fblocks` for `wasm32-wasi`; links `libobjc.a`, `libgnustep-base.a`, and `libffi.a` when Foundation is imported; Foundation headers are inlined from `foundation-headers.json`; includes a constructor wrapper for Objective-C class registration; auto-compiles `.m`/`.mm`/`.c` workspace files; trace debug instruments active source and uses wasm-idle controls; supports `stdin` and `programArgs`; large Objective-C assets may be served as gzip-only `.gz` files through the service worker or worker fallback | `runtimeAssets.objectivec.baseUrl`/`libobjcUrl`/`headersUrl`/`libgnustepBaseUrl`/`libgnustepBaseObjectUrl`/`foundationHeadersUrl`/`libffiUrl` or `PUBLIC_WASM_OBJECTIVEC_*`; `runtimeAssets.clang.baseUrl`/`loader` for the clang toolchain; `activePath`, `workspaceFiles`, `compileArgs`, `debug`, `breakpoints`, `pauseOnEntry` |
|
|
298
|
+
| Objective-C++<br>`OBJECTIVECXX` | Same GNUstep libobjc2 v2.3 + libc++ assets as Objective-C from the `wasm-llvm` producer + @wasm-idle/llvm-core@1.0.11; no extra compiler assets | `clang -x objective-c++ -std=gnu++20 -fobjc-runtime=gnustep-2.0 -fblocks` for `wasm32-wasi` with libc++ headers; active file defaults to `main.mm`; links `libobjc.a` (plus GNUstep Base and `libffi.a` when Foundation is imported); auto-compiles `.mm`/`.m`/`.c` workspace files; supports `stdin` and `programArgs`; trace debugging is not supported | Shares `runtimeAssets.objectivec` and `runtimeAssets.clang` with Objective-C; `activePath`, `workspaceFiles`, `compileArgs`, `programArgs` |
|
|
264
299
|
| Python<br>`PYTHON3` | static ESM `static/pyodide/pyodide.mjs` / pyodide@314.0.7 | loads `pyodide.mjs`, `pyodide.asm.mjs`, `pyodide.asm.wasm`, and `python_stdlib.zip` from the configured static asset tree on demand; supports `stdin`, workspace files, and trace debugging | `runtimeAssets.python.baseUrl`/`loader` or `rootUrl`; `stdin`, `activePath`, `workspaceFiles`, `debug`, `breakpoints`, `pauseOnEntry`, `debugPath` |
|
|
265
300
|
| Befunge-93<br>`BEFUNGE93` | catseye/Befunge-93 8fe4065c (BSD-3-Clause), compiled with WASI SDK 33 | Runs the original interpreter with an 80 by 25 wrapping playfield, signed 32-bit stack, string mode and self-modifying p/g instructions; character and integer stdin share the WASI terminal; character EOF is -1 | `runtimeAssets.rootUrl`, `stdin`, `activePath`, `workspaceFiles`; fixed quiet argv; prepare compiles the runtime without executing or validating the source |
|
|
266
301
|
| Brainfuck<br>`BRAINFUCK` | susam/bfc b1b92fc (MIT), compiled with WASI SDK 33 | Runs the pinned upstream interpreter in a browser Worker with a fresh read-only source filesystem; 30000 wrapping 8-bit cells, UTF-8 byte stdin/stdout, EOF sets the cell to zero | `runtimeAssets.rootUrl`, `stdin`, `activePath`, `workspaceFiles`; fixed interpreter argv; prepare compiles the runtime without executing or validating the source |
|
|
@@ -306,9 +341,9 @@ variables or import SvelteKit modules.
|
|
|
306
341
|
| Haskell<br>`HASKELL` | ghc-in-browser / GHC 9.14.0.20251031 WASI rootfs | loads `dyld.mjs`, `rootfs.tar.zst`, `bsdtar.wasm`; `compileArgs` become GHC args, otherwise legacy `args` become GHC args | `runtimeAssets.haskell.moduleUrl`/`rootfsUrl`/`bsdtarUrl`; `mainSoPath`, `searchDirs`, `activePath`, `workspaceFiles` |
|
|
307
342
|
| LFortran<br>`LFORTRAN` | receipt-pinned `wasm-llvm/producer/lfortran-browser` artifacts in `static/wasm-lfortran` | real LFortran 0.65.0-97-gab867a23 LLVM evaluator compiles and executes Emscripten side modules in a fresh Worker; shared-ring stdin supports delayed READ and EOF; experimental Fortran feature coverage | `runtimeAssets.lfortran.baseUrl` relocates the reviewed bundle; `stdin`, `activePath`, workspace data/include files, cancellation and execution limits; no program arguments or multi-file module build orchestration |
|
|
308
343
|
| Lean 4<br>`LEAN4` | receipt-pinned `wasm-llvm/producer/lean-browser` release downloaded from its immutable commit into `static/wasm-lean4` | real Lean 4.34.1 frontend and IR interpreter (`lean --run`) built for wasm32 Emscripten with pthreads; imports a wasm32 `Init` library compiled by that build; shared-ring stdin supports interactive `getLine` and EOF | `runtimeAssets.lean4.baseUrl` relocates the reviewed bundle; `stdin`, program arguments, `activePath`, cancellation and execution limits; single-file programs importing `Init` only (no `Std`/`Lean` imports or Lake packages) |
|
|
309
|
-
| Fortran<br>`FORTRAN` | Netlib f2c 2022-09-09 + `@cowasm/f2c 1.0.0` libf2c + @wasm-idle/llvm-core@1.
|
|
310
|
-
| COBOL<br>`COBOL` | GnuCOBOL 3.2 + GMP 6.3.0 assets from the `wasm-llvm` producer + @wasm-idle/llvm-core@1.
|
|
311
|
-
| V<br>`V` | V 0.5.2 compiler, vlib and WASI C sysroot assets from the `wasm-llvm` producer + @wasm-idle/llvm-core@1.
|
|
344
|
+
| Fortran<br>`FORTRAN` | Netlib f2c 2022-09-09 + `@cowasm/f2c 1.0.0` libf2c + @wasm-idle/llvm-core@1.0.11 | runs `f2c.wasm` in WASI, compiles generated C with the llvm-core Clang host, links `libf2c.a`, then executes the resulting WASI module with `stdin` and `programArgs` | `runtimeAssets.fortran.baseUrl`/`f2cWasmUrl`/`libf2cUrl`/`f2cHeaderUrl`/`analyzerUrl` or `PUBLIC_WASM_FORTRAN_*`; `runtimeAssets.clang.baseUrl`/`loader` for the C backend; `activePath`, `workspaceFiles`, `compileArgs` |
|
|
345
|
+
| COBOL<br>`COBOL` | GnuCOBOL 3.2 + GMP 6.3.0 assets from the `wasm-llvm` producer + @wasm-idle/llvm-core@1.0.11 | native gzip delivery for the frontend Wasm and filesystem tar assets; translates free-format COBOL with the real GnuCOBOL `cobc` frontend, compiles the generated C with the llvm-core Clang host, links libcob/GMP, and executes the resulting WASI module with `stdin` and `programArgs` | `runtimeAssets.cobol.baseUrl` or `PUBLIC_WASM_COBOL_BASE_URL`; `runtimeAssets.clang.baseUrl`/`loader` for the C backend; `activePath`, `workspaceFiles`, `compileArgs` |
|
|
346
|
+
| V<br>`V` | V 0.5.2 compiler, vlib and WASI C sysroot assets from the `wasm-llvm` producer + @wasm-idle/llvm-core@1.0.11 | native gzip delivery for the compiler Wasm and filesystem tar assets; translates V to C with the real V compiler (built from the upstream `vc` bootstrap for WASI), compiles the generated C with the llvm-core Clang host, and executes the resulting WASI module with `stdin` and `programArgs` | `runtimeAssets.v.baseUrl` or `PUBLIC_WASM_V_BASE_URL`; `runtimeAssets.clang.baseUrl`/`loader` for the C backend; `activePath`, `workspaceFiles`, `compileArgs` |
|
|
312
347
|
| R<br>`R` | versioned static `static/webr/<hash>/webr.js` / webr@0.6.0 | loads the browser ESM entry `webr.js` and its WebR runtime files from the configured static asset tree on demand; supports `stdin`, `programArgs`, and workspace files | `runtimeAssets.r.baseUrl` or `PUBLIC_WASM_R_BASE_URL`; `stdin`, `programArgs`, `activePath`, `workspaceFiles` |
|
|
313
348
|
| Octave<br>`OCTAVE` | Octave 10.3.0 (octave-10.3.0-pl5321h996e327_3.tar.bz2) | Octave CLI Emscripten worker; supports `stdin` and `programArgs` | `runtimeAssets.octave.baseUrl`/`workerUrl`/`manifestUrl` or `PUBLIC_WASM_OCTAVE_*` |
|
|
314
349
|
| DuckDB<br>`DUCKDB` | static ESM `static/wasm-duckdb/runtime.mjs` produced from @duckdb/duckdb-wasm@1.33.1-dev57.0 | selects the best DuckDB-Wasm MVP/EH bundle on demand and creates a fresh in-memory database per run; `stdin` is registered as `stdin.txt` and `/dev/stdin` rather than terminal stdin | `runtimeAssets.duckdb.moduleUrl` or `PUBLIC_WASM_DUCKDB_MODULE_URL` or `rootUrl`; `stdin`, `activePath`, `workspaceFiles` |
|
|
@@ -353,19 +388,25 @@ toolchains can be consumed from pinned external runtime repositories:
|
|
|
353
388
|
- `packages/react`: React hooks around `@wasm-idle/core`.
|
|
354
389
|
- `packages/vue`: Vue composables around `@wasm-idle/core`.
|
|
355
390
|
- `packages/node`: Node.js host helpers for Node-capable sandbox loaders.
|
|
356
|
-
- `runtimes/*`: imported runtime/compiler packages
|
|
357
|
-
`wasm-
|
|
358
|
-
`wasm-
|
|
359
|
-
`
|
|
360
|
-
|
|
391
|
+
- `runtimes/*`: imported runtime/compiler packages `wasm-rust`, `wasm-of-js-of-ocaml`, `wasm-go`,
|
|
392
|
+
`wasm-d`, `wasm-dotnet`, `wasm-typescript`, `wasm-wat`, `wasm-lua`, `wasm-lisp`, `wasm-elixir`,
|
|
393
|
+
`wasm-awk`, `wasm-bash`, `wasm-clojurescript`, `pyodide`, `teavm`, `ruby`, `r`, and
|
|
394
|
+
`js-sandbox`. `wasm-pascal` holds the pas2js compiler wrapper sources and is not a workspace
|
|
395
|
+
package.
|
|
396
|
+
- `runtimes/esolangs`: pinned upstream interpreter sources and licenses for the esoteric
|
|
397
|
+
languages. `pnpm build:esolangs` and the Aheui, APECode, and GolfScript sync scripts turn them
|
|
398
|
+
into `static/wasm-<language>/` assets.
|
|
361
399
|
- `runtimes/wasm-tinygo`: the public `TINYGO` browser compiler consumer plus an explicitly labeled
|
|
362
400
|
legacy AST-to-C development harness. Static releases publish only the receipt-verified upstream
|
|
363
401
|
consumer and its source-pinned toolchain assets.
|
|
402
|
+
- `runtimes/wasm-kotlin` and `runtimes/wasm-scala`: internal compiler candidates. They are not
|
|
403
|
+
registered playground languages or workspace packages.
|
|
364
404
|
- `producers/wasm-php`: standalone, locked producer for the checked-in PHP 8.4 page asset. It is
|
|
365
405
|
outside the root workspace and is never published as an npm package.
|
|
366
|
-
- `static/wasm-zig`, `static/wasm-haskell`, `static/wasm-julia`,
|
|
367
|
-
|
|
368
|
-
|
|
406
|
+
- `static/wasm-zig`, `static/wasm-haskell`, `static/wasm-julia`, `static/wasm-nim`,
|
|
407
|
+
`static/wasm-tcl`, `static/wasm-forth`, `static/wasm-j`, `static/wasm-bqn`, and
|
|
408
|
+
`static/wasm-janet`: bundled browser runtime and compiler assets synced from upstream asset
|
|
409
|
+
builds rather than local workspace packages.
|
|
369
410
|
|
|
370
411
|
Deployment builds retain both legacy `.gz` and canonical `.gz.bin` URLs by default.
|
|
371
412
|
After building and compressing the page, `pnpm run compact:build-runtimes` reports
|
|
@@ -388,9 +429,24 @@ pnpm sync:runtime list
|
|
|
388
429
|
pnpm sync:runtimes
|
|
389
430
|
```
|
|
390
431
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
432
|
+
`pnpm sync:runtime list` prints every runtime the wrapper knows. It marks `manual` runtimes, which
|
|
433
|
+
`pnpm sync:runtimes` skips unless `--include-manual` is passed, and `source-required` runtimes,
|
|
434
|
+
which need an explicit source directory and never run from `sync:runtimes`.
|
|
435
|
+
|
|
436
|
+
Default sources differ by runtime:
|
|
437
|
+
|
|
438
|
+
- Runtimes with sources under `runtimes/`, such as `wasm-go`, `wasm-d`, `wasm-dotnet`,
|
|
439
|
+
`wasm-lua`, `wasm-wat`, `wasm-typescript`, `wasm-lisp`, `wasm-awk`, `wasm-pascal`, and
|
|
440
|
+
`wasm-bash`, read `runtimes/<name>/dist`.
|
|
441
|
+
- Some read an installed npm package, such as `webr` or `swipl-wasm`.
|
|
442
|
+
- Some download a pinned upstream release, such as Tcl, Perl, and Octave.
|
|
443
|
+
- Julia and Nim re-verify the checked-in assets and download their pinned release only when those
|
|
444
|
+
assets are missing.
|
|
445
|
+
- J, BQN, and Janet prefer a sibling checkout and otherwise reuse the checked-in assets.
|
|
446
|
+
- Rust, TinyGo, and ClojureScript re-verify and redeploy the checked-in `static/` snapshot.
|
|
447
|
+
|
|
448
|
+
The optional `[sourceDir] [targetDir]` arguments override these defaults. `sync:wasm-php` is not
|
|
449
|
+
part of the wrapper; it consumes `producers/wasm-php/dist` or `WASM_IDLE_WASM_PHP_DIST`.
|
|
394
450
|
|
|
395
451
|
Published packages are built in workspace dependency order. Before publishing, run:
|
|
396
452
|
|
|
@@ -415,7 +471,7 @@ opaque, receipt-pinned storage paths; these files are deployed page assets, not
|
|
|
415
471
|
contents.
|
|
416
472
|
|
|
417
473
|
PHP is built independently under `producers/wasm-php`, with its own lockfile and exact
|
|
418
|
-
`@php-wasm/web-8-4@3.1.
|
|
474
|
+
`@php-wasm/web-8-4@3.1.57` and `@php-wasm/universal@3.1.57` dependencies. Refresh the checked-in
|
|
419
475
|
page asset only when changing that producer:
|
|
420
476
|
|
|
421
477
|
```bash
|
|
@@ -477,15 +533,26 @@ cd wasm-idle
|
|
|
477
533
|
pnpm run sync:wasm-julia
|
|
478
534
|
```
|
|
479
535
|
|
|
480
|
-
Nim
|
|
536
|
+
Nim compiler preparation is owned by `wasm-llvm/producer/nim-browser`; the pinned
|
|
537
|
+
`benagastov/Nim-WASM-Compiler` distribution is delivered under
|
|
481
538
|
`static/wasm-nim/`: Nim 2.2.4 compiled to WebAssembly emits C, then bundled clang/lld WebAssembly
|
|
482
|
-
assets link a runnable WASI module.
|
|
539
|
+
assets link a runnable WASI module. Package the compiler artifacts with the producer,
|
|
540
|
+
then publish the verified bundle and current consumer Worker:
|
|
483
541
|
|
|
484
542
|
```bash
|
|
485
|
-
|
|
486
|
-
pnpm
|
|
543
|
+
# In wasm-llvm: migrate existing verified assets or select a pinned upstream source.
|
|
544
|
+
pnpm package:nim -- --from-runtime /path/to/wasm-idle/static/wasm-nim --out out/nim-browser
|
|
545
|
+
# In wasm-idle:
|
|
546
|
+
pnpm sync:wasm-nim /path/to/wasm-llvm/out/nim-browser
|
|
487
547
|
```
|
|
488
548
|
|
|
549
|
+
D compiler source patches, porting probes and artifact packaging live in
|
|
550
|
+
`wasm-llvm/producer/d-browser`. Import its verified output through
|
|
551
|
+
`WASM_LLVM_D_ARTIFACT_DIR` when building `runtimes/wasm-d`; see [the D browser integration](docs/d-browser.md).
|
|
552
|
+
C3 and LFortran continue using their existing `wasm-llvm` producers. Compiler preparation for
|
|
553
|
+
these four paths belongs to the producer repository, while execution and cache ownership belong
|
|
554
|
+
to `wasm-idle`.
|
|
555
|
+
|
|
489
556
|
## Rust browser integration
|
|
490
557
|
|
|
491
558
|
The demo app publishes the workspace `wasm-rust` compiler as a receipt-pinned executable graph
|
|
@@ -627,7 +694,8 @@ are bounded and verified against the exact expanded size and SHA-256.
|
|
|
627
694
|
|
|
628
695
|
The preparer rejects source or target paths outside their configured roots, checks each redirect
|
|
629
696
|
before following it, writes atomically, and reuses only matching files. With no group argument,
|
|
630
|
-
it prepares
|
|
697
|
+
it prepares the Clang delivery bundle with its matching clangd assets, the complete OCaml browser
|
|
698
|
+
compiler graph, and the C3, LFortran, Lean 4, and Common Lisp payloads.
|
|
631
699
|
`WASM_IDLE_TEST_ASSET_BASE_URL` can select a compatible mirror with the same receipt-verified bytes.
|
|
632
700
|
For protected local browser tests, provide `WASM_IDLE_TEST_BYPASS_COOKIE` through the environment
|
|
633
701
|
in `dev_bypass_waf=<value>` form; the browser cookie jar scopes it to the test origin. Asset
|
|
@@ -786,8 +854,8 @@ and other workspace `.sql` files run first. Preloaded stdin is exposed as the se
|
|
|
786
854
|
`/dev/blob` (`COPY t FROM '/dev/blob'` or `pg_read_file('/dev/blob')`). Override the module with
|
|
787
855
|
`PUBLIC_WASM_POSTGRESQL_MODULE_URL` or `runtimeAssets.postgresql.moduleUrl`.
|
|
788
856
|
PHP dynamically imports the checked-in `static/wasm-php/runtime.mjs` output from the standalone
|
|
789
|
-
`producers/wasm-php` build. That producer pins `@php-wasm/web-8-4@3.1.
|
|
790
|
-
`@php-wasm/universal@3.1.
|
|
857
|
+
`producers/wasm-php` build. That producer pins `@php-wasm/web-8-4@3.1.57` and
|
|
858
|
+
`@php-wasm/universal@3.1.57`. It always creates PHP 8.4; there is no version field or
|
|
791
859
|
environment-based version selector. Override only the module location with
|
|
792
860
|
`PUBLIC_WASM_PHP_MODULE_URL` or `runtimeAssets.php.moduleUrl`. A custom host must serve the entry's
|
|
793
861
|
sibling chunks and assets with compatible CORS and cross-origin isolation headers; a cross-origin
|
|
@@ -855,6 +923,9 @@ the Rust worker:
|
|
|
855
923
|
|
|
856
924
|
- `wasm32-wasip1` runs as preview1 core wasm through `@bjorn3/browser_wasi_shim`
|
|
857
925
|
- `wasm32-wasip2` runs as a preview2 component through `preview2-shim` plus transpiled `jco` output
|
|
926
|
+
- `wasm32-wasip3` also returns a component and runs on the same preview2 path. This works only
|
|
927
|
+
while emitted components keep transitional WASIp2 imports; preview3 imports are rejected until a
|
|
928
|
+
browser preview3 shim exists
|
|
858
929
|
|
|
859
930
|
C-family compilation remains hosted by `@wasm-idle/llvm-core`, while Rust delegates artifact
|
|
860
931
|
execution to `wasm-rust` so the selected target and returned artifact format stay aligned.
|
|
@@ -917,7 +988,9 @@ const runtimeAssets: PlaygroundRuntimeAssets = {
|
|
|
917
988
|
stdlibUrl: 'https://cdn.example.com/wasm-zig/std.tar.gz'
|
|
918
989
|
},
|
|
919
990
|
lisp: {
|
|
920
|
-
moduleUrl: 'https://cdn.example.com/wasm-lisp/index.js'
|
|
991
|
+
moduleUrl: 'https://cdn.example.com/wasm-lisp/index.js',
|
|
992
|
+
manifestUrl: 'https://cdn.example.com/wasm-lisp/runtime-manifest.v2.json',
|
|
993
|
+
manifestFingerprint: '<runtime-manifest-fingerprint>'
|
|
921
994
|
},
|
|
922
995
|
haskell: {
|
|
923
996
|
moduleUrl: 'https://cdn.example.com/wasm-haskell/dyld.mjs',
|
|
@@ -926,7 +999,9 @@ const runtimeAssets: PlaygroundRuntimeAssets = {
|
|
|
926
999
|
},
|
|
927
1000
|
nim: {
|
|
928
1001
|
baseUrl: 'https://cdn.example.com/wasm-nim/',
|
|
929
|
-
workerUrl: 'https://cdn.example.com/wasm-nim/runner-worker.js'
|
|
1002
|
+
workerUrl: 'https://cdn.example.com/wasm-nim/runner-worker.js',
|
|
1003
|
+
// Complete identity and receipt bundle for the served bytes; see below.
|
|
1004
|
+
...nimTrustBundle
|
|
930
1005
|
}
|
|
931
1006
|
};
|
|
932
1007
|
```
|
|
@@ -934,12 +1009,22 @@ const runtimeAssets: PlaygroundRuntimeAssets = {
|
|
|
934
1009
|
Static module overrides such as PHP's `moduleUrl` identify an entry module, not a self-contained
|
|
935
1010
|
file. Mirror its complete sibling asset tree at the same relative paths. Cross-origin asset hosts
|
|
936
1011
|
must provide compatible CORS and COEP/CORP headers and cannot rely on wasm-idle's same-origin gzip
|
|
937
|
-
service worker.
|
|
1012
|
+
service worker. The checkout stores several files from the example above only as `.gz`, for
|
|
1013
|
+
example `wasm-zig/zig_small.wasm.gz`, `wasm-wat/index.js.gz`, `wasm-lisp/index.js.gz`, and
|
|
1014
|
+
`wasm-haskell/bsdtar.wasm.gz`. A host for those URLs must return the decompressed bytes, either as
|
|
1015
|
+
a decompressed file or as that `.gz` served with `Content-Encoding: gzip`; Zig's `std.tar.gz` is
|
|
1016
|
+
served as stored.
|
|
938
1017
|
|
|
939
1018
|
Verified static runtimes such as Janet and Julia intentionally omit URL-only examples: a custom
|
|
940
1019
|
`baseUrl`, `manifestUrl`, or `workerUrl` must be accompanied by every identity and asset-receipt
|
|
941
1020
|
field declared by that runtime's asset config, including the matching `workerReceipt`. Partial
|
|
942
|
-
trust bundles fail closed instead of borrowing receipts from bundled executable bytes.
|
|
1021
|
+
trust bundles fail closed instead of borrowing receipts from bundled executable bytes. In the Nim
|
|
1022
|
+
entry above, `nimTrustBundle` stands for `profileId`, `artifactRevision`, `nimRevision`,
|
|
1023
|
+
`llvmRevision`, `memfsRevision`, `emscriptenRevision`, `manifestFingerprint`, `manifestReceipt`,
|
|
1024
|
+
`nimJavaScriptReceipt`, `nimWasmReceipt`, `nimbaseReceipt`, `clangJavaScriptReceipt`,
|
|
1025
|
+
`clangWasmReceipt`, `lldWasmReceipt`, `memfsWasmReceipt`, `sysrootReceipt`, and `workerReceipt`. An
|
|
1026
|
+
explicit Nim `manifestUrl` must be `runtime-manifest.v2.json?v=<manifestFingerprint>` under
|
|
1027
|
+
`baseUrl`. A `rootUrl` mirror of the bundled Nim files needs no `nim` entry.
|
|
943
1028
|
|
|
944
1029
|
The bundled C/C++ app uses receipt-pinned Clang language sysroots: C initially downloads only the
|
|
945
1030
|
C base, while C++ or a mixed/opaque-language build loads the C++ add-on before compiling or linking.
|
|
@@ -990,8 +1075,8 @@ The pack contains the same locked upstream files, not an import-based subset. Ea
|
|
|
990
1075
|
### Retaining compiler caches across editor navigation
|
|
991
1076
|
|
|
992
1077
|
Create one `createRuntimeSession(assets)` owner per browser application and use
|
|
993
|
-
`session.createBinding()` for each editor or execution panel.
|
|
994
|
-
|
|
1078
|
+
`session.createBinding()` for each editor or execution panel. Clang consumers, Rust,
|
|
1079
|
+
TinyGo, D, C3, Nim, LFortran and Python share a bounded owner for verified assets and compiler modules:
|
|
995
1080
|
|
|
996
1081
|
```ts
|
|
997
1082
|
import { createRuntimeSession } from 'wasm-idle';
|
|
@@ -1005,12 +1090,14 @@ await panel.dispose(); // close this panel; retain the session's cache
|
|
|
1005
1090
|
|
|
1006
1091
|
const nextPanel = session.createBinding(); // another problem, same language
|
|
1007
1092
|
await nextPanel.load('PYTHON');
|
|
1008
|
-
await session.selectLanguage('CPP'); // release old-language panels
|
|
1093
|
+
await session.selectLanguage('CPP'); // release old-language panels; retain verified assets
|
|
1009
1094
|
await session.dispose(); // full, terminal release of this owner
|
|
1010
1095
|
```
|
|
1011
1096
|
|
|
1012
|
-
Selecting a language does not download assets.
|
|
1013
|
-
|
|
1097
|
+
Selecting a language does not download assets. Only the selected language keeps active
|
|
1098
|
+
execution leases; verified compiler assets survive language changes until LRU eviction
|
|
1099
|
+
or session disposal. Selecting an unsupported/server-only language releases active leases
|
|
1100
|
+
without clearing the session's verified assets.
|
|
1014
1101
|
Executions never share mutable Wasm instances, user files or stdin. C/C++ additionally
|
|
1015
1102
|
reuse compiled programs when source, workspace and compiler options match, while
|
|
1016
1103
|
custom loaders and debugging retain the original execution path. Python still creates
|
|
@@ -1019,7 +1106,23 @@ a fresh interpreter after `clear()`; module reuse does not eliminate interpreter
|
|
|
1019
1106
|
The asset cache is LRU-bounded to 64 entries and 256 MiB of logical asset bytes
|
|
1020
1107
|
(not a measurement of the browser engine's compiled-code memory). C/C++ program
|
|
1021
1108
|
artifacts are independently bounded to 8 entries and 32 MiB. `getCacheStats()` exposes
|
|
1022
|
-
cache counters for diagnostics.
|
|
1109
|
+
cache counters for diagnostics. COBOL, Fortran, V and Objective-C/Objective-C++ connect
|
|
1110
|
+
their Clang asset bridges to this same owner. Rust, TinyGo, D, C3, Nim and LFortran use one-shot MessagePorts
|
|
1111
|
+
to request compiler modules from the session after checking the pinned artifact receipt.
|
|
1112
|
+
The host verifies the bytes again before returning a module, including on cache hits.
|
|
1113
|
+
Nim also passes verified Clang, LLD and MemFS modules to its nested compiler Worker.
|
|
1114
|
+
C3 partitions its transformed compiler by the configured memory cap; LFortran shares
|
|
1115
|
+
its compiler module while generating fresh dynamic side modules in each execution.
|
|
1116
|
+
Cache identities include artifact receipts, authorization profiles and compilation
|
|
1117
|
+
settings; TinyGo also separates the memory-cap transformation used for each toolchain.
|
|
1118
|
+
|
|
1119
|
+
`@wasm-idle/core` exports `WorkerSession`, `RuntimeAssetCache` and the
|
|
1120
|
+
`createRuntimeWasmModuleService` / `serveRuntimeWasmModule` / `requestRuntimeWasmModule`
|
|
1121
|
+
helpers for hosts implementing the same ownership model. Cancelling one request closes
|
|
1122
|
+
its subscription without terminating another request that uses the same immutable
|
|
1123
|
+
module. Compiler instances, linear memory, files and compiler helper threads remain
|
|
1124
|
+
owned by individual jobs; this cache does not combine the LLVM binaries embedded in
|
|
1125
|
+
different toolchains.
|
|
1023
1126
|
|
|
1024
1127
|
### Optional idle runtime prewarming
|
|
1025
1128
|
|
|
@@ -201,20 +201,22 @@ const expectedAssetsForRuntime = (runtime, languageSysroots = false) => {
|
|
|
201
201
|
}
|
|
202
202
|
return assets;
|
|
203
203
|
};
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
:
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
204
|
+
// Read the contract fields directly: valid receipts can use inherited or hidden getters.
|
|
205
|
+
const snapshotIntegrityEntry = (receipt) => typeof receipt === 'string'
|
|
206
|
+
? receipt
|
|
207
|
+
: Object.freeze({
|
|
208
|
+
sha256: receipt.sha256,
|
|
209
|
+
bytes: receipt.bytes,
|
|
210
|
+
mediaType: receipt.mediaType,
|
|
211
|
+
uncompressedSha256: receipt.uncompressedSha256,
|
|
212
|
+
uncompressedBytes: receipt.uncompressedBytes
|
|
213
|
+
});
|
|
214
|
+
const integrityKey = (config) => {
|
|
215
|
+
const integrity = config.integrity || {};
|
|
216
|
+
return JSON.stringify(Object.getOwnPropertyNames(integrity)
|
|
217
|
+
.sort((left, right) => left.localeCompare(right))
|
|
218
|
+
.map((asset) => [asset, snapshotIntegrityEntry(integrity[asset])]));
|
|
219
|
+
};
|
|
218
220
|
const allowedBaseUrlsKey = (config) => JSON.stringify([...(config.allowedBaseUrls || [])].sort());
|
|
219
221
|
class RuntimeLoadProgress {
|
|
220
222
|
samples = new Map();
|
|
@@ -550,7 +552,6 @@ export class WorkerAssetBridge {
|
|
|
550
552
|
const generation = this.generation;
|
|
551
553
|
const controller = new AbortController();
|
|
552
554
|
const progress = this.progress;
|
|
553
|
-
const context = this.captureLoadContext();
|
|
554
555
|
const receiveProgress = (event) => {
|
|
555
556
|
if (controller.signal.aborted || generation !== this.generation)
|
|
556
557
|
return;
|
|
@@ -561,15 +562,33 @@ export class WorkerAssetBridge {
|
|
|
561
562
|
progress.activity(event.phase, event.asset);
|
|
562
563
|
}
|
|
563
564
|
};
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
565
|
+
// A rebind to the same worker aborts this load, but that worker still awaits a reply.
|
|
566
|
+
const replySuperseded = () => {
|
|
567
|
+
if (this.state !== 'active' || this.worker !== worker)
|
|
568
|
+
return;
|
|
569
|
+
try {
|
|
570
|
+
worker.postMessage({
|
|
571
|
+
assetResponse: {
|
|
572
|
+
id: request.id,
|
|
573
|
+
ok: false,
|
|
574
|
+
error: `Runtime asset ${request.asset} request was superseded by a rebind`
|
|
575
|
+
}
|
|
576
|
+
});
|
|
569
577
|
}
|
|
570
|
-
|
|
578
|
+
catch {
|
|
579
|
+
// The worker may already be terminated.
|
|
580
|
+
}
|
|
581
|
+
};
|
|
571
582
|
this.activeLoads.add(controller);
|
|
572
583
|
try {
|
|
584
|
+
const context = this.captureLoadContext();
|
|
585
|
+
const loadContext = (report) => ({
|
|
586
|
+
...context,
|
|
587
|
+
progress: {
|
|
588
|
+
update: (asset, loaded, total) => report({ kind: 'download', asset, loaded, total }, `download:${asset}`),
|
|
589
|
+
activity: (phase, asset) => report({ kind: 'activity', asset, phase }, `activity:${asset}`)
|
|
590
|
+
}
|
|
591
|
+
});
|
|
573
592
|
this.validateAssetRequest(loadContext(receiveProgress), request.asset);
|
|
574
593
|
const identity = [
|
|
575
594
|
this.runtime,
|
|
@@ -650,7 +669,7 @@ export class WorkerAssetBridge {
|
|
|
650
669
|
});
|
|
651
670
|
}
|
|
652
671
|
if (controller.signal.aborted || generation !== this.generation)
|
|
653
|
-
return;
|
|
672
|
+
return replySuperseded();
|
|
654
673
|
worker.postMessage({ assetResponse: { id: request.id, ok: true, module } });
|
|
655
674
|
return;
|
|
656
675
|
}
|
|
@@ -659,7 +678,7 @@ export class WorkerAssetBridge {
|
|
|
659
678
|
this.pythonPackageAssets = readPythonPackageAssets(loaded.bytes);
|
|
660
679
|
}
|
|
661
680
|
if (controller.signal.aborted || generation !== this.generation)
|
|
662
|
-
return;
|
|
681
|
+
return replySuperseded();
|
|
663
682
|
const buffer = transferBuffer(loaded.bytes, this.cache ? false : loaded.transferOwnership);
|
|
664
683
|
worker.postMessage({
|
|
665
684
|
assetResponse: {
|
|
@@ -672,7 +691,7 @@ export class WorkerAssetBridge {
|
|
|
672
691
|
}
|
|
673
692
|
catch (error) {
|
|
674
693
|
if (controller.signal.aborted || generation !== this.generation)
|
|
675
|
-
return;
|
|
694
|
+
return replySuperseded();
|
|
676
695
|
try {
|
|
677
696
|
worker.postMessage({
|
|
678
697
|
assetResponse: {
|
|
@@ -691,8 +710,24 @@ export class WorkerAssetBridge {
|
|
|
691
710
|
}
|
|
692
711
|
}
|
|
693
712
|
captureLoadContext() {
|
|
713
|
+
const config = { ...this.config };
|
|
714
|
+
const integrity = config.integrity;
|
|
715
|
+
// Cache identity and verification must observe the same receipt, even if a caller
|
|
716
|
+
// updates its configuration while an asynchronous asset load is in progress.
|
|
717
|
+
// The built-in Clang map and its receipts are frozen; its identity also selects
|
|
718
|
+
// verified streaming, so only caller-owned maps need a new snapshot.
|
|
719
|
+
if (integrity && integrity !== BUNDLED_CLANG_ASSET_INTEGRITY) {
|
|
720
|
+
config.integrity = Object.freeze(Object.fromEntries(
|
|
721
|
+
// Authorization accepts own map entries regardless of enumerability.
|
|
722
|
+
Object.getOwnPropertyNames(integrity).map((asset) => [
|
|
723
|
+
asset,
|
|
724
|
+
snapshotIntegrityEntry(integrity[asset])
|
|
725
|
+
])));
|
|
726
|
+
}
|
|
727
|
+
if (config.allowedBaseUrls)
|
|
728
|
+
config.allowedBaseUrls = [...config.allowedBaseUrls];
|
|
694
729
|
return {
|
|
695
|
-
config
|
|
730
|
+
config,
|
|
696
731
|
maxAssetBytes: this.maxAssetBytes,
|
|
697
732
|
expectedAssets: new Set(this.expectedAssets),
|
|
698
733
|
pythonPackageAssets: new Set(this.pythonPackageAssets),
|
|
@@ -743,6 +778,7 @@ export class WorkerAssetBridge {
|
|
|
743
778
|
throw runtimeAssetAbortReason(signal);
|
|
744
779
|
if (this.runtime === 'python' && asset === 'pyodide-lock.json')
|
|
745
780
|
readPythonPackageAssets(runtimeBytes);
|
|
781
|
+
await loaded.persist?.();
|
|
746
782
|
return {
|
|
747
783
|
bytes: runtimeBytes,
|
|
748
784
|
mimeType: loaded.mimeType,
|
|
@@ -768,8 +804,10 @@ export class WorkerAssetBridge {
|
|
|
768
804
|
if (!signal.aborted)
|
|
769
805
|
context.progress.update(asset, loaded, total);
|
|
770
806
|
};
|
|
771
|
-
|
|
772
|
-
|
|
807
|
+
// Do not expose the private verification context as a custom loader's receiver.
|
|
808
|
+
const loader = context.config.loader;
|
|
809
|
+
if (loader) {
|
|
810
|
+
const pendingResult = Promise.resolve(loader({
|
|
773
811
|
runtime: this.runtime,
|
|
774
812
|
asset,
|
|
775
813
|
reportProgress,
|
|
@@ -930,7 +968,8 @@ export class WorkerAssetBridge {
|
|
|
930
968
|
'bridge-v1',
|
|
931
969
|
context.config.baseUrl,
|
|
932
970
|
allowedBaseUrlsKey(context.config),
|
|
933
|
-
maxAssetBytes
|
|
971
|
+
maxAssetBytes,
|
|
972
|
+
expected?.mediaType
|
|
934
973
|
])
|
|
935
974
|
}
|
|
936
975
|
: undefined;
|
|
@@ -943,13 +982,44 @@ export class WorkerAssetBridge {
|
|
|
943
982
|
if (bytes) {
|
|
944
983
|
requireRuntimeAssetSize(asset, bytes.byteLength, maxAssetBytes);
|
|
945
984
|
context.progress.update(asset, bytes.byteLength, bytes.byteLength);
|
|
946
|
-
|
|
985
|
+
// A hit was validated against this same expected MIME type before it was stored.
|
|
986
|
+
return {
|
|
987
|
+
bytes,
|
|
988
|
+
mimeType: expected?.mediaType ?? receipt?.mediaType,
|
|
989
|
+
transferOwnership: true
|
|
990
|
+
};
|
|
947
991
|
}
|
|
948
992
|
}
|
|
949
993
|
const loaded = await this.fetchAssetFromNetwork(context, url, asset, signal, maxAssetBytes);
|
|
994
|
+
if (receipt) {
|
|
995
|
+
// Verify even when storage is disabled, unavailable or skipped. A body that the browser
|
|
996
|
+
// HTTP-decoded and that lost its gzip header is checked against the logical receipt.
|
|
997
|
+
const decoded = !!loaded.contentEncoding && !(loaded.bytes[0] === 0x1f && loaded.bytes[1] === 0x8b);
|
|
998
|
+
if (decoded && receipt.uncompressedSha256 !== undefined) {
|
|
999
|
+
await verifyRuntimeAssetIntegrity({
|
|
1000
|
+
asset,
|
|
1001
|
+
bytes: loaded.bytes,
|
|
1002
|
+
expected: {
|
|
1003
|
+
sha256: receipt.sha256,
|
|
1004
|
+
uncompressedSha256: receipt.uncompressedSha256,
|
|
1005
|
+
uncompressedBytes: receipt.uncompressedBytes
|
|
1006
|
+
},
|
|
1007
|
+
stage: 'uncompressed'
|
|
1008
|
+
});
|
|
1009
|
+
}
|
|
1010
|
+
else if (!decoded || !asset.endsWith('.gz')) {
|
|
1011
|
+
// Unpaired receipts for other assets already describe their logical bytes.
|
|
1012
|
+
await verifyRuntimeAssetIntegrity({
|
|
1013
|
+
asset,
|
|
1014
|
+
bytes: loaded.bytes,
|
|
1015
|
+
expected: { sha256: receipt.sha256, bytes: receipt.bytes }
|
|
1016
|
+
});
|
|
1017
|
+
}
|
|
1018
|
+
// A decoded .gz body with an unpaired receipt is left to runtime validation.
|
|
1019
|
+
}
|
|
950
1020
|
if (identity && !loaded.contentEncoding) {
|
|
951
|
-
//
|
|
952
|
-
|
|
1021
|
+
// A hit skips the response MIME check, so publish only bytes that passed it.
|
|
1022
|
+
loaded.persist = () => writePersistentRuntimeAsset({
|
|
953
1023
|
identity,
|
|
954
1024
|
cache: persistentCache,
|
|
955
1025
|
signal,
|
|
@@ -1177,6 +1247,11 @@ export class WorkerAssetBridge {
|
|
|
1177
1247
|
if (url.hash) {
|
|
1178
1248
|
throw new Error(`Runtime asset ${asset} URL must not include a fragment`);
|
|
1179
1249
|
}
|
|
1250
|
+
// The prefix check below sees `/base/..%2fother` as inside `/base/`, but a server that
|
|
1251
|
+
// decodes the separator before resolving dot segments serves `/other`.
|
|
1252
|
+
if (/%2f|%5c/iu.test(url.pathname)) {
|
|
1253
|
+
throw new Error(`Runtime asset ${asset} URL must not include encoded path separators`);
|
|
1254
|
+
}
|
|
1180
1255
|
const allowed = [context.config.baseUrl, ...(context.config.allowedBaseUrls || [])].some((baseUrl) => {
|
|
1181
1256
|
let base;
|
|
1182
1257
|
try {
|
|
@@ -663,12 +663,12 @@ export interface ResolvedZigRuntimeAssetConfig {
|
|
|
663
663
|
integrity: ZigExecutionAssetReceipts;
|
|
664
664
|
}
|
|
665
665
|
export declare const PYTHON_RUNTIME_LOAD_ASSETS: readonly ["pyodide.mjs", "pyodide.asm.mjs", "pyodide-lock.json", "pyodide.asm.wasm", "python_stdlib.zip"];
|
|
666
|
-
export declare const JAVA_RUNTIME_LOAD_ASSETS: readonly ["compiler.wasm-runtime.js", "compiler.wasm", "compile-classlib-teavm.bin", "runtime-classlib-teavm.bin"];
|
|
666
|
+
export declare const JAVA_RUNTIME_LOAD_ASSETS: readonly ["compiler.wasm-runtime.js", "compiler.wasm", "compiler.wasm-deobfuscator.wasm", "compile-classlib-teavm.bin", "runtime-classlib-teavm.bin"];
|
|
667
667
|
export declare const CLANG_RUNTIME_LOAD_ASSETS: readonly ["runtime-manifest.v1.json", "bin/memfs.wasm.gz", "bin/clang.wasm.gz", "bin/lld.wasm.gz", "bin/sysroot.tar.gz"];
|
|
668
668
|
export declare const CLANGD_RUNTIME_LOAD_ASSETS: readonly ["clangd.js", "clangd.wasm.gz", "clangd.headers.json.gz"];
|
|
669
669
|
export declare const RUNTIME_LOAD_ASSETS: {
|
|
670
670
|
python: readonly ["pyodide.mjs", "pyodide.asm.mjs", "pyodide-lock.json", "pyodide.asm.wasm", "python_stdlib.zip"];
|
|
671
|
-
java: readonly ["compiler.wasm-runtime.js", "compiler.wasm", "compile-classlib-teavm.bin", "runtime-classlib-teavm.bin"];
|
|
671
|
+
java: readonly ["compiler.wasm-runtime.js", "compiler.wasm", "compiler.wasm-deobfuscator.wasm", "compile-classlib-teavm.bin", "runtime-classlib-teavm.bin"];
|
|
672
672
|
clang: readonly ["runtime-manifest.v1.json", "bin/memfs.wasm.gz", "bin/clang.wasm.gz", "bin/lld.wasm.gz", "bin/sysroot.tar.gz"];
|
|
673
673
|
clangd: readonly ["clangd.js", "clangd.wasm.gz", "clangd.headers.json.gz"];
|
|
674
674
|
};
|