@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
@@ -5,30 +5,40 @@ import { InternalCompilerError } from "../../errors.js";
5
5
  * explicit resource management, and blocked-binding poisoning. */
6
6
  import * as ts from "../ts7/adapter.js";
7
7
  import { bindingSource } from "../binding-source.js";
8
- import { arrayValueRead, arrayValueStore, arrayValueType } from "./array-values.js";
8
+ import { arrayValueRead, arrayValueStore, arrayValueType, unionArrayValueRead } from "./array-values.js";
9
9
  import { lowerForAwaitGenerator, lowerForOfGenerator, lowerYieldStarStatement } from "./lower-generators.js";
10
10
  import { lowerForAwaitBuiltin } from "./lower-async-iteration.js";
11
- import { BOOL, BYTES_U8, CAUGHT, DYN, F64, JSVAL, STRING, UNDEFINED_T, VOID, arrayOf, isUnitType, shapeHasAccessorSlots, typeEquals } from "../../ir/ir.js";
11
+ import { BOOL, BYTES_U8, CAUGHT, DYN, F64, JSVAL, STRING, UNDEFINED_T, VOID, arrayOf, isDynTypedRefType, isUnitType, shapeHasAccessorSlots, typeEquals } from "../../ir/ir.js";
12
12
  import { PoisonError, boundIdentifiersOf, dynFallbackType, dynUndefinedExpr, importCallHandleType, neverTaintedJsType, staticImportNamespaceType, stmtUsesIsland, uncheckedOverloadHandleCall } from "./lowerer.js";
13
13
  import { enforceLibBoundary } from "./lib-boundary.js";
14
- import { cjsExportAssignmentOf, cjsExportDiscardReason, cjsExportTargetLiteral, isCjsJsFile, isEsModuleStamp, isJsSourceFile, locOf, requireSpecOf } from "../program.js";
14
+ import { cjsExportAssignmentOf, cjsExportDiscardReason, cjsExportTargetLiteral, isCjsJsFile, isEsModuleStamp, isJsSourceFile, isNodeEsmFile, locOf, requireSpecOf } from "../program.js";
15
15
  import { COMPOUND_ASSIGN_OPS, STR_METHODS, UNSUPPORTED_STMT, isStdlibMember, sideEffectFreeOptionValue, stdlibGlobalAliasDecl, stdlibGlobalAliasNameOf, stdlibGlobalNameOf } from "./surfaces.js";
16
+ import { isNativeBuiltinValueInitializer } from "./lower-builtin-values.js";
16
17
  import { isProvenanceSourceFile } from "../provenance-registry.js";
17
18
  import { ambientUndefVarRootOf, lowerImportEquals, nsUndefRead, nsWritableTarget, trapDeclRootOf } from "./lower-namespaces.js";
18
19
  import { expandoWritableTarget, lowerExpandoAssignStmt } from "./lower-expando.js";
19
20
  import { lowerForOfArrayIter, lowerForOfMap, lowerForOfSearchParams, lowerForOfSet, lowerSafeIndexRead, objectIterOverIndexShape, strCharsCall } from "./lower-containers.js";
20
21
  import { bindingContextualGenericFnNodeOf, bindingGenericFnAliasInfoOf, bindingGenericFnInfoOf, bindingGenericFnNodeOf, bindingNeverReassigned, deadUnmappableBinding, implicitLocalFnInfoOf, implicitLocalFnNodeOf, implicitMethodCallInfersReturn, nullishExprUnitOf, nullishGenericBindingUnitOf, recordKeysArrayCall, registerOverloadedCallableAlias } from "./lower-calls.js";
21
22
  import { isMixinFnBinding, mixinResultBindingClassOf } from "./lower-mixins.js";
22
- import { genericIfaceBindingKeepsClass } from "./lower-classes.js";
23
+ import { isCompiledPrototypeMember } from "./class-prototypes.js";
24
+ import { classStaticDataFor } from "./class-static-data.js";
25
+ import { objectFactorySignature } from "./object-factory-new.js";
26
+ import { lowerClassCallbackAssign } from "./class-callbacks.js";
27
+ import { genericIfaceBindingKeepsClass, staticFieldWriteTarget } from "./lower-classes.js";
23
28
  import { lowerStreamUnderscoreAssign, streamClassAliasDecl } from "./lower-stream.js";
24
29
  import { lowerHttpResPropertyAssignment, lowerHttpServerTimeoutAssignment, lowerServerCloseOverrideAssignment } from "./lower-server.js";
25
- import { builtinMemberRequireDecl, builtinNamespaceDestructureModuleOf, createRequireBindingDecl, createRequireCalleeFileOf, createRequireNamespaceDecl, createRequireProgramModuleDecl, createRequireProgramModuleOf, lowerNodeModuleCall, registerBuiltinCallableAlias, textCodecBindingDecl } from "./lower-builtins.js";
30
+ import { isNativeFfiRequire, builtinMemberRequireDecl, builtinNamespaceDestructureModuleOf, createRequireBindingDecl, createRequireCalleeFileOf, createRequireNamespaceDecl, createRequireProgramModuleDecl, createRequireProgramModuleOf, lowerNodeModuleCall, registerBuiltinCallableAlias } from "./lower-builtins.js";
26
31
  import { lowerEnumDeclaration } from "./lower-enums.js";
27
- import { abstractPropertyDeclOf, aliasTypeofNarrows, isMatchSliceType, lowerAbsenceProbe, lowerElementCompound, lowerGroupsProjection, lowerOptionalNumber, matchResultNamedGroupsOf, runtimeOptionalTrueIds, symbolFieldInfo, withRuntimeOptionalNarrowed } from "./lower-exprs.js";
32
+ import { abstractPropertyDeclOf, aliasTypeofNarrows, isMatchSliceType, lowerAbsenceProbe, lowerCompoundValueToTarget, lowerElementCompound, lowerGroupsProjection, matchResultNamedGroupsOf, runtimeOptionalGuardIds, runtimeOptionalTrueIds, symbolFieldInfo, withRuntimeOptionalNarrowed } from "./lower-exprs.js";
28
33
  import { isSafeToRepeat } from "./expressions/evaluation-safety.js";
34
+ import { globalSymbolKey } from "./expressions/global-symbols.js";
35
+ import { lowerShortCircuitAssignment } from "./expressions/nullish-assignment.js";
36
+ import { lowerEnvironmentKey, lowerNativeFunctionAssignment } from "./lower-exprs.js";
37
+ import { isNativeProxyInitializer } from "./expressions/native-proxy.js";
29
38
  import { tryLowerExpression } from "./expressions/try-lower-expression.js";
30
- import { checkerPanicDiag, isCheckerPanic, requiresDynamicDiag } from "../../diagnostics/diagnostic.js";
31
- import { isParseArgsDynTypeName, isUnitOnlyTsType, unitOnlyUnion } from "../type-mapper.js";
39
+ import { lowerUnionFieldWrite } from "./expressions/union-field-write.js";
40
+ import { UNSUPPORTED, checkerPanicDiag, isCheckerPanic, requiresDynamicDiag } from "../../diagnostics/diagnostic.js";
41
+ import { isParseArgsDynTypeName, isUnitOnlyTsType, jsOpenObjectType, unitOnlyUnion } from "../type-mapper.js";
32
42
  import { canonicalBuiltinModule } from "../builtin-modules.js";
33
43
  import { isRelativeSpecifier } from "../workspace-registry.js";
34
44
  import { probeNodeRequireRefusal } from "../npm.js";
