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.
Files changed (145) hide show
  1. package/README.md +140 -37
  2. package/dist/playground/assetBridge.js +106 -31
  3. package/dist/playground/assets.d.ts +2 -2
  4. package/dist/playground/c3.js +22 -0
  5. package/dist/playground/c3Memory.d.ts +19 -0
  6. package/dist/playground/c3Memory.js +117 -0
  7. package/dist/playground/cachedClang.js +143 -34
  8. package/dist/playground/clangAssetIntegrity.js +6 -6
  9. package/dist/playground/clangWorkerProtocol.d.ts +12 -1
  10. package/dist/playground/cobol.d.ts +3 -0
  11. package/dist/playground/cobol.js +10 -1
  12. package/dist/playground/commonlispAssets.d.ts +2 -2
  13. package/dist/playground/compiledArtifactCache.d.ts +3 -1
  14. package/dist/playground/compiledArtifactCache.js +31 -5
  15. package/dist/playground/container/ContainerExplorer.svelte +307 -0
  16. package/dist/playground/container/ContainerExplorer.svelte.d.ts +14 -0
  17. package/dist/playground/container/binding.d.ts +26 -0
  18. package/dist/playground/container/binding.js +247 -0
  19. package/dist/playground/container/clang-runtime.d.ts +38 -0
  20. package/dist/playground/container/clang-runtime.js +343 -0
  21. package/dist/playground/container/client.d.ts +15 -0
  22. package/dist/playground/container/client.js +189 -0
  23. package/dist/playground/container/explorer.d.ts +31 -0
  24. package/dist/playground/container/explorer.js +112 -0
  25. package/dist/playground/container/owner.worker.js +390 -0
  26. package/dist/playground/container/protocol.d.ts +73 -0
  27. package/dist/playground/container/protocol.js +28 -0
  28. package/dist/playground/container/release.d.ts +31 -0
  29. package/dist/playground/container/release.js +612 -0
  30. package/dist/playground/container/runtime-adapter.d.ts +73 -0
  31. package/dist/playground/container/runtime-adapter.js +474 -0
  32. package/dist/playground/container/shell-control.d.ts +49 -0
  33. package/dist/playground/container/shell-control.js +303 -0
  34. package/dist/playground/container/workspace.d.ts +8 -0
  35. package/dist/playground/container/workspace.js +29 -0
  36. package/dist/playground/d.d.ts +6 -1
  37. package/dist/playground/d.js +83 -5
  38. package/dist/playground/dotnet.js +6 -8
  39. package/dist/playground/fortran.d.ts +3 -0
  40. package/dist/playground/fortran.js +10 -1
  41. package/dist/playground/go.js +14 -3
  42. package/dist/playground/goDebugInstrumentation.js +184 -54
  43. package/dist/playground/java.js +3 -2
  44. package/dist/playground/javaRuntimeErrors.d.ts +9 -0
  45. package/dist/playground/javaRuntimeErrors.js +60 -0
  46. package/dist/playground/lean4Assets.d.ts +4 -4
  47. package/dist/playground/lfortran.js +10 -0
  48. package/dist/playground/lfortranAssets.d.ts +2 -2
  49. package/dist/playground/nim.js +22 -0
  50. package/dist/playground/objectivec.d.ts +3 -0
  51. package/dist/playground/objectivec.js +11 -2
  52. package/dist/playground/options.d.ts +2 -0
  53. package/dist/playground/python.js +8 -0
  54. package/dist/playground/runtimeAssetCache.d.ts +1 -32
  55. package/dist/playground/runtimeAssetCache.js +1 -193
  56. package/dist/playground/runtimeSession.d.ts +2 -2
  57. package/dist/playground/runtimeSession.js +11 -11
  58. package/dist/playground/rust.d.ts +6 -0
  59. package/dist/playground/rust.js +103 -6
  60. package/dist/playground/staticStdinRing.d.ts +2 -1
  61. package/dist/playground/staticStdinRing.js +21 -10
  62. package/dist/playground/staticWorkerRuntime.d.ts +15 -1
  63. package/dist/playground/staticWorkerRuntime.js +119 -17
  64. package/dist/playground/tinygo.d.ts +3 -0
  65. package/dist/playground/tinygo.js +81 -6
  66. package/dist/playground/v.d.ts +3 -0
  67. package/dist/playground/v.js +10 -1
  68. package/dist/playground/wasmAwkVersion.d.ts +13 -13
  69. package/dist/playground/wasmAwkVersion.js +4 -4
  70. package/dist/playground/wasmBqnVersion.d.ts +2 -2
  71. package/dist/playground/wasmBqnVersion.js +2 -2
  72. package/dist/playground/wasmC3Version.d.ts +2 -2
  73. package/dist/playground/wasmC3Version.js +2 -2
  74. package/dist/playground/wasmClojureScriptVersion.d.ts +2 -2
  75. package/dist/playground/wasmClojureScriptVersion.js +2 -2
  76. package/dist/playground/wasmCommonLispVersion.d.ts +2 -2
  77. package/dist/playground/wasmCommonLispVersion.js +2 -2
  78. package/dist/playground/wasmDIntegrity.d.ts +5 -5
  79. package/dist/playground/wasmDIntegrity.js +5 -5
  80. package/dist/playground/wasmDVersion.d.ts +16 -1
  81. package/dist/playground/wasmDVersion.js +16 -1
  82. package/dist/playground/wasmDebugVersion.d.ts +1 -1
  83. package/dist/playground/wasmDebugVersion.js +1 -1
  84. package/dist/playground/wasmForthVersion.d.ts +2 -2
  85. package/dist/playground/wasmForthVersion.js +2 -2
  86. package/dist/playground/wasmGleamVersion.d.ts +2 -2
  87. package/dist/playground/wasmGleamVersion.js +2 -2
  88. package/dist/playground/wasmGrainVersion.d.ts +2 -2
  89. package/dist/playground/wasmGrainVersion.js +2 -2
  90. package/dist/playground/wasmJVersion.d.ts +2 -2
  91. package/dist/playground/wasmJVersion.js +2 -2
  92. package/dist/playground/wasmJanetVersion.js +2 -2
  93. package/dist/playground/wasmJuliaVersion.js +2 -2
  94. package/dist/playground/wasmLean4Version.d.ts +5 -5
  95. package/dist/playground/wasmLean4Version.js +5 -5
  96. package/dist/playground/wasmLfortranVersion.d.ts +2 -2
  97. package/dist/playground/wasmLfortranVersion.js +2 -2
  98. package/dist/playground/wasmNimVersion.d.ts +9 -9
  99. package/dist/playground/wasmNimVersion.js +6 -6
  100. package/dist/playground/wasmOcamlVersion.d.ts +2 -2
  101. package/dist/playground/wasmOcamlVersion.js +1 -1
  102. package/dist/playground/wasmPascalVersion.js +2 -2
  103. package/dist/playground/wasmPerlVersion.js +2 -2
  104. package/dist/playground/wasmPrologVersion.d.ts +2 -2
  105. package/dist/playground/wasmPrologVersion.js +2 -2
  106. package/dist/playground/wasmReScriptVersion.d.ts +2 -2
  107. package/dist/playground/wasmReScriptVersion.js +2 -2
  108. package/dist/playground/wasmRustVersion.d.ts +8 -8
  109. package/dist/playground/wasmRustVersion.js +7 -7
  110. package/dist/playground/wasmTclVersion.d.ts +4 -4
  111. package/dist/playground/wasmTclVersion.js +2 -2
  112. package/dist/playground/wasmTinyGoVersion.d.ts +14 -14
  113. package/dist/playground/wasmTinyGoVersion.js +14 -14
  114. package/dist/playground/wasmTypeScriptVersion.d.ts +5 -5
  115. package/dist/playground/wasmTypeScriptVersion.js +5 -5
  116. package/dist/playground/worker/cachedClangCompile.js +52 -4
  117. package/dist/playground/worker/cachedClangExecute.js +6 -5
  118. package/dist/playground/worker/clang.js +32 -10
  119. package/dist/playground/worker/cobol.js +2 -2
  120. package/dist/playground/worker/d.js +12 -5
  121. package/dist/playground/worker/fortran.js +2 -2
  122. package/dist/playground/worker/go.js +16 -5
  123. package/dist/playground/worker/haskell.js +10 -7
  124. package/dist/playground/worker/java.js +75 -10
  125. package/dist/playground/worker/lua.js +2 -3
  126. package/dist/playground/worker/php.js +15 -9
  127. package/dist/playground/worker/python.js +46 -9
  128. package/dist/playground/worker/pythonExecution.js +17 -1
  129. package/dist/playground/worker/pythonWorkspaceFiles.d.ts +6 -0
  130. package/dist/playground/worker/pythonWorkspaceFiles.js +26 -0
  131. package/dist/playground/worker/pythonWorkspaceImports.d.ts +4 -0
  132. package/dist/playground/worker/pythonWorkspaceImports.js +129 -0
  133. package/dist/playground/worker/r.js +13 -6
  134. package/dist/playground/worker/rust.js +34 -2
  135. package/dist/playground/worker/sqlite.js +4 -3
  136. package/dist/playground/worker/tinygo.js +11 -3
  137. package/dist/playground/worker/typescript.js +2 -3
  138. package/dist/playground/worker/v.js +2 -2
  139. package/dist/playground/worker/wat.js +2 -3
  140. package/dist/playground/worker/zig.js +20 -6
  141. package/dist/playground/workerSession.d.ts +1 -28
  142. package/dist/playground/workerSession.js +1 -164
  143. package/package.json +20 -13
  144. package/dist/playground/worker/python.runtime.cases.js +0 -374
  145. /package/dist/playground/{worker/python.runtime.cases.d.ts → container/owner.worker.d.ts} +0 -0
