@scriptc/compiler 0.1.7 → 0.2.0

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 (1032) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +73 -24
  2. package/ambient/scriptc-overrides.d.ts +10 -6
  3. package/ambient/scriptc.d.ts +15 -0
  4. package/dist/backend/build-cache.d.ts +1 -3
  5. package/dist/backend/build-cache.js +3 -22
  6. package/dist/backend/build-cache.js.map +1 -1
  7. package/dist/backend/cache-root.d.ts +3 -0
  8. package/dist/backend/cache-root.js +23 -0
  9. package/dist/backend/cache-root.js.map +1 -0
  10. package/dist/backend/cycle-analysis.d.ts +15 -0
  11. package/dist/backend/cycle-analysis.js +107 -0
  12. package/dist/backend/cycle-analysis.js.map +1 -0
  13. package/dist/backend/cycle-analysis.test.js +124 -0
  14. package/dist/backend/cycle-analysis.test.js.map +1 -0
  15. package/dist/backend/executable-features.d.ts +4 -0
  16. package/dist/backend/executable-features.js +42 -0
  17. package/dist/backend/executable-features.js.map +1 -0
  18. package/dist/backend/external-c.d.ts +5 -27
  19. package/dist/backend/external-c.js +5 -40
  20. package/dist/backend/external-c.js.map +1 -1
  21. package/dist/backend/ffi-callbacks.d.ts +2 -3
  22. package/dist/backend/ffi-callbacks.js +2 -3
  23. package/dist/backend/ffi-callbacks.js.map +1 -1
  24. package/dist/backend/library-identity-markers.d.ts +4 -9
  25. package/dist/backend/library-identity-markers.js +11 -49
  26. package/dist/backend/library-identity-markers.js.map +1 -1
  27. package/dist/backend/library-pack.d.ts +5 -0
  28. package/dist/backend/library-pack.js +123 -0
  29. package/dist/backend/library-pack.js.map +1 -0
  30. package/dist/backend/link-plan-core.d.ts +20 -0
  31. package/dist/backend/link-plan-core.js +18 -0
  32. package/dist/backend/link-plan-core.js.map +1 -0
  33. package/dist/backend/link-plan.d.ts +1 -1
  34. package/dist/backend/link-plan.js +16 -17
  35. package/dist/backend/link-plan.js.map +1 -1
  36. package/dist/backend/link-trace.d.ts +2 -0
  37. package/dist/backend/link-trace.js +24 -0
  38. package/dist/backend/link-trace.js.map +1 -0
  39. package/dist/backend/linker.js +1 -1
  40. package/dist/backend/linker.js.map +1 -1
  41. package/dist/backend/literals.d.ts +9 -0
  42. package/dist/backend/literals.js +35 -0
  43. package/dist/backend/literals.js.map +1 -0
  44. package/dist/backend/literals.test.d.ts +1 -0
  45. package/dist/backend/literals.test.js +53 -0
  46. package/dist/backend/literals.test.js.map +1 -0
  47. package/dist/backend/llvm/blocks.d.ts +2 -0
  48. package/dist/backend/llvm/blocks.js +9 -4
  49. package/dist/backend/llvm/blocks.js.map +1 -1
  50. package/dist/backend/llvm/blocks.test.d.ts +1 -0
  51. package/dist/backend/llvm/blocks.test.js +91 -0
  52. package/dist/backend/llvm/blocks.test.js.map +1 -0
  53. package/dist/backend/llvm/classes.d.ts +14 -8
  54. package/dist/backend/llvm/classes.js +70 -28
  55. package/dist/backend/llvm/classes.js.map +1 -1
  56. package/dist/backend/llvm/common.d.ts +5 -1
  57. package/dist/backend/llvm/common.js +45 -4
  58. package/dist/backend/llvm/common.js.map +1 -1
  59. package/dist/backend/llvm/debug-info.js +2 -7
  60. package/dist/backend/llvm/debug-info.js.map +1 -1
  61. package/dist/backend/llvm/debug-info.test.d.ts +1 -0
  62. package/dist/backend/llvm/debug-info.test.js +110 -0
  63. package/dist/backend/llvm/debug-info.test.js.map +1 -0
  64. package/dist/backend/llvm/dyn.d.ts +16 -2
  65. package/dist/backend/llvm/dyn.js +494 -165
  66. package/dist/backend/llvm/dyn.js.map +1 -1
  67. package/dist/backend/llvm/emitter.d.ts +596 -1
  68. package/dist/backend/llvm/emitter.js +695 -410
  69. package/dist/backend/llvm/emitter.js.map +1 -1
  70. package/dist/backend/llvm/emitter.test.d.ts +1 -0
  71. package/dist/backend/llvm/emitter.test.js +179 -0
  72. package/dist/backend/llvm/emitter.test.js.map +1 -0
  73. package/dist/backend/llvm/expr-async.js +23 -14
  74. package/dist/backend/llvm/expr-async.js.map +1 -1
  75. package/dist/backend/llvm/expr-bytes.d.ts +1 -1
  76. package/dist/backend/llvm/expr-bytes.js +32 -14
  77. package/dist/backend/llvm/expr-bytes.js.map +1 -1
  78. package/dist/backend/llvm/expr-callbacks.d.ts +1 -1
  79. package/dist/backend/llvm/expr-callbacks.js +25 -22
  80. package/dist/backend/llvm/expr-callbacks.js.map +1 -1
  81. package/dist/backend/llvm/expr-calls.js +136 -35
  82. package/dist/backend/llvm/expr-calls.js.map +1 -1
  83. package/dist/backend/llvm/expr-containers.d.ts +1 -1
  84. package/dist/backend/llvm/expr-containers.js +43 -14
  85. package/dist/backend/llvm/expr-containers.js.map +1 -1
  86. package/dist/backend/llvm/expr-context.d.ts +5 -260
  87. package/dist/backend/llvm/expr-control.js +9 -5
  88. package/dist/backend/llvm/expr-control.js.map +1 -1
  89. package/dist/backend/llvm/expr-dispatch.d.ts +1 -1
  90. package/dist/backend/llvm/expr-dispatch.js +2 -0
  91. package/dist/backend/llvm/expr-dispatch.js.map +1 -1
  92. package/dist/backend/llvm/expr-dynamic.js +62 -74
  93. package/dist/backend/llvm/expr-dynamic.js.map +1 -1
  94. package/dist/backend/llvm/expr-island.d.ts +1 -1
  95. package/dist/backend/llvm/expr-island.js +11 -7
  96. package/dist/backend/llvm/expr-island.js.map +1 -1
  97. package/dist/backend/llvm/expr-primitives.d.ts +1 -1
  98. package/dist/backend/llvm/expr-primitives.js +51 -30
  99. package/dist/backend/llvm/expr-primitives.js.map +1 -1
  100. package/dist/backend/llvm/expr-primitives.test.js +1 -1
  101. package/dist/backend/llvm/expr-records.d.ts +5 -1
  102. package/dist/backend/llvm/expr-records.js +43 -4
  103. package/dist/backend/llvm/expr-records.js.map +1 -1
  104. package/dist/backend/llvm/expr-stream-bridges.d.ts +4 -4
  105. package/dist/backend/llvm/expr-stream-bridges.js +102 -121
  106. package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
  107. package/dist/backend/llvm/expr-stream-bridges.test.d.ts +1 -0
  108. package/dist/backend/llvm/expr-stream-bridges.test.js +55 -0
  109. package/dist/backend/llvm/expr-stream-bridges.test.js.map +1 -0
  110. package/dist/backend/llvm/expr-stream-callbacks.d.ts +1 -1
  111. package/dist/backend/llvm/expr-stream-callbacks.js +12 -12
  112. package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
  113. package/dist/backend/llvm/layouts.d.ts +19 -0
  114. package/dist/backend/llvm/layouts.js +12 -0
  115. package/dist/backend/llvm/layouts.js.map +1 -0
  116. package/dist/backend/llvm/lib-abi.d.ts +19 -0
  117. package/dist/backend/llvm/lib-abi.js +82 -0
  118. package/dist/backend/llvm/lib-abi.js.map +1 -0
  119. package/dist/backend/llvm/lib-connect.d.ts +2 -0
  120. package/dist/backend/llvm/lib-connect.js +51 -0
  121. package/dist/backend/llvm/lib-connect.js.map +1 -0
  122. package/dist/backend/llvm/lib-datagram.d.ts +2 -0
  123. package/dist/backend/llvm/lib-datagram.js +135 -0
  124. package/dist/backend/llvm/lib-datagram.js.map +1 -0
  125. package/dist/backend/llvm/lib-dispatch.js +50 -6
  126. package/dist/backend/llvm/lib-dispatch.js.map +1 -1
  127. package/dist/backend/llvm/lib-filesystem.js +30 -18
  128. package/dist/backend/llvm/lib-filesystem.js.map +1 -1
  129. package/dist/backend/llvm/lib-http2.d.ts +2 -0
  130. package/dist/backend/llvm/lib-http2.js +215 -0
  131. package/dist/backend/llvm/lib-http2.js.map +1 -0
  132. package/dist/backend/llvm/lib-lookup.d.ts +2 -0
  133. package/dist/backend/llvm/lib-lookup.js +39 -0
  134. package/dist/backend/llvm/lib-lookup.js.map +1 -0
  135. package/dist/backend/llvm/lib-network.js +25 -2
  136. package/dist/backend/llvm/lib-network.js.map +1 -1
  137. package/dist/backend/llvm/lib-process.js +21 -16
  138. package/dist/backend/llvm/lib-process.js.map +1 -1
  139. package/dist/backend/llvm/lib-shared.js +117 -1
  140. package/dist/backend/llvm/lib-shared.js.map +1 -1
  141. package/dist/backend/llvm/lib-stream.js +3 -2
  142. package/dist/backend/llvm/lib-stream.js.map +1 -1
  143. package/dist/backend/llvm/lib-test.d.ts +2 -0
  144. package/dist/backend/llvm/lib-test.js +34 -0
  145. package/dist/backend/llvm/lib-test.js.map +1 -0
  146. package/dist/backend/llvm/lib-tls.d.ts +2 -0
  147. package/dist/backend/llvm/lib-tls.js +82 -0
  148. package/dist/backend/llvm/lib-tls.js.map +1 -0
  149. package/dist/backend/llvm/shapes.d.ts +10 -9
  150. package/dist/backend/llvm/shapes.js +35 -130
  151. package/dist/backend/llvm/shapes.js.map +1 -1
  152. package/dist/backend/llvm/unsupported.d.ts +1 -0
  153. package/dist/backend/llvm/unsupported.js +1 -2
  154. package/dist/backend/llvm/unsupported.js.map +1 -1
  155. package/dist/backend/llvm/walkers.js +1 -7
  156. package/dist/backend/llvm/walkers.js.map +1 -1
  157. package/dist/backend/mangle.d.ts +2 -2
  158. package/dist/backend/mangle.js +16 -5
  159. package/dist/backend/mangle.js.map +1 -1
  160. package/dist/backend/{c/may-throw.d.ts → may-throw.d.ts} +1 -1
  161. package/dist/backend/{c/may-throw.js → may-throw.js} +51 -46
  162. package/dist/backend/may-throw.js.map +1 -0
  163. package/dist/backend/may-throw.test.d.ts +1 -0
  164. package/dist/backend/may-throw.test.js +58 -0
  165. package/dist/backend/may-throw.test.js.map +1 -0
  166. package/dist/backend/native-codegen-core.d.ts +22 -0
  167. package/dist/backend/native-codegen-core.js +44 -0
  168. package/dist/backend/native-codegen-core.js.map +1 -0
  169. package/dist/backend/native-codegen.d.ts +3 -19
  170. package/dist/backend/native-codegen.js +5 -44
  171. package/dist/backend/native-codegen.js.map +1 -1
  172. package/dist/backend/native-codegen.test.js +2 -2
  173. package/dist/backend/native-codegen.test.js.map +1 -1
  174. package/dist/backend/native-link-info-core.d.ts +94 -0
  175. package/dist/backend/native-link-info-core.js +62 -0
  176. package/dist/backend/native-link-info-core.js.map +1 -0
  177. package/dist/backend/native-link-info.d.ts +3 -88
  178. package/dist/backend/native-link-info.js +12 -243
  179. package/dist/backend/native-link-info.js.map +1 -1
  180. package/dist/backend/native-link-info.test.js +41 -146
  181. package/dist/backend/native-link-info.test.js.map +1 -1
  182. package/dist/backend/native-toolchain.d.ts +10 -25
  183. package/dist/backend/native-toolchain.js +31 -211
  184. package/dist/backend/native-toolchain.js.map +1 -1
  185. package/dist/backend/native-toolchain.test.js +5 -5
  186. package/dist/backend/native-toolchain.test.js.map +1 -1
  187. package/dist/backend/native-tools.d.ts +24 -0
  188. package/dist/backend/native-tools.js +33 -0
  189. package/dist/backend/native-tools.js.map +1 -0
  190. package/dist/backend/object-localize.js +19 -8
  191. package/dist/backend/object-localize.js.map +1 -1
  192. package/dist/backend/object-localize.test.js +22 -0
  193. package/dist/backend/object-localize.test.js.map +1 -1
  194. package/dist/backend/runtime-abi.d.ts +2 -2
  195. package/dist/backend/runtime-abi.js +2 -2
  196. package/dist/backend/runtime-pack-core.d.ts +101 -0
  197. package/dist/backend/runtime-pack-core.js +172 -0
  198. package/dist/backend/runtime-pack-core.js.map +1 -0
  199. package/dist/backend/runtime-pack-native.d.ts +21 -0
  200. package/dist/backend/runtime-pack-native.js +70 -0
  201. package/dist/backend/runtime-pack-native.js.map +1 -0
  202. package/dist/backend/runtime-pack-targets.test.js +1 -1
  203. package/dist/backend/runtime-pack.d.ts +3 -83
  204. package/dist/backend/runtime-pack.js +8 -151
  205. package/dist/backend/runtime-pack.js.map +1 -1
  206. package/dist/backend/runtime-pack.test.js +24 -1
  207. package/dist/backend/runtime-pack.test.js.map +1 -1
  208. package/dist/backend/target-diagnostics.d.ts +22 -0
  209. package/dist/backend/target-diagnostics.js +108 -0
  210. package/dist/backend/target-diagnostics.js.map +1 -0
  211. package/dist/backend/target-platform.d.ts +15 -0
  212. package/dist/backend/target-platform.js +72 -0
  213. package/dist/backend/target-platform.js.map +1 -0
  214. package/dist/backend/targets.d.ts +13 -4
  215. package/dist/backend/targets.js +95 -30
  216. package/dist/backend/targets.js.map +1 -1
  217. package/dist/backend/targets.test.js +65 -4
  218. package/dist/backend/targets.test.js.map +1 -1
  219. package/dist/backend/toolchain-environment.d.ts +6 -0
  220. package/dist/backend/toolchain-environment.js +99 -0
  221. package/dist/backend/toolchain-environment.js.map +1 -0
  222. package/dist/backend/vendor-archives.d.ts +1 -9
  223. package/dist/backend/vendor-archives.js +2 -9
  224. package/dist/backend/vendor-archives.js.map +1 -1
  225. package/dist/backend/vendor-inputs.d.ts +9 -0
  226. package/dist/backend/vendor-inputs.js +10 -0
  227. package/dist/backend/vendor-inputs.js.map +1 -0
  228. package/dist/backend/warm-cache.d.ts +3 -0
  229. package/dist/backend/warm-cache.js +41 -0
  230. package/dist/backend/warm-cache.js.map +1 -0
  231. package/dist/cli/command.d.ts +3 -0
  232. package/dist/cli/command.js +328 -0
  233. package/dist/cli/command.js.map +1 -0
  234. package/dist/cli/host.d.ts +24 -0
  235. package/dist/cli/host.js +2 -0
  236. package/dist/cli/host.js.map +1 -0
  237. package/dist/cli/output-options.d.ts +26 -0
  238. package/dist/cli/output-options.js +60 -0
  239. package/dist/cli/output-options.js.map +1 -0
  240. package/dist/cli/paths.d.ts +12 -0
  241. package/dist/cli/paths.js +42 -0
  242. package/dist/cli/paths.js.map +1 -0
  243. package/dist/cli/usage.d.ts +74 -0
  244. package/dist/cli/usage.js +86 -0
  245. package/dist/cli/usage.js.map +1 -0
  246. package/dist/cli/wasi-paths.d.ts +8 -0
  247. package/dist/cli/wasi-paths.js +41 -0
  248. package/dist/cli/wasi-paths.js.map +1 -0
  249. package/dist/cli/wasi-runner.d.ts +2 -0
  250. package/dist/cli/wasi-runner.js +28 -0
  251. package/dist/cli/wasi-runner.js.map +1 -0
  252. package/dist/compat/fetch-profile.js +3 -3
  253. package/dist/compat/fetch-profile.js.map +1 -1
  254. package/dist/compile-types.d.ts +162 -0
  255. package/dist/compile-types.js +2 -0
  256. package/dist/compile-types.js.map +1 -0
  257. package/dist/coverage/report.js +11 -5
  258. package/dist/coverage/report.js.map +1 -1
  259. package/dist/coverage/surface-manifest.js +5 -2
  260. package/dist/coverage/surface-manifest.js.map +1 -1
  261. package/dist/diagnostics/diagnostic.js +3 -3
  262. package/dist/diagnostics/diagnostic.js.map +1 -1
  263. package/dist/executable/executable-cache.d.ts +3 -4
  264. package/dist/executable/executable-cache.js +5 -6
  265. package/dist/executable/executable-cache.js.map +1 -1
  266. package/dist/executable/executable-cache.test.js +16 -17
  267. package/dist/executable/executable-cache.test.js.map +1 -1
  268. package/dist/executable/prepare.d.ts +14 -0
  269. package/dist/executable/prepare.js +66 -0
  270. package/dist/executable/prepare.js.map +1 -0
  271. package/dist/ffi/ffi-manifest.d.ts +11 -4
  272. package/dist/ffi/ffi-manifest.js +170 -58
  273. package/dist/ffi/ffi-manifest.js.map +1 -1
  274. package/dist/ffi/ffi-manifest.test.d.ts +1 -0
  275. package/dist/ffi/ffi-manifest.test.js +111 -0
  276. package/dist/ffi/ffi-manifest.test.js.map +1 -0
  277. package/dist/format-integer.d.ts +3 -0
  278. package/dist/format-integer.js +14 -0
  279. package/dist/format-integer.js.map +1 -0
  280. package/dist/frontend/analysis.d.ts +5 -0
  281. package/dist/frontend/analysis.js +88 -0
  282. package/dist/frontend/analysis.js.map +1 -0
  283. package/dist/frontend/arguments-usage.d.ts +1 -3
  284. package/dist/frontend/arguments-usage.js.map +1 -1
  285. package/dist/frontend/builtin-modules.d.ts +1 -1
  286. package/dist/frontend/builtin-modules.js +1 -1
  287. package/dist/frontend/builtin-modules.js.map +1 -1
  288. package/dist/frontend/cjs-lexer.d.ts +4 -25
  289. package/dist/frontend/cjs-lexer.js +6 -806
  290. package/dist/frontend/cjs-lexer.js.map +1 -1
  291. package/dist/frontend/cjs-resolve.d.ts +5 -0
  292. package/dist/frontend/cjs-resolve.js +429 -0
  293. package/dist/frontend/cjs-resolve.js.map +1 -0
  294. package/dist/frontend/cjs-syntax.d.ts +26 -0
  295. package/dist/frontend/cjs-syntax.js +806 -0
  296. package/dist/frontend/cjs-syntax.js.map +1 -0
  297. package/dist/frontend/comptime-node.d.ts +4 -0
  298. package/dist/frontend/comptime-node.js +16 -0
  299. package/dist/frontend/comptime-node.js.map +1 -0
  300. package/dist/frontend/comptime-node.test.d.ts +1 -0
  301. package/dist/frontend/comptime-node.test.js +37 -0
  302. package/dist/frontend/comptime-node.test.js.map +1 -0
  303. package/dist/frontend/dts-paths.d.ts +3 -4
  304. package/dist/frontend/dts-paths.js +15 -8
  305. package/dist/frontend/dts-paths.js.map +1 -1
  306. package/dist/frontend/fork-target.js +2 -2
  307. package/dist/frontend/fork-target.js.map +1 -1
  308. package/dist/frontend/helper-tokens.d.ts +1 -0
  309. package/dist/frontend/helper-tokens.js +147 -0
  310. package/dist/frontend/helper-tokens.js.map +1 -0
  311. package/dist/frontend/helper-tokens.test.d.ts +1 -0
  312. package/dist/frontend/helper-tokens.test.js +35 -0
  313. package/dist/frontend/helper-tokens.test.js.map +1 -0
  314. package/dist/frontend/inferred-js-diagnostics.d.ts +5 -0
  315. package/dist/frontend/inferred-js-diagnostics.js +69 -0
  316. package/dist/frontend/inferred-js-diagnostics.js.map +1 -0
  317. package/dist/frontend/inferred-js-diagnostics.test.d.ts +1 -0
  318. package/dist/frontend/inferred-js-diagnostics.test.js +58 -0
  319. package/dist/frontend/inferred-js-diagnostics.test.js.map +1 -0
  320. package/dist/frontend/input-tracker.d.ts +5 -2
  321. package/dist/frontend/input-tracker.js +24 -3
  322. package/dist/frontend/input-tracker.js.map +1 -1
  323. package/dist/frontend/input-tracker.test.js +23 -0
  324. package/dist/frontend/input-tracker.test.js.map +1 -1
  325. package/dist/frontend/lib-contract.js +32 -24
  326. package/dist/frontend/lib-contract.js.map +1 -1
  327. package/dist/frontend/literal-values.d.ts +4 -0
  328. package/dist/frontend/literal-values.js +21 -0
  329. package/dist/frontend/literal-values.js.map +1 -0
  330. package/dist/frontend/literal-values.test.d.ts +1 -0
  331. package/dist/frontend/literal-values.test.js +91 -0
  332. package/dist/frontend/literal-values.test.js.map +1 -0
  333. package/dist/frontend/lowering/abstract-equality.d.ts +1 -1
  334. package/dist/frontend/lowering/abstract-equality.js +3 -0
  335. package/dist/frontend/lowering/abstract-equality.js.map +1 -1
  336. package/dist/frontend/lowering/array-indexed-mutation.js +11 -6
  337. package/dist/frontend/lowering/array-indexed-mutation.js.map +1 -1
  338. package/dist/frontend/lowering/array-values.d.ts +4 -1
  339. package/dist/frontend/lowering/array-values.js +43 -1
  340. package/dist/frontend/lowering/array-values.js.map +1 -1
  341. package/dist/frontend/lowering/callback-arg.js +1 -0
  342. package/dist/frontend/lowering/callback-arg.js.map +1 -1
  343. package/dist/frontend/lowering/class-callbacks.d.ts +12 -0
  344. package/dist/frontend/lowering/class-callbacks.js +63 -0
  345. package/dist/frontend/lowering/class-callbacks.js.map +1 -0
  346. package/dist/frontend/lowering/class-descriptors.d.ts +9 -0
  347. package/dist/frontend/lowering/class-descriptors.js +73 -0
  348. package/dist/frontend/lowering/class-descriptors.js.map +1 -0
  349. package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +41 -0
  350. package/dist/frontend/lowering/class-dynamic-dispatch.js +803 -0
  351. package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -0
  352. package/dist/frontend/lowering/class-dynamic-dispatch.test.d.ts +1 -0
  353. package/dist/frontend/lowering/class-dynamic-dispatch.test.js +92 -0
  354. package/dist/frontend/lowering/class-dynamic-dispatch.test.js.map +1 -0
  355. package/dist/frontend/lowering/class-instance-constructor.d.ts +7 -0
  356. package/dist/frontend/lowering/class-instance-constructor.js +64 -0
  357. package/dist/frontend/lowering/class-instance-constructor.js.map +1 -0
  358. package/dist/frontend/lowering/class-method-values.d.ts +10 -0
  359. package/dist/frontend/lowering/class-method-values.js +170 -0
  360. package/dist/frontend/lowering/class-method-values.js.map +1 -0
  361. package/dist/frontend/lowering/class-prototypes.d.ts +16 -0
  362. package/dist/frontend/lowering/class-prototypes.js +134 -0
  363. package/dist/frontend/lowering/class-prototypes.js.map +1 -0
  364. package/dist/frontend/lowering/class-static-data.d.ts +6 -0
  365. package/dist/frontend/lowering/class-static-data.js +56 -0
  366. package/dist/frontend/lowering/class-static-data.js.map +1 -0
  367. package/dist/frontend/lowering/containers/buffer-numeric-methods.d.ts +4 -0
  368. package/dist/frontend/lowering/containers/buffer-numeric-methods.js +26 -0
  369. package/dist/frontend/lowering/containers/buffer-numeric-methods.js.map +1 -0
  370. package/dist/frontend/lowering/containers/bytes.d.ts +11 -7
  371. package/dist/frontend/lowering/containers/bytes.js +164 -155
  372. package/dist/frontend/lowering/containers/bytes.js.map +1 -1
  373. package/dist/frontend/lowering/containers/string-and-regexp.d.ts +2 -2
  374. package/dist/frontend/lowering/containers/string-and-regexp.js +39 -16
  375. package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
  376. package/dist/frontend/lowering/containers/string-replacement.d.ts +7 -0
  377. package/dist/frontend/lowering/containers/string-replacement.js +217 -0
  378. package/dist/frontend/lowering/containers/string-replacement.js.map +1 -0
  379. package/dist/frontend/lowering/error-methods.d.ts +11 -0
  380. package/dist/frontend/lowering/error-methods.js +78 -0
  381. package/dist/frontend/lowering/error-methods.js.map +1 -0
  382. package/dist/frontend/lowering/expressions/global-symbols.d.ts +6 -0
  383. package/dist/frontend/lowering/expressions/global-symbols.js +11 -0
  384. package/dist/frontend/lowering/expressions/global-symbols.js.map +1 -0
  385. package/dist/frontend/lowering/expressions/native-proxy.d.ts +7 -0
  386. package/dist/frontend/lowering/expressions/native-proxy.js +49 -0
  387. package/dist/frontend/lowering/expressions/native-proxy.js.map +1 -0
  388. package/dist/frontend/lowering/expressions/nullish-assignment.d.ts +6 -0
  389. package/dist/frontend/lowering/expressions/nullish-assignment.js +124 -0
  390. package/dist/frontend/lowering/expressions/nullish-assignment.js.map +1 -0
  391. package/dist/frontend/lowering/expressions/object-literals.d.ts +8 -8
  392. package/dist/frontend/lowering/expressions/object-literals.js +473 -178
  393. package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
  394. package/dist/frontend/lowering/expressions/optional-chains.js +20 -8
  395. package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
  396. package/dist/frontend/lowering/expressions/try-lower-expression.js +1 -0
  397. package/dist/frontend/lowering/expressions/try-lower-expression.js.map +1 -1
  398. package/dist/frontend/lowering/expressions/union-field-write.d.ts +8 -0
  399. package/dist/frontend/lowering/expressions/union-field-write.js +71 -0
  400. package/dist/frontend/lowering/expressions/union-field-write.js.map +1 -0
  401. package/dist/frontend/lowering/function-context.d.ts +93 -0
  402. package/dist/frontend/lowering/function-context.js +103 -0
  403. package/dist/frontend/lowering/function-context.js.map +1 -0
  404. package/dist/frontend/lowering/generator-delegation.d.ts +7 -0
  405. package/dist/frontend/lowering/generator-delegation.js +85 -0
  406. package/dist/frontend/lowering/generator-delegation.js.map +1 -0
  407. package/dist/frontend/lowering/generator-dynamic-dispatch.d.ts +10 -0
  408. package/dist/frontend/lowering/generator-dynamic-dispatch.js +105 -0
  409. package/dist/frontend/lowering/generator-dynamic-dispatch.js.map +1 -0
  410. package/dist/frontend/lowering/lib-boundary.d.ts +2 -1
  411. package/dist/frontend/lowering/lib-boundary.js +59 -20
  412. package/dist/frontend/lowering/lib-boundary.js.map +1 -1
  413. package/dist/frontend/lowering/lib-boundary.test.d.ts +1 -0
  414. package/dist/frontend/lowering/lib-boundary.test.js +45 -0
  415. package/dist/frontend/lowering/lib-boundary.test.js.map +1 -0
  416. package/dist/frontend/lowering/lower-array-sort.d.ts +1 -1
  417. package/dist/frontend/lowering/lower-assert.d.ts +1 -1
  418. package/dist/frontend/lowering/lower-assert.js.map +1 -1
  419. package/dist/frontend/lowering/lower-async-iteration.d.ts +1 -1
  420. package/dist/frontend/lowering/lower-async-iteration.js.map +1 -1
  421. package/dist/frontend/lowering/lower-builtin-values.d.ts +12 -0
  422. package/dist/frontend/lowering/lower-builtin-values.js +139 -0
  423. package/dist/frontend/lowering/lower-builtin-values.js.map +1 -0
  424. package/dist/frontend/lowering/lower-builtins.d.ts +27 -41
  425. package/dist/frontend/lowering/lower-builtins.js +539 -343
  426. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  427. package/dist/frontend/lowering/lower-calls.d.ts +20 -17
  428. package/dist/frontend/lowering/lower-calls.js +1236 -353
  429. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  430. package/dist/frontend/lowering/lower-classes.d.ts +83 -45
  431. package/dist/frontend/lowering/lower-classes.js +952 -339
  432. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  433. package/dist/frontend/lowering/lower-comptime.d.ts +1 -1
  434. package/dist/frontend/lowering/lower-comptime.js +23 -32
  435. package/dist/frontend/lowering/lower-comptime.js.map +1 -1
  436. package/dist/frontend/lowering/lower-containers.d.ts +27 -32
  437. package/dist/frontend/lowering/lower-containers.js +796 -151
  438. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  439. package/dist/frontend/lowering/lower-dgram.d.ts +1 -1
  440. package/dist/frontend/lowering/lower-dgram.js.map +1 -1
  441. package/dist/frontend/lowering/lower-enums.d.ts +1 -1
  442. package/dist/frontend/lowering/lower-enums.js.map +1 -1
  443. package/dist/frontend/lowering/lower-event-emitter.d.ts +30 -1
  444. package/dist/frontend/lowering/lower-event-emitter.js +58 -26
  445. package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
  446. package/dist/frontend/lowering/lower-expando.d.ts +7 -1
  447. package/dist/frontend/lowering/lower-expando.js +14 -6
  448. package/dist/frontend/lowering/lower-expando.js.map +1 -1
  449. package/dist/frontend/lowering/lower-exprs.d.ts +35 -11
  450. package/dist/frontend/lowering/lower-exprs.js +1674 -779
  451. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  452. package/dist/frontend/lowering/lower-generators.d.ts +2 -5
  453. package/dist/frontend/lowering/lower-generators.js +77 -46
  454. package/dist/frontend/lowering/lower-generators.js.map +1 -1
  455. package/dist/frontend/lowering/lower-global-value.d.ts +7 -0
  456. package/dist/frontend/lowering/lower-global-value.js +17 -0
  457. package/dist/frontend/lowering/lower-global-value.js.map +1 -0
  458. package/dist/frontend/lowering/lower-inspect.d.ts +1 -1
  459. package/dist/frontend/lowering/lower-inspect.js +17 -8
  460. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  461. package/dist/frontend/lowering/lower-island.d.ts +5 -8
  462. package/dist/frontend/lowering/lower-island.js +34 -23
  463. package/dist/frontend/lowering/lower-island.js.map +1 -1
  464. package/dist/frontend/lowering/lower-mixins.d.ts +2 -2
  465. package/dist/frontend/lowering/lower-mixins.js +5 -3
  466. package/dist/frontend/lowering/lower-mixins.js.map +1 -1
  467. package/dist/frontend/lowering/lower-modules.d.ts +1 -1
  468. package/dist/frontend/lowering/lower-modules.js +233 -30
  469. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  470. package/dist/frontend/lowering/lower-namespaces.d.ts +1 -1
  471. package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
  472. package/dist/frontend/lowering/lower-node-module.d.ts +1 -1
  473. package/dist/frontend/lowering/lower-node-module.js +13 -10
  474. package/dist/frontend/lowering/lower-node-module.js.map +1 -1
  475. package/dist/frontend/lowering/lower-server.d.ts +1 -1
  476. package/dist/frontend/lowering/lower-server.js +6 -10
  477. package/dist/frontend/lowering/lower-server.js.map +1 -1
  478. package/dist/frontend/lowering/lower-stmts.d.ts +10 -14
  479. package/dist/frontend/lowering/lower-stmts.js +728 -496
  480. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  481. package/dist/frontend/lowering/lower-stream.d.ts +1 -1
  482. package/dist/frontend/lowering/lower-stream.js +19 -10
  483. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  484. package/dist/frontend/lowering/lower-test.d.ts +1 -1
  485. package/dist/frontend/lowering/lower-test.js.map +1 -1
  486. package/dist/frontend/lowering/lower-url.d.ts +6 -0
  487. package/dist/frontend/lowering/lower-url.js +77 -0
  488. package/dist/frontend/lowering/lower-url.js.map +1 -0
  489. package/dist/frontend/lowering/lowerer.d.ts +113 -189
  490. package/dist/frontend/lowering/lowerer.js +1031 -672
  491. package/dist/frontend/lowering/lowerer.js.map +1 -1
  492. package/dist/frontend/lowering/lowerer.test.d.ts +1 -0
  493. package/dist/frontend/lowering/lowerer.test.js +26 -0
  494. package/dist/frontend/lowering/lowerer.test.js.map +1 -0
  495. package/dist/frontend/lowering/native-ffi.d.ts +5 -0
  496. package/dist/frontend/lowering/native-ffi.js +40 -0
  497. package/dist/frontend/lowering/native-ffi.js.map +1 -0
  498. package/dist/frontend/lowering/object-enumeration-receiver.d.ts +7 -0
  499. package/dist/frontend/lowering/object-enumeration-receiver.js +33 -0
  500. package/dist/frontend/lowering/object-enumeration-receiver.js.map +1 -0
  501. package/dist/frontend/lowering/object-factory-new.d.ts +8 -0
  502. package/dist/frontend/lowering/object-factory-new.js +68 -0
  503. package/dist/frontend/lowering/object-factory-new.js.map +1 -0
  504. package/dist/frontend/lowering/optional-arguments.js +6 -1
  505. package/dist/frontend/lowering/optional-arguments.js.map +1 -1
  506. package/dist/frontend/lowering/pairs-snapshot.js +2 -1
  507. package/dist/frontend/lowering/pairs-snapshot.js.map +1 -1
  508. package/dist/frontend/lowering/runtime-optional-locals.d.ts +14 -0
  509. package/dist/frontend/lowering/runtime-optional-locals.js +41 -0
  510. package/dist/frontend/lowering/runtime-optional-locals.js.map +1 -0
  511. package/dist/frontend/lowering/runtime-optional-locals.test.d.ts +1 -0
  512. package/dist/frontend/lowering/runtime-optional-locals.test.js +85 -0
  513. package/dist/frontend/lowering/runtime-optional-locals.test.js.map +1 -0
  514. package/dist/frontend/lowering/sanitize-class-types.d.ts +8 -0
  515. package/dist/frontend/lowering/sanitize-class-types.js +79 -0
  516. package/dist/frontend/lowering/sanitize-class-types.js.map +1 -0
  517. package/dist/frontend/lowering/sanitize-class-types.test.d.ts +1 -0
  518. package/dist/frontend/lowering/sanitize-class-types.test.js +60 -0
  519. package/dist/frontend/lowering/sanitize-class-types.test.js.map +1 -0
  520. package/dist/frontend/lowering/static-this.d.ts +5 -1
  521. package/dist/frontend/lowering/static-this.js +28 -2
  522. package/dist/frontend/lowering/static-this.js.map +1 -1
  523. package/dist/frontend/lowering/string-index.d.ts +7 -0
  524. package/dist/frontend/lowering/string-index.js +39 -0
  525. package/dist/frontend/lowering/string-index.js.map +1 -0
  526. package/dist/frontend/lowering/surfaces.d.ts +8 -3
  527. package/dist/frontend/lowering/surfaces.js +61 -29
  528. package/dist/frontend/lowering/surfaces.js.map +1 -1
  529. package/dist/frontend/lowering/symbol-fields.d.ts +22 -0
  530. package/dist/frontend/lowering/symbol-fields.js +183 -0
  531. package/dist/frontend/lowering/symbol-fields.js.map +1 -0
  532. package/dist/frontend/lowering/symbol-methods.d.ts +7 -0
  533. package/dist/frontend/lowering/symbol-methods.js +30 -0
  534. package/dist/frontend/lowering/symbol-methods.js.map +1 -0
  535. package/dist/frontend/lowering/text-decoder-encoding.d.ts +10 -0
  536. package/dist/frontend/lowering/text-decoder-encoding.js +77 -0
  537. package/dist/frontend/lowering/text-decoder-encoding.js.map +1 -0
  538. package/dist/frontend/lowering/text-decoder-encoding.test.d.ts +1 -0
  539. package/dist/frontend/lowering/text-decoder-encoding.test.js +38 -0
  540. package/dist/frontend/lowering/text-decoder-encoding.test.js.map +1 -0
  541. package/dist/frontend/lowering/union-narrow.d.ts +9 -0
  542. package/dist/frontend/lowering/union-narrow.js +59 -0
  543. package/dist/frontend/lowering/union-narrow.js.map +1 -0
  544. package/dist/frontend/lowering/union-narrow.test.d.ts +1 -0
  545. package/dist/frontend/lowering/union-narrow.test.js +72 -0
  546. package/dist/frontend/lowering/union-narrow.test.js.map +1 -0
  547. package/dist/frontend/lowering/union-retag.d.ts +43 -0
  548. package/dist/frontend/lowering/union-retag.js +259 -0
  549. package/dist/frontend/lowering/union-retag.js.map +1 -0
  550. package/dist/frontend/lowering/union-retag.test.d.ts +1 -0
  551. package/dist/frontend/lowering/union-retag.test.js +405 -0
  552. package/dist/frontend/lowering/union-retag.test.js.map +1 -0
  553. package/dist/frontend/lowering/unregistered-class-types.d.ts +14 -0
  554. package/dist/frontend/lowering/unregistered-class-types.js +94 -0
  555. package/dist/frontend/lowering/unregistered-class-types.js.map +1 -0
  556. package/dist/frontend/lowering/unregistered-class-types.test.d.ts +1 -0
  557. package/dist/frontend/lowering/unregistered-class-types.test.js +65 -0
  558. package/dist/frontend/lowering/unregistered-class-types.test.js.map +1 -0
  559. package/dist/frontend/lowering/width-lift.d.ts +40 -0
  560. package/dist/frontend/lowering/width-lift.js +2 -0
  561. package/dist/frontend/lowering/width-lift.js.map +1 -0
  562. package/dist/frontend/module-syntax.d.ts +58 -0
  563. package/dist/frontend/module-syntax.js +123 -0
  564. package/dist/frontend/module-syntax.js.map +1 -0
  565. package/dist/frontend/module-syntax.test.d.ts +1 -0
  566. package/dist/frontend/module-syntax.test.js +78 -0
  567. package/dist/frontend/module-syntax.test.js.map +1 -0
  568. package/dist/frontend/npm-fetch-analysis.d.ts +17 -0
  569. package/dist/frontend/npm-fetch-analysis.js +100 -0
  570. package/dist/frontend/npm-fetch-analysis.js.map +1 -0
  571. package/dist/frontend/npm-fetch-analysis.test.d.ts +1 -0
  572. package/dist/frontend/npm-fetch-analysis.test.js +107 -0
  573. package/dist/frontend/npm-fetch-analysis.test.js.map +1 -0
  574. package/dist/frontend/npm-fetch-node.d.ts +2 -0
  575. package/dist/frontend/npm-fetch-node.js +12 -0
  576. package/dist/frontend/npm-fetch-node.js.map +1 -0
  577. package/dist/frontend/npm-fetch-syntax.d.ts +6 -0
  578. package/dist/frontend/npm-fetch-syntax.js +207 -0
  579. package/dist/frontend/npm-fetch-syntax.js.map +1 -0
  580. package/dist/frontend/npm-node.d.ts +10 -0
  581. package/dist/frontend/npm-node.js +14 -0
  582. package/dist/frontend/npm-node.js.map +1 -0
  583. package/dist/frontend/npm-static-bundled-cjs.d.ts +8 -0
  584. package/dist/frontend/npm-static-bundled-cjs.js +236 -0
  585. package/dist/frontend/npm-static-bundled-cjs.js.map +1 -0
  586. package/dist/frontend/npm-static-bundled-cjs.test.d.ts +1 -0
  587. package/dist/frontend/npm-static-bundled-cjs.test.js +69 -0
  588. package/dist/frontend/npm-static-bundled-cjs.test.js.map +1 -0
  589. package/dist/frontend/npm-static-declaration-syntax.d.ts +57 -0
  590. package/dist/frontend/npm-static-declaration-syntax.js +944 -0
  591. package/dist/frontend/npm-static-declaration-syntax.js.map +1 -0
  592. package/dist/frontend/npm-static-declarations.d.ts +11 -39
  593. package/dist/frontend/npm-static-declarations.js +22 -561
  594. package/dist/frontend/npm-static-declarations.js.map +1 -1
  595. package/dist/frontend/npm-static-declarations.test.js +245 -6
  596. package/dist/frontend/npm-static-declarations.test.js.map +1 -1
  597. package/dist/frontend/npm-static-prune.d.ts +1 -1
  598. package/dist/frontend/npm-static-prune.js +5 -4
  599. package/dist/frontend/npm-static-prune.js.map +1 -1
  600. package/dist/frontend/npm-static-prune.test.js +1 -1
  601. package/dist/frontend/npm-static-prune.test.js.map +1 -1
  602. package/dist/frontend/npm-static-rewrite-host.d.ts +4 -0
  603. package/dist/frontend/npm-static-rewrite-host.js +179 -0
  604. package/dist/frontend/npm-static-rewrite-host.js.map +1 -0
  605. package/dist/frontend/npm-static-rewrite-syntax.d.ts +16 -0
  606. package/dist/frontend/npm-static-rewrite-syntax.js +905 -0
  607. package/dist/frontend/npm-static-rewrite-syntax.js.map +1 -0
  608. package/dist/frontend/npm-static-rewrite.d.ts +0 -5
  609. package/dist/frontend/npm-static-rewrite.js +2 -1079
  610. package/dist/frontend/npm-static-rewrite.js.map +1 -1
  611. package/dist/frontend/npm-static-subtyping.d.ts +5 -0
  612. package/dist/frontend/npm-static-subtyping.js +55 -0
  613. package/dist/frontend/npm-static-subtyping.js.map +1 -0
  614. package/dist/frontend/npm-static-subtyping.test.d.ts +1 -0
  615. package/dist/frontend/npm-static-subtyping.test.js +58 -0
  616. package/dist/frontend/npm-static-subtyping.test.js.map +1 -0
  617. package/dist/frontend/npm-static.d.ts +7 -15
  618. package/dist/frontend/npm-static.js +19 -28
  619. package/dist/frontend/npm-static.js.map +1 -1
  620. package/dist/frontend/npm.d.ts +8 -69
  621. package/dist/frontend/npm.js +21 -361
  622. package/dist/frontend/npm.js.map +1 -1
  623. package/dist/frontend/npm.test.js +2 -2
  624. package/dist/frontend/npm.test.js.map +1 -1
  625. package/dist/frontend/pipeline-native.d.ts +6 -0
  626. package/dist/frontend/pipeline-native.js +32 -0
  627. package/dist/frontend/pipeline-native.js.map +1 -0
  628. package/dist/frontend/pipeline.d.ts +54 -0
  629. package/dist/frontend/pipeline.js +382 -0
  630. package/dist/frontend/pipeline.js.map +1 -0
  631. package/dist/frontend/pipeline.test.d.ts +1 -0
  632. package/dist/frontend/pipeline.test.js +77 -0
  633. package/dist/frontend/pipeline.test.js.map +1 -0
  634. package/dist/frontend/program-analysis.d.ts +10 -0
  635. package/dist/frontend/program-analysis.js +14 -0
  636. package/dist/frontend/program-analysis.js.map +1 -0
  637. package/dist/frontend/program-node.d.ts +9 -0
  638. package/dist/frontend/program-node.js +48 -0
  639. package/dist/frontend/program-node.js.map +1 -0
  640. package/dist/frontend/program.d.ts +38 -19
  641. package/dist/frontend/program.js +344 -169
  642. package/dist/frontend/program.js.map +1 -1
  643. package/dist/frontend/program.test.js +87 -2
  644. package/dist/frontend/program.test.js.map +1 -1
  645. package/dist/frontend/provenance-core.d.ts +9 -0
  646. package/dist/frontend/provenance-core.js +435 -0
  647. package/dist/frontend/provenance-core.js.map +1 -0
  648. package/dist/frontend/provenance.d.ts +0 -4
  649. package/dist/frontend/provenance.js +4 -459
  650. package/dist/frontend/provenance.js.map +1 -1
  651. package/dist/frontend/resolve.d.ts +3 -1
  652. package/dist/frontend/resolve.js +6 -3
  653. package/dist/frontend/resolve.js.map +1 -1
  654. package/dist/frontend/runtime-resolve.d.ts +4 -3
  655. package/dist/frontend/runtime-resolve.js +22 -18
  656. package/dist/frontend/runtime-resolve.js.map +1 -1
  657. package/dist/frontend/runtime-resolve.test.js +53 -0
  658. package/dist/frontend/runtime-resolve.test.js.map +1 -1
  659. package/dist/frontend/services-node.d.ts +5 -0
  660. package/dist/frontend/services-node.js +19 -0
  661. package/dist/frontend/services-node.js.map +1 -0
  662. package/dist/frontend/services-node.test.d.ts +1 -0
  663. package/dist/frontend/services-node.test.js +70 -0
  664. package/dist/frontend/services-node.test.js.map +1 -0
  665. package/dist/frontend/services.d.ts +44 -0
  666. package/dist/frontend/services.js +90 -0
  667. package/dist/frontend/services.js.map +1 -0
  668. package/dist/frontend/services.test.d.ts +1 -0
  669. package/dist/frontend/services.test.js +174 -0
  670. package/dist/frontend/services.test.js.map +1 -0
  671. package/dist/frontend/ts7/adapter.d.ts +3 -3
  672. package/dist/frontend/ts7/adapter.js +14 -31
  673. package/dist/frontend/ts7/adapter.js.map +1 -1
  674. package/dist/frontend/ts7/api.d.ts +16 -0
  675. package/dist/frontend/ts7/api.js +24 -0
  676. package/dist/frontend/ts7/api.js.map +1 -0
  677. package/dist/frontend/ts7/ast-bytes.d.ts +31 -0
  678. package/dist/frontend/ts7/ast-bytes.js +137 -0
  679. package/dist/frontend/ts7/ast-bytes.js.map +1 -0
  680. package/dist/frontend/ts7/ast-bytes.test.d.ts +1 -0
  681. package/dist/frontend/ts7/ast-bytes.test.js +73 -0
  682. package/dist/frontend/ts7/ast-bytes.test.js.map +1 -0
  683. package/dist/frontend/ts7/ast-guards.generated.d.ts +353 -0
  684. package/dist/frontend/ts7/ast-guards.generated.js +1951 -0
  685. package/dist/frontend/ts7/ast-guards.generated.js.map +1 -0
  686. package/dist/frontend/ts7/ast-guards.test.d.ts +1 -0
  687. package/dist/frontend/ts7/ast-guards.test.js +43 -0
  688. package/dist/frontend/ts7/ast-guards.test.js.map +1 -0
  689. package/dist/frontend/ts7/ast-node.d.ts +194 -0
  690. package/dist/frontend/ts7/ast-node.js +448 -0
  691. package/dist/frontend/ts7/ast-node.js.map +1 -0
  692. package/dist/frontend/ts7/ast-node.test.d.ts +1 -0
  693. package/dist/frontend/ts7/ast-node.test.js +266 -0
  694. package/dist/frontend/ts7/ast-node.test.js.map +1 -0
  695. package/dist/frontend/ts7/ast-schema.generated.d.ts +503 -0
  696. package/dist/frontend/ts7/ast-schema.generated.js +1446 -0
  697. package/dist/frontend/ts7/ast-schema.generated.js.map +1 -0
  698. package/dist/frontend/ts7/ast-text.d.ts +6 -0
  699. package/dist/frontend/ts7/ast-text.js +124 -0
  700. package/dist/frontend/ts7/ast-text.js.map +1 -0
  701. package/dist/frontend/ts7/ast-text.test.d.ts +1 -0
  702. package/dist/frontend/ts7/ast-text.test.js +38 -0
  703. package/dist/frontend/ts7/ast-text.test.js.map +1 -0
  704. package/dist/frontend/ts7/ast-tokens.generated.d.ts +2 -0
  705. package/dist/frontend/ts7/ast-tokens.generated.js +155 -0
  706. package/dist/frontend/ts7/ast-tokens.generated.js.map +1 -0
  707. package/dist/frontend/ts7/ast-types.d.ts +42 -0
  708. package/dist/frontend/ts7/ast-types.generated.d.ts +1615 -0
  709. package/dist/frontend/ts7/ast-types.generated.js +5 -0
  710. package/dist/frontend/ts7/ast-types.generated.js.map +1 -0
  711. package/dist/frontend/ts7/ast-types.js +3 -0
  712. package/dist/frontend/ts7/ast-types.js.map +1 -0
  713. package/dist/frontend/ts7/ast-wire.d.ts +58 -0
  714. package/dist/frontend/ts7/ast-wire.js +267 -0
  715. package/dist/frontend/ts7/ast-wire.js.map +1 -0
  716. package/dist/frontend/ts7/ast-wire.test.d.ts +1 -0
  717. package/dist/frontend/ts7/ast-wire.test.js +151 -0
  718. package/dist/frontend/ts7/ast-wire.test.js.map +1 -0
  719. package/dist/frontend/ts7/ast.d.ts +14 -14
  720. package/dist/frontend/ts7/ast.js +21 -15
  721. package/dist/frontend/ts7/ast.js.map +1 -1
  722. package/dist/frontend/ts7/census-check.js +1 -0
  723. package/dist/frontend/ts7/census-check.js.map +1 -1
  724. package/dist/frontend/ts7/checker-cache.d.ts +48 -0
  725. package/dist/frontend/ts7/checker-cache.js +92 -0
  726. package/dist/frontend/ts7/checker-cache.js.map +1 -0
  727. package/dist/frontend/ts7/checker.d.ts +19 -46
  728. package/dist/frontend/ts7/checker.js +231 -161
  729. package/dist/frontend/ts7/checker.js.map +1 -1
  730. package/dist/frontend/ts7/checker.test.d.ts +1 -0
  731. package/dist/frontend/ts7/checker.test.js +335 -0
  732. package/dist/frontend/ts7/checker.test.js.map +1 -0
  733. package/dist/frontend/ts7/enums.d.ts +4 -27
  734. package/dist/frontend/ts7/enums.generated.d.ts +878 -0
  735. package/dist/frontend/ts7/enums.generated.js +1313 -0
  736. package/dist/frontend/ts7/enums.generated.js.map +1 -0
  737. package/dist/frontend/ts7/enums.js +4 -45
  738. package/dist/frontend/ts7/enums.js.map +1 -1
  739. package/dist/frontend/ts7/enums.test.d.ts +1 -0
  740. package/dist/frontend/ts7/enums.test.js +48 -0
  741. package/dist/frontend/ts7/enums.test.js.map +1 -0
  742. package/dist/frontend/ts7/native-api.d.ts +10 -0
  743. package/dist/frontend/ts7/native-api.js +10 -0
  744. package/dist/frontend/ts7/native-api.js.map +1 -0
  745. package/dist/frontend/ts7/native-host.d.ts +2 -0
  746. package/dist/frontend/ts7/native-host.js +11 -0
  747. package/dist/frontend/ts7/native-host.js.map +1 -0
  748. package/dist/frontend/ts7/native-process.d.ts +14 -0
  749. package/dist/frontend/ts7/native-process.js +62 -0
  750. package/dist/frontend/ts7/native-process.js.map +1 -0
  751. package/dist/frontend/ts7/program-adapter.d.ts +10 -98
  752. package/dist/frontend/ts7/program-adapter.js +16 -310
  753. package/dist/frontend/ts7/program-adapter.js.map +1 -1
  754. package/dist/frontend/ts7/program-host.d.ts +115 -0
  755. package/dist/frontend/ts7/program-host.js +347 -0
  756. package/dist/frontend/ts7/program-host.js.map +1 -0
  757. package/dist/frontend/ts7/program-host.test.d.ts +1 -0
  758. package/dist/frontend/ts7/program-host.test.js +207 -0
  759. package/dist/frontend/ts7/program-host.test.js.map +1 -0
  760. package/dist/frontend/ts7/rpc-api.d.ts +12 -0
  761. package/dist/frontend/ts7/rpc-api.js +23 -0
  762. package/dist/frontend/ts7/rpc-api.js.map +1 -0
  763. package/dist/frontend/ts7/rpc-client.d.ts +27 -0
  764. package/dist/frontend/ts7/rpc-client.js +102 -0
  765. package/dist/frontend/ts7/rpc-client.js.map +1 -0
  766. package/dist/frontend/ts7/rpc-client.test.d.ts +1 -0
  767. package/dist/frontend/ts7/rpc-client.test.js +133 -0
  768. package/dist/frontend/ts7/rpc-client.test.js.map +1 -0
  769. package/dist/frontend/ts7/rpc-filesystem.d.ts +16 -0
  770. package/dist/frontend/ts7/rpc-filesystem.js +42 -0
  771. package/dist/frontend/ts7/rpc-filesystem.js.map +1 -0
  772. package/dist/frontend/ts7/rpc-filesystem.test.d.ts +1 -0
  773. package/dist/frontend/ts7/rpc-filesystem.test.js +89 -0
  774. package/dist/frontend/ts7/rpc-filesystem.test.js.map +1 -0
  775. package/dist/frontend/ts7/rpc-process.d.ts +2 -0
  776. package/dist/frontend/ts7/rpc-process.js +148 -0
  777. package/dist/frontend/ts7/rpc-process.js.map +1 -0
  778. package/dist/frontend/ts7/rpc-process.test.d.ts +1 -0
  779. package/dist/frontend/ts7/rpc-process.test.js +29 -0
  780. package/dist/frontend/ts7/rpc-process.test.js.map +1 -0
  781. package/dist/frontend/ts7/rpc-wire.d.ts +46 -0
  782. package/dist/frontend/ts7/rpc-wire.js +195 -0
  783. package/dist/frontend/ts7/rpc-wire.js.map +1 -0
  784. package/dist/frontend/ts7/rpc-wire.test.d.ts +1 -0
  785. package/dist/frontend/ts7/rpc-wire.test.js +168 -0
  786. package/dist/frontend/ts7/rpc-wire.test.js.map +1 -0
  787. package/dist/frontend/ts7/semantic-checker.d.ts +137 -0
  788. package/dist/frontend/ts7/semantic-checker.js +221 -0
  789. package/dist/frontend/ts7/semantic-checker.js.map +1 -0
  790. package/dist/frontend/ts7/semantic-checker.test.d.ts +1 -0
  791. package/dist/frontend/ts7/semantic-checker.test.js +119 -0
  792. package/dist/frontend/ts7/semantic-checker.test.js.map +1 -0
  793. package/dist/frontend/ts7/semantic-json.d.ts +5 -0
  794. package/dist/frontend/ts7/semantic-json.js +52 -0
  795. package/dist/frontend/ts7/semantic-json.js.map +1 -0
  796. package/dist/frontend/ts7/semantic-json.test.d.ts +1 -0
  797. package/dist/frontend/ts7/semantic-json.test.js +42 -0
  798. package/dist/frontend/ts7/semantic-json.test.js.map +1 -0
  799. package/dist/frontend/ts7/semantic-model.d.ts +222 -0
  800. package/dist/frontend/ts7/semantic-model.js +423 -0
  801. package/dist/frontend/ts7/semantic-model.js.map +1 -0
  802. package/dist/frontend/ts7/semantic-model.test.d.ts +1 -0
  803. package/dist/frontend/ts7/semantic-model.test.js +322 -0
  804. package/dist/frontend/ts7/semantic-model.test.js.map +1 -0
  805. package/dist/frontend/ts7/semantic-schema.generated.d.ts +283 -0
  806. package/dist/frontend/ts7/semantic-schema.generated.js +222 -0
  807. package/dist/frontend/ts7/semantic-schema.generated.js.map +1 -0
  808. package/dist/frontend/ts7/semantic-types.d.ts +5 -0
  809. package/dist/frontend/ts7/semantic-types.js +2 -0
  810. package/dist/frontend/ts7/semantic-types.js.map +1 -0
  811. package/dist/frontend/ts7/session-cache.d.ts +17 -0
  812. package/dist/frontend/ts7/session-cache.js +97 -0
  813. package/dist/frontend/ts7/session-cache.js.map +1 -0
  814. package/dist/frontend/ts7/session-cache.test.d.ts +1 -0
  815. package/dist/frontend/ts7/session-cache.test.js +87 -0
  816. package/dist/frontend/ts7/session-cache.test.js.map +1 -0
  817. package/dist/frontend/ts7/session-path.d.ts +18 -0
  818. package/dist/frontend/ts7/session-path.js +203 -0
  819. package/dist/frontend/ts7/session-path.js.map +1 -0
  820. package/dist/frontend/ts7/session-path.test.d.ts +1 -0
  821. package/dist/frontend/ts7/session-path.test.js +34 -0
  822. package/dist/frontend/ts7/session-path.test.js.map +1 -0
  823. package/dist/frontend/ts7/session-schema.generated.d.ts +167 -0
  824. package/dist/frontend/ts7/session-schema.generated.js +5 -0
  825. package/dist/frontend/ts7/session-schema.generated.js.map +1 -0
  826. package/dist/frontend/ts7/session-timing.d.ts +50 -0
  827. package/dist/frontend/ts7/session-timing.js +61 -0
  828. package/dist/frontend/ts7/session-timing.js.map +1 -0
  829. package/dist/frontend/ts7/session-timing.test.d.ts +1 -0
  830. package/dist/frontend/ts7/session-timing.test.js +52 -0
  831. package/dist/frontend/ts7/session-timing.test.js.map +1 -0
  832. package/dist/frontend/ts7/session.d.ts +105 -0
  833. package/dist/frontend/ts7/session.js +233 -0
  834. package/dist/frontend/ts7/session.js.map +1 -0
  835. package/dist/frontend/ts7/session.test.d.ts +1 -0
  836. package/dist/frontend/ts7/session.test.js +215 -0
  837. package/dist/frontend/ts7/session.test.js.map +1 -0
  838. package/dist/frontend/ts7/source-parser-node.d.ts +6 -0
  839. package/dist/frontend/ts7/source-parser-node.js +15 -0
  840. package/dist/frontend/ts7/source-parser-node.js.map +1 -0
  841. package/dist/frontend/ts7/source-parser.d.ts +25 -0
  842. package/dist/frontend/ts7/source-parser.js +96 -0
  843. package/dist/frontend/ts7/source-parser.js.map +1 -0
  844. package/dist/frontend/ts7/source-parser.test.d.ts +1 -0
  845. package/dist/frontend/ts7/source-parser.test.js +151 -0
  846. package/dist/frontend/ts7/source-parser.test.js.map +1 -0
  847. package/dist/frontend/ts7/syntax.d.ts +3 -0
  848. package/dist/frontend/ts7/syntax.js +4 -0
  849. package/dist/frontend/ts7/syntax.js.map +1 -0
  850. package/dist/frontend/tsc-codes.js +3 -0
  851. package/dist/frontend/tsc-codes.js.map +1 -1
  852. package/dist/frontend/type-mapper.d.ts +25 -17
  853. package/dist/frontend/type-mapper.js +465 -121
  854. package/dist/frontend/type-mapper.js.map +1 -1
  855. package/dist/frontend/type-mapper.test.js +123 -2
  856. package/dist/frontend/type-mapper.test.js.map +1 -1
  857. package/dist/frontend/union-discriminants.d.ts +16 -0
  858. package/dist/frontend/union-discriminants.js +98 -0
  859. package/dist/frontend/union-discriminants.js.map +1 -0
  860. package/dist/frontend/union-discriminants.test.d.ts +1 -0
  861. package/dist/frontend/union-discriminants.test.js +182 -0
  862. package/dist/frontend/union-discriminants.test.js.map +1 -0
  863. package/dist/index.d.ts +7 -198
  864. package/dist/index.js +369 -1572
  865. package/dist/index.js.map +1 -1
  866. package/dist/ir/analysis.d.ts +16 -4
  867. package/dist/ir/analysis.js +21 -4
  868. package/dist/ir/analysis.js.map +1 -1
  869. package/dist/ir/analysis.test.js +15 -2
  870. package/dist/ir/analysis.test.js.map +1 -1
  871. package/dist/ir/constant-tables.js +67 -49
  872. package/dist/ir/constant-tables.js.map +1 -1
  873. package/dist/ir/constant-tables.test.js +1 -1
  874. package/dist/ir/control-flow.d.ts +6 -0
  875. package/dist/ir/control-flow.js +142 -0
  876. package/dist/ir/control-flow.js.map +1 -0
  877. package/dist/ir/control-flow.test.d.ts +1 -0
  878. package/dist/ir/control-flow.test.js +113 -0
  879. package/dist/ir/control-flow.test.js.map +1 -0
  880. package/dist/ir/integer-loops.js +7 -18
  881. package/dist/ir/integer-loops.js.map +1 -1
  882. package/dist/ir/integer-ranges.js +53 -27
  883. package/dist/ir/integer-ranges.js.map +1 -1
  884. package/dist/ir/ir.d.ts +291 -152
  885. package/dist/ir/ir.js +588 -881
  886. package/dist/ir/ir.js.map +1 -1
  887. package/dist/ir/ir.test.js +127 -1
  888. package/dist/ir/ir.test.js.map +1 -1
  889. package/dist/ir/scalar-records.js +165 -134
  890. package/dist/ir/scalar-records.js.map +1 -1
  891. package/dist/ir/scalar-records.test.js +1 -1
  892. package/dist/ir/serialize.d.ts +4 -2
  893. package/dist/ir/serialize.js +19 -12
  894. package/dist/ir/serialize.js.map +1 -1
  895. package/dist/ir/serialize.test.d.ts +1 -0
  896. package/dist/ir/serialize.test.js +53 -0
  897. package/dist/ir/serialize.test.js.map +1 -0
  898. package/dist/ir/traverse.d.ts +41 -0
  899. package/dist/ir/traverse.js +660 -0
  900. package/dist/ir/traverse.js.map +1 -0
  901. package/dist/ir/traverse.test.d.ts +1 -0
  902. package/dist/ir/traverse.test.js +242 -0
  903. package/dist/ir/traverse.test.js.map +1 -0
  904. package/dist/ir/validate.js +1942 -1491
  905. package/dist/ir/validate.js.map +1 -1
  906. package/dist/ir/validate.test.js +476 -2
  907. package/dist/ir/validate.test.js.map +1 -1
  908. package/dist/library/cache-primitives.d.ts +2 -3
  909. package/dist/library/cache-primitives.js +4 -6
  910. package/dist/library/cache-primitives.js.map +1 -1
  911. package/dist/library/fence-eval.js +2 -2
  912. package/dist/library/fence-eval.js.map +1 -1
  913. package/dist/library/int-infer.js +7 -6
  914. package/dist/library/int-infer.js.map +1 -1
  915. package/dist/library/int-infer.test.js +4 -4
  916. package/dist/library/library-cache.d.ts +3 -2
  917. package/dist/library/library-cache.js +5 -17
  918. package/dist/library/library-cache.js.map +1 -1
  919. package/dist/library/library-cache.test.js +54 -41
  920. package/dist/library/library-cache.test.js.map +1 -1
  921. package/dist/library/library-profile.d.ts +3 -1
  922. package/dist/library/library-profile.js +15 -6
  923. package/dist/library/library-profile.js.map +1 -1
  924. package/dist/library/prepare.d.ts +15 -0
  925. package/dist/library/prepare.js +584 -0
  926. package/dist/library/prepare.js.map +1 -0
  927. package/dist/library/semantic-source.d.ts +1 -1
  928. package/dist/library/semantic-source.js +8 -6
  929. package/dist/library/semantic-source.js.map +1 -1
  930. package/dist/library/sidecar-validate.js +4 -4
  931. package/dist/library/sidecar-validate.js.map +1 -1
  932. package/dist/library/sidecar.d.ts +2 -0
  933. package/dist/library/sidecar.js +10 -3
  934. package/dist/library/sidecar.js.map +1 -1
  935. package/dist/native/cache.d.ts +11 -0
  936. package/dist/native/cache.js +113 -0
  937. package/dist/native/cache.js.map +1 -0
  938. package/dist/native/cache.test.d.ts +1 -0
  939. package/dist/native/cache.test.js +66 -0
  940. package/dist/native/cache.test.js.map +1 -0
  941. package/dist/native/cli.d.ts +1 -0
  942. package/dist/native/cli.js +112 -0
  943. package/dist/native/cli.js.map +1 -0
  944. package/dist/native/compiler.d.ts +15 -0
  945. package/dist/native/compiler.js +336 -0
  946. package/dist/native/compiler.js.map +1 -0
  947. package/dist/native/compiler.test.d.ts +1 -0
  948. package/dist/native/compiler.test.js +174 -0
  949. package/dist/native/compiler.test.js.map +1 -0
  950. package/dist/native/comptime.d.ts +5 -0
  951. package/dist/native/comptime.js +73 -0
  952. package/dist/native/comptime.js.map +1 -0
  953. package/dist/native/comptime.test.d.ts +1 -0
  954. package/dist/native/comptime.test.js +65 -0
  955. package/dist/native/comptime.test.js.map +1 -0
  956. package/dist/native/executable-cache.d.ts +26 -0
  957. package/dist/native/executable-cache.js +228 -0
  958. package/dist/native/executable-cache.js.map +1 -0
  959. package/dist/native/executable-cache.test.d.ts +1 -0
  960. package/dist/native/executable-cache.test.js +151 -0
  961. package/dist/native/executable-cache.test.js.map +1 -0
  962. package/dist/native/file-identity.d.ts +4 -0
  963. package/dist/native/file-identity.js +14 -0
  964. package/dist/native/file-identity.js.map +1 -0
  965. package/dist/native/file-identity.test.d.ts +1 -0
  966. package/dist/native/file-identity.test.js +43 -0
  967. package/dist/native/file-identity.test.js.map +1 -0
  968. package/dist/native/library.d.ts +22 -0
  969. package/dist/native/library.js +83 -0
  970. package/dist/native/library.js.map +1 -0
  971. package/dist/native/prepare.d.ts +21 -0
  972. package/dist/native/prepare.js +174 -0
  973. package/dist/native/prepare.js.map +1 -0
  974. package/dist/native/prepare.test.d.ts +1 -0
  975. package/dist/native/prepare.test.js +70 -0
  976. package/dist/native/prepare.test.js.map +1 -0
  977. package/dist/native/sanitizer.d.ts +11 -0
  978. package/dist/native/sanitizer.js +135 -0
  979. package/dist/native/sanitizer.js.map +1 -0
  980. package/dist/native/sanitizer.test.d.ts +1 -0
  981. package/dist/native/sanitizer.test.js +58 -0
  982. package/dist/native/sanitizer.test.js.map +1 -0
  983. package/dist/native/task.d.ts +4 -0
  984. package/dist/native/task.js +16 -0
  985. package/dist/native/task.js.map +1 -0
  986. package/dist/native/task.test.d.ts +1 -0
  987. package/dist/native/task.test.js +17 -0
  988. package/dist/native/task.test.js.map +1 -0
  989. package/dist/native/toolchain.d.ts +45 -0
  990. package/dist/native/toolchain.js +74 -0
  991. package/dist/native/toolchain.js.map +1 -0
  992. package/dist/native/toolchain.test.d.ts +1 -0
  993. package/dist/native/toolchain.test.js +33 -0
  994. package/dist/native/toolchain.test.js.map +1 -0
  995. package/dist/startup-cache.d.ts +1 -1
  996. package/dist/startup-cache.js +2 -5
  997. package/dist/startup-cache.js.map +1 -1
  998. package/dist/timing.d.ts +4 -0
  999. package/dist/timing.js +19 -0
  1000. package/dist/timing.js.map +1 -0
  1001. package/dist/wasi-paths.js +10 -7
  1002. package/dist/wasi-paths.js.map +1 -1
  1003. package/package.json +28 -19
  1004. package/surface-manifest.json +52 -18
  1005. package/dist/backend/c/async.d.ts +0 -171
  1006. package/dist/backend/c/async.js +0 -1317
  1007. package/dist/backend/c/async.js.map +0 -1
  1008. package/dist/backend/c/c-emitter.d.ts +0 -536
  1009. package/dist/backend/c/c-emitter.js +0 -1932
  1010. package/dist/backend/c/c-emitter.js.map +0 -1
  1011. package/dist/backend/c/exprs.d.ts +0 -15
  1012. package/dist/backend/c/exprs.js +0 -8847
  1013. package/dist/backend/c/exprs.js.map +0 -1
  1014. package/dist/backend/c/island.d.ts +0 -45
  1015. package/dist/backend/c/island.js +0 -281
  1016. package/dist/backend/c/island.js.map +0 -1
  1017. package/dist/backend/c/may-throw.js.map +0 -1
  1018. package/dist/backend/c/shapes.d.ts +0 -142
  1019. package/dist/backend/c/shapes.js +0 -603
  1020. package/dist/backend/c/shapes.js.map +0 -1
  1021. package/dist/backend/c/stmts.d.ts +0 -76
  1022. package/dist/backend/c/stmts.js +0 -1108
  1023. package/dist/backend/c/stmts.js.map +0 -1
  1024. package/dist/backend/c/types.d.ts +0 -71
  1025. package/dist/backend/c/types.js +0 -459
  1026. package/dist/backend/c/types.js.map +0 -1
  1027. package/dist/backend/c/types.test.js +0 -32
  1028. package/dist/backend/c/types.test.js.map +0 -1
  1029. package/dist/backend/c/walkers.d.ts +0 -134
  1030. package/dist/backend/c/walkers.js +0 -1772
  1031. package/dist/backend/c/walkers.js.map +0 -1
  1032. /package/dist/backend/{c/types.test.d.ts → cycle-analysis.test.d.ts} +0 -0
