wasm-idle 1.0.5 → 1.0.7
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 +52 -5
- package/dist/index.d.ts +4 -1
- package/dist/index.js +2 -0
- package/dist/playground/assetBridge.d.ts +11 -2
- package/dist/playground/assetBridge.js +190 -46
- package/dist/playground/assets.d.ts +9 -1
- package/dist/playground/assets.js +29 -5
- package/dist/playground/awk.js +1 -0
- package/dist/playground/bash.d.ts +1 -0
- package/dist/playground/bash.js +7 -1
- package/dist/playground/bqn.js +1 -0
- package/dist/playground/bqnPreflight.d.ts +2 -1
- package/dist/playground/bqnPreflight.js +1 -0
- package/dist/playground/c3.js +1 -0
- package/dist/playground/cachedClang.d.ts +10 -0
- package/dist/playground/cachedClang.js +330 -0
- package/dist/playground/clang.d.ts +8 -0
- package/dist/playground/clang.js +47 -8
- package/dist/playground/clangWorkerProtocol.d.ts +57 -0
- package/dist/playground/clangWorkerProtocol.js +11 -0
- package/dist/playground/clojurescript.js +1 -0
- package/dist/playground/clojurescriptPreflight.d.ts +2 -1
- package/dist/playground/clojurescriptPreflight.js +1 -0
- package/dist/playground/compiledArtifactCache.d.ts +21 -0
- package/dist/playground/compiledArtifactCache.js +67 -0
- package/dist/playground/elixir.js +4 -1
- package/dist/playground/forth.js +1 -0
- package/dist/playground/forthPreflight.d.ts +2 -1
- package/dist/playground/forthPreflight.js +1 -0
- package/dist/playground/fortran.js +7 -1
- package/dist/playground/haskell.js +4 -1
- package/dist/playground/haskellAssets.d.ts +2 -1
- package/dist/playground/haskellAssets.js +8 -8
- package/dist/playground/index.d.ts +1 -1
- package/dist/playground/index.js +2 -2
- package/dist/playground/j.js +1 -0
- package/dist/playground/jPreflight.d.ts +2 -1
- package/dist/playground/jPreflight.js +1 -0
- package/dist/playground/janet.js +1 -0
- package/dist/playground/java.js +20 -8
- package/dist/playground/julia.js +1 -0
- package/dist/playground/lfortranAssets.d.ts +2 -1
- package/dist/playground/lfortranAssets.js +1 -0
- package/dist/playground/lisp.js +4 -1
- package/dist/playground/lispAssets.d.ts +2 -1
- package/dist/playground/lispAssets.js +10 -0
- package/dist/playground/lldbManifest.d.ts +2 -2
- package/dist/playground/lldbManifest.js +17 -3
- package/dist/playground/lldbSession.d.ts +1 -0
- package/dist/playground/lldbSession.js +2 -1
- package/dist/playground/nim.js +1 -0
- package/dist/playground/ocaml.d.ts +1 -0
- package/dist/playground/ocaml.js +12 -1
- package/dist/playground/options.d.ts +2 -0
- package/dist/playground/pascal.js +1 -0
- package/dist/playground/perl.js +1 -0
- package/dist/playground/prolog.js +1 -0
- package/dist/playground/python.d.ts +7 -0
- package/dist/playground/python.js +41 -8
- package/dist/playground/runtimeAssetCache.d.ts +26 -0
- package/dist/playground/runtimeAssetCache.js +84 -0
- package/dist/playground/runtimeSession.d.ts +21 -0
- package/dist/playground/runtimeSession.js +119 -0
- package/dist/playground/rust.d.ts +1 -0
- package/dist/playground/rust.js +11 -1
- package/dist/playground/rustExecutableGraph.d.ts +1 -0
- package/dist/playground/rustExecutableGraph.js +1 -0
- package/dist/playground/staticRuntimePreflight.d.ts +2 -1
- package/dist/playground/staticRuntimePreflight.js +4 -2
- package/dist/playground/staticRuntimePreflightExecute.js +1 -0
- package/dist/playground/staticRuntimePreflightProtocol.d.ts +2 -1
- package/dist/playground/staticWorkerRuntime.d.ts +3 -1
- package/dist/playground/staticWorkerRuntime.js +44 -3
- package/dist/playground/tcl.js +1 -0
- package/dist/playground/tinygo.d.ts +2 -0
- package/dist/playground/tinygo.js +57 -3
- package/dist/playground/tinygoExecutableGraph.d.ts +4 -1
- package/dist/playground/tinygoExecutableGraph.js +59 -7
- package/dist/playground/typescript.js +4 -1
- package/dist/playground/wasmGoVersion.d.ts +1 -1
- package/dist/playground/wasmGoVersion.js +1 -1
- package/dist/playground/wasmOcamlVersion.d.ts +2 -2
- package/dist/playground/wasmOcamlVersion.js +1 -1
- package/dist/playground/wasmRustVersion.d.ts +90 -24
- package/dist/playground/wasmRustVersion.js +98 -23
- package/dist/playground/wasmTinyGoVersion.d.ts +40 -29
- package/dist/playground/wasmTinyGoVersion.js +43 -31
- package/dist/playground/worker/assets.d.ts +3 -0
- package/dist/playground/worker/assets.js +41 -0
- package/dist/playground/worker/cachedClangCompile.d.ts +1 -0
- package/dist/playground/worker/cachedClangCompile.js +85 -0
- package/dist/playground/worker/cachedClangExecute.d.ts +1 -0
- package/dist/playground/worker/cachedClangExecute.js +67 -0
- package/dist/playground/worker/clang.js +2 -8
- package/dist/playground/worker/clangStreaming.d.ts +1 -1
- package/dist/playground/worker/clangStreaming.js +20 -2
- package/dist/playground/worker/elixir.js +10 -8
- package/dist/playground/worker/fortran.js +4 -7
- package/dist/playground/worker/haskell.js +2 -0
- package/dist/playground/worker/lisp.js +2 -0
- package/dist/playground/worker/ocaml.js +13 -1
- package/dist/playground/worker/python.js +3 -2
- package/dist/playground/worker/runtimeAssetFetch.d.ts +11 -1
- package/dist/playground/worker/runtimeAssetFetch.js +64 -1
- package/dist/playground/worker/runtimeModule.d.ts +8 -0
- package/dist/playground/worker/runtimeModule.js +49 -0
- package/dist/playground/worker/rust.js +9 -2
- package/dist/playground/worker/staticRuntimePreflight.js +2 -0
- package/dist/playground/worker/typescript.js +4 -1
- package/dist/playground/worker/zig.js +7 -4
- package/dist/playground/zig.js +4 -1
- package/package.json +10 -7
package/README.md
CHANGED
|
@@ -15,6 +15,10 @@ Compiler source pins, patches, and reproducible asset builds live in
|
|
|
15
15
|
[`seo-rii/wasm-llvm`](https://github.com/seo-rii/wasm-llvm); wasm-idle loads the generated
|
|
16
16
|
artifacts from external URLs instead of embedding them in npm packages.
|
|
17
17
|
|
|
18
|
+
Verified downloads can be retained across reloads using a version-pinned, capacity-bounded
|
|
19
|
+
CacheStorage/IndexedDB cache. See [persistent asset cache configuration and coverage](docs/runtime-asset-cache.md)
|
|
20
|
+
for global/per-call opt-out, cleanup and prefetch APIs.
|
|
21
|
+
|
|
18
22
|
## Language support policy
|
|
19
23
|
|
|
20
24
|
wasm-idle language support must run user code through the real language implementation in the
|
|
@@ -221,9 +225,9 @@ when they exist.
|
|
|
221
225
|
| Language / IDs | Package/version base | Execution defaults / flags | Customization |
|
|
222
226
|
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
223
227
|
| 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 |
|
|
224
|
-
| C<br>`C` | @wasm-idle/llvm-core@1.0.
|
|
225
|
-
| C++<br>`CPP` | @wasm-idle/llvm-core@1.0.
|
|
226
|
-
| Objective-C<br>`OBJC` | GNUstep libobjc2 v2.3 assets from the `wasm-llvm` producer + @wasm-idle/llvm-core@1.0.
|
|
228
|
+
| C<br>`C` | @wasm-idle/llvm-core@1.0.7 / 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` |
|
|
229
|
+
| C++<br>`CPP` | @wasm-idle/llvm-core@1.0.7 / 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` |
|
|
230
|
+
| Objective-C<br>`OBJC` | GNUstep libobjc2 v2.3 assets from the `wasm-llvm` producer + @wasm-idle/llvm-core@1.0.7 | `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` |
|
|
227
231
|
| Python<br>`PYTHON3` | static ESM `static/pyodide/pyodide.mjs` / pyodide@0.29.3 | loads `pyodide.mjs`, `pyodide.asm.js`, `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` |
|
|
228
232
|
| Java<br>`JAVA` | @wasm-idle/runtime-teavm@0.0.0 / TeaVM compiler assets | `compiler.wasm` compiles Java to browser WASM/JS; supports `stdin` and `programArgs` | `runtimeAssets.java.baseUrl`/`loader` or `rootUrl` |
|
|
229
233
|
| Rust<br>`RUST` | wasm-rust@0.1.0 / rust-1.99.0-browser-integrated-v1 + integrated LLVM/LLD 22.1.8 from the `wasm-llvm` producer; exact rustc/LLVM provenance is recorded for LLDB compatibility | browser host `wasm32-wasip1-threads`; default target `wasm32-wasip1`, selectable `wasm32-wasip1`, `wasm32-wasip2`, `wasm32-wasip3`; LLDB mode is currently limited to `wasm32-wasip1` and emits embedded DWARF with `-C debuginfo=2 -C opt-level=0`; normal Preview 1/2/3 execution remains unchanged; supports `stdin` and `programArgs` | `runtimeAssets.rust.compilerUrl`, `runtimeAssets.rust.debugModuleUrl`, or `PUBLIC_WASM_RUST_COMPILER_URL`; `rootUrl`, `rustTargetTriple`, `programArgs`, `debugMode`; compiler requests accept `edition`, `crateType`, `extendedTimeout`, `log`, and `onProgress`; runtime manifest controls compiler memory, timeout, and shared workspace size |
|
|
@@ -261,8 +265,8 @@ when they exist.
|
|
|
261
265
|
| Ruby<br>`RUBY` | receipt-pinned `static/wasm-ruby` profile produced from @ruby/3.4-wasm-wasi@2.9.3-2.9.4 + @ruby/wasm-wasi@2.9.3-2.9.4 | host-verifies the manifest, canonical stored module and gzip bytes, and logical WASM before transferring three owned buffers to a no-fetch CRuby 3.4 worker; supports `stdin`, `programArgs`, and workspace files | `rootUrl` mirrors reuse the bundled profile; explicit `runtimeAssets.ruby` overrides require one complete profile and same-origin canonical paths; URL-only `PUBLIC_WASM_RUBY_*` overrides fail closed; `stdin`, `programArgs`, `workspaceFiles` |
|
|
262
266
|
| 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` |
|
|
263
267
|
| 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 |
|
|
264
|
-
| Fortran<br>`FORTRAN` | Netlib f2c 2022-09-09 + `@cowasm/f2c 1.0.0` libf2c + @wasm-idle/llvm-core@1.0.
|
|
265
|
-
| COBOL<br>`COBOL` | GnuCOBOL 3.2 + GMP 6.3.0 assets from the `wasm-llvm` producer + @wasm-idle/llvm-core@1.0.
|
|
268
|
+
| Fortran<br>`FORTRAN` | Netlib f2c 2022-09-09 + `@cowasm/f2c 1.0.0` libf2c + @wasm-idle/llvm-core@1.0.7 | 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` |
|
|
269
|
+
| COBOL<br>`COBOL` | GnuCOBOL 3.2 + GMP 6.3.0 assets from the `wasm-llvm` producer + @wasm-idle/llvm-core@1.0.7 | 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` |
|
|
266
270
|
| 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` |
|
|
267
271
|
| 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_*` |
|
|
268
272
|
| DuckDB<br>`DUCKDB` | static ESM `static/wasm-duckdb/runtime.mjs` produced from @duckdb/duckdb-wasm@1.33.1-dev45.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` |
|
|
@@ -323,6 +327,15 @@ toolchains can be consumed from pinned external runtime repositories:
|
|
|
323
327
|
normal runtime workspace packages. `tools/dool` contains the Docker judge backend for Elixir and
|
|
324
328
|
the other server-side language runners.
|
|
325
329
|
|
|
330
|
+
Deployment builds retain both legacy `.gz` and canonical `.gz.bin` URLs by default.
|
|
331
|
+
After building and compressing the page, `pnpm run compact:build-runtimes` reports
|
|
332
|
+
byte-identical duplicates without changing files. Add `--drop-legacy-aliases` to
|
|
333
|
+
remove those duplicate files and add compatibility routing to the generated service
|
|
334
|
+
worker. This only preserves legacy URLs in service-worker-controlled requests:
|
|
335
|
+
external SDKs and uncontrolled first requests to the removed `.gz` URLs need to
|
|
336
|
+
migrate to `.gz.bin` or use server aliases. Opt in only after that migration. Source
|
|
337
|
+
assets and producer receipts stay intact; rerun compaction after each page build.
|
|
338
|
+
|
|
326
339
|
Useful workspace commands:
|
|
327
340
|
|
|
328
341
|
```bash
|
|
@@ -900,6 +913,40 @@ The pack contains the same locked upstream files, not an import-based subset. Ea
|
|
|
900
913
|
|
|
901
914
|
`node scripts/sync-runtime.mjs wasm-ruby` regenerates both profiles from the pinned producer inputs. `node scripts/sync-wasm-ruby-split.mjs --verify` additionally checks split-profile freshness without replacing published files.
|
|
902
915
|
|
|
916
|
+
### Retaining compiler caches across editor navigation
|
|
917
|
+
|
|
918
|
+
Create one `createRuntimeSession(assets)` owner per browser application and use
|
|
919
|
+
`session.createBinding()` for each editor or execution panel. C/C++ and Python
|
|
920
|
+
keep immutable compiler/runtime modules outside their disposable execution Workers:
|
|
921
|
+
|
|
922
|
+
```ts
|
|
923
|
+
import { createRuntimeSession } from 'wasm-idle';
|
|
924
|
+
|
|
925
|
+
const session = createRuntimeSession(assets); // browser scope, not an SSR singleton
|
|
926
|
+
const panel = session.createBinding();
|
|
927
|
+
const sandbox = await panel.load('PYTHON');
|
|
928
|
+
await sandbox.load('print("hi")', false);
|
|
929
|
+
await sandbox.clear(); // reset execution state; retain compiler/runtime cache
|
|
930
|
+
await panel.dispose(); // close this panel; retain the session's cache
|
|
931
|
+
|
|
932
|
+
const nextPanel = session.createBinding(); // another problem, same language
|
|
933
|
+
await nextPanel.load('PYTHON');
|
|
934
|
+
await session.selectLanguage('CPP'); // release old-language panels and cache
|
|
935
|
+
await session.dispose(); // full, terminal release of this owner
|
|
936
|
+
```
|
|
937
|
+
|
|
938
|
+
Selecting a language does not download assets. The owner retains only one language;
|
|
939
|
+
selecting an unsupported/server-only language also releases the previous cache.
|
|
940
|
+
Executions never share mutable Wasm instances, user files or stdin. C/C++ additionally
|
|
941
|
+
reuse compiled programs when source, workspace and compiler options match, while
|
|
942
|
+
custom loaders and debugging retain the original execution path. Python still creates
|
|
943
|
+
a fresh interpreter after `clear()`; module reuse does not eliminate interpreter startup.
|
|
944
|
+
|
|
945
|
+
The asset cache is LRU-bounded to 64 entries and 256 MiB of logical asset bytes
|
|
946
|
+
(not a measurement of the browser engine's compiled-code memory). C/C++ program
|
|
947
|
+
artifacts are independently bounded to 8 entries and 32 MiB. `getCacheStats()` exposes
|
|
948
|
+
cache counters for diagnostics. Other languages currently keep their existing lifecycle.
|
|
949
|
+
|
|
903
950
|
### Optional idle runtime prewarming
|
|
904
951
|
|
|
905
952
|
`createPlaygroundBinding(assets, { prewarm: true })` enables explicit
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import playground, { createPlaygroundBinding } from './playground';
|
|
2
2
|
export default playground;
|
|
3
3
|
export { createPlaygroundBinding, playground };
|
|
4
|
+
export { createRuntimeSession } from './playground/runtimeSession';
|
|
5
|
+
export { configureRuntimeAssetCache, createRuntimeAssetCacheBackend, fetchPinnedRuntimeAsset, prefetchRuntimeAssets, resolveRuntimeAssetLockEntry, type PrefetchRuntimeAssetsOptions, type PrefetchRuntimeAssetsResult, type RuntimeAssetCacheStats, type RuntimeAssetCacheBackend, type RuntimeAssetCacheBackendIdentity, type PinnedRuntimeAssetRequest, getRuntimeAssetCacheOptions, getRuntimeAssetCacheStats, clearRuntimeAssetCache, pruneRuntimeAssetCache, requestRuntimeAssetCachePersistence, type RuntimeAssetCacheOptions } from '@wasm-idle/core';
|
|
6
|
+
export type { PlaygroundRuntimeSession } from './playground/runtimeSession';
|
|
4
7
|
export { isSharedArrayBufferAvailable, requireSharedArrayBuffer } from './playground/sharedBuffer';
|
|
5
8
|
export type { DebugCommand, DebugFrame, DebugSessionEvent, DebugVariable, TerminalControl } from '@wasm-idle/core';
|
|
6
9
|
export type { CompilerDiagnostic, SandboxExecutionOptions } from './playground/options';
|
|
7
10
|
export type { PlaygroundRuntimeAssets, RuntimeAssetConfig, RuntimeAssetLoadRequest, RuntimeAssetLoader, RuntimeAssetLoaderResult } from './playground/assets';
|
|
8
11
|
export type { BoundSandbox, PlaygroundBinding, PlaygroundTerminalProps, SandboxProgress, SandboxRuntimeAssets } from './playground/sandbox';
|
|
9
|
-
export type { PlaygroundBindingOptions } from
|
|
12
|
+
export type { PlaygroundBindingOptions } from '@wasm-idle/core';
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import playground, { createPlaygroundBinding } from './playground';
|
|
2
2
|
export default playground;
|
|
3
3
|
export { createPlaygroundBinding, playground };
|
|
4
|
+
export { createRuntimeSession } from './playground/runtimeSession';
|
|
5
|
+
export { configureRuntimeAssetCache, createRuntimeAssetCacheBackend, fetchPinnedRuntimeAsset, prefetchRuntimeAssets, resolveRuntimeAssetLockEntry, getRuntimeAssetCacheOptions, getRuntimeAssetCacheStats, clearRuntimeAssetCache, pruneRuntimeAssetCache, requestRuntimeAssetCachePersistence } from '@wasm-idle/core';
|
|
4
6
|
export { isSharedArrayBufferAvailable, requireSharedArrayBuffer } from './playground/sharedBuffer';
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { type ResolvedRuntimeAssetConfig, type RuntimeAssetRuntime } from './assets';
|
|
2
|
-
import { type ProgressLike } from '@wasm-idle/core';
|
|
2
|
+
import { type RuntimeAssetCacheOptions, type ResolvedRuntimeAssetCacheOptions, type ProgressLike } from '@wasm-idle/core';
|
|
3
|
+
import { RuntimeAssetCache } from './runtimeAssetCache';
|
|
3
4
|
export declare const boundedUtf8ByteLength: (value: string, maxBytes?: number) => number;
|
|
4
5
|
export declare class WorkerAssetBridge {
|
|
6
|
+
private readonly cache?;
|
|
5
7
|
private worker;
|
|
6
8
|
private readonly runtime;
|
|
7
9
|
private config;
|
|
10
|
+
private persistentCacheBaseline;
|
|
11
|
+
private readonly persistentCacheBySignal;
|
|
8
12
|
private progress;
|
|
9
13
|
private expectedAssets;
|
|
10
14
|
private languageSysroots;
|
|
@@ -13,8 +17,10 @@ export declare class WorkerAssetBridge {
|
|
|
13
17
|
private state;
|
|
14
18
|
private readonly activeLoads;
|
|
15
19
|
private maxAssetBytes;
|
|
16
|
-
constructor(worker: Worker, runtime: RuntimeAssetRuntime, config: ResolvedRuntimeAssetConfig, progress?: ProgressLike, maxAssetBytes?: number, languageSysroots?: boolean);
|
|
20
|
+
constructor(worker: Worker, runtime: RuntimeAssetRuntime, config: ResolvedRuntimeAssetConfig, progress?: ProgressLike, maxAssetBytes?: number, languageSysroots?: boolean, cache?: RuntimeAssetCache | undefined);
|
|
17
21
|
matches(config: ResolvedRuntimeAssetConfig, maxAssetBytes?: number, languageSysroots?: boolean): boolean;
|
|
22
|
+
/** Apply one execution's policy without changing the configuration established by load(). */
|
|
23
|
+
setExecutionPersistentCache(override?: RuntimeAssetCacheOptions): ResolvedRuntimeAssetCacheOptions;
|
|
18
24
|
rebind(worker: Worker, config: ResolvedRuntimeAssetConfig, progress?: ProgressLike, maxAssetBytes?: number, languageSysroots?: boolean): void;
|
|
19
25
|
dispose(): void;
|
|
20
26
|
resetProgress(progress?: ProgressLike): void;
|
|
@@ -23,10 +29,13 @@ export declare class WorkerAssetBridge {
|
|
|
23
29
|
private sourceAssetByteLimit;
|
|
24
30
|
handleMessage(event: MessageEvent<any>): boolean;
|
|
25
31
|
private respond;
|
|
32
|
+
private loadVerifiedAsset;
|
|
33
|
+
private validateAssetRequest;
|
|
26
34
|
private loadAsset;
|
|
27
35
|
private verifyIntegrity;
|
|
28
36
|
private normalizeLoaderResult;
|
|
29
37
|
private fetchAsset;
|
|
38
|
+
private fetchAssetFromNetwork;
|
|
30
39
|
private requireAllowedAssetUrl;
|
|
31
40
|
private abortActiveLoads;
|
|
32
41
|
}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { RUNTIME_LOAD_ASSETS } from './assets';
|
|
2
|
-
import { ProtocolError, verifyRuntimeAssetIntegrity, verifyRuntimeAssetPair } from '@wasm-idle/core';
|
|
2
|
+
import { ProtocolError, verifyRuntimeAssetIntegrity, verifyRuntimeAssetPair, readPersistentRuntimeAsset, writePersistentRuntimeAsset, resolveRuntimeAssetLockEntry, resolveRuntimeAssetCacheOptions } from '@wasm-idle/core';
|
|
3
3
|
import { decompressGzip } from '@wasm-idle/llvm-core';
|
|
4
4
|
import { readPythonPackageAssets } from './pythonPackageLock';
|
|
5
5
|
import { BUNDLED_CLANG_LANGUAGE_SYSROOT_PROFILES } from './clangAssetIntegrity';
|
|
6
6
|
import { shouldStreamBundledClang } from './clangStreamingPolicy';
|
|
7
|
+
import { compileVerifiedWasmAsset } from '@wasm-idle/llvm-core/core/verified-wasm';
|
|
8
|
+
import { BUNDLED_CLANG_ASSET_INTEGRITY } from './clangAssetIntegrity';
|
|
9
|
+
import { RuntimeAssetCache } from './runtimeAssetCache';
|
|
7
10
|
const encoder = new TextEncoder();
|
|
8
11
|
const DEFAULT_STREAM_BUFFER_BYTES = 64 * 1024;
|
|
9
12
|
const MAX_RUNTIME_ASSET_BYTES = 128 * 1024 * 1024;
|
|
@@ -372,9 +375,12 @@ class RuntimeLoadProgress {
|
|
|
372
375
|
}
|
|
373
376
|
}
|
|
374
377
|
export class WorkerAssetBridge {
|
|
378
|
+
cache;
|
|
375
379
|
worker;
|
|
376
380
|
runtime;
|
|
377
381
|
config;
|
|
382
|
+
persistentCacheBaseline;
|
|
383
|
+
persistentCacheBySignal = new WeakMap();
|
|
378
384
|
progress;
|
|
379
385
|
expectedAssets;
|
|
380
386
|
languageSysroots;
|
|
@@ -383,10 +389,12 @@ export class WorkerAssetBridge {
|
|
|
383
389
|
state = 'active';
|
|
384
390
|
activeLoads = new Set();
|
|
385
391
|
maxAssetBytes;
|
|
386
|
-
constructor(worker, runtime, config, progress, maxAssetBytes = MAX_RUNTIME_ASSET_BYTES, languageSysroots = false) {
|
|
392
|
+
constructor(worker, runtime, config, progress, maxAssetBytes = MAX_RUNTIME_ASSET_BYTES, languageSysroots = false, cache) {
|
|
393
|
+
this.cache = cache;
|
|
387
394
|
this.worker = worker;
|
|
388
395
|
this.runtime = runtime;
|
|
389
|
-
this.
|
|
396
|
+
this.persistentCacheBaseline = resolveRuntimeAssetCacheOptions(config.persistentCache);
|
|
397
|
+
this.config = { ...config, persistentCache: this.persistentCacheBaseline };
|
|
390
398
|
this.maxAssetBytes = requireBridgeMaxAssetBytes(maxAssetBytes);
|
|
391
399
|
this.languageSysroots = canUseClangLanguageSysroots(runtime, config, languageSysroots);
|
|
392
400
|
this.progress = new RuntimeLoadProgress(runtime, this.languageSysroots);
|
|
@@ -402,7 +410,17 @@ export class WorkerAssetBridge {
|
|
|
402
410
|
this.config.loader === config.loader &&
|
|
403
411
|
integrityKey(this.config) === integrityKey(config) &&
|
|
404
412
|
allowedBaseUrlsKey(this.config) === allowedBaseUrlsKey(config) &&
|
|
405
|
-
this.config.useAssetBridge === config.useAssetBridge
|
|
413
|
+
this.config.useAssetBridge === config.useAssetBridge &&
|
|
414
|
+
JSON.stringify(this.persistentCacheBaseline) ===
|
|
415
|
+
JSON.stringify(resolveRuntimeAssetCacheOptions(config.persistentCache)));
|
|
416
|
+
}
|
|
417
|
+
/** Apply one execution's policy without changing the configuration established by load(). */
|
|
418
|
+
setExecutionPersistentCache(override) {
|
|
419
|
+
if (this.state !== 'active')
|
|
420
|
+
throw new Error('Cannot configure an inactive worker asset bridge');
|
|
421
|
+
const cache = resolveRuntimeAssetCacheOptions(this.persistentCacheBaseline, override);
|
|
422
|
+
this.config = { ...this.config, persistentCache: cache };
|
|
423
|
+
return cache;
|
|
406
424
|
}
|
|
407
425
|
rebind(worker, config, progress, maxAssetBytes = this.maxAssetBytes, languageSysroots = this.languageSysroots) {
|
|
408
426
|
if (this.state === 'disposed') {
|
|
@@ -425,7 +443,8 @@ export class WorkerAssetBridge {
|
|
|
425
443
|
throw new Error('Cannot rebind a disposed worker asset bridge');
|
|
426
444
|
}
|
|
427
445
|
this.worker = worker;
|
|
428
|
-
this.
|
|
446
|
+
this.persistentCacheBaseline = resolveRuntimeAssetCacheOptions(config.persistentCache);
|
|
447
|
+
this.config = { ...config, persistentCache: this.persistentCacheBaseline };
|
|
429
448
|
this.maxAssetBytes = nextMaxAssetBytes;
|
|
430
449
|
this.languageSysroots = nextLanguageSysroots;
|
|
431
450
|
this.expectedAssets = expectedAssetsForRuntime(this.runtime, nextLanguageSysroots);
|
|
@@ -520,53 +539,75 @@ export class WorkerAssetBridge {
|
|
|
520
539
|
const worker = this.worker;
|
|
521
540
|
const generation = this.generation;
|
|
522
541
|
const controller = new AbortController();
|
|
542
|
+
this.persistentCacheBySignal.set(controller.signal, resolveRuntimeAssetCacheOptions(this.config.persistentCache));
|
|
523
543
|
this.activeLoads.add(controller);
|
|
524
544
|
try {
|
|
525
|
-
|
|
526
|
-
const
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
this.
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
.toLowerCase()
|
|
542
|
-
.split(',')
|
|
543
|
-
.map((encoding) => encoding.trim())
|
|
544
|
-
.includes('gzip');
|
|
545
|
-
if (controller.signal.aborted || generation !== this.generation)
|
|
546
|
-
return;
|
|
547
|
-
let cancelOnAbort;
|
|
548
|
-
const aborted = new Promise((_resolve, reject) => {
|
|
549
|
-
cancelOnAbort = () => reject(runtimeAssetAbortReason(controller.signal));
|
|
550
|
-
controller.signal.addEventListener('abort', cancelOnAbort, { once: true });
|
|
551
|
-
});
|
|
552
|
-
try {
|
|
553
|
-
if (this.config.integrity?.[request.asset]) {
|
|
554
|
-
this.progress.activity('verifying', request.asset);
|
|
545
|
+
this.validateAssetRequest(request.asset);
|
|
546
|
+
const key = JSON.stringify([
|
|
547
|
+
this.runtime,
|
|
548
|
+
this.config.baseUrl,
|
|
549
|
+
this.cache?.identity(this.config.loader),
|
|
550
|
+
integrityKey(this.config),
|
|
551
|
+
allowedBaseUrlsKey(this.config),
|
|
552
|
+
this.config.useAssetBridge,
|
|
553
|
+
this.maxAssetBytes,
|
|
554
|
+
this.languageSysroots,
|
|
555
|
+
request.asset,
|
|
556
|
+
request.module === true ? 'module' : 'bytes'
|
|
557
|
+
]);
|
|
558
|
+
if (request.module === true) {
|
|
559
|
+
if (!/\.wasm(?:\.gz)?$/u.test(request.asset)) {
|
|
560
|
+
throw new Error('Only runtime Wasm assets can be compiled');
|
|
555
561
|
}
|
|
556
|
-
|
|
557
|
-
|
|
562
|
+
let module = this.cache?.get(key);
|
|
563
|
+
if (!module) {
|
|
564
|
+
const streaming = this.runtime === 'clang' &&
|
|
565
|
+
shouldStreamBundledClang(this.config) &&
|
|
566
|
+
(request.asset === 'bin/clang.wasm.gz' ||
|
|
567
|
+
request.asset === 'bin/lld.wasm.gz');
|
|
568
|
+
let bytes;
|
|
569
|
+
if (streaming) {
|
|
570
|
+
const receipt = BUNDLED_CLANG_ASSET_INTEGRITY[request.asset];
|
|
571
|
+
module = await compileVerifiedWasmAsset(new URL(request.asset, this.config.baseUrl).href, receipt, {
|
|
572
|
+
fetch: globalThis.fetch.bind(globalThis),
|
|
573
|
+
persistentCache: this.persistentCacheBySignal.get(controller.signal),
|
|
574
|
+
maxAssetBytes: this.maxAssetBytes,
|
|
575
|
+
signal: controller.signal,
|
|
576
|
+
onProgress: (loaded, total) => this.progress.update(request.asset, loaded, total)
|
|
577
|
+
});
|
|
578
|
+
bytes = receipt.uncompressedBytes;
|
|
579
|
+
}
|
|
580
|
+
else {
|
|
581
|
+
const loaded = await this.loadVerifiedAsset(request.asset, controller.signal);
|
|
582
|
+
bytes = loaded.bytes.byteLength;
|
|
583
|
+
module = await WebAssembly.compile(Uint8Array.from(loaded.bytes));
|
|
584
|
+
}
|
|
585
|
+
if (controller.signal.aborted || generation !== this.generation)
|
|
586
|
+
return;
|
|
587
|
+
this.cache?.set(key, module, bytes);
|
|
588
|
+
}
|
|
589
|
+
if (controller.signal.aborted || generation !== this.generation)
|
|
590
|
+
return;
|
|
591
|
+
worker.postMessage({ assetResponse: { id: request.id, ok: true, module } });
|
|
592
|
+
return;
|
|
558
593
|
}
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
594
|
+
let loaded = this.cache?.get(key);
|
|
595
|
+
if (!loaded) {
|
|
596
|
+
loaded = await this.loadVerifiedAsset(request.asset, controller.signal);
|
|
597
|
+
if (controller.signal.aborted || generation !== this.generation)
|
|
598
|
+
return;
|
|
599
|
+
// Keep private copies: never transfer or lend the owner cache's backing buffer.
|
|
600
|
+
if (this.cache) {
|
|
601
|
+
loaded = { bytes: Uint8Array.from(loaded.bytes), mimeType: loaded.mimeType };
|
|
602
|
+
this.cache.set(key, loaded, loaded.bytes.byteLength);
|
|
562
603
|
}
|
|
563
604
|
}
|
|
564
|
-
if (controller.signal.aborted || generation !== this.generation)
|
|
565
|
-
return;
|
|
566
605
|
if (this.runtime === 'python' && request.asset === 'pyodide-lock.json') {
|
|
567
|
-
this.pythonPackageAssets = readPythonPackageAssets(
|
|
606
|
+
this.pythonPackageAssets = readPythonPackageAssets(loaded.bytes);
|
|
568
607
|
}
|
|
569
|
-
|
|
608
|
+
if (controller.signal.aborted || generation !== this.generation)
|
|
609
|
+
return;
|
|
610
|
+
const buffer = transferBuffer(loaded.bytes, this.cache ? false : loaded.transferOwnership);
|
|
570
611
|
worker.postMessage({
|
|
571
612
|
assetResponse: {
|
|
572
613
|
id: request.id,
|
|
@@ -589,20 +630,73 @@ export class WorkerAssetBridge {
|
|
|
589
630
|
});
|
|
590
631
|
}
|
|
591
632
|
catch {
|
|
592
|
-
// The worker may already be terminated.
|
|
633
|
+
// The worker may already be terminated.
|
|
593
634
|
}
|
|
594
635
|
}
|
|
595
636
|
finally {
|
|
596
637
|
this.activeLoads.delete(controller);
|
|
597
638
|
}
|
|
598
639
|
}
|
|
599
|
-
async
|
|
640
|
+
async loadVerifiedAsset(asset, signal) {
|
|
641
|
+
const loaded = await this.loadAsset(asset, signal);
|
|
642
|
+
const deliveryBytes = canonicalUint8Array(loaded.bytes);
|
|
643
|
+
const sourceAssetByteLimit = this.sourceAssetByteLimit(asset);
|
|
644
|
+
const runtimeAssetByteLimit = this.runtimeAssetByteLimit(asset);
|
|
645
|
+
requireRuntimeAssetSize(asset, deliveryBytes.byteLength, sourceAssetByteLimit);
|
|
646
|
+
let normalizedRuntimeBytes;
|
|
647
|
+
if (asset.endsWith('.gz')) {
|
|
648
|
+
this.progress.activity('decompressing', asset);
|
|
649
|
+
normalizedRuntimeBytes = await decompressGzip(deliveryBytes, asset, runtimeAssetByteLimit, signal);
|
|
650
|
+
}
|
|
651
|
+
else {
|
|
652
|
+
normalizedRuntimeBytes = deliveryBytes;
|
|
653
|
+
}
|
|
654
|
+
const runtimeBytes = canonicalUint8Array(normalizedRuntimeBytes);
|
|
655
|
+
requireRuntimeAssetSize(asset, runtimeBytes.byteLength, runtimeAssetByteLimit);
|
|
656
|
+
const httpDecodedGzip = (loaded.contentEncoding || '')
|
|
657
|
+
.toLowerCase()
|
|
658
|
+
.split(',')
|
|
659
|
+
.map((encoding) => encoding.trim())
|
|
660
|
+
.includes('gzip');
|
|
661
|
+
if (signal.aborted)
|
|
662
|
+
throw runtimeAssetAbortReason(signal);
|
|
663
|
+
let cancelOnAbort;
|
|
664
|
+
const aborted = new Promise((_resolve, reject) => {
|
|
665
|
+
cancelOnAbort = () => reject(runtimeAssetAbortReason(signal));
|
|
666
|
+
signal.addEventListener('abort', cancelOnAbort, { once: true });
|
|
667
|
+
});
|
|
668
|
+
try {
|
|
669
|
+
if (this.config.integrity?.[asset]) {
|
|
670
|
+
this.progress.activity('verifying', asset);
|
|
671
|
+
}
|
|
672
|
+
const verification = this.verifyIntegrity(asset, deliveryBytes, runtimeBytes, loaded.mimeType, !httpDecodedGzip);
|
|
673
|
+
await Promise.race([verification, aborted]);
|
|
674
|
+
}
|
|
675
|
+
finally {
|
|
676
|
+
if (cancelOnAbort) {
|
|
677
|
+
signal.removeEventListener('abort', cancelOnAbort);
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
if (signal.aborted)
|
|
681
|
+
throw runtimeAssetAbortReason(signal);
|
|
682
|
+
if (this.runtime === 'python' && asset === 'pyodide-lock.json')
|
|
683
|
+
readPythonPackageAssets(runtimeBytes);
|
|
684
|
+
return {
|
|
685
|
+
bytes: runtimeBytes,
|
|
686
|
+
mimeType: loaded.mimeType,
|
|
687
|
+
transferOwnership: normalizedRuntimeBytes === deliveryBytes ? loaded.transferOwnership : true
|
|
688
|
+
};
|
|
689
|
+
}
|
|
690
|
+
validateAssetRequest(asset) {
|
|
600
691
|
if (!this.expectedAssets.has(asset) && !this.pythonPackageAssets.has(asset)) {
|
|
601
692
|
throw new Error(`Unexpected ${this.runtime} runtime asset: ${asset}`);
|
|
602
693
|
}
|
|
603
694
|
if (this.config.integrity && !Object.hasOwn(this.config.integrity, asset)) {
|
|
604
695
|
throw new Error(`Runtime asset ${asset} is missing integrity metadata`);
|
|
605
696
|
}
|
|
697
|
+
}
|
|
698
|
+
async loadAsset(asset, signal) {
|
|
699
|
+
this.validateAssetRequest(asset);
|
|
606
700
|
if (signal.aborted) {
|
|
607
701
|
throw runtimeAssetAbortReason(signal);
|
|
608
702
|
}
|
|
@@ -753,6 +847,56 @@ export class WorkerAssetBridge {
|
|
|
753
847
|
return null;
|
|
754
848
|
}
|
|
755
849
|
async fetchAsset(url, asset, signal, maxAssetBytes = this.sourceAssetByteLimit(asset)) {
|
|
850
|
+
const requestUrl = this.requireAllowedAssetUrl(asset, url);
|
|
851
|
+
const persistentCache = this.persistentCacheBySignal.get(signal) ?? this.config.persistentCache;
|
|
852
|
+
const configured = this.config.integrity?.[asset];
|
|
853
|
+
const expected = typeof configured === 'string' ? { sha256: configured } : configured;
|
|
854
|
+
const lock = this.config.assetPrefix
|
|
855
|
+
? resolveRuntimeAssetLockEntry(requestUrl, {
|
|
856
|
+
assetRoot: this.config.baseUrl,
|
|
857
|
+
assetPrefix: this.config.assetPrefix
|
|
858
|
+
})
|
|
859
|
+
: undefined;
|
|
860
|
+
// Existing .gz receipts without a pair describe logical bytes, not stored gzip bytes.
|
|
861
|
+
const receipt = expected && (!asset.endsWith('.gz') || expected.uncompressedSha256) ? expected : lock;
|
|
862
|
+
const identity = receipt
|
|
863
|
+
? {
|
|
864
|
+
url: requestUrl.href,
|
|
865
|
+
sha256: receipt.sha256,
|
|
866
|
+
bytes: receipt.bytes,
|
|
867
|
+
validationKey: JSON.stringify([
|
|
868
|
+
'bridge-v1',
|
|
869
|
+
this.config.baseUrl,
|
|
870
|
+
allowedBaseUrlsKey(this.config),
|
|
871
|
+
maxAssetBytes
|
|
872
|
+
])
|
|
873
|
+
}
|
|
874
|
+
: undefined;
|
|
875
|
+
if (identity && (identity.bytes === undefined || identity.bytes <= maxAssetBytes)) {
|
|
876
|
+
const bytes = await readPersistentRuntimeAsset({
|
|
877
|
+
identity,
|
|
878
|
+
cache: persistentCache,
|
|
879
|
+
signal
|
|
880
|
+
});
|
|
881
|
+
if (bytes) {
|
|
882
|
+
requireRuntimeAssetSize(asset, bytes.byteLength, maxAssetBytes);
|
|
883
|
+
this.progress.update(asset, bytes.byteLength, bytes.byteLength);
|
|
884
|
+
return { bytes, mimeType: receipt?.mediaType, transferOwnership: true };
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
const loaded = await this.fetchAssetFromNetwork(url, asset, signal, maxAssetBytes);
|
|
888
|
+
if (identity && !loaded.contentEncoding) {
|
|
889
|
+
// Only checksum-matching bytes are published. Existing runtime validation still runs.
|
|
890
|
+
await writePersistentRuntimeAsset({
|
|
891
|
+
identity,
|
|
892
|
+
cache: persistentCache,
|
|
893
|
+
signal,
|
|
894
|
+
bytes: loaded.bytes
|
|
895
|
+
});
|
|
896
|
+
}
|
|
897
|
+
return loaded;
|
|
898
|
+
}
|
|
899
|
+
async fetchAssetFromNetwork(url, asset, signal, maxAssetBytes = this.sourceAssetByteLimit(asset)) {
|
|
756
900
|
const requestUrl = this.requireAllowedAssetUrl(asset, url);
|
|
757
901
|
if (signal.aborted)
|
|
758
902
|
throw runtimeAssetAbortReason(signal);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type RuntimeAssetCacheOptions } from '@wasm-idle/core';
|
|
1
2
|
import { type DOuterAssetReceipts } from './dOuterAssets';
|
|
2
3
|
import type { ElixirRuntimeAssetReceipts } from './elixirAssets';
|
|
3
4
|
import { type FortranExecutionAssetReceipts } from './fortranAssets';
|
|
@@ -25,6 +26,7 @@ export type RuntimeAssetLoader = (request: RuntimeAssetLoadRequest) => RuntimeAs
|
|
|
25
26
|
export type RuntimeAssetIntegrityEntry = CoreRuntimeAssetIntegrityEntry;
|
|
26
27
|
export type RuntimeAssetIntegrityMap = Record<string, string | RuntimeAssetIntegrityEntry>;
|
|
27
28
|
export interface RuntimeAssetConfig {
|
|
29
|
+
persistentCache?: import('@wasm-idle/core').RuntimeAssetCacheOptions;
|
|
28
30
|
baseUrl?: string;
|
|
29
31
|
loader?: RuntimeAssetLoader;
|
|
30
32
|
loaderKey?: string;
|
|
@@ -139,11 +141,14 @@ export interface LispRuntimeAssetConfig {
|
|
|
139
141
|
moduleUrl?: string;
|
|
140
142
|
manifestUrl?: string;
|
|
141
143
|
manifestFingerprint?: string;
|
|
144
|
+
/** Optional raw JSON byte receipt; distinct from the canonical manifest fingerprint. */
|
|
145
|
+
manifestReceipt?: RuntimeAssetIntegrityEntry;
|
|
142
146
|
}
|
|
143
147
|
export interface ResolvedLispRuntimeAssetConfig {
|
|
144
148
|
moduleUrl: string;
|
|
145
149
|
manifestUrl: string;
|
|
146
150
|
manifestFingerprint: string;
|
|
151
|
+
manifestReceipt?: RuntimeAssetIntegrityEntry;
|
|
147
152
|
}
|
|
148
153
|
export interface RubyRuntimeAssetConfig {
|
|
149
154
|
/** Keep full stdlib compatibility, but load its data separately from the core Wasm. */
|
|
@@ -563,6 +568,9 @@ export interface TinyGoRuntimeAssetLoaderRequest {
|
|
|
563
568
|
export type TinyGoRuntimeAssetLoaderResult = RuntimeAssetDataResult | RuntimeAssetUrlResult | string | URL | ArrayBuffer | Uint8Array | Blob | null | undefined;
|
|
564
569
|
export type TinyGoRuntimeAssetLoader = (request: TinyGoRuntimeAssetLoaderRequest) => TinyGoRuntimeAssetLoaderResult | Promise<TinyGoRuntimeAssetLoaderResult>;
|
|
565
570
|
export interface ResolvedRuntimeAssetConfig {
|
|
571
|
+
persistentCache?: import('@wasm-idle/core').RuntimeAssetCacheOptions;
|
|
572
|
+
/** Built-in lock prefix; custom loaders use only explicitly supplied receipts. */
|
|
573
|
+
assetPrefix?: string;
|
|
566
574
|
baseUrl: string;
|
|
567
575
|
loader?: RuntimeAssetLoader;
|
|
568
576
|
integrity?: RuntimeAssetIntegrityMap;
|
|
@@ -607,7 +615,7 @@ export declare const RUNTIME_LOAD_ASSETS: {
|
|
|
607
615
|
clang: readonly ["runtime-manifest.v1.json", "bin/memfs.wasm.gz", "bin/clang.wasm.gz", "bin/lld.wasm.gz", "bin/sysroot.tar.gz"];
|
|
608
616
|
clangd: readonly ["clangd.js", "clangd.wasm.gz"];
|
|
609
617
|
};
|
|
610
|
-
export declare function resolveRuntimeAssetConfig(runtime: RuntimeAssetRuntime, options: string | PlaygroundRuntimeAssets | undefined, currentUrl?: string): ResolvedRuntimeAssetConfig;
|
|
618
|
+
export declare function resolveRuntimeAssetConfig(runtime: RuntimeAssetRuntime, options: string | PlaygroundRuntimeAssets | undefined, currentUrl?: string, callCache?: RuntimeAssetCacheOptions): ResolvedRuntimeAssetConfig;
|
|
611
619
|
export declare function resolveRustCompilerUrl(options: string | PlaygroundRuntimeAssets | undefined, currentUrl?: string): string;
|
|
612
620
|
export declare function resolveDebugRuntimeUrls(options: string | PlaygroundRuntimeAssets | undefined, currentUrl?: string): {
|
|
613
621
|
baseUrl: string;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { env as dynamicPublicEnv } from '$env/dynamic/public';
|
|
2
|
+
import { resolveRuntimeAssetCacheOptions, resolveRuntimeAssetLockEntry } from '@wasm-idle/core';
|
|
2
3
|
import { BUNDLED_CLANG_ASSET_INTEGRITY } from './clangAssetIntegrity';
|
|
3
4
|
import { snapshotDOuterAssetConfig } from './dOuterAssets';
|
|
4
5
|
import { snapshotFortranExecutionAssetReceipts } from './fortranAssets';
|
|
@@ -100,7 +101,21 @@ const RUNTIME_ASSET_FOLDERS = {
|
|
|
100
101
|
const resolveRuntimeRootBaseUrl = (config, rootUrl = '', currentUrl = '') => config.resolveRootBaseUrl?.(rootUrl, currentUrl) ||
|
|
101
102
|
resolveFolderRuntimeBaseUrl(config.folder, rootUrl, currentUrl);
|
|
102
103
|
const resolveRuntimeConfiguredBaseUrl = (config, baseUrl, currentUrl = '') => config.resolveConfiguredBaseUrl?.(baseUrl, currentUrl) || normalizeBaseUrl(baseUrl, currentUrl);
|
|
103
|
-
export function resolveRuntimeAssetConfig(runtime, options, currentUrl = '') {
|
|
104
|
+
export function resolveRuntimeAssetConfig(runtime, options, currentUrl = '', callCache) {
|
|
105
|
+
const config = resolveRuntimeAssetConfigWithoutCache(runtime, options, currentUrl);
|
|
106
|
+
const runtimeConfig = typeof options === 'object' ? options?.[runtime] : undefined;
|
|
107
|
+
const persistentCache = resolveRuntimeAssetCacheOptions(typeof options === 'object' ? options?.persistentCache : undefined, runtimeConfig?.persistentCache, callCache);
|
|
108
|
+
const assetPrefix = !config.loader && !runtimeConfig?.baseUrl
|
|
109
|
+
? RUNTIME_ASSET_FOLDERS[runtime].folder
|
|
110
|
+
: undefined;
|
|
111
|
+
return {
|
|
112
|
+
...config,
|
|
113
|
+
persistentCache,
|
|
114
|
+
assetPrefix,
|
|
115
|
+
useAssetBridge: config.useAssetBridge || (persistentCache.enabled && !!assetPrefix)
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
function resolveRuntimeAssetConfigWithoutCache(runtime, options, currentUrl = '') {
|
|
104
119
|
const runtimeFolder = RUNTIME_ASSET_FOLDERS[runtime];
|
|
105
120
|
if (typeof options === 'string') {
|
|
106
121
|
const integrity = resolveRuntimeAssetIntegrity(runtime, undefined);
|
|
@@ -733,12 +748,21 @@ export function resolveLispRuntimeAssetConfig(options, currentUrl = '') {
|
|
|
733
748
|
const configuredFingerprint = configured?.manifestFingerprint?.trim() ||
|
|
734
749
|
(publicEnv.PUBLIC_WASM_LISP_MANIFEST_FINGERPRINT || '').trim();
|
|
735
750
|
const usesBundledRoot = !configuredModuleUrl && !publicModuleUrl && rootUrl !== undefined;
|
|
751
|
+
const manifestUrl = configuredManifestUrl
|
|
752
|
+
? resolveConfiguredUrl(configuredManifestUrl, currentUrl)
|
|
753
|
+
: deriveLispManifestUrl(moduleUrl, currentUrl);
|
|
754
|
+
const manifestReceipt = configured?.manifestReceipt ??
|
|
755
|
+
(usesBundledRoot && !configuredManifestUrl && !configuredFingerprint
|
|
756
|
+
? resolveRuntimeAssetLockEntry(manifestUrl, {
|
|
757
|
+
assetRoot: new URL('./', new URL(moduleUrl, currentUrl || 'http://localhost/')),
|
|
758
|
+
assetPrefix: 'wasm-lisp'
|
|
759
|
+
})
|
|
760
|
+
: undefined);
|
|
736
761
|
return {
|
|
737
762
|
moduleUrl,
|
|
738
|
-
manifestUrl
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
manifestFingerprint: configuredFingerprint || (usesBundledRoot ? WASM_LISP_ASSET_VERSION : '')
|
|
763
|
+
manifestUrl,
|
|
764
|
+
manifestFingerprint: configuredFingerprint || (usesBundledRoot ? WASM_LISP_ASSET_VERSION : ''),
|
|
765
|
+
...(manifestReceipt ? { manifestReceipt: Object.freeze({ ...manifestReceipt }) } : {})
|
|
742
766
|
};
|
|
743
767
|
}
|
|
744
768
|
const RUBY_RUNTIME_CONFIG_KEYS = [
|
package/dist/playground/awk.js
CHANGED
|
@@ -40,6 +40,7 @@ class Awk extends StaticWorkerRuntimeSandbox {
|
|
|
40
40
|
manifestUrl: resolved.manifestUrl,
|
|
41
41
|
profile,
|
|
42
42
|
limits: context.limits,
|
|
43
|
+
persistentCache: context.persistentCache,
|
|
43
44
|
signal: context.signal,
|
|
44
45
|
reportProgress(progress) {
|
|
45
46
|
loadedByAsset.set(progress.assetKey, progress.loadedBytes);
|