wasm-idle 1.0.12 → 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 +150 -37
- package/dist/playground/applicationAssets.js +2 -0
- 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/commonlisp.d.ts +8 -0
- package/dist/playground/commonlisp.js +33 -0
- package/dist/playground/commonlispAssets.d.ts +30 -0
- package/dist/playground/commonlispAssets.js +184 -0
- 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.d.ts +1 -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/index.d.ts +1 -1
- package/dist/playground/index.js +14 -0
- 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/javaRuntimeStdin.d.ts +9 -0
- package/dist/playground/javaRuntimeStdin.js +145 -0
- package/dist/playground/lean4.d.ts +13 -0
- package/dist/playground/lean4.js +50 -0
- package/dist/playground/lean4Assets.d.ts +25 -0
- package/dist/playground/lean4Assets.js +123 -0
- package/dist/playground/lfortran.js +10 -0
- package/dist/playground/lfortranAssets.d.ts +2 -2
- package/dist/playground/loadingProgress.js +4 -1
- 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 +32 -0
- package/dist/playground/wasmCommonLispVersion.js +33 -0
- 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 +110 -0
- package/dist/playground/wasmLean4Version.js +111 -0
- 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 +92 -39
- package/dist/playground/worker/lua.js +2 -3
- package/dist/playground/worker/php.js +15 -9
- package/dist/playground/worker/python.js +131 -131
- package/dist/playground/worker/pythonDebugPreview.d.ts +2 -0
- package/dist/playground/worker/pythonDebugPreview.js +55 -0
- package/dist/playground/worker/pythonExecution.d.ts +8 -0
- package/dist/playground/worker/pythonExecution.js +183 -0
- package/dist/playground/worker/pythonStdio.d.ts +32 -0
- package/dist/playground/worker/pythonStdio.js +253 -0
- 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 +30 -15
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import { resolveExecutionLimits, resolveRuntimeAssetCacheOptions } from '@wasm-idle/core';
|
|
1
|
+
import { resolveExecutionLimits, resolveRuntimeAssetCacheOptions, OutputLimitError } from '@wasm-idle/core';
|
|
2
2
|
import { resolveRuntimeAssetConfig } from './assets';
|
|
3
3
|
import { WorkerAssetBridge } from './assetBridge';
|
|
4
4
|
import { shouldStreamBundledClang } from './clangStreamingPolicy';
|
|
5
5
|
import { CompiledArtifactCache, clangCompileKey } from './compiledArtifactCache';
|
|
6
|
+
import { CLANG_STDIN_DATA, CLANG_STDIN_EOF, CLANG_STDIN_HEADER_BYTES } from './clangWorkerProtocol';
|
|
7
|
+
const MAX_BUFFERED_INPUT_BYTES = 128 * 1024;
|
|
8
|
+
const MAX_HEADER_BUILD_TIMEOUT_MS = 30_000;
|
|
6
9
|
const workers = {
|
|
7
10
|
async compile() {
|
|
8
11
|
const { default: CompileWorker } = await import('./worker/cachedClangCompile?worker');
|
|
@@ -20,6 +23,7 @@ export function createCachedClangSandbox(legacy, language, runtimeCache, cache =
|
|
|
20
23
|
let runtimeBaseUrl = '';
|
|
21
24
|
let assetConfig;
|
|
22
25
|
let maxAssetBytes = 0;
|
|
26
|
+
let maxWasmMemoryBytes = 0;
|
|
23
27
|
let languageSysroots = false;
|
|
24
28
|
let activeWorker;
|
|
25
29
|
let cancelWorker;
|
|
@@ -30,47 +34,97 @@ export function createCachedClangSandbox(legacy, language, runtimeCache, cache =
|
|
|
30
34
|
let inputBuffer;
|
|
31
35
|
let inputRequested = false;
|
|
32
36
|
let pendingEof = false;
|
|
37
|
+
let loadedMaxInputBytes = MAX_BUFFERED_INPUT_BYTES;
|
|
38
|
+
let maxBufferedInputBytes = loadedMaxInputBytes;
|
|
39
|
+
let pendingInputBytes = 0;
|
|
40
|
+
let loadedHeaderTimeoutMs = MAX_HEADER_BUILD_TIMEOUT_MS;
|
|
41
|
+
let headerTimeoutMs = loadedHeaderTimeoutMs;
|
|
42
|
+
let loadedMaxWorkers = 1;
|
|
43
|
+
let maxWorkers = loadedMaxWorkers;
|
|
33
44
|
const pendingInput = [];
|
|
34
45
|
const encoder = new TextEncoder();
|
|
35
|
-
//
|
|
36
|
-
// runs and cancellations and is discarded only with the sandbox.
|
|
46
|
+
// Header builds survive ordinary cancellation, within their own deadline and Worker budget.
|
|
37
47
|
let precompiledHeader;
|
|
38
48
|
let headerWorker;
|
|
49
|
+
function disposeWorker(worker, bridge) {
|
|
50
|
+
worker.onmessage = null;
|
|
51
|
+
worker.onerror = null;
|
|
52
|
+
worker.onmessageerror = null;
|
|
53
|
+
try {
|
|
54
|
+
bridge?.dispose();
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// Cleanup must preserve the primary result and still attempt Worker termination.
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
worker.terminate();
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// Preserve the primary result even if a custom Worker fails to terminate.
|
|
64
|
+
}
|
|
65
|
+
}
|
|
39
66
|
function adoptHeaderWorker(worker, bridge) {
|
|
40
67
|
headerWorker?.dispose();
|
|
68
|
+
let settled = false;
|
|
69
|
+
let timeout;
|
|
41
70
|
const dispose = () => {
|
|
71
|
+
if (settled)
|
|
72
|
+
return;
|
|
73
|
+
settled = true;
|
|
74
|
+
clearTimeout(timeout);
|
|
42
75
|
if (headerWorker?.worker === worker)
|
|
43
76
|
headerWorker = undefined;
|
|
44
|
-
bridge
|
|
45
|
-
worker.onmessage = null;
|
|
46
|
-
worker.onerror = null;
|
|
47
|
-
worker.onmessageerror = null;
|
|
48
|
-
worker.terminate();
|
|
77
|
+
disposeWorker(worker, bridge);
|
|
49
78
|
};
|
|
50
79
|
headerWorker = { worker, dispose };
|
|
80
|
+
timeout = setTimeout(dispose, headerTimeoutMs);
|
|
51
81
|
worker.onerror = dispose;
|
|
52
82
|
worker.onmessageerror = dispose;
|
|
53
83
|
worker.onmessage = (event) => {
|
|
54
|
-
if (
|
|
55
|
-
return;
|
|
56
|
-
if (event.data?.type !== 'precompiled-header')
|
|
84
|
+
if (settled || disposed || headerWorker?.worker !== worker)
|
|
57
85
|
return;
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
86
|
+
try {
|
|
87
|
+
if (bridge?.handleMessage(event))
|
|
88
|
+
return;
|
|
89
|
+
if (event.data?.type === 'error' && event.data.code === 'output-limit') {
|
|
90
|
+
dispose();
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (event.data?.type !== 'precompiled-header')
|
|
94
|
+
return;
|
|
95
|
+
if (event.data.header)
|
|
96
|
+
precompiledHeader = event.data.header;
|
|
97
|
+
dispose();
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
dispose();
|
|
101
|
+
}
|
|
61
102
|
};
|
|
62
103
|
}
|
|
63
104
|
function resetInput() {
|
|
64
105
|
pendingInput.length = 0;
|
|
106
|
+
pendingInputBytes = 0;
|
|
65
107
|
pendingEof = false;
|
|
66
108
|
inputRequested = false;
|
|
67
109
|
inputBuffer = undefined;
|
|
110
|
+
maxBufferedInputBytes = loadedMaxInputBytes;
|
|
111
|
+
}
|
|
112
|
+
function bufferedInputBytes() {
|
|
113
|
+
const control = inputBuffer && new Int32Array(inputBuffer, 0, 2);
|
|
114
|
+
// DATA remains owned by the consumer until it requests its next chunk.
|
|
115
|
+
const publishedBytes = control && Atomics.load(control, 0) === CLANG_STDIN_DATA ? Atomics.load(control, 1) : 0;
|
|
116
|
+
return pendingInputBytes + publishedBytes;
|
|
117
|
+
}
|
|
118
|
+
function assertInputCapacity(actual, limit = maxBufferedInputBytes) {
|
|
119
|
+
if (actual > limit) {
|
|
120
|
+
throw new RangeError(`C/C++ stdin buffered bytes exceed ${limit}`);
|
|
121
|
+
}
|
|
68
122
|
}
|
|
69
123
|
function flushInput() {
|
|
70
124
|
if (!inputRequested || !inputBuffer)
|
|
71
125
|
return;
|
|
72
126
|
const control = new Int32Array(inputBuffer, 0, 2);
|
|
73
|
-
const payload = new Uint8Array(inputBuffer,
|
|
127
|
+
const payload = new Uint8Array(inputBuffer, CLANG_STDIN_HEADER_BYTES);
|
|
74
128
|
const next = pendingInput[0];
|
|
75
129
|
if (next) {
|
|
76
130
|
const length = Math.min(next.byteLength, payload.byteLength);
|
|
@@ -78,13 +132,14 @@ export function createCachedClangSandbox(legacy, language, runtimeCache, cache =
|
|
|
78
132
|
if (length === next.byteLength)
|
|
79
133
|
pendingInput.shift();
|
|
80
134
|
else
|
|
81
|
-
pendingInput[0] = next.
|
|
135
|
+
pendingInput[0] = next.slice(length);
|
|
136
|
+
pendingInputBytes -= length;
|
|
82
137
|
Atomics.store(control, 1, length);
|
|
83
|
-
Atomics.store(control, 0,
|
|
138
|
+
Atomics.store(control, 0, CLANG_STDIN_DATA);
|
|
84
139
|
}
|
|
85
140
|
else if (pendingEof) {
|
|
86
141
|
Atomics.store(control, 1, 0);
|
|
87
|
-
Atomics.store(control, 0,
|
|
142
|
+
Atomics.store(control, 0, CLANG_STDIN_EOF);
|
|
88
143
|
}
|
|
89
144
|
else
|
|
90
145
|
return;
|
|
@@ -98,9 +153,12 @@ export function createCachedClangSandbox(legacy, language, runtimeCache, cache =
|
|
|
98
153
|
resetInput();
|
|
99
154
|
}
|
|
100
155
|
async function workerOperation(factory, message, token, progress, compileLimit = 0, signal, executionAssetConfig = assetConfig) {
|
|
156
|
+
// The background compiler and the next foreground Worker share one budget.
|
|
157
|
+
if (headerWorker && maxWorkers < 2)
|
|
158
|
+
headerWorker.dispose();
|
|
101
159
|
const worker = await factory();
|
|
102
160
|
if (token !== generation || signal?.aborted) {
|
|
103
|
-
worker
|
|
161
|
+
disposeWorker(worker);
|
|
104
162
|
throw signal?.reason ?? new Error('Process terminated');
|
|
105
163
|
}
|
|
106
164
|
return new Promise((resolve, reject) => {
|
|
@@ -110,7 +168,7 @@ export function createCachedClangSandbox(legacy, language, runtimeCache, cache =
|
|
|
110
168
|
bridge = new WorkerAssetBridge(worker, 'clang', executionAssetConfig, progress, compileLimit, languageSysroots, runtimeCache);
|
|
111
169
|
}
|
|
112
170
|
catch (error) {
|
|
113
|
-
worker
|
|
171
|
+
disposeWorker(worker);
|
|
114
172
|
reject(error);
|
|
115
173
|
return;
|
|
116
174
|
}
|
|
@@ -124,15 +182,10 @@ export function createCachedClangSandbox(legacy, language, runtimeCache, cache =
|
|
|
124
182
|
activeWorker = undefined;
|
|
125
183
|
cancelWorker = undefined;
|
|
126
184
|
signal?.removeEventListener('abort', abort);
|
|
127
|
-
worker.onmessage = null;
|
|
128
|
-
worker.onerror = null;
|
|
129
|
-
worker.onmessageerror = null;
|
|
130
185
|
if (keepForHeader)
|
|
131
186
|
adoptHeaderWorker(worker, bridge);
|
|
132
|
-
else
|
|
133
|
-
bridge
|
|
134
|
-
worker.terminate();
|
|
135
|
-
}
|
|
187
|
+
else
|
|
188
|
+
disposeWorker(worker, bridge);
|
|
136
189
|
if (error)
|
|
137
190
|
reject(error);
|
|
138
191
|
else
|
|
@@ -170,6 +223,17 @@ export function createCachedClangSandbox(legacy, language, runtimeCache, cache =
|
|
|
170
223
|
flushInput();
|
|
171
224
|
}
|
|
172
225
|
else if (data.type === 'compiled' || data.type === 'error') {
|
|
226
|
+
if (data.type === 'error' && data.code === 'output-limit') {
|
|
227
|
+
finish(new OutputLimitError(data.error, {
|
|
228
|
+
limit: data.limit,
|
|
229
|
+
actual: data.actual,
|
|
230
|
+
phase: 'compile'
|
|
231
|
+
}));
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
for (const diagnostic of data.diagnostics ?? []) {
|
|
235
|
+
legacy.oncompilerdiagnostic?.({ ...diagnostic });
|
|
236
|
+
}
|
|
173
237
|
if (data.stdout)
|
|
174
238
|
legacy.output?.(data.stdout);
|
|
175
239
|
if (data.stderr)
|
|
@@ -178,7 +242,10 @@ export function createCachedClangSandbox(legacy, language, runtimeCache, cache =
|
|
|
178
242
|
if (data.type === 'error')
|
|
179
243
|
finish(new Error(data.error), undefined, keepForHeader);
|
|
180
244
|
else
|
|
181
|
-
finish(undefined,
|
|
245
|
+
finish(undefined, {
|
|
246
|
+
artifact: data.artifact,
|
|
247
|
+
diagnostics: data.diagnostics ?? []
|
|
248
|
+
}, keepForHeader);
|
|
182
249
|
}
|
|
183
250
|
else if (data.type === 'done') {
|
|
184
251
|
if (data.exitCode !== 0 && data.exitCode !== null)
|
|
@@ -222,6 +289,11 @@ export function createCachedClangSandbox(legacy, language, runtimeCache, cache =
|
|
|
222
289
|
return legacy.load(assets, code, log, args, options, progress);
|
|
223
290
|
runtimeBaseUrl = assetConfig.baseUrl;
|
|
224
291
|
maxAssetBytes = resolveExecutionLimits(options.limits).maxAssetBytes;
|
|
292
|
+
maxWasmMemoryBytes = resolveExecutionLimits(options.limits).maxWasmMemoryBytes;
|
|
293
|
+
loadedMaxInputBytes = Math.min(MAX_BUFFERED_INPUT_BYTES, resolveExecutionLimits(options.limits).maxWorkspaceBytes);
|
|
294
|
+
maxBufferedInputBytes = loadedMaxInputBytes;
|
|
295
|
+
loadedHeaderTimeoutMs = Math.min(MAX_HEADER_BUILD_TIMEOUT_MS, resolveExecutionLimits(options.limits).compileTimeoutMs);
|
|
296
|
+
loadedMaxWorkers = resolveExecutionLimits(options.limits).maxWorkers;
|
|
225
297
|
languageSysroots = config?.clang?.bundledLanguageSysroots === true;
|
|
226
298
|
},
|
|
227
299
|
async run(code, prepare, log = true, progress, args = [], options = {}) {
|
|
@@ -246,10 +318,13 @@ export function createCachedClangSandbox(legacy, language, runtimeCache, cache =
|
|
|
246
318
|
};
|
|
247
319
|
options.signal?.throwIfAborted();
|
|
248
320
|
const token = ++generation;
|
|
321
|
+
headerTimeoutMs = Math.min(loadedHeaderTimeoutMs, resolveExecutionLimits(options.limits).compileTimeoutMs);
|
|
322
|
+
maxWorkers = Math.min(loadedMaxWorkers, resolveExecutionLimits(options.limits).maxWorkers);
|
|
249
323
|
// Reactive UI arrays/records are Proxies and cannot cross postMessage.
|
|
250
324
|
// Snapshot known fields before awaiting compilation, so the cache key,
|
|
251
325
|
// compiler and executor also observe the same input values.
|
|
252
326
|
const request = {
|
|
327
|
+
maxWasmMemoryBytes: Math.min(maxWasmMemoryBytes, resolveExecutionLimits(options.limits).maxWasmMemoryBytes),
|
|
253
328
|
code,
|
|
254
329
|
language,
|
|
255
330
|
activePath: options.activePath,
|
|
@@ -268,16 +343,37 @@ export function createCachedClangSandbox(legacy, language, runtimeCache, cache =
|
|
|
268
343
|
? undefined
|
|
269
344
|
: Object.fromEntries(Object.entries(options.env));
|
|
270
345
|
const stdin = options.stdin;
|
|
346
|
+
const inputLimit = Math.min(loadedMaxInputBytes, resolveExecutionLimits(options.limits).maxWorkspaceBytes);
|
|
347
|
+
if (!prepare && typeof stdin === 'string') {
|
|
348
|
+
// A string stdin is a complete input stream and replaces any queued writes.
|
|
349
|
+
// Check UTF-16 length first to avoid encoding an arbitrarily large write.
|
|
350
|
+
assertInputCapacity(stdin.length, inputLimit);
|
|
351
|
+
assertInputCapacity(encoder.encode(stdin).byteLength, inputLimit);
|
|
352
|
+
resetInput();
|
|
353
|
+
pendingEof = true;
|
|
354
|
+
}
|
|
355
|
+
else {
|
|
356
|
+
assertInputCapacity(bufferedInputBytes(), inputLimit);
|
|
357
|
+
}
|
|
271
358
|
const limit = Math.min(maxAssetBytes, resolveExecutionLimits(options.limits).maxAssetBytes);
|
|
272
359
|
const key = clangCompileKey(runtimeBaseUrl, limit, request, languageSysroots);
|
|
273
360
|
let artifact = cache.get(key);
|
|
361
|
+
// Per-run backpressure starts only after admission and ends with this run.
|
|
362
|
+
maxBufferedInputBytes = inputLimit;
|
|
274
363
|
running = true;
|
|
275
364
|
try {
|
|
276
|
-
if (
|
|
277
|
-
|
|
365
|
+
if (artifact) {
|
|
366
|
+
for (const diagnostic of cache.getDiagnostics(key))
|
|
367
|
+
legacy.oncompilerdiagnostic?.(diagnostic);
|
|
368
|
+
if (token !== generation)
|
|
369
|
+
throw new Error('Process terminated');
|
|
370
|
+
}
|
|
371
|
+
else {
|
|
372
|
+
const compiled = await workerOperation(() => factories.compile(), {
|
|
278
373
|
request,
|
|
279
374
|
runtimeBaseUrl,
|
|
280
375
|
maxAssetBytes: limit,
|
|
376
|
+
maxOutputBytes: resolveExecutionLimits(options.limits).maxOutputBytes,
|
|
281
377
|
languageSysroots,
|
|
282
378
|
log,
|
|
283
379
|
persistentCache: executionAssetConfig.persistentCache,
|
|
@@ -293,14 +389,16 @@ export function createCachedClangSandbox(legacy, language, runtimeCache, cache =
|
|
|
293
389
|
}, token, progress, limit, options.signal, executionAssetConfig);
|
|
294
390
|
if (token !== generation)
|
|
295
391
|
throw new Error('Process terminated');
|
|
296
|
-
|
|
392
|
+
artifact = compiled.artifact;
|
|
393
|
+
cache.set(key, artifact, compiled.diagnostics);
|
|
297
394
|
}
|
|
298
395
|
progress?.set?.(1);
|
|
299
396
|
if (prepare)
|
|
300
397
|
return true;
|
|
301
|
-
inputBuffer = new SharedArrayBuffer(65536 +
|
|
398
|
+
inputBuffer = new SharedArrayBuffer(Math.min(65536, maxBufferedInputBytes) + CLANG_STDIN_HEADER_BYTES);
|
|
302
399
|
return await workerOperation(() => factories.execute(), {
|
|
303
400
|
artifact,
|
|
401
|
+
maxWasmMemoryBytes: request.maxWasmMemoryBytes,
|
|
304
402
|
code,
|
|
305
403
|
activePath: request.activePath,
|
|
306
404
|
workspaceFiles: request.workspaceFiles,
|
|
@@ -313,16 +411,27 @@ export function createCachedClangSandbox(legacy, language, runtimeCache, cache =
|
|
|
313
411
|
finally {
|
|
314
412
|
if (token === generation) {
|
|
315
413
|
running = false;
|
|
414
|
+
maxBufferedInputBytes = loadedMaxInputBytes;
|
|
316
415
|
if (!prepare)
|
|
317
416
|
resetInput();
|
|
318
417
|
}
|
|
319
418
|
}
|
|
320
419
|
},
|
|
321
420
|
write(input) {
|
|
421
|
+
if (disposed)
|
|
422
|
+
throw new Error('C/C++ sandbox was disposed');
|
|
322
423
|
if (!cached)
|
|
323
424
|
return legacy.write?.(input);
|
|
324
|
-
if (
|
|
325
|
-
|
|
425
|
+
if (pendingEof)
|
|
426
|
+
throw new Error('C/C++ stdin is closed');
|
|
427
|
+
if (input) {
|
|
428
|
+
const buffered = bufferedInputBytes();
|
|
429
|
+
assertInputCapacity(buffered + input.length);
|
|
430
|
+
const bytes = encoder.encode(input);
|
|
431
|
+
assertInputCapacity(buffered + bytes.byteLength);
|
|
432
|
+
pendingInput.push(bytes);
|
|
433
|
+
pendingInputBytes += bytes.byteLength;
|
|
434
|
+
}
|
|
326
435
|
flushInput();
|
|
327
436
|
},
|
|
328
437
|
eof() {
|
|
@@ -7,10 +7,10 @@ export const BUNDLED_CLANG_ASSET_INTEGRITY = Object.freeze({
|
|
|
7
7
|
'runtime-manifest.v1.json': integrityEntry(967, '0b854bc6b41924420cfcc840509ecbe03af3c63ca3edd4940897917e32c8d8ad'),
|
|
8
8
|
'libc-printscan-long-double.a.gz': integrityEntry(52_723, 'b3f11e17e40fb13371a97244fdde00d5bd951ad8e20dfdf88a069167d6be628b', 111_062, '33e04007d3547095068391b42189d1ac5398dd04e9da3118dfa644ffea7f4148'),
|
|
9
9
|
'bin/memfs.wasm.gz': integrityEntry(16_111, 'a3e43451bc15ae69a7f113009e2ee82ab4db711625c1782cd45d0d3c4d38175a', 38_071, '5b741e03dd3502bcfd80e4e5055232b5d633604e1461752efed0189f93407dc3'),
|
|
10
|
-
'bin/clang.wasm.gz': integrityEntry(
|
|
11
|
-
'bin/lld.wasm.gz': integrityEntry(
|
|
12
|
-
'bin/sysroot.tar.gz': integrityEntry(
|
|
13
|
-
'bin/c-sysroot.tar.gz': integrityEntry(
|
|
14
|
-
'bin/cpp-addon.tar.gz': integrityEntry(
|
|
15
|
-
'language-sysroots.v1.json': integrityEntry(
|
|
10
|
+
'bin/clang.wasm.gz': integrityEntry(13_124_999, 'cc7b6b229af392f439a1ca89dbb8d5e016792264a0a6ee59608ff24e269be982', 35_597_829, 'fe7c40c2369d4a1b91d87cd2a38b1a5be11cd7f381373b7888be0b5f209e2d5b'),
|
|
11
|
+
'bin/lld.wasm.gz': integrityEntry(6_421_841, '798ce825f3e3cf9a695b6a049f157ba28d38731a3dc5e699ccdf23d69d3a5c20', 16_136_490, '77949fed32d5481979b8ebe6081009e3ec69c7219cb355e3f388a316746ea9b7'),
|
|
12
|
+
'bin/sysroot.tar.gz': integrityEntry(6_780_412, '6188b500fa7af2dceadcbd6dcf2619b6935fa94c224c1c2078426666ebea1d50', 35_594_240, 'fb6d8a8786ec395009d44f62ff24a5bf09ff8672340b7dae9f48e28cf1569cba'),
|
|
13
|
+
'bin/c-sysroot.tar.gz': integrityEntry(2_006_388, 'da7a29250b2fe2d928fa8818069ff67e1dcb26c529bbf01f40bbeb251535ecaa', 12_213_760, '517b32208f4e556b22eb5ac775411c39fb75239dfaf81f206e6052e168425b62'),
|
|
14
|
+
'bin/cpp-addon.tar.gz': integrityEntry(4_776_509, '6e243c219561b1f5aad64db4a9ff8bbeb85a97b5e3b5df3ed71d8340d35a8cd7', 23_382_528, 'feaf2aa538623ec8c543ccb49e9a833d2a1aa6dee7a9ad502c277deba24ef642'),
|
|
15
|
+
'language-sysroots.v1.json': integrityEntry(426_858, '08f6c2c87b4bebc9599193334e1d0ed322ebb38cbdd2bbb83d2b8c3a4cb61263')
|
|
16
16
|
});
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type { BrowserClangArtifact, BrowserClangCompileProgress, BrowserClangCompileRequest, BrowserClangPrecompiledHeader, BrowserClangWorkspaceFile } from '@wasm-idle/llvm-core/clang';
|
|
2
|
+
import type { CompilerDiagnostic } from '@wasm-idle/llvm-core/clang';
|
|
2
3
|
import type { WorkerRuntimeAssetConfig } from './worker/assets';
|
|
3
4
|
export type ClangCompileWorkerRequest = {
|
|
4
5
|
request: Omit<BrowserClangCompileRequest, 'onProgress'>;
|
|
5
6
|
runtimeBaseUrl: string;
|
|
6
7
|
maxAssetBytes?: number;
|
|
8
|
+
maxOutputBytes?: number;
|
|
7
9
|
languageSysroots?: boolean;
|
|
8
10
|
log?: boolean;
|
|
9
11
|
assets: WorkerRuntimeAssetConfig;
|
|
@@ -23,18 +25,27 @@ export type ClangCompileWorkerResponse = {
|
|
|
23
25
|
artifact: BrowserClangArtifact;
|
|
24
26
|
stdout: string;
|
|
25
27
|
stderr: string;
|
|
28
|
+
diagnostics?: CompilerDiagnostic[];
|
|
26
29
|
precompiledHeader?: 'building';
|
|
27
|
-
} | {
|
|
30
|
+
} | ({
|
|
28
31
|
type: 'error';
|
|
29
32
|
error: string;
|
|
30
33
|
stdout: string;
|
|
31
34
|
stderr: string;
|
|
35
|
+
diagnostics?: CompilerDiagnostic[];
|
|
32
36
|
precompiledHeader?: 'building';
|
|
37
|
+
} & ({
|
|
38
|
+
code?: undefined;
|
|
33
39
|
} | {
|
|
40
|
+
code: 'output-limit';
|
|
41
|
+
limit: number;
|
|
42
|
+
actual: number;
|
|
43
|
+
})) | {
|
|
34
44
|
type: 'precompiled-header';
|
|
35
45
|
header?: BrowserClangPrecompiledHeader;
|
|
36
46
|
};
|
|
37
47
|
export type ClangExecuteWorkerRequest = {
|
|
48
|
+
maxWasmMemoryBytes?: number;
|
|
38
49
|
artifact: BrowserClangArtifact;
|
|
39
50
|
programArgs?: string[];
|
|
40
51
|
env?: Record<string, string>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { WorkerAssetBridge } from './assetBridge';
|
|
2
|
+
import type { RuntimeAssetCache } from './runtimeAssetCache';
|
|
2
3
|
import { type PlaygroundRuntimeAssets } from './assets';
|
|
3
4
|
import type { SandboxExecutionOptions } from './options';
|
|
4
5
|
import type { Sandbox, SandboxProgress } from './sandbox';
|
|
@@ -18,10 +19,12 @@ declare class Cobol implements Sandbox {
|
|
|
18
19
|
assetBridge: WorkerAssetBridge | null;
|
|
19
20
|
activeCobolBaseUrl: string;
|
|
20
21
|
private activeOperation;
|
|
22
|
+
private runtimeAssetCache?;
|
|
21
23
|
private disposed;
|
|
22
24
|
private disposePromise;
|
|
23
25
|
private readonly disposeCancellation;
|
|
24
26
|
private readonly workerSession;
|
|
27
|
+
setRuntimeAssetCache(cache: RuntimeAssetCache): void;
|
|
25
28
|
private beginOperation;
|
|
26
29
|
private isOperationActive;
|
|
27
30
|
private releaseOperation;
|
package/dist/playground/cobol.js
CHANGED
|
@@ -26,6 +26,7 @@ class Cobol {
|
|
|
26
26
|
assetBridge = null;
|
|
27
27
|
activeCobolBaseUrl = '';
|
|
28
28
|
activeOperation = null;
|
|
29
|
+
runtimeAssetCache;
|
|
29
30
|
disposed = false;
|
|
30
31
|
disposePromise = null;
|
|
31
32
|
disposeCancellation = new CancelledError('COBOL sandbox disposed', {
|
|
@@ -53,6 +54,14 @@ class Cobol {
|
|
|
53
54
|
this.pendingEof = false;
|
|
54
55
|
}
|
|
55
56
|
});
|
|
57
|
+
setRuntimeAssetCache(cache) {
|
|
58
|
+
if (this.runtimeAssetCache === cache)
|
|
59
|
+
return;
|
|
60
|
+
if (this.disposed || this.worker || this.activeOperation) {
|
|
61
|
+
throw new RuntimeConfigurationError('Cannot replace an active COBOL compiler cache');
|
|
62
|
+
}
|
|
63
|
+
this.runtimeAssetCache = cache;
|
|
64
|
+
}
|
|
56
65
|
beginOperation(phase) {
|
|
57
66
|
if (this.disposed) {
|
|
58
67
|
throw new RuntimeConfigurationError('COBOL sandbox is disposed', {
|
|
@@ -303,7 +312,7 @@ class Cobol {
|
|
|
303
312
|
}
|
|
304
313
|
let assetBridge;
|
|
305
314
|
try {
|
|
306
|
-
assetBridge = new WorkerAssetBridge(worker, 'clang', clangAssets, progress, limits.maxAssetBytes);
|
|
315
|
+
assetBridge = new WorkerAssetBridge(worker, 'clang', clangAssets, progress, limits.maxAssetBytes, false, this.runtimeAssetCache);
|
|
307
316
|
}
|
|
308
317
|
catch (error) {
|
|
309
318
|
try {
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { StaticWorkerRuntimeSandbox } from './staticWorkerRuntime';
|
|
2
|
+
/** Real upstream ECL (Embeddable Common-Lisp) built to Wasm by the wasm-llvm producer. */
|
|
3
|
+
export default class CommonLisp extends StaticWorkerRuntimeSandbox {
|
|
4
|
+
readonly evidence: {
|
|
5
|
+
current: unknown;
|
|
6
|
+
};
|
|
7
|
+
constructor();
|
|
8
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { StaticWorkerRuntimeSandbox } from './staticWorkerRuntime';
|
|
2
|
+
import { preflightCommonLispRuntimeAssets, resolveCommonLispRuntimeAssetConfig } from './commonlispAssets';
|
|
3
|
+
/** Real upstream ECL (Embeddable Common-Lisp) built to Wasm by the wasm-llvm producer. */
|
|
4
|
+
export default class CommonLisp extends StaticWorkerRuntimeSandbox {
|
|
5
|
+
evidence;
|
|
6
|
+
constructor() {
|
|
7
|
+
const evidence = { current: undefined };
|
|
8
|
+
super({
|
|
9
|
+
displayName: 'Common Lisp',
|
|
10
|
+
languageId: 'COMMONLISP',
|
|
11
|
+
defaultActivePath: 'main.lisp',
|
|
12
|
+
workerLifetime: { mode: 'per-run' },
|
|
13
|
+
runtimePreflightDelivery: 'transfer-owned',
|
|
14
|
+
inlineVerifiedWorker: true,
|
|
15
|
+
requireExactWorkerResponseUrl: true,
|
|
16
|
+
moduleWorker: true,
|
|
17
|
+
includeExecutionLimits: true,
|
|
18
|
+
onEvidence(value) {
|
|
19
|
+
evidence.current = value;
|
|
20
|
+
},
|
|
21
|
+
stdin: {
|
|
22
|
+
mode: 'streaming',
|
|
23
|
+
sourceHintPattern: /\(\s*(?:read|read-line|read-char|read-byte|peek-char)\b|\*standard-input\*/i
|
|
24
|
+
},
|
|
25
|
+
resolveRuntimeAssets: resolveCommonLispRuntimeAssetConfig,
|
|
26
|
+
async preflightRuntimeAssets(urls, context) {
|
|
27
|
+
evidence.current = undefined;
|
|
28
|
+
return context.createOwnedDelivery(await preflightCommonLispRuntimeAssets(urls.baseUrl, context));
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
this.evidence = evidence;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type ExecutionLimits, type RuntimeAssetCacheOptions } from '@wasm-idle/core';
|
|
2
|
+
import type { PlaygroundRuntimeAssets } from './assets';
|
|
3
|
+
export declare const COMMONLISP_INITIAL_MEMORY_BYTES: number;
|
|
4
|
+
/** ecl.wasm is delivered as the producer's pinned gzip bytes; `.bin` keeps hosts from adding
|
|
5
|
+
* Content-Encoding, so the browser never transparently decodes it before verification. */
|
|
6
|
+
export declare const COMMONLISP_WASM_STORAGE_PATH = "ecl.wasm.gz.bin";
|
|
7
|
+
export declare const COMMONLISP_RUNTIME_MANIFEST: import("@wasm-idle/core").RuntimeRegistryManifest;
|
|
8
|
+
export declare function resolveCommonLispRuntimeAssetConfig(assets: string | PlaygroundRuntimeAssets, currentUrl: string): {
|
|
9
|
+
baseUrl: string;
|
|
10
|
+
workerUrl: string;
|
|
11
|
+
manifestFingerprint: "56f1eb7cf6470619cb3393e99d5c8ad1841a001ab758f388c006ca1d801ba071";
|
|
12
|
+
workerReceipt: {
|
|
13
|
+
readonly bytes: 12104;
|
|
14
|
+
readonly sha256: "d179242c40cdce862ff45bb35f736eaf8e79b97bdc06754576406ad4de698b7d";
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
export declare function preflightCommonLispRuntimeAssets(baseUrl: string, options: {
|
|
18
|
+
limits: ExecutionLimits;
|
|
19
|
+
persistentCache?: RuntimeAssetCacheOptions;
|
|
20
|
+
signal?: AbortSignal;
|
|
21
|
+
reportProgress?: (value: number, stage: string) => void;
|
|
22
|
+
fetch?: typeof globalThis.fetch;
|
|
23
|
+
}): Promise<Readonly<{
|
|
24
|
+
fingerprint: "56f1eb7cf6470619cb3393e99d5c8ad1841a001ab758f388c006ca1d801ba071";
|
|
25
|
+
'producer-receipt.json': Uint8Array<ArrayBufferLike>;
|
|
26
|
+
'ecl.mjs': Uint8Array<ArrayBufferLike>;
|
|
27
|
+
'ecl.wasm': Uint8Array<ArrayBuffer>;
|
|
28
|
+
}>>;
|
|
29
|
+
/** Decode the verified gzip delivery into an exactly sized buffer and verify the logical receipt. */
|
|
30
|
+
export declare function decompressCommonLispWasm(compressed: Uint8Array, signal?: AbortSignal): Promise<Uint8Array<ArrayBuffer>>;
|