@@ -1,4 +1,15 @@
1
+ import { everyExprChild, everyStmtChild } from "../../ir/traverse.js";
2
+ import { RuntimeOptionalLocals } from "./runtime-optional-locals.js";
3
+ import { sanitizeUnregisteredClassTypes } from "./sanitize-class-types.js";
4
+ import { UnregisteredClassTypes } from "./unregistered-class-types.js";
5
+ import { buildUnionNarrow } from "./union-narrow.js";
6
+ import { planUnionRetag, buildUnionRetag, planRecordUnionWrap, buildRecordUnionWrap } from "./union-retag.js";
7
+ import { bindingInContext, captureContextBinding, declareContextLocal, declareContextThis } from "./function-context.js";
8
+ export { newFnCtx } from "./function-context.js";
1
9
  import { InternalCompilerError } from "../../errors.js";
10
+ import { defaultAfterUndefined, lowerStaticallyUndefinedArgument } from "./optional-arguments.js";
11
+ import { ClassDynamicDispatch } from "./class-dynamic-dispatch.js";
12
+ import { finalizeClassMethodValues } from "./class-method-values.js";
2
13
  /* AST + checker → IR.
3
14
  *
4
15
  * Invariants:
@@ -17,23 +28,28 @@ import { resolve } from "node:path";
17
28
  import { bindingSource } from "../binding-source.js";
18
29
  import { tsgoPath } from "../dts-paths.js";
19
30
  import * as ts from "../ts7/adapter.js";
20
- import { anyOpRequiresDynamicDiag, blockedBindingUseDiag, checkerPanicDiag, componentTypeDiag, isCheckerPanic, genericSignatureTypeDiag, indexSignatureTypeDiag, intersectionTypeDiag, noLoweringDiag, overloadedSignatureTypeDiag, recordShapeMismatchDiag, requiresDynamicApiDiag, requiresDynamicPackageDiag, requiresDynamicTypeDiag, unionMismatchDiag, unsupportedDiag, unsupportedTypeDiag, } from "../../diagnostics/diagnostic.js";
21
- import { arrayOf, BOOL, canAdaptDynFuncTo, canConvertToDyn, canCrossIslandBoundary, canExitIslandToType, canMarshalTypedFuncIntoIsland, DYN, DYN_HANDLE_KINDS, F64, isDynTypedRefType, isJsonSafeType, isJsonStringifySafeType, isUndefinedArmedUnion, isUnitType, JSVAL, NULL_T, RUNTIME_ERROR_CLASSES, STRING, typeEquals, UNDEFINED_T, VOID } from "../../ir/ir.js";
31
+ import { literalValues } from "../literal-values.js";
32
+ import { literalUnionArm } from "../union-discriminants.js";
33
+ import { anyOpRequiresDynamicDiag, blockedBindingUseDiag, checkerPanicDiag, componentTypeDiag, isCheckerPanic, genericSignatureTypeDiag, indexSignatureTypeDiag, intersectionTypeDiag, noLoweringDiag, overloadedSignatureTypeDiag, recordShapeMismatchDiag, requiresDynamicApiDiag, requiresDynamicPackageDiag, requiresDynamicTypeDiag, unionMismatchDiag, UNSUPPORTED, unsupportedDiag, unsupportedTypeDiag, } from "../../diagnostics/diagnostic.js";
34
+ import { arrayOf, BOOL, canAdaptDynFuncTo, canDynCheckTo, canConvertToDyn, canCrossIslandBoundary, canExitIslandToType, canMarshalTypedFuncIntoIsland, DYN, DYN_HANDLE_KINDS, F64, isDynTypedRefType, isJsonSafeType, isJsonStringifySafeType, isSupportedMapKey, isSupportedMapValue, isUndefinedArmedUnion, isUnitType, JSVAL, NULL_T, RUNTIME_ERROR_CLASSES, STRING, typeEquals, UNDEFINED_T, VOID } from "../../ir/ir.js";
35
+ import {} from "../npm.js";
22
36
  import { provenanceActive } from "../provenance-registry.js";
23
37
  import { ambientDtsPath, canonicalBuiltinModule, cjsExportAssignmentOf, cjsExportDiscardReason, fallbackDtsPath, isCjsExportTableLiteral, isCjsJsFile, isJsSourceFile, isNodeEsmFile, isNodeTypesPath, locOf, orderedImportsOf, overridesDtsPath, npmStaticDepSf7, requireSpecOf, resolveImport, workspacePackageOfPath, } from "../program.js";
24
- import { containsRecord, containsUnion, describeComponentBlocker, describeRecordMemberBlocker, formatIrType, ISLAND_AMBIENT_TYPES, isUnitOnlyTsType, mapType, ShapeRegistry, typeKey, UnionRegistry, withUndefinedArm as withUndefinedArmCanonical, } from "../type-mapper.js";
38
+ import { containsRecord, containsUnion, describeComponentBlocker, describeRecordMemberBlocker, formatIrType, ISLAND_AMBIENT_TYPES, isUnitOnlyTsType, jsOpenObjectType, mapType, ShapeRegistry, typeKey, UnionRegistry, withUndefinedArm as withUndefinedArmCanonical, } from "../type-mapper.js";
25
39
  import { boundaryIntoIslandMsg, boundaryOutOfIslandMsg, builtinConstLit, builtinModuleConstOf, builtinModulesArrayLit, builtinFenceHintOf, builtinModuleFnOf, stdlibMemberFence, isStdlibMember, isStdlibSymbol, isStdlibGlobal, stdlibGlobalMember, nodeTypesOnlySymbol } from "./surfaces.js";
26
40
  import { splitFiles, collectProgram, collectNpmImports, collectJsonImports, moduleArtifacts, collectGlobals, declSymbolOf, defaultExportSymbolOf, lowerFileInit, lowerDefaultExport, buildMain, appendDynamicImportModules, appendForkModules } from "./lower-modules.js";
27
41
  import { prepareCjsModuleGraph } from "./lower-node-module.js";
28
- import { registerBuiltinErrorClasses, registerBuiltinEmitterClass, registerBuiltinStreamClasses, builtinErrorInfoOf, builtinEmitterInfoOf, builtinStreamInfoOf, analyzeClassDecoration, classIteratorDrainCall, classIteratorNextCall, classIteratorOf, classIteratorOpenCall, classIteratorRestDrainCall, classMemberNameOf, classValueRef, collectClassShape, exactClassOfReceiver, collectClassShapeInner, ctorAbiEquals, findMethodOn, findStaticOn, findGenericMethodOn, findGenericStaticOn, genericClassInstanceType, isSubclassOf, inHierarchy, overrideBelow, staticShadowBelow, upcastTo, lowerClassMembers, lowerClassCtor, lowerClassExpression, lowerClassExpressionInfo, lowerClassMethodMember, lowerClassValueProperty, lowerStaticMethod, throwingSetterFn, fieldInitStmts, lowerStaticFieldInits, lowerStaticFieldRead, lowerDerivedCtorBody, superCallStmt, lowerSuperMethodCall, superThisRef, lowerSuperAccessorRead, lowerSuperAccessorWrite, inheritsBuiltinErrorCtor, inheritsBuiltinEmitterCtor, errorMessageArg, lowerNew, accessorCall } from "./lower-classes.js";
42
+ import { registerBuiltinErrorClasses, registerBuiltinEmitterClass, registerBuiltinStreamClasses, builtinErrorInfoOf, builtinEmitterInfoOf, builtinStreamInfoOf, analyzeClassDecoration, classIteratorDrainCall, classIteratorNextCall, classIteratorOf, classIteratorOpenCall, classIteratorRestDrainCall, classMemberNameOf, classValueRef, collectClassShape, exactClassOfReceiver, collectClassShapeInner, ctorAbiEquals, findMethodOn, findStaticOn, findGenericMethodOn, findGenericStaticOn, genericClassInstanceType, isSubclassOf, inHierarchy, overrideBelow, staticShadowBelow, upcastTo, lowerClassMembers, lowerClassCtor, lowerClassExpression, lowerClassExpressionInfo, lowerClassMethodMember, lowerClassValueProperty, lowerStaticMethod, throwingSetterFn, fieldInitStmts, lowerStaticFieldInits, lowerStaticFieldRead, lowerDerivedCtorBody, superCallStmt, lowerSuperMethodCall, superThisRef, lowerSuperAccessorRead, lowerSuperAccessorWrite, inheritsBuiltinErrorCtor, inheritsBuiltinEmitterCtor, errorConstructorArgs, lowerNew, accessorCall } from "./lower-classes.js";
29
43
  import { mixinCallClassInfoOf, mixinIntersectionInstanceType } from "./lower-mixins.js";
44
+ import { implicitAnyParamSymbolsOf } from "./lower-calls.js";
45
+ import { tryLowerExpression } from "./expressions/try-lower-expression.js";
30
46
  import { bindingNeverReassigned, bodyReadsArguments, funcTypeFromParamShapes, implicitMonoFile, isThisParameter, paramShape, paramShapes, checkDefaultParamBodyType, completeArgs, wrappedUndefined, undefinedArgFor, requireExactArityValue, bodyReturnType, declaredReturnType, collectSignature, collectSignatureInner, collectGenericSignature, genericFnOf, lowerGenericCall, lowerGenericFnValue, inferTypeParamBindings, lowerGenericInstance, lowerCall, lowerFfiCall, lowerTimersMemberCall, lowerPromiseMethodCall, lowerFilterNarrowCall, isTopLevelFnSymbol, lowerNestedFunctionDecl, lambdaSignature, lowerLambda, lowerFunction, validateFfiImports } from "./lower-calls.js";
31
47
  import { lowerArrayMethodCall, lowerMapMethodCall, lowerMapForEachCall, buildMapForEachFn, lowerRecordOvfCaptureHelper, lowerEnvToPairsHelper, lowerSetMethodCall, lowerSetForEachCall, buildSetForEachFn } from "./lower-containers.js";
32
48
  import { lowerBufferStaticCall, lowerBytesMethodCall, lowerBytesNew } from "./containers/bytes.js";
33
49
  import { lowerRegexMethodCall, lowerStringMethodCall } from "./containers/string-and-regexp.js";
34
50
  import { lowerStreamModuleCall } from "./lower-stream.js";
35
51
  import { lowerEmitOverrideSpec } from "./lower-event-emitter.js";
36
- import { builtinImportOf, createRequireBindingDecl, createRequireNamespaceDecl, createRequireProgramModuleOf, createRequireSpecOf, stripTypeCasts, lowerBuiltinModuleCall, lowerNodeModuleCall, lowerTimersPromisesSetInterval, lowerFsToUnixTimestampCall, lowerFsLadderCall, lowerChildArgsArg, lowerSpawnSyncCall, lowerSpawnCall, lowerExecFileCall, lowerExecSyncCall, recordToEnvPairs, lowerJsonMethodCall, fencedBuiltinImportOf, lowerCryptoComposedCall, lowerUrlMethodCall, lowerSearchParamsMethodCall, lowerStatsMethodCall, lowerChildMethodCall, lowerAtomicsCall, lowerBuiltinExtraProperty, registerPromisifiedBuiltinDecl, lowerExecFileAsyncCall, execFileAsyncHelper, lowerStringDecoderMethodCall, strdecHelper, lowerReadlineMethodCall, lowerDcChannelMethodCall, lowerDcChannelProperty, lowerAlsMethodCall, lowerDcTracingChannelMethodCall, lowerDcTracingChannelProperty, lowerJsonProperty, lowerErrorCodeProperty, lowerProcessProperty, isProcessEnv, envValueType, lowerProcessEnvGet, lowerProcessMethodCall, lowerProcessOptionalMethodCall, lowerTimeoutMethodCall, envSnapshotHelper, isConsoleLog, consoleCallMember, lowerNumberStaticCall, lowerNumberStaticProperty, lowerDateCall, lowerTextCodecCall, lowerCryptoModuleCall, lowerFsConstantsProperty, lowerBuiltinConstantsProperty, builtinConstantBindingOf, builtinConstantsDestructureDecl, lowerProcessStreamProperty, lowerStringStaticCall, lowerStringLastIndexOfCall, lowerPromiseStaticCall, textCodecBindingClassOf } from "./lower-builtins.js";
52
+ import { builtinImportOf, createRequireBindingDecl, createRequireNamespaceDecl, createRequireProgramModuleOf, createRequireSpecOf, stripTypeCasts, lowerBuiltinModuleCall, lowerNodeModuleCall, lowerTimersPromisesSetInterval, lowerFsToUnixTimestampCall, lowerFsLadderCall, lowerChildArgsArg, lowerSpawnSyncCall, lowerSpawnCall, lowerExecFileCall, lowerExecSyncCall, recordToEnvPairs, lowerJsonMethodCall, fencedBuiltinImportOf, lowerCryptoComposedCall, lowerUrlMethodCall, lowerSearchParamsMethodCall, lowerStatsMethodCall, lowerChildMethodCall, lowerAtomicsCall, lowerBuiltinExtraProperty, registerPromisifiedBuiltinDecl, lowerExecFileAsyncCall, execFileAsyncHelper, lowerStringDecoderMethodCall, strdecHelper, lowerReadlineMethodCall, lowerDcChannelMethodCall, lowerDcChannelProperty, lowerAlsMethodCall, lowerDcTracingChannelMethodCall, lowerDcTracingChannelProperty, lowerJsonProperty, lowerErrorCodeProperty, lowerProcessProperty, isProcessEnv, envValueType, lowerProcessEnvGet, lowerProcessMethodCall, lowerProcessOptionalMethodCall, lowerTimeoutMethodCall, envSnapshotHelper, isConsoleLog, consoleCallMember, lowerNumberStaticCall, lowerNumberStaticProperty, lowerDateCall, lowerTextCodecCall, lowerCryptoModuleCall, lowerFsConstantsProperty, lowerBuiltinConstantsProperty, builtinConstantBindingOf, builtinConstantsDestructureDecl, lowerProcessStreamProperty, lowerStringStaticCall, lowerStringLastIndexOfCall, lowerPromiseStaticCall } from "./lower-builtins.js";
37
53
  import { fenceFetchObjectAssignment, fenceFetchObjectBinding, fenceStaticAbortControllerMemberRead, fenceStaticHeadersIteration, fenceStaticHeadersMember, fenceStaticReadableStreamMember, fenceStaticResponseMember, fenceUnsupportedFetchConstructorMember, isIslandExpr, islandFuncValueFence, islandRegexpOf, jsvalIn, requireDynamicApi, islandGlobalFnOf, lowerAbortControllerNew, lowerDynamicHeadersIteratorCall, lowerDynamicHeadersSpread, lowerDynamicImportCall, lowerFetchCall, lowerFetchElementMethodCall, lowerResponseNew, lowerStaticFetchCompanionCall, lowerStaticAbortControllerCall, lowerStaticAbortSignalListenerCall, lowerStaticReadableStreamCancelCall, lowerStaticReadableStreamControllerCall, lowerStaticReadableStreamNew, lowerStaticReadableStreamReaderCall, lowerStaticResponseCall, lowerIslandMethodCall, lowerMathProperty, npmPackageOf, npmMemberFence, npmPackageOfSymbol } from "./lower-island.js";
38
54
  import { lowerHttpHeadersElement, lowerNetModuleCall, lowerServerMethodCall, lowerServerProperty, lowerTlsRootCertificates } from "./lower-server.js";
39
55
  import { lowerDgramDnsModuleCall, lowerDgramMethodCall } from "./lower-dgram.js";
@@ -49,6 +65,7 @@ import { lowerRecordFieldCall, lowerObjectMethodCall } from "./lower-calls.js";
49
65
  import { fenceCrossBlockNsRef, nsPathPrefix } from "./lower-namespaces.js";
50
66
  import { numLit, varRef } from "../../ir/build.js";
51
67
  import { isSafeToRepeat } from "./expressions/evaluation-safety.js";
68
+ import { lowerTernary } from "./lower-exprs.js";
52
69
  /** Entry function name. '%' cannot appear in a TS identifier, so a user
53
70
  * function can never collide with it (mangling is injective per prefix). */
