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
|
@@ -201,20 +201,22 @@ const expectedAssetsForRuntime = (runtime, languageSysroots = false) => {
|
|
|
201
201
|
}
|
|
202
202
|
return assets;
|
|
203
203
|
};
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
:
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
204
|
+
// Read the contract fields directly: valid receipts can use inherited or hidden getters.
|
|
205
|
+
const snapshotIntegrityEntry = (receipt) => typeof receipt === 'string'
|
|
206
|
+
? receipt
|
|
207
|
+
: Object.freeze({
|
|
208
|
+
sha256: receipt.sha256,
|
|
209
|
+
bytes: receipt.bytes,
|
|
210
|
+
mediaType: receipt.mediaType,
|
|
211
|
+
uncompressedSha256: receipt.uncompressedSha256,
|
|
212
|
+
uncompressedBytes: receipt.uncompressedBytes
|
|
213
|
+
});
|
|
214
|
+
const integrityKey = (config) => {
|
|
215
|
+
const integrity = config.integrity || {};
|
|
216
|
+
return JSON.stringify(Object.getOwnPropertyNames(integrity)
|
|
217
|
+
.sort((left, right) => left.localeCompare(right))
|
|
218
|
+
.map((asset) => [asset, snapshotIntegrityEntry(integrity[asset])]));
|
|
219
|
+
};
|
|
218
220
|
const allowedBaseUrlsKey = (config) => JSON.stringify([...(config.allowedBaseUrls || [])].sort());
|
|
219
221
|
class RuntimeLoadProgress {
|
|
220
222
|
samples = new Map();
|
|
@@ -550,7 +552,6 @@ export class WorkerAssetBridge {
|
|
|
550
552
|
const generation = this.generation;
|
|
551
553
|
const controller = new AbortController();
|
|
552
554
|
const progress = this.progress;
|
|
553
|
-
const context = this.captureLoadContext();
|
|
554
555
|
const receiveProgress = (event) => {
|
|
555
556
|
if (controller.signal.aborted || generation !== this.generation)
|
|
556
557
|
return;
|
|
@@ -561,15 +562,33 @@ export class WorkerAssetBridge {
|
|
|
561
562
|
progress.activity(event.phase, event.asset);
|
|
562
563
|
}
|
|
563
564
|
};
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
565
|
+
// A rebind to the same worker aborts this load, but that worker still awaits a reply.
|
|
566
|
+
const replySuperseded = () => {
|
|
567
|
+
if (this.state !== 'active' || this.worker !== worker)
|
|
568
|
+
return;
|
|
569
|
+
try {
|
|
570
|
+
worker.postMessage({
|
|
571
|
+
assetResponse: {
|
|
572
|
+
id: request.id,
|
|
573
|
+
ok: false,
|
|
574
|
+
error: `Runtime asset ${request.asset} request was superseded by a rebind`
|
|
575
|
+
}
|
|
576
|
+
});
|
|
569
577
|
}
|
|
570
|
-
|
|
578
|
+
catch {
|
|
579
|
+
// The worker may already be terminated.
|
|
580
|
+
}
|
|
581
|
+
};
|
|
571
582
|
this.activeLoads.add(controller);
|
|
572
583
|
try {
|
|
584
|
+
const context = this.captureLoadContext();
|
|
585
|
+
const loadContext = (report) => ({
|
|
586
|
+
...context,
|
|
587
|
+
progress: {
|
|
588
|
+
update: (asset, loaded, total) => report({ kind: 'download', asset, loaded, total }, `download:${asset}`),
|
|
589
|
+
activity: (phase, asset) => report({ kind: 'activity', asset, phase }, `activity:${asset}`)
|
|
590
|
+
}
|
|
591
|
+
});
|
|
573
592
|
this.validateAssetRequest(loadContext(receiveProgress), request.asset);
|
|
574
593
|
const identity = [
|
|
575
594
|
this.runtime,
|
|
@@ -650,7 +669,7 @@ export class WorkerAssetBridge {
|
|
|
650
669
|
});
|
|
651
670
|
}
|
|
652
671
|
if (controller.signal.aborted || generation !== this.generation)
|
|
653
|
-
return;
|
|
672
|
+
return replySuperseded();
|
|
654
673
|
worker.postMessage({ assetResponse: { id: request.id, ok: true, module } });
|
|
655
674
|
return;
|
|
656
675
|
}
|
|
@@ -659,7 +678,7 @@ export class WorkerAssetBridge {
|
|
|
659
678
|
this.pythonPackageAssets = readPythonPackageAssets(loaded.bytes);
|
|
660
679
|
}
|
|
661
680
|
if (controller.signal.aborted || generation !== this.generation)
|
|
662
|
-
return;
|
|
681
|
+
return replySuperseded();
|
|
663
682
|
const buffer = transferBuffer(loaded.bytes, this.cache ? false : loaded.transferOwnership);
|
|
664
683
|
worker.postMessage({
|
|
665
684
|
assetResponse: {
|
|
@@ -672,7 +691,7 @@ export class WorkerAssetBridge {
|
|
|
672
691
|
}
|
|
673
692
|
catch (error) {
|
|
674
693
|
if (controller.signal.aborted || generation !== this.generation)
|
|
675
|
-
return;
|
|
694
|
+
return replySuperseded();
|
|
676
695
|
try {
|
|
677
696
|
worker.postMessage({
|
|
678
697
|
assetResponse: {
|
|
@@ -691,8 +710,24 @@ export class WorkerAssetBridge {
|
|
|
691
710
|
}
|
|
692
711
|
}
|
|
693
712
|
captureLoadContext() {
|
|
713
|
+
const config = { ...this.config };
|
|
714
|
+
const integrity = config.integrity;
|
|
715
|
+
// Cache identity and verification must observe the same receipt, even if a caller
|
|
716
|
+
// updates its configuration while an asynchronous asset load is in progress.
|
|
717
|
+
// The built-in Clang map and its receipts are frozen; its identity also selects
|
|
718
|
+
// verified streaming, so only caller-owned maps need a new snapshot.
|
|
719
|
+
if (integrity && integrity !== BUNDLED_CLANG_ASSET_INTEGRITY) {
|
|
720
|
+
config.integrity = Object.freeze(Object.fromEntries(
|
|
721
|
+
// Authorization accepts own map entries regardless of enumerability.
|
|
722
|
+
Object.getOwnPropertyNames(integrity).map((asset) => [
|
|
723
|
+
asset,
|
|
724
|
+
snapshotIntegrityEntry(integrity[asset])
|
|
725
|
+
])));
|
|
726
|
+
}
|
|
727
|
+
if (config.allowedBaseUrls)
|
|
728
|
+
config.allowedBaseUrls = [...config.allowedBaseUrls];
|
|
694
729
|
return {
|
|
695
|
-
config
|
|
730
|
+
config,
|
|
696
731
|
maxAssetBytes: this.maxAssetBytes,
|
|
697
732
|
expectedAssets: new Set(this.expectedAssets),
|
|
698
733
|
pythonPackageAssets: new Set(this.pythonPackageAssets),
|
|
@@ -743,6 +778,7 @@ export class WorkerAssetBridge {
|
|
|
743
778
|
throw runtimeAssetAbortReason(signal);
|
|
744
779
|
if (this.runtime === 'python' && asset === 'pyodide-lock.json')
|
|
745
780
|
readPythonPackageAssets(runtimeBytes);
|
|
781
|
+
await loaded.persist?.();
|
|
746
782
|
return {
|
|
747
783
|
bytes: runtimeBytes,
|
|
748
784
|
mimeType: loaded.mimeType,
|
|
@@ -768,8 +804,10 @@ export class WorkerAssetBridge {
|
|
|
768
804
|
if (!signal.aborted)
|
|
769
805
|
context.progress.update(asset, loaded, total);
|
|
770
806
|
};
|
|
771
|
-
|
|
772
|
-
|
|
807
|
+
// Do not expose the private verification context as a custom loader's receiver.
|
|
808
|
+
const loader = context.config.loader;
|
|
809
|
+
if (loader) {
|
|
810
|
+
const pendingResult = Promise.resolve(loader({
|
|
773
811
|
runtime: this.runtime,
|
|
774
812
|
asset,
|
|
775
813
|
reportProgress,
|
|
@@ -930,7 +968,8 @@ export class WorkerAssetBridge {
|
|
|
930
968
|
'bridge-v1',
|
|
931
969
|
context.config.baseUrl,
|
|
932
970
|
allowedBaseUrlsKey(context.config),
|
|
933
|
-
maxAssetBytes
|
|
971
|
+
maxAssetBytes,
|
|
972
|
+
expected?.mediaType
|
|
934
973
|
])
|
|
935
974
|
}
|
|
936
975
|
: undefined;
|
|
@@ -943,13 +982,44 @@ export class WorkerAssetBridge {
|
|
|
943
982
|
if (bytes) {
|
|
944
983
|
requireRuntimeAssetSize(asset, bytes.byteLength, maxAssetBytes);
|
|
945
984
|
context.progress.update(asset, bytes.byteLength, bytes.byteLength);
|
|
946
|
-
|
|
985
|
+
// A hit was validated against this same expected MIME type before it was stored.
|
|
986
|
+
return {
|
|
987
|
+
bytes,
|
|
988
|
+
mimeType: expected?.mediaType ?? receipt?.mediaType,
|
|
989
|
+
transferOwnership: true
|
|
990
|
+
};
|
|
947
991
|
}
|
|
948
992
|
}
|
|
949
993
|
const loaded = await this.fetchAssetFromNetwork(context, url, asset, signal, maxAssetBytes);
|
|
994
|
+
if (receipt) {
|
|
995
|
+
// Verify even when storage is disabled, unavailable or skipped. A body that the browser
|
|
996
|
+
// HTTP-decoded and that lost its gzip header is checked against the logical receipt.
|
|
997
|
+
const decoded = !!loaded.contentEncoding && !(loaded.bytes[0] === 0x1f && loaded.bytes[1] === 0x8b);
|
|
998
|
+
if (decoded && receipt.uncompressedSha256 !== undefined) {
|
|
999
|
+
await verifyRuntimeAssetIntegrity({
|
|
1000
|
+
asset,
|
|
1001
|
+
bytes: loaded.bytes,
|
|
1002
|
+
expected: {
|
|
1003
|
+
sha256: receipt.sha256,
|
|
1004
|
+
uncompressedSha256: receipt.uncompressedSha256,
|
|
1005
|
+
uncompressedBytes: receipt.uncompressedBytes
|
|
1006
|
+
},
|
|
1007
|
+
stage: 'uncompressed'
|
|
1008
|
+
});
|
|
1009
|
+
}
|
|
1010
|
+
else if (!decoded || !asset.endsWith('.gz')) {
|
|
1011
|
+
// Unpaired receipts for other assets already describe their logical bytes.
|
|
1012
|
+
await verifyRuntimeAssetIntegrity({
|
|
1013
|
+
asset,
|
|
1014
|
+
bytes: loaded.bytes,
|
|
1015
|
+
expected: { sha256: receipt.sha256, bytes: receipt.bytes }
|
|
1016
|
+
});
|
|
1017
|
+
}
|
|
1018
|
+
// A decoded .gz body with an unpaired receipt is left to runtime validation.
|
|
1019
|
+
}
|
|
950
1020
|
if (identity && !loaded.contentEncoding) {
|
|
951
|
-
//
|
|
952
|
-
|
|
1021
|
+
// A hit skips the response MIME check, so publish only bytes that passed it.
|
|
1022
|
+
loaded.persist = () => writePersistentRuntimeAsset({
|
|
953
1023
|
identity,
|
|
954
1024
|
cache: persistentCache,
|
|
955
1025
|
signal,
|
|
@@ -1177,6 +1247,11 @@ export class WorkerAssetBridge {
|
|
|
1177
1247
|
if (url.hash) {
|
|
1178
1248
|
throw new Error(`Runtime asset ${asset} URL must not include a fragment`);
|
|
1179
1249
|
}
|
|
1250
|
+
// The prefix check below sees `/base/..%2fother` as inside `/base/`, but a server that
|
|
1251
|
+
// decodes the separator before resolving dot segments serves `/other`.
|
|
1252
|
+
if (/%2f|%5c/iu.test(url.pathname)) {
|
|
1253
|
+
throw new Error(`Runtime asset ${asset} URL must not include encoded path separators`);
|
|
1254
|
+
}
|
|
1180
1255
|
const allowed = [context.config.baseUrl, ...(context.config.allowedBaseUrls || [])].some((baseUrl) => {
|
|
1181
1256
|
let base;
|
|
1182
1257
|
try {
|
|
@@ -663,12 +663,12 @@ export interface ResolvedZigRuntimeAssetConfig {
|
|
|
663
663
|
integrity: ZigExecutionAssetReceipts;
|
|
664
664
|
}
|
|
665
665
|
export declare const PYTHON_RUNTIME_LOAD_ASSETS: readonly ["pyodide.mjs", "pyodide.asm.mjs", "pyodide-lock.json", "pyodide.asm.wasm", "python_stdlib.zip"];
|
|
666
|
-
export declare const JAVA_RUNTIME_LOAD_ASSETS: readonly ["compiler.wasm-runtime.js", "compiler.wasm", "compile-classlib-teavm.bin", "runtime-classlib-teavm.bin"];
|
|
666
|
+
export declare const JAVA_RUNTIME_LOAD_ASSETS: readonly ["compiler.wasm-runtime.js", "compiler.wasm", "compiler.wasm-deobfuscator.wasm", "compile-classlib-teavm.bin", "runtime-classlib-teavm.bin"];
|
|
667
667
|
export declare const CLANG_RUNTIME_LOAD_ASSETS: readonly ["runtime-manifest.v1.json", "bin/memfs.wasm.gz", "bin/clang.wasm.gz", "bin/lld.wasm.gz", "bin/sysroot.tar.gz"];
|
|
668
668
|
export declare const CLANGD_RUNTIME_LOAD_ASSETS: readonly ["clangd.js", "clangd.wasm.gz", "clangd.headers.json.gz"];
|
|
669
669
|
export declare const RUNTIME_LOAD_ASSETS: {
|
|
670
670
|
python: readonly ["pyodide.mjs", "pyodide.asm.mjs", "pyodide-lock.json", "pyodide.asm.wasm", "python_stdlib.zip"];
|
|
671
|
-
java: readonly ["compiler.wasm-runtime.js", "compiler.wasm", "compile-classlib-teavm.bin", "runtime-classlib-teavm.bin"];
|
|
671
|
+
java: readonly ["compiler.wasm-runtime.js", "compiler.wasm", "compiler.wasm-deobfuscator.wasm", "compile-classlib-teavm.bin", "runtime-classlib-teavm.bin"];
|
|
672
672
|
clang: readonly ["runtime-manifest.v1.json", "bin/memfs.wasm.gz", "bin/clang.wasm.gz", "bin/lld.wasm.gz", "bin/sysroot.tar.gz"];
|
|
673
673
|
clangd: readonly ["clangd.js", "clangd.wasm.gz", "clangd.headers.json.gz"];
|
|
674
674
|
};
|
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
|
+
}
|