@scriptc/compiler 0.1.1 → 0.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 (209) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +45 -17
  2. package/ambient/scriptc.d.ts +2 -1
  3. package/dist/backend/build-cache.js.map +1 -1
  4. package/dist/backend/c/async.js +24 -2
  5. package/dist/backend/c/async.js.map +1 -1
  6. package/dist/backend/c/c-emitter.d.ts +22 -10
  7. package/dist/backend/c/c-emitter.js +60 -15
  8. package/dist/backend/c/c-emitter.js.map +1 -1
  9. package/dist/backend/c/exprs.js +220 -10
  10. package/dist/backend/c/exprs.js.map +1 -1
  11. package/dist/backend/c/island.js.map +1 -1
  12. package/dist/backend/c/may-throw.js.map +1 -1
  13. package/dist/backend/c/stmts.d.ts +3 -5
  14. package/dist/backend/c/stmts.js +58 -17
  15. package/dist/backend/c/stmts.js.map +1 -1
  16. package/dist/backend/c/types.js.map +1 -1
  17. package/dist/backend/c/walkers.js +31 -5
  18. package/dist/backend/c/walkers.js.map +1 -1
  19. package/dist/backend/external-c.js.map +1 -1
  20. package/dist/backend/linker.js.map +1 -1
  21. package/dist/backend/llvm/blocks.js.map +1 -1
  22. package/dist/backend/llvm/dyn.js +56 -3
  23. package/dist/backend/llvm/dyn.js.map +1 -1
  24. package/dist/backend/llvm/emitter.js +98 -19
  25. package/dist/backend/llvm/emitter.js.map +1 -1
  26. package/dist/backend/llvm/expr-async.js +85 -3
  27. package/dist/backend/llvm/expr-async.js.map +1 -1
  28. package/dist/backend/llvm/expr-bytes.js.map +1 -1
  29. package/dist/backend/llvm/expr-calls.js.map +1 -1
  30. package/dist/backend/llvm/expr-containers.js.map +1 -1
  31. package/dist/backend/llvm/expr-context.d.ts +1 -0
  32. package/dist/backend/llvm/expr-control.js.map +1 -1
  33. package/dist/backend/llvm/expr-dispatch.js.map +1 -1
  34. package/dist/backend/llvm/expr-dynamic.js +6 -3
  35. package/dist/backend/llvm/expr-dynamic.js.map +1 -1
  36. package/dist/backend/llvm/expr-island.js.map +1 -1
  37. package/dist/backend/llvm/expr-primitives.js.map +1 -1
  38. package/dist/backend/llvm/expr-records.js.map +1 -1
  39. package/dist/backend/llvm/expr-stream-bridges.js +220 -9
  40. package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
  41. package/dist/backend/llvm/lib-dispatch.js +2 -0
  42. package/dist/backend/llvm/lib-dispatch.js.map +1 -1
  43. package/dist/backend/llvm/lib-shared.js +18 -0
  44. package/dist/backend/llvm/lib-shared.js.map +1 -1
  45. package/dist/backend/llvm/lib-stream.js +6 -3
  46. package/dist/backend/llvm/lib-stream.js.map +1 -1
  47. package/dist/backend/llvm/split.js.map +1 -1
  48. package/dist/backend/llvm/unsupported.js.map +1 -1
  49. package/dist/backend/llvm/walkers.js.map +1 -1
  50. package/dist/backend/native-codegen.js.map +1 -1
  51. package/dist/backend/native-codegen.test.js +2 -0
  52. package/dist/backend/native-codegen.test.js.map +1 -1
  53. package/dist/backend/native-toolchain.js.map +1 -1
  54. package/dist/backend/native-toolchain.test.js.map +1 -1
  55. package/dist/backend/runtime-pack.js.map +1 -1
  56. package/dist/backend/targets.js.map +1 -1
  57. package/dist/backend/vendor-archives.js.map +1 -1
  58. package/dist/compat/fetch-profile.js +4 -2
  59. package/dist/compat/fetch-profile.js.map +1 -1
  60. package/dist/coverage/report.js.map +1 -1
  61. package/dist/coverage/surface-manifest.js +12 -0
  62. package/dist/coverage/surface-manifest.js.map +1 -1
  63. package/dist/diagnostics/diagnostic.d.ts +6 -5
  64. package/dist/diagnostics/diagnostic.js +7 -6
  65. package/dist/diagnostics/diagnostic.js.map +1 -1
  66. package/dist/diagnostics/render.js.map +1 -1
  67. package/dist/ffi/ffi-manifest.js.map +1 -1
  68. package/dist/frontend/cjs-lexer.js.map +1 -1
  69. package/dist/frontend/dts-paths.js.map +1 -1
  70. package/dist/frontend/input-tracker.d.ts +10 -0
  71. package/dist/frontend/input-tracker.js +26 -3
  72. package/dist/frontend/input-tracker.js.map +1 -1
  73. package/dist/frontend/input-tracker.test.js +8 -1
  74. package/dist/frontend/input-tracker.test.js.map +1 -1
  75. package/dist/frontend/lib-contract.js.map +1 -1
  76. package/dist/frontend/lowering/array-values.d.ts +4 -0
  77. package/dist/frontend/lowering/array-values.js +18 -2
  78. package/dist/frontend/lowering/array-values.js.map +1 -1
  79. package/dist/frontend/lowering/callback-arg.js.map +1 -1
  80. package/dist/frontend/lowering/containers/bytes.d.ts +35 -0
  81. package/dist/frontend/lowering/containers/bytes.js +1021 -0
  82. package/dist/frontend/lowering/containers/bytes.js.map +1 -0
  83. package/dist/frontend/lowering/containers/string-and-regexp.d.ts +17 -0
  84. package/dist/frontend/lowering/containers/string-and-regexp.js +345 -0
  85. package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -0
  86. package/dist/frontend/lowering/expressions/evaluation-safety.d.ts +13 -0
  87. package/dist/frontend/lowering/expressions/evaluation-safety.js +76 -0
  88. package/dist/frontend/lowering/expressions/evaluation-safety.js.map +1 -0
  89. package/dist/frontend/lowering/expressions/object-literals.d.ts +44 -0
  90. package/dist/frontend/lowering/expressions/object-literals.js +1815 -0
  91. package/dist/frontend/lowering/expressions/object-literals.js.map +1 -0
  92. package/dist/frontend/lowering/expressions/optional-chains.d.ts +31 -0
  93. package/dist/frontend/lowering/expressions/optional-chains.js +382 -0
  94. package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -0
  95. package/dist/frontend/lowering/expressions/try-lower-expression.d.ts +7 -0
  96. package/dist/frontend/lowering/expressions/try-lower-expression.js +26 -0
  97. package/dist/frontend/lowering/expressions/try-lower-expression.js.map +1 -0
  98. package/dist/frontend/lowering/lib-boundary.js +7 -2
  99. package/dist/frontend/lowering/lib-boundary.js.map +1 -1
  100. package/dist/frontend/lowering/lower-assert.js.map +1 -1
  101. package/dist/frontend/lowering/lower-async-iteration.d.ts +7 -0
  102. package/dist/frontend/lowering/lower-async-iteration.js +657 -0
  103. package/dist/frontend/lowering/lower-async-iteration.js.map +1 -0
  104. package/dist/frontend/lowering/lower-builtins.d.ts +18 -0
  105. package/dist/frontend/lowering/lower-builtins.js +219 -48
  106. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  107. package/dist/frontend/lowering/lower-calls.d.ts +13 -4
  108. package/dist/frontend/lowering/lower-calls.js +407 -64
  109. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  110. package/dist/frontend/lowering/lower-classes.d.ts +7 -13
  111. package/dist/frontend/lowering/lower-classes.js +128 -35
  112. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  113. package/dist/frontend/lowering/lower-comptime.js.map +1 -1
  114. package/dist/frontend/lowering/lower-containers.d.ts +1 -47
  115. package/dist/frontend/lowering/lower-containers.js +135 -1467
  116. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  117. package/dist/frontend/lowering/lower-event-emitter.js +51 -5
  118. package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
  119. package/dist/frontend/lowering/lower-exprs.d.ts +0 -78
  120. package/dist/frontend/lowering/lower-exprs.js +402 -2351
  121. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  122. package/dist/frontend/lowering/lower-generators.d.ts +18 -3
  123. package/dist/frontend/lowering/lower-generators.js +145 -9
  124. package/dist/frontend/lowering/lower-generators.js.map +1 -1
  125. package/dist/frontend/lowering/lower-inspect.js +3 -3
  126. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  127. package/dist/frontend/lowering/lower-island.d.ts +6 -0
  128. package/dist/frontend/lowering/lower-island.js +37 -5
  129. package/dist/frontend/lowering/lower-island.js.map +1 -1
  130. package/dist/frontend/lowering/lower-modules.js +52 -15
  131. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  132. package/dist/frontend/lowering/lower-node-module.d.ts +18 -0
  133. package/dist/frontend/lowering/lower-node-module.js +302 -0
  134. package/dist/frontend/lowering/lower-node-module.js.map +1 -0
  135. package/dist/frontend/lowering/lower-server.js +1 -1
  136. package/dist/frontend/lowering/lower-server.js.map +1 -1
  137. package/dist/frontend/lowering/lower-stmts.d.ts +5 -24
  138. package/dist/frontend/lowering/lower-stmts.js +519 -253
  139. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  140. package/dist/frontend/lowering/lower-stream.js +4 -4
  141. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  142. package/dist/frontend/lowering/lowerer.d.ts +37 -34
  143. package/dist/frontend/lowering/lowerer.js +143 -57
  144. package/dist/frontend/lowering/lowerer.js.map +1 -1
  145. package/dist/frontend/lowering/optional-arguments.d.ts +9 -0
  146. package/dist/frontend/lowering/optional-arguments.js +57 -0
  147. package/dist/frontend/lowering/optional-arguments.js.map +1 -0
  148. package/dist/frontend/npm-static-declarations.d.ts +35 -0
  149. package/dist/frontend/npm-static-declarations.js +506 -0
  150. package/dist/frontend/npm-static-declarations.js.map +1 -0
  151. package/dist/frontend/npm-static-declarations.test.d.ts +1 -0
  152. package/dist/frontend/npm-static-declarations.test.js +122 -0
  153. package/dist/frontend/npm-static-declarations.test.js.map +1 -0
  154. package/dist/frontend/npm-static.d.ts +2 -0
  155. package/dist/frontend/npm-static.js +26 -10
  156. package/dist/frontend/npm-static.js.map +1 -1
  157. package/dist/frontend/npm.d.ts +60 -0
  158. package/dist/frontend/npm.js +38 -4
  159. package/dist/frontend/npm.js.map +1 -1
  160. package/dist/frontend/npm.test.d.ts +1 -0
  161. package/dist/frontend/npm.test.js +50 -0
  162. package/dist/frontend/npm.test.js.map +1 -0
  163. package/dist/frontend/program.d.ts +3 -2
  164. package/dist/frontend/program.js +495 -68
  165. package/dist/frontend/program.js.map +1 -1
  166. package/dist/frontend/resolve.d.ts +10 -2
  167. package/dist/frontend/resolve.js +90 -14
  168. package/dist/frontend/resolve.js.map +1 -1
  169. package/dist/frontend/resolve.test.js +4 -1
  170. package/dist/frontend/resolve.test.js.map +1 -1
  171. package/dist/frontend/runtime-resolve.d.ts +22 -0
  172. package/dist/frontend/runtime-resolve.js +101 -0
  173. package/dist/frontend/runtime-resolve.js.map +1 -0
  174. package/dist/frontend/runtime-resolve.test.d.ts +1 -0
  175. package/dist/frontend/runtime-resolve.test.js +18 -0
  176. package/dist/frontend/runtime-resolve.test.js.map +1 -0
  177. package/dist/frontend/ts7/adapter.js +12 -13
  178. package/dist/frontend/ts7/adapter.js.map +1 -1
  179. package/dist/frontend/ts7/ast.js.map +1 -1
  180. package/dist/frontend/ts7/census-check.js +3 -3
  181. package/dist/frontend/ts7/census-check.js.map +1 -1
  182. package/dist/frontend/ts7/checker.d.ts +3 -0
  183. package/dist/frontend/ts7/checker.js +12 -3
  184. package/dist/frontend/ts7/checker.js.map +1 -1
  185. package/dist/frontend/ts7/enums.js.map +1 -1
  186. package/dist/frontend/ts7/program-adapter.js +42 -3
  187. package/dist/frontend/ts7/program-adapter.js.map +1 -1
  188. package/dist/frontend/type-mapper.js +120 -7
  189. package/dist/frontend/type-mapper.js.map +1 -1
  190. package/dist/index.js +5 -5
  191. package/dist/index.js.map +1 -1
  192. package/dist/ir/analysis.js.map +1 -1
  193. package/dist/ir/ir.d.ts +60 -30
  194. package/dist/ir/ir.js +57 -6
  195. package/dist/ir/ir.js.map +1 -1
  196. package/dist/ir/validate.js +44 -59
  197. package/dist/ir/validate.js.map +1 -1
  198. package/dist/library/cache-primitives.js.map +1 -1
  199. package/dist/library/cache-reset.test.js.map +1 -1
  200. package/dist/library/compiler-self-identity.js.map +1 -1
  201. package/dist/library/int-infer.js.map +1 -1
  202. package/dist/library/int-infer.test.js.map +1 -1
  203. package/dist/library/library-profile.js.map +1 -1
  204. package/dist/library/sidecar-validate.js.map +1 -1
  205. package/dist/library/sidecar.js.map +1 -1
  206. package/dist/startup-cache.js.map +1 -1
  207. package/dist/wasi-paths.js.map +1 -1
  208. package/package.json +18 -18
  209. package/surface-manifest.json +60 -4