@@ -56,7 +66,7 @@ function npmStaticReturnedEmptyArrayType(lowerer, decl) {
56
66
  let owner = decl.parent;
57
67
  while (owner !== undefined && !ts.isFunctionLike(owner))
58
68
  owner = owner.parent;
59
- const ownerBody = owner !== undefined && "body" in owner ? owner.body : undefined;
69
+ const ownerBody = owner !== undefined && ts.isFunctionLike(owner) ? owner.body : undefined;
60
70
  if (ownerBody === undefined || !ts.isBlock(ownerBody))
61
71
  return null;
62
72
  let returned = false;
@@ -93,7 +103,7 @@ function npmStaticOptionalSelfWriteType(lowerer, decl, initial) {
93
103
  let owner = decl.parent;
94
104
  while (owner !== undefined && !ts.isFunctionLike(owner))
95
105
  owner = owner.parent;
96
- const ownerBody = owner !== undefined && "body" in owner ? owner.body : undefined;
106
+ const ownerBody = owner !== undefined && ts.isFunctionLike(owner) ? owner.body : undefined;
97
107
  if (ownerBody === undefined || !ts.isBlock(ownerBody))
98
108
  return null;
99
109
  let candidate = null;
@@ -320,7 +330,7 @@ export function provenanceElidedConstDecl(lowerer, decl) {
320
330
  const sf = decl.getSourceFile();
321
331
  if (!isProvenanceSourceFile(sf.fileName))
322
332
  return false;
323
- const stmt = decl.parent.parent;
333
+ const stmt = decl.parent?.parent;
324
334
  if (!ts.isVariableStatement(stmt) || !pureAnnotatedDeadConst(stmt, sf))
325
335
  return false;
326
336
  const diagsBefore = lowerer.diags.length;
@@ -509,11 +519,13 @@ export function lowerStmts(lowerer, stmts) {
509
519
  * empty-slot sentinel still works (a scalar slot has no spare state:
510
520
  * every bit pattern is a legal value — the setTimeout-handle shape,
511
521
  * `clearTimeout(timer)` captured above `const timer = setTimeout(...)`).
512
- * dyn/caught/jsval keep their existing capture fences. Unit-only types
522
+ * Checked-dynamic values use ref boxes with their own retain/release;
523
+ * a NULL payload remains distinct from the allocated undefined value.
524
+ * caught/jsval keep their existing capture fences. Unit-only types
513
525
  * never carry a useful forward capture. */
514
526
  const TDZ_KINDS = new Set([
515
527
  "func", "string", "array", "record", "object", "union", "map", "set", "regex", "bytes",
516
- "f64", "bool",
528
+ "f64", "bool", "dyn",
517
529
  // The runtime HANDLE kinds — heap, refcounted, pointer-backed like
518
530
  // `object`, so the box's NULL sentinel works unchanged. The canonical
519
531
  // shape is the const's own initializer capturing the const:
@@ -541,26 +553,25 @@ const TDZ_KINDS = new Set([
541
553
  * threads captures normally. The source declaration later becomes the
542
554
  * initializing `assign` (lowerVarDecl consumes tdzPredeclared). Reads
543
555
  * test the box and throw Node's exact catchable ReferenceError while it
544
- * is empty. CONST ONLY: `let` would need the same trap on writes, a
545
- * surface nothing yet needs. */
556
+ * is empty. Mutable bindings also guard writes; only the declaration's
557
+ * initializing assignment may leave the temporal dead zone. */
546
558
  export function predeclareForwardCapture(lowerer, symbol) {
547
559
  const decl = lowerer.checker.valueDeclarationOf(symbol);
548
560
  if (!decl || !ts.isVariableDeclaration(decl) || decl.name === undefined || !ts.isIdentifier(decl.name))
549
561
  return false;
550
562
  if (!decl.initializer)
551
563
  return false;
552
- if ((ts.getCombinedNodeFlags(decl) & ts.NodeFlags.Const) === 0)
564
+ const flags = ts.getCombinedNodeFlags(decl);
565
+ if ((flags & ts.NodeFlags.BlockScoped) === 0 || (flags & ts.NodeFlags.Using) !== 0)
553
566
  return false;
554
- if (lowerer.tdzPredeclared.has(symbol))
555
- return false; // defensive: never twice
556
- // MODULE-scope consts are pre-registered globals (collectGlobals):
567
+ // MODULE-scope bindings are pre-registered globals (collectGlobals):
557
568
  // references resolve through globalOf after the local search fails, so
558
569
  // a TDZ box here would SHADOW the global and never fill (the top-level
559
570
  // `const id = setInterval(cb)` self-capture — the global slot is the
560
571
  // binding). Function-scope declarations have no global; they predeclare.
561
572
  if (lowerer.globalsBySymbol.has(symbol))
562
573
  return false;
563
- const varStmt = decl.parent.parent;
574
+ const varStmt = decl.parent?.parent;
564
575
  if (!ts.isVariableStatement(varStmt))
565
576
  return false; // for-initializers stay out
566
577
  for (let i = lowerer.activeStmtLists.length - 1; i >= 0; i--) {
@@ -575,7 +586,7 @@ export function predeclareForwardCapture(lowerer, symbol) {
575
586
  // const's own initializer capturing the const (`const server =
576
587
  // createServer(h).listen(0, go)` with `go` reading `server`) is a
577
588
  // TDZ read until the initializing assign completes — JS exactly.
578
- if (idx < entry.index || entry.ctx === lowerer.ctx)
589
+ if (idx < entry.index || entry.ctx === lowerer.ctx || entry.ctx.tdzPredeclared.has(symbol))
579
590
  return false;
580
591
  const type = lowerer.irTypeOf(decl.name);
581
592
  if (!TDZ_KINDS.has(type.kind) || isUnitType(type))
@@ -583,11 +594,14 @@ export function predeclareForwardCapture(lowerer, symbol) {
583
594
  const name = decl.name.text;
584
595
  const count = entry.ctx.localCounters.get(name) ?? 0;
585
596
  entry.ctx.localCounters.set(name, count + 1);
586
- const local = { id: `${name}.${count}`, name, type, mutable: false, boxed: true, tdz: true };
597
+ const local = {
598
+ id: `${name}.${count}`, name, type,
599
+ mutable: (flags & ts.NodeFlags.Const) === 0, boxed: true, tdz: true,
600
+ };
587
601
  entry.ctx.locals.push(local);
588
602
  entry.frame.set(symbol, local);
589
603
  entry.out.push({ kind: "varDecl", localId: local.id, init: null, loc: locOf(decl) });
590
- lowerer.tdzPredeclared.set(symbol, local);
604
+ entry.ctx.tdzPredeclared.set(symbol, local);
591
605
  return true;
592
606
  }
593
607
  return false;
@@ -599,23 +613,20 @@ export function predeclareForwardCapture(lowerer, symbol) {
599
613
  * declaration and initializing assignment are pushed before the current
600
614
  * statement's IR, registered in the list's scope frame) and the statement
601
615
  * loop skips the source statement when it arrives
602
- * (lowerer.hoistedFnDecls). Same-function only: the declaration's own
603
- * lowering runs under the ctx that owns its statement list, and a
604
- * cross-function early capture would need lowering under a DIFFERENT
605
- * ctx than the one currently open — that shape keeps the honest fence. */
616
+ * (the owner's hoistedFnDecls). Forward references from nested functions
617
+ * lower the declaration under the owning statement list's context, then
618
+ * resume the caller and thread its captures normally. */
606
619
  export function predeclareForwardFnDecl(lowerer, symbol) {
607
620
  const decl = lowerer.checker.valueDeclarationOf(symbol);
608
621
  if (!decl || !ts.isFunctionDeclaration(decl) || !decl.body || decl.typeParameters)
609
622
  return false;
610
- if (lowerer.hoistedFnDecls.has(decl))
611
- return false; // defensive: never twice
612
623
  for (let i = lowerer.activeStmtLists.length - 1; i >= 0; i--) {
613
624
  const entry = lowerer.activeStmtLists[i];
614
625
  const idx = entry.stmts.indexOf(decl);
615
626
  if (idx < 0)
616
627
  continue;
617
628
  // Not forward — already lowered; resolution would have found it.
618
- if (idx <= entry.index)
629
+ if (idx <= entry.index || entry.ctx.hoistedFnDecls.has(decl))
619
630
  return false;
620
631
  // The declaration may live in an ENCLOSING function's open list (a
621
632
  // sibling hoisted function calling a later one — mutual recursion):
@@ -629,14 +640,14 @@ export function predeclareForwardFnDecl(lowerer, symbol) {
629
640
  const frameIdx = entry.ctx.scopes.indexOf(entry.frame);
630
641
  if (depth < 0 || frameIdx < 0)
631
642
  return false;
632
- lowerer.hoistedFnDecls.add(decl);
643
+ entry.ctx.hoistedFnDecls.add(decl);
633
644
  const fnTail = lowerer.fnStack.splice(depth + 1);
634
645
  const scopeTail = entry.ctx.scopes.splice(frameIdx + 1);
635
646
  try {
636
647
  entry.out.push(lowerer.lowerNestedFunctionDecl(decl));
637
648
  }
638
649
  catch (e) {
639
- lowerer.hoistedFnDecls.delete(decl);
650
+ entry.ctx.hoistedFnDecls.delete(decl);
640
651
  throw e;
641
652
  }
642
653
  finally {
@@ -651,7 +662,8 @@ export function predeclareForwardFnDecl(lowerer, symbol) {
651
662
  * was declared with `var` — no const/let/using flag anywhere on its
652
663
  * binding chain. */
653
664
  export function isVarDeclared(decl) {
654
- return (ts.getCombinedNodeFlags(decl) & ts.NodeFlags.BlockScoped) === 0;
665
+ const host = ts.isIdentifier(decl) ? hostVariableDeclarationOf(decl) : decl;
666
+ return host !== null && (ts.getCombinedNodeFlags(host) & ts.NodeFlags.BlockScoped) === 0;
655
667
  }
656
668
  /** The VariableDeclaration hosting a binding name (walking out of any
657
669
  * enclosing binding patterns), or null when the name belongs to some
@@ -688,6 +700,11 @@ export function forOfVarTarget(lowerer, decl) {
688
700
  * file rides the dyn fallback). Null when no static type can hold the
689
701
  * binding. */
690
702
  function varBindingType(lowerer, nameNode) {
703
+ if (ts.isVariableDeclaration(nameNode.parent) && isNativeProxyInitializer(lowerer, nameNode.parent.initializer))
704
+ return DYN;
705
+ if (isJsSourceFile(nameNode.getSourceFile()) && ts.isVariableDeclaration(nameNode.parent) &&
706
+ isNativeBuiltinValueInitializer(lowerer, nameNode.parent.initializer))
707
+ return DYN;
691
708
  let type = lowerer.mapTypeOf(lowerer.typeOf(nameNode));
692
709
  if (type?.kind === "record" && isJsSourceFile(nameNode.getSourceFile())) {
693
710
  const shape = lowerer.shapes.get(type.shapeId);
@@ -736,13 +753,13 @@ function varBindingType(lowerer, nameNode) {
736
753
  * classic capture semantics fall out: closures made in a loop share the
737
754
  * single boxed binding, where `let` gets a fresh box per iteration. */
738
755
  function hoistVarBinding(lowerer, symbol, nameNode) {
739
- const existing = lowerer.hoistedVars.get(symbol);
756
+ const existing = lowerer.ctx.hoistedVars.get(symbol);
740
757
  if (existing)
741
758
  return existing;
742
759
  // The parameter merge: the symbol already binds a function-root local.
743
760
  const bound = lowerer.bindingIn(lowerer.ctx, symbol);
744
761
  if (bound) {
745
- lowerer.hoistedVars.set(symbol, bound);
762
+ lowerer.ctx.hoistedVars.set(symbol, bound);
746
763
  return bound;
747
764
  }
748
765
  const type = varBindingType(lowerer, nameNode);
@@ -762,7 +779,7 @@ function hoistVarBinding(lowerer, symbol, nameNode) {
762
779
  // engine undefined for jsval).
763
780
  const wrapped = type.kind === "dyn" ? dynUndefinedExpr(locOf(nameNode)) : lowerer.unassignedSlotInit(type, locOf(nameNode));
764
781
  root.out.push({ kind: "varDecl", localId: local.id, init: wrapped, loc: locOf(nameNode) });
765
- lowerer.hoistedVars.set(symbol, local);
782
+ lowerer.ctx.hoistedVars.set(symbol, local);
766
783
  return local;
767
784
  }
768
785
  /** The forward twin of hoistVarBinding, entered from resolution failure: a
@@ -779,8 +796,6 @@ function hoistVarBinding(lowerer, symbol, nameNode) {
779
796
  * would yield if the capture ran early, and guessing "it won't" is the
780
797
  * silent-wrong-output sin. */
781
798
  export function predeclareForwardVar(lowerer, symbol) {
782
- if (lowerer.hoistedVars.has(symbol))
783
- return false; // would have resolved
784
799
  const decl = lowerer.checker.valueDeclarationOf(symbol);
785
800
  if (!decl || !ts.isVariableDeclaration(decl) || !isVarDeclared(decl))
786
801
  return false;
@@ -805,6 +820,8 @@ export function predeclareForwardVar(lowerer, symbol) {
805
820
  if (!owner)
806
821
  return false;
807
822
  const ctx = owner.ctx;
823
+ if (ctx.hoistedVars.has(symbol))
824
+ return false; // would have resolved
808
825
  // Only a slot that can hold `undefined` can carry the pre-
809
826
  // initialization reads: an undefined-armed union (the interned arm),
810
827
  // a checked-dynamic binding (the dyn undefined), or a jsval 'any'
@@ -823,7 +840,7 @@ export function predeclareForwardVar(lowerer, symbol) {
823
840
  ctx.locals.push(local);
824
841
  ctx.scopes[0].set(symbol, local);
825
842
  root.out.push({ kind: "varDecl", localId: local.id, init: wrapped, loc: locOf(decl) });
826
- lowerer.hoistedVars.set(symbol, local);
843
+ ctx.hoistedVars.set(symbol, local);
827
844
  return true;
828
845
  }
829
846
  /** Records the symbols a poisoned DECLARATION statement would have bound
@@ -868,13 +885,24 @@ export function isBlockedBinding(lowerer, symbol) {
868
885
  export function lowerScopedBlock(lowerer, stmt) {
869
886
  lowerer.scopes.push(new Map());
870
887
  try {
871
- const stmts = ts.isBlock(stmt) ? lowerer.lowerStmts(stmt.statements) : lowerer.lowerStmts([stmt]);
872
- return stmts;
888
+ return withRuntimeOptionalScope(lowerer, () => ts.isBlock(stmt) ? lowerer.lowerStmts(stmt.statements) : lowerer.lowerStmts([stmt]));
873
889
  }
874
890
  finally {
875
891
  lowerer.scopes.pop();
876
892
  }
877
893
  }
894
+ function withRuntimeOptionalScope(lowerer, lower) {
895
+ lowerer.runtimeOptionalLocals.beginScope();
896
+ try {
897
+ return lower();
898
+ }
899
+ finally {
900
+ // A guard inside one branch or loop body proves presence only for
901
+ // its remaining statements. Keep assignments that reactivated a
902
+ // slot, and restore every absence possibility from the outer scope.
903
+ lowerer.runtimeOptionalLocals.endScope();
904
+ }
905
+ }
878
906
  /** `lbl: stmt` — labeled statements. A label chain collapses to one name
879
907
  * list (`a: b: while ...` — both names target the same loop, JS-exact).
880
908
  * Loops and switches take the labels DIRECTLY (a labeled continue needs
@@ -916,6 +944,15 @@ function lowerLabeled(lowerer, stmt) {
916
944
  return { kind: "block", body, labels, loc: locOf(stmt) };
917
945
  }
918
946
  export function lowerStmt(lowerer, stmt) {
947
+ if (ts.isClassDeclaration(stmt)) {
948
+ if (!stmt.name)
949
+ lowerer.unsupported("SC1090", stmt, "anonymous local class declarations");
950
+ const info = lowerer.lowerClassExpressionInfo(stmt);
951
+ const type = { kind: "classval", className: info.def.name };
952
+ const local = lowerer.declareLocal(stmt.name, stmt.name.text, type, true);
953
+ const init = lowerer.lowerClassExpression(stmt);
954
+ return { kind: "varDecl", localId: local.id, init, loc: locOf(stmt) };
955
+ }
919
956
  if (ts.isVariableStatement(stmt)) {
920
957
  // `declare const` — ambient: no storage, no init (collectGlobals
921
958
  // skipped it; reads throw Node's ReferenceError at the access).
@@ -939,11 +976,11 @@ export function lowerStmt(lowerer, stmt) {
939
976
  // checker only performs for consts (aliasTypeofNarrows).
940
977
  const then = lowerer.narrowingAliases(aliasTypeofNarrows(lowerer, stmt.expression, true), () => withRuntimeOptionalNarrowed(lowerer, runtimeOptionalTrueIds(lowerer, stmt.expression), () => lowerer.lowerScopedBlock(stmt.thenStatement)));
941
978
  const else_ = stmt.elseStatement
942
- ? lowerer.narrowingAliases(aliasTypeofNarrows(lowerer, stmt.expression, false), () => lowerer.lowerScopedBlock(stmt.elseStatement))
979
+ ? lowerer.narrowingAliases(aliasTypeofNarrows(lowerer, stmt.expression, false), () => withRuntimeOptionalNarrowed(lowerer, runtimeOptionalGuardIds(lowerer, stmt.expression, false), () => lowerer.lowerScopedBlock(stmt.elseStatement)))
943
980
  : null;
944
- const narrowedAfter = falsyExitRuntimeOptionalLocal(lowerer, stmt);
945
- if (narrowedAfter !== null)
946
- lowerer.runtimeOptionalLocals.delete(lowerer.runtimeOptionalRootOf(narrowedAfter));
981
+ for (const local of falsyExitRuntimeOptionalLocals(lowerer, stmt)) {
982
+ lowerer.runtimeOptionalLocals.delete(lowerer.runtimeOptionalRootOf(local));
983
+ }
947
984
  return { kind: "if", cond, then, else_, loc: locOf(stmt) };
948
985
  }
949
986
  if (ts.isWhileStatement(stmt)) {
@@ -1093,7 +1130,7 @@ export function lowerStmt(lowerer, stmt) {
1093
1130
  // Already lowered eagerly by the forward-hoisting machinery
1094
1131
  // (predeclareForwardFnDecl) — its declaration and assignment are in
1095
1132
  // the list's output.
1096
- if (lowerer.hoistedFnDecls.has(stmt))
1133
+ if (lowerer.ctx.hoistedFnDecls.has(stmt))
1097
1134
  return null;
1098
1135
  return lowerer.lowerNestedFunctionDecl(stmt);
1099
1136
  }
@@ -1111,7 +1148,7 @@ export function lowerStmt(lowerer, stmt) {
1111
1148
  const entry = UNSUPPORTED_STMT[stmt.kind];
1112
1149
  if (entry)
1113
1150
  lowerer.unsupported(entry.code, stmt, entry.feature);
1114
- lowerer.unsupported("SC1090", stmt, `syntax '${ts.SyntaxKind[stmt.kind]}'`);
1151
+ lowerer.unsupported("SC1090", stmt, `syntax '${ts.syntaxKindName(stmt.kind)}'`);
1115
1152
  }
1116
1153
  /** A variable statement may carry several declarators (`let a = 1,
1117
1154
  * b = a + 1;`): each lowers to its own varDecl IN ORDER, so later
@@ -1150,6 +1187,7 @@ export function lowerVarStatement(lowerer, stmt) {
1150
1187
  // fence.
1151
1188
  if (decl.initializer !== undefined &&
1152
1189
  requireSpecOf(decl.initializer) !== null &&
1190
+ !isNativeFfiRequire(lowerer, decl.initializer) &&
1153
1191
  isJsSourceFile(decl.getSourceFile())) {
1154
1192
  const spec = requireSpecOf(decl.initializer);
1155
1193
  if (lowerer.externalTypes.has(spec))
@@ -1253,7 +1291,7 @@ function lowerNumericIteratorDecl(lowerer, decl, isConst) {
1253
1291
  if (sourceNode === null)
1254
1292
  return null;
1255
1293
  const sym = lowerer.checker.getSymbolAtLocation(decl.name);
1256
- if (!sym || lowerer.tdzPredeclared.has(sym))
1294
+ if (!sym || lowerer.ctx.tdzPredeclared.has(sym))
1257
1295
  return null;
1258
1296
  const source = lowerer.lowerExpr(sourceNode);
1259
1297
  if (!((source.type.kind === "array" && source.type.elem.kind === "f64") ||
@@ -1291,7 +1329,7 @@ function lowerMatchAllDrainDecl(lowerer, decl, isConst) {
1291
1329
  if (!call)
1292
1330
  return null;
1293
1331
  const sym = lowerer.checker.getSymbolAtLocation(decl.name);
1294
- if (!sym || lowerer.globalsBySymbol.has(sym) || lowerer.tdzPredeclared.has(sym))
1332
+ if (!sym || lowerer.globalsBySymbol.has(sym) || lowerer.ctx.tdzPredeclared.has(sym))
1295
1333
  return null;
1296
1334
  const rowsT = arrayOf(arrayOf(STRING));
1297
1335
  const declared = lowerer.mapTypeOf(lowerer.typeOf(decl.name));
@@ -1523,6 +1561,10 @@ export function lowerDestructuringDecl(lowerer, decl, isLet) {
1523
1561
  /** One pattern level: emits a declaration (or global assignment) per
1524
1562
  * bound name, recursing through hidden temps for nested patterns. */
1525
1563
  export function lowerBindingPattern(lowerer, pattern, srcRef, srcType, isLet, out, dynSpell, allowDynObject = false) {
1564
+ if (ts.isObjectBindingPattern(pattern)) {
1565
+ const patternSymbol = lowerer.typeOf(pattern).getSymbol();
1566
+ allowDynObject ||= patternSymbol?.name === "SegmentData" && lowerer.isStdlibSymbol(patternSymbol);
1567
+ }
1526
1568
  const present = patternSourceValue(lowerer, srcRef(), ts.isArrayBindingPattern(pattern), out, locOf(pattern), dynSpell);
1527
1569
  if (!typeEquals(present.type, srcType)) {
1528
1570
  lowerer.lowerBindingPattern(pattern, () => present, present.type, isLet, out, dynSpell, allowDynObject);
@@ -1530,6 +1572,23 @@ export function lowerBindingPattern(lowerer, pattern, srcRef, srcType, isLet, ou
1530
1572
  }
1531
1573
  if (ts.isArrayBindingPattern(pattern)) {
1532
1574
  lowerer.fenceStaticHeadersIteration(pattern);
1575
+ if (srcType.kind === "union" && lowerer.unions.get(srcType.unionId)?.arms.every((arm) => arm.kind === "array")) {
1576
+ for (let i = 0; i < pattern.elements.length; i++) {
1577
+ const el = pattern.elements[i];
1578
+ if (ts.isOmittedExpression(el) || el.name === undefined)
1579
+ continue;
1580
+ if (el.dotDotDotToken)
1581
+ lowerer.unsupported("SC1031", el, "rest elements over a union of array layouts");
1582
+ const loc = locOf(el);
1583
+ let value = unionArrayValueRead(lowerer, srcRef(), numLit(i, loc), loc);
1584
+ if (!value)
1585
+ lowerer.unsupported("SC1031", el, "array union elements without a common native representation");
1586
+ if (el.initializer)
1587
+ value = applyBindingDefault(lowerer, el, value);
1588
+ lowerer.bindPatternTarget(el.name, value, isLet, out);
1589
+ }
1590
+ return;
1591
+ }
1533
1592
  // Tuple sources: each position is a field read of the tuple's record
1534
1593
  // shape — the positional twin of object destructuring below.
1535
1594
  const tupleShape = srcType.kind === "record" ? lowerer.shapes.get(srcType.shapeId) : undefined;
@@ -2108,7 +2167,8 @@ function patternSourceValue(lowerer, value, arrayPattern, out, loc, spelling) {
2108
2167
  const unionId = value.type.unionId;
2109
2168
  const arms = lowerer.unions.get(unionId)?.arms;
2110
2169
  const present = arms?.filter((arm) => !isUnitType(arm));
2111
- if (!arms || present?.length !== 1 || arms.length === 1)
2170
+ if (!arms || !present?.length || present.length === arms.length ||
2171
+ (present.length > 1 && !(arrayPattern && present.every((arm) => arm.kind === "array"))))
2112
2172
  return value;
2113
2173
  for (const [tag, arm] of arms.entries()) {
2114
2174
  if (!isUnitType(arm))
@@ -2124,13 +2184,18 @@ function patternSourceValue(lowerer, value, arrayPattern, out, loc, spelling) {
2124
2184
  else_: null, loc,
2125
2185
  });
2126
2186
  }
2127
- return { kind: "unionNarrow", unionId, tag: lowerer.armTag(unionId, present[0]), value, type: present[0], loc };
2187
+ if (present.length === 1) {
2188
+ return { kind: "unionNarrow", unionId, tag: lowerer.armTag(unionId, present[0]), value, type: present[0], loc };
2189
+ }
2190
+ const type = { kind: "union", unionId: lowerer.unions.intern(present) };
2191
+ return lowerer.coerceToExpected(value, type);
2128
2192
  }
2129
2193
  /** The type a pattern element binds at — the checker's type of the bound
2130
2194
  * identifier, or of the nested pattern itself (its implied type). Null
2131
- * when the type has no static mapping (the caller fences). */
2195
+ * when the type has no static mapping or checked JS fallback. */
2132
2196
  function patternBindingType(lowerer, name) {
2133
- return lowerer.mapTypeOf(lowerer.typeOf(name));
2197
+ const type = lowerer.typeOf(name);
2198
+ return lowerer.mapTypeOf(type) ?? (isJsSourceFile(name.getSourceFile()) ? dynFallbackType(lowerer, name, type) : null);
2134
2199
  }
2135
2200
  /** The STATIC property name of a destructuring key: identifiers spell
2136
2201
  * themselves, string/numeric-literal keys and COMPUTED keys fold through
@@ -2334,7 +2399,7 @@ function stdlibGlobalTokenDestructure(lowerer, decl, isLet) {
2334
2399
  lowerer.unsupported("SC1031", el, `destructuring the member '${propName}' of the builtin global '${globalName}' (a detached member loses its receiver-keyed lowering — call it through the global)`);
2335
2400
  }
2336
2401
  const symbol = lowerer.checker.getSymbolAtLocation(el.name);
2337
- if (!symbol || lowerer.tdzPredeclared.has(symbol)) {
2402
+ if (!symbol || lowerer.ctx.tdzPredeclared.has(symbol)) {
2338
2403
  lowerer.unsupported("SC1031", el, `bindings with predeclared slots over the builtin global '${globalName}'`);
2339
2404
  }
2340
2405
  const g = lowerer.globalsBySymbol.get(symbol);
@@ -2353,7 +2418,7 @@ function stdlibGlobalTokenDestructure(lowerer, decl, isLet) {
2353
2418
  lowerer.stdlibGlobalAliases.set(symbol, b.alias);
2354
2419
  }
2355
2420
  if (b.g !== undefined) {
2356
- out.push({ kind: "assign", localId: b.g.id, value: lowerer.coerceInto(b.name, token, b.g.type), loc });
2421
+ out.push({ kind: "assign", localId: b.g.id, value: lowerer.coerceInto(b.name, token, b.g.type), ...(b.g.tdz ? { initializes: true } : {}), loc });
2357
2422
  }
2358
2423
  else {
2359
2424
  const local = lowerer.declareLocal(b.name, b.name.text, STRING, isLet);
@@ -2401,7 +2466,12 @@ function undefArmDefault(lowerer, blame, init, value, bodyT) {
2401
2466
  return { kind: "ternary", cond: isUndef, then: dflt, else_: value, type: bodyT, loc };
2402
2467
  }
2403
2468
  let present = null;
2404
- if (bodyT.kind === "union") {
2469
+ if (bodyT.kind === "dyn" && lowerer.dynConvertible(fieldType)) {
2470
+ // The undefined arm is handled by the ternary. A present JSON-safe
2471
+ // union can cross into the binding's checked-dynamic slot.
2472
+ present = lowerer.coerceInto(blame, value, bodyT);
2473
+ }
2474
+ else if (bodyT.kind === "union") {
2405
2475
  const retag = lowerer.unionRetagHelper(fieldType.unionId, bodyT.unionId, loc);
2406
2476
  if (retag)
2407
2477
  present = { kind: "call", callee: retag, args: [value], type: bodyT, loc };
@@ -2644,6 +2714,9 @@ function objectRestValue(lowerer, el, srcRef, srcType, shape) {
2644
2714
  * JS skips them and so does the packing. */
2645
2715
  function classInstanceRestValue(lowerer, blame, srcRef, srcType, info, consumed, restT) {
2646
2716
  const loc = locOf(blame);
2717
+ if (info.symbolFields?.size) {
2718
+ lowerer.unsupported("SC1031", blame, "rest bindings over class instances with symbol-keyed fields (the copied symbols have no record form)");
2719
+ }
2647
2720
  for (let c = info; c; c = c.base) {
2648
2721
  if (c.builtinError || c.builtinEmitter || c.builtinStream) {
2649
2722
  lowerer.unsupported("SC1031", blame, "rest bindings over runtime-provided class instances (Error/EventEmitter/stream internals have no record form)");
@@ -2905,7 +2978,7 @@ function enginePatternSpec(lowerer, pattern) {
2905
2978
  const d = exprText(el.initializer, boundBefore);
2906
2979
  if (d === null)
2907
2980
  return null;
2908
- sub += `=${d}`;
2981
+ sub = sub + `=${d}`;
2909
2982
  }
2910
2983
  parts.push(el.dotDotDotToken ? `...${sub}` : sub);
2911
2984
  }
@@ -2950,7 +3023,7 @@ function enginePatternSpec(lowerer, pattern) {
2950
3023
  const d = exprText(el.initializer, boundBefore);
2951
3024
  if (d === null)
2952
3025
  return null;
2953
- sub += `=${d}`;
3026
+ sub = sub + `=${d}`;
2954
3027
  }
2955
3028
  parts.push(`[${key}]:${sub}`);
2956
3029
  }
@@ -3026,7 +3099,7 @@ export function lowerJsvalBindingPattern(lowerer, pattern, srcRef, isLet, out) {
3026
3099
  const symbol = lowerer.checker.getSymbolAtLocation(name);
3027
3100
  const g = symbol ? lowerer.globalsBySymbol.get(symbol) : undefined;
3028
3101
  if (g) {
3029
- out.push({ kind: "assign", localId: g.id, value: lowerer.coerceInto(name, value, g.type), loc: bindLoc });
3102
+ out.push({ kind: "assign", localId: g.id, value: lowerer.coerceInto(name, value, g.type), ...(g.tdz ? { initializes: true } : {}), loc: bindLoc });
3030
3103
  return;
3031
3104
  }
3032
3105
  if (symbol && hostVariableDeclarationOf(name) !== null && isVarDeclared(name)) {
@@ -3056,7 +3129,7 @@ export function bindPatternTarget(lowerer, name, value, isLet, out, allowDynObje
3056
3129
  const symbol = lowerer.checker.getSymbolAtLocation(name);
3057
3130
  const g = symbol ? lowerer.globalsBySymbol.get(symbol) : undefined;
3058
3131
  if (g) {
3059
- out.push({ kind: "assign", localId: g.id, value: lowerer.coerceInto(name, value, g.type), loc });
3132
+ out.push({ kind: "assign", localId: g.id, value: lowerer.coerceInto(name, value, g.type), ...(g.tdz ? { initializes: true } : {}), loc });
3060
3133
  return;
3061
3134
  }
3062
3135
  // A `var`-declared pattern name assigns its function-scoped hoisted
@@ -3115,13 +3188,9 @@ export function bindPatternTarget(lowerer, name, value, isLet, out, allowDynObje
3115
3188
  out.push({ kind: "varDecl", localId: tmp.id, init: value, loc });
3116
3189
  lowerer.lowerBindingPattern(name, () => ({ kind: "varRef", localId: tmp.id, type: value.type, loc }), value.type, isLet, out, undefined, allowDynObject);
3117
3190
  }
3118
- /** For-loop initializers. let/const stay restricted to ONE declarator (JS
3119
- * per-iteration binding copies for several captured loop variables are
3120
- * not modeled yet); `var` initializers take any number — a `var` is ONE
3121
- * function-scoped binding with no per-iteration copies to model, so
3122
- * `for (var i = 0, n = xs.length; ...)` is just two hoisted-slot
3123
- * assignments (wrapped in a block when several). Statement position goes
3124
- * through lowerVarStatement. */
3191
+ /** For-loop initializers evaluate declarators from left to right. The LLVM
3192
+ * loop emitter keeps their scope alive and freshens every captured let
3193
+ * binding before the first condition and each subsequent update. */
3125
3194
  export function lowerVarDeclList(lowerer, list) {
3126
3195
  if ((list.flags & ts.NodeFlags.Using) !== 0) {
3127
3196
  lowerer.unsupported("SC1090", list, "'using' declarations (dispose-at-scope-exit semantics)");
@@ -3144,23 +3213,19 @@ export function lowerVarDeclList(lowerer, list) {
3144
3213
  return out[0];
3145
3214
  return { kind: "block", body: out, loc: locOf(list) };
3146
3215
  }
3147
- if (list.declarations.length !== 1) {
3148
- lowerer.unsupported("SC1090", list, "multi-declaration for-loop initializers");
3216
+ const out = [];
3217
+ for (const decl of list.declarations) {
3218
+ if (ts.isArrayBindingPattern(decl.name) || ts.isObjectBindingPattern(decl.name)) {
3219
+ // Destructuring produces nested initialization blocks; copying
3220
+ // their captured bindings still needs a distinct head-scope plan.
3221
+ lowerer.unsupported("SC1031", decl.name, "let/const destructuring in for-loop initializers (declare the pattern before the loop, or use var)");
3222
+ }
3223
+ const lowered = lowerer.lowerVarDecl(decl, isLet);
3224
+ if (!lowered)
3225
+ throw new InternalCompilerError("lowerer bug: for-init declarator resolved to a global");
3226
+ out.push(lowered);
3149
3227
  }
3150
- const decl = list.declarations[0];
3151
- if (ts.isArrayBindingPattern(decl.name) || ts.isObjectBindingPattern(decl.name)) {
3152
- // `for (let [x] = init; ...)`: the desugar is a multi-statement
3153
- // block, and the backend's per-iteration fresh-binding copy (what
3154
- // makes closures in iteration k see iteration k's let) keys off a
3155
- // single varDecl init — a captured destructured head would silently
3156
- // share one binding. `var` heads above have no per-iteration story
3157
- // and lower; let/const keep an honest fence.
3158
- lowerer.unsupported("SC1031", decl.name, "let/const destructuring in for-loop initializers (declare the pattern before the loop, or use var)");
3159
- }
3160
- const lowered = lowerer.lowerVarDecl(decl, isLet);
3161
- if (!lowered)
3162
- throw new InternalCompilerError("lowerer bug: for-init declarator resolved to a global");
3163
- return lowered;
3228
+ return out.length === 1 ? out[0] : { kind: "block", body: out, loc: locOf(list) };
3164
3229
  }
3165
3230
  /** A single static type for an initializer-less JavaScript `let` whose
3166
3231
  * later plain writes all agree. An evolving JS local reads as `undefined`
@@ -3173,7 +3238,7 @@ function inferredEvolvingLetType(lowerer, decl) {
3173
3238
  if (!ts.isIdentifier(decl.name))
3174
3239
  return null;
3175
3240
  const symbol = lowerer.checker.getSymbolAtLocation(decl.name);
3176
- const scope = decl.parent.parent.parent;
3241
+ const scope = decl.parent?.parent?.parent;
3177
3242
  if (symbol === undefined || (!ts.isBlock(scope) && !ts.isSourceFile(scope)))
3178
3243
  return null;
3179
3244
  const isPlainAssignmentTarget = (node) => {
@@ -3313,8 +3378,8 @@ export function lowerVarDecl(lowerer, decl, isLet) {
3313
3378
  // and keep the plain-variable lowering.
3314
3379
  if (!decl.initializer &&
3315
3380
  (decl.name.text === "module" || decl.name.text === "exports") &&
3316
- ts.isVariableStatement(decl.parent.parent) &&
3317
- ts.isSourceFile(decl.parent.parent.parent) &&
3381
+ ts.isVariableStatement(decl.parent?.parent) &&
3382
+ ts.isSourceFile(decl.parent?.parent?.parent) &&
3318
3383
  !isJsSourceFile(decl.getSourceFile()) &&
3319
3384
  !decl.getSourceFile().statements.some((s) => ts.isImportDeclaration(s) || ts.isExportDeclaration(s) || ts.isExportAssignment(s) ||
3320
3385
  (ts.canHaveModifiers(s) && ts.getModifiers(s)?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword) === true))) {
@@ -3335,7 +3400,7 @@ export function lowerVarDecl(lowerer, decl, isLet) {
3335
3400
  // plumbing: each call through the binding resolves per site
3336
3401
  // (lowerCreateRequireCall); no storage, no code (collectGlobals
3337
3402
  // skipped its global by the same test).
3338
- if (!isLet && createRequireBindingDecl(lowerer, decl.name, decl.initializer))
3403
+ if (createRequireBindingDecl(lowerer, decl.name, decl.initializer))
3339
3404
  return null;
3340
3405
  // `const fs = require("node:fs")` through that binding — a builtin
3341
3406
  // namespace import in const clothing: alias plumbing, no storage
@@ -3366,13 +3431,6 @@ export function lowerVarDecl(lowerer, decl, isLet) {
3366
3431
  })());
3367
3432
  if (stableStdlibAlias && stdlibGlobalAliasDecl(lowerer, decl.name, decl.initializer))
3368
3433
  return null;
3369
- // `const encoder = new TextEncoder()` and a statically-labelled
3370
- // TextDecoder twin: the codec has no general value representation, but calls
3371
- // through this stable binding resolve back to the initializer. The
3372
- // supported constructors are effect-free, so the declaration itself
3373
- // is compile-time alias plumbing with no storage or code.
3374
- if (!isLet && textCodecBindingDecl(lowerer, decl.name, decl.initializer))
3375
- return null;
3376
3434
  // `const f = <T>(x: T) => x` — a generic function value binding: the
3377
3435
  // initializer monomorphizes per call-site-resolved signature exactly
3378
3436
  // like a generic function declaration (bindingGenericFnInfoOf —
@@ -3478,7 +3536,8 @@ export function lowerVarDecl(lowerer, decl, isLet) {
3478
3536
  return { kind: "assign", localId: g.id, value: wrapped, loc: locOf(decl) };
3479
3537
  return null;
3480
3538
  }
3481
- const raw = lowerVariableInitializer(lowerer, decl.initializer);
3539
+ const raw = lowerVariableInitializer(lowerer, decl.initializer, g.type.kind === "dyn" && (isNativeBuiltinValueInitializer(lowerer, decl.initializer) ||
3540
+ ts.isArrayLiteralExpression(decl.initializer)) ? DYN : undefined);
3482
3541
  const arithmetic = raw.type.kind === "union"
3483
3542
  ? lowerer.unions.get(raw.type.unionId)?.arms
3484
3543
  : undefined;
@@ -3488,17 +3547,17 @@ export function lowerVarDecl(lowerer, decl, isLet) {
3488
3547
  lowerer.runtimeOptionalArithmeticGlobals.add(g);
3489
3548
  }
3490
3549
  const init = lowerer.coerceInto(decl.initializer, raw, g.type);
3491
- return { kind: "assign", localId: g.id, value: init, loc: locOf(decl) };
3550
+ return { kind: "assign", localId: g.id, value: init, ...(g.tdz ? { initializes: true } : {}), loc: locOf(decl) };
3492
3551
  }
3493
- // A forward-captured const pre-declared as a TDZ box (an earlier
3552
+ // A forward-captured binding pre-declared as a TDZ box (an earlier
3494
3553
  // function in this scope captured it — predeclareForwardCapture): the
3495
3554
  // binding and its scope-entry varDecl already exist; the source
3496
3555
  // declaration is the one initializing `assign` into the shared box.
3497
- const pre = declSymbol ? lowerer.tdzPredeclared.get(declSymbol) : undefined;
3556
+ const pre = declSymbol ? lowerer.ctx.tdzPredeclared.get(declSymbol) : undefined;
3498
3557
  if (pre && decl.initializer) {
3499
- lowerer.tdzPredeclared.delete(declSymbol);
3558
+ lowerer.ctx.tdzPredeclared.delete(declSymbol);
3500
3559
  const init = lowerer.lowerExprExpecting(decl.initializer, pre.type);
3501
- return { kind: "assign", localId: pre.id, value: init, loc: locOf(decl) };
3560
+ return { kind: "assign", localId: pre.id, value: init, initializes: true, loc: locOf(decl) };
3502
3561
  }
3503
3562
  // `var x = e` — an ASSIGNMENT into the function-scoped hoisted slot
3504
3563
  // (hoistVarBinding mints it on first encounter and pushes its varDecl
@@ -3529,7 +3588,7 @@ export function lowerVarDecl(lowerer, decl, isLet) {
3529
3588
  // `var v: void;` / `let x: undefined;` — a unit-only binding rides
3530
3589
  // the unit-only union (its undefined arm is the unassigned state,
3531
3590
  // which is also the only state).
3532
- if (type.kind === "void" && isUnitOnlyTsType(lowerer.typeOf(decl.name))) {
3591
+ if (type.kind === "void" && isUnitOnlyTsType(lowerer.typeOf(decl.name), lowerer.typeParamResolver)) {
3533
3592
  type = unitOnlyUnion(lowerer.unions);
3534
3593
  }
3535
3594
  if (type.kind === "void")
@@ -3546,11 +3605,15 @@ export function lowerVarDecl(lowerer, decl, isLet) {
3546
3605
  // function (with its hint), not the unmappable declared type. If it
3547
3606
  // poisons, still declare the local when its type is representable, so
3548
3607
  // later references to this name don't produce cascading errors.
3608
+ const inferredObjectType = isJsSourceFile(decl.getSourceFile()) ? lowerer.mapTypeOf(lowerer.typeOf(decl.name)) : null;
3609
+ const expandsObject = inferredObjectType?.kind === "record" && jsObjectBindingExpands(lowerer, decl, inferredObjectType);
3549
3610
  let init;
3550
3611
  try {
3551
- init = immediatelyGuardedAbsenceProbe(lowerer, decl)
3612
+ init = expandsObject || (isJsSourceFile(decl.getSourceFile()) && !decl.type &&
3613
+ isNativeBuiltinValueInitializer(lowerer, decl.initializer)) ? lowerer.lowerExprExpecting(decl.initializer, DYN) : immediatelyGuardedAbsenceProbe(lowerer, decl)
3552
3614
  ? (lowerAbsenceProbe(lowerer, decl.initializer) ?? lowerer.lowerExpr(decl.initializer))
3553
- : lowerVariableInitializer(lowerer, decl.initializer);
3615
+ : lowerVariableInitializer(lowerer, decl.initializer, decl.type && (lowerer.typeOf(decl.name).flags & ts.TypeFlags.Never) === 0
3616
+ ? lowerer.mapTypeOf(lowerer.typeOf(decl.name)) ?? undefined : undefined);
3554
3617
  }
3555
3618
  catch (e) {
3556
3619
  if (e instanceof PoisonError) {
@@ -3604,6 +3667,21 @@ export function lowerVarDecl(lowerer, decl, isLet) {
3604
3667
  npmStaticPackageOfPath(decl.getSourceFile().fileName) !== null) {
3605
3668
  type = DYN;
3606
3669
  }
3670
+ const preservesObjectIdentity = init.type.kind === "dyn" &&
3671
+ (inferredObjectType?.kind === "record" || inferredObjectType?.kind === "array" ||
3672
+ (isJsSourceFile(decl.getSourceFile()) && inferredObjectType !== null &&
3673
+ (inferredObjectType.kind === "date" || inferredObjectType.kind === "func" || jsOpenObjectType(decl, inferredObjectType, lowerer.shapes, lowerer.unions).kind === "dyn")) ||
3674
+ (isJsSourceFile(decl.getSourceFile()) && inferredObjectType !== null &&
3675
+ (isUnitType(inferredObjectType) || inferredObjectType.kind === "union" && lowerer.unions.get(inferredObjectType.unionId)?.arms.every(isUnitType)))) &&
3676
+ !decl.type && !hasJsTypeAnnotation(decl);
3677
+ if (expandsObject || preservesObjectIdentity || (isJsSourceFile(decl.getSourceFile()) &&
3678
+ !decl.type && isNativeBuiltinValueInitializer(lowerer, decl.initializer))) {
3679
+ type = DYN;
3680
+ }
3681
+ if (isJsSourceFile(decl.getSourceFile()) && !decl.type && init.type.kind === "array" && init.type.elem.kind === "dyn" &&
3682
+ (ts.isNewExpression(decl.initializer) || ts.isCallExpression(decl.initializer)) && lowerer.isStdlibGlobal(decl.initializer.expression, "Array")) {
3683
+ type = init.type;
3684
+ }
3607
3685
  // A JS `let x = {}`: TS's empty-object-literal type admits ANY later
3608
3686
  // non-nullish assignment (`envs = {}`, later `envs =
3609
3687
  // Object.fromEntries(...)` — tsc accepts every such write, since
@@ -3681,7 +3759,9 @@ export function lowerVarDecl(lowerer, decl, isLet) {
3681
3759
  // static signature would wrap an arity-narrowing adapter that DROPS
3682
3760
  // arguments JS would deliver; calls through the dyn binding take the
3683
3761
  // boxed thunk's JS arity instead.
3684
- if (type?.kind === "func" && init.type.kind === "dyn" && isJsSourceFile(decl.getSourceFile())) {
3762
+ if (type?.kind === "func" && init.type.kind === "dyn" &&
3763
+ (isJsSourceFile(decl.getSourceFile()) ||
3764
+ !decl.type && !hasJsTypeAnnotation(decl) && type.rest === true && type.restAbi === undefined)) {
3685
3765
  type = DYN;
3686
3766
  }
3687
3767
  // A checker-`any` CONST whose initializer lowered to a STATIC type
@@ -3718,6 +3798,9 @@ export function lowerVarDecl(lowerer, decl, isLet) {
3718
3798
  if (!type)
3719
3799
  lowerer.badType(decl.name, lowerer.typeOf(decl.name));
3720
3800
  let settledType = type;
3801
+ if (!isLet && isJsSourceFile(decl.getSourceFile()) && !hasJsTypeAnnotation(decl) && decl.initializer && ts.isNewExpression(decl.initializer)) {
3802
+ settledType = objectFactorySignature(lowerer, decl.initializer)?.returnType ?? settledType;
3803
+ }
3721
3804
  const arithmeticType = decl.initializer ? lowerer.runtimeOptionalArithmeticTypes.get(decl.initializer) : undefined;
3722
3805
  const isStringArithmeticUnion = (t) => {
3723
3806
  if (t.kind !== "union")
@@ -3734,16 +3817,26 @@ export function lowerVarDecl(lowerer, decl, isLet) {
3734
3817
  const optionalSelfWriteType = isLet
3735
3818
  ? npmStaticOptionalSelfWriteType(lowerer, decl, settledType)
3736
3819
  : null;
3737
- settledType = lowerer.runtimeOptionalBindingType(decl.name, settledType);
3820
+ settledType = expandsObject || preservesObjectIdentity ? DYN : lowerer.runtimeOptionalBindingType(decl.name, settledType);
3738
3821
  if (optionalSelfWriteType !== null)
3739
3822
  settledType = optionalSelfWriteType;
3740
3823
  if (returnedEmptyArrayType !== null)
3741
3824
  settledType = returnedEmptyArrayType;
3825
+ // Exhaustiveness witnesses (`const unreachable: never = value`) have
3826
+ // no useful checker layout, but their initializer still has a runtime
3827
+ // representation. Preserve it instead of forcing never's numeric
3828
+ // placeholder onto a recursive union or string. Keeping the value also
3829
+ // preserves behavior when an explicit assertion makes this reachable.
3830
+ if (!isLet && lowerer.checker.isNeverType(lowerer.typeOf(decl.name)) &&
3831
+ init.type.kind !== "void" && !isUnitType(init.type)) {
3832
+ settledType = init.type;
3833
+ }
3742
3834
  // `const x: void = undefined` / `let y: undefined = undefined`: the
3743
3835
  // unit-only union — the initializer's unit literal wraps into its arm
3744
- // like any optional completion. Non-literal void initializers (a
3745
- // void CALL's result) keep their fence at the coercion below.
3746
- if (settledType.kind === "void" && isUnitOnlyTsType(lowerer.typeOf(decl.name))) {
3836
+ // like any optional completion. A generic visitor can bind the slot's
3837
+ // T to void; consult that binding before deciding its value layout.
3838
+ // coerceInto preserves a void call's effects before wrapping undefined.
3839
+ if (settledType.kind === "void" && isUnitOnlyTsType(lowerer.typeOf(decl.name), lowerer.typeParamResolver)) {
3747
3840
  settledType = unitOnlyUnion(lowerer.unions);
3748
3841
  }
3749
3842
  if (settledType.kind === "void")
@@ -3817,15 +3910,15 @@ export function lowerVarDecl(lowerer, decl, isLet) {
3817
3910
  settledType = init.type;
3818
3911
  }
3819
3912
  // A TDZ box minted DURING this very initializer (a callback inside it
3820
- // captured this const — predeclareForwardCapture's current-statement
3913
+ // captured this binding — predeclareForwardCapture's current-statement
3821
3914
  // case): the binding and its scope-entry varDecl already exist, so
3822
3915
  // this declaration is the initializing `assign` into the shared box,
3823
3916
  // not a fresh local.
3824
- const preSelf = declSymbol ? lowerer.tdzPredeclared.get(declSymbol) : undefined;
3917
+ const preSelf = declSymbol ? lowerer.ctx.tdzPredeclared.get(declSymbol) : undefined;
3825
3918
  if (preSelf) {
3826
- lowerer.tdzPredeclared.delete(declSymbol);
3919
+ lowerer.ctx.tdzPredeclared.delete(declSymbol);
3827
3920
  init = lowerer.coerceInto(decl.initializer, init, preSelf.type);
3828
- return { kind: "assign", localId: preSelf.id, value: init, loc: locOf(decl) };
3921
+ return { kind: "assign", localId: preSelf.id, value: init, initializes: true, loc: locOf(decl) };
3829
3922
  }
3830
3923
  // Slot coercion: `const r: A | B = bValue;` wraps implicitly; width
3831
3924
  // subtyping (`const p: {a: number} = wider;`) is rejected, not coerced.
@@ -3841,7 +3934,7 @@ export function lowerVarDecl(lowerer, decl, isLet) {
3841
3934
  }
3842
3935
  return { kind: "varDecl", localId: local.id, init, loc: locOf(decl) };
3843
3936
  }
3844
- function lowerVariableInitializer(lowerer, node) {
3937
+ function lowerVariableInitializer(lowerer, node, expected) {
3845
3938
  let value = node;
3846
3939
  while (ts.isParenthesizedExpression(value) ||
3847
3940
  ts.isAsExpression(value) ||
@@ -3849,8 +3942,18 @@ function lowerVariableInitializer(lowerer, node) {
3849
3942
  ts.isSatisfiesExpression(value)) {
3850
3943
  value = value.expression;
3851
3944
  }
3852
- if (!ts.isObjectLiteralExpression(value))
3853
- return lowerer.lowerExpr(node);
3945
+ // An explicit destination supplies the layout for fresh construction,
3946
+ // including either arm of a conditional. Existing values still pass
3947
+ // through the normal conversion and alias-preservation rules.
3948
+ if (!ts.isObjectLiteralExpression(value)) {
3949
+ // Empty Map/Set construction can use its destination, but class
3950
+ // instances must retain their nominal layout for generic dispatch.
3951
+ const empty = expected ? lowerer.emptyCollectionFor(node, expected) : null;
3952
+ if (empty)
3953
+ return lowerer.coerceInto(node, empty, expected);
3954
+ return ts.isArrayLiteralExpression(value) || ts.isConditionalExpression(value)
3955
+ ? lowerer.lowerExprExpecting(node, expected) : lowerer.lowerExpr(node);
3956
+ }
3854
3957
  const previous = new Map();
3855
3958
  for (const property of value.properties) {
3856
3959
  if (!ts.isPropertyAssignment(property) || !ts.isComputedPropertyName(property.name))
@@ -3864,7 +3967,7 @@ function lowerVariableInitializer(lowerer, node) {
3864
3967
  lowerer.chainRecvByNode.set(keyNode, lowerer.ensureString(optional, keyNode));
3865
3968
  }
3866
3969
  try {
3867
- return lowerer.lowerExpr(node);
3970
+ return lowerer.lowerExprExpecting(node, expected);
3868
3971
  }
3869
3972
  finally {
3870
3973
  for (const [keyNode, prior] of previous) {
@@ -3875,6 +3978,87 @@ function lowerVariableInitializer(lowerer, node) {
3875
3978
  }
3876
3979
  }
3877
3980
  }
3981
+ /** A JS object literal's inferred fields do not close its later storage.
3982
+ * Keep the original native object when writes add keys or delete fields;
3983
+ * converting it to a fixed record would discard that behavior. */
3984
+ function jsObjectBindingExpands(lowerer, decl, type) {
3985
+ if (decl.type || !decl.initializer || !ts.isIdentifier(decl.name) || !isJsSourceFile(decl.getSourceFile()))
3986
+ return false;
3987
+ let initializer = decl.initializer;
3988
+ while (ts.isParenthesizedExpression(initializer))
3989
+ initializer = initializer.expression;
3990
+ if (!ts.isObjectLiteralExpression(initializer))
3991
+ return false;
3992
+ if (hasJsTypeAnnotation(decl))
3993
+ return false;
3994
+ // A generic clone retains its declared T contract. Its instantiated
3995
+ // record is also the factory's return/capture layout; it is not an
3996
+ // anonymous JavaScript object whose fields came only from inference.
3997
+ if (lowerer.typeParamResolver(lowerer.typeOf(decl.name)) !== null)
3998
+ return false;
3999
+ const symbol = lowerer.resolveValueSymbol(decl.name);
4000
+ const shape = lowerer.shapes.get(type.shapeId);
4001
+ if (!symbol || !shape)
4002
+ return false;
4003
+ const names = new Set(shape.fields.map((field) => field.name));
4004
+ let scope = decl;
4005
+ while (scope.parent && !ts.isFunctionLike(scope) && !ts.isSourceFile(scope))
4006
+ scope = scope.parent;
4007
+ const aliases = new Set([symbol]);
4008
+ const unwrap = (node) => {
4009
+ while (ts.isParenthesizedExpression(node))
4010
+ node = node.expression;
4011
+ return node;
4012
+ };
4013
+ let changed = true;
4014
+ while (changed) {
4015
+ changed = false;
4016
+ const collect = (node) => {
4017
+ if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name) && node.initializer && !node.type && !hasJsTypeAnnotation(node)) {
4018
+ const source = unwrap(node.initializer);
4019
+ const sourceSymbol = ts.isIdentifier(source) ? lowerer.resolveValueSymbol(source) : undefined;
4020
+ const alias = lowerer.resolveValueSymbol(node.name);
4021
+ if (sourceSymbol && aliases.has(sourceSymbol) && alias && !aliases.has(alias)) {
4022
+ aliases.add(alias);
4023
+ changed = true;
4024
+ }
4025
+ }
4026
+ ts.forEachChild(node, collect);
4027
+ };
4028
+ collect(scope);
4029
+ }
4030
+ let expands = false;
4031
+ const property = (node) => {
4032
+ if (!ts.isPropertyAccessExpression(node) && !ts.isElementAccessExpression(node))
4033
+ return undefined;
4034
+ const receiver = unwrap(node.expression);
4035
+ const receiverSymbol = ts.isIdentifier(receiver) ? lowerer.resolveValueSymbol(receiver) : undefined;
4036
+ if (!receiverSymbol || !aliases.has(receiverSymbol))
4037
+ return undefined;
4038
+ if (ts.isPropertyAccessExpression(node))
4039
+ return node.name.text;
4040
+ return ts.isStringLiteral(node.argumentExpression) || ts.isNumericLiteral(node.argumentExpression)
4041
+ ? node.argumentExpression.text : null;
4042
+ };
4043
+ const visit = (node) => {
4044
+ if (expands)
4045
+ return;
4046
+ if (ts.isBinaryExpression(node) && node.operatorToken.kind >= ts.SyntaxKind.FirstAssignment && node.operatorToken.kind <= ts.SyntaxKind.LastAssignment) {
4047
+ const name = property(node.left);
4048
+ if (name === null || (name !== undefined && !names.has(name)))
4049
+ expands = true;
4050
+ }
4051
+ if (ts.isDeleteExpression(node) && property(node.expression) !== undefined)
4052
+ expands = true;
4053
+ ts.forEachChild(node, visit);
4054
+ };
4055
+ visit(scope);
4056
+ return expands;
4057
+ }
4058
+ export function hasJsTypeAnnotation(decl) {
4059
+ const statement = decl.parent?.parent;
4060
+ return !!statement && /@type\b/.test(decl.getSourceFile().text.slice(statement.pos, decl.getStart()));
4061
+ }
3878
4062
  function immediatelyGuardedAbsenceProbe(lowerer, decl) {
3879
4063
  if (decl.type || !ts.isIdentifier(decl.name) || !decl.initializer)
3880
4064
  return false;
@@ -3899,96 +4083,71 @@ function immediatelyGuardedAbsenceProbe(lowerer, decl) {
3899
4083
  operand = operand.expression;
3900
4084
  return ts.isIdentifier(operand) && lowerer.resolveValueSymbol(operand) === lowerer.resolveValueSymbol(decl.name);
3901
4085
  }
3902
- function falsyExitRuntimeOptionalLocal(lowerer, stmt) {
4086
+ function falsyExitRuntimeOptionalLocals(lowerer, stmt) {
3903
4087
  if (stmt.elseStatement)
3904
- return null;
3905
- let condition = stmt.expression;
3906
- while (ts.isParenthesizedExpression(condition))
3907
- condition = condition.expression;
3908
- if (!ts.isPrefixUnaryExpression(condition) || condition.operator !== ts.SyntaxKind.ExclamationToken)
3909
- return null;
3910
- let operand = condition.operand;
3911
- while (ts.isParenthesizedExpression(operand))
3912
- operand = operand.expression;
3913
- if (!ts.isIdentifier(operand))
3914
- return null;
3915
- const local = lowerer.resolveLocal(operand);
3916
- if (!local || !lowerer.runtimeOptionalLocals.has(lowerer.runtimeOptionalRootOf(local)))
3917
- return null;
3918
- const exits = ts.isReturnStatement(stmt.thenStatement) || ts.isThrowStatement(stmt.thenStatement) ||
3919
- (ts.isBlock(stmt.thenStatement) && stmt.thenStatement.statements.length > 0 &&
3920
- (ts.isReturnStatement(stmt.thenStatement.statements[stmt.thenStatement.statements.length - 1]) ||
3921
- ts.isThrowStatement(stmt.thenStatement.statements[stmt.thenStatement.statements.length - 1])));
3922
- return exits ? local : null;
4088
+ return [];
4089
+ let tail = stmt.thenStatement;
4090
+ while (ts.isBlock(tail)) {
4091
+ const last = tail.statements[tail.statements.length - 1];
4092
+ if (!last)
4093
+ return [];
4094
+ tail = last;
4095
+ }
4096
+ const exits = ts.isReturnStatement(tail) || ts.isThrowStatement(tail) ||
4097
+ ts.isContinueStatement(tail) || ts.isBreakStatement(tail);
4098
+ return exits ? runtimeOptionalGuardIds(lowerer, stmt.expression, false) : [];
3923
4099
  }
3924
4100
  /** JS-exact switch (see docs/ir.md): one shared lexical scope for all case
3925
4101
  * bodies, lazy source-order test evaluation, fall-through. tsc has already
3926
4102
  * checked case-test comparability (TS2678) — the kind check below is the
3927
4103
  * backstop for cases tsc lets through (e.g. `unknown as` casts). */
3928
4104
  export function lowerSwitch(lowerer, stmt) {
3929
- // Labels consume HERE, before any nested statement can see them; the
3930
- // union desugar drops them (its if/else chain has no switch-end label
3931
- // point — labeled jumps naming this switch fence at the jump).
4105
+ // Consume labels before a nested statement can claim them. All switch
4106
+ // forms keep their own break target, including union comparisons.
3932
4107
  const labels = lowerer.takeLabels();
3933
4108
  const disc = lowerer.lowerExpr(stmt.expression);
3934
- const dk = disc.type.kind;
3935
- if (dk === "dyn")
3936
- return lowerDynSwitch(lowerer, stmt, disc);
3937
- if (dk === "union")
3938
- return lowerUnionSwitch(lowerer, stmt, disc);
3939
- if (dk !== "f64" && dk !== "string" && dk !== "bool") {
3940
- lowerer.unsupported("SC1090", stmt.expression, "switch on non-primitive values");
3941
- }
3942
- // The whole case-body sequence is ONE lexical scope in JS: a bare `let`
3943
- // in one case is visible in later cases.
3944
- lowerer.scopes.push(new Map());
3945
- try {
3946
- const cases = [];
3947
- for (const clause of stmt.caseBlock.clauses) {
3948
- let test = null;
3949
- if (ts.isCaseClause(clause)) {
3950
- test = lowerer.lowerExpr(clause.expression);
3951
- if (test.type.kind !== dk) {
3952
- lowerer.unsupported("SC1090", clause.expression, "switch case tests of a different type than the discriminant");
4109
+ return withRuntimeOptionalNarrowed(lowerer, runtimeOptionalGuardIds(lowerer, stmt.expression, null), () => {
4110
+ const dk = disc.type.kind;
4111
+ if (dk === "dyn")
4112
+ return lowerDynSwitch(lowerer, stmt, disc, labels);
4113
+ if (dk === "union")
4114
+ return lowerUnionSwitch(lowerer, stmt, disc, labels);
4115
+ if (dk !== "f64" && dk !== "string" && dk !== "bool") {
4116
+ lowerer.unsupported("SC1090", stmt.expression, "switch on non-primitive values");
4117
+ }
4118
+ // The whole case-body sequence is ONE lexical scope in JS: a bare `let`
4119
+ // in one case is visible in later cases.
4120
+ lowerer.scopes.push(new Map());
4121
+ try {
4122
+ const cases = [];
4123
+ for (const clause of stmt.caseBlock.clauses) {
4124
+ let test = null;
4125
+ if (ts.isCaseClause(clause)) {
4126
+ test = lowerer.lowerExpr(clause.expression);
4127
+ if (test.type.kind !== dk) {
4128
+ lowerer.unsupported("SC1090", clause.expression, "switch case tests of a different type than the discriminant");
4129
+ }
3953
4130
  }
4131
+ cases.push({ test, body: lowerer.inCtl("switch", () => withRuntimeOptionalScope(lowerer, () => lowerer.lowerStmts(clause.statements)), labels) });
3954
4132
  }
3955
- cases.push({ test, body: lowerer.inCtl("switch", () => lowerer.lowerStmts(clause.statements), labels) });
4133
+ return { kind: "switch", disc, cases, ...(labels && { labels }), loc: locOf(stmt) };
3956
4134
  }
3957
- return { kind: "switch", disc, cases, ...(labels && { labels }), loc: locOf(stmt) };
3958
- }
3959
- finally {
3960
- lowerer.scopes.pop();
3961
- }
4135
+ finally {
4136
+ lowerer.scopes.pop();
4137
+ }
4138
+ });
3962
4139
  }
3963
- /** Switch on a UNION-typed discriminant (`switch (m.type)` over
3964
- * `string | undefined`): desugared to an if/else-if chain of per-union
3965
- * strict-equality tests (unionEq — the case value wraps into the union,
3966
- * exactly `disc === test`), because the backend switch compares plain
3967
- * primitives only. The desugar is JS-exact for the shape it accepts and
3968
- * fences everything it cannot reproduce:
3969
- * - the discriminant evaluates exactly once; effectful values stabilize
3970
- * in a hidden local that every generated equality test reuses;
3971
- * - tests evaluate lazily in source order (the chain's short-circuit IS
3972
- * the switch's test order — grouped empty cases `case a: case b:` OR
3973
- * their tests, still in order);
3974
- * - each non-final clause must EXIT (a trailing unconditional break —
3975
- * dropped, it's the chain's own exit — or a return/throw/continue):
3976
- * real fall-through between bodies has no if/else shape;
3977
- * - any OTHER unlabeled break binding to this switch (a conditional
3978
- * early break) is fenced — desugared, it would bind to an enclosing
3979
- * loop instead;
3980
- * - `default` may sit anywhere in source (JS tests every case first;
3981
- * the chain's final else reproduces that as long as its body exits or
3982
- * is last).
3983
- * Case bodies share ONE lexical scope, exactly like the real switch. */
3984
- function lowerUnionSwitch(lowerer, stmt, disc) {
4140
+ /** Compare a union discriminant through a boolean switch. The native switch
4141
+ * already implements lazy case tests, shared scope, fallthrough and jumps;
4142
+ * keeping that control-flow node avoids rebinding an early break to a loop. */
4143
+ function lowerUnionSwitch(lowerer, stmt, disc, labels) {
3985
4144
  if (disc.type.kind !== "union")
3986
4145
  throw new InternalCompilerError("lowerer bug: non-union disc");
3987
4146
  const unionType = disc.type;
3988
4147
  if (!lowerer.eqComparableUnion(unionType.unionId)) {
3989
4148
  lowerer.unsupported("SC1090", stmt.expression, "switch on a union whose arms do not have static equality");
3990
4149
  }
3991
- return lowerBranchSwitch(lowerer, stmt, disc, (stableDisc, test, expression) => {
4150
+ return lowerBranchSwitch(lowerer, stmt, disc, labels, (stableDisc, test, expression) => {
3992
4151
  const unitTest = test.kind === "unitLit"
3993
4152
  ? lowerer.lowerUnitComparison(stableDisc, test, false, locOf(expression))
3994
4153
  : null;
@@ -4007,8 +4166,8 @@ function lowerUnionSwitch(lowerer, stmt, disc) {
4007
4166
  /** A checked-dynamic switch whose tests have native strict-equality
4008
4167
  * answers. Scalar tests use dynScalarEq; null/undefined use dyn kind tests.
4009
4168
  * Other case values retain the existing unknown-switch fence. */
4010
- function lowerDynSwitch(lowerer, stmt, disc) {
4011
- return lowerBranchSwitch(lowerer, stmt, disc, (stableDisc, test, expression) => {
4169
+ function lowerDynSwitch(lowerer, stmt, disc, labels) {
4170
+ return lowerBranchSwitch(lowerer, stmt, disc, labels, (stableDisc, test, expression) => {
4012
4171
  if (test.kind === "unitLit") {
4013
4172
  return { kind: "dynTest", test: test.unit, value: stableDisc, type: BOOL, loc: locOf(expression) };
4014
4173
  }
@@ -4019,121 +4178,47 @@ function lowerDynSwitch(lowerer, stmt, disc) {
4019
4178
  return { kind: "dynScalarEq", left: stableDisc, right: test, type: BOOL, loc: locOf(expression) };
4020
4179
  });
4021
4180
  }
4022
- function lowerBranchSwitch(lowerer, stmt, disc, compare) {
4181
+ function lowerBranchSwitch(lowerer, stmt, disc, labels, compare) {
4023
4182
  const loc = locOf(stmt);
4024
- const prefix = [];
4025
- let stableDisc = disc;
4026
- if (!isSafeToRepeat(disc)) {
4027
- const temp = lowerer.declareHiddenLocal("%switch", disc.type);
4028
- prefix.push({ kind: "varDecl", localId: temp.id, init: disc, loc });
4029
- stableDisc = { kind: "varRef", localId: temp.id, type: disc.type, loc };
4030
- }
4031
- const clauses = stmt.caseBlock.clauses;
4032
- // An unlabeled break at a clause's END exits the switch — the chain's
4033
- // own exit; anywhere else (conditional early breaks) the desugar would
4034
- // rebind it to an enclosing loop. Walk each clause's statements without
4035
- // descending into nested breakable constructs or functions (their
4036
- // breaks are their own).
4037
- const findStrayBreak = (node) => {
4038
- if (ts.isBreakStatement(node))
4039
- return node;
4040
- if (ts.isForStatement(node) || ts.isForOfStatement(node) || ts.isForInStatement(node) ||
4041
- ts.isWhileStatement(node) || ts.isDoStatement(node) || ts.isSwitchStatement(node) ||
4042
- ts.isFunctionLike(node)) {
4043
- return null;
4044
- }
4045
- return ts.forEachChild(node, findStrayBreak) ?? null;
4046
- };
4047
- for (const clause of clauses) {
4048
- const last = clause.statements[clause.statements.length - 1];
4049
- for (const s of clause.statements) {
4050
- const stray = s === last && ts.isBreakStatement(s) && !s.label ? null : findStrayBreak(s);
4051
- if (stray) {
4052
- lowerer.unsupported("SC1090", stray, "early 'break' inside a union-typed switch (only a trailing break exits the desugared chain — restructure with if/else)");
4053
- }
4054
- }
4055
- }
4056
- const statementExits = (last) => {
4057
- if (!last)
4058
- return false;
4059
- if ((ts.isBreakStatement(last) && !last.label) ||
4060
- ts.isReturnStatement(last) ||
4061
- ts.isThrowStatement(last) ||
4062
- ts.isContinueStatement(last))
4063
- return true;
4064
- return ts.isBlock(last) && statementExits(last.statements[last.statements.length - 1]);
4065
- };
4066
- const exits = (clause) => {
4067
- const last = clause.statements[clause.statements.length - 1];
4068
- return statementExits(last);
4069
- };
4070
- // The whole case-body sequence is ONE lexical scope, like the real
4071
- // switch lowering.
4183
+ // Even a plain variable must be snapshotted: a case expression can write
4184
+ // it before the next comparison, without changing the switch value.
4185
+ const temp = lowerer.declareHiddenLocal("%switch", disc.type);
4186
+ const stableDisc = varRef(temp.id, disc.type, loc);
4187
+ // Calls/assignments in a case test may mutate a captured discriminant
4188
+ // binding. The checker still narrows that binding as if it were the
4189
+ // snapshot. Keep the original tagged value in those case bodies.
4190
+ const effectful = stmt.caseBlock.clauses.some((clause) => ts.isCaseClause(clause) &&
4191
+ !ts.isStringLiteral(clause.expression) && !ts.isNumericLiteral(clause.expression) &&
4192
+ !ts.isIdentifier(clause.expression) && clause.expression.kind !== ts.SyntaxKind.NullKeyword &&
4193
+ clause.expression.kind !== ts.SyntaxKind.TrueKeyword && clause.expression.kind !== ts.SyntaxKind.FalseKeyword);
4194
+ let binding = stmt.expression;
4195
+ while (ts.isParenthesizedExpression(binding))
4196
+ binding = binding.expression;
4197
+ const symbol = effectful && ts.isIdentifier(binding) ? lowerer.resolveValueSymbol(binding) : undefined;
4198
+ const alreadyUnstable = symbol != null && lowerer.unstableSwitchBindings.has(symbol);
4199
+ if (symbol)
4200
+ lowerer.unstableSwitchBindings.add(symbol);
4072
4201
  lowerer.scopes.push(new Map());
4073
4202
  try {
4074
- // Group clauses: consecutive test-only cases (empty statements) share
4075
- // the next body, exactly JS's grouped-case idiom.
4076
- const groups = [];
4077
- let pendingTests = [];
4078
- for (let i = 0; i < clauses.length; i++) {
4079
- const clause = clauses[i];
4080
- if (ts.isCaseClause(clause)) {
4081
- const test = lowerer.lowerExpr(clause.expression);
4082
- // Case tests must be side-effect-free (literals or plain reads):
4083
- // the chain evaluates exactly the tests JS would EXCEPT those of
4084
- // a default-sharing group (dropped — the shared body is the
4085
- // final else, so matching them changes nothing when pure).
4086
- if (test.kind !== "strLit" && test.kind !== "numLit" &&
4087
- test.kind !== "boolLit" && test.kind !== "unitLit" &&
4088
- !isSafeToRepeat(test)) {
4089
- lowerer.unsupported("SC1090", clause.expression, "effectful case tests in a union-typed switch (bind the test value to a const first)");
4090
- }
4091
- // A unit-literal test takes the unit-comparison lowering: a tag
4092
- // test when the arm exists, the constant FALSE when the union
4093
- // lacks it (`case null:` on a `number | undefined` — legal TS,
4094
- // never matches; coercing the literal into the union would hit
4095
- // the stranded-arm trap and throw where JS just skips the case).
4096
- pendingTests.push(compare(stableDisc, test, clause.expression));
4097
- }
4098
- const isDefault = ts.isDefaultClause(clause);
4099
- if (clause.statements.length === 0 && !isDefault && i < clauses.length - 1) {
4100
- continue; // grouped with the next clause
4101
- }
4102
- if (!exits(clause) && i < clauses.length - 1 && (clause.statements.length > 0 || isDefault)) {
4103
- // A non-final body that doesn't exit falls into the NEXT body in
4104
- // JS — no if/else shape reproduces that (an EMPTY non-final
4105
- // default falls through too; empty non-final cases just group).
4106
- lowerer.unsupported("SC1090", clause, "fall-through between case bodies in a union-typed switch (end each case with break/return/throw/continue)");
4107
- }
4108
- const last = clause.statements[clause.statements.length - 1];
4109
- const stmts = last && ts.isBreakStatement(last)
4110
- ? clause.statements.slice(0, -1)
4111
- : clause.statements.slice();
4112
- const body = lowerer.lowerStmts(stmts);
4113
- groups.push({ tests: pendingTests, body, isDefault });
4114
- pendingTests = [];
4115
- }
4116
- // A default clause anywhere lands in the chain's final else; JS
4117
- // reaches it only after every case test fails, which the chain
4118
- // reproduces because default bodies that don't exit were fenced
4119
- // above (unless last in source, where falling out is falling out).
4120
- const defaultBody = groups.find((g) => g.isDefault)?.body ?? null;
4121
- const caseGroups = groups.filter((g) => !g.isDefault);
4122
- let chain = defaultBody ?? [];
4123
- for (let i = caseGroups.length - 1; i >= 0; i--) {
4124
- const g = caseGroups[i];
4125
- let cond = g.tests[0];
4126
- if (!cond)
4127
- continue; // a default-adjacent group with no tests (defensive)
4128
- for (const t of g.tests.slice(1)) {
4129
- cond = { kind: "logical", op: "||", left: cond, right: t, type: BOOL, loc };
4130
- }
4131
- chain = [{ kind: "if", cond, then: g.body, else_: chain.length > 0 ? chain : null, loc }];
4132
- }
4133
- return { kind: "block", body: [...prefix, ...chain], loc };
4203
+ const cases = stmt.caseBlock.clauses.map((clause) => ({
4204
+ test: ts.isCaseClause(clause)
4205
+ ? compare(stableDisc, lowerer.lowerExpr(clause.expression), clause.expression)
4206
+ : null,
4207
+ body: lowerer.inCtl("switch", () => withRuntimeOptionalScope(lowerer, () => lowerer.lowerStmts(clause.statements)), labels),
4208
+ }));
4209
+ return {
4210
+ kind: "block",
4211
+ body: [
4212
+ { kind: "varDecl", localId: temp.id, init: disc, loc },
4213
+ { kind: "switch", disc: { kind: "boolLit", value: true, type: BOOL, loc }, cases, ...(labels && { labels }), loc },
4214
+ ],
4215
+ loc,
4216
+ };
4134
4217
  }
4135
4218
  finally {
4136
4219
  lowerer.scopes.pop();
4220
+ if (symbol && !alreadyUnstable)
4221
+ lowerer.unstableSwitchBindings.delete(symbol);
4137
4222
  }
4138
4223
  }
4139
4224
  /** try/catch/finally:
@@ -4187,6 +4272,28 @@ export function lowerTry(lowerer, stmt) {
4187
4272
  loc: locOf(stmt),
4188
4273
  };
4189
4274
  }
4275
+ function hasUseStrictDirective(statements) {
4276
+ for (const statement of statements) {
4277
+ if (!ts.isExpressionStatement(statement) || !ts.isStringLiteral(statement.expression))
4278
+ return false;
4279
+ if (statement.expression.text === "use strict")
4280
+ return true;
4281
+ }
4282
+ return false;
4283
+ }
4284
+ function isStrictDelete(node) {
4285
+ for (let parent = node.parent; parent; parent = parent.parent) {
4286
+ if (ts.isClassDeclaration(parent) || ts.isClassExpression(parent))
4287
+ return true;
4288
+ if (ts.isFunctionLike(parent) && parent.body && ts.isBlock(parent.body) && hasUseStrictDirective(parent.body.statements))
4289
+ return true;
4290
+ if (ts.isSourceFile(parent)) {
4291
+ return hasUseStrictDirective(parent.statements) ||
4292
+ (!isCjsJsFile(parent) && (isNodeEsmFile(parent) || ts.isExternalModule(parent)));
4293
+ }
4294
+ }
4295
+ return false;
4296
+ }
4190
4297
  /** Statement-position `delete`: process.env keys → process.envUnset
4191
4298
  * (unsetenv), pure `Record<string, T>` keys → recordKeyDelete (the
4192
4299
  * overflow Map delete), declared OPTIONAL fields → the undefined-arm
@@ -4202,12 +4309,24 @@ function lowerDeleteStatement(lowerer, expr) {
4202
4309
  lowerer.unsupported("SC1090", expr, "'delete' of non-property expressions");
4203
4310
  }
4204
4311
  fenceNodeModuleMutation(lowerer, target, "delete");
4312
+ if (ts.isPropertyAccessExpression(target) && target.name.text === "cause") {
4313
+ const field = lowerer.fieldTarget(target);
4314
+ if (field?.container === "errorCause") {
4315
+ return { kind: "exprStmt", expr: { kind: "libCall", fn: "error.deleteCause", args: [field.obj], type: VOID, loc }, loc };
4316
+ }
4317
+ }
4318
+ const globalKey = ts.isElementAccessExpression(target) ? globalSymbolKey(lowerer, target.expression, target.argumentExpression) : null;
4319
+ if (globalKey)
4320
+ return { kind: "exprStmt", expr: { kind: "libCall", fn: "dyn.globalSymbolDelete", args: [globalKey], type: VOID, loc }, loc };
4205
4321
  const lowerKey = () => {
4206
4322
  if (ts.isPropertyAccessExpression(target)) {
4207
4323
  return { kind: "strLit", value: target.name.text, type: STRING, loc: locOf(target.name) };
4208
4324
  }
4209
4325
  const keyNode = target.argumentExpression;
4210
- let key = lowerer.lowerExpr(keyNode);
4326
+ let key = lowerer.isProcessEnv(target.expression) ? lowerEnvironmentKey(lowerer, keyNode) : lowerer.lowerExpr(keyNode);
4327
+ if (key.type.kind === "dyn") {
4328
+ key = { kind: "libCall", fn: "dyn.toStringCoerce", args: [key], type: STRING, loc: key.loc };
4329
+ }
4211
4330
  if (lowerer.runtimeOptionalWidening(key.type, STRING) !== null) {
4212
4331
  key = lowerer.ensureString(key, keyNode);
4213
4332
  }
@@ -4223,7 +4342,18 @@ function lowerDeleteStatement(lowerer, expr) {
4223
4342
  loc,
4224
4343
  };
4225
4344
  }
4226
- const obj = lowerer.lowerExpr(target.expression);
4345
+ let obj = lowerer.lowerExpr(target.expression);
4346
+ if (isJsSourceFile(expr.getSourceFile()) && obj.type.kind === "func" && lowerer.dynConvertible(obj.type)) {
4347
+ obj = lowerer.coerceToExpected(obj, DYN);
4348
+ }
4349
+ if (obj.type.kind === "dyn") {
4350
+ const strict = { kind: "boolLit", value: isStrictDelete(expr), type: BOOL, loc };
4351
+ if (ts.isElementAccessExpression(target)) {
4352
+ const key = lowerer.lowerExprExpecting(target.argumentExpression, DYN);
4353
+ return { kind: "exprStmt", expr: { kind: "libCall", fn: "dyn.keyDeleteComputed", args: [obj, key, strict], type: VOID, loc }, loc };
4354
+ }
4355
+ return { kind: "exprStmt", expr: { kind: "libCall", fn: "dyn.keyDelete", args: [obj, lowerKey(), strict], type: VOID, loc }, loc };
4356
+ }
4227
4357
  if (obj.type.kind === "record") {
4228
4358
  const shape = lowerer.shapes.get(obj.type.shapeId);
4229
4359
  if (shape?.indexValue && shape.fields.length === 0 && !shape.tuple) {
@@ -4597,7 +4727,7 @@ export function lowerExprStatement(lowerer, expr) {
4597
4727
  }
4598
4728
  }
4599
4729
  // `yield* inner();` — statement-position delegation desugars to the
4600
- // forwarding loop (lower-generators); value positions keep the fence.
4730
+ // forwarding loop (lower-generators), dropping the completed value.
4601
4731
  {
4602
4732
  const delegated = lowerYieldStarStatement(lowerer, expr);
4603
4733
  if (delegated)
@@ -4653,7 +4783,7 @@ export function lowerExprStatement(lowerer, expr) {
4653
4783
  // site (message with the one-entry require stack), CATCHABLE — the
4654
4784
  // optional-dependency try/require pattern. The compiled statement
4655
4785
  // IS that throw, wherever it sits.
4656
- if (isCjsJsFile(sf)) {
4786
+ if (isCjsJsFile(sf, lowerer.program)) {
4657
4787
  if (!isRelativeSpecifier(spec) &&
4658
4788
  canonicalBuiltinModule(spec) === null) {
4659
4789
  const refusal = probeNodeRequireRefusal(sf.fileName, spec);
@@ -4673,7 +4803,7 @@ export function lowerExprStatement(lowerer, expr) {
4673
4803
  }
4674
4804
  }
4675
4805
  }
4676
- if (isCjsJsFile(sf)) {
4806
+ if (isCjsJsFile(sf, lowerer.program)) {
4677
4807
  const init = lowerer.requireInitStmt(spec, expr);
4678
4808
  if (init)
4679
4809
  return init;
@@ -4728,6 +4858,9 @@ export function lowerExprStatement(lowerer, expr) {
4728
4858
  };
4729
4859
  }
4730
4860
  if (opKind === ts.SyntaxKind.EqualsToken) {
4861
+ const callableWrite = lowerNativeFunctionAssignment(lowerer, expr);
4862
+ if (callableWrite)
4863
+ return { kind: "exprStmt", expr: callableWrite, loc: locOf(expr) };
4731
4864
  // Expando function members (`foo.bar = 12`, `foo[SYM] = v` on a
4732
4865
  // module-level function/callable const): the member's module
4733
4866
  // global (lower-expando.ts) — claimed by symbol identity before
@@ -4845,13 +4978,20 @@ export function lowerExprStatement(lowerer, expr) {
4845
4978
  // SUBCLASS name (`D.x = v` creates an OWN property on D in JS —
4846
4979
  // different storage) and through class VALUES (the same dynamic
4847
4980
  // story) are named fences, never a silently-wrong global write.
4848
- if (!expr.left.questionDotToken && ts.isIdentifier(expr.left.expression)) {
4981
+ if (!expr.left.questionDotToken && (ts.isIdentifier(expr.left.expression) || expr.left.expression.kind === ts.SyntaxKind.ThisKeyword)) {
4849
4982
  // The receiver must BE the class exactly (its name, or a
4850
4983
  // const binding holding a class expression) — a general class
4851
4984
  // VALUE could hold a subclass, where JS creates an own
4852
4985
  // property instead of writing this storage.
4853
4986
  const classInfo = lowerer.exactClassOfReceiver(expr.left.expression);
4854
4987
  if (classInfo) {
4988
+ const data = classStaticDataFor(lowerer, classInfo, expr.left.name.text, locOf(expr.left));
4989
+ if (data) {
4990
+ const loc = locOf(expr);
4991
+ const key = { kind: "strLit", value: expr.left.name.text, type: STRING, loc };
4992
+ const value = lowerer.lowerExprExpecting(expr.right, DYN);
4993
+ return { kind: "exprStmt", expr: { kind: "libCall", fn: "dyn.keySet", args: [data, key, value], type: VOID, loc }, loc };
4994
+ }
4855
4995
  const found = lowerer.findStaticOn(classInfo, expr.left.name.text);
4856
4996
  if (found?.field !== undefined) {
4857
4997
  if (found.declarer !== classInfo) {
@@ -4952,17 +5092,38 @@ export function lowerExprStatement(lowerer, expr) {
4952
5092
  if (viaStream)
4953
5093
  return viaStream;
4954
5094
  }
5095
+ const unionWrite = lowerUnionFieldWrite(lowerer, expr.left, expr.right);
5096
+ if (unionWrite)
5097
+ return unionWrite;
4955
5098
  const target = lowerer.fieldTarget(expr.left);
4956
5099
  if (target) {
4957
5100
  const value = lowerer.lowerExprExpecting(expr.right, target.fieldType);
4958
5101
  return lowerer.fieldSetStmt(target, value, locOf(expr), expr.left);
4959
5102
  }
5103
+ const callback = lowerClassCallbackAssign(lowerer, expr);
5104
+ if (callback)
5105
+ return callback;
4960
5106
  // A write to an ABSTRACT property through an abstract-typed
4961
5107
  // receiver: the read fence's write twin (the declaration is
4962
5108
  // erased at runtime — no shared slot exists to write).
4963
5109
  if (abstractPropertyDeclOf(lowerer, expr.left)) {
4964
5110
  lowerer.unsupported("SC1090", expr.left, `writing the abstract property '${expr.left.name.text}' through a '${lowerer.checker.typeToString(lowerer.typeOf(expr.left.expression))}'-typed receiver (abstract property declarations are erased at runtime, so no shared slot exists — type the receiver as the concrete class, or declare an abstract accessor pair instead)`);
4965
5111
  }
5112
+ if (!expr.left.questionDotToken) {
5113
+ const recv = tryLowerExpression(lowerer, expr.left.expression);
5114
+ if (recv && isDynTypedRefType(recv.type)) {
5115
+ const info = lowerer.classes.get(recv.type.className);
5116
+ if (info && !info.def.runtime && !info.builtinError && !info.builtinEmitter && !info.builtinStream &&
5117
+ !isCompiledPrototypeMember(lowerer, info, expr.left.name.text)) {
5118
+ const loc = locOf(expr);
5119
+ return { kind: "exprStmt", expr: {
5120
+ kind: "libCall", fn: "dyn.keySet", args: [lowerer.coerceToExpected(recv, DYN),
5121
+ { kind: "strLit", value: expr.left.name.text, type: STRING, loc }, lowerer.lowerExprExpecting(expr.right, DYN)],
5122
+ type: VOID, loc,
5123
+ }, loc };
5124
+ }
5125
+ }
5126
+ }
4966
5127
  // Dot WRITE to an undeclared key of an index-signature shape:
4967
5128
  // the same deliberate fence as the dotted read, with the same
4968
5129
  // fix in the message (brackets are the index-signature form).
@@ -5005,34 +5166,9 @@ export function lowerExprStatement(lowerer, expr) {
5005
5166
  lowerer.runtimeOptionalLocals.add(runtimeOptionalRoot);
5006
5167
  return { kind: "assign", localId: target.id, value, loc: locOf(expr) };
5007
5168
  }
5008
- if (opKind === ts.SyntaxKind.QuestionQuestionEqualsToken) {
5009
- // `x ??= e` on a VARIABLE, statement position: desugar to
5010
- // `x = x ?? e` (x read once, e lazy). For a plain variable JS's
5011
- // assign-only-when-nullish is unobservable — the value written back
5012
- // on the non-nullish path is the same box. Property targets keep a
5013
- // distinct fence: accessors would make the always-write observable.
5014
- if (!ts.isIdentifier(expr.left)) {
5015
- lowerer.unsupported("SC1090", expr.left, "'??=' on non-variable targets (write it out: if (o.f === undefined) o.f = v)");
5016
- }
5017
- const target = lowerer.resolveWritable(expr.left);
5018
- if (!target)
5019
- lowerer.rejectUnresolved(expr.left, `assignment to '${expr.left.text}' (not a writable local or module global)`);
5020
- const loc = locOf(expr);
5021
- if (target.type.kind !== "union") {
5022
- // The checker says never nullish: JS neither evaluates e nor
5023
- // assigns — the statement is a no-op (lowerNullishCoalesce's
5024
- // trust-the-checker fold, statement form).
5025
- return { kind: "block", body: [], loc };
5026
- }
5027
- const def = lowerer.unions.get(target.type.unionId);
5028
- if (!def)
5029
- lowerer.badType(expr.left, lowerer.typeOf(expr.left));
5030
- if (!def.arms.some(isUnitType))
5031
- return { kind: "block", body: [], loc };
5032
- const read = { kind: "varRef", localId: target.id, type: target.type, loc: locOf(expr.left) };
5033
- const right = lowerer.lowerExprExpecting(expr.right, target.type);
5034
- const value = { kind: "nullish", left: read, right, type: target.type, loc };
5035
- return { kind: "assign", localId: target.id, value, loc };
5169
+ if (opKind === ts.SyntaxKind.QuestionQuestionEqualsToken ||
5170
+ opKind === ts.SyntaxKind.AmpersandAmpersandEqualsToken || opKind === ts.SyntaxKind.BarBarEqualsToken) {
5171
+ return { kind: "exprStmt", expr: lowerShortCircuitAssignment(lowerer, expr), loc: locOf(expr) };
5036
5172
  }
5037
5173
  const compound = COMPOUND_ASSIGN_OPS[opKind];
5038
5174
  if (compound !== undefined) {
@@ -5071,8 +5207,7 @@ export function lowerExprStatement(lowerer, expr) {
5071
5207
  }
5072
5208
  if (opKind >= ts.SyntaxKind.FirstCompoundAssignment &&
5073
5209
  opKind <= ts.SyntaxKind.LastCompoundAssignment) {
5074
- // Everything else is covered above; what remains is &&= and ||=.
5075
- lowerer.unsupported("SC1090", expr, "logical assignment (&&=, ||=) — write the if out");
5210
+ lowerer.unsupported("SC1090", expr, "this compound assignment operator");
5076
5211
  }
5077
5212
  }
5078
5213
  if ((ts.isPrefixUnaryExpression(expr) || ts.isPostfixUnaryExpression(expr)) &&
@@ -5086,6 +5221,9 @@ export function lowerExprStatement(lowerer, expr) {
5086
5221
  // increment (the member's global IS the variable); expando
5087
5222
  // function members (`foo.count++`) are module globals too.
5088
5223
  if (ts.isPropertyAccessExpression(expr.operand) && !expr.operand.questionDotToken) {
5224
+ const staticTarget = staticFieldWriteTarget(lowerer, expr.operand);
5225
+ if (staticTarget)
5226
+ return lowerIncDecToTarget(lowerer, expr, staticTarget);
5089
5227
  const exT = expandoWritableTarget(lowerer, expr.operand);
5090
5228
  if (exT)
5091
5229
  return lowerIncDecToTarget(lowerer, expr, exT);
@@ -5198,44 +5336,12 @@ function lowerIncDecToTarget(lowerer, expr, target) {
5198
5336
  * identifier form and the namespace-qualified spelling (`N.x += v`),
5199
5337
  * whose target is the member's module global. */
5200
5338
  function lowerCompoundToTarget(lowerer, expr, compound, target) {
5201
- const loc = locOf(expr);
5202
- const read = { kind: "varRef", localId: target.id, type: target.type, loc: locOf(expr.left) };
5203
- const rhs = lowerer.lowerExpr(expr.right);
5204
- const numericRhs = lowerOptionalNumber(lowerer, rhs, loc);
5205
- let value;
5206
- if (target.type.kind === "jsval" || rhs.type.kind === "jsval") {
5207
- const JS_COMPOUND = { "+": "add", "-": "sub", "*": "mul", "/": "div", "%": "mod", "**": "pow" };
5208
- const jop = JS_COMPOUND[compound];
5209
- if (jop === undefined)
5210
- lowerer.unsupported("SC1043", expr);
5211
- const wrapped = {
5212
- kind: "jsOp", op: jop,
5213
- args: [lowerer.jsvalIn(read, expr.left), lowerer.jsvalIn(rhs, expr.right)],
5214
- type: JSVAL, loc,
5215
- };
5216
- value = lowerer.coerceInto(expr, wrapped, target.type);
5217
- }
5218
- else if (compound === "+" && target.type.kind === "string") {
5219
- value = { kind: "strConcat", left: read, right: lowerer.ensureString(rhs, expr.right), type: STRING, loc };
5220
- }
5221
- else if (target.type.kind === "f64" && numericRhs.type.kind === "f64") {
5222
- value = { kind: "bin", op: compound, left: read, right: numericRhs, type: F64, loc };
5223
- }
5224
- else if ((target.type.kind === "dyn" || rhs.type.kind === "dyn") &&
5225
- (target.type.kind === "dyn" || target.type.kind === "f64") &&
5226
- (rhs.type.kind === "dyn" || rhs.type.kind === "f64") &&
5227
- isJsSourceFile(expr.getSourceFile())) {
5228
- // JS any-origin operands: check to number and compute natively
5229
- // (the binary-operator stance) — the dyn target takes the result
5230
- // back through the usual dyn conversion.
5231
- const checkNum = (e) => e.type.kind === "dyn" ? { kind: "dynCheck", value: e, type: F64, loc: e.loc } : e;
5232
- const computed = { kind: "bin", op: compound, left: checkNum(read), right: checkNum(rhs), type: F64, loc };
5233
- value = target.type.kind === "dyn" ? { kind: "dynFrom", value: computed, type: DYN, loc } : computed;
5234
- }
5235
- else {
5236
- lowerer.unsupported("SC1043", expr);
5237
- }
5238
- return { kind: "assign", localId: target.id, value, loc };
5339
+ return {
5340
+ kind: "assign",
5341
+ localId: target.id,
5342
+ value: lowerCompoundValueToTarget(lowerer, expr, compound, target),
5343
+ loc: locOf(expr),
5344
+ };
5239
5345
  }
5240
5346
  /** One destructuring-assignment pattern the island can run: empty object/
5241
5347
  * array patterns and flat identifier targets — shorthand `{ x }`,
@@ -5428,14 +5534,23 @@ export function lowerDestructuringAssign(lowerer, target, init, blame, loc) {
5428
5534
  }
5429
5535
  /** V8's spelling of a destructuring RHS in its TypeError message
5430
5536
  * ("Cannot destructure 'a' as it is undefined.") — plain identifiers
5431
- * spell their name (parens unwrap); everything else is V8's
5432
- * CallPrinter reconstruction, which is not reproduced — null keeps a
5433
- * fence at the caller. */
5537
+ * spell their name (parens unwrap), and calls append an ellipsis to a
5538
+ * supported callee spelling. Other CallPrinter forms keep a fence. */
5434
5539
  function destrSpellingOf(rhs) {
5435
5540
  let e = rhs;
5436
5541
  while (ts.isParenthesizedExpression(e))
5437
5542
  e = e.expression;
5438
- return ts.isIdentifier(e) ? e.text : null;
5543
+ if (ts.isIdentifier(e))
5544
+ return e.text;
5545
+ if (ts.isPropertyAccessExpression(e) && !e.questionDotToken) {
5546
+ const base = destrSpellingOf(e.expression);
5547
+ return base === null ? null : `${base}.${e.name.text}`;
5548
+ }
5549
+ if (ts.isCallExpression(e) && !e.questionDotToken) {
5550
+ const callee = destrSpellingOf(e.expression);
5551
+ return callee === null ? null : `${callee}(...)`;
5552
+ }
5553
+ return null;
5439
5554
  }
5440
5555
  /** Destructuring ASSIGNMENT (existing bindings — the declaration twin is
5441
5556
  * lowerDestructuringDecl): the RHS evaluates ONCE into a hidden temp,
@@ -5537,7 +5652,7 @@ function destructuringAssignInto(lowerer, target, init, rhs, blame, loc) {
5537
5652
  if (!checkedByInner) {
5538
5653
  const spelling = rhs === null ? null : destrSpellingOf(rhs);
5539
5654
  if (spelling === null) {
5540
- lowerer.unsupported("SC1031", blame, "destructuring assignment from a checked-dynamic source that is not a plain variable (V8's TypeError spells the source expression — assign it to a variable first)");
5655
+ lowerer.unsupported("SC1031", blame, "destructuring assignment from a checked-dynamic source whose expression spelling is unsupported (use a variable, ordinary property chain, or ordinary call)");
5541
5656
  }
5542
5657
  let firstProp;
5543
5658
  const p0 = target.properties[0];
@@ -6261,10 +6376,11 @@ export function lowerForOf(lowerer, stmt) {
6261
6376
  // desugars drop them — a labeled jump naming those loops fences at the
6262
6377
  // jump site (no label point exists in their desugared shape).
6263
6378
  const labels = lowerer.takeLabels();
6264
- // `for await` is ASYNC ITERATION, not the shipped async/await. Typed
6265
- // async generators use the generic request protocol; process.stdin
6266
- // and readable streams retain their dedicated next-chunk paths.
6267
- if (stmt.awaitModifier) {
6379
+ // A synchronous array iterator is also valid in `for await`. Its values
6380
+ // take the async-from-sync path below; other async sources retain their
6381
+ // dedicated request protocols.
6382
+ const awaitArray = !!stmt.awaitModifier && lowerer.mapTypeOf(lowerer.typeOf(stmt.expression))?.kind === "array";
6383
+ if (stmt.awaitModifier && !awaitArray) {
6268
6384
  {
6269
6385
  const genT = lowerer.mapTypeOf(lowerer.typeOf(stmt.expression));
6270
6386
  if (genT?.kind === "generator" && genT.async) {
@@ -6283,6 +6399,9 @@ export function lowerForOf(lowerer, stmt) {
6283
6399
  return builtin;
6284
6400
  lowerer.unsupported("SC1070", stmt, "'for await' over this value (supported: typed async generators, represented class async iterators, process.stdin, and Node/Web readable streams)");
6285
6401
  }
6402
+ if (awaitArray && !lowerer.ctx.isAsync) {
6403
+ lowerer.unsupported("SC1090", stmt, "top-level 'for await' (await outside async functions)");
6404
+ }
6286
6405
  lowerer.fenceStaticHeadersIteration(stmt.expression);
6287
6406
  // A stored numeric value iterator declared in this function keeps its
6288
6407
  // built-in protocol state in hidden locals (lowerVarStatement). The
@@ -6295,7 +6414,7 @@ export function lowerForOf(lowerer, stmt) {
6295
6414
  if (ts.isIdentifier(src)) {
6296
6415
  const sym = lowerer.resolveValueSymbol(src);
6297
6416
  const state = sym ? lowerer.numericIterators.get(sym) : undefined;
6298
- if (state?.ctx === lowerer.ctx) {
6417
+ if (state && state.ctx === lowerer.ctx) {
6299
6418
  return lowerForOfStoredNumericIterator(lowerer, stmt, state, labels);
6300
6419
  }
6301
6420
  }
@@ -6412,16 +6531,20 @@ export function lowerForOf(lowerer, stmt) {
6412
6531
  let iterable = lowerer.lowerExpr(iterSrc);
6413
6532
  // A nested loop receiver can be an OOB-safe array read from the outer
6414
6533
  // loop (`for (const row of grid) for (const cell of row)`). The checker
6415
- // sees the inner value as an array, while its runtime slot is array |
6416
- // undefined; validate the receiver before selecting the array iterator.
6534
+ // sees the inner value as an array, while its runtime slot retains
6535
+ // undefined. An Array.isArray guard can also select the array from a
6536
+ // node | node[] | undefined slot. Map lookups and optional fields also
6537
+ // retain nullable runtime slots after a guard selects a concrete
6538
+ // iterable. Validate the selected arm before choosing its iteration
6539
+ // protocol; unchecked null assertions still throw at runtime.
6417
6540
  const checkerIterable = lowerer.mapTypeOf(lowerer.typeOf(iterSrc));
6418
- if (iterable.type.kind === "union" && lowerer.armTag(iterable.type.unionId, UNDEFINED_T) >= 0 && checkerIterable?.kind === "array") {
6419
- const present = lowerer.stripUndefinedArm(iterable.type);
6420
- const helper = present.kind === "array"
6421
- ? lowerer.narrowedArmHelper(iterable.type.unionId, present, locOf(iterSrc))
6422
- : null;
6541
+ if (iterable.type.kind === "union" && checkerIterable !== null &&
6542
+ (checkerIterable.kind === "array" || checkerIterable.kind === "map" || checkerIterable.kind === "set" ||
6543
+ checkerIterable.kind === "bytes" || checkerIterable.kind === "string" || checkerIterable.kind === "searchParams" ||
6544
+ checkerIterable.kind === "generator" || checkerIterable.kind === "object")) {
6545
+ const helper = lowerer.narrowedArmHelper(iterable.type.unionId, checkerIterable, locOf(iterSrc));
6423
6546
  if (helper)
6424
- iterable = { kind: "call", callee: helper, args: [iterable], type: present, loc: locOf(iterSrc) };
6547
+ iterable = { kind: "call", callee: helper, args: [iterable], type: checkerIterable, loc: locOf(iterSrc) };
6425
6548
  }
6426
6549
  if (iterable.type.kind === "bytes") {
6427
6550
  return lowerForOfBytes(lowerer, stmt, iterable, labels);
@@ -6539,8 +6662,7 @@ export function lowerForOf(lowerer, stmt) {
6539
6662
  }
6540
6663
  // A CHECKED-DYNAMIC iterable (`unknown[]`, the collapsed
6541
6664
  // `(string | object)[]`, JSON-parsed values, wrapped engine
6542
- // values): the source packs ONCE through the spread walk and a
6543
- // hidden index loop binds each element as a dyn value.
6665
+ // values): a checked IteratorRecord binds each yielded dyn value.
6544
6666
  if (iterable.type.kind === "dyn") {
6545
6667
  return lowerForOfDyn(lowerer, stmt, iterable, labels);
6546
6668
  }
@@ -6548,29 +6670,132 @@ export function lowerForOf(lowerer, stmt) {
6548
6670
  lowerer.badType(stmt.expression, lowerer.typeOf(stmt.expression));
6549
6671
  }
6550
6672
  }
6551
- const elemValueT = arrayValueType(lowerer, iterable.type.elem);
6673
+ const yieldedT = arrayValueType(lowerer, iterable.type.elem);
6674
+ let elemValueT = yieldedT;
6675
+ let awaitPromiseTag = null;
6676
+ if (awaitArray) {
6677
+ let promiseElem = null;
6678
+ if (iterable.type.elem.kind === "promise") {
6679
+ promiseElem = iterable.type.elem;
6680
+ }
6681
+ else if (iterable.type.elem.kind === "union") {
6682
+ const arms = lowerer.unions.get(iterable.type.elem.unionId)?.arms;
6683
+ if (arms?.length === 2 && arms.some((arm) => arm.kind === "undefinedT")) {
6684
+ const arm = arms.find((candidate) => candidate.kind === "promise");
6685
+ if (arm?.kind === "promise")
6686
+ promiseElem = arm;
6687
+ }
6688
+ }
6689
+ const nonThenable = (type) => {
6690
+ if (type.kind === "union") {
6691
+ const arms = lowerer.unions.get(type.unionId)?.arms;
6692
+ return arms !== undefined && arms.every(nonThenable);
6693
+ }
6694
+ if (type.kind === "record") {
6695
+ const shape = lowerer.shapes.get(type.shapeId);
6696
+ return shape !== undefined && !shape.indexValue && !shape.fields.some((field) => field.name === "then");
6697
+ }
6698
+ return type.kind === "f64" || type.kind === "bigint" || type.kind === "string" ||
6699
+ type.kind === "bool" || type.kind === "symbol" || type.kind === "array" ||
6700
+ type.kind === "undefinedT" || type.kind === "nullT";
6701
+ };
6702
+ if (promiseElem && yieldedT.kind === "union" &&
6703
+ !["void", "union", "dyn", "jsval", "undefinedT", "nullT"].includes(promiseElem.inner.kind)) {
6704
+ awaitPromiseTag = lowerer.armTag(yieldedT.unionId, promiseElem);
6705
+ elemValueT = lowerer.withUndefinedArm(promiseElem.inner);
6706
+ }
6707
+ else if (!nonThenable(iterable.type.elem)) {
6708
+ lowerer.unsupported("SC1070", stmt.expression, "for-await over array values that may be promises or thenables");
6709
+ }
6710
+ }
6552
6711
  // Native arrays retain their payload ABI; the loop binds the value yielded
6553
6712
  // by Get, which is undefined for both holes and present undefined slots.
6554
6713
  const sourceT = iterable.type;
6555
6714
  const source = lowerer.declareHiddenLocal("%arrayIterator", sourceT);
6556
6715
  const cursor = lowerer.declareHiddenLocal("%arrayCursor", F64);
6557
6716
  cursor.mutable = true;
6558
- const forValues = (localId, body) => ({
6559
- kind: "block",
6560
- body: [
6561
- { kind: "varDecl", localId: source.id, init: iterable, loc: locOf(stmt) },
6562
- {
6563
- kind: "for",
6564
- init: { kind: "varDecl", localId: cursor.id, init: numLit(0, locOf(stmt)), loc: locOf(stmt) },
6565
- cond: { kind: "bin", op: "<", left: varRef(cursor.id, F64, locOf(stmt)), right: { kind: "arrIntrinsic", method: "length", receiver: varRef(source.id, sourceT, locOf(stmt)), args: [], type: F64, loc: locOf(stmt) }, type: BOOL, loc: locOf(stmt) },
6566
- update: { kind: "assign", localId: cursor.id, value: { kind: "bin", op: "+", left: varRef(cursor.id, F64, locOf(stmt)), right: numLit(1, locOf(stmt)), type: F64, loc: locOf(stmt) }, loc: locOf(stmt) },
6567
- body: [{ kind: "varDecl", localId, init: arrayValueRead(lowerer, varRef(source.id, sourceT, locOf(stmt)), varRef(cursor.id, F64, locOf(stmt)), sourceT.elem, locOf(stmt)), loc: locOf(stmt) }, ...body],
6568
- ...(labels && { labels }),
6569
- loc: locOf(stmt),
6570
- },
6571
- ],
6572
- loc: locOf(stmt),
6573
- });
6717
+ const forValues = (localId, body) => {
6718
+ const loc = locOf(stmt);
6719
+ const needsClose = awaitArray ? lowerer.declareHiddenLocal("%arrayIteratorNeedsClose", BOOL) : null;
6720
+ if (needsClose)
6721
+ needsClose.mutable = true;
6722
+ const yielded = arrayValueRead(lowerer, varRef(source.id, sourceT, loc), varRef(cursor.id, F64, loc), sourceT.elem, loc);
6723
+ const init = awaitPromiseTag === null ? yielded : {
6724
+ kind: "awaitUnionExpr", value: yielded, promiseTag: awaitPromiseTag, type: elemValueT, loc,
6725
+ };
6726
+ const hops = awaitArray ? (awaitPromiseTag === null ? 2 : 1) : 0;
6727
+ const hop = () => ({
6728
+ kind: "exprStmt", expr: { kind: "libCall", fn: "async.hop", args: [], type: VOID, loc }, loc,
6729
+ });
6730
+ const nextError = awaitPromiseTag !== null ? lowerer.declareHiddenLocal("%arrayIteratorNextError", CAUGHT) : null;
6731
+ const awaitedValue = nextError ? lowerer.declareHiddenLocal("%arrayIteratorValue", elemValueT) : null;
6732
+ if (awaitedValue)
6733
+ awaitedValue.mutable = true;
6734
+ const readValue = awaitedValue
6735
+ ? { kind: "assign", localId: awaitedValue.id, value: init, loc }
6736
+ : { kind: "varDecl", localId, init, loc };
6737
+ const nextValue = nextError ? {
6738
+ kind: "tryCatch",
6739
+ tryBody: [readValue],
6740
+ // Async-from-sync iteration has a continuation reaction between a
6741
+ // rejected element promise and the loop's rejected next result.
6742
+ catchBody: [hop(), { kind: "rethrow", localId: nextError.id, loc }],
6743
+ catchLocalId: nextError.id,
6744
+ finallyBody: null,
6745
+ loc,
6746
+ } : readValue;
6747
+ const length = () => ({
6748
+ kind: "arrIntrinsic", method: "length", receiver: varRef(source.id, sourceT, loc), args: [], type: F64, loc,
6749
+ });
6750
+ const loop = {
6751
+ kind: "for",
6752
+ init: { kind: "varDecl", localId: cursor.id, init: numLit(0, loc), loc },
6753
+ cond: awaitArray
6754
+ ? { kind: "boolLit", value: true, type: BOOL, loc }
6755
+ : { kind: "bin", op: "<", left: varRef(cursor.id, F64, loc), right: length(), type: BOOL, loc },
6756
+ update: { kind: "assign", localId: cursor.id, value: { kind: "bin", op: "+", left: varRef(cursor.id, F64, loc), right: numLit(1, loc), type: F64, loc }, loc },
6757
+ body: [
6758
+ ...(needsClose ? [{
6759
+ kind: "assign", localId: needsClose.id,
6760
+ value: { kind: "boolLit", value: false, type: BOOL, loc }, loc,
6761
+ }] : []),
6762
+ ...(needsClose ? [{
6763
+ kind: "if",
6764
+ cond: { kind: "bin", op: ">=", left: varRef(cursor.id, F64, loc), right: length(), type: BOOL, loc },
6765
+ then: [hop(), hop(), { kind: "break", loc }],
6766
+ else_: null,
6767
+ loc,
6768
+ }] : []),
6769
+ ...(awaitedValue ? [{ kind: "varDecl", localId: awaitedValue.id, init: null, loc }] : []),
6770
+ nextValue,
6771
+ ...(awaitedValue ? [{ kind: "varDecl", localId, init: varRef(awaitedValue.id, elemValueT, loc), loc }] : []),
6772
+ ...Array.from({ length: hops }, hop),
6773
+ // A rejected next value has no iterator close. Once a value has
6774
+ // arrived, an abrupt completion in the body does await close.
6775
+ ...(needsClose ? [{
6776
+ kind: "assign", localId: needsClose.id,
6777
+ value: { kind: "boolLit", value: true, type: BOOL, loc }, loc,
6778
+ }] : []),
6779
+ ...body,
6780
+ ],
6781
+ ...(labels && { labels }),
6782
+ loc,
6783
+ };
6784
+ return {
6785
+ kind: "block",
6786
+ body: [
6787
+ { kind: "varDecl", localId: source.id, init: iterable, loc },
6788
+ ...(needsClose ? [{ kind: "varDecl", localId: needsClose.id, init: { kind: "boolLit", value: false, type: BOOL, loc }, loc }] : []),
6789
+ needsClose ? {
6790
+ kind: "tryCatch",
6791
+ tryBody: [loop], catchBody: null, catchLocalId: null,
6792
+ finallyBody: [{ kind: "if", cond: varRef(needsClose.id, BOOL, loc), then: [hop()], else_: null, loc }],
6793
+ loc,
6794
+ } : loop,
6795
+ ],
6796
+ loc,
6797
+ };
6798
+ };
6574
6799
  if (!ts.isVariableDeclarationList(stmt.initializer)) {
6575
6800
  // `for (x of xs)` over a PRE-DECLARED writable binding: JS assigns
6576
6801
  // the existing binding once per pass — one shared binding across
@@ -6657,7 +6882,9 @@ export function lowerForOf(lowerer, stmt) {
6657
6882
  return forValues(tmp.id, [write, ...body]);
6658
6883
  }
6659
6884
  const local = lowerer.declareLocal(decl.name, decl.name.text, elemValueT, isLet);
6660
- if (!typeEquals(elemValueT, sourceT.elem)) {
6885
+ const declaredElement = lowerer.mapTypeOf(lowerer.typeOf(decl.name));
6886
+ if (!typeEquals(elemValueT, sourceT.elem) ||
6887
+ (declaredElement !== null && lowerer.runtimeOptionalWidening(elemValueT, declaredElement) !== null)) {
6661
6888
  const root = lowerer.runtimeOptionalRootOf(local);
6662
6889
  lowerer.runtimeOptionalLocals.add(root);
6663
6890
  lowerer.runtimeOptionalStorageLocals.add(root);
@@ -7115,66 +7342,46 @@ function lowerForOfClassIterator(lowerer, stmt, iterable, cit, labels) {
7115
7342
  lowerer.scopes.pop();
7116
7343
  }
7117
7344
  }
7118
- /** for-of over an ISLAND value (see lowerForOf's jsval arm): the
7119
- * engine's iterator protocol desugared over jsOps —
7120
- *
7121
- * it = iterNew(v); // GetIterator (prelude; may throw)
7122
- * while (true) {
7123
- * r = it.next(); // callMethod
7124
- * if (truthy(r.done)) break;
7125
- * <bind loop var(s) from r.value> // getProp
7126
- * ...body
7127
- * }
7128
- *
7129
- * The loop variable's ELEMENT is an island handle (jsval — exactly what
7130
- * the checker's package-typed element maps to); identifier heads bind
7131
- * it per iteration, destructuring heads run the jsval pattern desugar,
7132
- * pre-declared and var heads keep their fences (the array path's
7133
- * stories don't carry over mechanically). IteratorClose on early exit
7134
- * (break/return out of a partial iteration calling it.return()) is NOT
7135
- * run — a divergence only a custom island iterator with a return()
7136
- * method can observe. */
7137
- /** For-of over a CHECKED-DYNAMIC iterable: the source packs ONCE
7138
- * through the spread walk (dyn.iterPack — dyn arrays element-by-
7139
- * element, strings by code point, bytes by byte; a WRAPPED engine
7140
- * value drains through the ENGINE's own iterator protocol via the
7141
- * iter_drain arm; every other kind throws V8's not-iterable
7142
- * TypeError, the identifier spelling when the head has one), then a
7143
- * hidden index loop binds each element as a dyn value. The pack is an
7144
- * eager SNAPSHOT (the matchAll stance): body mutations of a dyn-array
7145
- * source don't extend the iteration where JS's live array iterator
7146
- * would — documented divergence; engine sources drain through their
7147
- * own protocol, so generators/Maps/Sets step exactly once like Node. */
7345
+ /** A checked IteratorRecord stays live throughout the loop. Cache next once,
7346
+ * read done before value, and close only after a yielded value has arrived.
7347
+ * Abrupt body throws retain precedence over errors raised by return(). */
7148
7348
  function lowerForOfDyn(lowerer, stmt, iterable, labels) {
7149
7349
  const loc = locOf(stmt);
7150
- const head = stmt.expression;
7151
- // V8's for-of CallPrinter spellings: named sources (identifiers and
7152
- // plain property chains) read "<src> is not iterable", call heads
7153
- // with a nameable callee "<callee> is not a function or its return
7154
- // value is not iterable"; everything else keeps the runtime kind
7155
- // wording. The runtime uses the spelling VERBATIM when non-empty.
7156
7350
  const headText = (e) => {
7157
7351
  if (ts.isIdentifier(e))
7158
7352
  return e.text;
7159
7353
  if (ts.isPropertyAccessExpression(e) && !e.questionDotToken && ts.isIdentifier(e.name)) {
7160
7354
  const base = headText(e.expression);
7161
- return base !== null ? `${base}.${e.name.text}` : null;
7355
+ return base === null ? null : `${base}.${e.name.text}`;
7162
7356
  }
7163
7357
  return null;
7164
7358
  };
7165
- const headName = headText(head);
7166
- const calleeName = ts.isCallExpression(head) ? headText(head.expression) : null;
7167
- const spell = headName !== null
7168
- ? `${headName} is not iterable`
7169
- : calleeName !== null
7170
- ? `${calleeName} is not a function or its return value is not iterable`
7171
- : "";
7172
- const pack = lowerer.declareHiddenLocal("%dofpack", DYN);
7173
- const idx = lowerer.declareHiddenLocal("%dofi", F64);
7174
- idx.mutable = true;
7175
- const packRef = () => ({ kind: "varRef", localId: pack.id, type: DYN, loc });
7176
- const iRef = () => ({ kind: "varRef", localId: idx.id, type: F64, loc });
7177
- const elemInit = () => ({ kind: "libCall", fn: "dyn.arrAt", args: [packRef(), iRef()], type: DYN, loc });
7359
+ const name = headText(stmt.expression);
7360
+ const callee = ts.isCallExpression(stmt.expression) ? headText(stmt.expression.expression) : null;
7361
+ const spell = name !== null ? `${name} is not iterable` : callee !== null ? `${callee} is not a function or its return value is not iterable` : "";
7362
+ const iterator = lowerer.declareHiddenLocal("%dofIterator", DYN);
7363
+ const next = lowerer.declareHiddenLocal("%dofNext", DYN);
7364
+ const step = lowerer.declareHiddenLocal("%dofStep", DYN);
7365
+ const value = lowerer.declareHiddenLocal("%dofValue", DYN);
7366
+ const returned = lowerer.declareHiddenLocal("%dofReturn", DYN);
7367
+ const needsClose = lowerer.declareHiddenLocal("%dofNeedsClose", BOOL);
7368
+ needsClose.mutable = true;
7369
+ const error = lowerer.declareHiddenLocal("%dofError", CAUGHT);
7370
+ const get = (source, key) => ({
7371
+ kind: "dynKeyGet", value: source, key: { kind: "strLit", value: key, type: STRING, loc }, type: DYN, loc,
7372
+ });
7373
+ const check = (value) => ({ kind: "libCall", fn: "dyn.iteratorResult", args: [value], type: DYN, loc });
7374
+ const call = (callee) => check({
7375
+ kind: "dynCall", callee, receiver: varRef(iterator.id, DYN, loc), calleeName: "iterator method", args: [], type: DYN, loc,
7376
+ });
7377
+ const setClose = (value) => ({ kind: "assign", localId: needsClose.id, value: { kind: "boolLit", value, type: BOOL, loc }, loc });
7378
+ const close = () => [
7379
+ { kind: "varDecl", localId: returned.id, init: get(varRef(iterator.id, DYN, loc), "return"), loc },
7380
+ { kind: "if", cond: { kind: "unary", op: "!", operand: { kind: "dynTest", test: "nullish", value: varRef(returned.id, DYN, loc), type: BOOL, loc }, type: BOOL, loc }, then: [
7381
+ { kind: "exprStmt", expr: call(varRef(returned.id, DYN, loc)), loc },
7382
+ ], else_: null, loc },
7383
+ ];
7384
+ const elemInit = () => varRef(value.id, DYN, loc);
7178
7385
  lowerer.scopes.push(new Map());
7179
7386
  try {
7180
7387
  const binds = [];
@@ -7242,40 +7449,35 @@ function lowerForOfDyn(lowerer, stmt, iterable, labels) {
7242
7449
  }
7243
7450
  }
7244
7451
  const body = lowerer.inCtl("loop", () => lowerer.lowerScopedBlock(stmt.statement), labels);
7452
+ const loop = {
7453
+ kind: "while", cond: { kind: "boolLit", value: true, type: BOOL, loc },
7454
+ body: [
7455
+ setClose(false),
7456
+ { kind: "varDecl", localId: step.id, init: call(varRef(next.id, DYN, loc)), loc },
7457
+ { kind: "if", cond: { kind: "dynTest", test: "truthy", value: get(varRef(step.id, DYN, loc), "done"), type: BOOL, loc }, then: [{ kind: "break", loc }], else_: null, loc },
7458
+ { kind: "varDecl", localId: value.id, init: get(varRef(step.id, DYN, loc), "value"), loc },
7459
+ setClose(true),
7460
+ ...binds, ...body,
7461
+ ],
7462
+ ...(labels && { labels }), loc,
7463
+ };
7245
7464
  return {
7246
7465
  kind: "block",
7247
7466
  body: [
7467
+ { kind: "varDecl", localId: iterator.id, init: check({ kind: "libCall", fn: "dyn.iterator", args: [iterable, { kind: "strLit", value: spell, type: STRING, loc }], type: DYN, loc }), loc },
7468
+ { kind: "varDecl", localId: next.id, init: get(varRef(iterator.id, DYN, loc), "next"), loc },
7469
+ { kind: "varDecl", localId: needsClose.id, init: { kind: "boolLit", value: false, type: BOOL, loc }, loc },
7248
7470
  {
7249
- kind: "varDecl",
7250
- localId: pack.id,
7251
- init: {
7252
- kind: "libCall",
7253
- fn: "dyn.iterPack",
7254
- args: [iterable, { kind: "strLit", value: spell, type: STRING, loc }],
7255
- type: DYN,
7256
- loc,
7257
- },
7258
- loc,
7259
- },
7260
- {
7261
- kind: "for",
7262
- init: { kind: "varDecl", localId: idx.id, init: { kind: "numLit", value: 0, type: F64, loc }, loc },
7263
- cond: {
7264
- kind: "bin",
7265
- op: "<",
7266
- left: iRef(),
7267
- right: { kind: "libCall", fn: "dyn.arrLen", args: [packRef()], type: F64, loc },
7268
- type: BOOL,
7269
- loc,
7270
- },
7271
- update: {
7272
- kind: "assign",
7273
- localId: idx.id,
7274
- value: { kind: "bin", op: "+", left: iRef(), right: { kind: "numLit", value: 1, type: F64, loc }, type: F64, loc },
7275
- loc,
7276
- },
7277
- body: [...binds, ...body],
7278
- ...(labels && { labels }),
7471
+ kind: "tryCatch", tryBody: [loop],
7472
+ catchBody: [
7473
+ { kind: "if", cond: varRef(needsClose.id, BOOL, loc), then: [
7474
+ setClose(false),
7475
+ { kind: "tryCatch", tryBody: close(), catchBody: [], catchLocalId: null, finallyBody: null, loc },
7476
+ ], else_: null, loc },
7477
+ { kind: "rethrow", localId: error.id, loc },
7478
+ ],
7479
+ catchLocalId: error.id,
7480
+ finallyBody: [{ kind: "if", cond: varRef(needsClose.id, BOOL, loc), then: close(), else_: null, loc }],
7279
7481
  loc,
7280
7482
  },
7281
7483
  ],
@@ -7286,6 +7488,25 @@ function lowerForOfDyn(lowerer, stmt, iterable, labels) {
7286
7488
  lowerer.scopes.pop();
7287
7489
  }
7288
7490
  }
7491
+ /** for-of over an ISLAND value (see lowerForOf's jsval arm): the
7492
+ * engine's iterator protocol desugared over jsOps —
7493
+ *
7494
+ * it = iterNew(v); // GetIterator (prelude; may throw)
7495
+ * while (true) {
7496
+ * r = it.next(); // callMethod
7497
+ * if (truthy(r.done)) break;
7498
+ * <bind loop var(s) from r.value> // getProp
7499
+ * ...body
7500
+ * }
7501
+ *
7502
+ * The loop variable's ELEMENT is an island handle (jsval — exactly what
7503
+ * the checker's package-typed element maps to); identifier heads bind
7504
+ * it per iteration, destructuring heads run the jsval pattern desugar,
7505
+ * pre-declared and var heads keep their fences (the array path's
7506
+ * stories don't carry over mechanically). IteratorClose on early exit
7507
+ * (break/return out of a partial iteration calling it.return()) is NOT
7508
+ * run — a divergence only a custom island iterator with a return()
7509
+ * method can observe. */
7289
7510
  function lowerForOfIsland(lowerer, stmt, iterable, labels) {
7290
7511
  const loc = locOf(stmt);
7291
7512
  if (!ts.isVariableDeclarationList(stmt.initializer)) {
@@ -7505,13 +7726,25 @@ function lowerForIn(lowerer, stmt) {
7505
7726
  if (stdlibGlobalNameOf(lowerer, stmt.expression) === "globalThis") {
7506
7727
  return { kind: "block", body: [], loc };
7507
7728
  }
7508
- const recvT = lowerer.mapTypeOf(lowerer.typeOf(stmt.expression));
7509
- if (recvT?.kind === "array")
7510
- return lowerForInArray(lowerer, stmt, labels);
7729
+ const receiver = lowerer.lowerExpr(stmt.expression);
7730
+ const recvT = receiver.type;
7731
+ if (recvT.kind === "dyn") {
7732
+ const recv = lowerer.declareHiddenLocal("%indyn", DYN);
7733
+ const ref = { kind: "varRef", localId: recv.id, type: DYN, loc };
7734
+ const keys = {
7735
+ kind: "dynCheck", value: { kind: "libCall", fn: "dyn.forInKeys", args: [ref], type: DYN, loc },
7736
+ type: arrayOf(STRING), loc,
7737
+ };
7738
+ const loop = lowerForInOverKeys(lowerer, stmt, keys, labels, (key) => ({
7739
+ kind: "libCall", fn: "dyn.hasKey", args: [ref, key], type: BOOL, loc,
7740
+ }));
7741
+ return { kind: "block", body: [{ kind: "varDecl", localId: recv.id, init: receiver, loc }, loop], loc };
7742
+ }
7743
+ if (recvT.kind === "array")
7744
+ return lowerForInArray(lowerer, stmt, labels, receiver);
7511
7745
  if (recvT?.kind === "record") {
7512
7746
  const shape = lowerer.shapes.get(recvT.shapeId);
7513
7747
  if (shape && !shape.tuple) {
7514
- const receiver = lowerer.lowerExpr(stmt.expression);
7515
7748
  if (receiver.type.kind !== "record")
7516
7749
  lowerer.badType(stmt.expression, lowerer.typeOf(stmt.expression));
7517
7750
  const rShape = lowerer.shapes.get(receiver.type.shapeId);
@@ -7640,9 +7873,8 @@ function lowerForInOverKeys(lowerer, stmt, keys, labels, guard) {
7640
7873
  * live-length guard is the per-visit presence check (keys removed by
7641
7874
  * pops are skipped, exactly Node's HasProperty re-check; indices are
7642
7875
  * dense, so `i < length` IS presence). */
7643
- function lowerForInArray(lowerer, stmt, labels) {
7876
+ function lowerForInArray(lowerer, stmt, labels, arrExpr) {
7644
7877
  const loc = locOf(stmt);
7645
- const arrExpr = lowerer.lowerExpr(stmt.expression);
7646
7878
  if (arrExpr.type.kind !== "array")
7647
7879
  lowerer.badType(stmt.expression, lowerer.typeOf(stmt.expression));
7648
7880
  lowerer.scopes.push(new Map());