wasm-idle 0.4.0 → 0.4.1

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 CHANGED
@@ -8,4 +8,22 @@ Refer to src/lib/clang.
8
8
 
9
9
  Java uses TeaVM's browser compiler/runtime. TeaVM compiler/runtime/classlib assets are bundled under `static/teavm/` by default, and the asset base URL can be overridden with `PUBLIC_TEAVM_BASE_URL`.
10
10
 
11
+ `Terminal` and `playground(...).load(...)` support either the legacy shared `path`/`rootUrl` or per-runtime asset config:
12
+
13
+ ```ts
14
+ import type { PlaygroundRuntimeAssets } from 'wasm-idle';
15
+
16
+ const runtimeAssets: PlaygroundRuntimeAssets = {
17
+ rootUrl: 'https://cdn.example.com/repl',
18
+ python: {
19
+ loader: async ({ asset }) => ({ url: `https://cdn.example.com/repl/pyodide/${asset}` })
20
+ },
21
+ java: {
22
+ baseUrl: 'https://cdn.example.com/repl/teavm/'
23
+ }
24
+ };
25
+ ```
26
+
27
+ Python custom loaders receive file names under the Pyodide asset root and can serve both core assets and package files. TeaVM custom loaders receive file names under the TeaVM asset root. Compressed TeaVM runtime assets are no longer unpacked inside the library; provide the final file URL or handle decompression in your own loader.
28
+
11
29
  Powered by [wasm-clang](https://github.com/binji/wasm-clang), Pyodide, and TeaVM.
package/dist/clang/app.js CHANGED
@@ -74,7 +74,9 @@ export default class App {
74
74
  return ESUCCESS;
75
75
  session.currentFunctionId = functionId;
76
76
  session.currentLine = line;
77
- const frame = [...session.frames].reverse().find((candidate) => candidate.functionId === functionId);
77
+ const frame = [...session.frames]
78
+ .reverse()
79
+ .find((candidate) => candidate.functionId === functionId);
78
80
  if (frame)
79
81
  frame.line = line;
80
82
  session.pauseOnEntry = false;
@@ -93,7 +95,10 @@ export default class App {
93
95
  : variable.length
94
96
  ? [variable.length]
95
97
  : [];
96
- if (!Number.isFinite(address) || address <= 0 || !dimensions.length || !variable.elementKind) {
98
+ if (!Number.isFinite(address) ||
99
+ address <= 0 ||
100
+ !dimensions.length ||
101
+ !variable.elementKind) {
97
102
  return [{ name: variable.name, value: '?' }];
98
103
  }
99
104
  const elementStride = variable.elementKind === 'double'
@@ -115,7 +120,9 @@ export default class App {
115
120
  }
116
121
  if (variable.elementKind === 'char') {
117
122
  const charCode = this.mem.read8(offset);
118
- values.push(charCode >= 0x20 && charCode <= 0x7e ? `'${String.fromCharCode(charCode)}'` : `${charCode}`);
123
+ values.push(charCode >= 0x20 && charCode <= 0x7e
124
+ ? `'${String.fromCharCode(charCode)}'`
125
+ : `${charCode}`);
119
126
  continue;
120
127
  }
121
128
  if (variable.elementKind === 'float') {
@@ -147,7 +154,9 @@ export default class App {
147
154
  }
148
155
  if (variable.elementKind === 'char') {
149
156
  const charCode = this.mem.read8(offset);
150
- values.push(charCode >= 0x20 && charCode <= 0x7e ? `'${String.fromCharCode(charCode)}'` : `${charCode}`);
157
+ values.push(charCode >= 0x20 && charCode <= 0x7e
158
+ ? `'${String.fromCharCode(charCode)}'`
159
+ : `${charCode}`);
151
160
  continue;
152
161
  }
153
162
  if (variable.elementKind === 'float') {
@@ -186,7 +195,10 @@ export default class App {
186
195
  locals: [...locals, ...globals],
187
196
  callStack: [...session.frames]
188
197
  .reverse()
189
- .map((stackFrame) => ({ functionName: stackFrame.functionName, line: stackFrame.line }))
198
+ .map((stackFrame) => ({
199
+ functionName: stackFrame.functionName,
200
+ line: stackFrame.line
201
+ }))
190
202
  });
191
203
  const sequence = Atomics.load(buffer, 0);
192
204
  while (true) {
@@ -2,6 +2,7 @@ import type { DebugVariable, DebugVariableMetadata } from '../playground/options
2
2
  import App from './app';
3
3
  import { MemFS } from './memory';
4
4
  import { type Writable } from 'svelte/store';
5
+ type ClangSourceLanguage = 'C' | 'CPP';
5
6
  interface APIOption {
6
7
  stdin: () => string;
7
8
  stdout: (str: string) => void;
@@ -17,7 +18,12 @@ interface APIOption {
17
18
  path: string;
18
19
  }
19
20
  interface DebugRunOptions {
21
+ language?: ClangSourceLanguage;
20
22
  args?: string[];
23
+ compileArgs?: string[];
24
+ programArgs?: string[];
25
+ cppVersion?: string;
26
+ cVersion?: string;
21
27
  debug?: boolean;
22
28
  breakpoints?: number[];
23
29
  pauseOnEntry?: boolean;
@@ -20,7 +20,94 @@ const clangCommonArgs = [
20
20
  '80',
21
21
  '-fcolor-diagnostics'
22
22
  ];
23
- const clangLanguageStandardArg = '-std=gnu++2a';
23
+ const defaultCppStandardArg = '-std=gnu++2a';
24
+ const defaultCStandardArg = '-std=gnu11';
25
+ function normalizeStandardCode(value) {
26
+ return (value || '').trim().toUpperCase().replaceAll(/\s+/g, '');
27
+ }
28
+ function resolveCppStandardArg(version) {
29
+ switch (normalizeStandardCode(version)) {
30
+ case '03':
31
+ case 'CPP03':
32
+ case 'C++03':
33
+ case 'GNU++03':
34
+ case 'GNUC++03':
35
+ return '-std=gnu++03';
36
+ case '11':
37
+ case 'CPP11':
38
+ case 'C++11':
39
+ case 'GNU++11':
40
+ case 'GNUC++11':
41
+ return '-std=gnu++11';
42
+ case '14':
43
+ case 'CPP14':
44
+ case 'C++14':
45
+ case 'GNU++14':
46
+ case 'GNUC++14':
47
+ return '-std=gnu++14';
48
+ case '17':
49
+ case 'CPP17':
50
+ case 'C++17':
51
+ case 'GNU++17':
52
+ case 'GNUC++17':
53
+ return '-std=gnu++17';
54
+ case '20':
55
+ case '23':
56
+ case '26':
57
+ case 'CPP20':
58
+ case 'CPP23':
59
+ case 'CPP26':
60
+ case 'C++20':
61
+ case 'C++23':
62
+ case 'C++26':
63
+ case 'GNU++20':
64
+ case 'GNU++23':
65
+ case 'GNU++26':
66
+ case 'GNUC++20':
67
+ case 'GNUC++23':
68
+ case 'GNUC++26':
69
+ return defaultCppStandardArg;
70
+ default:
71
+ return defaultCppStandardArg;
72
+ }
73
+ }
74
+ function resolveCStandardArg(version) {
75
+ switch (normalizeStandardCode(version)) {
76
+ case '99':
77
+ case 'C99':
78
+ case 'GNU99':
79
+ case 'GNUC99':
80
+ return '-std=gnu99';
81
+ case '11':
82
+ case 'C11':
83
+ case 'GNU11':
84
+ case 'GNUC11':
85
+ return '-std=gnu11';
86
+ case '17':
87
+ case '18':
88
+ case 'C17':
89
+ case 'C18':
90
+ case 'GNU17':
91
+ case 'GNU18':
92
+ case 'GNUC17':
93
+ case 'GNUC18':
94
+ return '-std=gnu17';
95
+ default:
96
+ return defaultCStandardArg;
97
+ }
98
+ }
99
+ function resolveClangLanguageArgs(language, options) {
100
+ if (language === 'C') {
101
+ return {
102
+ languageArg: 'c',
103
+ standardArg: resolveCStandardArg(options.cVersion)
104
+ };
105
+ }
106
+ return {
107
+ languageArg: 'c++',
108
+ standardArg: resolveCppStandardArg(options.cppVersion)
109
+ };
110
+ }
24
111
  const toUtf8 = (text) => {
25
112
  const surrogate = encodeURIComponent(text);
26
113
  let result = '';
@@ -127,8 +214,11 @@ export default class Clang {
127
214
  const input = options.input;
128
215
  let source = options.code;
129
216
  const obj = options.obj;
217
+ const language = options.language === 'C' ? 'C' : 'CPP';
218
+ const compileArgs = options.compileArgs ?? options.args ?? [];
219
+ const { languageArg, standardArg } = resolveClangLanguageArgs(language, options);
130
220
  const debug = !!options.debug;
131
- const opt = debug ? '0' : (options.opt || '2');
221
+ const opt = debug ? '0' : options.opt || '2';
132
222
  if (debug) {
133
223
  const lines = source.split('\n');
134
224
  let braceDepth = 0;
@@ -231,7 +321,8 @@ export default class Clang {
231
321
  }
232
322
  else {
233
323
  analysisLine =
234
- analysisLine.slice(0, commentStart) + analysisLine.slice(commentEnd + 2);
324
+ analysisLine.slice(0, commentStart) +
325
+ analysisLine.slice(commentEnd + 2);
235
326
  }
236
327
  }
237
328
  const lineComment = analysisLine.indexOf('//');
@@ -343,7 +434,9 @@ export default class Clang {
343
434
  let declarationParenDepth = 0;
344
435
  let declarationBraceDepth = 0;
345
436
  for (const character of declarationMatch[2]) {
346
- if (character === ',' && declarationParenDepth === 0 && declarationBraceDepth === 0) {
437
+ if (character === ',' &&
438
+ declarationParenDepth === 0 &&
439
+ declarationBraceDepth === 0) {
347
440
  if (declarationBuffer.trim())
348
441
  declarations.push(declarationBuffer.trim());
349
442
  declarationBuffer = '';
@@ -491,7 +584,8 @@ export default class Clang {
491
584
  }
492
585
  }
493
586
  for (const [name, variable] of globalVariables) {
494
- if (currentFunctionVariables.has(name) || currentFunctionContainers.has(name))
587
+ if (currentFunctionVariables.has(name) ||
588
+ currentFunctionContainers.has(name))
495
589
  continue;
496
590
  const escapedName = name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
497
591
  if (new RegExp(`(?:^|[^\\w])(?:\\+\\+|--)\\s*${escapedName}\\b`).test(normalized) ||
@@ -529,7 +623,8 @@ export default class Clang {
529
623
  for (const [name, variable] of currentFunctionVariables) {
530
624
  const escapedName = name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
531
625
  const mutationPattern = new RegExp(`(?:^|[^\\w])(?:\\+\\+|--)\\s*${escapedName}\\b|\\b${escapedName}\\s*(?:[+\\-*/%]?=|\\+\\+|--)`);
532
- if (!initLooksLikeDeclaration && mutationPattern.test(initSource)) {
626
+ if (!initLooksLikeDeclaration &&
627
+ mutationPattern.test(initSource)) {
533
628
  initHooks.push(`${variable.kind === 'bool' ? '__wasm_idle_debug_value_bool' : '__wasm_idle_debug_value_num'}(${currentFunctionId}, ${variable.slot}, ${name})`);
534
629
  }
535
630
  if (mutationPattern.test(updateSource)) {
@@ -648,9 +743,11 @@ export default class Clang {
648
743
  if (!nameMatch)
649
744
  continue;
650
745
  const name = nameMatch[1];
651
- const kind = /\bbool\b/.test(cleaned) ? 'bool' : /\b(?:int|float|double|char|short|long)\b/.test(cleaned)
652
- ? 'number'
653
- : '';
746
+ const kind = /\bbool\b/.test(cleaned)
747
+ ? 'bool'
748
+ : /\b(?:int|float|double|char|short|long)\b/.test(cleaned)
749
+ ? 'number'
750
+ : '';
654
751
  if (!kind)
655
752
  continue;
656
753
  const slot = nextVariableSlot++;
@@ -721,11 +818,11 @@ export default class Clang {
721
818
  '-O' + opt,
722
819
  '-o',
723
820
  obj,
724
- clangLanguageStandardArg,
821
+ standardArg,
725
822
  '-x',
726
- 'c++',
823
+ languageArg,
727
824
  input,
728
- ...(options.args || [])
825
+ ...compileArgs
729
826
  ];
730
827
  this.trace(`compile ${input} -> ${obj}`);
731
828
  return await this.run(clang, true, 'clang', ...compilerArgs);
@@ -781,34 +878,53 @@ export default class Clang {
781
878
  return stillRunning ? app : null;
782
879
  }
783
880
  async compileLink(code, options = {}) {
784
- const { args = [], debug = false, breakpoints = [], pauseOnEntry = false, debugBuffer, interruptBuffer } = options;
785
- const input = `test.cc`, obj = `test.o`, wasm = `test.wasm`;
881
+ const { language = 'CPP', args = [], compileArgs = args, debug = false, breakpoints = [], pauseOnEntry = false, cppVersion, cVersion, debugBuffer, interruptBuffer } = options;
882
+ const input = language === 'C' ? `test.c` : `test.cc`, obj = `test.o`, wasm = `test.wasm`;
786
883
  this.beginTrace(debug);
787
884
  this.debugBreakpoints = new Set(debug ? breakpoints : []);
788
885
  this.debugPauseOnEntry = debug && pauseOnEntry;
789
886
  this.debugBuffer = debugBuffer;
790
887
  this.debugInterruptBuffer = interruptBuffer;
791
- const buildKey = JSON.stringify({ code, args, debug });
888
+ const buildKey = JSON.stringify({
889
+ code,
890
+ language,
891
+ compileArgs,
892
+ cppVersion,
893
+ cVersion,
894
+ debug
895
+ });
792
896
  if (this.lastBuildKey === buildKey) {
793
897
  this.trace(`reuse ${wasm}`);
794
898
  return this.wasm;
795
899
  }
796
- await this.compile({ input, code, obj, args, debug });
900
+ await this.compile({
901
+ input,
902
+ code,
903
+ obj,
904
+ language,
905
+ compileArgs,
906
+ cppVersion,
907
+ cVersion,
908
+ debug
909
+ });
797
910
  await this.link(obj, wasm, debug);
798
911
  this.lastBuildKey = buildKey;
799
912
  const wasmBytes = Uint8Array.from(this.memfs.getFileContents(wasm));
800
913
  return (this.wasm = await this.hostLogAsync(`Compiling ${wasm}`, WebAssembly.compile(wasmBytes)));
801
914
  }
802
915
  async compileLinkRun(code, options = {}) {
803
- const { args = [], debug = false, breakpoints = [], pauseOnEntry = false, debugBuffer, interruptBuffer } = options;
916
+ const { language = 'CPP', args = [], compileArgs = args, programArgs = [], debug = false, breakpoints = [], pauseOnEntry = false, cppVersion, cVersion, debugBuffer, interruptBuffer } = options;
804
917
  this.debug = debug;
805
918
  return await this.run(await this.compileLink(code, {
806
- args,
919
+ language,
920
+ compileArgs,
807
921
  debug,
808
922
  breakpoints,
809
923
  pauseOnEntry,
924
+ cppVersion,
925
+ cVersion,
810
926
  debugBuffer,
811
927
  interruptBuffer
812
- }), true, `test.wasm`);
928
+ }), true, `test.wasm`, ...programArgs);
813
929
  }
814
930
  }
package/dist/index.d.ts CHANGED
@@ -5,4 +5,5 @@ export default Terminal;
5
5
  export { playground };
6
6
  export type { DebugCommand, DebugFrame, DebugSessionEvent, DebugVariable, SandboxExecutionOptions, TerminalControl } from './terminal';
7
7
  export type { CompilerDiagnostic } from './playground/options';
8
+ export type { PlaygroundRuntimeAssets, RuntimeAssetConfig, RuntimeAssetLoadRequest, RuntimeAssetLoader, RuntimeAssetLoaderResult } from './playground/assets';
8
9
  export type { DebugLanguageAdapter } from './debug';
@@ -0,0 +1,20 @@
1
+ import { type ResolvedRuntimeAssetConfig, type RuntimeAssetRuntime } from './assets';
2
+ type ProgressLike = {
3
+ set?: (value: number) => void;
4
+ };
5
+ export declare class WorkerAssetBridge {
6
+ private worker;
7
+ private readonly runtime;
8
+ private config;
9
+ private readonly progress;
10
+ constructor(worker: Worker, runtime: RuntimeAssetRuntime, config: ResolvedRuntimeAssetConfig, progress?: ProgressLike);
11
+ matches(config: ResolvedRuntimeAssetConfig): boolean;
12
+ rebind(worker: Worker, config: ResolvedRuntimeAssetConfig, progress?: ProgressLike): void;
13
+ resetProgress(progress?: ProgressLike): void;
14
+ handleMessage(event: MessageEvent<any>): boolean;
15
+ private respond;
16
+ private loadAsset;
17
+ private normalizeLoaderResult;
18
+ private fetchAsset;
19
+ }
20
+ export {};
@@ -0,0 +1,192 @@
1
+ import { JAVA_RUNTIME_LOAD_ASSETS, PYTHON_RUNTIME_LOAD_ASSETS } from './assets';
2
+ const encoder = new TextEncoder();
3
+ const transferBuffer = (bytes) => bytes.byteOffset === 0 && bytes.byteLength === bytes.buffer.byteLength
4
+ ? bytes.buffer
5
+ : bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
6
+ const expectedAssetsForRuntime = (runtime) => new Set(runtime === 'python' ? [...PYTHON_RUNTIME_LOAD_ASSETS] : [...JAVA_RUNTIME_LOAD_ASSETS]);
7
+ class RuntimeLoadProgress {
8
+ fractions = new Map();
9
+ expectedAssets;
10
+ progress;
11
+ constructor(runtime) {
12
+ this.expectedAssets = expectedAssetsForRuntime(runtime);
13
+ this.reset();
14
+ }
15
+ reset(progress) {
16
+ this.progress = progress;
17
+ this.fractions.clear();
18
+ for (const asset of this.expectedAssets)
19
+ this.fractions.set(asset, 0);
20
+ this.emit();
21
+ }
22
+ update(asset, loaded, total) {
23
+ if (!this.expectedAssets.has(asset))
24
+ return;
25
+ const fraction = total && total > 0 ? Math.min(loaded / total, 1) : loaded > 0 ? 1 : 0;
26
+ this.fractions.set(asset, fraction);
27
+ this.emit();
28
+ }
29
+ emit() {
30
+ if (!this.progress)
31
+ return;
32
+ if (!this.fractions.size)
33
+ return this.progress.set?.(0);
34
+ let total = 0;
35
+ for (const fraction of this.fractions.values())
36
+ total += fraction;
37
+ this.progress.set?.(total / this.fractions.size);
38
+ }
39
+ }
40
+ export class WorkerAssetBridge {
41
+ worker;
42
+ runtime;
43
+ config;
44
+ progress;
45
+ constructor(worker, runtime, config, progress) {
46
+ this.worker = worker;
47
+ this.runtime = runtime;
48
+ this.config = config;
49
+ this.progress = new RuntimeLoadProgress(runtime);
50
+ this.progress.reset(progress);
51
+ }
52
+ matches(config) {
53
+ return (this.config.baseUrl === config.baseUrl &&
54
+ this.config.loader === config.loader &&
55
+ this.config.useAssetBridge === config.useAssetBridge);
56
+ }
57
+ rebind(worker, config, progress) {
58
+ this.worker = worker;
59
+ this.config = config;
60
+ this.progress.reset(progress);
61
+ }
62
+ resetProgress(progress) {
63
+ this.progress.reset(progress);
64
+ }
65
+ handleMessage(event) {
66
+ const assetRequest = event.data?.assetRequest;
67
+ if (assetRequest) {
68
+ void this.respond(assetRequest);
69
+ return true;
70
+ }
71
+ const assetProgress = event.data?.assetProgress;
72
+ if (assetProgress) {
73
+ this.progress.update(assetProgress.asset, assetProgress.loaded, assetProgress.total);
74
+ return true;
75
+ }
76
+ return false;
77
+ }
78
+ async respond(request) {
79
+ try {
80
+ const loaded = await this.loadAsset(request.asset);
81
+ const buffer = transferBuffer(loaded.bytes);
82
+ this.worker.postMessage({
83
+ assetResponse: {
84
+ id: request.id,
85
+ ok: true,
86
+ bytes: buffer,
87
+ mimeType: loaded.mimeType
88
+ }
89
+ }, [buffer]);
90
+ }
91
+ catch (error) {
92
+ this.worker.postMessage({
93
+ assetResponse: {
94
+ id: request.id,
95
+ ok: false,
96
+ error: error instanceof Error ? error.message : String(error)
97
+ }
98
+ });
99
+ }
100
+ }
101
+ async loadAsset(asset) {
102
+ const reportProgress = (loaded, total) => this.progress.update(asset, loaded, total);
103
+ if (this.config.loader) {
104
+ const loaded = await this.normalizeLoaderResult(await this.config.loader({
105
+ runtime: this.runtime,
106
+ asset,
107
+ reportProgress
108
+ }), asset);
109
+ if (loaded)
110
+ return loaded;
111
+ }
112
+ return await this.fetchAsset(new URL(asset, this.config.baseUrl).href, asset);
113
+ }
114
+ async normalizeLoaderResult(result, asset) {
115
+ if (!result)
116
+ return null;
117
+ if (typeof result === 'string' || result instanceof URL) {
118
+ return await this.fetchAsset(String(result), asset);
119
+ }
120
+ if (result instanceof ArrayBuffer) {
121
+ const bytes = new Uint8Array(result);
122
+ this.progress.update(asset, bytes.byteLength, bytes.byteLength);
123
+ return { bytes };
124
+ }
125
+ if (result instanceof Uint8Array) {
126
+ this.progress.update(asset, result.byteLength, result.byteLength);
127
+ return { bytes: result };
128
+ }
129
+ if (result instanceof Blob) {
130
+ const bytes = new Uint8Array(await result.arrayBuffer());
131
+ this.progress.update(asset, bytes.byteLength, bytes.byteLength);
132
+ return { bytes, mimeType: result.type || undefined };
133
+ }
134
+ if ('url' in result && result.url) {
135
+ return await this.fetchAsset(String(result.url), asset);
136
+ }
137
+ if ('data' in result) {
138
+ if (typeof result.data === 'string') {
139
+ const bytes = encoder.encode(result.data);
140
+ this.progress.update(asset, bytes.byteLength, bytes.byteLength);
141
+ return { bytes, mimeType: result.mimeType };
142
+ }
143
+ if (result.data instanceof ArrayBuffer) {
144
+ const bytes = new Uint8Array(result.data);
145
+ this.progress.update(asset, bytes.byteLength, bytes.byteLength);
146
+ return { bytes, mimeType: result.mimeType };
147
+ }
148
+ if (result.data instanceof Uint8Array) {
149
+ this.progress.update(asset, result.data.byteLength, result.data.byteLength);
150
+ return { bytes: result.data, mimeType: result.mimeType };
151
+ }
152
+ const bytes = new Uint8Array(await result.data.arrayBuffer());
153
+ this.progress.update(asset, bytes.byteLength, bytes.byteLength);
154
+ return { bytes, mimeType: result.mimeType || result.data.type || undefined };
155
+ }
156
+ return null;
157
+ }
158
+ async fetchAsset(url, asset) {
159
+ const response = await fetch(url);
160
+ if (!response.ok)
161
+ throw new Error(`Failed to load ${asset}: ${response.status}`);
162
+ const contentLength = Number(response.headers.get('content-length') || 0) || undefined;
163
+ const mimeType = response.headers.get('content-type') || undefined;
164
+ if (!response.body) {
165
+ const bytes = new Uint8Array(await response.arrayBuffer());
166
+ this.progress.update(asset, bytes.byteLength, contentLength ?? bytes.byteLength);
167
+ return { bytes, mimeType };
168
+ }
169
+ const reader = response.body.getReader();
170
+ let receivedLength = 0;
171
+ const chunks = [];
172
+ while (true) {
173
+ const { done, value } = await reader.read();
174
+ if (done)
175
+ break;
176
+ if (!value)
177
+ continue;
178
+ const chunk = Uint8Array.from(value);
179
+ chunks.push(chunk);
180
+ receivedLength += chunk.byteLength;
181
+ this.progress.update(asset, receivedLength, contentLength);
182
+ }
183
+ const bytes = new Uint8Array(receivedLength);
184
+ let position = 0;
185
+ for (const chunk of chunks) {
186
+ bytes.set(chunk, position);
187
+ position += chunk.byteLength;
188
+ }
189
+ this.progress.update(asset, receivedLength, contentLength ?? receivedLength);
190
+ return { bytes, mimeType };
191
+ }
192
+ }
@@ -0,0 +1,32 @@
1
+ export type RuntimeAssetRuntime = 'python' | 'java';
2
+ export interface RuntimeAssetLoadRequest {
3
+ runtime: RuntimeAssetRuntime;
4
+ asset: string;
5
+ reportProgress: (loaded: number, total?: number) => void;
6
+ }
7
+ export interface RuntimeAssetDataResult {
8
+ data: string | ArrayBuffer | Uint8Array | Blob;
9
+ mimeType?: string;
10
+ }
11
+ export interface RuntimeAssetUrlResult {
12
+ url: string | URL;
13
+ }
14
+ export type RuntimeAssetLoaderResult = RuntimeAssetDataResult | RuntimeAssetUrlResult | string | URL | ArrayBuffer | Uint8Array | Blob | null | undefined;
15
+ export type RuntimeAssetLoader = (request: RuntimeAssetLoadRequest) => RuntimeAssetLoaderResult | Promise<RuntimeAssetLoaderResult>;
16
+ export interface RuntimeAssetConfig {
17
+ baseUrl?: string;
18
+ loader?: RuntimeAssetLoader;
19
+ }
20
+ export interface PlaygroundRuntimeAssets {
21
+ rootUrl?: string;
22
+ python?: RuntimeAssetConfig;
23
+ java?: RuntimeAssetConfig;
24
+ }
25
+ export interface ResolvedRuntimeAssetConfig {
26
+ baseUrl: string;
27
+ loader?: RuntimeAssetLoader;
28
+ useAssetBridge: boolean;
29
+ }
30
+ export declare const PYTHON_RUNTIME_LOAD_ASSETS: readonly ["pyodide.asm.js", "pyodide-lock.json", "pyodide.asm.wasm", "python_stdlib.zip"];
31
+ export declare const JAVA_RUNTIME_LOAD_ASSETS: readonly ["compiler.wasm-runtime.js", "compiler.wasm", "compile-classlib-teavm.bin", "runtime-classlib-teavm.bin"];
32
+ export declare function resolveRuntimeAssetConfig(runtime: RuntimeAssetRuntime, options: string | PlaygroundRuntimeAssets | undefined, currentUrl?: string): ResolvedRuntimeAssetConfig;