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
@@ -46,7 +46,7 @@ export const WASM_TINYGO_EXECUTABLE_GRAPH_PROFILE = Object.freeze({
46
46
  schemaVersion: 1,
47
47
  format: WASM_TINYGO_EXECUTABLE_GRAPH_FORMAT,
48
48
  entryPath: 'upstream.js',
49
- fingerprint: '8ecbffd4b4e44ff67288d8c46328a1b06d0a0ac76d7a50a9e458603b68d0d795',
49
+ fingerprint: '8b2e87ec50b586591903adcff8c547b37c3b23d4e12f97d8266035cefdeebac4',
50
50
  modules: Object.freeze({
51
51
  'assets/upstream-binaryen-59aad93503b5fd53.wasm.gz.bin': Object.freeze({
52
52
  bytes: 2366782,
@@ -55,14 +55,9 @@ export const WASM_TINYGO_EXECUTABLE_GRAPH_PROFILE = Object.freeze({
55
55
  uncompressedSha256: '59aad93503b5fd539993f2f5571c11dce9ddb4c5d10b681abc8e5dc124aed526',
56
56
  imports: Object.freeze([])
57
57
  }),
58
- 'assets/upstream-compile-worker-CFw6Ych6.js': Object.freeze({
59
- bytes: 558,
60
- sha256: '03a76345c69f8bd751dac18894f65c0918f1690fbbb661f38052819cd5ae8209',
61
- imports: Object.freeze([])
62
- }),
63
- 'assets/upstream-compile-worker-CUrboB1_.js': Object.freeze({
64
- bytes: 103559,
65
- sha256: '42337c2f06d04b51d79f0ec66ae685f0cfb2a78718b0636df980dc92dd1db9d5',
58
+ 'assets/upstream-compile-worker-6CYe8gHb.js': Object.freeze({
59
+ bytes: 105574,
60
+ sha256: '30c6b0d3f0968222e0d78f7ec54300838eca0326558e448bc48ab213e35aae2f',
66
61
  imports: Object.freeze([
67
62
  Object.freeze({
68
63
  specifier: './upstream-compile-worker-CeYS3ydo.js',
@@ -71,6 +66,11 @@ export const WASM_TINYGO_EXECUTABLE_GRAPH_PROFILE = Object.freeze({
71
66
  })
72
67
  ])
73
68
  }),
69
+ 'assets/upstream-compile-worker-CFw6Ych6.js': Object.freeze({
70
+ bytes: 558,
71
+ sha256: '03a76345c69f8bd751dac18894f65c0918f1690fbbb661f38052819cd5ae8209',
72
+ imports: Object.freeze([])
73
+ }),
74
74
  'assets/upstream-compile-worker-CeYS3ydo.js': Object.freeze({
75
75
  bytes: 181175,
76
76
  sha256: 'faa2bf6a310cd23991babde1fb62cd34253d692fee03029fe3508eae4c24b1c0',
@@ -104,16 +104,16 @@ export const WASM_TINYGO_EXECUTABLE_GRAPH_PROFILE = Object.freeze({
104
104
  ])
105
105
  }),
106
106
  'upstream.js': Object.freeze({
107
- bytes: 126073,
108
- sha256: '136a957aa940c3e2b8c7a925eb538f3fce81f699aa9113e1fd93ce0b35c879aa',
107
+ bytes: 126235,
108
+ sha256: 'b780e6d7492c60f9c7481eda0b3ef45be15887ee367b8728532e824a4592e3b1',
109
109
  imports: Object.freeze([
110
110
  Object.freeze({
111
- specifier: 'assets/upstream-compile-worker-CUrboB1_.js',
112
- target: 'assets/upstream-compile-worker-CUrboB1_.js',
111
+ specifier: 'assets/upstream-compile-worker-6CYe8gHb.js',
112
+ target: 'assets/upstream-compile-worker-6CYe8gHb.js',
113
113
  kind: 'worker'
114
114
  })
115
115
  ])
116
116
  })
117
117
  })
118
118
  });
119
- export const WASM_TINYGO_ASSET_VERSION = '0b2e827ae219eecc806d4118ee4a2b6032adbe7a960e6c0e471c4491d9a1f2f3';
119
+ export const WASM_TINYGO_ASSET_VERSION = '43cb86856c8d017a66529bbed945b564b3c6a8d6a59bf3e98afb47d1ac25f8f2';
@@ -1,9 +1,9 @@
1
- export declare const WASM_TYPESCRIPT_ASSET_VERSION = "2d968f66f878ce33";
1
+ export declare const WASM_TYPESCRIPT_ASSET_VERSION = "e48868a1d3851320";
2
2
  export declare const WASM_TYPESCRIPT_MODULE_RECEIPT: Readonly<{
3
- bytes: 3759064;
4
- sha256: "2c8942b6383d25d4582e9db0ee38d85b61eb8016f16e57c840f3c20af9ac848b";
3
+ bytes: 3882154;
4
+ sha256: "df071064e3d1e8ce1c5bae87853db00021681d069b3ef046a884b95fa58eadfe";
5
5
  }>;
6
6
  export declare const WASM_JAVASCRIPT_MODULE_RECEIPT: Readonly<{
7
- bytes: 35866;
8
- sha256: "21b176cfe1ce4d39519979422bd1b3b598f183e9b3fe042ecc8cc37a535c3608";
7
+ bytes: 158899;
8
+ sha256: "9e2df469ef3934424fba004bb66b5a3b042ecaf1ad3496789ac8fe8e67389d65";
9
9
  }>;
@@ -1,9 +1,9 @@
1
- export const WASM_TYPESCRIPT_ASSET_VERSION = '2d968f66f878ce33';
1
+ export const WASM_TYPESCRIPT_ASSET_VERSION = 'e48868a1d3851320';
2
2
  export const WASM_TYPESCRIPT_MODULE_RECEIPT = Object.freeze({
3
- bytes: 3759064,
4
- sha256: '2c8942b6383d25d4582e9db0ee38d85b61eb8016f16e57c840f3c20af9ac848b'
3
+ bytes: 3882154,
4
+ sha256: 'df071064e3d1e8ce1c5bae87853db00021681d069b3ef046a884b95fa58eadfe'
5
5
  });
6
6
  export const WASM_JAVASCRIPT_MODULE_RECEIPT = Object.freeze({
7
- bytes: 35866,
8
- sha256: '21b176cfe1ce4d39519979422bd1b3b598f183e9b3fe042ecc8cc37a535c3608'
7
+ bytes: 158899,
8
+ sha256: '9e2df469ef3934424fba004bb66b5a3b042ecaf1ad3496789ac8fe8e67389d65'
9
9
  });
@@ -1,7 +1,8 @@
1
- import { BrowserClangRuntime, loadRuntimeManifest, resolveRuntimeManifestUrl } from '@wasm-idle/llvm-core/clang';
1
+ import { BrowserClangRuntime, loadRuntimeManifest, extractCompilerDiagnostics, resolveRuntimeManifestUrl } from '@wasm-idle/llvm-core/clang';
2
2
  import { configureWorkerRuntimeAssets, handleWorkerAssetMessage } from './assets';
3
3
  import { compileWorkerRuntimeAsset } from './runtimeModule';
4
4
  import { BUNDLED_CLANG_ASSET_INTEGRITY, BUNDLED_CLANG_LANGUAGE_SYSROOT_PROFILES } from '../clangAssetIntegrity';
5
+ import { OutputLimitError, resolveExecutionLimits } from '@wasm-idle/core';
5
6
  const worker = globalThis;
6
7
  let started = false;
7
8
  worker.onmessage = async ({ data }) => {
@@ -11,8 +12,36 @@ worker.onmessage = async ({ data }) => {
11
12
  return;
12
13
  started = true;
13
14
  const output = [];
15
+ const encoder = new TextEncoder();
16
+ let outputBytes = 0;
17
+ let outputLimitError;
18
+ const controller = new AbortController();
14
19
  let runtime;
15
20
  try {
21
+ const maxOutputBytes = resolveExecutionLimits(data.maxOutputBytes === undefined ? {} : { maxOutputBytes: data.maxOutputBytes }).maxOutputBytes;
22
+ const checkOutputBytes = (additionalBytes) => {
23
+ if (outputLimitError)
24
+ throw outputLimitError;
25
+ const actual = outputBytes + additionalBytes;
26
+ if (actual <= maxOutputBytes)
27
+ return;
28
+ outputLimitError = new OutputLimitError(`Compiler output exceeded ${maxOutputBytes} bytes`, { limit: maxOutputBytes, actual, phase: 'compile' });
29
+ const stdout = output.join('');
30
+ // Report before retaining a chunk, including temporarily buffered PCH diagnostics.
31
+ worker.postMessage({
32
+ type: 'error',
33
+ error: outputLimitError.message,
34
+ code: 'output-limit',
35
+ limit: maxOutputBytes,
36
+ actual,
37
+ stdout,
38
+ diagnostics: extractCompilerDiagnostics(stdout),
39
+ stderr: ''
40
+ });
41
+ // A header builder can recover close-time stream errors; prevent its cache write too.
42
+ controller.abort(outputLimitError);
43
+ throw outputLimitError;
44
+ };
16
45
  if (data.request.debug || (data.request.debugMode && data.request.debugMode !== 'none')) {
17
46
  throw new Error('Cached C/C++ execution does not support debug artifacts.');
18
47
  }
@@ -53,8 +82,16 @@ worker.onmessage = async ({ data }) => {
53
82
  maxAssetBytes: data.maxAssetBytes,
54
83
  manifest,
55
84
  persistentCache: data.persistentCache,
85
+ signal: controller.signal,
56
86
  log: data.log ?? false,
57
- stdout: (chunk) => output.push(chunk),
87
+ stdout: (chunk) => {
88
+ if (!chunk)
89
+ return;
90
+ const bytes = encoder.encode(chunk).byteLength;
91
+ checkOutputBytes(bytes);
92
+ outputBytes += bytes;
93
+ output.push(chunk);
94
+ },
58
95
  progress: (value) => worker.postMessage({
59
96
  type: 'progress',
60
97
  progress: {
@@ -79,9 +116,12 @@ worker.onmessage = async ({ data }) => {
79
116
  });
80
117
  const artifact = await runtime.compileArtifact(data.request.code, {
81
118
  ...data.request,
119
+ onBufferedOutput: checkOutputBytes,
82
120
  persistentCache: data.persistentCache,
83
121
  precompiledHeader: data.precompiledHeader
84
122
  });
123
+ if (outputLimitError)
124
+ return;
85
125
  if (runtime.usedPrecompiledHeader)
86
126
  worker.postMessage({
87
127
  type: 'progress',
@@ -93,19 +133,25 @@ worker.onmessage = async ({ data }) => {
93
133
  message: 'Compiled with precompiled <bits/stdc++.h>'
94
134
  }
95
135
  });
136
+ const stdout = output.join('');
96
137
  worker.postMessage({
97
138
  type: 'compiled',
98
139
  artifact,
99
- stdout: output.join(''),
140
+ stdout,
141
+ diagnostics: extractCompilerDiagnostics(stdout),
100
142
  stderr: '',
101
143
  ...buildingPrecompiledHeader(runtime)
102
144
  });
103
145
  }
104
146
  catch (error) {
147
+ if (outputLimitError)
148
+ return;
149
+ const stdout = output.join('');
105
150
  worker.postMessage({
106
151
  type: 'error',
107
152
  error: error instanceof Error ? error.message : String(error),
108
- stdout: output.join(''),
153
+ stdout,
154
+ diagnostics: extractCompilerDiagnostics(stdout),
109
155
  stderr: '',
110
156
  ...buildingPrecompiledHeader(runtime)
111
157
  });
@@ -114,6 +160,8 @@ worker.onmessage = async ({ data }) => {
114
160
  // headers, prepares <bits/stdc++.h> for the next compile.
115
161
  if (runtime && buildingPrecompiledHeader(runtime).precompiledHeader) {
116
162
  const header = await runtime.buildPrecompiledHeader().catch(() => undefined);
163
+ if (outputLimitError)
164
+ return;
117
165
  worker.postMessage({ type: 'precompiled-header', header }, header ? [header.bytes.buffer] : []);
118
166
  }
119
167
  };
@@ -13,19 +13,20 @@ worker.onmessage = async ({ data }) => {
13
13
  : new Uint8Array(data.inputBuffer, CLANG_STDIN_HEADER_BYTES);
14
14
  if (payload && payload.byteLength === 0)
15
15
  throw new Error('C/C++ stdin buffer is empty.');
16
- const files = (data.workspaceFiles || []).map(({ path, content }) => ({
17
- path,
18
- contents: content
19
- }));
16
+ const activePath = data.activePath || (data.artifact.language === 'C' ? 'main.c' : 'main.cc');
17
+ const files = (data.workspaceFiles || [])
18
+ .filter(({ path }) => data.code === undefined || path !== activePath)
19
+ .map(({ path, content }) => ({ path, contents: content }));
20
20
  if (data.code !== undefined) {
21
21
  files.push({
22
- path: data.activePath || (data.artifact.language === 'C' ? 'main.c' : 'main.cc'),
22
+ path: activePath,
23
23
  contents: data.code
24
24
  });
25
25
  }
26
26
  // The public executor creates a fresh WASI host, files, descriptors and Wasm
27
27
  // instance. Only the immutable compiled Module is reused across executions.
28
28
  const result = await executeBrowserClangArtifact(data.artifact, {
29
+ maxWasmMemoryBytes: data.maxWasmMemoryBytes,
29
30
  args: data.programArgs,
30
31
  env: data.env,
31
32
  files,
@@ -19,6 +19,25 @@ function missingPrecompiledHeader() {
19
19
  function postProgress(percent, stage) {
20
20
  postMessage({ progress: { percent, stage } });
21
21
  }
22
+ function normalizeLldbWorkspaceFiles(files) {
23
+ // Both compiler phases and LLDB accept text; retain BOMs and original FS bytes.
24
+ const decoder = new TextDecoder('utf-8', { fatal: true, ignoreBOM: true });
25
+ return files.map((file) => {
26
+ let content = file.content;
27
+ if (typeof content !== 'string') {
28
+ const path = `/workspace/${normalizeDwarfWorkspacePath(file.path)}`;
29
+ if (!(content instanceof Uint8Array))
30
+ throw new TypeError(`LLDB workspace file content must be a string or Uint8Array: ${path}`);
31
+ try {
32
+ content = decoder.decode(content);
33
+ }
34
+ catch (cause) {
35
+ throw new Error(`LLDB workspace file is not valid UTF-8: ${path}`, { cause });
36
+ }
37
+ }
38
+ return { ...file, content };
39
+ });
40
+ }
22
41
  async function loadClang(path, log, maxAssetBytes, verifiedStreaming = false, languageSysrootProfiles = false, persistentCache) {
23
42
  const { BrowserClangRuntime, loadRuntimeManifest, resolveRuntimeManifestUrl } = await import('@wasm-idle/llvm-core/clang');
24
43
  const manifest = await loadRuntimeManifest(resolveRuntimeManifestUrl(path), fetch, undefined, maxAssetBytes);
@@ -106,7 +125,9 @@ self.onmessage = async (event) => {
106
125
  compileArgs,
107
126
  programArgs,
108
127
  activePath,
109
- workspaceFiles,
128
+ workspaceFiles: resolvedDebugMode === 'lldb'
129
+ ? normalizeLldbWorkspaceFiles(workspaceFiles || [])
130
+ : workspaceFiles,
110
131
  cppVersion,
111
132
  cVersion,
112
133
  debugMode: resolvedDebugMode,
@@ -143,12 +164,21 @@ self.onmessage = async (event) => {
143
164
  }
144
165
  try {
145
166
  if (resolvedDebugMode === 'lldb') {
167
+ const inputPath = normalizeDwarfWorkspacePath(activePath || (language === 'C' ? 'main.c' : 'main.cc')) || (language === 'C' ? 'main.c' : 'main.cc');
168
+ const sources = new Map();
169
+ const compilerWorkspaceFiles = normalizeLldbWorkspaceFiles(workspaceFiles || []);
170
+ for (const file of compilerWorkspaceFiles) {
171
+ const sourcePath = normalizeDwarfWorkspacePath(file.path);
172
+ if (sourcePath)
173
+ sources.set(`/workspace/${sourcePath}`, file.content);
174
+ }
175
+ sources.set(`/workspace/${inputPath}`, code);
146
176
  const artifact = await clang.compileArtifact(code, {
147
177
  language,
148
178
  compileArgs,
149
179
  programArgs,
150
180
  activePath,
151
- workspaceFiles,
181
+ workspaceFiles: compilerWorkspaceFiles,
152
182
  cppVersion,
153
183
  cVersion,
154
184
  debugMode: 'lldb',
@@ -158,14 +188,6 @@ self.onmessage = async (event) => {
158
188
  if (!artifact.debug) {
159
189
  throw new Error('wasm-clang did not return an LLDB DWARF descriptor');
160
190
  }
161
- const inputPath = normalizeDwarfWorkspacePath(activePath || (language === 'C' ? 'main.c' : 'main.cc')) || (language === 'C' ? 'main.c' : 'main.cc');
162
- const sources = new Map();
163
- for (const file of workspaceFiles || []) {
164
- const sourcePath = normalizeDwarfWorkspacePath(file.path);
165
- if (sourcePath)
166
- sources.set(`/workspace/${sourcePath}`, file.content);
167
- }
168
- sources.set(`/workspace/${inputPath}`, code);
169
191
  self.postMessage({
170
192
  lldbArtifact: {
171
193
  bytes: new Uint8Array(artifact.bytes),
@@ -51,7 +51,7 @@ self.onmessage = async (event) => {
51
51
  postMessage({ load: true });
52
52
  }
53
53
  catch (error) {
54
- postMessage({ error: error.message });
54
+ postMessage({ error: error?.message || String(error) });
55
55
  }
56
56
  }
57
57
  else if (typeof log === 'boolean' && !code) {
@@ -101,7 +101,7 @@ self.onmessage = async (event) => {
101
101
  postMessage({ results: true });
102
102
  }
103
103
  catch (error) {
104
- postMessage({ error: error.message });
104
+ postMessage({ error: error?.message || String(error) });
105
105
  }
106
106
  }
107
107
  };
@@ -1,12 +1,13 @@
1
1
  import { waitForBufferedStdin } from '../stdinBuffer';
2
2
  import { loadVerifiedDOuterAssets, snapshotDOuterAssetConfig } from '../dOuterAssets';
3
- import { createRuntimeAssetsKey, verifyRuntimeAssetIntegrity } from '@wasm-idle/core';
3
+ import { createRuntimeAssetsKey, requestRuntimeWasmModule, verifyRuntimeAssetIntegrity } from '@wasm-idle/core';
4
4
  let stdinBufferD = null;
5
5
  let runtimeConfig = null;
6
6
  let loadedRuntimeKey = '';
7
7
  let runtimePromise = null;
8
8
  let compiledArtifact = null;
9
9
  let compiledCacheKey = '';
10
+ let compilerModulePorts;
10
11
  async function loadRuntime(config) {
11
12
  const snapshot = snapshotDOuterAssetConfig(config);
12
13
  const runtimeKey = createRuntimeAssetsKey({ d: snapshot });
@@ -56,7 +57,13 @@ async function loadRuntime(config) {
56
57
  compiler: await factory({
57
58
  runtimeBaseUrl: runtimeBaseUrl.href,
58
59
  manifest,
59
- verifyRuntimeAssetIntegrity
60
+ verifyRuntimeAssetIntegrity,
61
+ compileModule(kind, bytes, signal) {
62
+ const port = compilerModulePorts?.[kind];
63
+ return port
64
+ ? requestRuntimeWasmModule(Uint8Array.from(bytes), port, { signal })
65
+ : WebAssembly.compile(Uint8Array.from(bytes).buffer);
66
+ }
60
67
  }),
61
68
  executeBrowserDArtifact: module.executeBrowserDArtifact
62
69
  };
@@ -102,6 +109,7 @@ self.onmessage = async (event) => {
102
109
  return;
103
110
  }
104
111
  stdinBufferD = new Int32Array(buffer);
112
+ compilerModulePorts = event.data.compilerModulePorts;
105
113
  if (!runtimeConfig)
106
114
  throw new Error('D runtime has not been loaded');
107
115
  const runtime = await loadRuntime(runtimeConfig);
@@ -185,9 +193,8 @@ self.onmessage = async (event) => {
185
193
  }
186
194
  });
187
195
  if (execution.exitCode !== 0) {
188
- throw new Error(execution.stderr
189
- ? `D program exited with code ${execution.exitCode}\n${execution.stderr}`
190
- : `D program exited with code ${execution.exitCode}`);
196
+ // stderr was already streamed to the terminal above.
197
+ throw new Error(`D program exited with code ${execution.exitCode}`);
191
198
  }
192
199
  postMessage({ results: true });
193
200
  }
@@ -250,7 +250,7 @@ self.onmessage = async (event) => {
250
250
  postMessage({ load: true });
251
251
  }
252
252
  catch (error) {
253
- postMessage({ error: error.message });
253
+ postMessage({ error: error?.message || String(error) });
254
254
  }
255
255
  }
256
256
  else if (typeof log === 'boolean' && !code) {
@@ -286,7 +286,7 @@ self.onmessage = async (event) => {
286
286
  postMessage({ results: true });
287
287
  }
288
288
  catch (error) {
289
- postMessage({ error: error.message });
289
+ postMessage({ error: error?.message || String(error) });
290
290
  }
291
291
  }
292
292
  };
@@ -210,6 +210,7 @@ function createGoDebugHost(options) {
210
210
  }
211
211
  self.onmessage = async (event) => {
212
212
  const { load, compilerUrl: nextCompilerUrl, manifestUrl: nextManifestUrl, runtimeLimits, buffer, debugBuffer, code, prepare, args = [], stdin, target = 'wasip1/wasm', log, debug = false, breakpoints = [], pauseOnEntry = false } = event.data;
213
+ let abandonedJsWasmRun = false;
213
214
  try {
214
215
  if (load) {
215
216
  compilerUrl = nextCompilerUrl;
@@ -344,8 +345,16 @@ self.onmessage = async (event) => {
344
345
  }
345
346
  });
346
347
  }
348
+ catch (error) {
349
+ // wasm_exec.js runs js/wasm programs on this worker's event loop, so a rejected
350
+ // run (such as an expired runtime deadline) may still be running here.
351
+ abandonedJsWasmRun = effectiveTarget === 'js/wasm';
352
+ throw error;
353
+ }
347
354
  finally {
348
- restoreGoDebugHost?.();
355
+ // The abandoned program may still call the hook until the host discards this worker.
356
+ if (!abandonedJsWasmRun)
357
+ restoreGoDebugHost?.();
349
358
  }
350
359
  if (log) {
351
360
  console.log(`[wasm-idle:go-worker] wasi run complete exitCode=${String(execution?.exitCode)}`);
@@ -354,9 +363,8 @@ self.onmessage = async (event) => {
354
363
  throw new Error('Go program did not return an execution result');
355
364
  }
356
365
  if (execution.exitCode !== 0) {
357
- throw new Error(execution.stderr
358
- ? `Go program exited with code ${execution.exitCode}\n${execution.stderr}`
359
- : `Go program exited with code ${execution.exitCode}`);
366
+ // stderr was already streamed to the terminal above.
367
+ throw new Error(`Go program exited with code ${execution.exitCode}`);
360
368
  }
361
369
  postMessage({ results: true });
362
370
  }
@@ -364,6 +372,9 @@ self.onmessage = async (event) => {
364
372
  if (log) {
365
373
  console.error('[wasm-idle:go-worker] failed', error);
366
374
  }
367
- postMessage({ error: error?.message || String(error) });
375
+ postMessage({
376
+ error: error?.message || String(error),
377
+ ...(abandonedJsWasmRun ? { fatal: true } : {})
378
+ });
368
379
  }
369
380
  };
@@ -99,7 +99,7 @@ function outputLine(line) {
99
99
  postMessage({ output: line.endsWith('\n') ? line : `${line}\n` });
100
100
  }
101
101
  function remapDiagnosticPath(line) {
102
- const match = /^(.*?)(:\d+:\d+:\s+(?:error|warning):)/i.exec(line);
102
+ const match = /^(.*?)(:(?:\d+:\d+(?:-\d+)?|\(\d+,\d+\)-\(\d+,\d+\)):\s+(?:error|warning):)/i.exec(line);
103
103
  if (!match)
104
104
  return line;
105
105
  const workspacePath = activeDiagnosticPaths?.get(match[1]);
@@ -264,10 +264,12 @@ export function parseHaskellDiagnostics(output) {
264
264
  const diagnostics = [];
265
265
  const lines = output.split(/\r\n|\r|\n/);
266
266
  for (let index = 0; index < lines.length; index += 1) {
267
- const match = /^(.*?):(\d+):(\d+):\s+(error|warning):\s*(.*)$/i.exec(lines[index]);
267
+ // GHC locations are `l:c`, `l:c-c`, or `(l,c)-(l,c)`.
268
+ const match = /^(.*?):(?:(\d+):(\d+)(?:-\d+)?|\((\d+),(\d+)\)-\(\d+,\d+\)):\s+(error|warning):\s*(.*)$/i.exec(lines[index]);
268
269
  if (!match)
269
270
  continue;
270
- let message = match[5].trim();
271
+ // GHC 9.6+ prefixes the message with tags such as `[GHC-88464] [-Wunused-top-binds]`.
272
+ let message = match[7].replace(/^(?:\[(?:GHC-\d+|-W[^\]]*)\]\s*)*/, '').trim();
271
273
  if (!message) {
272
274
  for (const extraLine of lines.slice(index + 1)) {
273
275
  const trimmed = extraLine.trim();
@@ -279,9 +281,9 @@ export function parseHaskellDiagnostics(output) {
279
281
  }
280
282
  diagnostics.push({
281
283
  fileName: match[1] || null,
282
- lineNumber: Math.max(1, Number(match[2] || 1)),
283
- columnNumber: Math.max(1, Number(match[3] || 1)),
284
- severity: match[4].toLowerCase() === 'warning' ? 'warning' : 'error',
284
+ lineNumber: Math.max(1, Number(match[2] || match[4] || 1)),
285
+ columnNumber: Math.max(1, Number(match[3] || match[5] || 1)),
286
+ severity: match[6].toLowerCase() === 'warning' ? 'warning' : 'error',
285
287
  message: message || lines[index]
286
288
  });
287
289
  }
@@ -447,7 +449,8 @@ self.onmessage = async (event) => {
447
449
  for (const diagnostic of parseHaskellDiagnostics(stderrText)) {
448
450
  postMessage({ diagnostic });
449
451
  }
450
- throw new Error(stderrText.trim() || formatError(error), { cause: error });
452
+ // The host stderr callback already streamed stderrText to the terminal.
453
+ throw new Error(formatError(error), { cause: error });
451
454
  }
452
455
  finally {
453
456
  activeStderrCollector = null;