@@ -69,59 +69,112 @@ function stripLineComment(line) {
69
69
  const commentStart = lineCommentStart(line);
70
70
  return commentStart === -1 ? line : line.slice(0, commentStart);
71
71
  }
72
- function countNesting(line) {
73
- const source = stripLineComment(line);
74
- let quote = '';
75
- let escaped = false;
76
- let braces = 0;
77
- let parens = 0;
78
- let brackets = 0;
79
- for (const character of source) {
80
- if (quote) {
81
- if (quote === '`') {
82
- if (character === '`')
83
- quote = '';
84
- continue;
85
- }
86
- if (escaped) {
87
- escaped = false;
88
- continue;
89
- }
90
- if (character === '\\') {
91
- escaped = true;
92
- continue;
72
+ const goKeywords = new Set([
73
+ ...'break case chan const continue default defer else fallthrough for func go'.split(' '),
74
+ ...'goto if import interface map package range return select struct switch type var'.split(' ')
75
+ ]);
76
+ // Final tokens after which Go inserts a semicolon at a line break. Literals are tokenized as
77
+ // '0' (number), '"' (string), "'" (rune) and '`' (raw string).
78
+ const statementEndTokens = new Set([
79
+ ...'break continue fallthrough return ++ -- ) ] }'.split(' '),
80
+ ...['0', '"', "'", '`']
81
+ ]);
82
+ function isIdentifier(token) {
83
+ return token !== undefined && /^[\p{L}_]/u.test(token) && !goKeywords.has(token);
84
+ }
85
+ function endsStatement(token) {
86
+ return statementEndTokens.has(token) || isIdentifier(token);
87
+ }
88
+ // Inside an if/for/switch header Go reads `T{` as the block, but `[]T{`, `[N]*pkg.T{`,
89
+ // `map[K]V{` and `struct{...}{` still open composite literals.
90
+ function followsLiteralType(tokens, braceIndex, closedFrame) {
91
+ let index = braceIndex - 1;
92
+ if (tokens[index] === '}')
93
+ return closedFrame === 'type';
94
+ if (!isIdentifier(tokens[index]))
95
+ return false;
96
+ index -= 1;
97
+ if (tokens[index] === '.' && isIdentifier(tokens[index - 1]))
98
+ index -= 2;
99
+ const pointer = tokens[index] === '*';
100
+ while (tokens[index] === '*')
101
+ index -= 1;
102
+ if (tokens[index] !== ']')
103
+ return false;
104
+ if (!pointer)
105
+ return true;
106
+ // `a[i] * b {` multiplies; only `[]*T` and `map[K]*V` are element types.
107
+ let open = index - 1;
108
+ for (let depth = 1; open >= 0; open -= 1) {
109
+ if (tokens[open] === ']')
110
+ depth += 1;
111
+ else if (tokens[open] === '[' && --depth === 0)
112
+ break;
113
+ }
114
+ return open === index - 1 || tokens[open - 1] === 'map';
115
+ }
116
+ function lineTokens(line, state) {
117
+ const tokens = [];
118
+ const wordPattern = /[\p{L}_][\p{L}\p{N}_]*|\.?\d[\p{L}\p{N}_.]*/uy;
119
+ let index = 0;
120
+ while (index < line.length) {
121
+ if (state.rawString || state.blockComment) {
122
+ const end = line.indexOf(state.rawString ? '`' : '*/', index);
123
+ if (end === -1)
124
+ break;
125
+ if (state.rawString)
126
+ tokens.push('`');
127
+ index = end + (state.rawString ? 1 : 2);
128
+ state.rawString = false;
129
+ state.blockComment = false;
130
+ continue;
131
+ }
132
+ const character = line[index] || '';
133
+ if (/\s/.test(character)) {
134
+ index += 1;
135
+ continue;
136
+ }
137
+ if (line.startsWith('//', index))
138
+ break;
139
+ if (line.startsWith('/*', index)) {
140
+ state.blockComment = true;
141
+ index += 2;
142
+ continue;
143
+ }
144
+ if (character === '`') {
145
+ state.rawString = true;
146
+ index += 1;
147
+ continue;
148
+ }
149
+ if (character === '"' || character === "'") {
150
+ index += 1;
151
+ while (index < line.length && line[index] !== character) {
152
+ index += line[index] === '\\' ? 2 : 1;
93
153
  }
94
- if (character === quote)
95
- quote = '';
154
+ tokens.push(character);
155
+ index += 1;
96
156
  continue;
97
157
  }
98
- if (character === '"' || character === "'" || character === '`') {
99
- quote = character;
158
+ wordPattern.lastIndex = index;
159
+ const word = wordPattern.exec(line)?.[0];
160
+ if (word) {
161
+ tokens.push(/^[\p{L}_]/u.test(word) ? word : '0');
162
+ index += word.length;
100
163
  continue;
101
164
  }
102
- if (character === '{')
103
- braces += 1;
104
- else if (character === '}')
105
- braces -= 1;
106
- else if (character === '(')
107
- parens += 1;
108
- else if (character === ')')
109
- parens -= 1;
110
- else if (character === '[')
111
- brackets += 1;
112
- else if (character === ']')
113
- brackets -= 1;
165
+ const operator = ['++', '--', ':=', '...'].find((candidate) => line.startsWith(candidate, index)) ||
166
+ character;
167
+ tokens.push(operator);
168
+ index += operator.length;
114
169
  }
115
- return { braces, parens, brackets };
170
+ return tokens;
116
171
  }
117
172
  function functionNameFromLine(line) {
118
173
  const source = stripLineComment(line).trim();
119
174
  const match = source.match(/^func\s+(?:\([^)]*\)\s*)?([A-Za-z_]\w*)\s*\(/);
120
175
  return match?.[1] || null;
121
176
  }
122
- function shouldInstrumentLine(line, parenDepth, bracketDepth) {
123
- if (parenDepth > 0 || bracketDepth > 0)
124
- return false;
177
+ function shouldInstrumentLine(line) {
125
178
  const trimmed = stripLineComment(line).trim();
126
179
  if (!trimmed)
127
180
  return false;
@@ -190,31 +243,108 @@ function instrumentFunctionLines(source) {
190
243
  const lines = source.split('\n');
191
244
  const instrumented = [];
192
245
  const functionStack = [];
246
+ const lexState = { rawString: false, blockComment: false };
247
+ const frames = [];
248
+ // Frame depths where a `func` signature still awaits its body, and where an if/for/switch
249
+ // header still awaits its block.
250
+ let pendingFunctionDepths = [];
251
+ let headerDepth = -1;
252
+ let closedFrame;
253
+ let previousToken = ';';
254
+ let continuesStatement = false;
255
+ let followsLabel = false;
193
256
  let braceDepth = 0;
194
- let parenDepth = 0;
195
- let bracketDepth = 0;
196
257
  for (let index = 0; index < lines.length; index += 1) {
197
258
  const line = lines[index] || '';
198
259
  const lineNumber = index + 1;
199
- const functionName = functionNameFromLine(line);
260
+ const startsInCode = !lexState.rawString && !lexState.blockComment;
261
+ const functionName = startsInCode ? functionNameFromLine(line) : null;
200
262
  const inFunction = functionStack.length > 0;
201
263
  const indent = line.match(/^\s*/)?.[0] || '';
202
- if (inFunction && shouldInstrumentLine(line, parenDepth, bracketDepth)) {
264
+ // Only hook lines that start a statement directly inside a block: not inside a raw
265
+ // string, comment, composite literal, call or index, and not continuing the previous line.
266
+ if (inFunction &&
267
+ startsInCode &&
268
+ frames.at(-1) === 'block' &&
269
+ !frames.includes('(') &&
270
+ !frames.includes('[') &&
271
+ !continuesStatement &&
272
+ !followsLabel &&
273
+ shouldInstrumentLine(line)) {
203
274
  instrumented.push(`${indent}__wasmIdleDebugLine(${lineNumber})`);
204
275
  }
205
276
  instrumented.push(line);
206
- const nesting = countNesting(line);
207
- const nextBraceDepth = braceDepth + nesting.braces;
208
- const nextParenDepth = Math.max(0, parenDepth + nesting.parens);
209
- const nextBracketDepth = Math.max(0, bracketDepth + nesting.brackets);
210
- if (functionName && nesting.braces > 0) {
277
+ const tokens = lineTokens(line, lexState);
278
+ let braces = 0;
279
+ for (let tokenIndex = 0; tokenIndex < tokens.length; tokenIndex += 1) {
280
+ const token = tokens[tokenIndex] || '';
281
+ const depth = frames.length;
282
+ if (token === '(' || token === '[') {
283
+ frames.push(token);
284
+ }
285
+ else if (token === ')' || token === ']' || token === '}') {
286
+ closedFrame = frames.pop();
287
+ if (token === '}')
288
+ braces -= 1;
289
+ pendingFunctionDepths = pendingFunctionDepths.filter((pending) => pending <= frames.length);
290
+ if (headerDepth > frames.length)
291
+ headerDepth = -1;
292
+ }
293
+ else if (token === '{') {
294
+ let frame = '{';
295
+ if (pendingFunctionDepths.includes(depth)) {
296
+ frame = 'block';
297
+ pendingFunctionDepths = pendingFunctionDepths.filter((pending) => pending !== depth);
298
+ }
299
+ else if (previousToken === 'struct' || previousToken === 'interface') {
300
+ frame = 'type';
301
+ }
302
+ else if (['else', 'for', 'switch', 'select'].includes(previousToken) ||
303
+ (headerDepth === depth &&
304
+ tokenIndex === tokens.length - 1 &&
305
+ !followsLiteralType(tokens, tokenIndex, closedFrame)) ||
306
+ ([';', '{', ':'].includes(previousToken) &&
307
+ (frames.at(-1) ?? 'block') === 'block')) {
308
+ // Go ends an if/for/switch header at the `{` that closes its line; any other
309
+ // `{` after an operand (`P{`, `[]int{`) opens a literal.
310
+ frame = 'block';
311
+ if (headerDepth === depth)
312
+ headerDepth = -1;
313
+ }
314
+ frames.push(frame);
315
+ braces += 1;
316
+ }
317
+ else if (token === 'func' && previousToken !== ']' && previousToken !== 'chan') {
318
+ pendingFunctionDepths.push(depth);
319
+ }
320
+ else if (['if', 'for', 'switch', 'select'].includes(token)) {
321
+ headerDepth = depth;
322
+ }
323
+ else if ([',', ';', '=', ':='].includes(token)) {
324
+ pendingFunctionDepths = pendingFunctionDepths.filter((pending) => pending !== depth);
325
+ }
326
+ previousToken = token;
327
+ }
328
+ const lastToken = tokens.at(-1);
329
+ if (lastToken !== undefined) {
330
+ const trimmed = stripLineComment(line).trim();
331
+ continuesStatement = !endsStatement(lastToken) && !['{', ':', ';'].includes(lastToken);
332
+ followsLabel = /^[A-Za-z_]\w*:$/.test(trimmed) && trimmed !== 'default:';
333
+ if (endsStatement(lastToken)) {
334
+ previousToken = ';';
335
+ pendingFunctionDepths = pendingFunctionDepths.filter((pending) => pending < frames.length);
336
+ if (headerDepth >= frames.length)
337
+ headerDepth = -1;
338
+ }
339
+ }
340
+ // A signature line that ends inside a raw string or block comment has no place for the
341
+ // entry hook; leave that function uninstrumented rather than edit the literal.
342
+ if (functionName && braces > 0 && !lexState.rawString && !lexState.blockComment) {
211
343
  const bodyIndent = `${indent}\t`;
212
344
  instrumented.push(`${bodyIndent}__wasmIdleDebugEnter(${JSON.stringify(functionName)}, ${lineNumber})`, `${bodyIndent}defer __wasmIdleDebugLeave()`);
213
- functionStack.push({ depth: nextBraceDepth, name: functionName });
345
+ functionStack.push({ depth: braceDepth + braces, name: functionName });
214
346
  }
215
- braceDepth = nextBraceDepth;
216
- parenDepth = nextParenDepth;
217
- bracketDepth = nextBracketDepth;
347
+ braceDepth += braces;
218
348
  while (functionStack.length &&
219
349
  braceDepth < functionStack[functionStack.length - 1].depth) {
220
350
  functionStack.pop();
@@ -687,8 +687,9 @@ class Java {
687
687
  resolve(results);
688
688
  return;
689
689
  }
690
- if (error)
691
- failRun(error);
690
+ if (Object.hasOwn(event.data, 'error')) {
691
+ failRun(error === '' ? 'Java execution failed' : error);
692
+ }
692
693
  }
693
694
  catch (error) {
694
695
  failRun(error, true);
@@ -0,0 +1,9 @@
1
+ /** A real Java entry point keeps exception formatting inside the Java class library. */
2
+ export declare function prepareJavaExceptionBridge(mainClass: string, sourceTexts: readonly string[], classFiles: readonly string[]): {
3
+ mainClass: string;
4
+ sourceFileName: string;
5
+ formatterSourceFileName: string;
6
+ formatExport: string;
7
+ source: string;
8
+ formatterSource: string;
9
+ };
@@ -0,0 +1,60 @@
1
+ /** A real Java entry point keeps exception formatting inside the Java class library. */
2
+ export function prepareJavaExceptionBridge(mainClass, sourceTexts, classFiles) {
3
+ const packageName = mainClass.slice(0, Math.max(0, mainClass.lastIndexOf('.')));
4
+ const packagePath = packageName ? `${packageName.replaceAll('.', '/')}/` : '';
5
+ const entryClass = mainClass.slice(mainClass.lastIndexOf('.') + 1);
6
+ const sourcePrefix = packageName ? `package ${packageName};\n\n` : '';
7
+ let className = 'WasmIdleJavaEntryPoint';
8
+ while (classFiles.some((path) => path === `${packagePath}${className}.class` ||
9
+ path.startsWith(`${packagePath}${className}$`)))
10
+ className += '_';
11
+ let formatterClass = 'WasmIdleJavaExceptionBridge';
12
+ while (classFiles.some((path) => path === `${packagePath}${formatterClass}.class` ||
13
+ path.startsWith(`${packagePath}${formatterClass}$`)))
14
+ formatterClass += '_';
15
+ // Conservatively reserve names even when user identifiers use Java Unicode escapes.
16
+ const decodedSources = sourceTexts.map((source) => source.replace(/\\u+([0-9a-f]{4})/gi, (_, hex) => String.fromCharCode(parseInt(hex, 16))));
17
+ let formatExport = 'wasmIdleFormatJavaException';
18
+ while (decodedSources.some((source) => source.includes(formatExport)))
19
+ formatExport += '_';
20
+ return {
21
+ mainClass: packageName ? `${packageName}.${formatterClass}` : formatterClass,
22
+ sourceFileName: `${className}.java`,
23
+ formatterSourceFileName: `${formatterClass}.java`,
24
+ formatExport,
25
+ // No imported types can hide the user entry class, even when it is named String.
26
+ source: `${sourcePrefix}final class ${className} {
27
+ static ${formatterClass}.Program program() {
28
+ return ${entryClass}::main;
29
+ }
30
+ }
31
+ `,
32
+ formatterSource: `${sourcePrefix}import java.lang.String;
33
+ import java.lang.Throwable;
34
+ import java.io.StringWriter;
35
+ import java.io.PrintWriter;
36
+ import org.teavm.jso.JSExport;
37
+ import org.teavm.jso.JSObject;
38
+ import org.teavm.jso.JSExceptions;
39
+
40
+ final class ${formatterClass} {
41
+ interface Program {
42
+ void run(String[] args) throws Throwable;
43
+ }
44
+
45
+ public static void main(String[] args) throws Throwable {
46
+ ${className}.program().run(args);
47
+ }
48
+
49
+ @JSExport
50
+ public static String ${formatExport}(JSObject error) {
51
+ Throwable exception = JSExceptions.getJavaException(error);
52
+ if (exception == null) return null;
53
+ StringWriter text = new StringWriter();
54
+ exception.printStackTrace(new PrintWriter(text));
55
+ return text.toString();
56
+ }
57
+ }
58
+ `
59
+ };
60
+ }
@@ -8,10 +8,10 @@ export declare const LEAN4_RUNTIME_MANIFEST: import("@wasm-idle/core").RuntimeRe
8
8
  export declare function resolveLean4RuntimeAssetConfig(runtimeAssets: string | PlaygroundRuntimeAssets, currentUrl: string): {
9
9
  baseUrl: string;
10
10
  workerUrl: string;
11
- manifestFingerprint: "e60eb3fdcc108fa7c6127c5a8925ffb622706facb17bc4f84e9ed27f82495fa1";
11
+ manifestFingerprint: "335bd6e1720371fc161859cb7c2858600ec12314c30da1f0e5e503e324a96d42";
12
12
  workerReceipt: {
13
- readonly bytes: 15759;
14
- readonly sha256: "469ef5ec7accf4c221d06134ccd4989f14e9229c61dd35c386617a015aec6f03";
13
+ readonly bytes: 16049;
14
+ readonly sha256: "3611a263c4304246c9ee2967c07be2a1c70764a39d642db87ba0b86bfbe9d519";
15
15
  };
16
16
  };
17
17
  export declare function preflightLean4RuntimeAssets(baseUrl: string, options: {
@@ -21,5 +21,5 @@ export declare function preflightLean4RuntimeAssets(baseUrl: string, options: {
21
21
  reportProgress?: (value: number, stage: string) => void;
22
22
  fetch?: typeof globalThis.fetch;
23
23
  }): Promise<Readonly<{
24
- fingerprint: "e60eb3fdcc108fa7c6127c5a8925ffb622706facb17bc4f84e9ed27f82495fa1";
24
+ fingerprint: "335bd6e1720371fc161859cb7c2858600ec12314c30da1f0e5e503e324a96d42";
25
25
  }>>;
@@ -1,5 +1,6 @@
1
1
  import { StaticWorkerRuntimeSandbox } from './staticWorkerRuntime';
2
2
  import { preflightLfortranRuntimeAssets, resolveLfortranRuntimeAssetConfig } from './lfortranAssets';
3
+ import { WASM_LFORTRAN_PROFILE as profile } from './wasmLfortranVersion';
3
4
  /** Real upstream FortranEvaluator using LLVM and Emscripten dynamic side modules. */
4
5
  export default class LFortran extends StaticWorkerRuntimeSandbox {
5
6
  memoryEvidence;
@@ -20,6 +21,15 @@ export default class LFortran extends StaticWorkerRuntimeSandbox {
20
21
  },
21
22
  stdin: { mode: 'streaming', sourceHintPattern: /\bread\b/i },
22
23
  resolveRuntimeAssets: resolveLfortranRuntimeAssetConfig,
24
+ compilerModules() {
25
+ return {
26
+ compiler: {
27
+ receipt: profile.assets['lfortran.wasm'],
28
+ // Defined memories live in fresh instances; the compiler imports the job's bounded memory.
29
+ compileKey: 'lfortran-native-imported-memory-v1'
30
+ }
31
+ };
32
+ },
23
33
  async preflightRuntimeAssets(urls, context) {
24
34
  memoryEvidence.current = undefined;
25
35
  return context.createOwnedDelivery(await preflightLfortranRuntimeAssets(urls.baseUrl, context));
@@ -7,8 +7,8 @@ export declare function resolveLfortranRuntimeAssetConfig(assets: string | Playg
7
7
  workerUrl: string;
8
8
  manifestFingerprint: "11c9baef85c5221440edc4462690312cda62b48998a133b9a397ce32c6a97c45";
9
9
  workerReceipt: {
10
- readonly bytes: 11569;
11
- readonly sha256: "e801cbf4dca7be9fc6fd1205dc4e6ab17af4530f42527dcc8e544eb8373a1469";
10
+ readonly bytes: 13875;
11
+ readonly sha256: "6443226c53cdadbbfdc25d43d1c07c4f13d8855cfe5cfd609f45ca9b29a96cdf";
12
12
  };
13
13
  };
14
14
  export declare function preflightLfortranRuntimeAssets(baseUrl: string, options: {
@@ -14,6 +14,28 @@ class Nim extends StaticWorkerRuntimeSandbox {
14
14
  sourceHintPattern: /\b(?:stdin|readLine|readAll|lines)\b/i
15
15
  },
16
16
  inlineVerifiedWorker: true,
17
+ includeExecutionLimits: true,
18
+ compilerModules(urls) {
19
+ const profile = snapshotNimRuntimePreflightProfile(urls.preflightProfile);
20
+ return Object.fromEntries([
21
+ ['nim', profile.nimWasmReceipt],
22
+ ['clang', profile.clangWasmReceipt],
23
+ ['lld', profile.lldWasmReceipt],
24
+ ['memfs', profile.memfsWasmReceipt]
25
+ ].map(([key, receipt]) => {
26
+ const integrity = receipt;
27
+ return [
28
+ key,
29
+ {
30
+ receipt: {
31
+ bytes: integrity.uncompressedBytes,
32
+ sha256: integrity.uncompressedSha256
33
+ },
34
+ compileKey: 'nim-llvm8-native-v1'
35
+ }
36
+ ];
37
+ }));
38
+ },
17
39
  resolveRuntimeAssets(runtimeAssets, currentUrl) {
18
40
  const resolved = resolveNimRuntimeAssetConfig(runtimeAssets, currentUrl);
19
41
  const profile = snapshotNimRuntimePreflightProfile(resolved.preflightProfile);
@@ -1,4 +1,5 @@
1
1
  import { WorkerAssetBridge } from './assetBridge';
2
+ import type { RuntimeAssetCache } from './runtimeAssetCache';
2
3
  import type { DebugCommand, DebugSessionEvent } from './options';
3
4
  import { type PlaygroundRuntimeAssets } from './assets';
4
5
  import type { SandboxExecutionOptions } from './options';
@@ -24,8 +25,10 @@ declare class ObjectiveC implements Sandbox {
24
25
  exit: boolean;
25
26
  assetBridge: WorkerAssetBridge | null;
26
27
  activeObjectiveCAssetsKey: string;
28
+ private runtimeAssetCache?;
27
29
  private readonly workerSession;
28
30
  constructor(language?: ObjectiveCSandboxLanguage);
31
+ setRuntimeAssetCache(cache: RuntimeAssetCache): void;
29
32
  load(runtimeAssets?: string | PlaygroundRuntimeAssets, code?: string, log?: boolean, args?: string[], options?: SandboxExecutionOptions, progress?: SandboxProgress): Promise<void>;
30
33
  write(input: string): void;
31
34
  eof(): void;
@@ -5,7 +5,7 @@ import { createWasmIdleSharedBuffer, requireSharedArrayBuffer } from './sharedBu
5
5
  import { WorkerSession } from './workerSession';
6
6
  import { reportWorkerInputReady } from './workerProgress';
7
7
  import { bufferedSequence, flushBufferedEof, flushQueuedStdin, resetBufferedStdin, waitForBufferedSequenceChange } from './stdinBuffer';
8
- import { AssetTooLargeError, createRuntimeAssetsKey, resolveExecutionLimits } from '@wasm-idle/core';
8
+ import { AssetTooLargeError, RuntimeConfigurationError, createRuntimeAssetsKey, resolveExecutionLimits } from '@wasm-idle/core';
9
9
  const debugBreakpointBufferInts = 1028;
10
10
  const objectiveCAssetsKey = (assets) => createRuntimeAssetsKey({ objectivec: assets }) || '';
11
11
  class ObjectiveC {
@@ -28,6 +28,7 @@ class ObjectiveC {
28
28
  exit = true;
29
29
  assetBridge = null;
30
30
  activeObjectiveCAssetsKey = '';
31
+ runtimeAssetCache;
31
32
  workerSession = new WorkerSession({
32
33
  label: 'Objective-C',
33
34
  onDispose: (worker) => {
@@ -52,6 +53,14 @@ class ObjectiveC {
52
53
  constructor(language = 'OBJC') {
53
54
  this.language = language;
54
55
  }
56
+ setRuntimeAssetCache(cache) {
57
+ if (this.runtimeAssetCache === cache)
58
+ return;
59
+ if (this.worker) {
60
+ throw new RuntimeConfigurationError('Cannot replace an active Objective-C compiler cache');
61
+ }
62
+ this.runtimeAssetCache = cache;
63
+ }
55
64
  load(runtimeAssets = '', code = '', log = true, args = [], options = {}, progress) {
56
65
  let limits;
57
66
  try {
@@ -93,7 +102,7 @@ class ObjectiveC {
93
102
  if (!this.workerSession.attach(worker, operation))
94
103
  return;
95
104
  this.worker = worker;
96
- this.assetBridge = new WorkerAssetBridge(this.worker, 'clang', clangAssets, progress, limits.maxAssetBytes);
105
+ this.assetBridge = new WorkerAssetBridge(this.worker, 'clang', clangAssets, progress, limits.maxAssetBytes, false, this.runtimeAssetCache);
97
106
  this.activeObjectiveCAssetsKey = nextObjectiveCAssetsKey;
98
107
  this.worker.onmessage = (event) => {
99
108
  if (!this.workerSession.isActive(operation))
@@ -40,6 +40,8 @@ export interface SandboxExecutionOptions {
40
40
  workspaceFiles?: SandboxWorkspaceFile[];
41
41
  compileArgs?: string[];
42
42
  programArgs?: string[];
43
+ /** Requested environment overrides; a runtime may reject unsupported options. */
44
+ env?: Record<string, string>;
43
45
  cppVersion?: string;
44
46
  cVersion?: string;
45
47
  rustTargetTriple?: RustTargetTriple;
@@ -380,6 +380,14 @@ class Python {
380
380
  activePath = options.activePath;
381
381
  debugPath = options.debugPath;
382
382
  workspaceFiles = options.workspaceFiles;
383
+ if (this.workerLanguage === 'python') {
384
+ if (_args.length || options.programArgs?.length) {
385
+ throw new RuntimeConfigurationError('Python does not support program arguments', { runtimeId: this.runtimeId });
386
+ }
387
+ if (options.env !== undefined) {
388
+ throw new RuntimeConfigurationError('Python does not support environment overrides', { runtimeId: this.runtimeId });
389
+ }
390
+ }
383
391
  if (this.usesInterpreterStdio) {
384
392
  limits = resolveExecutionLimits(options.limits);
385
393
  if (_args.length || options.programArgs?.length) {
@@ -1,32 +1 @@
1
- /** Immutable bootstrap assets only: never store a worker, Wasm instance, or user filesystem. */
2
- export declare class RuntimeAssetCache {
3
- private readonly maxBytes;
4
- private readonly maxEntries;
5
- private entries;
6
- private inFlight;
7
- private inFlightKeyBytes;
8
- private identities;
9
- private nextIdentity;
10
- private bytes;
11
- private hits;
12
- private misses;
13
- private disposed;
14
- constructor(maxBytes?: number, maxEntries?: number);
15
- /** Identity is owner-local; a custom loader must never alias another loader. */
16
- identity(value: object | undefined): number;
17
- get<T>(key: string): T | undefined;
18
- /** Only the trusted host publishes fully verified results; failures are never retained. */
19
- set<T>(key: string, value: T, bytes: number): void;
20
- /** Share work, but give every consumer its own cancellation and progress subscription. */
21
- share<T, Progress = never>(key: string, signal: AbortSignal, start: (signal: AbortSignal, report: (progress: Progress, progressKey?: string) => void) => Promise<T>, onProgress?: (progress: Progress) => void): Promise<T>;
22
- private removeOperation;
23
- stats(): {
24
- hits: number;
25
- misses: number;
26
- entries: number;
27
- bytes: number;
28
- inFlight: number;
29
- disposed: boolean;
30
- };
31
- dispose(): void;
32
- }
1
+ export { RuntimeAssetCache } from '@wasm-idle/core';