wasm-idle 1.1.0 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +140 -37
- package/dist/playground/assetBridge.js +106 -31
- package/dist/playground/assets.d.ts +2 -2
- package/dist/playground/c3.js +22 -0
- package/dist/playground/c3Memory.d.ts +19 -0
- package/dist/playground/c3Memory.js +117 -0
- package/dist/playground/cachedClang.js +143 -34
- package/dist/playground/clangAssetIntegrity.js +6 -6
- package/dist/playground/clangWorkerProtocol.d.ts +12 -1
- package/dist/playground/cobol.d.ts +3 -0
- package/dist/playground/cobol.js +10 -1
- package/dist/playground/commonlispAssets.d.ts +2 -2
- package/dist/playground/compiledArtifactCache.d.ts +3 -1
- package/dist/playground/compiledArtifactCache.js +31 -5
- package/dist/playground/container/ContainerExplorer.svelte +307 -0
- package/dist/playground/container/ContainerExplorer.svelte.d.ts +14 -0
- package/dist/playground/container/binding.d.ts +26 -0
- package/dist/playground/container/binding.js +247 -0
- package/dist/playground/container/clang-runtime.d.ts +38 -0
- package/dist/playground/container/clang-runtime.js +343 -0
- package/dist/playground/container/client.d.ts +15 -0
- package/dist/playground/container/client.js +189 -0
- package/dist/playground/container/explorer.d.ts +31 -0
- package/dist/playground/container/explorer.js +112 -0
- package/dist/playground/container/owner.worker.js +390 -0
- package/dist/playground/container/protocol.d.ts +73 -0
- package/dist/playground/container/protocol.js +28 -0
- package/dist/playground/container/release.d.ts +31 -0
- package/dist/playground/container/release.js +612 -0
- package/dist/playground/container/runtime-adapter.d.ts +73 -0
- package/dist/playground/container/runtime-adapter.js +474 -0
- package/dist/playground/container/shell-control.d.ts +49 -0
- package/dist/playground/container/shell-control.js +303 -0
- package/dist/playground/container/workspace.d.ts +8 -0
- package/dist/playground/container/workspace.js +29 -0
- package/dist/playground/d.d.ts +6 -1
- package/dist/playground/d.js +83 -5
- package/dist/playground/dotnet.js +6 -8
- package/dist/playground/fortran.d.ts +3 -0
- package/dist/playground/fortran.js +10 -1
- package/dist/playground/go.js +14 -3
- package/dist/playground/goDebugInstrumentation.js +184 -54
- package/dist/playground/java.js +3 -2
- package/dist/playground/javaRuntimeErrors.d.ts +9 -0
- package/dist/playground/javaRuntimeErrors.js +60 -0
- package/dist/playground/lean4Assets.d.ts +4 -4
- package/dist/playground/lfortran.js +10 -0
- package/dist/playground/lfortranAssets.d.ts +2 -2
- package/dist/playground/nim.js +22 -0
- package/dist/playground/objectivec.d.ts +3 -0
- package/dist/playground/objectivec.js +11 -2
- package/dist/playground/options.d.ts +2 -0
- package/dist/playground/python.js +8 -0
- package/dist/playground/runtimeAssetCache.d.ts +1 -32
- package/dist/playground/runtimeAssetCache.js +1 -193
- package/dist/playground/runtimeSession.d.ts +2 -2
- package/dist/playground/runtimeSession.js +11 -11
- package/dist/playground/rust.d.ts +6 -0
- package/dist/playground/rust.js +103 -6
- package/dist/playground/staticStdinRing.d.ts +2 -1
- package/dist/playground/staticStdinRing.js +21 -10
- package/dist/playground/staticWorkerRuntime.d.ts +15 -1
- package/dist/playground/staticWorkerRuntime.js +119 -17
- package/dist/playground/tinygo.d.ts +3 -0
- package/dist/playground/tinygo.js +81 -6
- package/dist/playground/v.d.ts +3 -0
- package/dist/playground/v.js +10 -1
- package/dist/playground/wasmAwkVersion.d.ts +13 -13
- package/dist/playground/wasmAwkVersion.js +4 -4
- package/dist/playground/wasmBqnVersion.d.ts +2 -2
- package/dist/playground/wasmBqnVersion.js +2 -2
- package/dist/playground/wasmC3Version.d.ts +2 -2
- package/dist/playground/wasmC3Version.js +2 -2
- package/dist/playground/wasmClojureScriptVersion.d.ts +2 -2
- package/dist/playground/wasmClojureScriptVersion.js +2 -2
- package/dist/playground/wasmCommonLispVersion.d.ts +2 -2
- package/dist/playground/wasmCommonLispVersion.js +2 -2
- package/dist/playground/wasmDIntegrity.d.ts +5 -5
- package/dist/playground/wasmDIntegrity.js +5 -5
- package/dist/playground/wasmDVersion.d.ts +16 -1
- package/dist/playground/wasmDVersion.js +16 -1
- package/dist/playground/wasmDebugVersion.d.ts +1 -1
- package/dist/playground/wasmDebugVersion.js +1 -1
- package/dist/playground/wasmForthVersion.d.ts +2 -2
- package/dist/playground/wasmForthVersion.js +2 -2
- package/dist/playground/wasmGleamVersion.d.ts +2 -2
- package/dist/playground/wasmGleamVersion.js +2 -2
- package/dist/playground/wasmGrainVersion.d.ts +2 -2
- package/dist/playground/wasmGrainVersion.js +2 -2
- package/dist/playground/wasmJVersion.d.ts +2 -2
- package/dist/playground/wasmJVersion.js +2 -2
- package/dist/playground/wasmJanetVersion.js +2 -2
- package/dist/playground/wasmJuliaVersion.js +2 -2
- package/dist/playground/wasmLean4Version.d.ts +5 -5
- package/dist/playground/wasmLean4Version.js +5 -5
- package/dist/playground/wasmLfortranVersion.d.ts +2 -2
- package/dist/playground/wasmLfortranVersion.js +2 -2
- package/dist/playground/wasmNimVersion.d.ts +9 -9
- package/dist/playground/wasmNimVersion.js +6 -6
- package/dist/playground/wasmOcamlVersion.d.ts +2 -2
- package/dist/playground/wasmOcamlVersion.js +1 -1
- package/dist/playground/wasmPascalVersion.js +2 -2
- package/dist/playground/wasmPerlVersion.js +2 -2
- package/dist/playground/wasmPrologVersion.d.ts +2 -2
- package/dist/playground/wasmPrologVersion.js +2 -2
- package/dist/playground/wasmReScriptVersion.d.ts +2 -2
- package/dist/playground/wasmReScriptVersion.js +2 -2
- package/dist/playground/wasmRustVersion.d.ts +8 -8
- package/dist/playground/wasmRustVersion.js +7 -7
- package/dist/playground/wasmTclVersion.d.ts +4 -4
- package/dist/playground/wasmTclVersion.js +2 -2
- package/dist/playground/wasmTinyGoVersion.d.ts +14 -14
- package/dist/playground/wasmTinyGoVersion.js +14 -14
- package/dist/playground/wasmTypeScriptVersion.d.ts +5 -5
- package/dist/playground/wasmTypeScriptVersion.js +5 -5
- package/dist/playground/worker/cachedClangCompile.js +52 -4
- package/dist/playground/worker/cachedClangExecute.js +6 -5
- package/dist/playground/worker/clang.js +32 -10
- package/dist/playground/worker/cobol.js +2 -2
- package/dist/playground/worker/d.js +12 -5
- package/dist/playground/worker/fortran.js +2 -2
- package/dist/playground/worker/go.js +16 -5
- package/dist/playground/worker/haskell.js +10 -7
- package/dist/playground/worker/java.js +75 -10
- package/dist/playground/worker/lua.js +2 -3
- package/dist/playground/worker/php.js +15 -9
- package/dist/playground/worker/python.js +46 -9
- package/dist/playground/worker/pythonExecution.js +17 -1
- package/dist/playground/worker/pythonWorkspaceFiles.d.ts +6 -0
- package/dist/playground/worker/pythonWorkspaceFiles.js +26 -0
- package/dist/playground/worker/pythonWorkspaceImports.d.ts +4 -0
- package/dist/playground/worker/pythonWorkspaceImports.js +129 -0
- package/dist/playground/worker/r.js +13 -6
- package/dist/playground/worker/rust.js +34 -2
- package/dist/playground/worker/sqlite.js +4 -3
- package/dist/playground/worker/tinygo.js +11 -3
- package/dist/playground/worker/typescript.js +2 -3
- package/dist/playground/worker/v.js +2 -2
- package/dist/playground/worker/wat.js +2 -3
- package/dist/playground/worker/zig.js +20 -6
- package/dist/playground/workerSession.d.ts +1 -28
- package/dist/playground/workerSession.js +1 -164
- package/package.json +20 -13
- package/dist/playground/worker/python.runtime.cases.js +0 -374
- /package/dist/playground/{worker/python.runtime.cases.d.ts → container/owner.worker.d.ts} +0 -0
package/dist/playground/c3.js
CHANGED
|
@@ -2,6 +2,7 @@ import { resolveC3BaseUrl } from './assets';
|
|
|
2
2
|
import { StaticWorkerRuntimeSandbox } from './staticWorkerRuntime';
|
|
3
3
|
import { bundledC3Profile as profile, bundledC3WorkerReceipt } from './wasmC3Version';
|
|
4
4
|
import { preflightRuntimeAssets, RuntimeConfigurationError } from '@wasm-idle/core';
|
|
5
|
+
import { limitC3WasmMemory } from './c3Memory.js';
|
|
5
6
|
export const C3_DEFAULT_WASM_MEMORY_BYTES = 1024 ** 3;
|
|
6
7
|
function c3ExecutionOptions(options = {}) {
|
|
7
8
|
if (options.compileArgs?.length)
|
|
@@ -114,6 +115,27 @@ class C3 extends StaticWorkerRuntimeSandbox {
|
|
|
114
115
|
workerReceipt: bundledC3WorkerReceipt
|
|
115
116
|
};
|
|
116
117
|
},
|
|
118
|
+
compilerModules(_urls, limits) {
|
|
119
|
+
const totalCap = Math.min(limits.maxWasmMemoryBytes, 2 * 1024 ** 3);
|
|
120
|
+
const guestCap = Math.min(64 * 1024 ** 2, Math.floor(totalCap / 8 / 65536) * 65536);
|
|
121
|
+
const compilerCap = totalCap - guestCap;
|
|
122
|
+
return {
|
|
123
|
+
compiler: {
|
|
124
|
+
receipt: profile.compilerWasmReceipt,
|
|
125
|
+
compileKey: `c3-defined-memory-cap-v1:${compilerCap}`,
|
|
126
|
+
async compile(bytes) {
|
|
127
|
+
const limited = await limitC3WasmMemory(bytes, compilerCap, {
|
|
128
|
+
verifyModules: false
|
|
129
|
+
});
|
|
130
|
+
const module = await WebAssembly.compile(limited.bytes);
|
|
131
|
+
if (WebAssembly.Module.imports(module).some((item) => item.kind === 'memory')) {
|
|
132
|
+
throw new Error('Imported C3 Wasm memories are unsupported');
|
|
133
|
+
}
|
|
134
|
+
return module;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
},
|
|
117
139
|
async preflightRuntimeAssets(urls, context) {
|
|
118
140
|
memoryEvidence.current = undefined;
|
|
119
141
|
const result = await preflightRuntimeAssets({
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/** @param {Uint8Array<ArrayBuffer>} bytes */
|
|
2
|
+
export function c3Digest(bytes: Uint8Array<ArrayBuffer>): Promise<string>;
|
|
3
|
+
/**
|
|
4
|
+
* @param {Uint8Array<ArrayBuffer>} bytes
|
|
5
|
+
* @param {number} maximumBytes
|
|
6
|
+
* @param {{verifyModules?: boolean}} [options]
|
|
7
|
+
*/
|
|
8
|
+
export function limitC3WasmMemory(bytes: Uint8Array<ArrayBuffer>, maximumBytes: number, { verifyModules }?: {
|
|
9
|
+
verifyModules?: boolean;
|
|
10
|
+
}): Promise<{
|
|
11
|
+
bytes: Uint8Array<ArrayBuffer>;
|
|
12
|
+
evidence: {
|
|
13
|
+
originalSha256: string;
|
|
14
|
+
limitedSha256: string;
|
|
15
|
+
initialBytes: number;
|
|
16
|
+
maximumBytes: number;
|
|
17
|
+
originalMaximumBytes: number | null;
|
|
18
|
+
};
|
|
19
|
+
}>;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
const C3_WASM_PAGE_BYTES = 65536;
|
|
2
|
+
|
|
3
|
+
/** @param {Uint8Array<ArrayBuffer>} bytes */
|
|
4
|
+
export async function c3Digest(bytes) {
|
|
5
|
+
return Array.from(new Uint8Array(await crypto.subtle.digest('SHA-256', bytes)), (value) =>
|
|
6
|
+
value.toString(16).padStart(2, '0')
|
|
7
|
+
).join('');
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// Only lower the limit of one defined, unshared wasm32 memory. Instructions and data stay intact.
|
|
11
|
+
/**
|
|
12
|
+
* @param {Uint8Array<ArrayBuffer>} bytes
|
|
13
|
+
* @param {number} maximumBytes
|
|
14
|
+
* @param {{verifyModules?: boolean}} [options]
|
|
15
|
+
*/
|
|
16
|
+
export async function limitC3WasmMemory(bytes, maximumBytes, { verifyModules = true } = {}) {
|
|
17
|
+
if (
|
|
18
|
+
!(bytes instanceof Uint8Array) ||
|
|
19
|
+
bytes.length < 8 ||
|
|
20
|
+
!Number.isSafeInteger(maximumBytes) ||
|
|
21
|
+
maximumBytes < 0
|
|
22
|
+
) {
|
|
23
|
+
throw new Error('Invalid C3 Wasm memory limit request');
|
|
24
|
+
}
|
|
25
|
+
const header = [0, 97, 115, 109, 1, 0, 0, 0];
|
|
26
|
+
if (!header.every((byte, index) => bytes[index] === byte))
|
|
27
|
+
throw new Error('Invalid Wasm header');
|
|
28
|
+
let offset = 8;
|
|
29
|
+
const u32 = (end = bytes.length) => {
|
|
30
|
+
let result = 0;
|
|
31
|
+
for (let index = 0; index < 5; index++) {
|
|
32
|
+
if (offset >= end) throw new Error('Truncated Wasm integer');
|
|
33
|
+
const byte = bytes[offset++];
|
|
34
|
+
if (index === 4 && byte > 15) throw new Error('Invalid Wasm u32');
|
|
35
|
+
result += (byte & 127) * 2 ** (7 * index);
|
|
36
|
+
if (!(byte & 128)) return result;
|
|
37
|
+
}
|
|
38
|
+
throw new Error('Invalid Wasm integer');
|
|
39
|
+
};
|
|
40
|
+
/** @param {number} value */
|
|
41
|
+
const encode = (value) => {
|
|
42
|
+
const result = [];
|
|
43
|
+
do {
|
|
44
|
+
const low = value % 128;
|
|
45
|
+
value = Math.floor(value / 128);
|
|
46
|
+
result.push(low | (value ? 128 : 0));
|
|
47
|
+
} while (value);
|
|
48
|
+
return result;
|
|
49
|
+
};
|
|
50
|
+
let memory;
|
|
51
|
+
while (offset < bytes.length) {
|
|
52
|
+
const start = offset;
|
|
53
|
+
const id = bytes[offset++];
|
|
54
|
+
const size = u32();
|
|
55
|
+
const end = offset + size;
|
|
56
|
+
if (end > bytes.length) throw new Error('Truncated Wasm section');
|
|
57
|
+
if (id === 5) {
|
|
58
|
+
if (memory || u32(end) !== 1)
|
|
59
|
+
throw new Error('C3 supports exactly one defined Wasm memory');
|
|
60
|
+
const flags = u32(end);
|
|
61
|
+
if (flags !== 0 && flags !== 1)
|
|
62
|
+
throw new Error('Shared and memory64 C3 memories are unsupported');
|
|
63
|
+
const minimum = u32(end);
|
|
64
|
+
const originalMaximum = flags === 1 ? u32(end) : null;
|
|
65
|
+
if (
|
|
66
|
+
offset !== end ||
|
|
67
|
+
minimum > 65536 ||
|
|
68
|
+
(originalMaximum !== null && (originalMaximum < minimum || originalMaximum > 65536))
|
|
69
|
+
) {
|
|
70
|
+
throw new Error('Invalid Wasm memory section');
|
|
71
|
+
}
|
|
72
|
+
const maximum = Math.min(
|
|
73
|
+
Math.floor(maximumBytes / C3_WASM_PAGE_BYTES),
|
|
74
|
+
originalMaximum ?? 65536
|
|
75
|
+
);
|
|
76
|
+
if (minimum > maximum) {
|
|
77
|
+
const error = new Error(
|
|
78
|
+
'C3 Wasm initial memory exceeds the configured memory limit'
|
|
79
|
+
);
|
|
80
|
+
Object.assign(error, {
|
|
81
|
+
code: 'resource-limit',
|
|
82
|
+
resource: 'wasm-memory',
|
|
83
|
+
actual: minimum * C3_WASM_PAGE_BYTES,
|
|
84
|
+
limit: maximumBytes
|
|
85
|
+
});
|
|
86
|
+
throw error;
|
|
87
|
+
}
|
|
88
|
+
memory = { start, end, minimum, maximum, originalMaximum };
|
|
89
|
+
}
|
|
90
|
+
offset = end;
|
|
91
|
+
}
|
|
92
|
+
if (!memory) throw new Error('C3 requires one defined Wasm memory');
|
|
93
|
+
if (verifyModules) {
|
|
94
|
+
const module = await WebAssembly.compile(bytes);
|
|
95
|
+
if (WebAssembly.Module.imports(module).some((item) => item.kind === 'memory')) {
|
|
96
|
+
throw new Error('Imported C3 Wasm memories are unsupported');
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const payload = [1, 1, ...encode(memory.minimum), ...encode(memory.maximum)];
|
|
100
|
+
const section = Uint8Array.from([5, ...encode(payload.length), ...payload]);
|
|
101
|
+
const limited = new Uint8Array(bytes.length - (memory.end - memory.start) + section.length);
|
|
102
|
+
limited.set(bytes.subarray(0, memory.start));
|
|
103
|
+
limited.set(section, memory.start);
|
|
104
|
+
limited.set(bytes.subarray(memory.end), memory.start + section.length);
|
|
105
|
+
if (verifyModules) await WebAssembly.compile(limited);
|
|
106
|
+
return {
|
|
107
|
+
bytes: limited,
|
|
108
|
+
evidence: {
|
|
109
|
+
originalSha256: await c3Digest(bytes),
|
|
110
|
+
limitedSha256: await c3Digest(limited),
|
|
111
|
+
initialBytes: memory.minimum * C3_WASM_PAGE_BYTES,
|
|
112
|
+
maximumBytes: memory.maximum * C3_WASM_PAGE_BYTES,
|
|
113
|
+
originalMaximumBytes:
|
|
114
|
+
memory.originalMaximum === null ? null : memory.originalMaximum * C3_WASM_PAGE_BYTES
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
}
|
|
@@ -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 {
|
|
@@ -10,8 +10,8 @@ export declare function resolveCommonLispRuntimeAssetConfig(assets: string | Pla
|
|
|
10
10
|
workerUrl: string;
|
|
11
11
|
manifestFingerprint: "56f1eb7cf6470619cb3393e99d5c8ad1841a001ab758f388c006ca1d801ba071";
|
|
12
12
|
workerReceipt: {
|
|
13
|
-
readonly bytes:
|
|
14
|
-
readonly sha256: "
|
|
13
|
+
readonly bytes: 12104;
|
|
14
|
+
readonly sha256: "d179242c40cdce862ff45bb35f736eaf8e79b97bdc06754576406ad4de698b7d";
|
|
15
15
|
};
|
|
16
16
|
};
|
|
17
17
|
export declare function preflightCommonLispRuntimeAssets(baseUrl: string, options: {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { BrowserClangArtifact, BrowserClangCompileRequest } from '@wasm-idle/llvm-core/clang';
|
|
2
|
+
import type { CompilerDiagnostic } from '@wasm-idle/llvm-core/clang';
|
|
2
3
|
/** Only immutable compiler output lives here, never a worker, instance, or filesystem. */
|
|
3
4
|
export declare class CompiledArtifactCache {
|
|
4
5
|
private entries;
|
|
@@ -9,7 +10,8 @@ export declare class CompiledArtifactCache {
|
|
|
9
10
|
private maxBytes;
|
|
10
11
|
constructor(maxEntries?: number, maxBytes?: number);
|
|
11
12
|
get(key: string): BrowserClangArtifact | undefined;
|
|
12
|
-
|
|
13
|
+
getDiagnostics(key: string): CompilerDiagnostic[];
|
|
14
|
+
set(key: string, artifact: BrowserClangArtifact, diagnostics?: CompilerDiagnostic[]): void;
|
|
13
15
|
clear(): void;
|
|
14
16
|
stats(): {
|
|
15
17
|
hits: number;
|