wasm-idle 1.0.6 → 1.0.8
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 +18 -5
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -0
- package/dist/playground/assetBridge.d.ts +6 -1
- package/dist/playground/assetBridge.js +77 -4
- 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.js +15 -8
- package/dist/playground/clang.d.ts +1 -0
- package/dist/playground/clang.js +8 -1
- package/dist/playground/clangAssetIntegrity.d.ts +6 -0
- package/dist/playground/clangAssetIntegrity.js +3 -2
- 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/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.js +3 -1
- package/dist/playground/runtimeSession.d.ts +2 -1
- package/dist/playground/runtimeSession.js +2 -2
- 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/clang.js +1 -5
- 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/runtimeAssetFetch.d.ts +11 -1
- package/dist/playground/worker/runtimeAssetFetch.js +64 -1
- 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
|
@@ -21,6 +21,8 @@ export interface SandboxWorkspaceFile {
|
|
|
21
21
|
content: string;
|
|
22
22
|
}
|
|
23
23
|
export interface SandboxExecutionOptions {
|
|
24
|
+
/** Overrides instance/global persistent asset caching for this operation. */
|
|
25
|
+
persistentCache?: import('@wasm-idle/core').RuntimeAssetCacheOptions;
|
|
24
26
|
debugMode?: BrowserDebugMode;
|
|
25
27
|
/** @deprecated Use debugMode. true maps to trace unless the caller explicitly selects lldb. */
|
|
26
28
|
debug?: boolean;
|
|
@@ -40,6 +40,7 @@ class Pascal extends StaticWorkerRuntimeSandbox {
|
|
|
40
40
|
systemPascalUrl: resolved.systemPascalUrl,
|
|
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);
|
package/dist/playground/perl.js
CHANGED
|
@@ -38,6 +38,7 @@ class Perl extends StaticWorkerRuntimeSandbox {
|
|
|
38
38
|
manifestUrl: urls.manifestUrl || '',
|
|
39
39
|
profile,
|
|
40
40
|
limits: context.limits,
|
|
41
|
+
persistentCache: context.persistentCache,
|
|
41
42
|
signal: context.signal,
|
|
42
43
|
reportProgress(progress) {
|
|
43
44
|
loadedByAsset.set(progress.assetKey, progress.loadedBytes);
|
|
@@ -47,6 +47,7 @@ class Prolog extends StaticWorkerRuntimeSandbox {
|
|
|
47
47
|
manifestUrl: urls.manifestUrl || '',
|
|
48
48
|
profile,
|
|
49
49
|
limits: context.limits,
|
|
50
|
+
persistentCache: context.persistentCache,
|
|
50
51
|
signal: context.signal,
|
|
51
52
|
reportProgress(progress) {
|
|
52
53
|
if (progress.kind === 'asset') {
|
|
@@ -205,7 +205,7 @@ class Python {
|
|
|
205
205
|
this.pendingInput = [];
|
|
206
206
|
this.waitingForInput = false;
|
|
207
207
|
this.pendingEof = false;
|
|
208
|
-
const assetConfig = resolveRuntimeAssetConfig('python', runtimeAssets, typeof window !== 'undefined' ? window.location.href : '');
|
|
208
|
+
const assetConfig = resolveRuntimeAssetConfig('python', runtimeAssets, typeof window !== 'undefined' ? window.location.href : '', options.persistentCache);
|
|
209
209
|
if (!this.isOperationActive(operation))
|
|
210
210
|
return;
|
|
211
211
|
const needsWorkerReset = !this.worker ||
|
|
@@ -343,11 +343,13 @@ class Python {
|
|
|
343
343
|
activePath = options.activePath;
|
|
344
344
|
debugPath = options.debugPath;
|
|
345
345
|
workspaceFiles = options.workspaceFiles;
|
|
346
|
+
const persistentCache = options.persistentCache;
|
|
346
347
|
if (!this.isOperationActive(activeOperation)) {
|
|
347
348
|
return Promise.reject(this.releaseBeforeSession(activeOperation, 'Python execution cancelled'));
|
|
348
349
|
}
|
|
349
350
|
if (debug)
|
|
350
351
|
requireSharedArrayBuffer('Python debugging');
|
|
352
|
+
this.assetBridge?.setExecutionPersistentCache(persistentCache);
|
|
351
353
|
this.setBreakpoints(debug ? breakpoints : []);
|
|
352
354
|
}
|
|
353
355
|
catch (error) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type PlaygroundBindingOptions } from '@wasm-idle/core';
|
|
1
2
|
import type { PlaygroundBinding, SandboxRuntimeAssets } from './sandbox';
|
|
2
3
|
import { RuntimeAssetCache } from './runtimeAssetCache';
|
|
3
4
|
import { CompiledArtifactCache } from './compiledArtifactCache';
|
|
@@ -17,4 +18,4 @@ export interface PlaygroundRuntimeSession {
|
|
|
17
18
|
* A browser-owned language session. Panels own disposable execution leases, not the
|
|
18
19
|
* compiler cache. A problem/editor change may release all leases without cooling it.
|
|
19
20
|
*/
|
|
20
|
-
export declare function createRuntimeSession(runtimeAssets: SandboxRuntimeAssets): PlaygroundRuntimeSession;
|
|
21
|
+
export declare function createRuntimeSession(runtimeAssets: SandboxRuntimeAssets, options?: PlaygroundBindingOptions): PlaygroundRuntimeSession;
|
|
@@ -7,7 +7,7 @@ import { createCachedClangSandbox } from './cachedClang';
|
|
|
7
7
|
* A browser-owned language session. Panels own disposable execution leases, not the
|
|
8
8
|
* compiler cache. A problem/editor change may release all leases without cooling it.
|
|
9
9
|
*/
|
|
10
|
-
export function createRuntimeSession(runtimeAssets) {
|
|
10
|
+
export function createRuntimeSession(runtimeAssets, options = {}) {
|
|
11
11
|
let language;
|
|
12
12
|
let epoch = 0;
|
|
13
13
|
let disposed = false;
|
|
@@ -86,7 +86,7 @@ export function createRuntimeSession(runtimeAssets) {
|
|
|
86
86
|
return target === 'C' || target === 'CPP'
|
|
87
87
|
? createCachedClangSandbox(sandbox, target, cache, artifacts)
|
|
88
88
|
: sandbox;
|
|
89
|
-
});
|
|
89
|
+
}, options);
|
|
90
90
|
leases.add(lease);
|
|
91
91
|
const binding = core;
|
|
92
92
|
// Do not override core.dispose in place: the lease calls that exact owner method.
|
|
@@ -19,6 +19,7 @@ declare class Rust implements Sandbox {
|
|
|
19
19
|
debugManifestUrl: string;
|
|
20
20
|
debugManifestReceipt?: Readonly<RuntimeAssetIntegrityEntry>;
|
|
21
21
|
executableGraphFingerprint: string;
|
|
22
|
+
private persistentCacheBaseline?;
|
|
22
23
|
oncompilerdiagnostic?: (diagnostic: CompilerDiagnostic) => void;
|
|
23
24
|
waitingForInput: boolean;
|
|
24
25
|
pendingEof: boolean;
|
package/dist/playground/rust.js
CHANGED
|
@@ -8,7 +8,7 @@ import { resolveRustNonDebugResourceLimits } from './rustWorkerLimits';
|
|
|
8
8
|
import { WASM_RUST_EXECUTABLE_GRAPH_PROFILE, WASM_RUST_RUNTIME_PROFILE } from './wasmRustVersion';
|
|
9
9
|
import { WorkerSession } from './workerSession';
|
|
10
10
|
import { reportWorkerInputReady, reportWorkerProgress } from './workerProgress';
|
|
11
|
-
import { resolveExecutionLimits, TimeoutError } from '@wasm-idle/core';
|
|
11
|
+
import { resolveExecutionLimits, resolveRuntimeAssetCacheOptions, TimeoutError } from '@wasm-idle/core';
|
|
12
12
|
const debugBreakpointBufferInts = 1028;
|
|
13
13
|
const rustLldbSourcePath = '/workspace/main.rs';
|
|
14
14
|
const outputEncoder = new TextEncoder();
|
|
@@ -54,6 +54,7 @@ class Rust {
|
|
|
54
54
|
debugManifestUrl = '';
|
|
55
55
|
debugManifestReceipt;
|
|
56
56
|
executableGraphFingerprint = '';
|
|
57
|
+
persistentCacheBaseline;
|
|
57
58
|
oncompilerdiagnostic;
|
|
58
59
|
waitingForInput = false;
|
|
59
60
|
pendingEof = false;
|
|
@@ -122,6 +123,7 @@ class Rust {
|
|
|
122
123
|
let clearCandidateWait = () => { };
|
|
123
124
|
try {
|
|
124
125
|
const currentUrl = typeof window !== 'undefined' ? window.location.href : '';
|
|
126
|
+
const persistentCache = resolveRuntimeAssetCacheOptions(typeof runtimeAssets === 'object' ? runtimeAssets.persistentCache : undefined, _options.persistentCache);
|
|
125
127
|
const nextCompilerUrl = resolveRustCompilerUrl(runtimeAssets, currentUrl);
|
|
126
128
|
const nextDebugModuleUrl = resolveRustDebugModuleUrl(runtimeAssets, currentUrl);
|
|
127
129
|
const debugRuntime = resolveDebugRuntimeUrls(runtimeAssets, currentUrl);
|
|
@@ -175,6 +177,7 @@ class Rust {
|
|
|
175
177
|
this.executableGraphFingerprint !==
|
|
176
178
|
WASM_RUST_EXECUTABLE_GRAPH_PROFILE.fingerprint;
|
|
177
179
|
if (!needsWorkerReset) {
|
|
180
|
+
this.persistentCacheBaseline = persistentCache;
|
|
178
181
|
this.debugRuntimeBaseUrl = nextDebugRuntimeBaseUrl;
|
|
179
182
|
this.debugManifestUrl = nextDebugManifestUrl;
|
|
180
183
|
this.debugManifestReceipt = nextDebugManifestReceipt;
|
|
@@ -182,6 +185,7 @@ class Rust {
|
|
|
182
185
|
return;
|
|
183
186
|
}
|
|
184
187
|
nextExecutableGraph = await loadVerifiedRustExecutableGraph({
|
|
188
|
+
persistentCache,
|
|
185
189
|
moduleUrl: nextCompilerUrl,
|
|
186
190
|
currentUrl,
|
|
187
191
|
profile: WASM_RUST_EXECUTABLE_GRAPH_PROFILE,
|
|
@@ -255,6 +259,7 @@ class Rust {
|
|
|
255
259
|
};
|
|
256
260
|
candidateWorker.postMessage({
|
|
257
261
|
load: true,
|
|
262
|
+
persistentCache,
|
|
258
263
|
compilerUrl: nextExecutableGraph.entryUrl,
|
|
259
264
|
debugModuleUrl: nextDebugModuleUrl,
|
|
260
265
|
path: nextAssetPath,
|
|
@@ -274,6 +279,7 @@ class Rust {
|
|
|
274
279
|
this.waitingForInput = false;
|
|
275
280
|
this.pendingEof = false;
|
|
276
281
|
this.compilerUrl = nextCompilerUrl;
|
|
282
|
+
this.persistentCacheBaseline = persistentCache;
|
|
277
283
|
this.debugModuleUrl = nextDebugModuleUrl;
|
|
278
284
|
this.assetPath = nextAssetPath;
|
|
279
285
|
this.debugRuntimeBaseUrl = nextDebugRuntimeBaseUrl;
|
|
@@ -360,7 +366,9 @@ class Rust {
|
|
|
360
366
|
}
|
|
361
367
|
let limits;
|
|
362
368
|
let nonDebugResourceLimits;
|
|
369
|
+
let persistentCache;
|
|
363
370
|
try {
|
|
371
|
+
persistentCache = resolveRuntimeAssetCacheOptions(this.persistentCacheBaseline, options.persistentCache);
|
|
364
372
|
limits = resolveExecutionLimits(options.limits);
|
|
365
373
|
nonDebugResourceLimits =
|
|
366
374
|
debugMode === 'none' ? resolveRustNonDebugResourceLimits(limits) : undefined;
|
|
@@ -567,6 +575,7 @@ class Rust {
|
|
|
567
575
|
startPhaseTimeout('run', limits.runTimeoutMs);
|
|
568
576
|
const compilerWorker = this.worker;
|
|
569
577
|
const lldbSession = new LldbSandboxSession({
|
|
578
|
+
persistentCache,
|
|
570
579
|
manifestUrl: this.debugManifestUrl,
|
|
571
580
|
manifestReceipt: this.debugManifestReceipt,
|
|
572
581
|
runtimeBaseUrl: this.debugRuntimeBaseUrl,
|
|
@@ -671,6 +680,7 @@ class Rust {
|
|
|
671
680
|
this.begin = Date.now();
|
|
672
681
|
try {
|
|
673
682
|
this.worker.postMessage({
|
|
683
|
+
persistentCache,
|
|
674
684
|
code,
|
|
675
685
|
prepare,
|
|
676
686
|
buffer: this.buffer,
|
|
@@ -70,6 +70,7 @@ export interface RustExecutableGraphProgress {
|
|
|
70
70
|
readonly totalBytes: number;
|
|
71
71
|
}
|
|
72
72
|
export interface LoadRustExecutableGraphOptions {
|
|
73
|
+
readonly persistentCache?: import('@wasm-idle/core').RuntimeAssetCacheOptions;
|
|
73
74
|
readonly moduleUrl: string;
|
|
74
75
|
readonly currentUrl?: string;
|
|
75
76
|
readonly profile: unknown;
|
|
@@ -822,6 +822,7 @@ export async function loadVerifiedRustExecutableGraph(options) {
|
|
|
822
822
|
if (options.assetTimeoutMs !== undefined)
|
|
823
823
|
limits.assetTimeoutMs = options.assetTimeoutMs;
|
|
824
824
|
const preflight = await preflightRuntimeAssets({
|
|
825
|
+
persistentCache: options.persistentCache,
|
|
825
826
|
manifest: createPreflightManifest(profile, sourceContext.keysByPath),
|
|
826
827
|
runtimeId: 'rust/executable-graph',
|
|
827
828
|
rootUrl: sourceContext.storageRootUrl,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ExecutionLimits } from '@wasm-idle/core';
|
|
1
|
+
import { type ExecutionLimits, type RuntimeAssetCacheOptions } from '@wasm-idle/core';
|
|
2
2
|
import { type StaticRuntimePreflightProgress, type StaticRuntimePreflightRuntimeId } from './staticRuntimePreflightProtocol';
|
|
3
3
|
export interface StaticRuntimeWorkerPreflightRequest {
|
|
4
4
|
readonly runtimeId: StaticRuntimePreflightRuntimeId;
|
|
@@ -7,6 +7,7 @@ export interface StaticRuntimeWorkerPreflightRequest {
|
|
|
7
7
|
readonly manifestUrl: string;
|
|
8
8
|
readonly profile: unknown;
|
|
9
9
|
readonly limits?: Partial<ExecutionLimits>;
|
|
10
|
+
readonly persistentCache?: RuntimeAssetCacheOptions;
|
|
10
11
|
readonly signal?: AbortSignal;
|
|
11
12
|
readonly reportProgress?: (progress: StaticRuntimePreflightProgress) => void;
|
|
12
13
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { CancelledError, ProtocolError, TimeoutError, WorkerStartupError, resolveExecutionLimits } from '@wasm-idle/core';
|
|
1
|
+
import { CancelledError, ProtocolError, TimeoutError, WorkerStartupError, resolveExecutionLimits, resolveRuntimeAssetCacheOptions } from '@wasm-idle/core';
|
|
2
2
|
import { STATIC_RUNTIME_PREFLIGHT_PROTOCOL_VERSION, collectStaticRuntimePreflightTransferables, deserializeStaticRuntimePreflightError, isStaticRuntimePreflightProgress, isStaticRuntimePreflightSerializedError } from './staticRuntimePreflightProtocol';
|
|
3
3
|
const REQUEST_ID = 1;
|
|
4
4
|
export async function preflightStaticRuntimeAssetsInWorker(request) {
|
|
5
5
|
const limits = resolveExecutionLimits(request.limits);
|
|
6
|
+
const persistentCache = resolveRuntimeAssetCacheOptions(request.persistentCache);
|
|
6
7
|
if (request.signal?.aborted) {
|
|
7
8
|
throw new CancelledError(`${request.displayName} runtime preflight cancelled`, {
|
|
8
9
|
cause: request.signal.reason,
|
|
@@ -210,7 +211,8 @@ export async function preflightStaticRuntimeAssetsInWorker(request) {
|
|
|
210
211
|
baseUrl: request.baseUrl,
|
|
211
212
|
manifestUrl: request.manifestUrl,
|
|
212
213
|
profile: request.profile,
|
|
213
|
-
limits
|
|
214
|
+
limits,
|
|
215
|
+
persistentCache
|
|
214
216
|
});
|
|
215
217
|
}
|
|
216
218
|
catch (error) {
|
|
@@ -8,6 +8,7 @@ export async function executeStaticRuntimePreflight(request, reportProgress, sig
|
|
|
8
8
|
baseUrl: request.baseUrl,
|
|
9
9
|
manifestUrl: request.manifestUrl,
|
|
10
10
|
limits: request.limits,
|
|
11
|
+
persistentCache: request.persistentCache,
|
|
11
12
|
signal,
|
|
12
13
|
reportProgress: (progress) => reportProgress({ kind: 'asset', progress })
|
|
13
14
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ExecutionLimits, type RuntimeAssetPreflightProgress, type RuntimeErrorCode, type RuntimePhase, type RuntimeResourceKind } from '@wasm-idle/core';
|
|
1
|
+
import { type ExecutionLimits, type RuntimeAssetCacheOptions, type RuntimeAssetPreflightProgress, type RuntimeErrorCode, type RuntimePhase, type RuntimeResourceKind } from '@wasm-idle/core';
|
|
2
2
|
export declare const STATIC_RUNTIME_PREFLIGHT_PROTOCOL_VERSION: 1;
|
|
3
3
|
export type StaticRuntimePreflightRuntimeId = 'BQN' | 'CLOJURESCRIPT' | 'FORTH' | 'J' | 'JANET' | 'PROLOG';
|
|
4
4
|
export type StaticRuntimePreflightProgress = {
|
|
@@ -19,6 +19,7 @@ export interface StaticRuntimePreflightRequestMessage {
|
|
|
19
19
|
readonly manifestUrl: string;
|
|
20
20
|
readonly profile: unknown;
|
|
21
21
|
readonly limits: ExecutionLimits;
|
|
22
|
+
readonly persistentCache?: RuntimeAssetCacheOptions;
|
|
22
23
|
}
|
|
23
24
|
export interface StaticRuntimePreflightProgressMessage {
|
|
24
25
|
readonly protocolVersion: typeof STATIC_RUNTIME_PREFLIGHT_PROTOCOL_VERSION;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { PlaygroundRuntimeAssets } from './assets';
|
|
2
|
-
import { type ExecutionLimits, type RuntimeAssetIntegrityEntry, type RuntimeStdinMode, type RuntimeWorkerLifetimePolicy } from '@wasm-idle/core';
|
|
2
|
+
import { type ExecutionLimits, type RuntimeAssetIntegrityEntry, type RuntimeAssetCacheOptions, type RuntimeStdinMode, type RuntimeWorkerLifetimePolicy } from '@wasm-idle/core';
|
|
3
3
|
import { type CompilerDiagnostic, type SandboxExecutionOptions } from './options';
|
|
4
4
|
import type { Sandbox, SandboxProgress } from './sandbox';
|
|
5
5
|
type StaticWorkerReceipt = Readonly<Required<Pick<RuntimeAssetIntegrityEntry, 'bytes' | 'sha256'>>>;
|
|
@@ -14,6 +14,7 @@ export interface StaticWorkerRuntimeUrls {
|
|
|
14
14
|
}
|
|
15
15
|
export interface StaticWorkerRuntimePreflightContext {
|
|
16
16
|
readonly limits: ExecutionLimits;
|
|
17
|
+
readonly persistentCache?: RuntimeAssetCacheOptions;
|
|
17
18
|
readonly signal?: AbortSignal;
|
|
18
19
|
readonly reportProgress: (value: number, stage?: string) => void;
|
|
19
20
|
/**
|
|
@@ -85,6 +86,7 @@ export declare class StaticWorkerRuntimeSandbox implements Sandbox {
|
|
|
85
86
|
private disposePromise;
|
|
86
87
|
private disposeReason;
|
|
87
88
|
private lifecycleProgress?;
|
|
89
|
+
private persistentCache?;
|
|
88
90
|
private readonly progressController;
|
|
89
91
|
private progressUid;
|
|
90
92
|
private startingRunId;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AssetNotFoundError, AssetTooLargeError, BusyError, CancelledError, DEFAULT_WORKSPACE_LIMITS, DiagnosticLimitError, OutputLimitError, ProtocolError, RuntimeConfigurationError, RuntimeExecutionError, RuntimeProgressController, RuntimeWorkerLifetimeController, TimeoutError, WorkerStartupError, isWasmIdleError, resolveExecutionLimits, validateExecutionWorkspace, verifyRuntimeAssetIntegrity } from '@wasm-idle/core';
|
|
1
|
+
import { AssetNotFoundError, AssetTooLargeError, BusyError, CancelledError, DEFAULT_WORKSPACE_LIMITS, DiagnosticLimitError, OutputLimitError, ProtocolError, RuntimeConfigurationError, RuntimeExecutionError, RuntimeProgressController, RuntimeWorkerLifetimeController, TimeoutError, WorkerStartupError, isWasmIdleError, resolveExecutionLimits, resolveRuntimeAssetCacheOptions, readPersistentRuntimeAsset, writePersistentRuntimeAsset, validateExecutionWorkspace, verifyRuntimeAssetIntegrity } from '@wasm-idle/core';
|
|
2
2
|
import { resolveSandboxExecutionArgs } from './options';
|
|
3
3
|
import { StaticStdinRingHost } from './staticStdinRing';
|
|
4
4
|
import { deserializeStaticRuntimePreflightError, isStaticRuntimePreflightSerializedError, inspectStaticRuntimePreflightBytes } from './staticRuntimePreflightProtocol';
|
|
@@ -39,6 +39,7 @@ export class StaticWorkerRuntimeSandbox {
|
|
|
39
39
|
disposePromise = null;
|
|
40
40
|
disposeReason = null;
|
|
41
41
|
lifecycleProgress;
|
|
42
|
+
persistentCache;
|
|
42
43
|
progressController = new RuntimeProgressController();
|
|
43
44
|
progressUid = 0;
|
|
44
45
|
startingRunId = null;
|
|
@@ -134,7 +135,8 @@ export class StaticWorkerRuntimeSandbox {
|
|
|
134
135
|
async load(runtimeAssets = '', code = '', _log = true, _args = [], options = {}, progress) {
|
|
135
136
|
this.assertNotDisposed();
|
|
136
137
|
try {
|
|
137
|
-
const
|
|
138
|
+
const persistentCache = typeof runtimeAssets === 'string' ? undefined : runtimeAssets.persistentCache;
|
|
139
|
+
const controls = this.resolveExecutionControls(options, persistentCache ?? {});
|
|
138
140
|
this.assertOperationNotDisposed();
|
|
139
141
|
if (controls.signal?.aborted) {
|
|
140
142
|
throw new CancelledError(`${this.config.displayName} startup cancelled`, {
|
|
@@ -149,6 +151,7 @@ export class StaticWorkerRuntimeSandbox {
|
|
|
149
151
|
const currentUrl = typeof window !== 'undefined' ? window.location.href : '';
|
|
150
152
|
const urls = this.config.resolveRuntimeAssets(runtimeAssets, currentUrl);
|
|
151
153
|
this.assertOperationNotDisposed();
|
|
154
|
+
this.persistentCache = persistentCache;
|
|
152
155
|
const nextManifestUrl = urls.manifestUrl || '';
|
|
153
156
|
const nextManifestFingerprint = urls.manifestFingerprint || '';
|
|
154
157
|
const nextPreflightKey = urls.preflightKey || '';
|
|
@@ -304,9 +307,10 @@ export class StaticWorkerRuntimeSandbox {
|
|
|
304
307
|
beginProgressLifecycle(progress, stage) {
|
|
305
308
|
return this.progressController.begin(`${this.config.languageId.toLowerCase()}-${++this.progressUid}`, progress, stage);
|
|
306
309
|
}
|
|
307
|
-
resolveExecutionControls(options) {
|
|
310
|
+
resolveExecutionControls(options, persistentCache = this.persistentCache) {
|
|
308
311
|
return {
|
|
309
312
|
limits: resolveExecutionLimits(options.limits),
|
|
313
|
+
persistentCache: resolveRuntimeAssetCacheOptions(persistentCache, options.persistentCache),
|
|
310
314
|
...(options.signal ? { signal: options.signal } : {})
|
|
311
315
|
};
|
|
312
316
|
}
|
|
@@ -400,6 +404,17 @@ export class StaticWorkerRuntimeSandbox {
|
|
|
400
404
|
if (workerRequestUrl.hash) {
|
|
401
405
|
throw new RuntimeConfigurationError(`${this.config.displayName} worker script URL must not include a fragment`, { runtimeId: this.config.languageId });
|
|
402
406
|
}
|
|
407
|
+
const persistentIdentity = workerReceipt
|
|
408
|
+
? {
|
|
409
|
+
url: workerRequestUrl.href,
|
|
410
|
+
sha256: workerReceipt.sha256,
|
|
411
|
+
bytes: workerReceipt.bytes,
|
|
412
|
+
validationKey: JSON.stringify([
|
|
413
|
+
'static-worker-v1',
|
|
414
|
+
this.config.requireExactWorkerResponseUrl === true
|
|
415
|
+
])
|
|
416
|
+
}
|
|
417
|
+
: undefined;
|
|
403
418
|
const phaseController = new AbortController();
|
|
404
419
|
let timedOut = false;
|
|
405
420
|
const onAbort = () => phaseController.abort(signal?.reason);
|
|
@@ -414,6 +429,18 @@ export class StaticWorkerRuntimeSandbox {
|
|
|
414
429
|
throw (phaseController.signal.reason ??
|
|
415
430
|
new DOMException('Worker script fetch aborted', 'AbortError'));
|
|
416
431
|
}
|
|
432
|
+
if (persistentIdentity && workerReceipt) {
|
|
433
|
+
const cached = await readPersistentRuntimeAsset({
|
|
434
|
+
identity: persistentIdentity,
|
|
435
|
+
cache: controls.persistentCache,
|
|
436
|
+
signal: phaseController.signal
|
|
437
|
+
});
|
|
438
|
+
if (cached) {
|
|
439
|
+
await this.verifyWorkerReceipt(cached, workerReceipt, phaseController.signal);
|
|
440
|
+
this.reportProgress(progress, 0.2, `${this.config.displayName} worker cached`);
|
|
441
|
+
return Uint8Array.from(cached);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
417
444
|
const pendingResponse = Promise.resolve(fetch(workerRequestUrl.href, {
|
|
418
445
|
cache: this.config.inlineVerifiedWorker ? 'no-store' : 'force-cache',
|
|
419
446
|
credentials: 'omit',
|
|
@@ -531,6 +558,12 @@ export class StaticWorkerRuntimeSandbox {
|
|
|
531
558
|
const bytes = new Uint8Array(buffer);
|
|
532
559
|
if (workerReceipt) {
|
|
533
560
|
await this.verifyWorkerReceipt(bytes, workerReceipt, phaseController.signal);
|
|
561
|
+
await writePersistentRuntimeAsset({
|
|
562
|
+
identity: persistentIdentity,
|
|
563
|
+
cache: controls.persistentCache,
|
|
564
|
+
signal: phaseController.signal,
|
|
565
|
+
bytes
|
|
566
|
+
});
|
|
534
567
|
return bytes;
|
|
535
568
|
}
|
|
536
569
|
return undefined;
|
|
@@ -641,6 +674,12 @@ export class StaticWorkerRuntimeSandbox {
|
|
|
641
674
|
offset += chunk.byteLength;
|
|
642
675
|
}
|
|
643
676
|
await this.verifyWorkerReceipt(bytes, workerReceipt, phaseController.signal);
|
|
677
|
+
await writePersistentRuntimeAsset({
|
|
678
|
+
identity: persistentIdentity,
|
|
679
|
+
cache: controls.persistentCache,
|
|
680
|
+
signal: phaseController.signal,
|
|
681
|
+
bytes
|
|
682
|
+
});
|
|
644
683
|
return bytes;
|
|
645
684
|
}
|
|
646
685
|
return undefined;
|
|
@@ -856,6 +895,7 @@ self.postMessage = (message, transferOrOptions) => {
|
|
|
856
895
|
progress,
|
|
857
896
|
controls: {
|
|
858
897
|
limits: controls.limits,
|
|
898
|
+
persistentCache: controls.persistentCache,
|
|
859
899
|
signal: startAbortController.signal
|
|
860
900
|
}
|
|
861
901
|
};
|
|
@@ -916,6 +956,7 @@ self.postMessage = (message, transferOrOptions) => {
|
|
|
916
956
|
try {
|
|
917
957
|
runtimePreflight = await this.config.preflightRuntimeAssets(urls, {
|
|
918
958
|
limits: controls.limits,
|
|
959
|
+
persistentCache: controls.persistentCache,
|
|
919
960
|
signal: controls.signal,
|
|
920
961
|
reportProgress: (value, stage) => this.reportProgress(progress, value, stage),
|
|
921
962
|
createOwnedDelivery: (payload) => {
|
package/dist/playground/tcl.js
CHANGED
|
@@ -39,6 +39,7 @@ class Tcl extends StaticWorkerRuntimeSandbox {
|
|
|
39
39
|
manifestUrl: urls.manifestUrl || '',
|
|
40
40
|
profile,
|
|
41
41
|
limits: context.limits,
|
|
42
|
+
persistentCache: context.persistentCache,
|
|
42
43
|
signal: context.signal,
|
|
43
44
|
reportProgress(progress) {
|
|
44
45
|
loadedByAsset.set(progress.assetKey, progress.loadedBytes);
|
|
@@ -46,6 +46,8 @@ declare class TinyGo implements Sandbox {
|
|
|
46
46
|
rustRuntimeBaseUrl: string;
|
|
47
47
|
oncompilerdiagnostic?: (diagnostic: CompilerDiagnostic) => void;
|
|
48
48
|
assetLoader: TinyGoRuntimeAssetLoader | undefined;
|
|
49
|
+
private persistentCache?;
|
|
50
|
+
private persistentCacheBaseline?;
|
|
49
51
|
runtimeProfile: TinyGoUpstreamRuntimeProfile | undefined;
|
|
50
52
|
executableGraph: LoadedTinyGoExecutableGraph | null;
|
|
51
53
|
runtime: TinyGoRuntimeHooks | null;
|
|
@@ -5,7 +5,7 @@ import { flushBufferedEof, flushQueuedStdin, resetBufferedStdin } from './stdinB
|
|
|
5
5
|
import { createWasmIdleSharedBuffer } from './sharedBuffer';
|
|
6
6
|
import { WorkerSession } from './workerSession';
|
|
7
7
|
import { reportWorkerProgress } from './workerProgress';
|
|
8
|
-
import { BusyError, CancelledError, DEFAULT_EXECUTION_LIMITS, DEFAULT_WORKSPACE_LIMITS, DiagnosticLimitError, OutputLimitError, RuntimeConfigurationError, TimeoutError, WorkspaceValidationError, resolveExecutionLimits, validateExecutionWorkspace } from '@wasm-idle/core';
|
|
8
|
+
import { BusyError, CancelledError, DEFAULT_EXECUTION_LIMITS, DEFAULT_WORKSPACE_LIMITS, DiagnosticLimitError, OutputLimitError, RuntimeConfigurationError, TimeoutError, WorkspaceValidationError, resolveExecutionLimits, resolveRuntimeAssetCacheOptions, fetchPinnedRuntimeAsset, validateExecutionWorkspace } from '@wasm-idle/core';
|
|
9
9
|
const ACTIVITY_PREFIX_PATTERN = /^\[\d{2}:\d{2}:\d{2}\]\s?/gm;
|
|
10
10
|
const MAX_TIMER_DELAY_MS = 2_147_483_647;
|
|
11
11
|
const TINYGO_BROWSER_COMPILER_DEFAULT_MAX_WASM_MEMORY_BYTES = 2 * 1024 * 1024 * 1024;
|
|
@@ -73,6 +73,8 @@ class TinyGo {
|
|
|
73
73
|
rustRuntimeBaseUrl = '';
|
|
74
74
|
oncompilerdiagnostic;
|
|
75
75
|
assetLoader = undefined;
|
|
76
|
+
persistentCache;
|
|
77
|
+
persistentCacheBaseline;
|
|
76
78
|
runtimeProfile = undefined;
|
|
77
79
|
executableGraph = null;
|
|
78
80
|
runtime = null;
|
|
@@ -117,8 +119,11 @@ class TinyGo {
|
|
|
117
119
|
}
|
|
118
120
|
load(runtimeAssets = '', _code = '', _log = true, _args = [], options = {}, progress) {
|
|
119
121
|
return this.executeOperation('startup', options, async (operation) => {
|
|
122
|
+
const persistentCache = resolveRuntimeAssetCacheOptions(typeof runtimeAssets === 'object' ? runtimeAssets.persistentCache : undefined, options.persistentCache);
|
|
120
123
|
try {
|
|
121
124
|
this.assertOperation(operation);
|
|
125
|
+
this.persistentCacheBaseline = persistentCache;
|
|
126
|
+
this.persistentCache = persistentCache;
|
|
122
127
|
this.clearPendingStdin();
|
|
123
128
|
const currentUrl = typeof window !== 'undefined' ? window.location.href : '';
|
|
124
129
|
this.assertOperation(operation);
|
|
@@ -692,6 +697,7 @@ class TinyGo {
|
|
|
692
697
|
});
|
|
693
698
|
}
|
|
694
699
|
nextExecutableGraph = await loadVerifiedTinyGoExecutableGraph({
|
|
700
|
+
persistentCache: this.persistentCache,
|
|
695
701
|
moduleUrl,
|
|
696
702
|
profile: WASM_TINYGO_EXECUTABLE_GRAPH_PROFILE,
|
|
697
703
|
signal: operation.controller.signal,
|
|
@@ -700,6 +706,42 @@ class TinyGo {
|
|
|
700
706
|
});
|
|
701
707
|
this.assertOperation(operation);
|
|
702
708
|
const executableGraph = nextExecutableGraph;
|
|
709
|
+
// The upstream loader owns gzip fallback and logical-byte verification.
|
|
710
|
+
// Preserve raw .wasm probes; cache only exact profile-pinned transport URLs.
|
|
711
|
+
const transportReceipts = new Map();
|
|
712
|
+
for (const [path, receipt] of [
|
|
713
|
+
[runtimeProfile.manifestPath, runtimeProfile.manifestReceipt],
|
|
714
|
+
...Object.entries(runtimeProfile.assetReceipts)
|
|
715
|
+
]) {
|
|
716
|
+
const transportPath = receipt.uncompressedSha256 ? `${path}.gz` : path;
|
|
717
|
+
transportReceipts.set(new URL(transportPath, executableGraph.assetBaseUrl).href, receipt);
|
|
718
|
+
}
|
|
719
|
+
const pinnedFetch = async (input, init) => {
|
|
720
|
+
const url = typeof input === 'string'
|
|
721
|
+
? input
|
|
722
|
+
: input instanceof URL
|
|
723
|
+
? input.href
|
|
724
|
+
: input.url;
|
|
725
|
+
const receipt = transportReceipts.get(url);
|
|
726
|
+
if (!receipt)
|
|
727
|
+
return globalThis.fetch(input, init);
|
|
728
|
+
const owner = this.activeOperation;
|
|
729
|
+
if (!owner)
|
|
730
|
+
throw new Error('TinyGo asset load has no active operation');
|
|
731
|
+
this.assertOperation(owner);
|
|
732
|
+
const bytes = await fetchPinnedRuntimeAsset({
|
|
733
|
+
url,
|
|
734
|
+
receipt,
|
|
735
|
+
persistentCache: this.persistentCache,
|
|
736
|
+
maxAssetBytes: owner.limits?.maxAssetBytes ?? maxAssetBytes,
|
|
737
|
+
signal: init?.signal ?? owner.controller.signal
|
|
738
|
+
});
|
|
739
|
+
this.assertOperation(owner);
|
|
740
|
+
// This is a verified byte adapter, not a network response with a fabricated URL.
|
|
741
|
+
return new Response(Uint8Array.from(bytes).buffer, {
|
|
742
|
+
headers: { 'Content-Length': String(bytes.byteLength) }
|
|
743
|
+
});
|
|
744
|
+
};
|
|
703
745
|
const runtimeModule = (await import(
|
|
704
746
|
/* @vite-ignore */ executableGraph.entryUrl));
|
|
705
747
|
this.assertOperation(operation);
|
|
@@ -762,7 +804,9 @@ class TinyGo {
|
|
|
762
804
|
assetsPromise = loadUpstreamAssets({
|
|
763
805
|
assetBaseUrl: executableGraph.assetBaseUrl,
|
|
764
806
|
profile: runtimeProfile,
|
|
765
|
-
...(assetLoader
|
|
807
|
+
...(assetLoader
|
|
808
|
+
? { loader: assetLoader }
|
|
809
|
+
: { fetchImpl: pinnedFetch }),
|
|
766
810
|
onProgress: commonOptions.onProgress,
|
|
767
811
|
signal: controller.signal,
|
|
768
812
|
maxAssetBytes: assetLimit
|
|
@@ -1051,6 +1095,7 @@ class TinyGo {
|
|
|
1051
1095
|
}
|
|
1052
1096
|
run(code, prepare, _log = true, _prog, args = [], options = {}) {
|
|
1053
1097
|
return this.executeOperation('execute', options, async (operation, request) => {
|
|
1098
|
+
this.persistentCache = request.persistentCache;
|
|
1054
1099
|
this.exit = false;
|
|
1055
1100
|
try {
|
|
1056
1101
|
this.begin = Date.now();
|
|
@@ -1155,6 +1200,8 @@ class TinyGo {
|
|
|
1155
1200
|
throw error;
|
|
1156
1201
|
}
|
|
1157
1202
|
}, (operation) => {
|
|
1203
|
+
this.assertOperation(operation);
|
|
1204
|
+
const persistentCache = resolveRuntimeAssetCacheOptions(this.persistentCacheBaseline, options.persistentCache);
|
|
1158
1205
|
this.assertOperation(operation);
|
|
1159
1206
|
if (typeof code !== 'string') {
|
|
1160
1207
|
throw new TypeError('TinyGo source code must be a string');
|
|
@@ -1281,7 +1328,14 @@ class TinyGo {
|
|
|
1281
1328
|
const buffer = this.buffer;
|
|
1282
1329
|
this.assertOperation(operation);
|
|
1283
1330
|
operation.buffer = buffer;
|
|
1284
|
-
return {
|
|
1331
|
+
return {
|
|
1332
|
+
buffer,
|
|
1333
|
+
programArgs,
|
|
1334
|
+
stdin,
|
|
1335
|
+
target,
|
|
1336
|
+
workspaceFiles: runtimeWorkspace,
|
|
1337
|
+
persistentCache
|
|
1338
|
+
};
|
|
1285
1339
|
});
|
|
1286
1340
|
}
|
|
1287
1341
|
resetOwnedBuffers(operationBuffer) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export declare const TINYGO_EXECUTABLE_GRAPH_FORMAT: "wasm-idle-tinygo-executable-graph-v1";
|
|
2
2
|
export declare const TINYGO_EXECUTABLE_GRAPH_FINGERPRINT_DOMAIN: "wasm-idle:tinygo-executable-graph:v1\n";
|
|
3
|
-
export type TinyGoExecutableImportKind = 'static' | 'dynamic' | 'worker';
|
|
3
|
+
export type TinyGoExecutableImportKind = 'static' | 'dynamic' | 'worker' | 'asset';
|
|
4
4
|
export interface TinyGoExecutableGraphImport {
|
|
5
5
|
readonly specifier: string;
|
|
6
6
|
readonly target: string;
|
|
@@ -9,6 +9,8 @@ export interface TinyGoExecutableGraphImport {
|
|
|
9
9
|
export interface TinyGoExecutableGraphModule {
|
|
10
10
|
readonly bytes: number;
|
|
11
11
|
readonly sha256: string;
|
|
12
|
+
readonly uncompressedBytes?: number;
|
|
13
|
+
readonly uncompressedSha256?: string;
|
|
12
14
|
readonly imports: readonly TinyGoExecutableGraphImport[];
|
|
13
15
|
}
|
|
14
16
|
export interface TinyGoExecutableGraphProfile {
|
|
@@ -30,6 +32,7 @@ export interface TinyGoExecutableGraphProgress {
|
|
|
30
32
|
readonly totalBytes: number;
|
|
31
33
|
}
|
|
32
34
|
export interface LoadTinyGoExecutableGraphOptions {
|
|
35
|
+
readonly persistentCache?: import('@wasm-idle/core').RuntimeAssetCacheOptions;
|
|
33
36
|
readonly moduleUrl: string;
|
|
34
37
|
readonly currentUrl?: string;
|
|
35
38
|
readonly profile: unknown;
|