54
71
  export const ENTRY_NAME = "%main";
@@ -62,24 +79,6 @@ export class PoisonError extends Error {
62
79
  export function own(table, key) {
63
80
  return Object.hasOwn(table, key) ? table[key] : undefined;
64
81
  }
65
- /** Sentinel binding key for `this` (which has no ts.Symbol): a stable
66
- * object identity used in the same scope/capture maps as real symbols, so
67
- * arrows capturing `this` ride the ordinary capture machinery. */
68
- const THIS_BINDING = { escapedName: "%this" };
69
- export function newFnCtx(lifted, selfSymbol, selfType, returnType) {
70
- return {
71
- locals: [],
72
- scopes: [new Map()],
73
- localCounters: new Map(),
74
- captures: lifted ? [] : null,
75
- captureSources: [],
76
- captureBySymbol: new Map(),
77
- selfSymbol,
78
- selfType,
79
- returnType,
80
- ctl: [],
81
- };
82
- }
83
82
  /** IrStmt discriminants — the island walk below must not descend into
84
83
  * NESTED statements (each is counted individually by its own lowerStmts
85
84
  * visit; descending would attribute a nested island statement to every
@@ -90,10 +89,6 @@ const IR_STMT_KINDS = new Set([
90
89
  "arraySet", "arraySetLength", "arraySetUndefined", "arrayDelete", "forOf", "return", "fieldSet", "recordSet", "break",
91
90
  "continue", "block", "tryCatch", "throw", "rethrow", "runtimeFence",
92
91
  ]);
93
- /** True when a lowered statement's OWN expressions contain island
94
- * constructs — a generic JSON walk (like moduleUsesRegex): `kind`
95
- * discriminants live only on IR objects, so user string values can never
96
- * false-positive. Nested statements are skipped (counted separately). */
97
92
  /** Every identifier a binding name binds: the identifier itself, or all
98
93
  * identifiers of a (possibly nested) destructuring pattern in source
99
94
  * order. */
@@ -110,31 +105,22 @@ export function boundIdentifiersOf(name) {
110
105
  }
111
106
  return out;
112
107
  }