@@ -64,7 +64,7 @@ import { InternalCompilerError } from "../../errors.js";
64
64
  import { deflateRawSync } from "node:zlib";
65
65
  import { endsWithJump, matchStringSelfConcat } from "../../ir/analysis.js";
66
66
  import { emitLibraryIdentityLines } from "../library-identity-markers.js";
67
- import { CAUGHT, ffiCallbackType, isFfiContextParam, isRefCounted, isUnitType, moduleEmbedsBuiltin, moduleEmbedsCompressedNpm, moduleUsesDynInvoke, moduleUsesFetch, moduleUsesFsWatch, moduleUsesHttpServer, moduleUsesNet, moduleUsesNodeTest, moduleUsesProcessEvents, moduleUsesStream, moduleUsesTls, moduleUsesTlsCa, NPM_COMPRESS_MIN, POINTER_KINDS, RUNTIME_EMITTER_CLASS, RUNTIME_ERROR_CLASSES, RUNTIME_STREAM_CLASSES, VOID } from "../../ir/ir.js";
67
+ import { CAUGHT, ffiCallbackType, isFfiContextParam, isRefCounted, isUnitType, moduleEmbedsBuiltin, moduleEmbedsCompressedNpm, moduleUsesChildProcess, moduleUsesDynInvoke, moduleUsesFetch, moduleUsesFsWatch, moduleUsesHttpServer, moduleUsesNet, moduleUsesNodeTest, moduleUsesProcessEvents, moduleUsesStream, moduleUsesTls, moduleUsesTlsCa, NPM_COMPRESS_MIN, POINTER_KINDS, RUNTIME_EMITTER_CLASS, RUNTIME_ERROR_CLASSES, RUNTIME_STREAM_CLASSES, typeKey, VOID } from "../../ir/ir.js";
68
68
  import { matchIntegerBytesForLoop } from "../../ir/integer-loops.js";