108
+ /** Inspect executable children directly, without boxing the statement tree
109
+ * into checked-dynamic storage just to calculate coverage. */
113
110
  export function stmtUsesIsland(stmts) {
114
- let found = false;
115
- const visit = (v, root) => {
116
- if (found || v === null || typeof v !== "object")
117
- return;
118
- if (Array.isArray(v)) {
119
- for (const item of v)
120
- visit(item, root);
121
- return;
122
- }
123
- const kind = v.kind;
124
- if (!root && typeof kind === "string" && IR_STMT_KINDS.has(kind))
125
- return;
126
- const fn = v.fn;
127
- if (kind === "jsOp" || kind === "jsExit" || kind === "jsBridgePromise" ||
128
- fn === "island.eval" || fn === "island.import" || fn === "island.importDyn" ||
129
- fn === "island.castFail") {
130
- found = true;
131
- return;
132
- }
133
- for (const value of Object.values(v))
134
- visit(value, false);
111
+ // Keep the accounting boundary at the source statement: nested statement
112
+ // lists are counted by their own lowerStmts invocation.
113
+ const nested = (stmt) => IR_STMT_KINDS.has(stmt.kind) || everyStmtChild(stmt, expr, nested);
114
+ const expr = (node) => {
115
+ if (node.kind === "jsOp" || node.kind === "jsExit" || node.kind === "jsBridgePromise" ||
116
+ (node.kind === "libCall" && (node.fn === "island.eval" || node.fn === "island.import" ||
117
+ node.fn === "island.importDyn" || node.fn === "island.castFail")))
118
+ return false;
119
+ return everyExprChild(node, expr, nested);
135
120
  };
136
- visit(stmts, true);
137
- return found;
121
+ if (Array.isArray(stmts))
122
+ return !stmts.every((stmt) => everyStmtChild(stmt, expr, nested));
123
+ return !everyStmtChild(stmts, expr, nested);
138
124
  }
139
125
  function directExternalTypeSpecifiersByFile(externalTypes) {
140
126
  const out = new Map();
@@ -173,12 +159,14 @@ export function lowerToIr(program, entry, moduleOrder, options = {}) {
173
159
  if (!phaseTiming)
174
160
  return;
175
161
  const now = performance.now();
176
- process.stderr.write(`scriptc lowering ${JSON.stringify({
162
+ const event = {
177
163
  phase,
178
164
  phase_ms: Math.round((now - phaseLast) * 10) / 10,
179
165
  total_ms: Math.round((now - phaseStarted) * 10) / 10,
180
- ...detail,
181
- })}\n`);
166
+ };
167
+ for (const key of Object.keys(detail))
168
+ event[key] = detail[key];
169
+ process.stderr.write(`scriptc lowering ${JSON.stringify(event)}\n`);
182
170
  phaseLast = now;
183
171
  };
184
172
  const dynamic = options.dynamic ?? false;
@@ -216,6 +204,7 @@ export function lowerToIr(program, entry, moduleOrder, options = {}) {
216
204
  const externalTypeSpecifiersByFile = options.externalTypeSpecifiersByFile ??
217
205
  directExternalTypeSpecifiersByFile(externalTypes);
218
206
  const validation = new Lowerer(program, entry, moduleOrder, dynamic, {
207
+ frontendServices: options.frontendServices,
219
208
  targetPlatform,
220
209
  startupCrash,
221
210
  ffiImports,
@@ -234,6 +223,7 @@ export function lowerToIr(program, entry, moduleOrder, options = {}) {
234
223
  const reachableEmit = ffiImports.length === 0
235
224
  ? validation
236
225
  : new Lowerer(program, entry, moduleOrder, dynamic, {
226
+ frontendServices: options.frontendServices,
237
227
  targetPlatform,
238
228
  startupCrash,
239
229
  ffiImports,
@@ -261,6 +251,7 @@ export function lowerToIr(program, entry, moduleOrder, options = {}) {
261
251
  // without such a settled fence retain checker-backed IR exactly once.
262
252
  if (reachableEmit.requiresHistoricalOrderRelower) {
263
253
  const emit = new Lowerer(program, entry, moduleOrder, dynamic, {
254
+ frontendServices: options.frontendServices,
264
255
  reachable,
265
256
  targetPlatform,
266
257
  startupCrash,
@@ -282,6 +273,7 @@ export function lowerToIr(program, entry, moduleOrder, options = {}) {
282
273
  if (options.coverage !== true)
283
274
  return result;
284
275
  const remainder = new Lowerer(program, entry, moduleOrder, dynamic, {
276
+ frontendServices: options.frontendServices,
285
277
  reachable,
286
278
  remainder: true,
287
279
  alreadyFlushed: resultLowerer.flushedSymbols,
@@ -353,7 +345,7 @@ export function staticImportNamespaceType(lowerer, expr) {
353
345
  if (moduleId === null) {
354
346
  const symbol = lowerer.checker.getSymbolAtLocation(arg);
355
347
  const source = symbol && lowerer.checker.declarationsOf(symbol).find((decl) => ts.isSourceFile(decl) && !decl.isDeclarationFile);
356
- if (source && !source.fileName.endsWith(".cts") && !isCjsJsFile(source) &&
348
+ if (source && !source.fileName.endsWith(".cts") && !isCjsJsFile(source, lowerer.program) &&
357
349
  lowerer.moduleOrder.includes(source)) {
358
350
  moduleId = `file:${tsgoPath(resolve(source.fileName))}`;
359
351
  }
@@ -527,6 +519,25 @@ export function dynFallbackType(lowerer, node, t) {
527
519
  // the whole type's own fence.
528
520
  return anyPiecedFuncType(lowerer, node, t);
529
521
  }
522
+ const promise = jsFallbackPromiseType(lowerer, t);
523
+ if (promise)
524
+ return promise;
525
+ const generator = jsFallbackGeneratorType(lowerer, t);
526
+ if (generator)
527
+ return generator;
528
+ const symbol = t.getSymbol();
529
+ if ((symbol?.name === "Map" || symbol?.name === "ReadonlyMap") && lowerer.isStdlibSymbol(symbol)) {
530
+ const args = lowerer.checker.getTypeArguments(t);
531
+ if (args.length === 2) {
532
+ const key = lowerer.mapTypeOf(args[0]);
533
+ const value = lowerer.mapTypeOf(args[1]);
534
+ return {
535
+ kind: "map",
536
+ key: key && isSupportedMapKey(key, key.kind === "union" ? lowerer.unions.get(key.unionId)?.arms : undefined) ? key : DYN,
537
+ value: value && isSupportedMapValue(value) ? value : DYN,
538
+ };
539
+ }
540
+ }
530
541
  // JS inference commonly spells a callback field initialized to null as
531
542
  // `((value: any) => any) | null`. Preserve the callable arm and its
532
543
  // checked-dynamic pieces instead of collapsing the whole slot to dyn.
@@ -588,6 +599,32 @@ export function dynFallbackType(lowerer, node, t) {
588
599
  return fallbackFunction;
589
600
  return DYN;
590
601
  }
602
+ /** An inferred JS promise keeps its asynchronous ABI even when its payload
603
+ * has no fixed shape. The settled value crosses the checked native boundary. */
604
+ function jsFallbackPromiseType(lowerer, t) {
605
+ const symbol = t.getSymbol();
606
+ if (symbol?.name !== "Promise" || !lowerer.isStdlibSymbol(symbol))
607
+ return null;
608
+ const inner = lowerer.checker.getTypeArguments(t)[0];
609
+ return inner ? { kind: "promise", inner: lowerer.mapTypeOf(inner) ?? DYN } : null;
610
+ }
611
+ /** An inferred generator with channels outside the typed result union
612
+ * keeps its fiber ABI and carries yielded/resumed values as checked values. */
613
+ function jsFallbackGeneratorType(lowerer, t) {
614
+ const symbol = t.getSymbol();
615
+ if (!symbol || !["Generator", "AsyncGenerator", "IterableIterator"].includes(symbol.name) ||
616
+ !lowerer.isStdlibSymbol(symbol))
617
+ return null;
618
+ const [yielded, returned, resumed] = lowerer.checker.getTypeArguments(t);
619
+ const unit = ts.TypeFlags.Void | ts.TypeFlags.Undefined | ts.TypeFlags.Never;
620
+ return {
621
+ kind: "generator",
622
+ ...(symbol.name === "AsyncGenerator" ? { async: true } : {}),
623
+ yieldT: yielded && yielded.flags & ts.TypeFlags.Never ? VOID : DYN,
624
+ retT: !returned || returned.flags & unit ? VOID : DYN,
625
+ nextT: !resumed || resumed.flags & unit ? UNDEFINED_T : DYN,
626
+ };
627
+ }
591
628
  function jsFallbackFunctionType(lowerer, node, t) {
592
629
  const sig = pureSingleCallSignatureOf(lowerer, t);
593
630
  if (!sig)
@@ -602,6 +639,7 @@ function jsFallbackFunctionType(lowerer, node, t) {
602
639
  // `enabled = true`) rather than that call-site type, so recover the
603
640
  // syntactic optionality from the parameter declaration.
604
641
  const decl = lowerer.checker.valueDeclarationOf(p);
642
+ mapped = jsOpenObjectType(decl, mapped, lowerer.shapes, lowerer.unions);
605
643
  const optional = decl !== undefined &&
606
644
  ts.isParameter(decl) &&
607
645
  (decl.questionToken !== undefined || decl.initializer !== undefined);
@@ -614,12 +652,16 @@ function jsFallbackFunctionType(lowerer, node, t) {
614
652
  return mapped;
615
653
  });
616
654
  const retT = lowerer.checker.getReturnTypeOfSignature(sig);
617
- const ret = retT.flags & ts.TypeFlags.Void ? VOID : lowerer.mapTypeOf(retT) ?? DYN;
655
+ const sigDecl = lowerer.checker.signatureDeclaration(sig);
656
+ const jsUnitReturn = sigDecl !== undefined && isJsSourceFile(sigDecl.getSourceFile()) &&
657
+ (retT.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined)) !== 0;
658
+ const ret = jsUnitReturn ? DYN : retT.flags & ts.TypeFlags.Void ? VOID
659
+ : lowerer.mapTypeOf(retT) ?? jsFallbackPromiseType(lowerer, retT) ?? jsFallbackGeneratorType(lowerer, retT) ?? DYN;
618
660
  return { kind: "func", params, ret };
619
661
  }
620
- /** A JavaScript `arguments` reader has the spelled parameters plus a hidden
621
- * array of all supplied arguments in the native ABI. Recover that ABI from
622
- * the implementation when the function flows through a value binding. */
662
+ /** Recover a JavaScript variadic callable's native ABI from its declaration.
663
+ * Rest parameters and an implicit `arguments` array must keep their packing
664
+ * convention when the function flows through a value or an export. */
623
665
  function jsArgumentsFunctionType(lowerer, t) {
624
666
  if (!(t.flags & ts.TypeFlags.Object))
625
667
  return null;
@@ -627,16 +669,19 @@ function jsArgumentsFunctionType(lowerer, t) {
627
669
  if (sigs.length !== 1 || sigs[0].getTypeParameters().length !== 0 || lowerer.checker.getConstructSignatures(t).length !== 0 || lowerer.checker.getPropertiesOfType(t).length !== 0)
628
670
  return null;
629
671
  const decl = lowerer.checker.signatureDeclaration(sigs[0]);
630
- if (decl === undefined || !(ts.isFunctionDeclaration(decl) || ts.isFunctionExpression(decl)) ||
631
- !isJsSourceFile(decl.getSourceFile()) || !isNodeEsmFile(decl.getSourceFile()) ||
632
- decl.parameters.length === 0 ||
633
- decl.parameters.some((p) => p.dotDotDotToken !== undefined) ||
634
- !bodyReadsArguments(decl))
672
+ if (decl === undefined || !(ts.isFunctionDeclaration(decl) || ts.isFunctionExpression(decl) || ts.isArrowFunction(decl)) ||
673
+ !isJsSourceFile(decl.getSourceFile()))
674
+ return null;
675
+ const hasRest = decl.parameters.some((p) => p.dotDotDotToken !== undefined);
676
+ if (!hasRest && (ts.isArrowFunction(decl) || !bodyReadsArguments(decl) ||
677
+ decl.parameters.length > 0 && !isNodeEsmFile(decl.getSourceFile(), lowerer.program)))
635
678
  return null;
636
679
  const shapes = paramShapes(lowerer, decl.parameters);
637
680
  const retType = lowerer.checker.getReturnTypeOfSignature(sigs[0]);
638
- const ret = retType.flags & ts.TypeFlags.Void ? VOID : lowerer.mapTypeOf(retType) ?? DYN;
639
- return funcTypeFromParamShapes([...shapes, { type: DYN, mode: "arguments" }], ret);
681
+ const ret = retType.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined)
682
+ ? DYN
683
+ : retType.flags & ts.TypeFlags.Void ? VOID : lowerer.mapTypeOf(retType) ?? DYN;
684
+ return funcTypeFromParamShapes(hasRest ? shapes : [...shapes, { type: DYN, mode: "arguments" }], ret);
640
685
  }
641
686
  /** The one call signature of a PURE function type — single signature, no
642
687
  * properties, no construct signatures, no type parameters, no rest params
@@ -731,6 +776,7 @@ export class Lowerer {
731
776
  entry;
732
777
  moduleOrder;
733
778
  dynamic;
779
+ frontendServices;
734
780
  checker;
735
781
  diags = [];
736
782
  fnSigsBySymbol = new Map();
@@ -935,6 +981,7 @@ export class Lowerer {
935
981
  /** Non-null while an instance body lowers: type-parameter symbol →
936
982
  * concrete IR type, consulted inside mapType's recursion. */
937
983
  typeParamBindings = null;
984
+ localClassInstantiations = [];
938
985
  /** The ts-level twin of typeParamBindings, non-null while a CALL-keyed
939
986
  * instance body lowers: type-parameter symbol → the bound CHECKER type,
940
987
  * consulted where the mapped IrType has already widened away information
@@ -959,10 +1006,23 @@ export class Lowerer {
959
1006
  * aliases, so this carries the var/let form the checker cannot.
960
1007
  * Scoped strictly by narrowingAliases (lowerIf / lowerCondition). */
961
1008
  aliasNarrowTypes = new Map();
1009
+ /** These caches belong to this lowering pass. The program already owns
1010
+ * their symbol/node keys; no module-level cache should retain a pass. */
1011
+ classSymbolKeys = new Map();
1012
+ registeredClassSymbols = new Map();
1013
+ httpClientFnBindings = new Map();
1014
+ streamPropMutatedSyms = null;
1015
+ requestInitPropMutatedSyms = null;
1016
+ emitterEventTable = null;
1017
+ emitterComputedPatterns = [];
962
1018
  /** Locals widened beyond the checker's type because an inferred indexed
963
1019
  * read can be absent at runtime. Bare reads preserve that union until a
964
1020
  * surrounding JavaScript guard/default consumes it. */
965
- runtimeOptionalLocals = new Set();
1021
+ runtimeOptionalLocals = new RuntimeOptionalLocals();
1022
+ /** An effectful switch test can change the original binding after the
1023
+ * discriminant was captured. A case match narrows the captured value,
1024
+ * not that mutable binding; preserve its tagged representation on reads. */
1025
+ unstableSwitchBindings = new Set();
966
1026
  /** All storage slots widened for runtime absence, including slots whose
967
1027
  * current control-flow branch has temporarily narrowed the value. */
968
1028
  runtimeOptionalStorageLocals = new Set();
@@ -981,18 +1041,21 @@ export class Lowerer {
981
1041
  runtimeOptionalBindingTypes = new Map();
982
1042
  /** Concise callback/lambda returns promoted by the HOF callback prepass;
983
1043
  * arrows have no declaration symbol to key in fnSigsBySymbol. */
984
- runtimeOptionalFunctionReturns = new WeakMap();
1044
+ runtimeOptionalFunctionReturns = new Map();
1045
+ /** Intrinsic callback slots can supply a destination for fresh return
1046
+ * literals, such as a reduce accumulator with recursive union fields. */
1047
+ contextualFunctionReturns = new Map();
985
1048
  /** Arithmetic over an unchecked string read can answer either NaN or a
986
1049
  * string. Bindings and returns use this marker to retain that result union
987
1050
  * through checker-bare string annotations. */
988
- runtimeOptionalArithmeticTypes = new WeakMap();
1051
+ runtimeOptionalArithmeticTypes = new Map();
989
1052
  /** Record fields promoted to an undefined-armed union by an indexed-read
990
1053
  * value. The key is the concrete emitted shape and field name. */
991
1054
  runtimeOptionalFields = new Set();
992
1055
  /** Callback pattern parameters carry an optional source without making
993
1056
  * every name destructured from a present source optional. */
994
- runtimeOptionalPatternTypes = new WeakMap();
995
- runtimeOptionalReduceTypes = new WeakMap();
1057
+ runtimeOptionalPatternTypes = new Map();
1058
+ runtimeOptionalReduceTypes = new Map();
996
1059
  /** Capture entries and their origin share one mutable box. Normalize each
997
1060
  * entry to the origin so writes and flow proofs stay synchronized. */
998
1061
  runtimeOptionalRoots = new Map();
@@ -1352,6 +1415,12 @@ export class Lowerer {
1352
1415
  /** Keyed by program-wide qualified class name (what IR object types carry). */
1353
1416
  classes = new Map();
1354
1417
  classBySymbol = new Map();
1418
+ /** Inferred JS methods participating in an override chain keep a vtable
1419
+ * ABI instead of call-site specialization. Filled before class collection. */
1420
+ virtualJsMethods = new Set();
1421
+ /** Largest fixed argument list below a JS method, discovered before any
1422
+ * base vtable signature is collected. Unused checked slots carry undefined. */
1423
+ virtualJsMethodArity = new Map();
1355
1424
  /** The class whose members are lowering — `super` binds lexically to it
1356
1425
  * (arrows inside methods lower within this window, so they see it too). */
1357
1426
  currentClass = null;
@@ -1404,6 +1473,7 @@ export class Lowerer {
1404
1473
  * engine handle (a dynamic import's namespace object) — paramShape's
1405
1474
  * early-out. */
1406
1475
  jsvalParamOverrides = new Set();
1476
+ checkedCallbackParams = new Set();
1407
1477
  /** Inline Promise.then parameters whose contextual type is a builtin
1408
1478
  * module namespace anonymous object. The settled native token is the
1409
1479
  * ABI truth even when the checker type has no stable module symbol. */
@@ -1493,6 +1563,9 @@ export class Lowerer {
1493
1563
  // top level, top = the innermost nested function currently lowering).
1494
1564
  fnStack = [];
1495
1565
  liftedFns = [];
1566
+ /** One Error-method helper belongs to this lowering session. Its cached
1567
+ * dispatch revision needs no weak-key identity or process-global state. */
1568
+ errorMethodDispatchRevision = null;
1496
1569
  lambdaCounter = 0;
1497
1570
  /** Statement lists currently mid-lowering, innermost last: the forward-
1498
1571
  * capture machinery needs to know which later statements of an OPEN list
@@ -1500,20 +1573,6 @@ export class Lowerer {
1500
1573
  * register into, and where to insert predeclarations before closures or
1501
1574
  * earlier source statements need them. */
1502
1575
  activeStmtLists = [];
1503
- /** Forward-captured consts pre-declared as TDZ boxes, keyed by symbol:
1504
- * lowerVarDecl consumes the entry when the source declaration arrives and
1505
- * emits the initializing `assign` instead of a fresh declaration. */
1506
- tdzPredeclared = new Map();
1507
- /** Nested function DECLARATIONS lowered eagerly by the forward-hoisting
1508
- * machinery (predeclareForwardFnDecl — a reference above the declaration
1509
- * in the same function, JS's function hoisting): the statement loop skips
1510
- * the source statement when it arrives. */
1511
- hoistedFnDecls = new Set();
1512
- /** `var` bindings hoisted to their function root (hoistVarBinding), keyed
1513
- * by the checker's merged symbol — every same-name `var` in one function
1514
- * is one symbol, so one slot. Module-scope vars live in globalsBySymbol
1515
- * instead. */
1516
- hoistedVars = new Map();
1517
1576
  /** Per-file `var` module globals whose type carries an undefined arm:
1518
1577
  * lowerFileInit assigns them the interned undefined right after the
1519
1578
  * run-once guard — JS hoists module vars to `undefined` at entry, so a
@@ -1602,13 +1661,19 @@ export class Lowerer {
1602
1661
  let s = this.statsByFile.get(file);
1603
1662
  if (!s)
1604
1663
  this.statsByFile.set(file, (s = { total: 0, failed: 0, island: 0 }));
1605
- s[kind]++;
1664
+ if (kind === "total")
1665
+ s.total += 1;
1666
+ else if (kind === "failed")
1667
+ s.failed += 1;
1668
+ else
1669
+ s.island += 1;
1606
1670
  }
1607
1671
  constructor(program, entry, moduleOrder, dynamic, mode = {}) {
1608
1672
  this.program = program;
1609
1673
  this.entry = entry;
1610
1674
  this.moduleOrder = moduleOrder;
1611
1675
  this.dynamic = dynamic;
1676
+ this.frontendServices = mode.frontendServices;
1612
1677
  this.reachable = mode.reachable ?? null;
1613
1678
  this.remainder = mode.remainder ?? false;
1614
1679
  this.alreadyFlushed = mode.alreadyFlushed ?? new Set();
@@ -1633,10 +1698,25 @@ export class Lowerer {
1633
1698
  classNamer: this.classNamer,
1634
1699
  resolveTypeParam: this.typeParamResolver,
1635
1700
  resolveTypeParamTs: this.typeParamTsResolver,
1636
- genericClassInstance: (decl, ref) => this.genericClassInstanceType(decl, ref),
1701
+ genericClassInstance: (decl, ref, mapArgument) => this.genericClassInstanceType(decl, ref, mapArgument),
1637
1702
  mixinClassInstance: (decl) => this.mixinTypeContext && this.mixinTypeContext.classNode === decl
1638
1703
  ? { kind: "object", className: this.mixinTypeContext.className }
1639
1704
  : null,
1705
+ localClassInstance: (decl) => {
1706
+ for (let parent = decl.parent; parent && !ts.isSourceFile(parent); parent = parent.parent) {
1707
+ if (!ts.isFunctionDeclaration(parent) && !ts.isFunctionExpression(parent) &&
1708
+ !ts.isArrowFunction(parent) && !ts.isMethodDeclaration(parent))
1709
+ continue;
1710
+ if (this.localClassInstantiations.some((entry) => entry.owner === parent))
1711
+ break;
1712
+ if (parent.typeParameters?.length || (implicitMonoFile(parent.getSourceFile()) && implicitAnyParamSymbolsOf(this, parent)))
1713
+ return null;
1714
+ }
1715
+ const className = this.classNamer(decl);
1716
+ if (!this.collectingExprClasses.has(decl))
1717
+ this.lowerClassExpressionInfo(decl);
1718
+ return { kind: "object", className };
1719
+ },
1640
1720
  mixinIntersectionInstance: (widened) => mixinIntersectionInstanceType(this, widened),
1641
1721
  isStdlibFile: this.isStdlibFile,
1642
1722
  isNpmFile: this.isNpmFile,
@@ -1678,7 +1758,7 @@ export class Lowerer {
1678
1758
  sym = this.checker.getAliasedSymbol(sym);
1679
1759
  for (const decl of this.checker.declarationsOf(sym)) {
1680
1760
  if (ts.isSourceFile(decl) && !decl.isDeclarationFile &&
1681
- !decl.fileName.endsWith(".cts") && !isCjsJsFile(decl) &&
1761
+ !decl.fileName.endsWith(".cts") && !isCjsJsFile(decl, this.program) &&
1682
1762
  this.moduleOrder.includes(decl)) {
1683
1763
  return `file:${tsgoPath(resolve(decl.fileName))}`;
1684
1764
  }
@@ -1717,9 +1797,25 @@ export class Lowerer {
1717
1797
  * builds (no counter can drift between invocations),
1718
1798
  * program-unique through the file qualifier, and collision-free with
1719
1799
  * user identifiers ('%'). */
1720
- classNamer = (decl) => ts.isClassExpression(decl)
1721
- ? this.qualify(decl.getSourceFile(), `%cx${decl.getStart()}.${decl.name?.text ?? ""}`)
1722
- : this.qualify(decl.getSourceFile(), nsPathPrefix(decl) + (decl.name ? decl.name.text : "%anon"));
1800
+ classNamer = (decl) => {
1801
+ const name = ts.isClassExpression(decl) || (() => {
1802
+ for (let parent = decl.parent; parent && !ts.isSourceFile(parent); parent = parent.parent) {
1803
+ if (ts.isFunctionLike(parent))
1804
+ return true;
1805
+ }
1806
+ return false;
1807
+ })()
1808
+ ? this.qualify(decl.getSourceFile(), `%cx${decl.getStart()}.${decl.name?.text ?? ""}`)
1809
+ : this.qualify(decl.getSourceFile(), nsPathPrefix(decl) + (decl.name ? decl.name.text : "%anon"));
1810
+ for (let index = this.localClassInstantiations.length - 1; index >= 0; index--) {
1811
+ const entry = this.localClassInstantiations[index];
1812
+ for (let parent = decl.parent; parent && !ts.isSourceFile(parent); parent = parent.parent) {
1813
+ if (parent === entry.owner)
1814
+ return `${name}%${entry.name}`;
1815
+ }
1816
+ }
1817
+ return name;
1818
+ };
1723
1819
  /** Follows import aliases to the original declaration's symbol. Every
1724
1820
  * value reference resolves through here, so it doubles as the flush
1725
1821
  * point for deferred collection diagnostics: resolving a reference to a
@@ -1931,7 +2027,7 @@ export class Lowerer {
1931
2027
  : undefined;
1932
2028
  if (namespaceDecl === undefined)
1933
2029
  return null;
1934
- const importDecl = namespaceDecl.parent.parent;
2030
+ const importDecl = namespaceDecl.parent?.parent;
1935
2031
  if (!ts.isImportDeclaration(importDecl) || !ts.isStringLiteral(importDecl.moduleSpecifier))
1936
2032
  return null;
1937
2033
  if (this.externalTypes.has(importDecl.moduleSpecifier.text))
@@ -1953,7 +2049,7 @@ export class Lowerer {
1953
2049
  let specNode;
1954
2050
  let importedName = null;
1955
2051
  if (ts.isImportSpecifier(decl)) {
1956
- const importDecl = decl.parent.parent.parent;
2052
+ const importDecl = decl.parent?.parent?.parent;
1957
2053
  if (ts.isImportDeclaration(importDecl))
1958
2054
  specNode = importDecl.moduleSpecifier;
1959
2055
  importedName = (decl.propertyName ?? decl.name).text;
@@ -1964,13 +2060,13 @@ export class Lowerer {
1964
2060
  importedName = "default";
1965
2061
  }
1966
2062
  else if (ts.isNamespaceImport(decl)) {
1967
- const importDecl = decl.parent.parent;
2063
+ const importDecl = decl.parent?.parent;
1968
2064
  if (ts.isImportDeclaration(importDecl))
1969
2065
  specNode = importDecl.moduleSpecifier;
1970
2066
  importedName = null;
1971
2067
  }
1972
2068
  else if (ts.isExportSpecifier(decl)) {
1973
- const exportDecl = decl.parent.parent;
2069
+ const exportDecl = decl.parent?.parent;
1974
2070
  if (ts.isExportDeclaration(exportDecl))
1975
2071
  specNode = exportDecl.moduleSpecifier;
1976
2072
  importedName = (decl.propertyName ?? decl.name).text;
@@ -2031,13 +2127,13 @@ export class Lowerer {
2031
2127
  name = "default";
2032
2128
  }
2033
2129
  else if (d && ts.isImportSpecifier(d)) {
2034
- const idecl = d.parent.parent.parent;
2130
+ const idecl = d.parent?.parent?.parent;
2035
2131
  if (ts.isImportDeclaration(idecl))
2036
2132
  spec = idecl.moduleSpecifier;
2037
2133
  name = (d.propertyName ?? d.name).text;
2038
2134
  }
2039
2135
  else if (d && ts.isExportSpecifier(d)) {
2040
- const edecl = d.parent.parent;
2136
+ const edecl = d.parent?.parent;
2041
2137
  if (ts.isExportDeclaration(edecl))
2042
2138
  spec = edecl.moduleSpecifier;
2043
2139
  name = (d.propertyName ?? d.name).text;
@@ -2150,7 +2246,7 @@ export class Lowerer {
2150
2246
  // relative imports; an opted-in --npm-static package is the fallback.
2151
2247
  const dep = resolveImport(this.program, importDecl.getSourceFile(), spec) ??
2152
2248
  npmStaticDepSf7(this.program, importDecl.getSourceFile(), spec);
2153
- if (!dep || !isJsSourceFile(dep) || isNodeEsmFile(dep))
2249
+ if (!dep || !isJsSourceFile(dep) || isNodeEsmFile(dep, this.program))
2154
2250
  return null;
2155
2251
  return dep;
2156
2252
  }
@@ -2171,7 +2267,7 @@ export class Lowerer {
2171
2267
  const directSpec = requireSpecOf(decl.initializer);
2172
2268
  if (directSpec !== null) {
2173
2269
  return resolveImport(this.program, decl.getSourceFile(), directSpec) ??
2174
- npmStaticDepSf7(this.program, decl.getSourceFile(), directSpec);
2270
+ npmStaticDepSf7(this.program, decl.getSourceFile(), directSpec, "require");
2175
2271
  }
2176
2272
  return createRequireProgramModuleOf(this, decl.initializer)?.dep ?? null;
2177
2273
  }
@@ -2382,7 +2478,7 @@ export class Lowerer {
2382
2478
  while (changed) {
2383
2479
  changed = false;
2384
2480
  for (const fp of parts) {
2385
- if (this.asyncInitFiles.has(fp.sf) || !isNodeEsmFile(fp.sf))
2481
+ if (this.asyncInitFiles.has(fp.sf) || !isNodeEsmFile(fp.sf, this.program))
2386
2482
  continue;
2387
2483
  if (orderedImportsOf(this.program, fp.sf).some(({ dep }) => dep !== null && this.asyncInitFiles.has(dep))) {
2388
2484
  this.asyncInitFiles.add(fp.sf);
@@ -2406,9 +2502,14 @@ export class Lowerer {
2406
2502
  }
2407
2503
  const orderIndex = new Map(parts.map((fp, i) => [fp.sf, i]));
2408
2504
  const partSet = new Set(parts.map((fp) => fp.sf));
2409
- const staticDeps = (sf) => orderedImportsOf(this.program, sf)
2410
- .map(({ dep }) => dep)
2411
- .filter((dep) => dep !== null && dep !== sf && partSet.has(dep));
2505
+ const staticDeps = (sf) => {
2506
+ const dependencies = [];
2507
+ for (const { dep } of orderedImportsOf(this.program, sf)) {
2508
+ if (dep !== null && dep !== sf && partSet.has(dep))
2509
+ dependencies.push(dep);
2510
+ }
2511
+ return dependencies;
2512
+ };
2412
2513
  // Tarjan SCCs over the same static graph. The last postorder member is
2413
2514
  // a deterministic COMPONENT representative for internal-edge tests
2414
2515
  // and global naming. The runtime evaluation root can differ: a cycle
@@ -2486,7 +2587,7 @@ export class Lowerer {
2486
2587
  // those globals stay uninitialized: the dep's module body would never
2487
2588
  // run.
2488
2589
  const dep = resolveImport(this.program, node.getSourceFile(), spec) ??
2489
- npmStaticDepSf7(this.program, node.getSourceFile(), spec);
2590
+ npmStaticDepSf7(this.program, node.getSourceFile(), spec, "require");
2490
2591
  if (!dep || dep.fileName.endsWith(".json"))
2491
2592
  return null;
2492
2593
  if (this.asyncInitFiles.has(dep)) {
@@ -2566,6 +2667,9 @@ export class Lowerer {
2566
2667
  };
2567
2668
  const functionDeclBySymbol = new Map();
2568
2669
  const signatureBySymbol = new Map();
2670
+ const methodFamilies = new Map();
2671
+ const familyBySymbol = new Map();
2672
+ const optionalMethodFamilies = new Set();
2569
2673
  for (const [symbol, sig] of this.fnSigsBySymbol)
2570
2674
  signatureBySymbol.set(symbol, { params: sig.params, returnType: sig.returnType, top: sig });
2571
2675
  for (const decl of fnDecls) {
@@ -2589,8 +2693,18 @@ export class Lowerer {
2589
2693
  continue;
2590
2694
  const symbol = symbolOf(member.name);
2591
2695
  const sig = info.methods.get(mName);
2592
- if (symbol && sig)
2696
+ if (symbol && sig) {
2593
2697
  signatureBySymbol.set(symbol, { params: sig.params, returnType: sig.ret, method: sig });
2698
+ let root = info;
2699
+ for (let base = info.base; base; base = base.base)
2700
+ if (base.methods.has(mName))
2701
+ root = base;
2702
+ const key = `${root.def.name}:${mName}`;
2703
+ const family = methodFamilies.get(key) ?? [];
2704
+ family.push(symbol);
2705
+ methodFamilies.set(key, family);
2706
+ familyBySymbol.set(symbol, family);
2707
+ }
2594
2708
  }
2595
2709
  }
2596
2710
  const peel = (node) => {
@@ -2600,6 +2714,32 @@ export class Lowerer {
2600
2714
  }
2601
2715
  return e;
2602
2716
  };
2717
+ const callableSymbols = new Map();
2718
+ const callableSymbolOf = (node) => {
2719
+ const cached = callableSymbols.get(node);
2720
+ if (cached !== undefined)
2721
+ return cached;
2722
+ let symbol = symbolOf(ts.isPropertyAccessExpression(node) ? node.name : node);
2723
+ if (symbol === null || signatureBySymbol.has(symbol)) {
2724
+ callableSymbols.set(node, symbol);
2725
+ return symbol;
2726
+ }
2727
+ const seen = new Set();
2728
+ while (symbol && !signatureBySymbol.has(symbol) && !seen.has(symbol)) {
2729
+ seen.add(symbol);
2730
+ const declaration = this.checker.valueDeclarationOf(symbol);
2731
+ if (declaration && ts.isMethodDeclaration(declaration)) {
2732
+ symbol = symbolOf(declaration.name);
2733
+ }
2734
+ else if (declaration && ts.isVariableDeclaration(declaration) && declaration.initializer && ts.isIdentifier(peel(declaration.initializer))) {
2735
+ symbol = symbolOf(peel(declaration.initializer));
2736
+ }
2737
+ else
2738
+ break;
2739
+ }
2740
+ callableSymbols.set(node, symbol);
2741
+ return symbol;
2742
+ };
2603
2743
  const explicitlyNonNull = (node) => {
2604
2744
  let e = node;
2605
2745
  while (ts.isParenthesizedExpression(e) || ts.isAsExpression(e) || ts.isTypeAssertion(e) || ts.isNonNullExpression(e)) {
@@ -2661,13 +2801,17 @@ export class Lowerer {
2661
2801
  this.mapTypeOf(this.typeOf(e))?.kind === "union" &&
2662
2802
  this.armTag(this.mapTypeOf(this.typeOf(e)).unionId, UNDEFINED_T) >= 0)
2663
2803
  return true;
2664
- if (ts.isIdentifier(e))
2665
- return optionalSymbols.has(symbolOf(e) ?? {});
2804
+ if (ts.isIdentifier(e)) {
2805
+ const symbol = symbolOf(e);
2806
+ return symbol !== null && optionalSymbols.has(symbol);
2807
+ }
2666
2808
  if (ts.isCallExpression(e) && ts.isIdentifier(e.expression)) {
2667
- return optionalReturns.has(symbolOf(e.expression) ?? {});
2809
+ const symbol = callableSymbolOf(e.expression);
2810
+ return symbol !== null && optionalReturns.has(symbol);
2668
2811
  }
2669
2812
  if (ts.isCallExpression(e) && ts.isPropertyAccessExpression(e.expression)) {
2670
- return optionalReturns.has(symbolOf(e.expression.name) ?? {});
2813
+ const symbol = callableSymbolOf(e.expression);
2814
+ return symbol !== null && optionalReturns.has(symbol);
2671
2815
  }
2672
2816
  if (ts.isConditionalExpression(e)) {
2673
2817
  return mayBeOptional(e.whenTrue) || mayBeOptional(e.whenFalse);
@@ -2680,7 +2824,8 @@ export class Lowerer {
2680
2824
  return mayBeOptional(e.left) || mayBeOptional(e.right);
2681
2825
  }
2682
2826
  if (ts.isPropertyAccessExpression(e) && ts.isIdentifier(e.expression)) {
2683
- const fields = optionalFields.get(symbolOf(e.expression) ?? {});
2827
+ const symbol = symbolOf(e.expression);
2828
+ const fields = symbol === null ? undefined : optionalFields.get(symbol);
2684
2829
  return fields?.has(fieldName(e)) ?? false;
2685
2830
  }
2686
2831
  return false;
@@ -2690,9 +2835,11 @@ export class Lowerer {
2690
2835
  if (!ts.isBinaryExpression(e) || e.operatorToken.kind !== ts.SyntaxKind.PlusToken)
2691
2836
  return null;
2692
2837
  const stringArrayRead = (part) => {
2693
- const t = this.mapTypeOf(this.typeOf(part));
2694
2838
  const p = peel(part);
2695
- if (t?.kind !== "string" || !ts.isElementAccessExpression(p))
2839
+ if (!ts.isElementAccessExpression(p))
2840
+ return false;
2841
+ const t = this.mapTypeOf(this.typeOf(part));
2842
+ if (t?.kind !== "string")
2696
2843
  return false;
2697
2844
  const recv = this.mapTypeOf(this.typeOf(p.expression));
2698
2845
  return recv?.kind === "array" && recv.elem.kind === "string";
@@ -2767,19 +2914,36 @@ export class Lowerer {
2767
2914
  return [0];
2768
2915
  return null;
2769
2916
  };
2770
- const bodyReturnsOptional = (fn) => {
2917
+ // Syntax does not change during the fixed point. Reuse its return sites
2918
+ // while recomputing their optionality from each pass's current bindings.
2919
+ const returnSites = new Map();
2920
+ const returnsOf = (fn) => {
2921
+ const cached = returnSites.get(fn);
2922
+ if (cached !== undefined)
2923
+ return cached;
2924
+ const expressions = [];
2925
+ returnSites.set(fn, expressions);
2771
2926
  if (!fn.body)
2772
- return false;
2773
- if (!ts.isBlock(fn.body))
2774
- return mayBeOptional(fn.body);
2775
- let found = false;
2927
+ return expressions;
2928
+ if (!ts.isBlock(fn.body)) {
2929
+ expressions.push(fn.body);
2930
+ }
2776
2931
  ts.walkPreorder(fn.body, (node) => {
2777
2932
  if (node !== fn.body && (ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node) || ts.isArrowFunction(node) || ts.isMethodDeclaration(node)))
2778
2933
  return "skip";
2779
- if (ts.isReturnStatement(node) && node.expression && mayBeOptional(node.expression))
2780
- found = true;
2934
+ if (ts.isReturnStatement(node) && node.expression)
2935
+ expressions.push(node.expression);
2781
2936
  return undefined;
2782
2937
  });
2938
+ return expressions;
2939
+ };
2940
+ const bodyReturnsOptional = (fn) => {
2941
+ if (fn.body && !ts.isBlock(fn.body))
2942
+ return mayBeOptional(fn.body);
2943
+ let found = false;
2944
+ for (const expression of returnsOf(fn))
2945
+ if (mayBeOptional(expression))
2946
+ found = true;
2783
2947
  return found;
2784
2948
  };
2785
2949
  const promoteHofCallback = (callback, parameterIndices, seen = new Set()) => {
@@ -2791,6 +2955,8 @@ export class Lowerer {
2791
2955
  };
2792
2956
  const promoteNode = (fn) => {
2793
2957
  for (const parameterIndex of parameterIndices) {
2958
+ if (parameterIndex === undefined)
2959
+ continue;
2794
2960
  const parameter = fn.parameters[parameterIndex];
2795
2961
  if (!parameter)
2796
2962
  continue;
@@ -2863,6 +3029,8 @@ export class Lowerer {
2863
3029
  const sig = signatureBySymbol.get(symbol);
2864
3030
  if (sig) {
2865
3031
  for (const parameterIndex of parameterIndices) {
3032
+ if (parameterIndex === undefined)
3033
+ continue;
2866
3034
  if (!sig.params[parameterIndex])
2867
3035
  continue;
2868
3036
  const before = sig.params[parameterIndex].type;
@@ -2878,6 +3046,8 @@ export class Lowerer {
2878
3046
  if (valueType?.kind === "func") {
2879
3047
  const params = valueType.params.slice();
2880
3048
  for (const parameterIndex of parameterIndices) {
3049
+ if (parameterIndex === undefined)
3050
+ continue;
2881
3051
  if (params[parameterIndex])
2882
3052
  params[parameterIndex] = this.runtimeOptionalType(params[parameterIndex]);
2883
3053
  }
@@ -2928,9 +3098,22 @@ export class Lowerer {
2928
3098
  const decl = this.checker.valueDeclarationOf(symbol);
2929
3099
  return !!decl && ts.isVariableDeclaration(decl) && !!decl.initializer && callbackReturnsOptional(decl.initializer, seen);
2930
3100
  };
3101
+ const scanSites = new Map();
3102
+ const sitesOf = (sf) => {
3103
+ const cached = scanSites.get(sf);
3104
+ if (cached !== undefined)
3105
+ return cached;
3106
+ const nodes = [];
3107
+ ts.walkPreorder(sf, (node) => {
3108
+ if (ts.isVariableDeclaration(node) || ts.isBinaryExpression(node) || ts.isCallExpression(node))
3109
+ nodes.push(node);
3110
+ });
3111
+ scanSites.set(sf, nodes);
3112
+ return nodes;
3113
+ };
2931
3114
  const scanFile = (sf) => {
2932
3115
  let changed = false;
2933
- ts.walkPreorder(sf, (node) => {
3116
+ const scan = (node) => {
2934
3117
  if (ts.isVariableDeclaration(node)) {
2935
3118
  if (node.initializer) {
2936
3119
  if (ts.isIdentifier(node.name) && isDynamicObjectEntryRead(node.initializer)) {
@@ -3021,102 +3204,137 @@ export class Lowerer {
3021
3204
  }
3022
3205
  if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression)) {
3023
3206
  const callbackIndices = hofCallbackIndices(node.expression.name.text, node.arguments.length >= 2);
3024
- const receiverNode = node.expression.expression;
3025
- const receiverTs = this.typeOf(receiverNode);
3026
- let receiver = this.mapTypeOf(receiverTs);
3027
- // An array method after an optional-chain guard only runs on the
3028
- // present receiver. The checker includes the chain's short-circuit
3029
- // undefined in intermediate call types, so use the same narrowed
3030
- // receiver the method lowerer sees when promoting HOF callbacks.
3031
- if (callbackIndices !== null && receiver?.kind === "union" &&
3032
- (node.expression.questionDotToken !== undefined || isOptionalChainTail(this, node))) {
3033
- receiver = this.mapTypeOf(this.checker.getNonNullableType(receiverTs));
3034
- }
3035
- const callback = callbackIndices === null ? undefined : node.arguments[0];
3036
- const tuple = receiver?.kind === "record" && this.shapes.get(receiver.shapeId)?.tuple === true;
3037
- // A JS/evolving-any array may have acquired a precise FLOW type
3038
- // at this call while its actual binding remains a checked-dynamic
3039
- // array. Its callback consumes DYN values through runtime method
3040
- // dispatch, so widening that callback to the native array value
3041
- // ABI makes it impossible to box back into DYN. Judge a simple
3042
- // binding by its declaration type, the same storage fact local
3043
- // declaration lowering uses.
3044
- let nativeArrayReceiver = receiver?.kind === "array" || tuple;
3045
- if (nativeArrayReceiver && ts.isIdentifier(receiverNode)) {
3046
- const receiverSymbol = symbolOf(receiverNode);
3047
- const declaration = receiverSymbol ? this.checker.valueDeclarationOf(receiverSymbol) : undefined;
3048
- if (declaration && ts.isVariableDeclaration(declaration)) {
3049
- const declared = this.mapTypeOf(this.typeOf(declaration.name));
3050
- if (declared?.kind !== "array" && !(declared?.kind === "record" && this.shapes.get(declared.shapeId)?.tuple === true)) {
3051
- nativeArrayReceiver = false;
3207
+ const callback = node.arguments[0];
3208
+ if (callbackIndices !== null && callback !== undefined && !ts.isSpreadElement(callback)) {
3209
+ const receiverNode = node.expression.expression;
3210
+ const receiverTs = this.typeOf(receiverNode);
3211
+ let receiver = this.mapTypeOf(receiverTs);
3212
+ // An array method after an optional-chain guard only runs on the
3213
+ // present receiver. The checker includes the chain's short-circuit
3214
+ // undefined in intermediate call types, so use the same narrowed
3215
+ // receiver the method lowerer sees when promoting HOF callbacks.
3216
+ if (receiver?.kind === "union" &&
3217
+ (node.expression.questionDotToken !== undefined || isOptionalChainTail(this, node))) {
3218
+ receiver = this.mapTypeOf(this.checker.getNonNullableType(receiverTs));
3219
+ }
3220
+ const tuple = receiver?.kind === "record" && this.shapes.get(receiver.shapeId)?.tuple === true;
3221
+ // A JS/evolving-any array may have acquired a precise FLOW type
3222
+ // at this call while its actual binding remains a checked-dynamic
3223
+ // array. Its callback consumes DYN values through runtime method
3224
+ // dispatch, so widening that callback to the native array value
3225
+ // ABI makes it impossible to box back into DYN. Judge a simple
3226
+ // binding by its declaration type, the same storage fact local
3227
+ // declaration lowering uses.
3228
+ let nativeArrayReceiver = receiver?.kind === "array" || tuple;
3229
+ if (nativeArrayReceiver && ts.isIdentifier(receiverNode)) {
3230
+ const receiverSymbol = symbolOf(receiverNode);
3231
+ const declaration = receiverSymbol ? this.checker.valueDeclarationOf(receiverSymbol) : undefined;
3232
+ if (declaration && ts.isVariableDeclaration(declaration)) {
3233
+ const declared = this.mapTypeOf(this.typeOf(declaration.name));
3234
+ if (declared?.kind !== "array" && !(declared?.kind === "record" && this.shapes.get(declared.shapeId)?.tuple === true)) {
3235
+ nativeArrayReceiver = false;
3236
+ }
3052
3237
  }
3053
3238
  }
3054
- }
3055
- if (nativeArrayReceiver && callback && !ts.isSpreadElement(callback)) {
3056
- if (promoteHofCallback(callback, callbackIndices))
3057
- changed = true;
3058
- const method = node.expression.name.text;
3059
- if ((method === "reduce" || method === "reduceRight") &&
3060
- (node.arguments.length < 2 || callbackReturnsOptional(callback))) {
3061
- if (promoteHofCallback(callback, [0, 1]))
3062
- changed = true;
3063
- const result = this.runtimeOptionalType(this.irTypeOf(node));
3064
- const previous = this.runtimeOptionalReduceTypes.get(node);
3065
- if (!previous || !typeEquals(previous, result)) {
3066
- this.runtimeOptionalReduceTypes.set(node, result);
3239
+ if (nativeArrayReceiver) {
3240
+ if (promoteHofCallback(callback, callbackIndices))
3067
3241
  changed = true;
3242
+ const method = node.expression.name.text;
3243
+ if ((method === "reduce" || method === "reduceRight") &&
3244
+ (node.arguments.length < 2 || callbackReturnsOptional(callback))) {
3245
+ if (promoteHofCallback(callback, [0, 1]))
3246
+ changed = true;
3247
+ const result = this.runtimeOptionalType(this.irTypeOf(node));
3248
+ const previous = this.runtimeOptionalReduceTypes.get(node);
3249
+ if (!previous || !typeEquals(previous, result)) {
3250
+ this.runtimeOptionalReduceTypes.set(node, result);
3251
+ changed = true;
3252
+ }
3068
3253
  }
3069
3254
  }
3070
3255
  }
3071
3256
  }
3072
3257
  if (ts.isCallExpression(node) &&
3073
3258
  (ts.isIdentifier(node.expression) || ts.isPropertyAccessExpression(node.expression))) {
3074
- const calleeNode = ts.isIdentifier(node.expression) ? node.expression : node.expression.name;
3075
- const symbol = symbolOf(calleeNode);
3259
+ const symbol = callableSymbolOf(node.expression);
3076
3260
  if (!symbol)
3077
3261
  return;
3078
3262
  const sig = signatureBySymbol.get(symbol);
3079
- if (!sig) {
3080
- const decl = this.checker.valueDeclarationOf(symbol);
3081
- if (decl && ts.isVariableDeclaration(decl) && decl.initializer && ts.isIdentifier(decl.initializer)) {
3082
- const source = symbolOf(decl.initializer);
3083
- const sourceSig = source ? signatureBySymbol.get(source) : undefined;
3084
- if (sourceSig) {
3085
- node.arguments.forEach((arg, i) => {
3086
- if (ts.isSpreadElement(arg) || !mayBeOptional(arg) || !sourceSig.params[i])
3087
- return;
3088
- const before = sourceSig.params[i].type;
3089
- sourceSig.params[i].type = this.runtimeOptionalType(before);
3090
- if (!typeEquals(before, sourceSig.params[i].type)) {
3091
- changed = true;
3092
- const sourceFn = functionDeclBySymbol.get(source);
3093
- const parameter = sourceFn?.parameters[i];
3094
- if (parameter) {
3095
- for (const bound of boundIdentifiersOf(parameter.name)) {
3096
- const boundSymbol = symbolOf(bound);
3097
- if (boundSymbol && !optionalSymbols.has(boundSymbol)) {
3098
- optionalSymbols.add(boundSymbol);
3099
- changed = true;
3100
- }
3101
- }
3263
+ if (!sig)
3264
+ return;
3265
+ // JSDoc describes the usual value, not a runtime arity check.
3266
+ // A short JavaScript call still passes undefined. Widen only the
3267
+ // observed slots before bodies lower so both caller and callee
3268
+ // agree on that value's representation.
3269
+ const callee = functionDeclBySymbol.get(symbol);
3270
+ if (callee && isJsSourceFile(callee.getSourceFile()) && !node.arguments.some(ts.isSpreadElement)) {
3271
+ for (let i = 0; i < sig.params.length; i++) {
3272
+ const arg = node.arguments[i];
3273
+ if (arg && (this.typeOf(arg).flags & (ts.TypeFlags.Undefined | ts.TypeFlags.Void)) === 0)
3274
+ continue;
3275
+ const family = familyBySymbol.get(symbol);
3276
+ if (family)
3277
+ optionalMethodFamilies.add(family);
3278
+ for (const target of familyBySymbol.get(symbol) ?? [symbol]) {
3279
+ const shape = signatureBySymbol.get(target)?.params[i];
3280
+ if (!shape || shape.mode !== "required")
3281
+ continue;
3282
+ const widened = addUndefined(shape.type);
3283
+ if (typeEquals(shape.type, widened))
3284
+ continue;
3285
+ shape.type = widened;
3286
+ const parameter = functionDeclBySymbol.get(target)?.parameters[i];
3287
+ if (parameter) {
3288
+ for (const bound of boundIdentifiersOf(parameter.name)) {
3289
+ const boundSymbol = symbolOf(bound);
3290
+ if (boundSymbol) {
3291
+ optionalSymbols.add(boundSymbol);
3292
+ if (ts.isIdentifier(parameter.name))
3293
+ this.runtimeOptionalBindingTypes.set(boundSymbol, shape.type);
3102
3294
  }
3103
3295
  }
3104
- });
3296
+ }
3297
+ changed = true;
3105
3298
  }
3106
3299
  }
3107
- return;
3108
3300
  }
3109
- node.arguments.forEach((arg, i) => {
3110
- const callbackSlot = sig.params[i]?.type;
3301
+ const restAt = sig.params.findIndex((shape) => shape.mode === "rest" || shape.mode === "dynRest" || shape.mode === "islandRest" || shape.mode === "arguments");
3302
+ node.arguments.forEach((arg, argumentIndex) => {
3303
+ const i = restAt >= 0 && argumentIndex >= restAt ? restAt : argumentIndex;
3304
+ const shape = sig.params[i];
3305
+ const callbackSlot = shape?.type;
3111
3306
  if (callbackSlot?.kind === "func" && !ts.isSpreadElement(arg)) {
3112
3307
  const optionalCallbackParams = callbackSlot.params.flatMap((type, index) => type.kind === "union" && this.armTag(type.unionId, UNDEFINED_T) >= 0 ? [index] : []);
3113
3308
  if (optionalCallbackParams.length > 0 && promoteHofCallback(arg, optionalCallbackParams)) {
3114
3309
  changed = true;
3115
3310
  }
3116
3311
  }
3117
- if (ts.isSpreadElement(arg) || !mayBeOptional(arg) || !sig.params[i])
3312
+ if (ts.isSpreadElement(arg) || !mayBeOptional(arg) || !shape)
3118
3313
  return;
3314
+ if (i === restAt) {
3315
+ // A rest binding always receives an array. An unchecked
3316
+ // argument can make its elements undefined, not the pack.
3317
+ // Keep every virtual implementation on the same array ABI.
3318
+ for (const target of familyBySymbol.get(symbol) ?? [symbol]) {
3319
+ const rest = signatureBySymbol.get(target)?.params[i];
3320
+ if (rest?.mode !== "rest" || rest.type.kind !== "array")
3321
+ continue;
3322
+ const widened = arrayOf(addUndefined(rest.type.elem));
3323
+ if (typeEquals(rest.type, widened))
3324
+ continue;
3325
+ rest.type = widened;
3326
+ const parameter = functionDeclBySymbol.get(target)?.parameters[i];
3327
+ if (parameter && ts.isIdentifier(parameter.name)) {
3328
+ const bound = symbolOf(parameter.name);
3329
+ if (bound)
3330
+ this.runtimeOptionalBindingTypes.set(bound, widened);
3331
+ }
3332
+ changed = true;
3333
+ }
3334
+ return;
3335
+ }
3119
3336
  const set = optionalParams.get(symbol) ?? new Set();
3337
+ shape.type = addUndefined(shape.type);
3120
3338
  const before = set.size;
3121
3339
  set.add(i);
3122
3340
  optionalParams.set(symbol, set);
@@ -3136,40 +3354,24 @@ export class Lowerer {
3136
3354
  }
3137
3355
  });
3138
3356
  }
3139
- });
3357
+ };
3358
+ for (const node of sitesOf(sf))
3359
+ scan(node);
3140
3360
  return changed;
3141
3361
  };
3142
3362
  const scanReturns = (symbol, decl) => {
3143
- if (!decl.body)
3144
- return false;
3145
3363
  let changed = false;
3146
- if (!ts.isBlock(decl.body) && mayBeOptional(decl.body) && !optionalReturns.has(symbol)) {
3147
- optionalReturns.add(symbol);
3148
- changed = true;
3149
- }
3150
- if (!ts.isBlock(decl.body)) {
3151
- const arithmetic = optionalStringArithmeticType(decl.body);
3364
+ for (const expression of returnsOf(decl)) {
3365
+ if (mayBeOptional(expression) && !optionalReturns.has(symbol)) {
3366
+ optionalReturns.add(symbol);
3367
+ changed = true;
3368
+ }
3369
+ const arithmetic = optionalStringArithmeticType(expression);
3152
3370
  if (arithmetic && !arithmeticReturns.has(symbol)) {
3153
3371
  arithmeticReturns.set(symbol, arithmetic);
3154
3372
  changed = true;
3155
3373
  }
3156
3374
  }
3157
- ts.walkPreorder(decl.body, (node) => {
3158
- if (node !== decl.body && (ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node) || ts.isArrowFunction(node) || ts.isMethodDeclaration(node)))
3159
- return "skip";
3160
- if (ts.isReturnStatement(node) && node.expression && mayBeOptional(node.expression) && !optionalReturns.has(symbol)) {
3161
- optionalReturns.add(symbol);
3162
- changed = true;
3163
- }
3164
- if (ts.isReturnStatement(node) && node.expression) {
3165
- const arithmetic = optionalStringArithmeticType(node.expression);
3166
- if (arithmetic && !arithmeticReturns.has(symbol)) {
3167
- arithmeticReturns.set(symbol, arithmetic);
3168
- changed = true;
3169
- }
3170
- }
3171
- return undefined;
3172
- });
3173
3375
  return changed;
3174
3376
  };
3175
3377
  let changed = true;
@@ -3181,6 +3383,18 @@ export class Lowerer {
3181
3383
  for (const [symbol, decl] of functionDeclBySymbol)
3182
3384
  if (scanReturns(symbol, decl))
3183
3385
  changed = true;
3386
+ // Every implementation of a virtual slot must retain the same ABI,
3387
+ // including when just one body forwards an omitted parameter.
3388
+ for (const family of optionalMethodFamilies) {
3389
+ if (!family.some((symbol) => optionalReturns.has(symbol)))
3390
+ continue;
3391
+ for (const symbol of family) {
3392
+ if (!optionalReturns.has(symbol)) {
3393
+ optionalReturns.add(symbol);
3394
+ changed = true;
3395
+ }
3396
+ }
3397
+ }
3184
3398
  }
3185
3399
  for (const [symbol, sig] of signatureBySymbol) {
3186
3400
  const params = optionalParams.get(symbol);
@@ -3306,7 +3520,7 @@ export class Lowerer {
3306
3520
  continue;
3307
3521
  const sig = declSymbol ? this.fnSigsBySymbol.get(declSymbol) : undefined;
3308
3522
  // A body nothing reaches never lowers: its constructs can't fail
3309
- // the build and it leaves no trace in the emitted C.
3523
+ // the build and it leaves no trace in the emitted LLVM.
3310
3524
  if (sig && !this.wantBody(sig.name))
3311
3525
  continue;
3312
3526
  const fn = this.lowerFunction(decl);
@@ -3352,7 +3566,10 @@ export class Lowerer {
3352
3566
  let gc = 0;
3353
3567
  let gi = 0;
3354
3568
  let es = 0;
3355
- while (ec < this.exprClasses.length ||
3569
+ const classDispatch = new ClassDynamicDispatch();
3570
+ let dispatchChanged = !this.remainder;
3571
+ while (dispatchChanged ||
3572
+ ec < this.exprClasses.length ||
3356
3573
  gc < this.genericClassInstances.length ||
3357
3574
  gi < this.instantiationQueue.length ||
3358
3575
  es < this.emitSpecQueue.length) {
@@ -3390,6 +3607,9 @@ export class Lowerer {
3390
3607
  throw e;
3391
3608
  }
3392
3609
  }
3610
+ dispatchChanged = !this.remainder && classDispatch.process(this, [
3611
+ ...functions, ...this.liftedFns, ...this.implicitFns,
3612
+ ]);
3393
3613
  }
3394
3614
  }
3395
3615
  // Lambdas lifted while lowering any of the above (plus synthetic
@@ -3423,6 +3643,7 @@ export class Lowerer {
3423
3643
  /** Final retention, pruning, and module assembly shared by ordinary emit
3424
3644
  * and the retained reachability worklist. */
3425
3645
  finishModule(functions) {
3646
+ finalizeClassMethodValues(this, functions);
3426
3647
  // Globals typed by a class that never REGISTERED (a JS class whose
3427
3648
  // collection fenced — Symbol-keyed fields, an unsupported base): the
3428
3649
  // declaration statement and every use compiled to runtime fences, but
@@ -3433,8 +3654,9 @@ export class Lowerer {
3433
3654
  // fences), so drop it — guarded by a reference scan, with the
3434
3655
  // validator's registration check as the backstop for anything that
3435
3656
  // does slip through with a live reference.
3436
- const brokenGlobals = this.globalsList.filter((g) => this.typeNamesUnregisteredClass(g.type));
3437
- const brokenLocalFns = functions.filter((fn) => fn.locals.some((l) => this.typeNamesUnregisteredClass(l.type)));
3657
+ const unregistered = new UnregisteredClassTypes((id) => this.shapes.get(id), (id) => this.unions.get(id), (name) => this.classes.has(name));
3658
+ const brokenGlobals = this.globalsList.filter((g) => unregistered.has(g.type));
3659
+ const brokenLocalFns = functions.filter((fn) => fn.locals.some((l) => unregistered.has(l.type)));
3438
3660
  if (brokenGlobals.length > 0 || brokenLocalFns.length > 0) {
3439
3661
  const referencedIn = (root) => {
3440
3662
  const referenced = new Set();
@@ -3455,7 +3677,7 @@ export class Lowerer {
3455
3677
  referenced.add(catchId);
3456
3678
  // Closure captures name their source locals as PLAIN STRINGS
3457
3679
  // (captures: string[]) — a captured broken-class local is live.
3458
- if (rec["kind"] === "closure" && Array.isArray(rec["captures"])) {
3680
+ if ((rec["kind"] === "closure" || rec["kind"] === "classRef") && Array.isArray(rec["captures"])) {
3459
3681
  for (const c of rec["captures"])
3460
3682
  if (typeof c === "string")
3461
3683
  referenced.add(c);
@@ -3483,8 +3705,8 @@ export class Lowerer {
3483
3705
  for (const fn of brokenLocalFns) {
3484
3706
  // Params and captures list their locals by id too — never prune
3485
3707
  // those out from under them.
3486
- const referenced = referencedIn([fn.body, fn.params, fn.captures ?? []]);
3487
- fn.locals = fn.locals.filter((l) => referenced.has(l.id) || !this.typeNamesUnregisteredClass(l.type));
3708
+ const referenced = referencedIn([fn.body, fn.params, fn.captures ?? [], fn.classCaptures ?? []]);
3709
+ fn.locals = fn.locals.filter((l) => referenced.has(l.id) || !unregistered.has(l.type));
3488
3710
  }
3489
3711
  }
3490
3712
  // Computed before the module gate: retention resolves every class name
@@ -3502,13 +3724,10 @@ export class Lowerer {
3502
3724
  // slots), uniformly across params/locals/globals/fields/body types so
3503
3725
  // every producer and consumer agrees. Programs with no unregistered
3504
3726
  // reference are untouched — byte-stability holds.
3505
- if (this.diags.length === 0) {
3506
- this.sanitizeUnregisteredClassTypes([functions, this.globalsList, artifacts.classes, artifacts.records, artifacts.unions]);
3507
- }
3508
3727
  const module = this.diags.length > 0
3509
3728
  ? null
3510
3729
  : {
3511
- irVersion: 11,
3730
+ irVersion: 13,
3512
3731
  sourceFile: this.entry.fileName,
3513
3732
  functions,
3514
3733
  classes: artifacts.classes,
@@ -3519,6 +3738,8 @@ export class Lowerer {
3519
3738
  entry: ENTRY_NAME,
3520
3739
  ...(this.ffiImports.length > 0 ? { ffiImports: [...this.ffiImports] } : {}),
3521
3740
  };
3741
+ if (module)
3742
+ sanitizeUnregisteredClassTypes(module, (name) => this.classes.has(name));
3522
3743
  return {
3523
3744
  module,
3524
3745
  diagnostics: this.diags,
@@ -3530,45 +3751,6 @@ export class Lowerer {
3530
3751
  ...(this.npmLazyTraps ? { npmLazyTraps: this.npmLazyTraps } : {}),
3531
3752
  };
3532
3753
  }
3533
- /** The unregistered-class type sweep (run()'s last step before the
3534
- * module assembles): every `{kind:"object"}` TYPE naming a class with
3535
- * no registered ClassInfo is rewritten IN PLACE to the f64 dummy.
3536
- * classval types are exempt (they emit the class-independent
3537
- * `ScrClassObj *` — inert-but-valid storage, the validator's own
3538
- * stance), and only type objects rewrite — node-level classNames
3539
- * (`new`, upcasts) cannot reach here (their lowerings fence without a
3540
- * registered class), so the validator still backstops those. */
3541
- sanitizeUnregisteredClassTypes(roots) {
3542
- const isUnregisteredObjectType = (v) => typeof v === "object" && v !== null &&
3543
- v.kind === "object" &&
3544
- typeof v.className === "string" &&
3545
- !this.classes.has(v.className);
3546
- const sweep = (node) => {
3547
- if (node === null || typeof node !== "object")
3548
- return;
3549
- if (Array.isArray(node)) {
3550
- node.forEach((item, i) => {
3551
- if (isUnregisteredObjectType(item))
3552
- node[i] = F64;
3553
- else
3554
- sweep(item);
3555
- });
3556
- return;
3557
- }
3558
- const rec = node;
3559
- for (const key of Object.keys(rec)) {
3560
- if (key === "loc")
3561
- continue;
3562
- const v = rec[key];
3563
- if (isUnregisteredObjectType(v))
3564
- rec[key] = F64;
3565
- else
3566
- sweep(v);
3567
- }
3568
- };
3569
- for (const root of roots)
3570
- sweep(root);
3571
- }
3572
3754
  /** True when `t` (recursively) names a class instance type with no
3573
3755
  * registered ClassInfo — the shape of a JS class whose collection fenced.
3574
3756
  * Used by run()'s global pruning; shapes/unions recurse with a seen-set
@@ -3666,11 +3848,16 @@ export class Lowerer {
3666
3848
  const bodyRoots = (...roots) => roots.filter((root) => root !== undefined && root !== null);
3667
3849
  const functionRoots = (decl) => bodyRoots(...decl.parameters.map((param) => param.initializer), decl.body);
3668
3850
  const classCtorRoots = (info) => bodyRoots(...(info.ctor?.parameters ?? []).map((param) => param.initializer), info.ctor?.body, ...info.fieldOrder.map((field) => field.initializer));
3669
- const classMemberRoots = (info) => [
3670
- ...classCtorRoots(info),
3671
- ...[...this.classMethodMembers(info)].flatMap(({ member }) => functionRoots(member)),
3672
- ...[...(info.staticMethods?.values() ?? [])].flatMap(({ member }) => functionRoots(member)),
3673
- ];
3851
+ const classMemberRoots = (info) => {
3852
+ const roots = classCtorRoots(info);
3853
+ for (const { member } of this.classMethodMembers(info))
3854
+ roots.push(...functionRoots(member));
3855
+ if (info.staticMethods) {
3856
+ for (const { member } of info.staticMethods.values())
3857
+ roots.push(...functionRoots(member));
3858
+ }
3859
+ return roots;
3860
+ };
3674
3861
  let unitOrder = 0;
3675
3862
  for (const fp of parts) {
3676
3863
  for (const decl of fp.fnDecls) {
@@ -3724,12 +3911,14 @@ export class Lowerer {
3724
3911
  });
3725
3912
  }
3726
3913
  }
3727
- for (const [name, entry] of info.staticMethods ?? []) {
3728
- units.set(`%${cName}.static:${name}`, {
3729
- order: unitOrder++,
3730
- roots: functionRoots(entry.member),
3731
- lower: () => lowerStaticMethod(this, info, name),
3732
- });
3914
+ if (info.staticMethods) {
3915
+ for (const [name, entry] of info.staticMethods) {
3916
+ units.set(`%${cName}.static:${name}`, {
3917
+ order: unitOrder++,
3918
+ roots: functionRoots(entry.member),
3919
+ lower: () => lowerStaticMethod(this, info, name),
3920
+ });
3921
+ }
3733
3922
  }
3734
3923
  }
3735
3924
  // The old emit pass visited each file's functions and then its classes,
@@ -3764,8 +3953,10 @@ export class Lowerer {
3764
3953
  rank(`%${cName}.constructor`);
3765
3954
  for (const { mName } of this.classMethodMembers(info))
3766
3955
  rank(`%${cName}.${mName}`);
3767
- for (const name of info.staticMethods?.keys() ?? [])
3768
- rank(`%${cName}.static:${name}`);
3956
+ if (info.staticMethods) {
3957
+ for (const name of info.staticMethods.keys())
3958
+ rank(`%${cName}.static:${name}`);
3959
+ }
3769
3960
  for (const prop of info.throwingSetters)
3770
3961
  rank(`%${cName}.set:${prop}`);
3771
3962
  }
@@ -3811,9 +4002,10 @@ export class Lowerer {
3811
4002
  for (const { mName, member } of this.classMethodMembers(info)) {
3812
4003
  register(`%${cName}.${mName}`, functionRoots(member), () => this.lowerClassMethodMember(info, member));
3813
4004
  }
3814
- for (const [name, entry] of info.staticMethods ?? []) {
3815
- register(`%${cName}.static:${name}`, functionRoots(entry.member), () => lowerStaticMethod(this, info, name));
3816
- }
4005
+ if (info.staticMethods)
4006
+ for (const [name, entry] of info.staticMethods) {
4007
+ register(`%${cName}.static:${name}`, functionRoots(entry.member), () => lowerStaticMethod(this, info, name));
4008
+ }
3817
4009
  for (const prop of info.throwingSetters) {
3818
4010
  register(`%${cName}.set:${prop}`, [], () => this.throwingSetterFn(info, prop));
3819
4011
  }
@@ -3939,9 +4131,13 @@ export class Lowerer {
3939
4131
  // turn queue more instances. Continue to the joint fixpoint; the initial
3940
4132
  // queue above is the only portion whose discovery order differed from
3941
4133
  // historical emit order.
4134
+ const classDispatch = new ClassDynamicDispatch(extraRoots !== undefined);
3942
4135
  for (;;) {
3943
4136
  drainInstances();
3944
- if (queue.length === 0)
4137
+ const dispatchChanged = classDispatch.process(this, [
4138
+ ...loweredUnits.values(), ...initFunctions, ...instanceFunctions, ...this.liftedFns, ...this.implicitFns,
4139
+ ]);
4140
+ if (queue.length === 0 && !dispatchChanged)
3945
4141
  break;
3946
4142
  drainUnits();
3947
4143
  this.restoreGenericInstanceOrder(instLowered);
@@ -4027,7 +4223,8 @@ export class Lowerer {
4027
4223
  if (target.kind === "statement")
4028
4224
  return fence;
4029
4225
  const params = target.params ?? [];
4030
- const name = typeof target.name === "function" ? target.name() : target.name;
4226
+ const targetName = target.name;
4227
+ const name = typeof targetName === "function" ? targetName() : targetName;
4031
4228
  const fn = {
4032
4229
  name,
4033
4230
  params,
@@ -4198,7 +4395,7 @@ export class Lowerer {
4198
4395
  // package-declared generic signature stays the package's story.
4199
4396
  {
4200
4397
  const parts = widened.isUnionType() ? ts.constituentTypes(widened) : [widened];
4201
- if (parts.some((p) => this.checker.getCallSignatures(p).some((s) => (s.typeParameters?.length ?? 0) > 0))) {
4398
+ if (parts.some((p) => this.checker.getCallSignatures(p).some((s) => s.getTypeParameters().length > 0))) {
4202
4399
  this.pushDiag(genericSignatureTypeDiag(this.checker.typeToString(type), locOf(node)));
4203
4400
  throw new PoisonError();
4204
4401
  }
@@ -4279,8 +4476,8 @@ export class Lowerer {
4279
4476
  RelativeTimeFormat: intlHint,
4280
4477
  Segmenter: intlHint,
4281
4478
  DisplayNames: intlHint,
4282
- TextEncoder: "TextEncoder values have no representation — call through a const initialized with new TextEncoder(), or use the composed new TextEncoder().encode(s) form",
4283
- TextDecoder: "TextDecoder values have no representation — call through a const initialized with a recognized literal label, or use the composed new TextDecoder(<literal label>).decode(bytes) form",
4479
+ TextEncoder: "TextEncoder instances support encode(string) and encode(); other codec operations require a dedicated lowering",
4480
+ TextDecoder: "TextDecoder instances support recognized literal labels with default options and whole-buffer decode(Uint8Array); runtime labels and options remain unsupported",
4284
4481
  };
4285
4482
  this.pushDiag(noLoweringDiag(this.checker.typeToString(type), locOf(node), typeHints[stdlibOwnSym?.name ?? ""]));
4286
4483
  throw new PoisonError();
@@ -4377,6 +4574,11 @@ export class Lowerer {
4377
4574
  return bound;
4378
4575
  if (typeEquals(narrowedIr, boundIr))
4379
4576
  return t;
4577
+ // A checked value can contain any runtime kind. A checker-proven
4578
+ // branch narrow therefore cannot contradict this specialization;
4579
+ // reads still validate the payload through maybeNarrow.
4580
+ if (boundIr.kind === "dyn")
4581
+ return t;
4380
4582
  // A union binding narrowed to one of its arms (typeof/equality
4381
4583
  // guards over string|number bindings) — the narrow is truth.
4382
4584
  if (boundIr.kind === "union") {
@@ -4397,10 +4599,11 @@ export class Lowerer {
4397
4599
  return t;
4398
4600
  }
4399
4601
  /** mapType with this Lowerer's registries and (while a generic instance
4400
- * body lowers) type-parameter bindings threaded through. */
4401
- mapTypeOf(t) {
4402
- const mapped = mapType(t, this.typeCtx);
4403
- return mapped?.kind === "func" ? jsArgumentsFunctionType(this, t) ?? mapped : mapped;
4602
+ * body lowers) type-parameter bindings threaded through. A supplied mapper
4603
+ * retains interface-view substitutions while sharing ABI normalization. */
4604
+ mapTypeOf(t, mapper) {
4605
+ const mapped = mapper ? mapper(t) : mapType(t, this.typeCtx);
4606
+ return mapped === null || mapped.kind === "func" ? jsArgumentsFunctionType(this, t) ?? mapped : mapped;
4404
4607
  }
4405
4608
  /** The one position where a contextual UNION must not be adopted over the
4406
4609
  * expression's own: the LEFT operand of `&&`, `||`, or `??`. Adopting a
@@ -4555,6 +4758,11 @@ export class Lowerer {
4555
4758
  };
4556
4759
  irTypeOf(node) {
4557
4760
  const t = this.typeOf(node);
4761
+ // JS inference can leave mutable fields, accessor parameters and
4762
+ // locals at null/undefined despite later writes. Keep mutable native
4763
+ // storage instead of a slot restricted to the initializer's unit value.
4764
+ if (isJsSourceFile(node.getSourceFile()) && (t.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined)) !== 0)
4765
+ return DYN;
4558
4766
  // A never-tainted JS type (neverTaintedJsType) maps — never rides as
4559
4767
  // f64 — but must not: pre-empt the mapping so the JS fallback below
4560
4768
  // answers instead.
@@ -4577,7 +4785,7 @@ export class Lowerer {
4577
4785
  return dyn;
4578
4786
  this.badType(node, t);
4579
4787
  }
4580
- return mapped;
4788
+ return jsOpenObjectType(node, mapped, this.shapes, this.unions);
4581
4789
  }
4582
4790
  /** Exact-shape enforcement (SC2002). Records are monomorphic structs, so
4583
4791
  * everywhere a value flows into a typed slot (call arg, initializer,
@@ -4795,8 +5003,11 @@ export class Lowerer {
4795
5003
  return { kind: "promiseVoidWiden", value: expr, type: expected, loc: expr.loc };
4796
5004
  }
4797
5005
  if (expected.kind === "dyn" && expr.type.kind !== "dyn") {
4798
- if (expr.kind === "unitLit" || this.dynConvertible(expr.type)) {
4799
- return { kind: "dynFrom", value: expr, type: DYN, loc: expr.loc };
5006
+ // Native void calls still have a JavaScript value: undefined. Keep
5007
+ // the call's effects before exposing that value to checked JS code.
5008
+ if (expr.type.kind === "void") {
5009
+ return { kind: "seqExpr", stmts: [{ kind: "exprStmt", expr, loc: expr.loc }],
5010
+ result: dynUndefinedExpr(expr.loc), type: DYN, loc: expr.loc };
4800
5011
  }
4801
5012
  // An error-HIERARCHY object (builtin subclass or user `extends
4802
5013
  // Error` class) upcasts to the %Error root first — the caughtToDyn
@@ -4813,6 +5024,9 @@ export class Lowerer {
4813
5024
  loc: expr.loc,
4814
5025
  };
4815
5026
  }
5027
+ if (expr.kind === "unitLit" || this.dynConvertible(expr.type)) {
5028
+ return { kind: "dynFrom", value: expr, type: DYN, loc: expr.loc };
5029
+ }
4816
5030
  return expr;
4817
5031
  }
4818
5032
  // A dyn ('unknown') ACTUAL flowing into a typed slot the checker
@@ -4848,7 +5062,7 @@ export class Lowerer {
4848
5062
  const funcOk = expected.kind === "func" &&
4849
5063
  canAdaptDynFuncTo(expected, (id) => this.shapes.get(id), (id) => this.unions.get(id));
4850
5064
  const handleOk = DYN_HANDLE_KINDS.has(expected.kind);
4851
- if (this.jsonSafe(expected) || undefArmedOk || bytesOk || errorOk || classOk || funcOk || handleOk) {
5065
+ if (canDynCheckTo(expected, (id) => this.shapes.get(id), (id) => this.unions.get(id)) || undefArmedOk || bytesOk || errorOk || classOk || funcOk || handleOk) {
4852
5066
  return { kind: "dynCheck", value: expr, type: expected, loc: expr.loc };
4853
5067
  }
4854
5068
  return expr;
@@ -5005,6 +5219,11 @@ export class Lowerer {
5005
5219
  return expr;
5006
5220
  }
5007
5221
  const tag = this.armTag(expected.unionId, expr.type);
5222
+ if (tag >= 0 && expr.type.kind === "record" && expr.kind !== "recordLit") {
5223
+ const helper = this.recordUnionWrapHelper(expr.type, expected.unionId, expr.loc);
5224
+ if (helper)
5225
+ return { kind: "call", callee: helper, args: [expr], type: expected, loc: expr.loc };
5226
+ }
5008
5227
  if (tag < 0) {
5009
5228
  // A derived class flowing into a union with a base-class arm widens
5010
5229
  // first (nearest ancestor arm wins), then wraps like any arm value.
@@ -5174,9 +5393,11 @@ export class Lowerer {
5174
5393
  * before any helper exists. The cases, in order:
5175
5394
  * copy — exact same type (typeEquals), the field/element moves as is
5176
5395
  * retag — union into union, every arm mapped (unionRetagMappable —
5177
- * identity arms, trap-less; record/array arms may width-lift
5178
- * into exactly one destination arm)
5396
+ * identity arms and compatible payload conversions; a shared
5397
+ * discriminant may select different record destinations)
5179
5398
  * wrap — a non-unit arm value into a union that contains it
5399
+ * discriminantWrap — identical recursive layouts distinguished by
5400
+ * their literal field value rather than their storage id
5180
5401
  * liftWrap — a record/array value into a union with NO identical arm
5181
5402
  * but exactly ONE arm it width-lifts into (the findRoute
5182
5403
  * rule applied at every level; several candidates are
@@ -5211,17 +5432,25 @@ export class Lowerer {
5211
5432
  if (isUnitType(src))
5212
5433
  return null;
5213
5434
  const tag = this.armTag(dst.unionId, src);
5214
- if (tag >= 0)
5215
- return { how: "wrap", tag };
5216
5435
  const def = this.unions.get(dst.unionId);
5217
5436
  if (!def)
5218
5437
  return null;
5438
+ if (tag >= 0) {
5439
+ const shape = src.kind === "record" ? this.shapes.get(src.shapeId) : undefined;
5440
+ if (shape && planRecordUnionWrap(shape, def, (id) => this.shapes.get(id)))
5441
+ return { how: "discriminantWrap" };
5442
+ return { how: "wrap", tag };
5443
+ }
5219
5444
  const candidates = [];
5220
5445
  def.arms.forEach((arm, i) => {
5221
5446
  if (isUnitType(arm))
5222
5447
  return;
5223
5448
  const sameFamily = (src.kind === "record" && arm.kind === "record") ||
5224
5449
  (src.kind === "array" && arm.kind === "array") ||
5450
+ (src.kind === "object" && arm.kind === "object") ||
5451
+ // Tuples already lift into ordinary array slots. Consider that
5452
+ // same conversion when the array is an arm of a union too.
5453
+ (src.kind === "record" && this.shapes.get(src.shapeId)?.tuple === true && arm.kind === "array") ||
5225
5454
  (src.kind === "object" && arm.kind === "record") ||
5226
5455
  (src.kind === "record" && arm.kind === "object");
5227
5456
  if (sameFamily && this.widthLiftPlan(src, arm) !== null)
@@ -5260,6 +5489,25 @@ export class Lowerer {
5260
5489
  if (dst.kind === "record" && src.kind === "record") {
5261
5490
  return this.recordWidthPlan(src.shapeId, dst.shapeId) !== null ? { how: "width" } : null;
5262
5491
  }
5492
+ if (dst.kind === "record" && src.kind === "union") {
5493
+ // A union of records can share a structural destination without
5494
+ // choosing one payload layout in advance. Plan every arm: omitted
5495
+ // destination fields need the ordinary optional-field completion,
5496
+ // and a required field missing from any arm still rejects the pair.
5497
+ const from = this.unions.get(src.unionId);
5498
+ if (!from || from.arms.length === 0 || !from.arms.every((arm) => arm.kind === "record"))
5499
+ return null;
5500
+ const key = `unionWidth:${src.unionId}:${dst.shapeId}`;
5501
+ if (this.widthPlanning.has(key))
5502
+ return { how: "unionWidth" };
5503
+ this.widthPlanning.add(key);
5504
+ try {
5505
+ return from.arms.every((arm) => this.widthLiftPlan(arm, dst) !== null) ? { how: "unionWidth" } : null;
5506
+ }
5507
+ finally {
5508
+ this.widthPlanning.delete(key);
5509
+ }
5510
+ }
5263
5511
  if (dst.kind === "record" && src.kind === "object") {
5264
5512
  return this.objToRecordPlan(src.className, dst.shapeId) !== null ? { how: "objWidth" } : null;
5265
5513
  }
@@ -5313,6 +5561,14 @@ export class Lowerer {
5313
5561
  throw new InternalCompilerError("lowerer bug: wrap lift against a non-union");
5314
5562
  return { kind: "unionWrap", unionId: dst.unionId, tag: lift.tag, value, type: dst, loc };
5315
5563
  }
5564
+ case "discriminantWrap": {
5565
+ if (dst.kind !== "union" || value.type.kind !== "record")
5566
+ throw new InternalCompilerError("lowerer bug: record discriminator lift shape");
5567
+ const helper = this.recordUnionWrapHelper(value.type, dst.unionId, loc);
5568
+ if (!helper)
5569
+ throw new InternalCompilerError("lowerer bug: planned record discriminator lift failed to intern");
5570
+ return { kind: "call", callee: helper, args: [value], type: dst, loc };
5571
+ }
5316
5572
  case "retag": {
5317
5573
  if (dst.kind !== "union" || value.type.kind !== "union")
5318
5574
  throw new InternalCompilerError("lowerer bug: retag lift shape");
@@ -5338,6 +5594,12 @@ export class Lowerer {
5338
5594
  throw new InternalCompilerError("lowerer bug: planned width lift failed to intern");
5339
5595
  return { kind: "call", callee: helper, args: [value], type: dst, loc };
5340
5596
  }
5597
+ case "unionWidth": {
5598
+ if (dst.kind !== "record" || value.type.kind !== "union")
5599
+ throw new InternalCompilerError("lowerer bug: union width lift shape");
5600
+ const helper = this.unionRecordWidthHelper(value.type.unionId, dst, loc);
5601
+ return { kind: "call", callee: helper, args: [value], type: dst, loc };
5602
+ }
5341
5603
  case "arr": {
5342
5604
  if (dst.kind !== "array" || value.type.kind !== "array")
5343
5605
  throw new InternalCompilerError("lowerer bug: arr lift shape");
@@ -5409,6 +5671,50 @@ export class Lowerer {
5409
5671
  }
5410
5672
  }
5411
5673
  }
5674
+ /** Dispatch a structural copy from its runtime union tag. Each record
5675
+ * payload has its own field offsets and optional-field completions;
5676
+ * interpreting all arms as the destination layout would corrupt memory.
5677
+ * Intern before descending so recursive record unions can reuse it. */
5678
+ unionRecordWidthHelper(fromId, target, loc) {
5679
+ const key = `unionWidth:${fromId}:${target.shapeId}`;
5680
+ const existing = this.widthHelpers.get(key);
5681
+ if (existing)
5682
+ return existing;
5683
+ const name = `%union.record.${this.widthHelpers.size}`;
5684
+ this.widthHelpers.set(key, name);
5685
+ const type = { kind: "union", unionId: fromId };
5686
+ const value = varRef("value.0", type, loc);
5687
+ const from = this.unions.get(fromId);
5688
+ if (!from)
5689
+ throw new InternalCompilerError("lowerer bug: missing record union");
5690
+ const body = [];
5691
+ from.arms.forEach((arm, tag) => {
5692
+ const lift = this.widthLiftPlan(arm, target);
5693
+ if (!lift || arm.kind !== "record")
5694
+ throw new InternalCompilerError("lowerer bug: invalid union record plan");
5695
+ const narrowed = { kind: "unionNarrow", unionId: fromId, tag, value, type: arm, loc };
5696
+ body.push({
5697
+ kind: "if",
5698
+ cond: { kind: "unionIsTag", unionId: fromId, tag, negated: false, value, type: BOOL, loc },
5699
+ then: [{ kind: "return", value: this.applyWidthLift(lift, narrowed, target, loc), loc }],
5700
+ else_: null, loc,
5701
+ });
5702
+ });
5703
+ body.push({
5704
+ kind: "throw",
5705
+ value: {
5706
+ kind: "libCall", fn: "error.new",
5707
+ args: [{ kind: "strLit", value: "invalid record union tag", type: STRING, loc }],
5708
+ type: { kind: "object", className: "%TypeError" }, loc,
5709
+ },
5710
+ loc,
5711
+ });
5712
+ this.liftedFns.push({
5713
+ name, params: [{ localId: "value.0", name: "value", type }], returnType: target,
5714
+ locals: [{ id: "value.0", name: "value", type, mutable: false }], body, loc,
5715
+ });
5716
+ return name;
5717
+ }
5412
5718
  /** Interned `%rec.width.<n>(r)` — builds the target shape from a source
5413
5719
  * record by copying fields: every target field must exist on the source
5414
5720
  * with the EXACT same type, or with a type that LIFTS under
@@ -6157,6 +6463,7 @@ export class Lowerer {
6157
6463
  {
6158
6464
  kind: "callValue",
6159
6465
  callee: { kind: "varRef", localId: "f.0", type: fromT, loc },
6466
+ receiver: { kind: "libCall", fn: "dyn.this", args: [], type: DYN, loc },
6160
6467
  args: [],
6161
6468
  type: fromT.ret,
6162
6469
  loc,
@@ -6289,9 +6596,33 @@ export class Lowerer {
6289
6596
  // value — the call runs (a `never` thrower never comes back, so the
6290
6597
  // trap is unreachable there), then the stranded TypeError.
6291
6598
  let strandParams = false;
6599
+ const narrowedParams = new Map();
6600
+ const partialDynParams = new Map();
6292
6601
  for (let i = 0; i < fromT.params.length; i++) {
6293
- if (!this.coercibleValue(toT.params[i], fromT.params[i]))
6294
- strandParams = true;
6602
+ const actual = toT.params[i];
6603
+ const expected = fromT.params[i];
6604
+ if (this.coercibleValue(actual, expected))
6605
+ continue;
6606
+ if (actual.kind === "union" && expected.kind === "dyn") {
6607
+ const arms = this.unions.get(actual.unionId)?.arms.filter((arm) => this.dynConvertible(arm)) ?? [];
6608
+ if (arms.length > 0) {
6609
+ partialDynParams.set(i, arms.length === 1 ? arms[0] : { kind: "union", unionId: this.unions.intern(arms) });
6610
+ continue;
6611
+ }
6612
+ }
6613
+ // A stored native builtin can have a narrower supported overload
6614
+ // than its public declaration. Preserve every supported union arm
6615
+ // and reject only an invocation carrying an unsupported arm. This
6616
+ // is the union counterpart of the checked single-arm extraction.
6617
+ if (actual.kind === "union" && expected.kind === "union") {
6618
+ const source = this.unions.get(actual.unionId);
6619
+ const target = this.unions.get(expected.unionId);
6620
+ if (source && target && target.arms.every((arm) => this.armTag(actual.unionId, arm) >= 0)) {
6621
+ narrowedParams.set(i, new Set(source.arms.flatMap((arm, tag) => this.armTag(expected.unionId, arm) < 0 ? [tag] : [])));
6622
+ continue;
6623
+ }
6624
+ }
6625
+ strandParams = true;
6295
6626
  }
6296
6627
  let voidRet = null;
6297
6628
  let strandRet = false;
@@ -6339,7 +6670,25 @@ export class Lowerer {
6339
6670
  else {
6340
6671
  const args = fromT.params.map((pt, i) => {
6341
6672
  const aRef = { kind: "varRef", localId: `a.${i}`, type: toT.params[i], loc };
6342
- const converted = this.coerceToExpected(aRef, pt);
6673
+ const partial = partialDynParams.get(i);
6674
+ if (partial && aRef.type.kind === "union") {
6675
+ const source = this.unions.get(aRef.type.unionId);
6676
+ const supported = partial.kind === "union" ? this.unions.get(partial.unionId).arms : [partial];
6677
+ const rejected = new Set(source.arms.flatMap((arm, tag) => supported.some((accepted) => typeEquals(accepted, arm)) ? [] : [tag]));
6678
+ const narrow = partial.kind === "union"
6679
+ ? this.unionRetagHelper(aRef.type.unionId, partial.unionId, loc, rejected)
6680
+ : this.narrowedArmHelper(aRef.type.unionId, partial, loc);
6681
+ if (!narrow)
6682
+ throw new InternalCompilerError("lowerer bug: partial callable parameter stopped narrowing");
6683
+ return this.coerceToExpected({ kind: "call", callee: narrow, args: [aRef], type: partial, loc }, pt);
6684
+ }
6685
+ const narrowed = narrowedParams.get(i);
6686
+ const helper = narrowed && aRef.type.kind === "union" && pt.kind === "union"
6687
+ ? this.unionRetagHelper(aRef.type.unionId, pt.unionId, loc, narrowed)
6688
+ : null;
6689
+ const converted = helper
6690
+ ? { kind: "call", callee: helper, args: [aRef], type: pt, loc }
6691
+ : this.coerceToExpected(aRef, pt);
6343
6692
  if (!typeEquals(converted.type, pt))
6344
6693
  throw new InternalCompilerError("lowerer bug: probed fn-adapter param stopped coercing");
6345
6694
  return converted;
@@ -6347,6 +6696,7 @@ export class Lowerer {
6347
6696
  const call = {
6348
6697
  kind: "callValue",
6349
6698
  callee: { kind: "varRef", localId: "f.0", type: fromT, loc },
6699
+ receiver: { kind: "libCall", fn: "dyn.this", args: [], type: DYN, loc },
6350
6700
  args,
6351
6701
  type: fromT.ret,
6352
6702
  loc,
@@ -6508,6 +6858,7 @@ export class Lowerer {
6508
6858
  init: {
6509
6859
  kind: "callValue",
6510
6860
  callee: { kind: "varRef", localId: "f.0", type: fromT, loc },
6861
+ receiver: { kind: "libCall", fn: "dyn.this", args: [], type: DYN, loc },
6511
6862
  args: params.map((p) => ({ kind: "varRef", localId: p.localId, type: p.type, loc })),
6512
6863
  type: fromT.ret,
6513
6864
  loc,
@@ -6543,44 +6894,20 @@ export class Lowerer {
6543
6894
  });
6544
6895
  return name;
6545
6896
  }
6546
- /** Interned `%union.retag.<n>(u)` — the runtime re-tag for a value of
6547
- * union `fromId` flowing into a slot of union `toId`: a switch on the
6548
- * source tag re-wraps the payload under its tag in the destination
6549
- * (unionNarrow + unionWrap — the payload pointer moves, no copy, so
6550
- * ref-arm identity is preserved across the re-tag). Arms map by
6551
- * canonical type (typeEquals): every non-unit source arm must exist in
6552
- * the destination, or the pair isn't mappable (null — the caller keeps
6553
- * the SC2003 fence). A stranded UNIT arm (undefined/null with no
6554
- * destination arm) is different: it means tsc's picture at the site was
6555
- * NARROWER than the IR type — control-flow narrowing to a sub-union, or
6556
- * a non-null assertion, both of which erase at lowering — so the arm is
6557
- * exactly the possibility the checker proved (or the source asserted)
6558
- * away. It compiles to a runtime trap case throwing a catchable
6559
- * TypeError-shaped string, the lying-cast stance (SEMANTICS.md): sound
6560
- * narrowing never reaches it, a lying `!` throws instead of smuggling
6561
- * an unrepresentable unit into the destination. */
6562
- /** True when unionRetagHelper can bridge the pair — every non-unit
6563
- * source arm exists (typeEquals) in the destination, or width-lifts
6564
- * into exactly one destination arm (widthLiftPlan — record and array
6565
- * arms compose the re-tag with the per-arm reshape). Pure: callers that
6566
- * must validate a WHOLE plan before interning anything (recordWidthHelper)
6567
- * probe with this so a failed later field never orphans a helper. */
6897
+ /** Validate the complete union conversion before interning helpers.
6898
+ * Recursive width plans close through the same in-progress pair guard;
6899
+ * no optimistic result is memoized after that planning stack unwinds. */
6568
6900
  unionRetagMappable(fromId, toId) {
6569
6901
  const from = this.unions.get(fromId);
6570
- if (!from || !this.unions.get(toId))
6902
+ const to = this.unions.get(toId);
6903
+ if (!from || !to)
6571
6904
  return false;
6572
- // The union-pair face of the widthPlanning cycle guard: recursive
6573
- // aliases can close their cycle through a union without repeating a
6574
- // record pair (`type Json = Json[] | undefined`) — an in-progress
6575
- // pair re-entered answers "assume mappable", same greatest-fixed-point
6576
- // reading as recordWidthPlan's.
6577
6905
  const key = `u:${fromId}:${toId}`;
6578
6906
  if (this.widthPlanning.has(key))
6579
6907
  return true;
6580
6908
  this.widthPlanning.add(key);
6581
6909
  try {
6582
- const toT = { kind: "union", unionId: toId };
6583
- return from.arms.every((arm) => isUnitType(arm) || this.widthLiftPlan(arm, toT) !== null);
6910
+ return planUnionRetag(from, to, (id) => this.shapes.get(id), (src, dst) => this.widthLiftPlan(src, dst)) !== null;
6584
6911
  }
6585
6912
  finally {
6586
6913
  this.widthPlanning.delete(key);
@@ -6751,111 +7078,44 @@ export class Lowerer {
6751
7078
  }
6752
7079
  return { kind: "call", callee: name, args: isUnitType(src) ? [] : [expr], type: expected, loc };
6753
7080
  }
7081
+ recordUnionWrapHelper(source, toId, loc) {
7082
+ const shape = this.shapes.get(source.shapeId);
7083
+ const to = this.unions.get(toId);
7084
+ if (!shape || !to)
7085
+ return null;
7086
+ const plan = planRecordUnionWrap(shape, to, (id) => this.shapes.get(id));
7087
+ if (!plan)
7088
+ return null;
7089
+ const key = `recordWrap:${source.shapeId}:${toId}`;
7090
+ const existing = this.retagHelpers.get(key);
7091
+ if (existing)
7092
+ return existing;
7093
+ const name = `%record.wrap.${this.retagHelpers.size}`;
7094
+ this.retagHelpers.set(key, name);
7095
+ this.liftedFns.push(buildRecordUnionWrap(name, source, to, plan, loc, (lift, value, dst) => this.applyWidthLift(lift, value, dst, loc)));
7096
+ return name;
7097
+ }
6754
7098
  unionRetagHelper(fromId, toId, loc, trappable) {
6755
7099
  const from = this.unions.get(fromId);
6756
7100
  const to = this.unions.get(toId);
6757
7101
  if (!from || !to)
6758
7102
  return null;
6759
- // Per-arm WIDTH LIFTS: a RECORD or ARRAY arm with no identical
6760
- // destination arm may width-lift into exactly ONE destination arm
6761
- // (widthLiftPlan's liftWrap — the findRoute pattern: `{hostname, port,
6762
- // tailscaleUrl?} | undefined` returning as `{hostname, port} |
6763
- // undefined`; nested width and per-element array reshapes compose).
6764
- // Planned PURELY first so a failing arm never orphans an interned
6765
- // width helper; ambiguity (several liftable destination arms) declines
6766
- // — no honest single mapping exists. A lifted arm is a COPY
6767
- // (divergence 35's stance), unlike the identity-preserving plain
6768
- // re-wrap.
6769
- const toT = { kind: "union", unionId: toId };
6770
- const lifts = new Map();
6771
- from.arms.forEach((arm, i) => {
6772
- if (this.armTag(toId, arm) >= 0 || isUnitType(arm) || (trappable?.has(i) ?? false))
6773
- return;
6774
- const lp = this.widthLiftPlan(arm, toT);
6775
- if (lp && lp.how === "liftWrap")
6776
- lifts.set(i, lp);
6777
- });
6778
- // `trappable` extends the unit-arm rule to arms the CHECKER proved
6779
- // away at the coercion site (narrowedRetagHelper): those may trap too.
6780
- const ok = from.arms.every((arm, i) => this.armTag(toId, arm) >= 0 || isUnitType(arm) || (trappable?.has(i) ?? false) || lifts.has(i));
6781
- if (!ok)
7103
+ const plan = planUnionRetag(from, to, (id) => this.shapes.get(id), (src, dst) => this.widthLiftPlan(src, dst), trappable);
7104
+ if (plan === null)
6782
7105
  return null;
6783
- const mapping = from.arms.map((arm, i) => {
6784
- const identity = this.armTag(toId, arm);
6785
- return identity >= 0 ? identity : (lifts.get(i)?.tag ?? -1);
6786
- });
6787
- const stranded = mapping.flatMap((t, i) => (t < 0 ? [i] : []));
6788
- // Lifts are a pure function of the (from, to) pair, so the historic
6789
- // key stays sound for them; stranded arms depend on the SITE.
7106
+ // The registry pair determines every route; only checker-proven
7107
+ // stranded arms vary by site. Publish the name before building widths
7108
+ // so recursive records and arrays can call this same helper.
7109
+ const stranded = [];
7110
+ plan.forEach((arm, tag) => { if (arm.kind === "trap")
7111
+ stranded.push(tag); });
6790
7112
  const key = `${fromId}:${toId}:${stranded.join(".")}`;
6791
7113
  const existing = this.retagHelpers.get(key);
6792
7114
  if (existing)
6793
7115
  return existing;
6794
7116
  const name = `%union.retag.${this.retagHelpers.size}`;
6795
7117
  this.retagHelpers.set(key, name);
6796
- const fromT = { kind: "union", unionId: fromId };
6797
- const u = { kind: "varRef", localId: "u.0", type: fromT, loc };
6798
- const body = [];
6799
- from.arms.forEach((arm, i) => {
6800
- const tag = mapping[i];
6801
- const cond = { kind: "unionIsTag", unionId: fromId, tag: i, negated: false, value: u, type: BOOL, loc };
6802
- let then;
6803
- if (tag < 0) {
6804
- const what = isUnitType(arm)
6805
- ? (arm.kind === "undefinedT" ? "undefined" : "null")
6806
- : `a '${this.fmt(arm)}' value`;
6807
- then = [
6808
- {
6809
- kind: "throw",
6810
- value: {
6811
- kind: "libCall",
6812
- fn: "error.new",
6813
- args: [
6814
- {
6815
- kind: "strLit",
6816
- value: `${what} is not representable in the target union (a value narrowed or asserted past it still held it)`,
6817
- type: STRING,
6818
- loc,
6819
- },
6820
- ],
6821
- type: { kind: "object", className: "%TypeError" },
6822
- loc,
6823
- },
6824
- loc,
6825
- },
6826
- ];
6827
- }
6828
- else {
6829
- const value = isUnitType(arm)
6830
- ? { kind: "unitLit", unit: arm.kind === "undefinedT" ? "undefined" : "null", type: arm, loc }
6831
- : { kind: "unionNarrow", unionId: fromId, tag: i, value: u, type: arm, loc };
6832
- const lift = lifts.get(i);
6833
- // Width-lifted arm: the narrowed payload reshapes into the
6834
- // destination arm and wraps (applyWidthLift — planned above, so
6835
- // the interns cannot fail here); identity arms re-wrap the same
6836
- // payload pointer.
6837
- const wrapped = lift
6838
- ? this.applyWidthLift(lift, value, toT, loc)
6839
- : { kind: "unionWrap", unionId: toId, tag, value, type: toT, loc };
6840
- then = [{ kind: "return", value: wrapped, loc }];
6841
- }
6842
- body.push({ kind: "if", cond, then, else_: null, loc });
6843
- });
6844
- // Unreachable when tags are exhaustive (they are, by construction);
6845
- // satisfies the all-paths-return rule and keeps a corrupted tag loud.
6846
- body.push({
6847
- kind: "throw",
6848
- value: { kind: "strLit", value: "scriptc: internal error: invalid union tag", type: STRING, loc },
6849
- loc,
6850
- });
6851
- this.liftedFns.push({
6852
- name,
6853
- params: [{ localId: "u.0", name: "u", type: fromT }],
6854
- returnType: toT,
6855
- locals: [{ id: "u.0", name: "u", type: fromT, mutable: true }],
6856
- body,
6857
- loc,
6858
- });
7118
+ this.liftedFns.push(buildUnionRetag(name, from, to, plan, loc, (lift, value, dst) => this.applyWidthLift(lift, value, dst, loc), (type) => this.fmt(type)));
6859
7119
  return name;
6860
7120
  }
6861
7121
  /** Interned `%union.narrow.<n>(u)` — the CHECKED single-arm extraction
@@ -6881,55 +7141,10 @@ export class Lowerer {
6881
7141
  const name = `%union.narrow.${this.narrowHelpers.size}`;
6882
7142
  this.narrowHelpers.set(key, name);
6883
7143
  this.checkedNarrowHelpers.add(name);
6884
- const fromT = { kind: "union", unionId: fromId };
6885
- const u = { kind: "varRef", localId: "u.0", type: fromT, loc };
6886
- const body = [];
6887
- from.arms.forEach((arm, i) => {
6888
- if (i === tag)
6889
- return; // the fall-through extraction below
6890
- const what = isUnitType(arm)
6891
- ? (arm.kind === "undefinedT" ? "undefined" : "null")
6892
- : `a '${this.fmt(arm)}' value`;
6893
- body.push({
6894
- kind: "if",
6895
- cond: { kind: "unionIsTag", unionId: fromId, tag: i, negated: false, value: u, type: BOOL, loc },
6896
- then: [
6897
- {
6898
- kind: "throw",
6899
- value: {
6900
- kind: "libCall",
6901
- fn: "error.new",
6902
- args: [
6903
- {
6904
- kind: "strLit",
6905
- value: `${what} is not representable in the target union (a value narrowed or asserted past it still held it)`,
6906
- type: STRING,
6907
- loc,
6908
- },
6909
- ],
6910
- type: { kind: "object", className: "%TypeError" },
6911
- loc,
6912
- },
6913
- loc,
6914
- },
6915
- ],
6916
- else_: null,
6917
- loc,
6918
- });
6919
- });
6920
- body.push({
6921
- kind: "return",
6922
- value: { kind: "unionNarrow", unionId: fromId, tag, value: u, type: target, loc },
6923
- loc,
6924
- });
6925
- this.liftedFns.push({
6926
- name,
6927
- params: [{ localId: "u.0", name: "u", type: fromT }],
6928
- returnType: target,
6929
- locals: [{ id: "u.0", name: "u", type: fromT, mutable: true }],
6930
- body,
6931
- loc,
6932
- });
7144
+ const fn = buildUnionNarrow(name, from, target, loc, (type) => this.fmt(type));
7145
+ if (!fn)
7146
+ throw new InternalCompilerError("lowerer bug: invalid checked union extraction");
7147
+ this.liftedFns.push(fn);
6933
7148
  return name;
6934
7149
  }
6935
7150
  /** The DEFERRED-INIT field read (`stream!: T` assigned past the
@@ -6957,32 +7172,13 @@ export class Lowerer {
6957
7172
  return existing;
6958
7173
  const name = `%deferred.read.${this.narrowHelpers.size}`;
6959
7174
  this.narrowHelpers.set(key, name);
6960
- const fromT = { kind: "union", unionId: fromId };
6961
- const u = { kind: "varRef", localId: "u.0", type: fromT, loc };
6962
7175
  const dflt = target.kind === "bool"
6963
7176
  ? { kind: "boolLit", value: false, type: BOOL, loc }
6964
7177
  : { kind: "numLit", value: NaN, type: F64, loc };
6965
- this.liftedFns.push({
6966
- name,
6967
- params: [{ localId: "u.0", name: "u", type: fromT }],
6968
- returnType: target,
6969
- locals: [{ id: "u.0", name: "u", type: fromT, mutable: true }],
6970
- body: [
6971
- {
6972
- kind: "if",
6973
- cond: { kind: "unionIsTag", unionId: fromId, tag: utag, negated: false, value: u, type: BOOL, loc },
6974
- then: [{ kind: "return", value: dflt, loc }],
6975
- else_: null,
6976
- loc,
6977
- },
6978
- {
6979
- kind: "return",
6980
- value: { kind: "unionNarrow", unionId: fromId, tag, value: u, type: target, loc },
6981
- loc,
6982
- },
6983
- ],
6984
- loc,
6985
- });
7178
+ const fn = buildUnionNarrow(name, from, target, loc, (type) => this.fmt(type), dflt);
7179
+ if (!fn)
7180
+ throw new InternalCompilerError("lowerer bug: invalid deferred union extraction");
7181
+ this.liftedFns.push(fn);
6986
7182
  return name;
6987
7183
  }
6988
7184
  /** True when a static value can become ONE island value: jsval itself,
@@ -7366,7 +7562,66 @@ export class Lowerer {
7366
7562
  * lowering goes through here (via lowerExprExpecting) or calls this
7367
7563
  * directly when the expression was already lowered. */
7368
7564
  coerceInto(node, expr, expected) {
7565
+ // A union destination can accept the binding's tagged storage directly.
7566
+ // The checker's single-arm flow type can be stale after a callback writes
7567
+ // the binding. Extracting that arm and wrapping it again would discard the
7568
+ // actual tag and could read a different record layout. Retag the stored
7569
+ // value instead; ordinary coercion checks any excluded destination arms.
7570
+ // Explicit assertions keep their own conversion and validation.
7571
+ if (expected.kind === "union" && expr.kind === "unionNarrow") {
7572
+ let source = node;
7573
+ while (ts.isParenthesizedExpression(source) || ts.isSatisfiesExpression(source))
7574
+ source = source.expression;
7575
+ if (ts.isIdentifier(source) || ts.isShorthandPropertyAssignment(source))
7576
+ expr = expr.value;
7577
+ }
7578
+ // A fresh literal can retain a wider runtime-optional field after its
7579
+ // initial contextual layout was chosen. Its known discriminator still
7580
+ // selects the destination arm; validate that payload before wrapping.
7581
+ // Work with the already lowered value so property effects run once.
7582
+ if (expr.type.kind === "record" && expected.kind === "union") {
7583
+ let literal = node;
7584
+ while (ts.isParenthesizedExpression(literal) || ts.isSatisfiesExpression(literal))
7585
+ literal = literal.expression;
7586
+ const def = this.unions.get(expected.unionId);
7587
+ if (def?.discriminant && ts.isObjectLiteralExpression(literal)) {
7588
+ const property = this.checker.getPropertyOfType(this.typeOf(literal), def.discriminant.field);
7589
+ if (property && !(property.flags & (ts.SymbolFlags.Optional | ts.SymbolFlags.GetAccessor | ts.SymbolFlags.SetAccessor))) {
7590
+ const values = literalValues(this.checker.getTypeOfSymbol(property));
7591
+ const arm = values && literalUnionArm(def, values, (id) => this.shapes.get(id));
7592
+ if (arm)
7593
+ expr = this.coerceInto(node, expr, arm);
7594
+ }
7595
+ }
7596
+ }
7597
+ if (expected.kind === "dyn") {
7598
+ const contextual = this.checker.getContextualType(node);
7599
+ const parts = contextual?.isUnionType() ? ts.constituentTypes(contextual) : contextual ? [contextual] : [];
7600
+ const errorOptions = parts.some((part) => {
7601
+ const sym = part.getAliasSymbol() ?? part.getSymbol();
7602
+ return sym?.name === "ErrorOptions" && this.isStdlibSymbol(sym);
7603
+ });
7604
+ if (errorOptions) {
7605
+ const actual = this.typeOf(node);
7606
+ for (const part of actual.isUnionType() ? ts.constituentTypes(actual) : [actual]) {
7607
+ const cause = this.checker.getPropertyOfType(part, "cause");
7608
+ if (cause && cause.flags & (ts.SymbolFlags.GetAccessor | ts.SymbolFlags.SetAccessor)) {
7609
+ this.unsupported("SC1090", node, "Error options with a cause accessor (use a data property)");
7610
+ }
7611
+ }
7612
+ }
7613
+ }
7369
7614
  let e = this.coerceToExpected(expr, expected);
7615
+ // Existing JavaScript arrays retain mutations and identity across checked
7616
+ // slots. Fresh literals have no prior identity and use checked storage
7617
+ // directly, so later writes can change their inferred element type.
7618
+ let literal = node;
7619
+ while (ts.isParenthesizedExpression(literal))
7620
+ literal = literal.expression;
7621
+ if (isJsSourceFile(node.getSourceFile()) && !ts.isArrayLiteralExpression(literal) &&
7622
+ e.kind === "dynFrom" && e.value.type.kind === "array") {
7623
+ e = { ...e, liveRef: true };
7624
+ }
7370
7625
  // An 'any' value PROVABLY null/undefined (the unit literal itself, or
7371
7626
  // a read of a binding nothing ever assigns a non-unit value) flowing
7372
7627
  // implicitly into a primitive slot: the validated exit refuses units
@@ -7401,6 +7656,20 @@ export class Lowerer {
7401
7656
  if (helper) {
7402
7657
  e = { kind: "call", callee: helper, args: [e], type: expected, loc: e.loc };
7403
7658
  }
7659
+ // Shipped JavaScript can select overloads using runtime brand data
7660
+ // that its JSDoc union does not narrow. Preserve the numeric/string/
7661
+ // boolean destination check, just as for an unknown-typed argument;
7662
+ // never reinterpret an object payload as a scalar union arm.
7663
+ if (e.type.kind === "union" && !typeEquals(e.type, expected) && isJsSourceFile(node.getSourceFile()) &&
7664
+ this.dynConvertible(e.type)) {
7665
+ const sourceArms = this.unions.get(e.type.unionId)?.arms ?? [];
7666
+ const targetArms = this.unions.get(expected.unionId)?.arms ?? [];
7667
+ if (sourceArms.some(isDynTypedRefType) && targetArms.length > 0 &&
7668
+ targetArms.every((arm) => isUnitType(arm) || arm.kind === "f64" || arm.kind === "string" || arm.kind === "bool") &&
7669
+ targetArms.some((arm) => !isUnitType(arm) && sourceArms.some((source) => typeEquals(source, arm)))) {
7670
+ e = this.coerceToExpected(this.coerceToExpected(e, DYN), expected);
7671
+ }
7672
+ }
7404
7673
  }
7405
7674
  // A JS FUNC value outside the island marshal set flowing into a
7406
7675
  // jsval slot (`withPlugins(getSupportInfoWithoutPlugins, 0)` — a
@@ -7414,7 +7683,9 @@ export class Lowerer {
7414
7683
  this.requireExactShape(node, e.type, expected);
7415
7684
  }
7416
7685
  catch (err) {
7417
- const fence = islandFuncValueFence(this, err, diagsBefore, node);
7686
+ if (!(err instanceof PoisonError))
7687
+ throw err;
7688
+ const fence = islandFuncValueFence(this, diagsBefore, node);
7418
7689
  if (fence)
7419
7690
  return fence;
7420
7691
  throw err;
@@ -7492,53 +7763,145 @@ export class Lowerer {
7492
7763
  return null;
7493
7764
  return [...units].sort().join(" or ");
7494
7765
  }
7495
- /** Lowers an expression that flows into a slot of a known expected type,
7496
- * then applies the coercion path (coerceInto). An EMPTY array literal
7497
- * takes the slot's array type directly — the caller-supplied `expected`
7498
- * lowerArrayLiteral documents, for the positions where tsc's contextual
7499
- * API answers nothing (binding-element defaults: `{ json = [] }`) and
7500
- * the literal's own never[] would build the f64 representation. */
7766
+ /** A key conversion may rebox or upcast a reference, but must never copy
7767
+ * its referent. Apply the ordinary checked narrowing to absent arms from
7768
+ * runtime-optional reads; only present reference arms participate here. */
7769
+ lowerCollectionKey(node, expected) {
7770
+ if (expected.kind === "dyn") {
7771
+ const value = this.lowerExprExpecting(node, expected);
7772
+ // An adapting promise changes identity, while the Error boundary
7773
+ // snapshots mutable fields. Neither is a live collection reference.
7774
+ const copiesReference = (type) => (type.kind === "promise" && type.inner.kind !== "dyn") ||
7775
+ (type.kind === "object" && (RUNTIME_ERROR_CLASSES.has(type.className) || this.isSubclassOf(type.className, "%Error"))) ||
7776
+ (type.kind === "union" && (this.unions.get(type.unionId)?.arms.some(copiesReference) ?? false));
7777
+ if (value.kind === "dynFrom" && copiesReference(value.value.type)) {
7778
+ this.noLowering("collection slot conversion requiring an Error snapshot or promise adapter", node, "use a collection with the original reference type; checked collection slots require identity-preserving conversions");
7779
+ }
7780
+ // Collections expose the stored reference again. Preserve records,
7781
+ // arrays and byte views rather than taking the ordinary dyn snapshot.
7782
+ const hasLiveReference = (type) => type.kind === "record" || type.kind === "array" || type.kind === "bytes" ||
7783
+ (type.kind === "union" && (this.unions.get(type.unionId)?.arms.some(hasLiveReference) ?? false));
7784
+ if (value.kind === "dynFrom" && hasLiveReference(value.value.type)) {
7785
+ return { ...value, liveRef: true };
7786
+ }
7787
+ return value;
7788
+ }
7789
+ let literal = node;
7790
+ while (ts.isParenthesizedExpression(literal))
7791
+ literal = literal.expression;
7792
+ // Fresh literals have no previous outer identity to preserve. Build them
7793
+ // for their storage layout, just as ordinary contextual literals do.
7794
+ if (ts.isObjectLiteralExpression(literal) || ts.isArrayLiteralExpression(literal) || expected.kind === "f64" || expected.kind === "string") {
7795
+ return this.lowerExprExpecting(node, expected);
7796
+ }
7797
+ // Assertions can perform their own conversion before slot coercion.
7798
+ // Inspect the assertion chain so a width copy cannot hide behind its
7799
+ // already-converted result type. Union-arm checks only unwrap a box.
7800
+ let asserted = literal;
7801
+ while (ts.isAsExpression(asserted) || ts.isTypeAssertion(asserted) || ts.isNonNullExpression(asserted) || ts.isParenthesizedExpression(asserted)) {
7802
+ if (ts.isAsExpression(asserted) || ts.isTypeAssertion(asserted)) {
7803
+ const from = this.mapTypeOf(this.typeOf(asserted.expression));
7804
+ const to = this.mapTypeOf(this.checker.getTypeFromTypeNode(asserted.type));
7805
+ if (from?.kind === "dyn" || from?.kind === "jsval" || (from?.kind === "record" && to?.kind === "record" && !typeEquals(from, to))) {
7806
+ this.noLowering("collection key assertion requiring a structural copy or dynamic conversion", asserted, "use the original reference with the same type as the collection key");
7807
+ }
7808
+ }
7809
+ asserted = asserted.expression;
7810
+ }
7811
+ const value = this.lowerExpr(node);
7812
+ const source = (value.type.kind === "union" ? this.unions.get(value.type.unionId)?.arms ?? [] : [value.type]).filter((type) => !isUnitType(type));
7813
+ const target = expected.kind === "union" ? this.unions.get(expected.unionId)?.arms ?? [] : [expected];
7814
+ const preservesIdentity = source.length > 0 && source.every((from) => target.some((to) => typeEquals(from, to) || (from.kind === "object" && to.kind === "object" && this.isSubclassOf(from.className, to.className))));
7815
+ if (!preservesIdentity || value.kind === "dynCheck" || value.kind === "jsExit") {
7816
+ this.noLowering(`collection key conversion from '${this.fmt(value.type)}' to '${this.fmt(expected)}' requiring a structural copy or dynamic conversion`, node, "use the same reference type for the key and collection; copying a key would change its identity");
7817
+ }
7818
+ return this.coerceInto(node, value, expected);
7819
+ }
7820
+ /** Lower for a known destination, then apply ordinary value coercion.
7821
+ * Fresh arrays and records use the destination layout directly. */
7501
7822
  lowerExprExpecting(node, expected) {
7823
+ // These wrappers do not change the value or its inferred type. Keep a
7824
+ // fresh literal visible to destination-directed construction. Assertions
7825
+ // retain their own checked conversion and must not be erased here.
7826
+ while (ts.isParenthesizedExpression(node) || ts.isSatisfiesExpression(node))
7827
+ node = node.expression;
7828
+ if (expected) {
7829
+ if (ts.isConditionalExpression(node))
7830
+ return lowerTernary(this, node, expected);
7831
+ const fresh = this.emptyCollectionFor(node, expected);
7832
+ if (fresh)
7833
+ return this.coerceInto(node, fresh, expected);
7834
+ }
7502
7835
  if (expected?.kind === "array") {
7503
7836
  let x = node;
7504
7837
  while (ts.isParenthesizedExpression(x))
7505
7838
  x = x.expression;
7506
- if (ts.isArrayLiteralExpression(x) && x.elements.length === 0) {
7839
+ // Fresh arrays are built for the actual destination, including
7840
+ // nested literals whose checker context names a wider recursive
7841
+ // union. Existing arrays still go through ordinary value coercion.
7842
+ if (ts.isArrayLiteralExpression(x)) {
7507
7843
  return this.coerceInto(node, this.lowerArrayLiteral(x, expected), expected);
7508
7844
  }
7509
7845
  }
7846
+ if (expected?.kind === "record") {
7847
+ let x = node;
7848
+ while (ts.isParenthesizedExpression(x))
7849
+ x = x.expression;
7850
+ if (ts.isObjectLiteralExpression(x)) {
7851
+ return this.coerceInto(node, this.lowerObjectLiteral(x, expected), expected);
7852
+ }
7853
+ }
7854
+ if (expected?.kind === "union" && ts.isObjectLiteralExpression(node)) {
7855
+ const def = this.unions.get(expected.unionId);
7856
+ if (def?.discriminant) {
7857
+ const property = this.checker.getPropertyOfType(this.typeOf(node), def.discriminant.field);
7858
+ if (property && !(property.flags & (ts.SymbolFlags.Optional | ts.SymbolFlags.GetAccessor | ts.SymbolFlags.SetAccessor))) {
7859
+ const values = literalValues(this.checker.getTypeOfSymbol(property));
7860
+ const arm = values && literalUnionArm(def, values, (id) => this.shapes.get(id));
7861
+ if (arm)
7862
+ return this.coerceInto(node, this.lowerObjectLiteral(node, arm), expected);
7863
+ }
7864
+ }
7865
+ }
7510
7866
  // An OBJECT LITERAL against a checked-dynamic slot in a JS file (the
7511
7867
  // getSupportInfo options argument — a dyn-ABI param), or against the
7512
- // standard RequestInit type in TypeScript: the value's world IS the
7868
+ // standard RequestInit/ErrorOptions types in TypeScript: the value's world IS the
7513
7869
  // checked-dynamic tree — build the dyn literal directly.
7514
7870
  if (expected?.kind === "dyn") {
7515
7871
  let x = node;
7516
7872
  while (ts.isParenthesizedExpression(x))
7517
7873
  x = x.expression;
7874
+ // A fresh dense array entering a checked slot has no typed aliases.
7875
+ // Construct its actual storage here so identity and WeakMap lifetime
7876
+ // belong to the array the program keeps, rather than a typed snapshot.
7877
+ if (ts.isArrayLiteralExpression(x) && x.elements.every((element) => !ts.isSpreadElement(element) && !ts.isOmittedExpression(element))) {
7878
+ return { kind: "dynArrLit", elems: x.elements.map((element) => this.lowerExprExpecting(element, DYN)), type: DYN, loc: locOf(x) };
7879
+ }
7880
+ const contextual = this.checker.getContextualType(x);
7881
+ const widened = contextual ? this.checker.getBaseTypeOfLiteralType(contextual) : undefined;
7882
+ const parts = widened?.isUnionType() ? ts.constituentTypes(widened) : widened ? [widened] : [];
7883
+ const builtinOption = (name) => parts.some((part) => {
7884
+ const sym = part.getAliasSymbol() ?? part.getSymbol();
7885
+ return sym?.name === name && this.isStdlibSymbol(sym);
7886
+ });
7518
7887
  if (ts.isObjectLiteralExpression(x)) {
7519
- const contextual = this.checker.getContextualType(x);
7520
- const widened = contextual
7521
- ? this.checker.getBaseTypeOfLiteralType(contextual)
7522
- : undefined;
7523
- const sym = widened?.getAliasSymbol() ?? widened?.getSymbol();
7524
- const requestInit = sym?.name === "RequestInit" && this.isStdlibSymbol(sym);
7525
- if (isJsSourceFile(x.getSourceFile()) || requestInit) {
7888
+ if (isJsSourceFile(x.getSourceFile()) || builtinOption("RequestInit") || builtinOption("ErrorOptions")) {
7526
7889
  return lowerDynObjectLiteral(this, x);
7527
7890
  }
7528
7891
  }
7529
7892
  }
7530
- // An ARRAY LITERAL against a UNION slot whose own type has no static
7531
- // home (the JS dyn fallback — the checker gave no usable context):
7532
- // when the union has exactly ONE array-family arm — an array, or an
7533
- // arity-matching tuple (the option-table `default: [{ value: [] }]`
7534
- // shape) — build AS that arm and wrap; the IR-directed twin of
7535
- // lowerArrayLiteral's contextual-union rule.
7893
+ // A fresh array can use the unique array-family destination inside a
7894
+ // union too. In nullable recursive fields the checker can report the
7895
+ // whole union as context: an identity lift of that context does not
7896
+ // mean the literal's independently inferred element layout fits.
7897
+ // Construct the elements for the selected arm before wrapping it.
7898
+ // When several array arms fit a fresh literal, any complete element
7899
+ // layout is valid: the new array has no existing aliases to preserve.
7536
7900
  if (expected?.kind === "union") {
7537
7901
  let x = node;
7538
7902
  while (ts.isParenthesizedExpression(x))
7539
7903
  x = x.expression;
7540
7904
  if (ts.isArrayLiteralExpression(x)) {
7541
- const own = this.mapTypeOf(this.checker.getContextualType(x) ?? this.typeOf(x));
7542
7905
  // Elements beyond bare null/undefined literals can never live in
7543
7906
  // a unit-only-element array — a checker type that degraded to one
7544
7907
  // (`[]`-flavored inference over a populated literal) carries no
@@ -7546,26 +7909,60 @@ export class Lowerer {
7546
7909
  const nonUnitElems = x.elements.some((el) => !ts.isOmittedExpression(el) &&
7547
7910
  el.kind !== ts.SyntaxKind.NullKeyword &&
7548
7911
  !(ts.isIdentifier(el) && el.text === "undefined"));
7549
- if (own === null || own.kind === "dyn" || own.kind === "jsval" ||
7550
- (own.kind === "array" && nonUnitElems && this.unitOnlyElem(own.elem)) ||
7551
- this.widthLiftPlan(own, expected) === null) {
7552
- const def = this.unions.get(expected.unionId);
7553
- const arms = (def?.arms ?? []).filter((a) => (a.kind === "array" && !(nonUnitElems && this.unitOnlyElem(a.elem))) ||
7554
- (a.kind === "record" &&
7555
- !!this.shapes.get(a.shapeId)?.tuple &&
7556
- this.shapes.get(a.shapeId).fields.length === x.elements.length &&
7557
- !x.elements.some(ts.isSpreadElement)));
7558
- if (arms.length === 1) {
7559
- const arm = arms[0];
7560
- const built = this.lowerArrayLiteral(x, arm);
7561
- return this.coerceInto(node, built, expected);
7912
+ const def = this.unions.get(expected.unionId);
7913
+ const arms = (def?.arms ?? []).filter((a) => (a.kind === "array" && !(nonUnitElems && this.unitOnlyElem(a.elem))) ||
7914
+ (a.kind === "record" &&
7915
+ !!this.shapes.get(a.shapeId)?.tuple &&
7916
+ this.shapes.get(a.shapeId).fields.length === x.elements.length &&
7917
+ !x.elements.some(ts.isSpreadElement)));
7918
+ let arm = arms.length === 1 ? arms[0] : undefined;
7919
+ if (!arm && arms.length > 1 && x.elements.length > 0 &&
7920
+ x.elements.every((el) => !ts.isSpreadElement(el) && !ts.isOmittedExpression(el))) {
7921
+ const ownType = this.mapTypeOf(this.typeOf(x));
7922
+ arm = arms.find((candidate) => ownType !== null && typeEquals(candidate, ownType));
7923
+ if (!arm) {
7924
+ const elements = x.elements.map((el) => tryLowerExpression(this, el));
7925
+ arm = arms.find((candidate) => candidate.kind === "array" &&
7926
+ elements.every((element) => element !== null && this.widthLiftPlan(element.type, candidate.elem) !== null));
7562
7927
  }
7563
7928
  }
7929
+ if (arm) {
7930
+ const built = this.lowerArrayLiteral(x, arm);
7931
+ return this.coerceInto(node, built, expected);
7932
+ }
7564
7933
  }
7565
7934
  }
7566
- const e = this.lowerExpr(node);
7935
+ let e = this.lowerExpr(node);
7936
+ if (expected?.kind === "union" && this.armTag(expected.unionId, UNDEFINED_T) >= 0) {
7937
+ // A destination that accepts undefined must retain an unchecked
7938
+ // read's storage value even when the checker still calls it present.
7939
+ e = this.runtimeOptionalSourceValue(node, e) ?? e;
7940
+ }
7567
7941
  return expected ? this.coerceInto(node, e, expected) : e;
7568
7942
  }
7943
+ /** An unannotated empty collection has no existing elements or aliases
7944
+ * that constrain its layout. An explicit type argument still wins. */
7945
+ emptyCollectionFor(node, expected) {
7946
+ let value = node;
7947
+ while (ts.isParenthesizedExpression(value))
7948
+ value = value.expression;
7949
+ if (!ts.isNewExpression(value) || !ts.isIdentifier(value.expression) || (value.arguments?.length ?? 0) !== 0 ||
7950
+ (value.typeArguments?.length ?? 0) !== 0)
7951
+ return null;
7952
+ const symbol = this.resolveValueSymbol(value.expression);
7953
+ if (!symbol || !this.isStdlibSymbol(symbol))
7954
+ return null;
7955
+ const kind = symbol.name === "Map" ? "map" : symbol.name === "Set" ? "set" : null;
7956
+ if (!kind)
7957
+ return null;
7958
+ const arms = expected.kind === "union" ? this.unions.get(expected.unionId)?.arms ?? [] : [expected];
7959
+ const candidates = arms.filter((arm) => arm.kind === kind);
7960
+ if (candidates.length !== 1)
7961
+ return null;
7962
+ const type = candidates[0];
7963
+ return type.kind === "map" ? { kind: "mapNew", type, loc: locOf(value) }
7964
+ : type.kind === "set" ? { kind: "setNew", type, loc: locOf(value) } : null;
7965
+ }
7569
7966
  /** A value flowing into an index-signature VALUE slot (an overflow
7570
7967
  * literal entry, a dynamic-keyed record write). dyn slots (`unknown`
7571
7968
  * signatures — ModelPricing's) take a dyn conversion: dyn values pass
@@ -7623,6 +8020,22 @@ export class Lowerer {
7623
8020
  * nothing evaluates; unit-typed non-literals keep the fences. */
7624
8021
  lowerReturnValue(node) {
7625
8022
  const expected = this.ctx.returnType;
8023
+ // A return slot supplies the same construction layout as an argument
8024
+ // or initializer. In particular, contextual callbacks can return fresh
8025
+ // arrays of recursive unions and nullable, unannotated collections.
8026
+ // Async returns still resolve a promise before converting its payload.
8027
+ if (!this.ctx.isAsync && expected.kind !== "void")
8028
+ return this.lowerExprExpecting(node, expected);
8029
+ // Fresh JS objects returned through a checked-native ABI use that
8030
+ // storage directly, just like arguments and variable initializers.
8031
+ // Contextual types (such as Proxy descriptors' symbol-valued fields)
8032
+ // must not force an intermediate record with incompatible field slots.
8033
+ let literal = node;
8034
+ while (ts.isParenthesizedExpression(literal))
8035
+ literal = literal.expression;
8036
+ if (expected.kind === "dyn" && isJsSourceFile(node.getSourceFile()) && ts.isObjectLiteralExpression(literal)) {
8037
+ return this.lowerExprExpecting(node, expected);
8038
+ }
7626
8039
  const e = this.lowerExpr(node);
7627
8040
  if (expected.kind === "void" && e.kind === "unitLit")
7628
8041
  return null;
@@ -7690,7 +8103,7 @@ export class Lowerer {
7690
8103
  if (rest.length === 1)
7691
8104
  return rest[0];
7692
8105
  // Removing an arm keeps canonical (typeKey-sorted) order.
7693
- return { kind: "union", unionId: this.unions.intern(rest) };
8106
+ return { kind: "union", unionId: this.unions.transform(def, rest) };
7694
8107
  }
7695
8108
  /** The interned `T | undefined` union over a non-union arm type — the ABI
7696
8109
  * type of a defaulted parameter, and the result type of lookups that may
@@ -7962,7 +8375,7 @@ export class Lowerer {
7962
8375
  * members ride fp.classDecls; expressions register only when their
7963
8376
  * containing statement lowers). */
7964
8377
  exprClasses = [];
7965
- exprClassInfoByNode = new Map();
8378
+ exprClassInfoByName = new Map();
7966
8379
  /** Class expressions whose collection is IN FLIGHT — the reentrancy
7967
8380
  * guard for heritage-demanded collection (lowerClassExpressionInfo). */
7968
8381
  collectingExprClasses = new Set();
@@ -8016,8 +8429,8 @@ export class Lowerer {
8016
8429
  * onExprClassCollected should instantiations ever need eager
8017
8430
  * registration. */
8018
8431
  onLateClassCollected = null;
8019
- genericClassInstanceType(decl, ref) {
8020
- return genericClassInstanceType(this, decl, ref);
8432
+ genericClassInstanceType(decl, ref, mapArgument) {
8433
+ return genericClassInstanceType(this, decl, ref, mapArgument);
8021
8434
  }
8022
8435
  findStaticOn(info, name) {
8023
8436
  return findStaticOn(this, info, name);
@@ -8090,14 +8503,10 @@ export class Lowerer {
8090
8503
  superCallStmt(info, thisLocal, args, loc) {
8091
8504
  return superCallStmt(this, info, thisLocal, args, loc);
8092
8505
  }
8093
- /** Declares the `this` param local, registered under the THIS_BINDING
8094
- * sentinel so lexical-this capture in arrows uses the normal machinery. */
8506
+ /** Declares the this parameter in the function's dedicated binding slot.
8507
+ * Arrow captures use the same boxing and threading as named bindings. */
8095
8508
  declareThis(type) {
8096
- const ctx = this.ctx;
8097
- const local = { id: "this.0", name: "this", type, mutable: false };
8098
- ctx.locals.push(local);
8099
- ctx.scopes[ctx.scopes.length - 1].set(THIS_BINDING, local);
8100
- return local;
8509
+ return declareContextThis(this.ctx, type);
8101
8510
  }
8102
8511
  lowerFunction(decl) {
8103
8512
  return lowerFunction(this, decl);
@@ -8116,26 +8525,13 @@ export class Lowerer {
8116
8525
  }
8117
8526
  /* ── scoping and captures ─────────────────────────────────────────── */
8118
8527
  declareLocal(nameNode, name, type, mutable) {
8119
- const ctx = this.ctx;
8120
- const count = ctx.localCounters.get(name) ?? 0;
8121
- ctx.localCounters.set(name, count + 1);
8122
- const local = { id: `${name}.${count}`, name, type, mutable, source: bindingSource(nameNode) };
8123
- ctx.locals.push(local);
8124
- const symbol = this.checker.getSymbolAtLocation(nameNode);
8125
- if (symbol)
8126
- ctx.scopes[ctx.scopes.length - 1].set(symbol, local);
8127
- return local;
8528
+ return declareContextLocal(this.ctx, name, type, mutable, this.checker.getSymbolAtLocation(nameNode), bindingSource(nameNode));
8128
8529
  }
8129
8530
  /** A function-scope local bound to NO ts.Symbol — the hidden ABI slot of a
8130
8531
  * defaulted parameter (the parameter's symbol binds to the separately-
8131
8532
  * declared body local; nothing in the source can name this one). */
8132
8533
  declareHiddenLocal(name, type) {
8133
- const ctx = this.ctx;
8134
- const count = ctx.localCounters.get(name) ?? 0;
8135
- ctx.localCounters.set(name, count + 1);
8136
- const local = { id: `${name}.${count}`, name, type, mutable: false };
8137
- ctx.locals.push(local);
8138
- return local;
8534
+ return declareContextLocal(this.ctx, name, type, false, undefined, undefined);
8139
8535
  }
8140
8536
  /** Declares a callee's parameter locals from its ParamShapes and builds
8141
8537
  * the DEFAULT-PARAM PROLOGUE. Required/optional/rest params bind their
@@ -8158,6 +8554,13 @@ export class Lowerer {
8158
8554
  const decls = rawDecls.filter((p) => !isThisParameter(p));
8159
8555
  const params = [];
8160
8556
  const prologue = [];
8557
+ const defaultValue = (node, expected) => {
8558
+ const undefinedValue = lowerStaticallyUndefinedArgument(this, node);
8559
+ if (undefinedValue === null)
8560
+ return this.lowerExprExpecting(node, expected);
8561
+ const absent = { kind: "unitLit", unit: "undefined", type: UNDEFINED_T, loc: locOf(node) };
8562
+ return defaultAfterUndefined(undefinedValue, this.coerceInto(node, absent, expected));
8563
+ };
8161
8564
  decls.forEach((decl, i) => {
8162
8565
  const shape = shapes[i];
8163
8566
  if (ts.isArrayBindingPattern(decl.name) || ts.isObjectBindingPattern(decl.name)) {
@@ -8184,7 +8587,7 @@ export class Lowerer {
8184
8587
  // dynamic dyn): the slot holds its tier's undefined directly,
8185
8588
  // so the default test is the runtime undefined test — then
8186
8589
  // the pattern destructures the picked value.
8187
- const dflt = this.lowerExprExpecting(decl.initializer, abi);
8590
+ const dflt = defaultValue(decl.initializer, abi);
8188
8591
  const src = this.declareHiddenLocal("%psrc", abi);
8189
8592
  const inRef = () => ({ kind: "varRef", localId: slot.id, type: abi, loc });
8190
8593
  const isUndef = abi.kind === "jsval"
@@ -8199,6 +8602,16 @@ export class Lowerer {
8199
8602
  const pickedT = abi;
8200
8603
  srcType = pickedT;
8201
8604
  srcRef = () => ({ kind: "varRef", localId: src.id, type: pickedT, loc });
8605
+ // An empty object pattern still rejects null after applying
8606
+ // the default. With no property reads, nothing else performs
8607
+ // RequireObjectCoercible; use V8's default-expression spelling.
8608
+ if (abi.kind === "dyn" && ts.isObjectBindingPattern(decl.name) && decl.name.elements.length === 0) {
8609
+ prologue.push({
8610
+ kind: "exprStmt",
8611
+ expr: { kind: "dynDestrCheck", value: srcRef(), spelling: "(intermediate value)(intermediate value)(intermediate value)", type: DYN, loc },
8612
+ loc,
8613
+ });
8614
+ }
8202
8615
  this.lowerBindingPattern(decl.name, srcRef, srcType, true, prologue);
8203
8616
  return;
8204
8617
  }
@@ -8228,7 +8641,7 @@ export class Lowerer {
8228
8641
  }
8229
8642
  if (!present)
8230
8643
  this.unsupported("SC1090", decl, "this parameter form"); // defensive: abi = bodyType + undefined by construction
8231
- const dflt = this.lowerExprExpecting(decl.initializer, shape.bodyType);
8644
+ const dflt = defaultValue(decl.initializer, shape.bodyType);
8232
8645
  const src = this.declareHiddenLocal("%psrc", shape.bodyType);
8233
8646
  prologue.push({
8234
8647
  kind: "varDecl",
@@ -8258,7 +8671,7 @@ export class Lowerer {
8258
8671
  const isUndef = abi.kind === "jsval"
8259
8672
  ? { kind: "jsOp", op: "eq", args: [inRef(), { kind: "jsOp", op: "undefLit", args: [], type: JSVAL, loc }], type: BOOL, loc }
8260
8673
  : { kind: "dynTest", test: "undefined", value: inRef(), type: BOOL, loc };
8261
- const dflt = this.lowerExprExpecting(decl.initializer, abi);
8674
+ const dflt = defaultValue(decl.initializer, abi);
8262
8675
  const body = this.declareLocal(decl.name, name, abi, true);
8263
8676
  prologue.push({
8264
8677
  kind: "varDecl",
@@ -8282,7 +8695,7 @@ export class Lowerer {
8282
8695
  // the body keeps the full `T | undefined` union (tsc's type),
8283
8696
  // so a present argument passes through unchanged and an omitted
8284
8697
  // one takes the default AS IS — no narrow on either branch.
8285
- const dflt = this.lowerExprExpecting(decl.initializer, abi);
8698
+ const dflt = defaultValue(decl.initializer, abi);
8286
8699
  const body = this.declareLocal(decl.name, name, abi, true);
8287
8700
  prologue.push({
8288
8701
  kind: "varDecl",
@@ -8308,7 +8721,7 @@ export class Lowerer {
8308
8721
  const retag = this.unionRetagHelper(abi.unionId, shape.bodyType.unionId, loc);
8309
8722
  if (!retag)
8310
8723
  this.unsupported("SC1090", decl, "this parameter form"); // defensive
8311
- const dflt = this.lowerExprExpecting(decl.initializer, shape.bodyType);
8724
+ const dflt = defaultValue(decl.initializer, shape.bodyType);
8312
8725
  const body = this.declareLocal(decl.name, name, shape.bodyType, true);
8313
8726
  prologue.push({
8314
8727
  kind: "varDecl",
@@ -8331,7 +8744,7 @@ export class Lowerer {
8331
8744
  // The default lowers BEFORE the body local binds, so a same-named
8332
8745
  // outer binding referenced in it can never resolve to the fresh
8333
8746
  // local (tsc separately rejects `x = x`).
8334
- const dflt = this.lowerExprExpecting(decl.initializer, shape.bodyType);
8747
+ const dflt = defaultValue(decl.initializer, shape.bodyType);
8335
8748
  const body = this.declareLocal(decl.name, name, shape.bodyType, true);
8336
8749
  prologue.push({
8337
8750
  kind: "varDecl",
@@ -8364,12 +8777,7 @@ export class Lowerer {
8364
8777
  /** The binding for `symbol` inside context `ctx` — a scoped local or an
8365
8778
  * already-threaded capture entry. */
8366
8779
  bindingIn(ctx, symbol) {
8367
- for (let i = ctx.scopes.length - 1; i >= 0; i--) {
8368
- const local = ctx.scopes[i].get(symbol);
8369
- if (local)
8370
- return local;
8371
- }
8372
- return ctx.captureBySymbol.get(symbol) ?? null;
8780
+ return bindingInContext(ctx, symbol);
8373
8781
  }
8374
8782
  /** Resolves an identifier to a local of the CURRENT function, creating
8375
8783
  * capture entries (and boxing the origin binding) when the name lives in
@@ -8408,7 +8816,7 @@ export class Lowerer {
8408
8816
  * through arrows (function expressions/declarations reset `this` in JS;
8409
8817
  * their bodies never see an enclosing method's binding). */
8410
8818
  resolveThis() {
8411
- return this.resolveKey(THIS_BINDING);
8819
+ return this.resolveKey(undefined);
8412
8820
  }
8413
8821
  /** READ-ONLY twin of resolveLocal for PROBES (isIslandExpr): answers
8414
8822
  * the nearest binding entry without boxing, threading, or predeclaring.
@@ -8432,75 +8840,23 @@ export class Lowerer {
8432
8840
  return null;
8433
8841
  }
8434
8842
  resolveKey(symbol, blame) {
8435
- const direct = this.bindingIn(this.ctx, symbol);
8436
- if (direct)
8437
- return direct;
8438
- // Search enclosing functions, innermost first.
8439
- for (let depth = this.fnStack.length - 2; depth >= 0; depth--) {
8440
- const origin = this.bindingIn(this.fnStack[depth], symbol);
8441
- if (!origin)
8442
- continue;
8443
- // dyn captures ride an UNTRACED obj-box (scr_dyn_retain_v/release_v
8444
- // — boxNewC): the mustCall wrapper closing over its implicit-any
8445
- // `fn` param. A dyn tree is pure data except the function kind,
8446
- // whose closure edge the collector never sees — cycles through a
8447
- // captured dyn are uncollectable (leak, never dangle: trial
8448
- // deletion treats untraced edges as external roots). SEMANTICS.md.
8449
- // jsval captures are fine: the box is an obj-box carrying the
8450
- // island handle's own retain/release (scr_jsval_*_v), untraced like
8451
- // every jsval container position — engine-side back-references are
8452
- // the island's documented collection stance, not the box's.
8453
- if (origin.type.kind === "caught") {
8454
- // A catch binding never escapes its catch (KEEP NARROW): narrow it
8455
- // into a typed local and capture THAT.
8456
- this.unsupported("SC1090", blame ?? this.checker.declarationsOf(symbol)[0] ?? this.entry, "closures capturing catch bindings (narrow into a typed local first)");
8457
- }
8458
- // The binding escapes into a nested function: it must live in a box,
8459
- // shared by everyone (that's what makes mutation visible everywhere).
8460
- origin.boxed = true;
8461
- // Thread a capture through every function between origin and here.
8462
- let parentEntry = origin;
8463
- for (let j = depth + 1; j < this.fnStack.length; j++) {
8464
- const ctx = this.fnStack[j];
8465
- let entry = ctx.captureBySymbol.get(symbol);
8466
- if (!entry) {
8467
- // A context that takes NO captures (a plain declared function —
8468
- // monomorphized/implicit instances lower this way) cannot carry
8469
- // the binding through: the shape is a module binding whose only
8470
- // storage is the init function's LOCAL (a typed-but-unmappable
8471
- // const — the file-scope `new Map()` ledger idiom) read from
8472
- // inside a nested instance. Fence it — in JS the statement
8473
- // defers to its runtime trap like every collection failure;
8474
- // asserting here was an ICE on ordinary npm-static JS.
8475
- if (ctx.captures === null) {
8476
- this.unsupported("SC1090", blame ?? this.checker.declarationsOf(symbol)[0] ?? this.entry, `the binding '${origin.name}' captured through a plain nested function (the declaration has no static storage a capture can thread — bind the value through a typed const, or read it in the declaring scope)`);
8477
- }
8478
- const count = ctx.localCounters.get(origin.name) ?? 0;
8479
- ctx.localCounters.set(origin.name, count + 1);
8480
- entry = {
8481
- id: `${origin.name}.${count}`,
8482
- name: origin.name,
8483
- type: origin.type,
8484
- mutable: origin.mutable,
8485
- boxed: true,
8486
- ...(origin.source ? { source: origin.source } : {}),
8487
- // TDZ travels with the binding: reads through ANY capture of a
8488
- // forward-captured const must trap while the box is empty.
8489
- ...(origin.tdz ? { tdz: true } : {}),
8490
- };
8491
- ctx.locals.push(entry);
8492
- ctx.captureBySymbol.set(symbol, entry);
8493
- ctx.captures.push({ localId: entry.id, name: entry.name, type: entry.type });
8494
- ctx.captureSources.push(parentEntry.id);
8495
- const runtimeOptionalRoot = this.runtimeOptionalRootOf(parentEntry);
8496
- if (this.runtimeOptionalStorageLocals.has(runtimeOptionalRoot)) {
8497
- this.runtimeOptionalRoots.set(entry, runtimeOptionalRoot);
8498
- }
8499
- }
8500
- parentEntry = entry;
8501
- }
8502
- return parentEntry;
8503
- }
8843
+ const resolved = captureContextBinding(this.fnStack, symbol, (parentEntry, entry) => {
8844
+ const root = this.runtimeOptionalRootOf(parentEntry);
8845
+ if (this.runtimeOptionalStorageLocals.has(root))
8846
+ this.runtimeOptionalRoots.set(entry, root);
8847
+ });
8848
+ if (resolved.error !== null) {
8849
+ const location = blame ?? (symbol === undefined ? undefined : this.checker.declarationsOf(symbol)[0]) ?? this.entry;
8850
+ const message = resolved.error === "caught"
8851
+ ? "closures capturing catch bindings (narrow into a typed local first)"
8852
+ : `the binding '${resolved.origin.name}' captured through a plain nested function (the declaration has no static storage a capture can thread — bind the value through a typed const, or read it in the declaring scope)`;
8853
+ this.unsupported("SC1090", location, message);
8854
+ }
8855
+ if (resolved.local !== null)
8856
+ return resolved.local;
8857
+ // This cannot be forward-declared: its parameter must already exist.
8858
+ if (symbol === undefined)
8859
+ return null;
8504
8860
  // Nothing declared yet anywhere on the stack: the hoisted-handler shape
8505
8861
  // — a function declared BEFORE a const it captures (`const cleanup =
8506
8862
  // () => onSigInt; ...; const onSigInt = ...`). Pre-declare the const as
@@ -8566,21 +8922,10 @@ export class Lowerer {
8566
8922
  // binding-form text.
8567
8923
  if (symbol) {
8568
8924
  const d = this.checker.valueDeclarationOf(symbol);
8569
- if (d && ts.isVariableDeclaration(d) && ts.isVariableDeclarationList(d.parent) &&
8570
- (d.parent.flags & ts.NodeFlags.Const) !== 0) {
8571
- const codec = textCodecBindingClassOf(this, d.name, d.initializer);
8572
- if (codec !== null) {
8573
- const call = codec === "TextEncoder" ? `${name}.encode(s)` : `${name}.decode(bytes)`;
8574
- const composed = codec === "TextEncoder"
8575
- ? "new TextEncoder().encode(s)"
8576
- : "new TextDecoder().decode(bytes)";
8577
- this.noLowering(`${codec} instance stored in ${name}`, node, `${call} compiles through this const; the codec object itself has no representation (the composed ${composed} form also compiles)`);
8578
- }
8579
- }
8580
8925
  if (d && ts.isVariableDeclaration(d) && d.initializer === undefined) {
8581
8926
  const t = this.checker.getTypeOfSymbol(symbol);
8582
8927
  const parts = t.isUnionType() ? ts.constituentTypes(t) : [t];
8583
- if (parts.some((p) => this.checker.getCallSignatures(p).some((s) => (s.typeParameters?.length ?? 0) > 0))) {
8928
+ if (parts.some((p) => this.checker.getCallSignatures(p).some((s) => s.getTypeParameters().length > 0))) {
8584
8929
  this.unsupported("SC1030", node, `the generic-signature binding '${name}' (its type keeps type parameters and the declaration has no initializer — no function body exists to monomorphize, so nothing can pin a concrete signature)`);
8585
8930
  }
8586
8931
  }
@@ -8904,8 +9249,8 @@ export class Lowerer {
8904
9249
  lowerArrayLiteral(expr, expected) {
8905
9250
  return lowerArrayLiteral(this, expr, expected);
8906
9251
  }
8907
- lowerObjectLiteral(expr) {
8908
- return lowerObjectLiteral(this, expr);
9252
+ lowerObjectLiteral(expr, expected) {
9253
+ return lowerObjectLiteral(this, expr, expected);
8909
9254
  }
8910
9255
  lowerShorthandValue(prop) {
8911
9256
  return lowerShorthandValue(this, prop);
@@ -9203,8 +9548,8 @@ export class Lowerer {
9203
9548
  lowerFieldCompound(access, op, rhsNode, loc) {
9204
9549
  return lowerFieldCompound(this, access, op, rhsNode, loc);
9205
9550
  }
9206
- errorMessageArg(args, loc, blame) {
9207
- return errorMessageArg(this, args, loc, blame);
9551
+ errorConstructorArgs(args, loc, blame) {
9552
+ return errorConstructorArgs(this, args, loc, blame);
9208
9553
  }
9209
9554
  inheritsBuiltinErrorCtor(info) {
9210
9555
  return inheritsBuiltinErrorCtor(this, info);
@@ -9384,7 +9729,7 @@ export class Lowerer {
9384
9729
  }
9385
9730
  if (!ts.isNamespaceImport(decl))
9386
9731
  return null;
9387
- const importDecl = decl.parent.parent;
9732
+ const importDecl = decl.parent?.parent;
9388
9733
  if (!ts.isImportDeclaration(importDecl) || !ts.isStringLiteral(importDecl.moduleSpecifier))
9389
9734
  return null;
9390
9735
  return canonicalBuiltinModule(importDecl.moduleSpecifier.text);
@@ -9404,6 +9749,16 @@ export class Lowerer {
9404
9749
  builtinMemberOf(access) {
9405
9750
  if (access.questionDotToken)
9406
9751
  return null;
9752
+ // Function-owned builtin members still require import provenance. A
9753
+ // user object named realpathSync must retain its ordinary method call.
9754
+ if (access.name.text === "native") {
9755
+ const owner = access.expression;
9756
+ const imported = ts.isIdentifier(owner) ? this.builtinImportOf(owner)
9757
+ : ts.isPropertyAccessExpression(owner) ? this.builtinMemberOf(owner) : null;
9758
+ if (imported?.module === "fs" && imported.member === "realpathSync") {
9759
+ return { module: "fs", member: "realpathSync.native" };
9760
+ }
9761
+ }
9407
9762
  const module = this.builtinNamespaceModuleOf(access.expression);
9408
9763
  if (module !== null)
9409
9764
  return { module, member: access.name.text };
@@ -9544,10 +9899,9 @@ export class Lowerer {
9544
9899
  if (roots)
9545
9900
  return roots;
9546
9901
  }
9547
- // TypeScript builtin values admitted by an explicit surface-table
9548
- // contract materialize as interned closures. JavaScript sources retain
9549
- // their established builtin identity-token/fence policy.
9550
- if (!isJsSourceFile(expr.getSourceFile())) {
9902
+ // Builtin values admitted by an explicit surface-table contract use
9903
+ // the same interned native closures in TypeScript and JavaScript.
9904
+ {
9551
9905
  const callable = this.lowerBuiltinCallableValue(bi, loc);
9552
9906
  if (callable)
9553
9907
  return callable;
@@ -9568,8 +9922,11 @@ export class Lowerer {
9568
9922
  * are only dispatch sentinels for call-site-specific lowering. */
9569
9923
  lowerBuiltinCallableValue(bi, loc) {
9570
9924
  const fn = builtinModuleFnOf(this, bi.module, bi.member);
9571
- const valueParams = fn?.valueParams;
9572
- if (!fn || !valueParams)
9925
+ return fn ? this.lowerNativeCallableValue(fn, `${bi.module}.${bi.member}`, loc) : null;
9926
+ }
9927
+ lowerNativeCallableValue(fn, display, loc) {
9928
+ const valueParams = fn.valueParams;
9929
+ if (!valueParams)
9573
9930
  return null;
9574
9931
  const shapes = valueParams.map((param) => {
9575
9932
  if (param.mode === "rest")
@@ -9593,10 +9950,10 @@ export class Lowerer {
9593
9950
  name: `arg${index}`,
9594
9951
  type,
9595
9952
  }));
9596
- const args = params.map((param, index) => {
9597
- const valueParam = valueParams[index];
9598
- if (!valueParam) {
9599
- throw new InternalCompilerError(`builtin callable value '${bi.module}.${bi.member}' has a missing value parameter`);
9953
+ const args = valueParams.map((valueParam, index) => {
9954
+ const param = params[index];
9955
+ if (!param || !valueParam) {
9956
+ throw new InternalCompilerError(`builtin callable value '${display}' has a missing value parameter`);
9600
9957
  }
9601
9958
  const ref = {
9602
9959
  kind: "varRef",
@@ -9606,13 +9963,13 @@ export class Lowerer {
9606
9963
  };
9607
9964
  if (valueParam.mode !== "optional")
9608
9965
  return ref;
9609
- if (valueParam.type.kind !== "string" || param.type.kind !== "union") {
9610
- throw new InternalCompilerError(`builtin callable value '${bi.module}.${bi.member}' has an unsupported optional default`);
9966
+ if ((valueParam.type.kind !== "string" && valueParam.type.kind !== "f64") || param.type.kind !== "union") {
9967
+ throw new InternalCompilerError(`builtin callable value '${display}' has an unsupported optional default`);
9611
9968
  }
9612
9969
  const undefTag = this.armTag(param.type.unionId, UNDEFINED_T);
9613
9970
  const valueTag = this.armTag(param.type.unionId, valueParam.type);
9614
9971
  if (undefTag < 0 || valueTag < 0) {
9615
- throw new InternalCompilerError(`builtin callable value '${bi.module}.${bi.member}' has an invalid optional ABI`);
9972
+ throw new InternalCompilerError(`builtin callable value '${display}' has an invalid optional ABI`);
9616
9973
  }
9617
9974
  return {
9618
9975
  kind: "ternary",
@@ -9625,7 +9982,9 @@ export class Lowerer {
9625
9982
  type: BOOL,
9626
9983
  loc,
9627
9984
  },
9628
- then: { kind: "strLit", value: valueParam.defaultValue, type: STRING, loc },
9985
+ then: typeof valueParam.defaultValue === "string"
9986
+ ? { kind: "strLit", value: valueParam.defaultValue, type: STRING, loc }
9987
+ : { kind: "numLit", value: valueParam.defaultValue, type: F64, loc },
9629
9988
  else_: {
9630
9989
  kind: "unionNarrow",
9631
9990
  unionId: param.type.unionId,