69
69
  import { allocateFfiCallbackAdapters, hasForeignFfiCallback, hasRetainedFfiCallback } from "../ffi-callbacks.js";
70
70
  import { RUNTIME_ABI_MARKER } from "../runtime-abi.js";
@@ -202,8 +202,8 @@ class LlEmitter {
202
202
  /** ReadableStream.from adapters keep typed arrays by reference and box
203
203
  * one current element per pull. */
204
204
  streamFromArrayAdapters = new Map();
205
- /** Identity-preserving static→dyn capsules used by Web APIs whose values
206
- * remain directly observable (stream chunks and AbortSignal reasons). */
205
+ /** Identity-preserving static→dyn capsules for program classes and Web
206
+ * APIs whose values remain directly observable. */
207
207
  liveDynRefAdapters = new Map();
208
208
  /** Runtime-arm dispatchers for live union values. */
209
209
  liveDynUnionRefAdapters = new Map();
@@ -256,8 +256,8 @@ class LlEmitter {
256
256
  * `tryDepth` snapshots tryStack.length at region entry: a throw inside
257
257
  * a pending-return finally copy propagates OUT of the completing try
258
258
  * (past its own catch), so the copies emit under the truncated stack.
259
- * break/continue never cross a finally (frontend fence + validator
260
- * backstop), so return and the two tryCatch paths are the only copies. */
259
+ * break/continue use the same region snapshots through
260
+ * emitFinallysForJump. */
261
261
  finallyStack = [];
262
262
  /** Enclosing try contexts, innermost last — the compile-time unwind
263
263
  * targets (CEmitter.tryStack): a pending check or `throw` inside a try
@@ -692,6 +692,7 @@ class LlEmitter {
692
692
  // BEFORE the global releases (the C emitter's runExitListeners
693
693
  // ordering — the atexit half becomes an idempotent no-op).
694
694
  const usesEvents = moduleUsesProcessEvents(this.mod);
695
+ const usesChildProcess = moduleUsesChildProcess(this.mod);
695
696
  const usesFsWatch = moduleUsesFsWatch(this.mod);
696
697
  // Stream-surface programs fill the loop's stream hook (the deferred
697
698
  // next-tick emissions) and the emitter's post-registration flow kick
@@ -724,6 +725,8 @@ class LlEmitter {
724
725
  // Declared NOW — the extern block flushes before main assembles.
725
726
  if (usesEvents)
726
727
  this.declare(`declare void @scr_events_install()`);
728
+ if (usesChildProcess)
729
+ this.declare(`declare void @scr_child_dyn_install()`);
727
730
  if (usesFsWatch)
728
731
  this.declare(`declare void @scr_watch_install()`);
729
732
  if (this.ffiHasForeignCallback)
@@ -1114,7 +1117,7 @@ class LlEmitter {
1114
1117
  // Event-surface programs (signal/exit listeners) fill the loop's
1115
1118
  // nullable event hooks before %main — scr_events.c links only when
1116
1119
  // this line is emitted (native-toolchain.ts gates on the same predicate).
1117
- ...(usesEvents ? [` call void @scr_events_install()`] : []),
1120
+ ...(usesEvents ? [` call void @scr_events_install()`] : []), ...(usesChildProcess ? [` call void @scr_child_dyn_install()`] : []),
1118
1121
  // fs.watch programs fill the loop's watch hooks the same way —
1119
1122
  // scr_watch.c links only when this line is emitted.
1120
1123
  ...(usesFsWatch ? [` call void @scr_watch_install()`] : []), ...(this.ffiHasForeignCallback ? [` call void @scr_ffi_install()`] : []), ...(snapshotsTlsCa ? [` call void @scr_tls_ca_install()`] : []), ...(usesFetch ? [` call void @scr_fetch_install()`] : []), ...(embedsZlib ? [` call void @scr_zlib_island_install()`] : []), ...(embedsNet ? [` call void @scr_net_island_install()`] : []), ...(usesNet ? [` call void @scr_net_install()`, ` call void @scr_net_dyn_install()`] : []), ...(usesHttp ? [` call void @scr_http_dyn_install()`] : []), ...(usesStream ? [` call void @scr_stream_install()`] : []), ` call void @scr_lib_init(i32 %argc, ptr %argv)`, ...(usesIsland
@@ -1537,7 +1540,7 @@ class LlEmitter {
1537
1540
  out.push(`define void @scr_wasi_coro_resume(ptr %handle) ${FN_ATTRS} {`, `entry:`, ` call void @llvm.coro.resume(ptr %handle)`, ` ret void`, `}`, `define void @scr_wasi_coro_destroy(ptr %handle) ${FN_ATTRS} {`, `entry:`, ` call void @llvm.coro.destroy(ptr %handle)`, ` ret void`, `}`, ``);
1538
1541
  }
1539
1542
  for (const fn of this.mod.functions) {
1540
- if (fn.async !== true)
1543
+ if (fn.async !== true || fn.generator !== undefined)
1541
1544
  continue;
1542
1545
  const { definitions, ret, tr, spawnParams, argPackLines } = this.emitArgPackAndTrampolinePrologue(fn);
1543
1546
  out.push(...definitions);
@@ -1708,6 +1711,27 @@ class LlEmitter {
1708
1711
  tr.push(` br label %done`, `done:`, ` ret void`, `}`, ``);
1709
1712
  }
1710
1713
  out.push(...tr);
1714
+ let settleAsync = null;
1715
+ if (fn.async) {
1716
+ this.declare(`declare ptr @scr_async_gen_new(ptr, ptr, ptr, ptr)`);
1717
+ const genT = {
1718
+ kind: "generator",
1719
+ async: true,
1720
+ yieldT: fn.generator.yieldT,
1721
+ retT: ret,
1722
+ nextT: fn.generator.nextT,
1723
+ };
1724
+ const resultT = fn.generator.resultType;
1725
+ const build = this.genResultThunkFor(genT, resultT);
1726
+ settleAsync = `${build}_async`;
1727
+ const settleKey = `ags:${typeKey(genT)}`;
1728
+ if (!this.resolveThunks.has(settleKey)) {
1729
+ this.resolveThunks.set(settleKey, settleAsync);
1730
+ const adapters = vAdapters(this, resultT);
1731
+ this.resolveThunkDefs.push(`define internal void @${settleAsync}(ptr %g, ptr %p) ${FN_ATTRS} {`, `entry:`, ` %r = call ptr @${build}(ptr %g)`, ` call void @scr_promise_fulfill_ref(ptr %p, ptr %r, ptr ${adapters.retain}, ptr ${adapters.release}, ptr ${traceArg(this, resultT)})`, ` ret void`, `}`, ``);
1732
+ }
1733
+ this.declare(`declare void @scr_promise_fulfill_ref(ptr, ptr, ptr, ptr, ptr)`);
1734
+ }
1711
1735
  // The never-started teardown: drop the packed (+1) arguments.
1712
1736
  const dr = [
1713
1737
  `define internal void @${mangleGenDrop(fn.name)}(ptr %ap) ${FN_ATTRS} {`,
@@ -1739,7 +1763,9 @@ class LlEmitter {
1739
1763
  `entry:`,
1740
1764
  ...argPackLines,
1741
1765
  ];
1742
- sp.push(` %gg = call ptr @scr_gen_new(ptr @${mangleTrampoline(fn.name)}, ptr %ap, ptr @${mangleGenDrop(fn.name)})`, ` ret ptr %gg`, `}`, ``);
1766
+ sp.push(settleAsync === null
1767
+ ? ` %gg = call ptr @scr_gen_new(ptr @${mangleTrampoline(fn.name)}, ptr %ap, ptr @${mangleGenDrop(fn.name)})`
1768
+ : ` %gg = call ptr @scr_async_gen_new(ptr @${mangleTrampoline(fn.name)}, ptr %ap, ptr @${mangleGenDrop(fn.name)}, ptr @${settleAsync})`, ` ret ptr %gg`, `}`, ``);
1743
1769
  out.push(...sp);
1744
1770
  }
1745
1771
  return out;
@@ -1867,6 +1893,34 @@ class LlEmitter {
1867
1893
  for (let i = this.scopes.length - 1; i >= scopeDepth; i--)
1868
1894
  this.releaseScope(this.scopes[i]);
1869
1895
  }
1896
+ /** Run the finally regions an abrupt loop/block jump crosses, then
1897
+ * release to the already-resolved target. This is the return path's
1898
+ * completion walk without a parked result value. */
1899
+ emitFinallysForJump(finallyDepth, frameDepth, scopeDepth) {
1900
+ if (this.finallyStack.length <= finallyDepth) {
1901
+ this.releaseForJump(frameDepth, scopeDepth);
1902
+ return;
1903
+ }
1904
+ const savedFrames = this.frames;
1905
+ const savedScopes = this.scopes;
1906
+ const savedFinally = this.finallyStack;
1907
+ const savedTry = this.tryStack;
1908
+ for (let i = savedFinally.length - 1; i >= finallyDepth && !this.B.isTerminated(); i--) {
1909
+ const fin = savedFinally[i];
1910
+ this.releaseForJump(fin.frameDepth, fin.scopeDepth);
1911
+ this.frames = this.frames.slice(0, fin.frameDepth);
1912
+ this.scopes = this.scopes.slice(0, fin.scopeDepth);
1913
+ this.finallyStack = savedFinally.slice(0, i);
1914
+ this.tryStack = savedTry.slice(0, fin.tryDepth);
1915
+ this.emitBlock(fin.body);
1916
+ }
1917
+ if (!this.B.isTerminated())
1918
+ this.releaseForJump(frameDepth, scopeDepth);
1919
+ this.frames = savedFrames;
1920
+ this.scopes = savedScopes;
1921
+ this.finallyStack = savedFinally;
1922
+ this.tryStack = savedTry;
1923
+ }
1870
1924
  /** THE unwind path at a point where an exception is pending: release
1871
1925
  * everything between here and the innermost try handler — or the whole
1872
1926
  * function — and branch to the handler / return a dummy value (never
@@ -2362,10 +2416,10 @@ class LlEmitter {
2362
2416
  * fiber and returns the generator object) — CEmitter.callTargetC. */
2363
2417
  callTarget(fnName) {
2364
2418
  const fn = this.fnByName.get(fnName);
2365
- if (fn?.async === true)
2366
- return mangleAsyncSpawn(fnName);
2367
2419
  if (fn?.generator !== undefined)
2368
2420
  return mangleGenSpawn(fnName);
2421
+ if (fn?.async === true)
2422
+ return mangleAsyncSpawn(fnName);
2369
2423
  return mangleFunction(fnName);
2370
2424
  }
2371
2425
  /** Queue the current wasm coroutine and suspend it. The runtime decides
@@ -2495,7 +2549,7 @@ class LlEmitter {
2495
2549
  B.line(`call void @scr_wasi_coro_started(ptr ${handle})`);
2496
2550
  B.line(`${self} = call ptr @scr_fiber_self()`);
2497
2551
  this.currentWasiCoro = {
2498
- kind: fn.async === true ? "async" : "generator",
2552
+ kind: fn.generator !== undefined ? "generator" : "async",
2499
2553
  id,
2500
2554
  handle,
2501
2555
  self,
@@ -2964,6 +3018,7 @@ class LlEmitter {
2964
3018
  labels: s.labels,
2965
3019
  frameDepth: this.frames.length,
2966
3020
  scopeDepth: this.scopes.length,
3021
+ finallyDepth: this.finallyStack.length,
2967
3022
  });
2968
3023
  this.emitBlock(s.body);
2969
3024
  this.jumpTargets.pop();
@@ -3003,6 +3058,7 @@ class LlEmitter {
3003
3058
  ...(s.labels !== undefined && { labels: s.labels }),
3004
3059
  frameDepth: this.frames.length,
3005
3060
  scopeDepth: this.scopes.length,
3061
+ finallyDepth: this.finallyStack.length,
3006
3062
  });
3007
3063
  this.emitBlock(s.body);
3008
3064
  this.jumpTargets.pop();
@@ -3024,6 +3080,7 @@ class LlEmitter {
3024
3080
  ...(s.labels !== undefined && { labels: s.labels }),
3025
3081
  frameDepth: this.frames.length,
3026
3082
  scopeDepth: this.scopes.length,
3083
+ finallyDepth: this.finallyStack.length,
3027
3084
  });
3028
3085
  this.emitBlock(s.body);
3029
3086
  this.jumpTargets.pop();
@@ -3085,6 +3142,7 @@ class LlEmitter {
3085
3142
  ...(s.labels !== undefined && { labels: s.labels }),
3086
3143
  frameDepth: this.frames.length,
3087
3144
  scopeDepth: this.scopes.length,
3145
+ finallyDepth: this.finallyStack.length,
3088
3146
  });
3089
3147
  this.emitBlock(s.body);
3090
3148
  this.jumpTargets.pop();
@@ -3156,6 +3214,7 @@ class LlEmitter {
3156
3214
  ...(s.labels !== undefined && { labels: s.labels }),
3157
3215
  frameDepth: this.frames.length,
3158
3216
  scopeDepth: this.scopes.length,
3217
+ finallyDepth: this.finallyStack.length,
3159
3218
  });
3160
3219
  // The loop variable is a fresh const per iteration: its scope opens
3161
3220
  // here, holds the (for ref elements: owned +1) current element, and
@@ -3216,8 +3275,9 @@ class LlEmitter {
3216
3275
  }
3217
3276
  if (!target)
3218
3277
  throw new InternalCompilerError("llvm emitter bug: break target not found");
3219
- this.releaseForJump(target.frameDepth, target.scopeDepth);
3220
- B.terminate(`br label %${target.brkLabel}`);
3278
+ this.emitFinallysForJump(target.finallyDepth, target.frameDepth, target.scopeDepth);
3279
+ if (!B.isTerminated())
3280
+ B.terminate(`br label %${target.brkLabel}`);
3221
3281
  break;
3222
3282
  }
3223
3283
  case "continue": {
@@ -3233,8 +3293,9 @@ class LlEmitter {
3233
3293
  }
3234
3294
  if (!target || target.contLabel === null)
3235
3295
  throw new InternalCompilerError("llvm emitter bug: continue target not found");
3236
- this.releaseForJump(target.frameDepth, target.scopeDepth);
3237
- B.terminate(`br label %${target.contLabel}`);
3296
+ this.emitFinallysForJump(target.finallyDepth, target.frameDepth, target.scopeDepth);
3297
+ if (!B.isTerminated())
3298
+ B.terminate(`br label %${target.contLabel}`);
3238
3299
  break;
3239
3300
  }
3240
3301
  case "return": {
@@ -3369,10 +3430,9 @@ class LlEmitter {
3369
3430
  * <unwind> stash (it unwinds through the synthetic
3370
3431
  * try.e: scope entry) — JS's semantics exactly
3371
3432
  *
3372
- * Returns inside tryBody/catchBody ride the finallyStack (inline copies
3373
- * at the return site — see `return`); break/continue never cross a
3374
- * finally and no jump leaves a finally body (frontend fence + validator
3375
- * backstop). */
3433
+ * Abrupt completions inside tryBody/catchBody ride the finallyStack:
3434
+ * returns inline copies at the return site, while break/continue use the
3435
+ * shared region walk before branching to their resolved target. */
3376
3436
  emitTryCatch(s) {
3377
3437
  const B = this.B;
3378
3438
  const hasCatch = s.catchBody !== null;
@@ -3471,11 +3531,29 @@ class LlEmitter {
3471
3531
  B.line(`${stash} = call ptr @scr_exc_take() ; stash across finally`);
3472
3532
  B.line(`store ptr ${stash}, ptr ${stashSlot}`);
3473
3533
  this.scopes.push([{ slot: stashSlot, type: CAUGHT }]);
3534
+ const suppressHandler = s.suppressFinallyErrors
3535
+ ? {
3536
+ label: B.newLabel("try.fs"),
3537
+ used: false,
3538
+ frameDepth: this.frames.length,
3539
+ scopeDepth: this.scopes.length,
3540
+ }
3541
+ : null;
3542
+ if (suppressHandler)
3543
+ this.tryStack.push(suppressHandler);
3474
3544
  this.emitBlock(s.finallyBody);
3545
+ if (suppressHandler)
3546
+ this.tryStack.pop();
3475
3547
  this.scopes.pop(); // normal completion keeps the stash for the re-raise
3476
3548
  B.line(`call void @scr_rethrow(ptr ${stash})`);
3477
3549
  B.line(`call void @scr_caught_release(ptr ${stash})`);
3478
3550
  this.emitUnwind();
3551
+ if (suppressHandler?.used) {
3552
+ B.startBlock(suppressHandler.label);
3553
+ this.declare(`declare void @scr_exc_suppress(ptr)`);
3554
+ B.line(`call void @scr_exc_suppress(ptr ${stash}) ; consumes stash`);
3555
+ this.emitUnwind();
3556
+ }
3479
3557
  }
3480
3558
  B.startBlock(endLabel);
3481
3559
  }
@@ -3546,6 +3624,7 @@ class LlEmitter {
3546
3624
  ...(s.labels !== undefined && { labels: s.labels }),
3547
3625
  frameDepth: this.frames.length,
3548
3626
  scopeDepth: this.scopes.length,
3627
+ finallyDepth: this.finallyStack.length,
3549
3628
  });
3550
3629
  const scope = [];
3551
3630
  this.scopes.push(scope);