@scriptc/compiler 0.1.7 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1032) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +73 -24
  2. package/ambient/scriptc-overrides.d.ts +10 -6
  3. package/ambient/scriptc.d.ts +15 -0
  4. package/dist/backend/build-cache.d.ts +1 -3
  5. package/dist/backend/build-cache.js +3 -22
  6. package/dist/backend/build-cache.js.map +1 -1
  7. package/dist/backend/cache-root.d.ts +3 -0
  8. package/dist/backend/cache-root.js +23 -0
  9. package/dist/backend/cache-root.js.map +1 -0
  10. package/dist/backend/cycle-analysis.d.ts +15 -0
  11. package/dist/backend/cycle-analysis.js +107 -0
  12. package/dist/backend/cycle-analysis.js.map +1 -0
  13. package/dist/backend/cycle-analysis.test.js +124 -0
  14. package/dist/backend/cycle-analysis.test.js.map +1 -0
  15. package/dist/backend/executable-features.d.ts +4 -0
  16. package/dist/backend/executable-features.js +42 -0
  17. package/dist/backend/executable-features.js.map +1 -0
  18. package/dist/backend/external-c.d.ts +5 -27
  19. package/dist/backend/external-c.js +5 -40
  20. package/dist/backend/external-c.js.map +1 -1
  21. package/dist/backend/ffi-callbacks.d.ts +2 -3
  22. package/dist/backend/ffi-callbacks.js +2 -3
  23. package/dist/backend/ffi-callbacks.js.map +1 -1
  24. package/dist/backend/library-identity-markers.d.ts +4 -9
  25. package/dist/backend/library-identity-markers.js +11 -49
  26. package/dist/backend/library-identity-markers.js.map +1 -1
  27. package/dist/backend/library-pack.d.ts +5 -0
  28. package/dist/backend/library-pack.js +123 -0
  29. package/dist/backend/library-pack.js.map +1 -0
  30. package/dist/backend/link-plan-core.d.ts +20 -0
  31. package/dist/backend/link-plan-core.js +18 -0
  32. package/dist/backend/link-plan-core.js.map +1 -0
  33. package/dist/backend/link-plan.d.ts +1 -1
  34. package/dist/backend/link-plan.js +16 -17
  35. package/dist/backend/link-plan.js.map +1 -1
  36. package/dist/backend/link-trace.d.ts +2 -0
  37. package/dist/backend/link-trace.js +24 -0
  38. package/dist/backend/link-trace.js.map +1 -0
  39. package/dist/backend/linker.js +1 -1
  40. package/dist/backend/linker.js.map +1 -1
  41. package/dist/backend/literals.d.ts +9 -0
  42. package/dist/backend/literals.js +35 -0
  43. package/dist/backend/literals.js.map +1 -0
  44. package/dist/backend/literals.test.d.ts +1 -0
  45. package/dist/backend/literals.test.js +53 -0
  46. package/dist/backend/literals.test.js.map +1 -0
  47. package/dist/backend/llvm/blocks.d.ts +2 -0
  48. package/dist/backend/llvm/blocks.js +9 -4
  49. package/dist/backend/llvm/blocks.js.map +1 -1
  50. package/dist/backend/llvm/blocks.test.d.ts +1 -0
  51. package/dist/backend/llvm/blocks.test.js +91 -0
  52. package/dist/backend/llvm/blocks.test.js.map +1 -0
  53. package/dist/backend/llvm/classes.d.ts +14 -8
  54. package/dist/backend/llvm/classes.js +70 -28
  55. package/dist/backend/llvm/classes.js.map +1 -1
  56. package/dist/backend/llvm/common.d.ts +5 -1
  57. package/dist/backend/llvm/common.js +45 -4
  58. package/dist/backend/llvm/common.js.map +1 -1
  59. package/dist/backend/llvm/debug-info.js +2 -7
  60. package/dist/backend/llvm/debug-info.js.map +1 -1
  61. package/dist/backend/llvm/debug-info.test.d.ts +1 -0
  62. package/dist/backend/llvm/debug-info.test.js +110 -0
  63. package/dist/backend/llvm/debug-info.test.js.map +1 -0
  64. package/dist/backend/llvm/dyn.d.ts +16 -2
  65. package/dist/backend/llvm/dyn.js +494 -165
  66. package/dist/backend/llvm/dyn.js.map +1 -1
  67. package/dist/backend/llvm/emitter.d.ts +596 -1
  68. package/dist/backend/llvm/emitter.js +695 -410
  69. package/dist/backend/llvm/emitter.js.map +1 -1
  70. package/dist/backend/llvm/emitter.test.d.ts +1 -0
  71. package/dist/backend/llvm/emitter.test.js +179 -0
  72. package/dist/backend/llvm/emitter.test.js.map +1 -0
  73. package/dist/backend/llvm/expr-async.js +23 -14
  74. package/dist/backend/llvm/expr-async.js.map +1 -1
  75. package/dist/backend/llvm/expr-bytes.d.ts +1 -1
  76. package/dist/backend/llvm/expr-bytes.js +32 -14
  77. package/dist/backend/llvm/expr-bytes.js.map +1 -1
  78. package/dist/backend/llvm/expr-callbacks.d.ts +1 -1
  79. package/dist/backend/llvm/expr-callbacks.js +25 -22
  80. package/dist/backend/llvm/expr-callbacks.js.map +1 -1
  81. package/dist/backend/llvm/expr-calls.js +136 -35
  82. package/dist/backend/llvm/expr-calls.js.map +1 -1
  83. package/dist/backend/llvm/expr-containers.d.ts +1 -1
  84. package/dist/backend/llvm/expr-containers.js +43 -14
  85. package/dist/backend/llvm/expr-containers.js.map +1 -1
  86. package/dist/backend/llvm/expr-context.d.ts +5 -260
  87. package/dist/backend/llvm/expr-control.js +9 -5
  88. package/dist/backend/llvm/expr-control.js.map +1 -1
  89. package/dist/backend/llvm/expr-dispatch.d.ts +1 -1
  90. package/dist/backend/llvm/expr-dispatch.js +2 -0
  91. package/dist/backend/llvm/expr-dispatch.js.map +1 -1
  92. package/dist/backend/llvm/expr-dynamic.js +62 -74
  93. package/dist/backend/llvm/expr-dynamic.js.map +1 -1
  94. package/dist/backend/llvm/expr-island.d.ts +1 -1
  95. package/dist/backend/llvm/expr-island.js +11 -7
  96. package/dist/backend/llvm/expr-island.js.map +1 -1
  97. package/dist/backend/llvm/expr-primitives.d.ts +1 -1
  98. package/dist/backend/llvm/expr-primitives.js +51 -30
  99. package/dist/backend/llvm/expr-primitives.js.map +1 -1
  100. package/dist/backend/llvm/expr-primitives.test.js +1 -1
  101. package/dist/backend/llvm/expr-records.d.ts +5 -1
  102. package/dist/backend/llvm/expr-records.js +43 -4
  103. package/dist/backend/llvm/expr-records.js.map +1 -1
  104. package/dist/backend/llvm/expr-stream-bridges.d.ts +4 -4
  105. package/dist/backend/llvm/expr-stream-bridges.js +102 -121
  106. package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
  107. package/dist/backend/llvm/expr-stream-bridges.test.d.ts +1 -0
  108. package/dist/backend/llvm/expr-stream-bridges.test.js +55 -0
  109. package/dist/backend/llvm/expr-stream-bridges.test.js.map +1 -0
  110. package/dist/backend/llvm/expr-stream-callbacks.d.ts +1 -1
  111. package/dist/backend/llvm/expr-stream-callbacks.js +12 -12
  112. package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
  113. package/dist/backend/llvm/layouts.d.ts +19 -0
  114. package/dist/backend/llvm/layouts.js +12 -0
  115. package/dist/backend/llvm/layouts.js.map +1 -0
  116. package/dist/backend/llvm/lib-abi.d.ts +19 -0
  117. package/dist/backend/llvm/lib-abi.js +82 -0
  118. package/dist/backend/llvm/lib-abi.js.map +1 -0
  119. package/dist/backend/llvm/lib-connect.d.ts +2 -0
  120. package/dist/backend/llvm/lib-connect.js +51 -0
  121. package/dist/backend/llvm/lib-connect.js.map +1 -0
  122. package/dist/backend/llvm/lib-datagram.d.ts +2 -0
  123. package/dist/backend/llvm/lib-datagram.js +135 -0
  124. package/dist/backend/llvm/lib-datagram.js.map +1 -0
  125. package/dist/backend/llvm/lib-dispatch.js +50 -6
  126. package/dist/backend/llvm/lib-dispatch.js.map +1 -1
  127. package/dist/backend/llvm/lib-filesystem.js +30 -18
  128. package/dist/backend/llvm/lib-filesystem.js.map +1 -1
  129. package/dist/backend/llvm/lib-http2.d.ts +2 -0
  130. package/dist/backend/llvm/lib-http2.js +215 -0
  131. package/dist/backend/llvm/lib-http2.js.map +1 -0
  132. package/dist/backend/llvm/lib-lookup.d.ts +2 -0
  133. package/dist/backend/llvm/lib-lookup.js +39 -0
  134. package/dist/backend/llvm/lib-lookup.js.map +1 -0
  135. package/dist/backend/llvm/lib-network.js +25 -2
  136. package/dist/backend/llvm/lib-network.js.map +1 -1
  137. package/dist/backend/llvm/lib-process.js +21 -16
  138. package/dist/backend/llvm/lib-process.js.map +1 -1
  139. package/dist/backend/llvm/lib-shared.js +117 -1
  140. package/dist/backend/llvm/lib-shared.js.map +1 -1
  141. package/dist/backend/llvm/lib-stream.js +3 -2
  142. package/dist/backend/llvm/lib-stream.js.map +1 -1
  143. package/dist/backend/llvm/lib-test.d.ts +2 -0
  144. package/dist/backend/llvm/lib-test.js +34 -0
  145. package/dist/backend/llvm/lib-test.js.map +1 -0
  146. package/dist/backend/llvm/lib-tls.d.ts +2 -0
  147. package/dist/backend/llvm/lib-tls.js +82 -0
  148. package/dist/backend/llvm/lib-tls.js.map +1 -0
  149. package/dist/backend/llvm/shapes.d.ts +10 -9
  150. package/dist/backend/llvm/shapes.js +35 -130
  151. package/dist/backend/llvm/shapes.js.map +1 -1
  152. package/dist/backend/llvm/unsupported.d.ts +1 -0
  153. package/dist/backend/llvm/unsupported.js +1 -2
  154. package/dist/backend/llvm/unsupported.js.map +1 -1
  155. package/dist/backend/llvm/walkers.js +1 -7
  156. package/dist/backend/llvm/walkers.js.map +1 -1
  157. package/dist/backend/mangle.d.ts +2 -2
  158. package/dist/backend/mangle.js +16 -5
  159. package/dist/backend/mangle.js.map +1 -1
  160. package/dist/backend/{c/may-throw.d.ts → may-throw.d.ts} +1 -1
  161. package/dist/backend/{c/may-throw.js → may-throw.js} +51 -46
  162. package/dist/backend/may-throw.js.map +1 -0
  163. package/dist/backend/may-throw.test.d.ts +1 -0
  164. package/dist/backend/may-throw.test.js +58 -0
  165. package/dist/backend/may-throw.test.js.map +1 -0
  166. package/dist/backend/native-codegen-core.d.ts +22 -0
  167. package/dist/backend/native-codegen-core.js +44 -0
  168. package/dist/backend/native-codegen-core.js.map +1 -0
  169. package/dist/backend/native-codegen.d.ts +3 -19
  170. package/dist/backend/native-codegen.js +5 -44
  171. package/dist/backend/native-codegen.js.map +1 -1
  172. package/dist/backend/native-codegen.test.js +2 -2
  173. package/dist/backend/native-codegen.test.js.map +1 -1
  174. package/dist/backend/native-link-info-core.d.ts +94 -0
  175. package/dist/backend/native-link-info-core.js +62 -0
  176. package/dist/backend/native-link-info-core.js.map +1 -0
  177. package/dist/backend/native-link-info.d.ts +3 -88
  178. package/dist/backend/native-link-info.js +12 -243
  179. package/dist/backend/native-link-info.js.map +1 -1
  180. package/dist/backend/native-link-info.test.js +41 -146
  181. package/dist/backend/native-link-info.test.js.map +1 -1
  182. package/dist/backend/native-toolchain.d.ts +10 -25
  183. package/dist/backend/native-toolchain.js +31 -211
  184. package/dist/backend/native-toolchain.js.map +1 -1
  185. package/dist/backend/native-toolchain.test.js +5 -5
  186. package/dist/backend/native-toolchain.test.js.map +1 -1
  187. package/dist/backend/native-tools.d.ts +24 -0
  188. package/dist/backend/native-tools.js +33 -0
  189. package/dist/backend/native-tools.js.map +1 -0
  190. package/dist/backend/object-localize.js +19 -8
  191. package/dist/backend/object-localize.js.map +1 -1
  192. package/dist/backend/object-localize.test.js +22 -0
  193. package/dist/backend/object-localize.test.js.map +1 -1
  194. package/dist/backend/runtime-abi.d.ts +2 -2
  195. package/dist/backend/runtime-abi.js +2 -2
  196. package/dist/backend/runtime-pack-core.d.ts +101 -0
  197. package/dist/backend/runtime-pack-core.js +172 -0
  198. package/dist/backend/runtime-pack-core.js.map +1 -0
  199. package/dist/backend/runtime-pack-native.d.ts +21 -0
  200. package/dist/backend/runtime-pack-native.js +70 -0
  201. package/dist/backend/runtime-pack-native.js.map +1 -0
  202. package/dist/backend/runtime-pack-targets.test.js +1 -1
  203. package/dist/backend/runtime-pack.d.ts +3 -83
  204. package/dist/backend/runtime-pack.js +8 -151
  205. package/dist/backend/runtime-pack.js.map +1 -1
  206. package/dist/backend/runtime-pack.test.js +24 -1
  207. package/dist/backend/runtime-pack.test.js.map +1 -1
  208. package/dist/backend/target-diagnostics.d.ts +22 -0
  209. package/dist/backend/target-diagnostics.js +108 -0
  210. package/dist/backend/target-diagnostics.js.map +1 -0
  211. package/dist/backend/target-platform.d.ts +15 -0
  212. package/dist/backend/target-platform.js +72 -0
  213. package/dist/backend/target-platform.js.map +1 -0
  214. package/dist/backend/targets.d.ts +13 -4
  215. package/dist/backend/targets.js +95 -30
  216. package/dist/backend/targets.js.map +1 -1
  217. package/dist/backend/targets.test.js +65 -4
  218. package/dist/backend/targets.test.js.map +1 -1
  219. package/dist/backend/toolchain-environment.d.ts +6 -0
  220. package/dist/backend/toolchain-environment.js +99 -0
  221. package/dist/backend/toolchain-environment.js.map +1 -0
  222. package/dist/backend/vendor-archives.d.ts +1 -9
  223. package/dist/backend/vendor-archives.js +2 -9
  224. package/dist/backend/vendor-archives.js.map +1 -1
  225. package/dist/backend/vendor-inputs.d.ts +9 -0
  226. package/dist/backend/vendor-inputs.js +10 -0
  227. package/dist/backend/vendor-inputs.js.map +1 -0
  228. package/dist/backend/warm-cache.d.ts +3 -0
  229. package/dist/backend/warm-cache.js +41 -0
  230. package/dist/backend/warm-cache.js.map +1 -0
  231. package/dist/cli/command.d.ts +3 -0
  232. package/dist/cli/command.js +328 -0
  233. package/dist/cli/command.js.map +1 -0
  234. package/dist/cli/host.d.ts +24 -0
  235. package/dist/cli/host.js +2 -0
  236. package/dist/cli/host.js.map +1 -0
  237. package/dist/cli/output-options.d.ts +26 -0
  238. package/dist/cli/output-options.js +60 -0
  239. package/dist/cli/output-options.js.map +1 -0
  240. package/dist/cli/paths.d.ts +12 -0
  241. package/dist/cli/paths.js +42 -0
  242. package/dist/cli/paths.js.map +1 -0
  243. package/dist/cli/usage.d.ts +74 -0
  244. package/dist/cli/usage.js +86 -0
  245. package/dist/cli/usage.js.map +1 -0
  246. package/dist/cli/wasi-paths.d.ts +8 -0
  247. package/dist/cli/wasi-paths.js +41 -0
  248. package/dist/cli/wasi-paths.js.map +1 -0
  249. package/dist/cli/wasi-runner.d.ts +2 -0
  250. package/dist/cli/wasi-runner.js +28 -0
  251. package/dist/cli/wasi-runner.js.map +1 -0
  252. package/dist/compat/fetch-profile.js +3 -3
  253. package/dist/compat/fetch-profile.js.map +1 -1
  254. package/dist/compile-types.d.ts +162 -0
  255. package/dist/compile-types.js +2 -0
  256. package/dist/compile-types.js.map +1 -0
  257. package/dist/coverage/report.js +11 -5
  258. package/dist/coverage/report.js.map +1 -1
  259. package/dist/coverage/surface-manifest.js +5 -2
  260. package/dist/coverage/surface-manifest.js.map +1 -1
  261. package/dist/diagnostics/diagnostic.js +3 -3
  262. package/dist/diagnostics/diagnostic.js.map +1 -1
  263. package/dist/executable/executable-cache.d.ts +3 -4
  264. package/dist/executable/executable-cache.js +5 -6
  265. package/dist/executable/executable-cache.js.map +1 -1
  266. package/dist/executable/executable-cache.test.js +16 -17
  267. package/dist/executable/executable-cache.test.js.map +1 -1
  268. package/dist/executable/prepare.d.ts +14 -0
  269. package/dist/executable/prepare.js +66 -0
  270. package/dist/executable/prepare.js.map +1 -0
  271. package/dist/ffi/ffi-manifest.d.ts +11 -4
  272. package/dist/ffi/ffi-manifest.js +170 -58
  273. package/dist/ffi/ffi-manifest.js.map +1 -1
  274. package/dist/ffi/ffi-manifest.test.d.ts +1 -0
  275. package/dist/ffi/ffi-manifest.test.js +111 -0
  276. package/dist/ffi/ffi-manifest.test.js.map +1 -0
  277. package/dist/format-integer.d.ts +3 -0
  278. package/dist/format-integer.js +14 -0
  279. package/dist/format-integer.js.map +1 -0
  280. package/dist/frontend/analysis.d.ts +5 -0
  281. package/dist/frontend/analysis.js +88 -0
  282. package/dist/frontend/analysis.js.map +1 -0
  283. package/dist/frontend/arguments-usage.d.ts +1 -3
  284. package/dist/frontend/arguments-usage.js.map +1 -1
  285. package/dist/frontend/builtin-modules.d.ts +1 -1
  286. package/dist/frontend/builtin-modules.js +1 -1
  287. package/dist/frontend/builtin-modules.js.map +1 -1
  288. package/dist/frontend/cjs-lexer.d.ts +4 -25
  289. package/dist/frontend/cjs-lexer.js +6 -806
  290. package/dist/frontend/cjs-lexer.js.map +1 -1
  291. package/dist/frontend/cjs-resolve.d.ts +5 -0
  292. package/dist/frontend/cjs-resolve.js +429 -0
  293. package/dist/frontend/cjs-resolve.js.map +1 -0
  294. package/dist/frontend/cjs-syntax.d.ts +26 -0
  295. package/dist/frontend/cjs-syntax.js +806 -0
  296. package/dist/frontend/cjs-syntax.js.map +1 -0
  297. package/dist/frontend/comptime-node.d.ts +4 -0
  298. package/dist/frontend/comptime-node.js +16 -0
  299. package/dist/frontend/comptime-node.js.map +1 -0
  300. package/dist/frontend/comptime-node.test.d.ts +1 -0
  301. package/dist/frontend/comptime-node.test.js +37 -0
  302. package/dist/frontend/comptime-node.test.js.map +1 -0
  303. package/dist/frontend/dts-paths.d.ts +3 -4
  304. package/dist/frontend/dts-paths.js +15 -8
  305. package/dist/frontend/dts-paths.js.map +1 -1
  306. package/dist/frontend/fork-target.js +2 -2
  307. package/dist/frontend/fork-target.js.map +1 -1
  308. package/dist/frontend/helper-tokens.d.ts +1 -0
  309. package/dist/frontend/helper-tokens.js +147 -0
  310. package/dist/frontend/helper-tokens.js.map +1 -0
  311. package/dist/frontend/helper-tokens.test.d.ts +1 -0
  312. package/dist/frontend/helper-tokens.test.js +35 -0
  313. package/dist/frontend/helper-tokens.test.js.map +1 -0
  314. package/dist/frontend/inferred-js-diagnostics.d.ts +5 -0
  315. package/dist/frontend/inferred-js-diagnostics.js +69 -0
  316. package/dist/frontend/inferred-js-diagnostics.js.map +1 -0
  317. package/dist/frontend/inferred-js-diagnostics.test.d.ts +1 -0
  318. package/dist/frontend/inferred-js-diagnostics.test.js +58 -0
  319. package/dist/frontend/inferred-js-diagnostics.test.js.map +1 -0
  320. package/dist/frontend/input-tracker.d.ts +5 -2
  321. package/dist/frontend/input-tracker.js +24 -3
  322. package/dist/frontend/input-tracker.js.map +1 -1
  323. package/dist/frontend/input-tracker.test.js +23 -0
  324. package/dist/frontend/input-tracker.test.js.map +1 -1
  325. package/dist/frontend/lib-contract.js +32 -24
  326. package/dist/frontend/lib-contract.js.map +1 -1
  327. package/dist/frontend/literal-values.d.ts +4 -0
  328. package/dist/frontend/literal-values.js +21 -0
  329. package/dist/frontend/literal-values.js.map +1 -0
  330. package/dist/frontend/literal-values.test.d.ts +1 -0
  331. package/dist/frontend/literal-values.test.js +91 -0
  332. package/dist/frontend/literal-values.test.js.map +1 -0
  333. package/dist/frontend/lowering/abstract-equality.d.ts +1 -1
  334. package/dist/frontend/lowering/abstract-equality.js +3 -0
  335. package/dist/frontend/lowering/abstract-equality.js.map +1 -1
  336. package/dist/frontend/lowering/array-indexed-mutation.js +11 -6
  337. package/dist/frontend/lowering/array-indexed-mutation.js.map +1 -1
  338. package/dist/frontend/lowering/array-values.d.ts +4 -1
  339. package/dist/frontend/lowering/array-values.js +43 -1
  340. package/dist/frontend/lowering/array-values.js.map +1 -1
  341. package/dist/frontend/lowering/callback-arg.js +1 -0
  342. package/dist/frontend/lowering/callback-arg.js.map +1 -1
  343. package/dist/frontend/lowering/class-callbacks.d.ts +12 -0
  344. package/dist/frontend/lowering/class-callbacks.js +63 -0
  345. package/dist/frontend/lowering/class-callbacks.js.map +1 -0
  346. package/dist/frontend/lowering/class-descriptors.d.ts +9 -0
  347. package/dist/frontend/lowering/class-descriptors.js +73 -0
  348. package/dist/frontend/lowering/class-descriptors.js.map +1 -0
  349. package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +41 -0
  350. package/dist/frontend/lowering/class-dynamic-dispatch.js +803 -0
  351. package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -0
  352. package/dist/frontend/lowering/class-dynamic-dispatch.test.d.ts +1 -0
  353. package/dist/frontend/lowering/class-dynamic-dispatch.test.js +92 -0
  354. package/dist/frontend/lowering/class-dynamic-dispatch.test.js.map +1 -0
  355. package/dist/frontend/lowering/class-instance-constructor.d.ts +7 -0
  356. package/dist/frontend/lowering/class-instance-constructor.js +64 -0
  357. package/dist/frontend/lowering/class-instance-constructor.js.map +1 -0
  358. package/dist/frontend/lowering/class-method-values.d.ts +10 -0
  359. package/dist/frontend/lowering/class-method-values.js +170 -0
  360. package/dist/frontend/lowering/class-method-values.js.map +1 -0
  361. package/dist/frontend/lowering/class-prototypes.d.ts +16 -0
  362. package/dist/frontend/lowering/class-prototypes.js +134 -0
  363. package/dist/frontend/lowering/class-prototypes.js.map +1 -0
  364. package/dist/frontend/lowering/class-static-data.d.ts +6 -0
  365. package/dist/frontend/lowering/class-static-data.js +56 -0
  366. package/dist/frontend/lowering/class-static-data.js.map +1 -0
  367. package/dist/frontend/lowering/containers/buffer-numeric-methods.d.ts +4 -0
  368. package/dist/frontend/lowering/containers/buffer-numeric-methods.js +26 -0
  369. package/dist/frontend/lowering/containers/buffer-numeric-methods.js.map +1 -0
  370. package/dist/frontend/lowering/containers/bytes.d.ts +11 -7
  371. package/dist/frontend/lowering/containers/bytes.js +164 -155
  372. package/dist/frontend/lowering/containers/bytes.js.map +1 -1
  373. package/dist/frontend/lowering/containers/string-and-regexp.d.ts +2 -2
  374. package/dist/frontend/lowering/containers/string-and-regexp.js +39 -16
  375. package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
  376. package/dist/frontend/lowering/containers/string-replacement.d.ts +7 -0
  377. package/dist/frontend/lowering/containers/string-replacement.js +217 -0
  378. package/dist/frontend/lowering/containers/string-replacement.js.map +1 -0
  379. package/dist/frontend/lowering/error-methods.d.ts +11 -0
  380. package/dist/frontend/lowering/error-methods.js +78 -0
  381. package/dist/frontend/lowering/error-methods.js.map +1 -0
  382. package/dist/frontend/lowering/expressions/global-symbols.d.ts +6 -0
  383. package/dist/frontend/lowering/expressions/global-symbols.js +11 -0
  384. package/dist/frontend/lowering/expressions/global-symbols.js.map +1 -0
  385. package/dist/frontend/lowering/expressions/native-proxy.d.ts +7 -0
  386. package/dist/frontend/lowering/expressions/native-proxy.js +49 -0
  387. package/dist/frontend/lowering/expressions/native-proxy.js.map +1 -0
  388. package/dist/frontend/lowering/expressions/nullish-assignment.d.ts +6 -0
  389. package/dist/frontend/lowering/expressions/nullish-assignment.js +124 -0
  390. package/dist/frontend/lowering/expressions/nullish-assignment.js.map +1 -0
  391. package/dist/frontend/lowering/expressions/object-literals.d.ts +8 -8
  392. package/dist/frontend/lowering/expressions/object-literals.js +473 -178
  393. package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
  394. package/dist/frontend/lowering/expressions/optional-chains.js +20 -8
  395. package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
  396. package/dist/frontend/lowering/expressions/try-lower-expression.js +1 -0
  397. package/dist/frontend/lowering/expressions/try-lower-expression.js.map +1 -1
  398. package/dist/frontend/lowering/expressions/union-field-write.d.ts +8 -0
  399. package/dist/frontend/lowering/expressions/union-field-write.js +71 -0
  400. package/dist/frontend/lowering/expressions/union-field-write.js.map +1 -0
  401. package/dist/frontend/lowering/function-context.d.ts +93 -0
  402. package/dist/frontend/lowering/function-context.js +103 -0
  403. package/dist/frontend/lowering/function-context.js.map +1 -0
  404. package/dist/frontend/lowering/generator-delegation.d.ts +7 -0
  405. package/dist/frontend/lowering/generator-delegation.js +85 -0
  406. package/dist/frontend/lowering/generator-delegation.js.map +1 -0
  407. package/dist/frontend/lowering/generator-dynamic-dispatch.d.ts +10 -0
  408. package/dist/frontend/lowering/generator-dynamic-dispatch.js +105 -0
  409. package/dist/frontend/lowering/generator-dynamic-dispatch.js.map +1 -0
  410. package/dist/frontend/lowering/lib-boundary.d.ts +2 -1
  411. package/dist/frontend/lowering/lib-boundary.js +59 -20
  412. package/dist/frontend/lowering/lib-boundary.js.map +1 -1
  413. package/dist/frontend/lowering/lib-boundary.test.d.ts +1 -0
  414. package/dist/frontend/lowering/lib-boundary.test.js +45 -0
  415. package/dist/frontend/lowering/lib-boundary.test.js.map +1 -0
  416. package/dist/frontend/lowering/lower-array-sort.d.ts +1 -1
  417. package/dist/frontend/lowering/lower-assert.d.ts +1 -1
  418. package/dist/frontend/lowering/lower-assert.js.map +1 -1
  419. package/dist/frontend/lowering/lower-async-iteration.d.ts +1 -1
  420. package/dist/frontend/lowering/lower-async-iteration.js.map +1 -1
  421. package/dist/frontend/lowering/lower-builtin-values.d.ts +12 -0
  422. package/dist/frontend/lowering/lower-builtin-values.js +139 -0
  423. package/dist/frontend/lowering/lower-builtin-values.js.map +1 -0
  424. package/dist/frontend/lowering/lower-builtins.d.ts +27 -41
  425. package/dist/frontend/lowering/lower-builtins.js +539 -343
  426. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  427. package/dist/frontend/lowering/lower-calls.d.ts +20 -17
  428. package/dist/frontend/lowering/lower-calls.js +1236 -353
  429. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  430. package/dist/frontend/lowering/lower-classes.d.ts +83 -45
  431. package/dist/frontend/lowering/lower-classes.js +952 -339
  432. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  433. package/dist/frontend/lowering/lower-comptime.d.ts +1 -1
  434. package/dist/frontend/lowering/lower-comptime.js +23 -32
  435. package/dist/frontend/lowering/lower-comptime.js.map +1 -1
  436. package/dist/frontend/lowering/lower-containers.d.ts +27 -32
  437. package/dist/frontend/lowering/lower-containers.js +796 -151
  438. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  439. package/dist/frontend/lowering/lower-dgram.d.ts +1 -1
  440. package/dist/frontend/lowering/lower-dgram.js.map +1 -1
  441. package/dist/frontend/lowering/lower-enums.d.ts +1 -1
  442. package/dist/frontend/lowering/lower-enums.js.map +1 -1
  443. package/dist/frontend/lowering/lower-event-emitter.d.ts +30 -1
  444. package/dist/frontend/lowering/lower-event-emitter.js +58 -26
  445. package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
  446. package/dist/frontend/lowering/lower-expando.d.ts +7 -1
  447. package/dist/frontend/lowering/lower-expando.js +14 -6
  448. package/dist/frontend/lowering/lower-expando.js.map +1 -1
  449. package/dist/frontend/lowering/lower-exprs.d.ts +35 -11
  450. package/dist/frontend/lowering/lower-exprs.js +1674 -779
  451. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  452. package/dist/frontend/lowering/lower-generators.d.ts +2 -5
  453. package/dist/frontend/lowering/lower-generators.js +77 -46
  454. package/dist/frontend/lowering/lower-generators.js.map +1 -1
  455. package/dist/frontend/lowering/lower-global-value.d.ts +7 -0
  456. package/dist/frontend/lowering/lower-global-value.js +17 -0
  457. package/dist/frontend/lowering/lower-global-value.js.map +1 -0
  458. package/dist/frontend/lowering/lower-inspect.d.ts +1 -1
  459. package/dist/frontend/lowering/lower-inspect.js +17 -8
  460. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  461. package/dist/frontend/lowering/lower-island.d.ts +5 -8
  462. package/dist/frontend/lowering/lower-island.js +34 -23
  463. package/dist/frontend/lowering/lower-island.js.map +1 -1
  464. package/dist/frontend/lowering/lower-mixins.d.ts +2 -2
  465. package/dist/frontend/lowering/lower-mixins.js +5 -3
  466. package/dist/frontend/lowering/lower-mixins.js.map +1 -1
  467. package/dist/frontend/lowering/lower-modules.d.ts +1 -1
  468. package/dist/frontend/lowering/lower-modules.js +233 -30
  469. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  470. package/dist/frontend/lowering/lower-namespaces.d.ts +1 -1
  471. package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
  472. package/dist/frontend/lowering/lower-node-module.d.ts +1 -1
  473. package/dist/frontend/lowering/lower-node-module.js +13 -10
  474. package/dist/frontend/lowering/lower-node-module.js.map +1 -1
  475. package/dist/frontend/lowering/lower-server.d.ts +1 -1
  476. package/dist/frontend/lowering/lower-server.js +6 -10
  477. package/dist/frontend/lowering/lower-server.js.map +1 -1
  478. package/dist/frontend/lowering/lower-stmts.d.ts +10 -14
  479. package/dist/frontend/lowering/lower-stmts.js +728 -496
  480. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  481. package/dist/frontend/lowering/lower-stream.d.ts +1 -1
  482. package/dist/frontend/lowering/lower-stream.js +19 -10
  483. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  484. package/dist/frontend/lowering/lower-test.d.ts +1 -1
  485. package/dist/frontend/lowering/lower-test.js.map +1 -1
  486. package/dist/frontend/lowering/lower-url.d.ts +6 -0
  487. package/dist/frontend/lowering/lower-url.js +77 -0
  488. package/dist/frontend/lowering/lower-url.js.map +1 -0
  489. package/dist/frontend/lowering/lowerer.d.ts +113 -189
  490. package/dist/frontend/lowering/lowerer.js +1031 -672
  491. package/dist/frontend/lowering/lowerer.js.map +1 -1
  492. package/dist/frontend/lowering/lowerer.test.d.ts +1 -0
  493. package/dist/frontend/lowering/lowerer.test.js +26 -0
  494. package/dist/frontend/lowering/lowerer.test.js.map +1 -0
  495. package/dist/frontend/lowering/native-ffi.d.ts +5 -0
  496. package/dist/frontend/lowering/native-ffi.js +40 -0
  497. package/dist/frontend/lowering/native-ffi.js.map +1 -0
  498. package/dist/frontend/lowering/object-enumeration-receiver.d.ts +7 -0
  499. package/dist/frontend/lowering/object-enumeration-receiver.js +33 -0
  500. package/dist/frontend/lowering/object-enumeration-receiver.js.map +1 -0
  501. package/dist/frontend/lowering/object-factory-new.d.ts +8 -0
  502. package/dist/frontend/lowering/object-factory-new.js +68 -0
  503. package/dist/frontend/lowering/object-factory-new.js.map +1 -0
  504. package/dist/frontend/lowering/optional-arguments.js +6 -1
  505. package/dist/frontend/lowering/optional-arguments.js.map +1 -1
  506. package/dist/frontend/lowering/pairs-snapshot.js +2 -1
  507. package/dist/frontend/lowering/pairs-snapshot.js.map +1 -1
  508. package/dist/frontend/lowering/runtime-optional-locals.d.ts +14 -0
  509. package/dist/frontend/lowering/runtime-optional-locals.js +41 -0
  510. package/dist/frontend/lowering/runtime-optional-locals.js.map +1 -0
  511. package/dist/frontend/lowering/runtime-optional-locals.test.d.ts +1 -0
  512. package/dist/frontend/lowering/runtime-optional-locals.test.js +85 -0
  513. package/dist/frontend/lowering/runtime-optional-locals.test.js.map +1 -0
  514. package/dist/frontend/lowering/sanitize-class-types.d.ts +8 -0
  515. package/dist/frontend/lowering/sanitize-class-types.js +79 -0
  516. package/dist/frontend/lowering/sanitize-class-types.js.map +1 -0
  517. package/dist/frontend/lowering/sanitize-class-types.test.d.ts +1 -0
  518. package/dist/frontend/lowering/sanitize-class-types.test.js +60 -0
  519. package/dist/frontend/lowering/sanitize-class-types.test.js.map +1 -0
  520. package/dist/frontend/lowering/static-this.d.ts +5 -1
  521. package/dist/frontend/lowering/static-this.js +28 -2
  522. package/dist/frontend/lowering/static-this.js.map +1 -1
  523. package/dist/frontend/lowering/string-index.d.ts +7 -0
  524. package/dist/frontend/lowering/string-index.js +39 -0
  525. package/dist/frontend/lowering/string-index.js.map +1 -0
  526. package/dist/frontend/lowering/surfaces.d.ts +8 -3
  527. package/dist/frontend/lowering/surfaces.js +61 -29
  528. package/dist/frontend/lowering/surfaces.js.map +1 -1
  529. package/dist/frontend/lowering/symbol-fields.d.ts +22 -0
  530. package/dist/frontend/lowering/symbol-fields.js +183 -0
  531. package/dist/frontend/lowering/symbol-fields.js.map +1 -0
  532. package/dist/frontend/lowering/symbol-methods.d.ts +7 -0
  533. package/dist/frontend/lowering/symbol-methods.js +30 -0
  534. package/dist/frontend/lowering/symbol-methods.js.map +1 -0
  535. package/dist/frontend/lowering/text-decoder-encoding.d.ts +10 -0
  536. package/dist/frontend/lowering/text-decoder-encoding.js +77 -0
  537. package/dist/frontend/lowering/text-decoder-encoding.js.map +1 -0
  538. package/dist/frontend/lowering/text-decoder-encoding.test.d.ts +1 -0
  539. package/dist/frontend/lowering/text-decoder-encoding.test.js +38 -0
  540. package/dist/frontend/lowering/text-decoder-encoding.test.js.map +1 -0
  541. package/dist/frontend/lowering/union-narrow.d.ts +9 -0
  542. package/dist/frontend/lowering/union-narrow.js +59 -0
  543. package/dist/frontend/lowering/union-narrow.js.map +1 -0
  544. package/dist/frontend/lowering/union-narrow.test.d.ts +1 -0
  545. package/dist/frontend/lowering/union-narrow.test.js +72 -0
  546. package/dist/frontend/lowering/union-narrow.test.js.map +1 -0
  547. package/dist/frontend/lowering/union-retag.d.ts +43 -0
  548. package/dist/frontend/lowering/union-retag.js +259 -0
  549. package/dist/frontend/lowering/union-retag.js.map +1 -0
  550. package/dist/frontend/lowering/union-retag.test.d.ts +1 -0
  551. package/dist/frontend/lowering/union-retag.test.js +405 -0
  552. package/dist/frontend/lowering/union-retag.test.js.map +1 -0
  553. package/dist/frontend/lowering/unregistered-class-types.d.ts +14 -0
  554. package/dist/frontend/lowering/unregistered-class-types.js +94 -0
  555. package/dist/frontend/lowering/unregistered-class-types.js.map +1 -0
  556. package/dist/frontend/lowering/unregistered-class-types.test.d.ts +1 -0
  557. package/dist/frontend/lowering/unregistered-class-types.test.js +65 -0
  558. package/dist/frontend/lowering/unregistered-class-types.test.js.map +1 -0
  559. package/dist/frontend/lowering/width-lift.d.ts +40 -0
  560. package/dist/frontend/lowering/width-lift.js +2 -0
  561. package/dist/frontend/lowering/width-lift.js.map +1 -0
  562. package/dist/frontend/module-syntax.d.ts +58 -0
  563. package/dist/frontend/module-syntax.js +123 -0
  564. package/dist/frontend/module-syntax.js.map +1 -0
  565. package/dist/frontend/module-syntax.test.d.ts +1 -0
  566. package/dist/frontend/module-syntax.test.js +78 -0
  567. package/dist/frontend/module-syntax.test.js.map +1 -0
  568. package/dist/frontend/npm-fetch-analysis.d.ts +17 -0
  569. package/dist/frontend/npm-fetch-analysis.js +100 -0
  570. package/dist/frontend/npm-fetch-analysis.js.map +1 -0
  571. package/dist/frontend/npm-fetch-analysis.test.d.ts +1 -0
  572. package/dist/frontend/npm-fetch-analysis.test.js +107 -0
  573. package/dist/frontend/npm-fetch-analysis.test.js.map +1 -0
  574. package/dist/frontend/npm-fetch-node.d.ts +2 -0
  575. package/dist/frontend/npm-fetch-node.js +12 -0
  576. package/dist/frontend/npm-fetch-node.js.map +1 -0
  577. package/dist/frontend/npm-fetch-syntax.d.ts +6 -0
  578. package/dist/frontend/npm-fetch-syntax.js +207 -0
  579. package/dist/frontend/npm-fetch-syntax.js.map +1 -0
  580. package/dist/frontend/npm-node.d.ts +10 -0
  581. package/dist/frontend/npm-node.js +14 -0
  582. package/dist/frontend/npm-node.js.map +1 -0
  583. package/dist/frontend/npm-static-bundled-cjs.d.ts +8 -0
  584. package/dist/frontend/npm-static-bundled-cjs.js +236 -0
  585. package/dist/frontend/npm-static-bundled-cjs.js.map +1 -0
  586. package/dist/frontend/npm-static-bundled-cjs.test.d.ts +1 -0
  587. package/dist/frontend/npm-static-bundled-cjs.test.js +69 -0
  588. package/dist/frontend/npm-static-bundled-cjs.test.js.map +1 -0
  589. package/dist/frontend/npm-static-declaration-syntax.d.ts +57 -0
  590. package/dist/frontend/npm-static-declaration-syntax.js +944 -0
  591. package/dist/frontend/npm-static-declaration-syntax.js.map +1 -0
  592. package/dist/frontend/npm-static-declarations.d.ts +11 -39
  593. package/dist/frontend/npm-static-declarations.js +22 -561
  594. package/dist/frontend/npm-static-declarations.js.map +1 -1
  595. package/dist/frontend/npm-static-declarations.test.js +245 -6
  596. package/dist/frontend/npm-static-declarations.test.js.map +1 -1
  597. package/dist/frontend/npm-static-prune.d.ts +1 -1
  598. package/dist/frontend/npm-static-prune.js +5 -4
  599. package/dist/frontend/npm-static-prune.js.map +1 -1
  600. package/dist/frontend/npm-static-prune.test.js +1 -1
  601. package/dist/frontend/npm-static-prune.test.js.map +1 -1
  602. package/dist/frontend/npm-static-rewrite-host.d.ts +4 -0
  603. package/dist/frontend/npm-static-rewrite-host.js +179 -0
  604. package/dist/frontend/npm-static-rewrite-host.js.map +1 -0
  605. package/dist/frontend/npm-static-rewrite-syntax.d.ts +16 -0
  606. package/dist/frontend/npm-static-rewrite-syntax.js +905 -0
  607. package/dist/frontend/npm-static-rewrite-syntax.js.map +1 -0
  608. package/dist/frontend/npm-static-rewrite.d.ts +0 -5
  609. package/dist/frontend/npm-static-rewrite.js +2 -1079
  610. package/dist/frontend/npm-static-rewrite.js.map +1 -1
  611. package/dist/frontend/npm-static-subtyping.d.ts +5 -0
  612. package/dist/frontend/npm-static-subtyping.js +55 -0
  613. package/dist/frontend/npm-static-subtyping.js.map +1 -0
  614. package/dist/frontend/npm-static-subtyping.test.d.ts +1 -0
  615. package/dist/frontend/npm-static-subtyping.test.js +58 -0
  616. package/dist/frontend/npm-static-subtyping.test.js.map +1 -0
  617. package/dist/frontend/npm-static.d.ts +7 -15
  618. package/dist/frontend/npm-static.js +19 -28
  619. package/dist/frontend/npm-static.js.map +1 -1
  620. package/dist/frontend/npm.d.ts +8 -69
  621. package/dist/frontend/npm.js +21 -361
  622. package/dist/frontend/npm.js.map +1 -1
  623. package/dist/frontend/npm.test.js +2 -2
  624. package/dist/frontend/npm.test.js.map +1 -1
  625. package/dist/frontend/pipeline-native.d.ts +6 -0
  626. package/dist/frontend/pipeline-native.js +32 -0
  627. package/dist/frontend/pipeline-native.js.map +1 -0
  628. package/dist/frontend/pipeline.d.ts +54 -0
  629. package/dist/frontend/pipeline.js +382 -0
  630. package/dist/frontend/pipeline.js.map +1 -0
  631. package/dist/frontend/pipeline.test.d.ts +1 -0
  632. package/dist/frontend/pipeline.test.js +77 -0
  633. package/dist/frontend/pipeline.test.js.map +1 -0
  634. package/dist/frontend/program-analysis.d.ts +10 -0
  635. package/dist/frontend/program-analysis.js +14 -0
  636. package/dist/frontend/program-analysis.js.map +1 -0
  637. package/dist/frontend/program-node.d.ts +9 -0
  638. package/dist/frontend/program-node.js +48 -0
  639. package/dist/frontend/program-node.js.map +1 -0
  640. package/dist/frontend/program.d.ts +38 -19
  641. package/dist/frontend/program.js +344 -169
  642. package/dist/frontend/program.js.map +1 -1
  643. package/dist/frontend/program.test.js +87 -2
  644. package/dist/frontend/program.test.js.map +1 -1
  645. package/dist/frontend/provenance-core.d.ts +9 -0
  646. package/dist/frontend/provenance-core.js +435 -0
  647. package/dist/frontend/provenance-core.js.map +1 -0
  648. package/dist/frontend/provenance.d.ts +0 -4
  649. package/dist/frontend/provenance.js +4 -459
  650. package/dist/frontend/provenance.js.map +1 -1
  651. package/dist/frontend/resolve.d.ts +3 -1
  652. package/dist/frontend/resolve.js +6 -3
  653. package/dist/frontend/resolve.js.map +1 -1
  654. package/dist/frontend/runtime-resolve.d.ts +4 -3
  655. package/dist/frontend/runtime-resolve.js +22 -18
  656. package/dist/frontend/runtime-resolve.js.map +1 -1
  657. package/dist/frontend/runtime-resolve.test.js +53 -0
  658. package/dist/frontend/runtime-resolve.test.js.map +1 -1
  659. package/dist/frontend/services-node.d.ts +5 -0
  660. package/dist/frontend/services-node.js +19 -0
  661. package/dist/frontend/services-node.js.map +1 -0
  662. package/dist/frontend/services-node.test.d.ts +1 -0
  663. package/dist/frontend/services-node.test.js +70 -0
  664. package/dist/frontend/services-node.test.js.map +1 -0
  665. package/dist/frontend/services.d.ts +44 -0
  666. package/dist/frontend/services.js +90 -0
  667. package/dist/frontend/services.js.map +1 -0
  668. package/dist/frontend/services.test.d.ts +1 -0
  669. package/dist/frontend/services.test.js +174 -0
  670. package/dist/frontend/services.test.js.map +1 -0
  671. package/dist/frontend/ts7/adapter.d.ts +3 -3
  672. package/dist/frontend/ts7/adapter.js +14 -31
  673. package/dist/frontend/ts7/adapter.js.map +1 -1
  674. package/dist/frontend/ts7/api.d.ts +16 -0
  675. package/dist/frontend/ts7/api.js +24 -0
  676. package/dist/frontend/ts7/api.js.map +1 -0
  677. package/dist/frontend/ts7/ast-bytes.d.ts +31 -0
  678. package/dist/frontend/ts7/ast-bytes.js +137 -0
  679. package/dist/frontend/ts7/ast-bytes.js.map +1 -0
  680. package/dist/frontend/ts7/ast-bytes.test.d.ts +1 -0
  681. package/dist/frontend/ts7/ast-bytes.test.js +73 -0
  682. package/dist/frontend/ts7/ast-bytes.test.js.map +1 -0
  683. package/dist/frontend/ts7/ast-guards.generated.d.ts +353 -0
  684. package/dist/frontend/ts7/ast-guards.generated.js +1951 -0
  685. package/dist/frontend/ts7/ast-guards.generated.js.map +1 -0
  686. package/dist/frontend/ts7/ast-guards.test.d.ts +1 -0
  687. package/dist/frontend/ts7/ast-guards.test.js +43 -0
  688. package/dist/frontend/ts7/ast-guards.test.js.map +1 -0
  689. package/dist/frontend/ts7/ast-node.d.ts +194 -0
  690. package/dist/frontend/ts7/ast-node.js +448 -0
  691. package/dist/frontend/ts7/ast-node.js.map +1 -0
  692. package/dist/frontend/ts7/ast-node.test.d.ts +1 -0
  693. package/dist/frontend/ts7/ast-node.test.js +266 -0
  694. package/dist/frontend/ts7/ast-node.test.js.map +1 -0
  695. package/dist/frontend/ts7/ast-schema.generated.d.ts +503 -0
  696. package/dist/frontend/ts7/ast-schema.generated.js +1446 -0
  697. package/dist/frontend/ts7/ast-schema.generated.js.map +1 -0
  698. package/dist/frontend/ts7/ast-text.d.ts +6 -0
  699. package/dist/frontend/ts7/ast-text.js +124 -0
  700. package/dist/frontend/ts7/ast-text.js.map +1 -0
  701. package/dist/frontend/ts7/ast-text.test.d.ts +1 -0
  702. package/dist/frontend/ts7/ast-text.test.js +38 -0
  703. package/dist/frontend/ts7/ast-text.test.js.map +1 -0
  704. package/dist/frontend/ts7/ast-tokens.generated.d.ts +2 -0
  705. package/dist/frontend/ts7/ast-tokens.generated.js +155 -0
  706. package/dist/frontend/ts7/ast-tokens.generated.js.map +1 -0
  707. package/dist/frontend/ts7/ast-types.d.ts +42 -0
  708. package/dist/frontend/ts7/ast-types.generated.d.ts +1615 -0
  709. package/dist/frontend/ts7/ast-types.generated.js +5 -0
  710. package/dist/frontend/ts7/ast-types.generated.js.map +1 -0
  711. package/dist/frontend/ts7/ast-types.js +3 -0
  712. package/dist/frontend/ts7/ast-types.js.map +1 -0
  713. package/dist/frontend/ts7/ast-wire.d.ts +58 -0
  714. package/dist/frontend/ts7/ast-wire.js +267 -0
  715. package/dist/frontend/ts7/ast-wire.js.map +1 -0
  716. package/dist/frontend/ts7/ast-wire.test.d.ts +1 -0
  717. package/dist/frontend/ts7/ast-wire.test.js +151 -0
  718. package/dist/frontend/ts7/ast-wire.test.js.map +1 -0
  719. package/dist/frontend/ts7/ast.d.ts +14 -14
  720. package/dist/frontend/ts7/ast.js +21 -15
  721. package/dist/frontend/ts7/ast.js.map +1 -1
  722. package/dist/frontend/ts7/census-check.js +1 -0
  723. package/dist/frontend/ts7/census-check.js.map +1 -1
  724. package/dist/frontend/ts7/checker-cache.d.ts +48 -0
  725. package/dist/frontend/ts7/checker-cache.js +92 -0
  726. package/dist/frontend/ts7/checker-cache.js.map +1 -0
  727. package/dist/frontend/ts7/checker.d.ts +19 -46
  728. package/dist/frontend/ts7/checker.js +231 -161
  729. package/dist/frontend/ts7/checker.js.map +1 -1
  730. package/dist/frontend/ts7/checker.test.d.ts +1 -0
  731. package/dist/frontend/ts7/checker.test.js +335 -0
  732. package/dist/frontend/ts7/checker.test.js.map +1 -0
  733. package/dist/frontend/ts7/enums.d.ts +4 -27
  734. package/dist/frontend/ts7/enums.generated.d.ts +878 -0
  735. package/dist/frontend/ts7/enums.generated.js +1313 -0
  736. package/dist/frontend/ts7/enums.generated.js.map +1 -0
  737. package/dist/frontend/ts7/enums.js +4 -45
  738. package/dist/frontend/ts7/enums.js.map +1 -1
  739. package/dist/frontend/ts7/enums.test.d.ts +1 -0
  740. package/dist/frontend/ts7/enums.test.js +48 -0
  741. package/dist/frontend/ts7/enums.test.js.map +1 -0
  742. package/dist/frontend/ts7/native-api.d.ts +10 -0
  743. package/dist/frontend/ts7/native-api.js +10 -0
  744. package/dist/frontend/ts7/native-api.js.map +1 -0
  745. package/dist/frontend/ts7/native-host.d.ts +2 -0
  746. package/dist/frontend/ts7/native-host.js +11 -0
  747. package/dist/frontend/ts7/native-host.js.map +1 -0
  748. package/dist/frontend/ts7/native-process.d.ts +14 -0
  749. package/dist/frontend/ts7/native-process.js +62 -0
  750. package/dist/frontend/ts7/native-process.js.map +1 -0
  751. package/dist/frontend/ts7/program-adapter.d.ts +10 -98
  752. package/dist/frontend/ts7/program-adapter.js +16 -310
  753. package/dist/frontend/ts7/program-adapter.js.map +1 -1
  754. package/dist/frontend/ts7/program-host.d.ts +115 -0
  755. package/dist/frontend/ts7/program-host.js +347 -0
  756. package/dist/frontend/ts7/program-host.js.map +1 -0
  757. package/dist/frontend/ts7/program-host.test.d.ts +1 -0
  758. package/dist/frontend/ts7/program-host.test.js +207 -0
  759. package/dist/frontend/ts7/program-host.test.js.map +1 -0
  760. package/dist/frontend/ts7/rpc-api.d.ts +12 -0
  761. package/dist/frontend/ts7/rpc-api.js +23 -0
  762. package/dist/frontend/ts7/rpc-api.js.map +1 -0
  763. package/dist/frontend/ts7/rpc-client.d.ts +27 -0
  764. package/dist/frontend/ts7/rpc-client.js +102 -0
  765. package/dist/frontend/ts7/rpc-client.js.map +1 -0
  766. package/dist/frontend/ts7/rpc-client.test.d.ts +1 -0
  767. package/dist/frontend/ts7/rpc-client.test.js +133 -0
  768. package/dist/frontend/ts7/rpc-client.test.js.map +1 -0
  769. package/dist/frontend/ts7/rpc-filesystem.d.ts +16 -0
  770. package/dist/frontend/ts7/rpc-filesystem.js +42 -0
  771. package/dist/frontend/ts7/rpc-filesystem.js.map +1 -0
  772. package/dist/frontend/ts7/rpc-filesystem.test.d.ts +1 -0
  773. package/dist/frontend/ts7/rpc-filesystem.test.js +89 -0
  774. package/dist/frontend/ts7/rpc-filesystem.test.js.map +1 -0
  775. package/dist/frontend/ts7/rpc-process.d.ts +2 -0
  776. package/dist/frontend/ts7/rpc-process.js +148 -0
  777. package/dist/frontend/ts7/rpc-process.js.map +1 -0
  778. package/dist/frontend/ts7/rpc-process.test.d.ts +1 -0
  779. package/dist/frontend/ts7/rpc-process.test.js +29 -0
  780. package/dist/frontend/ts7/rpc-process.test.js.map +1 -0
  781. package/dist/frontend/ts7/rpc-wire.d.ts +46 -0
  782. package/dist/frontend/ts7/rpc-wire.js +195 -0
  783. package/dist/frontend/ts7/rpc-wire.js.map +1 -0
  784. package/dist/frontend/ts7/rpc-wire.test.d.ts +1 -0
  785. package/dist/frontend/ts7/rpc-wire.test.js +168 -0
  786. package/dist/frontend/ts7/rpc-wire.test.js.map +1 -0
  787. package/dist/frontend/ts7/semantic-checker.d.ts +137 -0
  788. package/dist/frontend/ts7/semantic-checker.js +221 -0
  789. package/dist/frontend/ts7/semantic-checker.js.map +1 -0
  790. package/dist/frontend/ts7/semantic-checker.test.d.ts +1 -0
  791. package/dist/frontend/ts7/semantic-checker.test.js +119 -0
  792. package/dist/frontend/ts7/semantic-checker.test.js.map +1 -0
  793. package/dist/frontend/ts7/semantic-json.d.ts +5 -0
  794. package/dist/frontend/ts7/semantic-json.js +52 -0
  795. package/dist/frontend/ts7/semantic-json.js.map +1 -0
  796. package/dist/frontend/ts7/semantic-json.test.d.ts +1 -0
  797. package/dist/frontend/ts7/semantic-json.test.js +42 -0
  798. package/dist/frontend/ts7/semantic-json.test.js.map +1 -0
  799. package/dist/frontend/ts7/semantic-model.d.ts +222 -0
  800. package/dist/frontend/ts7/semantic-model.js +423 -0
  801. package/dist/frontend/ts7/semantic-model.js.map +1 -0
  802. package/dist/frontend/ts7/semantic-model.test.d.ts +1 -0
  803. package/dist/frontend/ts7/semantic-model.test.js +322 -0
  804. package/dist/frontend/ts7/semantic-model.test.js.map +1 -0
  805. package/dist/frontend/ts7/semantic-schema.generated.d.ts +283 -0
  806. package/dist/frontend/ts7/semantic-schema.generated.js +222 -0
  807. package/dist/frontend/ts7/semantic-schema.generated.js.map +1 -0
  808. package/dist/frontend/ts7/semantic-types.d.ts +5 -0
  809. package/dist/frontend/ts7/semantic-types.js +2 -0
  810. package/dist/frontend/ts7/semantic-types.js.map +1 -0
  811. package/dist/frontend/ts7/session-cache.d.ts +17 -0
  812. package/dist/frontend/ts7/session-cache.js +97 -0
  813. package/dist/frontend/ts7/session-cache.js.map +1 -0
  814. package/dist/frontend/ts7/session-cache.test.d.ts +1 -0
  815. package/dist/frontend/ts7/session-cache.test.js +87 -0
  816. package/dist/frontend/ts7/session-cache.test.js.map +1 -0
  817. package/dist/frontend/ts7/session-path.d.ts +18 -0
  818. package/dist/frontend/ts7/session-path.js +203 -0
  819. package/dist/frontend/ts7/session-path.js.map +1 -0
  820. package/dist/frontend/ts7/session-path.test.d.ts +1 -0
  821. package/dist/frontend/ts7/session-path.test.js +34 -0
  822. package/dist/frontend/ts7/session-path.test.js.map +1 -0
  823. package/dist/frontend/ts7/session-schema.generated.d.ts +167 -0
  824. package/dist/frontend/ts7/session-schema.generated.js +5 -0
  825. package/dist/frontend/ts7/session-schema.generated.js.map +1 -0
  826. package/dist/frontend/ts7/session-timing.d.ts +50 -0
  827. package/dist/frontend/ts7/session-timing.js +61 -0
  828. package/dist/frontend/ts7/session-timing.js.map +1 -0
  829. package/dist/frontend/ts7/session-timing.test.d.ts +1 -0
  830. package/dist/frontend/ts7/session-timing.test.js +52 -0
  831. package/dist/frontend/ts7/session-timing.test.js.map +1 -0
  832. package/dist/frontend/ts7/session.d.ts +105 -0
  833. package/dist/frontend/ts7/session.js +233 -0
  834. package/dist/frontend/ts7/session.js.map +1 -0
  835. package/dist/frontend/ts7/session.test.d.ts +1 -0
  836. package/dist/frontend/ts7/session.test.js +215 -0
  837. package/dist/frontend/ts7/session.test.js.map +1 -0
  838. package/dist/frontend/ts7/source-parser-node.d.ts +6 -0
  839. package/dist/frontend/ts7/source-parser-node.js +15 -0
  840. package/dist/frontend/ts7/source-parser-node.js.map +1 -0
  841. package/dist/frontend/ts7/source-parser.d.ts +25 -0
  842. package/dist/frontend/ts7/source-parser.js +96 -0
  843. package/dist/frontend/ts7/source-parser.js.map +1 -0
  844. package/dist/frontend/ts7/source-parser.test.d.ts +1 -0
  845. package/dist/frontend/ts7/source-parser.test.js +151 -0
  846. package/dist/frontend/ts7/source-parser.test.js.map +1 -0
  847. package/dist/frontend/ts7/syntax.d.ts +3 -0
  848. package/dist/frontend/ts7/syntax.js +4 -0
  849. package/dist/frontend/ts7/syntax.js.map +1 -0
  850. package/dist/frontend/tsc-codes.js +3 -0
  851. package/dist/frontend/tsc-codes.js.map +1 -1
  852. package/dist/frontend/type-mapper.d.ts +25 -17
  853. package/dist/frontend/type-mapper.js +465 -121
  854. package/dist/frontend/type-mapper.js.map +1 -1
  855. package/dist/frontend/type-mapper.test.js +123 -2
  856. package/dist/frontend/type-mapper.test.js.map +1 -1
  857. package/dist/frontend/union-discriminants.d.ts +16 -0
  858. package/dist/frontend/union-discriminants.js +98 -0
  859. package/dist/frontend/union-discriminants.js.map +1 -0
  860. package/dist/frontend/union-discriminants.test.d.ts +1 -0
  861. package/dist/frontend/union-discriminants.test.js +182 -0
  862. package/dist/frontend/union-discriminants.test.js.map +1 -0
  863. package/dist/index.d.ts +7 -198
  864. package/dist/index.js +369 -1572
  865. package/dist/index.js.map +1 -1
  866. package/dist/ir/analysis.d.ts +16 -4
  867. package/dist/ir/analysis.js +21 -4
  868. package/dist/ir/analysis.js.map +1 -1
  869. package/dist/ir/analysis.test.js +15 -2
  870. package/dist/ir/analysis.test.js.map +1 -1
  871. package/dist/ir/constant-tables.js +67 -49
  872. package/dist/ir/constant-tables.js.map +1 -1
  873. package/dist/ir/constant-tables.test.js +1 -1
  874. package/dist/ir/control-flow.d.ts +6 -0
  875. package/dist/ir/control-flow.js +142 -0
  876. package/dist/ir/control-flow.js.map +1 -0
  877. package/dist/ir/control-flow.test.d.ts +1 -0
  878. package/dist/ir/control-flow.test.js +113 -0
  879. package/dist/ir/control-flow.test.js.map +1 -0
  880. package/dist/ir/integer-loops.js +7 -18
  881. package/dist/ir/integer-loops.js.map +1 -1
  882. package/dist/ir/integer-ranges.js +53 -27
  883. package/dist/ir/integer-ranges.js.map +1 -1
  884. package/dist/ir/ir.d.ts +291 -152
  885. package/dist/ir/ir.js +588 -881
  886. package/dist/ir/ir.js.map +1 -1
  887. package/dist/ir/ir.test.js +127 -1
  888. package/dist/ir/ir.test.js.map +1 -1
  889. package/dist/ir/scalar-records.js +165 -134
  890. package/dist/ir/scalar-records.js.map +1 -1
  891. package/dist/ir/scalar-records.test.js +1 -1
  892. package/dist/ir/serialize.d.ts +4 -2
  893. package/dist/ir/serialize.js +19 -12
  894. package/dist/ir/serialize.js.map +1 -1
  895. package/dist/ir/serialize.test.d.ts +1 -0
  896. package/dist/ir/serialize.test.js +53 -0
  897. package/dist/ir/serialize.test.js.map +1 -0
  898. package/dist/ir/traverse.d.ts +41 -0
  899. package/dist/ir/traverse.js +660 -0
  900. package/dist/ir/traverse.js.map +1 -0
  901. package/dist/ir/traverse.test.d.ts +1 -0
  902. package/dist/ir/traverse.test.js +242 -0
  903. package/dist/ir/traverse.test.js.map +1 -0
  904. package/dist/ir/validate.js +1942 -1491
  905. package/dist/ir/validate.js.map +1 -1
  906. package/dist/ir/validate.test.js +476 -2
  907. package/dist/ir/validate.test.js.map +1 -1
  908. package/dist/library/cache-primitives.d.ts +2 -3
  909. package/dist/library/cache-primitives.js +4 -6
  910. package/dist/library/cache-primitives.js.map +1 -1
  911. package/dist/library/fence-eval.js +2 -2
  912. package/dist/library/fence-eval.js.map +1 -1
  913. package/dist/library/int-infer.js +7 -6
  914. package/dist/library/int-infer.js.map +1 -1
  915. package/dist/library/int-infer.test.js +4 -4
  916. package/dist/library/library-cache.d.ts +3 -2
  917. package/dist/library/library-cache.js +5 -17
  918. package/dist/library/library-cache.js.map +1 -1
  919. package/dist/library/library-cache.test.js +54 -41
  920. package/dist/library/library-cache.test.js.map +1 -1
  921. package/dist/library/library-profile.d.ts +3 -1
  922. package/dist/library/library-profile.js +15 -6
  923. package/dist/library/library-profile.js.map +1 -1
  924. package/dist/library/prepare.d.ts +15 -0
  925. package/dist/library/prepare.js +584 -0
  926. package/dist/library/prepare.js.map +1 -0
  927. package/dist/library/semantic-source.d.ts +1 -1
  928. package/dist/library/semantic-source.js +8 -6
  929. package/dist/library/semantic-source.js.map +1 -1
  930. package/dist/library/sidecar-validate.js +4 -4
  931. package/dist/library/sidecar-validate.js.map +1 -1
  932. package/dist/library/sidecar.d.ts +2 -0
  933. package/dist/library/sidecar.js +10 -3
  934. package/dist/library/sidecar.js.map +1 -1
  935. package/dist/native/cache.d.ts +11 -0
  936. package/dist/native/cache.js +113 -0
  937. package/dist/native/cache.js.map +1 -0
  938. package/dist/native/cache.test.d.ts +1 -0
  939. package/dist/native/cache.test.js +66 -0
  940. package/dist/native/cache.test.js.map +1 -0
  941. package/dist/native/cli.d.ts +1 -0
  942. package/dist/native/cli.js +112 -0
  943. package/dist/native/cli.js.map +1 -0
  944. package/dist/native/compiler.d.ts +15 -0
  945. package/dist/native/compiler.js +336 -0
  946. package/dist/native/compiler.js.map +1 -0
  947. package/dist/native/compiler.test.d.ts +1 -0
  948. package/dist/native/compiler.test.js +174 -0
  949. package/dist/native/compiler.test.js.map +1 -0
  950. package/dist/native/comptime.d.ts +5 -0
  951. package/dist/native/comptime.js +73 -0
  952. package/dist/native/comptime.js.map +1 -0
  953. package/dist/native/comptime.test.d.ts +1 -0
  954. package/dist/native/comptime.test.js +65 -0
  955. package/dist/native/comptime.test.js.map +1 -0
  956. package/dist/native/executable-cache.d.ts +26 -0
  957. package/dist/native/executable-cache.js +228 -0
  958. package/dist/native/executable-cache.js.map +1 -0
  959. package/dist/native/executable-cache.test.d.ts +1 -0
  960. package/dist/native/executable-cache.test.js +151 -0
  961. package/dist/native/executable-cache.test.js.map +1 -0
  962. package/dist/native/file-identity.d.ts +4 -0
  963. package/dist/native/file-identity.js +14 -0
  964. package/dist/native/file-identity.js.map +1 -0
  965. package/dist/native/file-identity.test.d.ts +1 -0
  966. package/dist/native/file-identity.test.js +43 -0
  967. package/dist/native/file-identity.test.js.map +1 -0
  968. package/dist/native/library.d.ts +22 -0
  969. package/dist/native/library.js +83 -0
  970. package/dist/native/library.js.map +1 -0
  971. package/dist/native/prepare.d.ts +21 -0
  972. package/dist/native/prepare.js +174 -0
  973. package/dist/native/prepare.js.map +1 -0
  974. package/dist/native/prepare.test.d.ts +1 -0
  975. package/dist/native/prepare.test.js +70 -0
  976. package/dist/native/prepare.test.js.map +1 -0
  977. package/dist/native/sanitizer.d.ts +11 -0
  978. package/dist/native/sanitizer.js +135 -0
  979. package/dist/native/sanitizer.js.map +1 -0
  980. package/dist/native/sanitizer.test.d.ts +1 -0
  981. package/dist/native/sanitizer.test.js +58 -0
  982. package/dist/native/sanitizer.test.js.map +1 -0
  983. package/dist/native/task.d.ts +4 -0
  984. package/dist/native/task.js +16 -0
  985. package/dist/native/task.js.map +1 -0
  986. package/dist/native/task.test.d.ts +1 -0
  987. package/dist/native/task.test.js +17 -0
  988. package/dist/native/task.test.js.map +1 -0
  989. package/dist/native/toolchain.d.ts +45 -0
  990. package/dist/native/toolchain.js +74 -0
  991. package/dist/native/toolchain.js.map +1 -0
  992. package/dist/native/toolchain.test.d.ts +1 -0
  993. package/dist/native/toolchain.test.js +33 -0
  994. package/dist/native/toolchain.test.js.map +1 -0
  995. package/dist/startup-cache.d.ts +1 -1
  996. package/dist/startup-cache.js +2 -5
  997. package/dist/startup-cache.js.map +1 -1
  998. package/dist/timing.d.ts +4 -0
  999. package/dist/timing.js +19 -0
  1000. package/dist/timing.js.map +1 -0
  1001. package/dist/wasi-paths.js +10 -7
  1002. package/dist/wasi-paths.js.map +1 -1
  1003. package/package.json +28 -19
  1004. package/surface-manifest.json +52 -18
  1005. package/dist/backend/c/async.d.ts +0 -171
  1006. package/dist/backend/c/async.js +0 -1317
  1007. package/dist/backend/c/async.js.map +0 -1
  1008. package/dist/backend/c/c-emitter.d.ts +0 -536
  1009. package/dist/backend/c/c-emitter.js +0 -1932
  1010. package/dist/backend/c/c-emitter.js.map +0 -1
  1011. package/dist/backend/c/exprs.d.ts +0 -15
  1012. package/dist/backend/c/exprs.js +0 -8847
  1013. package/dist/backend/c/exprs.js.map +0 -1
  1014. package/dist/backend/c/island.d.ts +0 -45
  1015. package/dist/backend/c/island.js +0 -281
  1016. package/dist/backend/c/island.js.map +0 -1
  1017. package/dist/backend/c/may-throw.js.map +0 -1
  1018. package/dist/backend/c/shapes.d.ts +0 -142
  1019. package/dist/backend/c/shapes.js +0 -603
  1020. package/dist/backend/c/shapes.js.map +0 -1
  1021. package/dist/backend/c/stmts.d.ts +0 -76
  1022. package/dist/backend/c/stmts.js +0 -1108
  1023. package/dist/backend/c/stmts.js.map +0 -1
  1024. package/dist/backend/c/types.d.ts +0 -71
  1025. package/dist/backend/c/types.js +0 -459
  1026. package/dist/backend/c/types.js.map +0 -1
  1027. package/dist/backend/c/types.test.js +0 -32
  1028. package/dist/backend/c/types.test.js.map +0 -1
  1029. package/dist/backend/c/walkers.d.ts +0 -134
  1030. package/dist/backend/c/walkers.js +0 -1772
  1031. package/dist/backend/c/walkers.js.map +0 -1
  1032. /package/dist/backend/{c/types.test.d.ts → cycle-analysis.test.d.ts} +0 -0
@@ -1,28 +1,34 @@
1
+ import { objectEnumerationReceiver } from "./object-enumeration-receiver.js";
1
2
  import { InternalCompilerError } from "../../errors.js";
2
3
  /* Call lowering: the lowerCall dispatch chain, parameter-shape analysis and
3
4
  * argument completion (optional/default/rest, explicit-undefined ≡ omission),
4
5
  * function/lambda lowering and signature collection, and monomorphizing
5
6
  * generic instantiation (bounded by MAX_GENERIC_INSTANCES). */
6
7
  import * as ts from "../ts7/adapter.js";
8
+ import { AstNode } from "../ts7/ast-node.js";
7
9
  import { bodyReadsArguments } from "../arguments-usage.js";
8
10
  import { lowerGenMethodCall } from "./lower-generators.js";
9
- import { BIGINT_T, BOOL, CAUGHT, DYN, F64, JSVAL, STRING, SYMBOL_T, UNDEFINED_T, VOID, arrayOf, canBoxFuncIntoDyn, canConvertToDyn, canDynCheckTo, canMarshalTypedFuncIntoIsland, ffiClassType, ffiSourceParamTypes, funcOf, isFfiCallbackParam, isFfiContextParam, isFfiReleaseParam, isUnitType, shapeHasAccessorSlots, typeEquals } from "../../ir/ir.js";
10
- import { isJsSourceFile, isNodeEsmFile, locOf } from "../program.js";
11
- import { genResultRecord, isGenericCallableMemberType, typeKey } from "../type-mapper.js";
11
+ import { lowerClassSymbolMethodCall } from "./symbol-methods.js";
12
+ import { errorToStringCall } from "./error-methods.js";
13
+ import { lowerClassPrototypeAssign } from "./class-prototypes.js";
14
+ import { BYTES_ELEMENT_NAME, BIGINT_T, BOOL, CAUGHT, DYN, F64, JSVAL, NULL_T, STRING, SYMBOL_T, UNDEFINED_T, VOID, arrayOf, canBoxFuncIntoDyn, canConvertToDyn, canDynCheckTo, canMarshalTypedFuncIntoIsland, ffiClassType, ffiSourceParamTypes, funcOf, isDynTypedRefType, isFfiCallbackParam, isFfiContextParam, isFfiReleaseParam, isUnitType, shapeHasAccessorSlots, typeEquals } from "../../ir/ir.js";
15
+ import { isJsSourceFile, isNodeEsmFile, locOf, requireSpecOf } from "../program.js";
16
+ import { genResultRecord, isGenericCallableMemberType, jsOpenObjectType, typeKey } from "../type-mapper.js";
12
17
  import { PoisonError, dynFallbackType, dynUndefinedExpr, importCallHandleType, jsFuncNameOf, newFnCtx, nodeThrowExpr, staticImportNamespaceType } from "./lowerer.js";
13
18
  import { enforceLibBoundary } from "./lib-boundary.js";
14
19
  import { NARROW_FIRST, STRING_INDEX_METHODS, STR_METHODS, builtinFenceHintOf, builtinModuleFnOf } from "./surfaces.js";
15
20
  import { ffiBindingDiag, ffiSignatureDiag, libCallbackDiag, requiresDynamicDiag } from "../../diagnostics/diagnostic.js";
16
21
  import { mixinFnShapeOf } from "./lower-mixins.js";
17
22
  import { dynStringReceiver, lowerArrayConstructor, lowerArrayFromCall, lowerArrayOfCall, lowerDynArrayFilterCall, lowerDynArrayFlatMapCall, lowerGroupByStaticCall, lowerIteratorHelperCall, lowerObjectAssignIndexShape, lowerObjectFromEntriesCall, lowerObjectIterOverIndexShape, lowerTupleReadMethodCall } from "./lower-containers.js";
18
- import { bufEncoding } from "./containers/bytes.js";
23
+ import { lowerBytesStaticCall } from "./containers/bytes.js";
19
24
  import { lowerRegexMethodCall, lowerStringIndexCall, lowerStringMethodCall, lowerStringPaddingCall, lowerStringSplitCall } from "./containers/string-and-regexp.js";
20
- import { lowerChildStreamMethodCall, lowerChildWriterMethodCall, lowerCreateRequireCall, lowerCryptoHashMethodCall, lowerDirentMethodCall, lowerFileHandleMethodCall, lowerImportMetaResolveCall, lowerNodeModuleCall, lowerPerfHooksCall, lowerProcStreamMethodCall, lowerReflectApplyCall, lowerRequireResolveCall, lowerWatcherMethodCall } from "./lower-builtins.js";
25
+ import { createRequireSpecOf, lowerChildStreamMethodCall, lowerChildWriterMethodCall, lowerCreateRequireCall, lowerCryptoHashMethodCall, lowerDirentMethodCall, lowerFileHandleMethodCall, lowerImportMetaResolveCall, lowerNodeModuleCall, lowerPerfHooksCall, lowerProcStreamMethodCall, lowerReflectApplyCall, lowerRequireResolveCall, lowerWatcherMethodCall } from "./lower-builtins.js";
21
26
  import { lowerAbsenceProbe, lowerPromiseAllTupleCall, lowerPromiseRejectCall, stringWrapperToString, templateRawTextOf } from "./lower-exprs.js";
22
27
  import { isSafeToDiscard } from "./expressions/evaluation-safety.js";
23
28
  import { tryLowerExpression } from "./expressions/try-lower-expression.js";
24
29
  import { httpClientFnBindingOf, isStreamUndefCallExpr, lowerCompatReqStreamOptionalCall, lowerHttpClientFnCall } from "./lower-server.js";
25
- import { EMITTER_API_MEMBERS, exactInstanceClassOf, findGenericMethodOn, lowerClassGenericMethodCall, lowerStaticMethodCall } from "./lower-classes.js";
30
+ import { EMITTER_API_MEMBERS, exactInstanceClassOf, findGenericMethodOn, lowerClassGenericMethodCall, lowerStaticMethodCall, returnsOnlyThis } from "./lower-classes.js";
31
+ import { classCallbackCall, isClassCallback } from "./class-callbacks.js";
26
32
  import { emitterRooted, lowerEmitterMethodCall } from "./lower-event-emitter.js";
27
33
  import { lowerConsoleInspectArg, lowerFormatCall } from "./lower-inspect.js";
28
34
  import { STREAM_API_MEMBERS, lowerStreamMethodCall, lowerStreamModuleCall, lowerStreamStaticCall, streamSidesOf } from "./lower-stream.js";
@@ -30,10 +36,13 @@ import { ambientNsRootOf, ambientUndefReadType, ambientUndefVarRootOf, ambientUn
30
36
  import { declSymbolOf } from "./lower-modules.js";
31
37
  import { expandoMemberRead } from "./lower-expando.js";
32
38
  import { npmStaticPackageOfPath } from "../npm-static.js";
33
- import { countedFor, varRef } from "../../ir/build.js";
39
+ import { countedFor, numLit, varRef } from "../../ir/build.js";
34
40
  import { rejectStaticThis } from "./static-this.js";
35
41
  import { fenceNodeModuleMutationCall, lowerRequireCacheKeys } from "./lower-node-module.js";
36
42
  import { defaultAfterUndefined, lowerOptionalArgument, lowerStaticallyUndefinedArgument, positionNumber } from "./optional-arguments.js";
43
+ import { fenceSymbolFieldCopy } from "./symbol-fields.js";
44
+ import { lowerClassDataDescriptor, lowerClassDescriptorRead } from "./class-descriptors.js";
45
+ import { classStaticDataFor } from "./class-static-data.js";
37
46
  export { bodyReadsArguments };
38
47
  /** The one func-type projection of completed parameter shapes. Typed rest
39
48
  * parameters keep their packed array as the trailing native ABI slot and
@@ -51,11 +60,7 @@ export function funcTypeFromParamShapes(shapes, ret) {
51
60
  ret,
52
61
  ...(typedRest || dynRest || islandRest || argumentsAll ? { rest: true } : {}),
53
62
  ...(argumentsAll ? { argumentsAll: true } : {}),
54
- ...(typedRest
55
- ? { restAbi: "typed" }
56
- : islandRest
57
- ? { restAbi: "jsval" }
58
- : {}),
63
+ ...(typedRest || islandRest ? { restAbi: typedRest ? "typed" : "jsval" } : {}),
59
64
  };
60
65
  }
61
66
  /** Registers `const alias = overloadedDeclaration` as a compile-time
@@ -118,6 +123,11 @@ export const MAX_GENERIC_INSTANCES = 100;
118
123
  * - `...xs: T[]`: the ABI type is the array; call sites pack the surplus.
119
124
  */
120
125
  export function paramShape(lowerer, param) {
126
+ if (lowerer.checkedCallbackParams.has(param)) {
127
+ return param.initializer
128
+ ? { type: DYN, mode: "omittable", bodyType: DYN }
129
+ : { type: DYN, mode: "required" };
130
+ }
121
131
  const moduleNs = lowerer.moduleNsParamOverrides.get(param);
122
132
  if (moduleNs !== undefined) {
123
133
  return { type: moduleNs, mode: param.questionToken ? "omittable" : "required" };
@@ -159,21 +169,7 @@ export function paramShape(lowerer, param) {
159
169
  // default when the argument was omitted or undefined, then the
160
170
  // pattern destructures the picked value (declareParams).
161
171
  const raw = lowerer.irTypeOf(param.name);
162
- // A DYNAMIC-TIER pattern source (`function f({} = a)` with
163
- // `a: any` — jsval for island values, dyn for the checked-dynamic
164
- // dyn): the slot holds its tier's undefined DIRECTLY, so the ABI
165
- // is the slot itself — no synthesized union; the prologue tests
166
- // undefined at runtime (declareParams).
167
- if (raw.kind === "dyn" || raw.kind === "jsval") {
168
- return { type: raw, mode: "omittable", bodyType: raw };
169
- }
170
- const bodyType = lowerer.stripUndefinedArm(raw);
171
- lowerer.checkDefaultParamBodyType(param, bodyType);
172
- const abi = bodyType.kind === "union" ? lowerer.withUndefinedArmOf(bodyType) : lowerer.withUndefinedArm(bodyType);
173
- if (!abi) {
174
- lowerer.badType(param.name, lowerer.typeOf(param.name)); // defensive: unknown union id
175
- }
176
- return { type: abi, mode: "omittable", bodyType };
172
+ return defaultParameterShape(lowerer, param, raw);
177
173
  }
178
174
  return { type: lowerer.runtimeOptionalBindingType(param.name, lowerer.irTypeOf(param.name)), mode: "required" };
179
175
  }
@@ -207,41 +203,12 @@ export function paramShape(lowerer, param) {
207
203
  }
208
204
  if (param.initializer) {
209
205
  const raw = lowerer.irTypeOf(param.name);
210
- // A DYNAMIC-TIER defaulted param (`function f(x = a)` with `a: any`
211
- // — tsc types x any; jsval for island values, dyn for the checked-
212
- // dynamic dyn): the slot holds its tier's undefined directly, so
213
- // the ABI is the slot itself and the prologue's default test is the
214
- // runtime undefined test (declareParams).
215
- if (raw.kind === "dyn" || raw.kind === "jsval") {
216
- return { type: raw, mode: "omittable", bodyType: raw };
217
- }
218
- // A default that may ITSELF be undefined (`x = process.env.FOO`):
219
- // tsc keeps undefined in the body's type, so there is nothing to
220
- // narrow — the ABI union IS the body type and the prologue passes a
221
- // present argument through unchanged (declareParams's pass-through
222
- // branch). The generic strip-and-narrow below would demand a
223
- // `string`-typed default and fence on the union re-tag.
224
- if (lowerer.bareUndefinedArmedUnion(raw)) {
225
- const initT = lowerer.mapTypeOf(lowerer.typeOf(param.initializer));
226
- if (initT && (initT.kind === "undefinedT" || lowerer.bareUndefinedArmedUnion(initT))) {
227
- return { type: raw, mode: "omittable", bodyType: raw };
228
- }
229
- }
230
- const bodyType = lowerer.stripUndefinedArm(raw);
231
- lowerer.checkDefaultParamBodyType(param, bodyType);
232
- // A UNION body type (`tlds: string | string[] = "localhost"`) arms
233
- // the ABI with undefined ON TOP of the body's arms; the prologue
234
- // re-tags a present argument back into the body union (undefined
235
- // sorts last among arm typeKeys in practice, so the mapping is
236
- // usually the identity prefix — the interned retag helper handles
237
- // any order).
238
- const abi = bodyType.kind === "union" ? lowerer.withUndefinedArmOf(bodyType) : lowerer.withUndefinedArm(bodyType);
239
- if (!abi) {
240
- lowerer.badType(param.name, lowerer.typeOf(param.name)); // defensive: unknown union id
241
- }
242
- return { type: abi, mode: "omittable", bodyType };
206
+ return defaultParameterShape(lowerer, param, raw);
243
207
  }
244
208
  const type = lowerer.runtimeOptionalBindingType(param.name, lowerer.irTypeOf(param.name));
209
+ if (type.kind === "void") {
210
+ lowerer.unsupported("SC1090", param, "function parameters with void type");
211
+ }
245
212
  if (param.questionToken && !lowerer.bareUndefinedArmedUnion(type) && type.kind !== "dyn" && type.kind !== "jsval") {
246
213
  // `x?: unknown` where unknown came from an annotation: undefined is
247
214
  // absorbed into the hole type, so no undefined ARM exists — but a
@@ -269,7 +236,7 @@ export function paramShapes(lowerer, params, signature, blameOf) {
269
236
  return params.map((declParam, i) => {
270
237
  const symbol = signature.getParameters()[i];
271
238
  const tsType = symbol ? lowerer.checker.getTypeOfSymbol(symbol) : lowerer.typeOf(declParam.name);
272
- const mapped = lowerer.runtimeOptionalBindingType(declParam.name, lowerer.mapTypeOf(tsType) ?? lowerer.irTypeOf(declParam.name));
239
+ const mapped = jsOpenObjectType(declParam, lowerer.runtimeOptionalBindingType(declParam.name, lowerer.mapTypeOf(tsType) ?? lowerer.irTypeOf(declParam.name)), lowerer.shapes, lowerer.unions);
273
240
  if (!mapped || mapped.kind === "void")
274
241
  lowerer.badType(blameOf?.(declParam, i) ?? declParam.name, tsType);
275
242
  if (declParam.dotDotDotToken) {
@@ -277,30 +244,46 @@ export function paramShapes(lowerer, params, signature, blameOf) {
277
244
  lowerer.badType(blameOf?.(declParam, i) ?? declParam.name, tsType);
278
245
  return { type: mapped, mode: "rest" };
279
246
  }
280
- if (declParam.initializer) {
281
- if (mapped.kind === "dyn" || mapped.kind === "jsval") {
282
- return { type: mapped, mode: "omittable", bodyType: mapped };
283
- }
284
- const bodyType = lowerer.stripUndefinedArm(mapped);
285
- lowerer.checkDefaultParamBodyType(declParam, bodyType);
286
- return { type: lowerer.withUndefinedArm(bodyType), mode: "omittable", bodyType };
287
- }
247
+ if (declParam.initializer)
248
+ return defaultParameterShape(lowerer, declParam, mapped);
288
249
  if (declParam.questionToken && !lowerer.bareUndefinedArmedUnion(mapped)) {
289
250
  lowerer.unsupported("SC1090", declParam, `optional parameters of type '${lowerer.fmt(mapped)}'`);
290
251
  }
291
252
  return { type: mapped, mode: declParam.questionToken ? "omittable" : "required" };
292
253
  });
293
254
  }
255
+ /** A default expression may itself yield undefined. Keep that arm in the
256
+ * body and parameter-property storage, including for literal `undefined`
257
+ * and void expressions: the general type mapper represents those as VOID,
258
+ * so checking only a mapped undefinedT silently erased a valid value.
259
+ * Shared by declared and instantiated signatures, including destructuring. */
260
+ function defaultParameterShape(lowerer, param, raw) {
261
+ if (raw.kind === "dyn" || raw.kind === "jsval") {
262
+ return { type: raw, mode: "omittable", bodyType: raw };
263
+ }
264
+ if (lowerer.bareUndefinedArmedUnion(raw) && param.initializer) {
265
+ const initializer = lowerer.typeOf(param.initializer);
266
+ const parts = initializer.isUnionType() ? ts.constituentTypes(initializer) : [initializer];
267
+ if (parts.some((part) => (part.flags & (ts.TypeFlags.Undefined | ts.TypeFlags.Void)) !== 0)) {
268
+ return { type: raw, mode: "omittable", bodyType: raw };
269
+ }
270
+ }
271
+ const bodyType = lowerer.stripUndefinedArm(raw);
272
+ lowerer.checkDefaultParamBodyType(param, bodyType);
273
+ const abi = bodyType.kind === "union" ? lowerer.withUndefinedArmOf(bodyType) : lowerer.withUndefinedArm(bodyType);
274
+ if (!abi)
275
+ lowerer.badType(param.name, lowerer.typeOf(param.name));
276
+ return { type: abi, mode: "omittable", bodyType };
277
+ }
294
278
  /** The fences on a defaulted parameter's body type: it becomes the value
295
279
  * arm of the synthesized `T | undefined` ABI union, so it must be a valid
296
- * single arm. func and Set ARE valid here: the ABI union's only test is
280
+ * single arm. Functions, Maps and Sets are valid: the ABI union's test is
297
281
  * the prologue's own undefined-tag check (never a user narrowing, which
298
- * is what keeps map/set out of general unions), so `runner: Runner =
282
+ * is what keeps containers out of unions with data siblings), so `runner: Runner =
299
283
  * defaultRunner` and `skip: Set<string> = new Set()` arm like any ref
300
284
  * kind — the nullable-callback union shape, built by the compiler. */
301
285
  export function checkDefaultParamBodyType(lowerer, param, bodyType) {
302
286
  if (bodyType.kind === "void" ||
303
- bodyType.kind === "map" ||
304
287
  bodyType.kind === "regex" ||
305
288
  bodyType.kind === "date" ||
306
289
  bodyType.kind === "dyn" ||
@@ -336,7 +319,62 @@ export function completeArgs(lowerer, argNodes, shapes, loc, blame,
336
319
  * coercion an ordinary argument gets (coerceInto against its shape,
337
320
  * DYN conversion in a dyn rest, element coercion in a typed rest). */
338
321
  leading) {
339
- const isIr = (s) => s !== undefined && !("kind" in s);
322
+ // Conversion eligibility can traverse the whole recursive parameter
323
+ // graph. Ordinary calls and fixed tuples never need that analysis.
324
+ if (argNodes.some((arg) => ts.isSpreadElement(arg) && !fixedTupleSpreadInfo(lowerer, arg.expression)) &&
325
+ canCompleteRuntimeSpread(lowerer, shapes)) {
326
+ // Runtime-length spreads determine the complete argument list before
327
+ // any parameter default runs. Build it once in source order, then
328
+ // extract the fixed native ABI slots; missing elements are undefined.
329
+ const pack = lowerer.declareHiddenLocal("%spreadArgs", DYN);
330
+ const ref = () => ({ kind: "varRef", localId: pack.id, type: DYN, loc });
331
+ const stmts = [{ kind: "varDecl", localId: pack.id, init: { kind: "dynArrLit", elems: [], type: DYN, loc }, loc }];
332
+ const push = (value, fn) => {
333
+ stmts.push({ kind: "exprStmt", expr: { kind: "libCall", fn, args: [ref(), value], type: VOID, loc: value.loc }, loc: value.loc });
334
+ };
335
+ for (const value of leading ?? [])
336
+ push(lowerer.coerceInto(blame, value, DYN), "dyn.packPush");
337
+ const spreads = argNodes.filter(ts.isSpreadElement).length;
338
+ argNodes.forEach((arg, index) => {
339
+ if (!ts.isSpreadElement(arg)) {
340
+ push(lowerer.lowerExprExpecting(arg, DYN), "dyn.packPush");
341
+ return;
342
+ }
343
+ let value = lowerer.lowerExpr(arg.expression);
344
+ if (value.type.kind === "set") {
345
+ value = { kind: "setIntrinsic", method: "toArray", receiver: value, args: [], type: arrayOf(value.type.elem), loc: value.loc };
346
+ }
347
+ else if (value.type.kind === "object") {
348
+ value = lowerer.classIteratorDrainCall(value, locOf(arg)) ?? value;
349
+ }
350
+ if (value.type.kind === "array") {
351
+ // Argument iteration materializes holes as present undefined
352
+ // before conversion to the dense checked-dynamic argument pack.
353
+ value = { kind: "arrayLit", elems: [value], spreads: [0], type: value.type, loc: value.loc };
354
+ }
355
+ value = lowerer.coerceInto(arg.expression, value, DYN);
356
+ if (spreads === 1 && index === argNodes.length - 1) {
357
+ stmts.push({ kind: "exprStmt", expr: {
358
+ kind: "libCall", fn: "dyn.packPushSpread", args: [ref(), value, { kind: "strLit", value: arg.expression.getText(), type: STRING, loc }], type: VOID, loc,
359
+ }, loc });
360
+ }
361
+ else
362
+ push(value, "dyn.packPushSpreadIter");
363
+ });
364
+ const args = shapes.map((shape, index) => {
365
+ if (shape.mode === "arguments")
366
+ return ref();
367
+ const value = shape.mode === "rest" || shape.mode === "dynRest"
368
+ ? { kind: "dynInvoke", recv: ref(), method: "slice", calleeName: "arguments.slice", args: [{ kind: "dynFrom", value: { kind: "numLit", value: index, type: F64, loc }, type: DYN, loc }], type: DYN, loc }
369
+ : { kind: "dynKeyGet", value: ref(), key: { kind: "strLit", value: String(index), type: STRING, loc }, type: DYN, loc };
370
+ return lowerer.coerceInto(blame, value, shape.type);
371
+ });
372
+ // Every supported form has at least one native slot to carry the
373
+ // evaluation prefix, including calls whose only slot is their rest.
374
+ args[0] = { kind: "seqExpr", stmts, result: args[0], type: args[0].type, loc };
375
+ return args;
376
+ }
377
+ const isIr = (s) => s !== undefined && !(s instanceof AstNode);
340
378
  const sources = leading?.map((ir) => ({ ir })) ?? [];
341
379
  for (const arg of argNodes) {
342
380
  if (!ts.isSpreadElement(arg)) {
@@ -399,9 +437,20 @@ leading) {
399
437
  lowerer.unsupported("SC1090", source, "spread arguments into fixed parameter positions (a spread can only fill a rest parameter)");
400
438
  }
401
439
  const slotType = i < restAt ? positional[i].type : DYN;
402
- const value = isIr(source)
403
- ? lowerer.coerceInto(blame, source.ir, slotType)
404
- : lowerer.lowerExprExpecting(source, slotType);
440
+ let value;
441
+ if (isIr(source)) {
442
+ let ir = source.ir;
443
+ // Tuple-spread storage also feeds later arguments. Declare it in
444
+ // this shared sequence, not inside one argument's initializer,
445
+ // whose statement frame ends before the next field is read.
446
+ if (ir.kind === "seqExpr") {
447
+ stmts.push(...ir.stmts);
448
+ ir = ir.result;
449
+ }
450
+ value = lowerer.coerceInto(blame, ir, slotType);
451
+ }
452
+ else
453
+ value = lowerer.lowerExprExpecting(source, slotType);
405
454
  const saved = lowerer.declareHiddenLocal("%callArg", slotType);
406
455
  stmts.push({ kind: "varDecl", localId: saved.id, init: value, loc: value.loc });
407
456
  return { kind: "varRef", localId: saved.id, type: slotType, loc: value.loc };
@@ -409,7 +458,7 @@ leading) {
409
458
  const fixed = positional.map((shape, i) => {
410
459
  if (i < passed.length)
411
460
  return passed[i];
412
- if (shape.mode === "omittable")
461
+ if (shape.mode === "omittable" || lowerer.bareUndefinedArmedUnion(shape.type))
413
462
  return shape.callDefault ?? lowerer.undefinedArgFor(shape.type, loc, blame);
414
463
  if (shape.type.kind === "dyn")
415
464
  return { kind: "dynFrom", value: { kind: "unitLit", unit: "undefined", type: UNDEFINED_T, loc }, type: DYN, loc };
@@ -434,9 +483,19 @@ leading) {
434
483
  // completion has no home for that. Spreads fill REST slots only.
435
484
  lowerer.unsupported("SC1090", arg, "spread arguments into fixed parameter positions (a spread can only fill a rest parameter)");
436
485
  }
437
- if (arg)
486
+ if (arg) {
487
+ let operand = arg;
488
+ while (ts.isParenthesizedExpression(operand))
489
+ operand = operand.expression;
490
+ if (ts.isVoidExpression(operand)) {
491
+ const absent = omittedArgFor(lowerer, shape.type, loc);
492
+ const effect = lowerStaticallyUndefinedArgument(lowerer, operand);
493
+ if (absent && effect)
494
+ return defaultAfterUndefined(effect, absent);
495
+ }
438
496
  return lowerer.lowerExprExpecting(arg, shape.type);
439
- if (shape.mode !== "omittable") {
497
+ }
498
+ if (shape.mode !== "omittable" && !lowerer.bareUndefinedArmedUnion(shape.type)) {
440
499
  // A missing argument for a CHECKED-DYNAMIC param (an implicit-any
441
500
  // JS signature called short — `mustCall(fn)` with `expected`
442
501
  // omitted): JS fills undefined, and the dyn slot holds exactly
@@ -690,7 +749,9 @@ export function requireExactArityValue(lowerer, blame, contextual, shapes, funcT
690
749
  // slot): judge by the expression's OWN completed type; the slot's
691
750
  // coercion still enforces (or adapts) the flow it lands in.
692
751
  if (mappedFn?.kind !== "func" && contextual) {
693
- mappedFn = lowerer.mapTypeOf(lowerer.typeOf(contextual));
752
+ const ownType = lowerer.typeOf(contextual);
753
+ mappedFn = lowerer.mapTypeOf(ownType) ??
754
+ (isJsSourceFile(contextual.getSourceFile()) ? dynFallbackType(lowerer, contextual, ownType) : null);
694
755
  }
695
756
  if (mappedFn && typeEquals(mappedFn, funcType))
696
757
  return;
@@ -810,6 +871,10 @@ export function declaredReturnType(lowerer, decl, blame) {
810
871
  if (!sig)
811
872
  lowerer.unsupported("SC1090", decl, "this function form");
812
873
  const retTsType = lowerer.checker.getReturnTypeOfSignature(sig);
874
+ // An inferred null/undefined return in JS can read a mutable checked-value
875
+ // field. Keep the actual value instead of restricting it to the initializer.
876
+ if (isJsSourceFile(decl.getSourceFile()) && (retTsType.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined)) !== 0)
877
+ return DYN;
813
878
  // A body that always throws infers `never` — as a RETURN type that is
814
879
  // void with a stronger guarantee (`() => never` is assignable to
815
880
  // `() => void`), and throw-only callbacks are ordinary code
@@ -817,10 +882,34 @@ export function declaredReturnType(lowerer, decl, blame) {
817
882
  if (retTsType.flags & ts.TypeFlags.Never)
818
883
  return VOID;
819
884
  const mappedReturn = lowerer.mapTypeOf(retTsType);
885
+ if (isJsSourceFile(decl.getSourceFile()) && !decl.type && !hasExplicitJsDocReturn(decl) && mappedReturn?.kind === "date")
886
+ return DYN;
887
+ // JS inference assigns Number to arithmetic over any, although the
888
+ // runtime operands can both be BigInts. Preserve that native result.
889
+ if (isJsSourceFile(decl.getSourceFile()) && !decl.type && !hasExplicitJsDocReturn(decl) &&
890
+ mappedReturn?.kind === "f64") {
891
+ let numericAnyReturn = false;
892
+ const numeric = new Set([ts.SyntaxKind.MinusToken, ts.SyntaxKind.AsteriskToken,
893
+ ts.SyntaxKind.SlashToken, ts.SyntaxKind.PercentToken, ts.SyntaxKind.AsteriskAsteriskToken]);
894
+ const check = (node) => {
895
+ if (node !== decl && ts.isFunctionLike(node))
896
+ return;
897
+ const value = ts.isReturnStatement(node) ? node.expression
898
+ : node === decl && ts.isArrowFunction(decl) && !ts.isBlock(decl.body) ? decl.body : undefined;
899
+ if (value && ts.isBinaryExpression(value) && numeric.has(value.operatorToken.kind) &&
900
+ [value.left, value.right].some((operand) => (lowerer.typeOf(operand).flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) !== 0))
901
+ numericAnyReturn = true;
902
+ node.forEachChild(check);
903
+ };
904
+ check(decl);
905
+ if (numericAnyReturn)
906
+ return DYN;
907
+ }
820
908
  if (isJsSourceFile(decl.getSourceFile()) &&
821
909
  !hasExplicitJsDocReturn(decl) &&
822
910
  mappedReturn !== null &&
823
911
  promiseCarriesDyn(lowerer, mappedReturn) &&
912
+ !decl.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.AsyncKeyword) &&
824
913
  decl.parameters.some((param) => {
825
914
  const mapped = lowerer.mapTypeOf(lowerer.typeOf(param.name));
826
915
  return mapped === null || mapped.kind === "dyn";
@@ -852,14 +941,19 @@ export function declaredReturnType(lowerer, decl, blame) {
852
941
  // checked-dynamic (or none): a lambda with RECORD-typed parameters
853
942
  // (a reduce reducer over a typed array) legitimately returns its
854
943
  // parameters' records and keeps the static type.
944
+ // Native-only members (such as Int32Array layout offsets) cannot cross
945
+ // that boundary; their factories keep the native record ABI.
946
+ const asyncReturn = decl.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.AsyncKeyword) && mappedReturn?.kind === "promise";
947
+ const recordReturn = asyncReturn ? mappedReturn.inner : mappedReturn;
855
948
  if (isJsSourceFile(decl.getSourceFile()) &&
856
949
  decl.type === undefined &&
857
- lowerer.mapTypeOf(retTsType)?.kind === "record" &&
950
+ recordReturn?.kind === "record" &&
951
+ lowerer.dynConvertible(recordReturn) &&
858
952
  decl.parameters.every((p) => {
859
953
  const mt = lowerer.mapTypeOf(lowerer.typeOf(p));
860
954
  return mt === null || mt.kind === "dyn";
861
955
  })) {
862
- return DYN;
956
+ return asyncReturn ? { kind: "promise", inner: DYN } : DYN;
863
957
  }
864
958
  const returnType = lowerer.mapTypeOf(retTsType);
865
959
  if (!returnType) {
@@ -884,7 +978,7 @@ export function declaredReturnType(lowerer, decl, blame) {
884
978
  * other unmappable type (the caller's badType reports those). */
885
979
  function fenceGenericSignatureResult(lowerer, blame, t) {
886
980
  const parts = t.isUnionType() ? ts.constituentTypes(t) : [t];
887
- if (!parts.some((p) => lowerer.checker.getCallSignatures(p).some((s) => (s.typeParameters?.length ?? 0) > 0))) {
981
+ if (!parts.some((p) => lowerer.checker.getCallSignatures(p).some((s) => s.getTypeParameters().length > 0))) {
888
982
  return;
889
983
  }
890
984
  lowerer.unsupported("SC1090", blame, `results that are themselves generic functions ('${lowerer.checker.typeToString(t)}' keeps its type parameters — no call-site instantiation pins them, and the returned value would need the producing call's frame; restructure to one generic function taking all arguments)`);
@@ -961,7 +1055,7 @@ export function collectSignatureInner(lowerer, decl) {
961
1055
  if (!params.some((sh) => sh.mode === "rest" || sh.mode === "dynRest" || sh.mode === "islandRest") &&
962
1056
  isJsSourceFile(decl.getSourceFile()) &&
963
1057
  bodyReadsArguments(decl)) {
964
- if (decl.parameters.length > 0 && !isNodeEsmFile(decl.getSourceFile())) {
1058
+ if (decl.parameters.length > 0 && !isNodeEsmFile(decl.getSourceFile(), lowerer.program)) {
965
1059
  lowerer.unsupported("SC1090", decl, "parameterized 'arguments' outside an ES module (sloppy-mode parameter aliases)");
966
1060
  }
967
1061
  params.push({ type: DYN, mode: decl.parameters.length > 0 ? "arguments" : "dynRest" });
@@ -1193,7 +1287,7 @@ export function inferTypeParamBindings(lowerer, expr, info, rsig, tsBindings) {
1193
1287
  return;
1194
1288
  const taT = lowerer.checker.getTypeFromTypeNode(ta);
1195
1289
  const mapped = lowerer.mapTypeOf(taT);
1196
- if (mapped && mapped.kind !== "void") {
1290
+ if (mapped) {
1197
1291
  bindings.set(tp, mapped);
1198
1292
  tsBindings?.set(tp, taT);
1199
1293
  }
@@ -1213,7 +1307,7 @@ function bindDefaultTypeParams(lowerer, typeParams, typeParamDecls, bindings, ts
1213
1307
  return;
1214
1308
  const defT = lowerer.checker.getTypeFromTypeNode(tpDecl.defaultType);
1215
1309
  const mapped = lowerer.mapTypeOf(defT);
1216
- if (mapped && mapped.kind !== "void") {
1310
+ if (mapped) {
1217
1311
  bindings.set(tp, mapped);
1218
1312
  tsBindings?.set(tp, defT);
1219
1313
  }
@@ -1255,7 +1349,10 @@ function unifySignatureBindings(lowerer, info, rsig, bindings, tsBindings) {
1255
1349
  }
1256
1350
  if (!bindings.has(sym)) {
1257
1351
  const mapped = lowerer.mapTypeOf(inst);
1258
- if (mapped && mapped.kind !== "void")
1352
+ // A visitor's inferred T can be void. It still binds the
1353
+ // return convention of `(node) => T`; discarding it leaves
1354
+ // the callback's return type spuriously uninstantiated.
1355
+ if (mapped)
1259
1356
  bindings.set(sym, mapped);
1260
1357
  }
1261
1358
  }
@@ -1270,10 +1367,20 @@ function unifySignatureBindings(lowerer, info, rsig, bindings, tsBindings) {
1270
1367
  // unbound type parameter surfaces as a mapping diagnostic later).
1271
1368
  if (declared.isUnionType()) {
1272
1369
  const unitFlags = ts.TypeFlags.Undefined | ts.TypeFlags.Null;
1273
- const dParts = ts.constituentTypes(declared).filter((t) => !(t.flags & unitFlags));
1274
- const iParts = inst.isUnionType() ? ts.constituentTypes(inst).filter((t) => !(t.flags & unitFlags)) : [inst];
1370
+ const declaredParts = ts.constituentTypes(declared);
1371
+ const declaredUnits = declaredParts.reduce((flags, t) => flags | (t.flags & unitFlags), 0);
1372
+ const dParts = declaredParts.filter((t) => !(t.flags & unitFlags));
1373
+ const iParts = inst.isUnionType() ? ts.constituentTypes(inst).filter((t) => !(t.flags & declaredUnits)) : [inst];
1275
1374
  if (dParts.length === 1 && iParts.length === 1)
1276
1375
  unify(dParts[0], iParts[0], depth + 1);
1376
+ else if (dParts.length === 1 && iParts.length > 1 &&
1377
+ iParts.every((t) => (t.flags & unitFlags) === 0)) {
1378
+ // T | undefined can receive boolean | undefined: boolean itself
1379
+ // has two literal arms. There is still one declared data slot,
1380
+ // so match it against the whole remaining union. Removing null
1381
+ // too is safe only when no undeclared null arm remains.
1382
+ unify(dParts[0], lowerer.checker.getNonNullableType(inst), depth + 1);
1383
+ }
1277
1384
  return;
1278
1385
  }
1279
1386
  // Instantiations of the SAME generic ALIAS (Partial<T> vs
@@ -1426,16 +1533,21 @@ export function lowerGenericInstance(lowerer, info, inst) {
1426
1533
  fnCtx.generator = generatorMeta(lowerer, inst.returnType);
1427
1534
  }
1428
1535
  lowerer.fnStack.push(fnCtx);
1536
+ lowerer.localClassInstantiations.push({ owner: decl, name: inst.name });
1429
1537
  try {
1430
- // STATIC generic methods: `this`/`super` name the RECEIVER class (a
1431
- // dynamic value) — the lowerStaticMethod fence, applied here because
1432
- // generic statics have no non-generic lowering pass. Arrow functions
1433
- // are transparent (they inherit the method's `this`); this-binding
1434
- // function forms are opaque.
1538
+ // Static specializations bind lexical this only when the caller
1539
+ // proved its exact receiver. Other instances retain the fence;
1540
+ // super remains unsupported. Arrows inherit the lexical receiver.
1435
1541
  if (info.member?.kind === "static" && decl.body) {
1436
- rejectStaticThis(lowerer, decl.body, (keyword) => `'${keyword}' in static methods (it names the RECEIVER class — a dynamic value; reference the class by name instead)`);
1542
+ rejectStaticThis(lowerer, decl.body, (keyword) => `'${keyword}' in static methods (it names the RECEIVER class — a dynamic value; reference the class by name instead)`, false, info.staticReceiver !== undefined);
1437
1543
  }
1438
1544
  const params = [];
1545
+ const receiverInit = [];
1546
+ if (info.staticReceiver) {
1547
+ const value = lowerer.classValueRef(info.staticReceiver, decl);
1548
+ const local = lowerer.declareThis(value.type);
1549
+ receiverInit.push({ kind: "varDecl", localId: local.id, init: value, loc: locOf(decl) });
1550
+ }
1439
1551
  if (cls && info.member.kind === "method") {
1440
1552
  // Instance methods take `this` as param 0, exactly like plain
1441
1553
  // `%C.method` functions (lowerClassMethodMemberInner).
@@ -1447,7 +1559,7 @@ export function lowerGenericInstance(lowerer, info, inst) {
1447
1559
  // threaded — a default mentioning T resolves like any body expression.
1448
1560
  const declared = lowerer.declareParams(decl.parameters, inst.params);
1449
1561
  params.push(...declared.params);
1450
- const body = [...declared.prologue];
1562
+ const body = [...receiverInit, ...declared.prologue];
1451
1563
  const bodyBlock = blockBodyOf(decl);
1452
1564
  if (bodyBlock) {
1453
1565
  body.push(...lowerer.lowerStmts(bodyBlock.statements));
@@ -1490,6 +1602,8 @@ export function lowerGenericInstance(lowerer, info, inst) {
1490
1602
  }
1491
1603
  const fn = {
1492
1604
  name: inst.name,
1605
+ sourceName: info.baseName,
1606
+ ...(!isAsync && !decl.asteriskToken && (ts.isFunctionDeclaration(decl) || ts.isFunctionExpression(decl)) ? { ownsPrototype: true } : {}),
1493
1607
  params,
1494
1608
  returnType: bodyReturn,
1495
1609
  locals: lowerer.ctx.locals,
@@ -1509,6 +1623,7 @@ export function lowerGenericInstance(lowerer, info, inst) {
1509
1623
  lowerer.typeParamTsBindings = prevTsBindings;
1510
1624
  lowerer.implicitParamTypes = prevImplicit;
1511
1625
  lowerer.instantiationContext = prevContext;
1626
+ lowerer.localClassInstantiations.pop();
1512
1627
  lowerer.suppressStats = prevSuppress;
1513
1628
  }
1514
1629
  }
@@ -1531,7 +1646,6 @@ function resolveInferredReturn(lowerer, inst, infer, body, decl) {
1531
1646
  // returning — JS answers undefined.
1532
1647
  const last = body[body.length - 1];
1533
1648
  const mayFallThrough = !last || !(last.kind === "return" || last.kind === "throw" || last.kind === "rethrow" || last.kind === "runtimeFence");
1534
- const valued = infer.entries.filter((e) => e.stmt.kind === "return" && e.stmt.value !== null && e.stmt.value !== undefined);
1535
1649
  const sawBare = mayFallThrough || infer.entries.some((e) => e.stmt.kind === "return" && (e.stmt.value === null || e.stmt.value === undefined));
1536
1650
  let final;
1537
1651
  if (inst.returnPinned) {
@@ -1539,16 +1653,19 @@ function resolveInferredReturn(lowerer, inst, infer, body, decl) {
1539
1653
  }
1540
1654
  else {
1541
1655
  const distinct = [];
1542
- for (const e of valued) {
1543
- if (!distinct.some((t) => typeEquals(t, e.stmt.value.type)))
1544
- distinct.push(e.stmt.value.type);
1656
+ for (const e of infer.entries) {
1657
+ if (e.stmt.kind !== "return" || e.stmt.value === null || e.stmt.value === undefined)
1658
+ continue;
1659
+ const type = e.stmt.value.type;
1660
+ if (!distinct.some((t) => typeEquals(t, type)))
1661
+ distinct.push(type);
1545
1662
  }
1546
1663
  if (distinct.length === 0) {
1547
1664
  final = DYN; // no valued return: JS completes with undefined — the dyn undefined, today's slot
1548
1665
  }
1549
1666
  else if (distinct.length === 1) {
1550
1667
  const t = distinct[0];
1551
- final = !sawBare ? t : t.kind === "dyn" ? DYN : (lowerer.withUndefinedArmOf(t) ?? DYN);
1668
+ final = isUnitType(t) ? DYN : !sawBare ? t : t.kind === "dyn" ? DYN : (lowerer.withUndefinedArmOf(t) ?? DYN);
1552
1669
  }
1553
1670
  else {
1554
1671
  final = DYN; // disagreeing returns: the checked-dynamic join
@@ -1559,23 +1676,24 @@ function resolveInferredReturn(lowerer, inst, infer, body, decl) {
1559
1676
  for (const e of infer.entries) {
1560
1677
  if (e.stmt.kind !== "return")
1561
1678
  continue;
1562
- const st = e.stmt;
1679
+ // Write through the recorded statement. A narrowed local can acquire a
1680
+ // different record layout and copy it in the native compiler.
1563
1681
  const diagsBefore = lowerer.diags.length;
1564
1682
  try {
1565
- if (st.value === null || st.value === undefined) {
1683
+ if (e.stmt.value === null || e.stmt.value === undefined) {
1566
1684
  if (final.kind === "dyn")
1567
- st.value = dynUndefinedExpr(st.loc);
1685
+ e.stmt.value = dynUndefinedExpr(e.stmt.loc);
1568
1686
  else if (final.kind === "union") {
1569
- const wrapped = lowerer.wrappedUndefined(final, st.loc);
1687
+ const wrapped = lowerer.wrappedUndefined(final, e.stmt.loc);
1570
1688
  if (!wrapped) {
1571
1689
  lowerer.unsupported("SC1090", e.node ?? decl, `bare 'return' in a function whose inferred return type is '${lowerer.fmt(final)}'`);
1572
1690
  }
1573
- st.value = wrapped;
1691
+ e.stmt.value = wrapped;
1574
1692
  }
1575
1693
  // void final: bare return stands as-is
1576
1694
  }
1577
- else if (!typeEquals(st.value.type, final)) {
1578
- st.value = lowerer.coerceInto(e.node ?? decl, st.value, final);
1695
+ else if (!typeEquals(e.stmt.value.type, final)) {
1696
+ e.stmt.value = lowerer.coerceInto(e.node ?? decl, e.stmt.value, final);
1579
1697
  }
1580
1698
  }
1581
1699
  catch (err) {
@@ -1590,7 +1708,7 @@ function resolveInferredReturn(lowerer, inst, infer, body, decl) {
1590
1708
  lowerer.diags.push(...ice);
1591
1709
  lowerer.runtimeFences.push(...captured.filter((d) => d.code !== "SC9001"));
1592
1710
  const first = captured.find((d) => d.code !== "SC9001");
1593
- const mutable = st;
1711
+ const mutable = e.stmt;
1594
1712
  delete mutable["value"];
1595
1713
  mutable["kind"] = "runtimeFence";
1596
1714
  mutable["code"] = first?.code ?? "SC1090";
@@ -1848,10 +1966,12 @@ function broadPromiseParam(lowerer, type) {
1848
1966
  }
1849
1967
  /** The implicit-type-parameter slots of a JS function-like: parallel to
1850
1968
  * decl.parameters, the param SYMBOL where the slot is a bindable
1851
- * implicit-any param (identifier-named, no annotation/JSDoc type, not
1852
- * rest/optional/defaulted, never written), null elsewhere. Null overall
1853
- * when nothing qualifies — the declaration keeps today's path. */
1854
- export function implicitAnyParamSymbolsOf(lowerer, decl) {
1969
+ * implicit param (identifier-named, broad inferred/JSDoc type, not
1970
+ * rest/optional/defaulted, never written), null elsewhere. Package JS
1971
+ * methods may also specialize class parameters: JSDoc names a nominal
1972
+ * class even when the body accepts other objects with the same members.
1973
+ * Null overall when nothing qualifies — the declaration keeps its ABI. */
1974
+ export function implicitAnyParamSymbolsOf(lowerer, decl, classParams = false) {
1855
1975
  if (!decl.body)
1856
1976
  return null;
1857
1977
  if (decl.asteriskToken)
@@ -1877,7 +1997,9 @@ export function implicitAnyParamSymbolsOf(lowerer, decl) {
1877
1997
  const broadFunction = lowerer.checker.typeToString(t) === "Function";
1878
1998
  const broadArray = lowerer.checkerAnyArrayType(t);
1879
1999
  const broadPromise = broadPromiseParam(lowerer, t);
1880
- if ((t.flags & ts.TypeFlags.Any) === 0 && !broadFunction && !broadArray && !broadPromise)
2000
+ const declaredKind = classParams ? lowerer.mapTypeOf(t)?.kind : undefined;
2001
+ const classParam = classParams && (declaredKind === "object" || declaredKind === "array");
2002
+ if ((t.flags & ts.TypeFlags.Any) === 0 && !broadFunction && !broadArray && !broadPromise && !classParam)
1881
2003
  return null;
1882
2004
  const sym = lowerer.checker.getSymbolAtLocation(param.name);
1883
2005
  if (!sym)
@@ -1896,6 +2018,11 @@ export function implicitAnyParamSymbolsOf(lowerer, decl) {
1896
2018
  * selects return INFERENCE with DYN as the recursion pin. */
1897
2019
  function implicitDeclaredReturn(lowerer, info) {
1898
2020
  try {
2021
+ // Static JS helpers can accept a structurally compatible class despite
2022
+ // narrower JSDoc (for example a Vector2 target documented as Vector3).
2023
+ // Infer their result from the specialized body as well.
2024
+ if (info.member?.kind === "static" && info.decl.parameters.some((param, index) => info.implicitParams?.[index] && lowerer.mapTypeOf(lowerer.typeOf(param.name))?.kind === "object"))
2025
+ return null;
1899
2026
  const broadCallbackSymbols = new Set(info.decl.parameters.flatMap((param, index) => {
1900
2027
  const symbol = info.implicitParams?.[index];
1901
2028
  return symbol !== null && symbol !== undefined &&
@@ -1915,7 +2042,10 @@ function implicitDeclaredReturn(lowerer, info) {
1915
2042
  expression = expression.expression;
1916
2043
  if (ts.isCallExpression(expression) &&
1917
2044
  ts.isIdentifier(expression.expression) &&
1918
- broadCallbackSymbols.has(lowerer.checker.getSymbolAtLocation(expression.expression) ?? {})) {
2045
+ (() => {
2046
+ const symbol = lowerer.checker.getSymbolAtLocation(expression.expression);
2047
+ return symbol !== undefined && broadCallbackSymbols.has(symbol);
2048
+ })()) {
1919
2049
  returnsBroadCallback = true;
1920
2050
  return "stop";
1921
2051
  }
@@ -1930,7 +2060,12 @@ function implicitDeclaredReturn(lowerer, info) {
1930
2060
  const retTs = lowerer.checker.getReturnTypeOfSignature(declSig);
1931
2061
  if (retTs.flags & ts.TypeFlags.Any)
1932
2062
  return null;
2063
+ if (retTs.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined))
2064
+ return DYN;
1933
2065
  if (lowerer.checker.isArrayType(retTs)) {
2066
+ if (info.decl.parameters.some((param, index) => info.implicitParams?.[index] &&
2067
+ lowerer.mapTypeOf(lowerer.typeOf(param.name))?.kind === "array"))
2068
+ return null;
1934
2069
  const elem = lowerer.checker.getTypeArguments(retTs)[0];
1935
2070
  // An implicit-any parameter poisons an inferred array result to
1936
2071
  // any[] even when this instance's body produces one concrete
@@ -1941,6 +2076,11 @@ function implicitDeclaredReturn(lowerer, info) {
1941
2076
  return null;
1942
2077
  }
1943
2078
  const mapped = lowerer.mapTypeOf(retTs);
2079
+ // Inferred variadic results carry runtime argument packs. Their
2080
+ // factory must retain the lowered callable rather than extracting a
2081
+ // fixed native signature from a checked value.
2082
+ if (mapped?.kind === "func" && mapped.rest === true && mapped.restAbi === undefined && !hasExplicitJsDocReturn(info.decl))
2083
+ return null;
1944
2084
  if (mapped !== null && promiseCarriesDyn(lowerer, mapped) && !hasExplicitJsDocReturn(info.decl))
1945
2085
  return null;
1946
2086
  return mapped;
@@ -1972,6 +2112,30 @@ function bindableImplicitIr(t) {
1972
2112
  t.kind !== "void" && t.kind !== "dyn" && t.kind !== "jsval" &&
1973
2113
  t.kind !== "caught" && t.kind !== "undefinedT" && t.kind !== "nullT");
1974
2114
  }
2115
+ /** A represented binding or direct callable result can be wider than the
2116
+ * checker's inferred shape. Preserve that boundary when specializing JS. */
2117
+ function storedImplicitArgumentType(lowerer, arg) {
2118
+ while (ts.isParenthesizedExpression(arg))
2119
+ arg = arg.expression;
2120
+ if (ts.isAwaitExpression(arg)) {
2121
+ const awaited = storedImplicitArgumentType(lowerer, arg.expression);
2122
+ return awaited?.kind === "promise" ? awaited.inner : awaited;
2123
+ }
2124
+ if (ts.isObjectLiteralExpression(arg) && isJsSourceFile(arg.getSourceFile()) && arg.properties.some((property) => !ts.isSpreadAssignment(property) && property.name !== undefined && ts.isComputedPropertyName(property.name) &&
2125
+ lowerer.foldedStringKeyOf(property.name.expression) === null))
2126
+ return DYN;
2127
+ if (ts.isIdentifier(arg))
2128
+ return lowerer.peekLocal(arg)?.type ?? lowerer.globalOf(arg)?.type ?? null;
2129
+ if (ts.isCallExpression(arg) && ts.isIdentifier(arg.expression)) {
2130
+ const callee = storedImplicitArgumentType(lowerer, arg.expression);
2131
+ if (callee?.kind === "dyn")
2132
+ return DYN;
2133
+ if (callee?.kind === "func")
2134
+ return callee.ret;
2135
+ return lowerer.fnSigOf(arg.expression)?.returnType ?? null;
2136
+ }
2137
+ return null;
2138
+ }
1975
2139
  /** The instance a CALL of an implicit-any function-like names: each
1976
2140
  * bindable implicit param takes the call's WIDENED argument checker type
1977
2141
  * when it maps statically (DYN otherwise — today's slot), typed params
@@ -1994,19 +2158,52 @@ export function implicitCallInstance(lowerer, call, info) {
1994
2158
  bound = declared.type;
1995
2159
  const arg = call.arguments[i];
1996
2160
  if (arg && !ts.isSpreadElement(arg)) {
1997
- const runtimeLocal = ts.isIdentifier(arg) ? lowerer.peekLocal(arg) : null;
1998
- if (runtimeLocal?.type.kind === "dyn") {
2161
+ const stored = storedImplicitArgumentType(lowerer, arg);
2162
+ if (stored?.kind === "dyn") {
1999
2163
  bound = DYN;
2000
2164
  argTypes.set(sym, lowerer.checker.getUnknownType());
2001
2165
  shapes.push({ type: bound, mode: "required" });
2002
2166
  return;
2003
2167
  }
2168
+ // A represented native array must keep its storage when a direct
2169
+ // inferred helper receives it. Re-boxing a checker-any array would
2170
+ // copy it, losing writes (and attempting to read unfilled slots).
2171
+ if (stored?.kind === "array") {
2172
+ argTypes.set(sym, lowerer.typeOf(arg));
2173
+ shapes.push({ type: stored, mode: "required" });
2174
+ return;
2175
+ }
2004
2176
  // The argument's own checker type, literal-widened ('add' binds
2005
2177
  // string) — typeOf consults the ACTIVE instance's bindings, so a
2006
2178
  // bound param forwarded into another implicit call transitively
2007
2179
  // instantiates it (this._initCommandGroup(command)).
2008
2180
  const t = lowerer.checker.getBaseTypeOfLiteralType(lowerer.typeOf(arg));
2009
2181
  const mapped = lowerer.mapTypeOf(t) ?? dynFallbackType(lowerer, arg, t);
2182
+ // JavaScript arguments-based callables travel as checked functions.
2183
+ // Specializing a parameter to the inferred rest signature would
2184
+ // require extracting a native variadic ABI that the value does not
2185
+ // expose. Its checked invocation preserves the complete argument pack.
2186
+ if (mapped?.kind === "func" && mapped.rest === true && mapped.restAbi === undefined) {
2187
+ argTypes.set(sym, lowerer.checker.getUnknownType());
2188
+ shapes.push({ type: DYN, mode: "required" });
2189
+ return;
2190
+ }
2191
+ // JS inference can absorb heterogeneous loop values into `{}`.
2192
+ // That checker supertype is not an empty-record runtime layout:
2193
+ // preserve represented arms through the checked boundary instead
2194
+ // of specializing a call to a union that would discard them.
2195
+ const mappedArms = mapped?.kind === "union" ? lowerer.unions.get(mapped.unionId)?.arms ?? [] : mapped ? [mapped] : [];
2196
+ const hasTopObject = mappedArms.some((arm) => {
2197
+ const shape = arm.kind === "record" ? lowerer.shapes.get(arm.shapeId) : undefined;
2198
+ return shape && !shape.tuple && !shape.indexValue && shape.fields.length === 0;
2199
+ });
2200
+ if (stored?.kind === "union" && hasTopObject && lowerer.dynConvertible(stored) &&
2201
+ lowerer.unions.get(stored.unionId)?.arms.some((arm) => !isUnitType(arm) &&
2202
+ !mappedArms.some((target) => lowerer.widthLiftPlan(arm, target) !== null))) {
2203
+ argTypes.set(sym, lowerer.checker.getUnknownType());
2204
+ shapes.push({ type: DYN, mode: "required" });
2205
+ return;
2206
+ }
2010
2207
  if (ts.isArrowFunction(arg) &&
2011
2208
  arg.type === undefined &&
2012
2209
  mapped?.kind === "func" &&
@@ -2031,15 +2228,32 @@ export function implicitCallInstance(lowerer, call, info) {
2031
2228
  /** The all-dyn DEFAULT instance — today's compiled body exactly: what a
2032
2229
  * VALUE reference of an implicit-any function names (indirect calls
2033
2230
  * carry no per-site types to bind). */
2034
- function implicitDefaultInstance(lowerer, blame, info) {
2231
+ export function implicitDefaultInstance(lowerer, blame, info) {
2035
2232
  const shapes = info.decl.parameters.map((param, i) => info.implicitParams[i] ? { type: DYN, mode: "required" } : lowerer.paramShape(param));
2036
- return internImplicitInstance(lowerer, blame, info, shapes, new Map());
2233
+ const argTypes = new Map();
2234
+ // Newly bindable nominal class parameters must not retain their JSDoc
2235
+ // receiver type in the checked fallback. Keep existing broad JS inference.
2236
+ for (let i = 0; i < info.decl.parameters.length; i++) {
2237
+ const symbol = info.implicitParams?.[i];
2238
+ const kind = lowerer.mapTypeOf(lowerer.typeOf(info.decl.parameters[i].name))?.kind;
2239
+ if (symbol && (kind === "object" || kind === "array")) {
2240
+ argTypes.set(symbol, lowerer.checker.getUnknownType());
2241
+ }
2242
+ }
2243
+ return internImplicitInstance(lowerer, blame, info, shapes, argTypes);
2037
2244
  }
2038
2245
  function internImplicitInstance(lowerer, blame, info, shapes, argTypes) {
2039
2246
  const key = shapes.map((s) => typeKey(s.type)).join(",");
2040
2247
  let inst = info.instances.get(key);
2041
- if (inst)
2248
+ if (inst?.implicitState === "failed")
2249
+ lowerer.unsupported("SC1090", blame, `the failed specialization of '${info.baseName}'`);
2250
+ if (inst) {
2251
+ // A recursive caller has observed this ABI before inference settles.
2252
+ // Keep the promised return slot and coerce the completed body's returns.
2253
+ if (inst.implicitState === "lowering")
2254
+ inst.returnPinned = true;
2042
2255
  return inst;
2256
+ }
2043
2257
  if (info.instances.size >= MAX_GENERIC_INSTANCES) {
2044
2258
  lowerer.unsupported("SC1090", blame, `unbounded implicit-any instantiation ('${info.baseName}' exceeded ` +
2045
2259
  `${MAX_GENERIC_INSTANCES} instances — polymorphic recursion?)`);
@@ -2065,11 +2279,15 @@ function internImplicitInstance(lowerer, blame, info, shapes, argTypes) {
2065
2279
  ...(declared === null ? { implicitInferReturn: true } : {}),
2066
2280
  };
2067
2281
  info.instances.set(key, inst);
2068
- // EAGER lowering (nested, the lambda discipline): the call site needs
2069
- // the settled return type NOW. A body-level poison (a fenced parameter
2070
- // form) skips the function like lowerFunction's rule — calls then meet
2071
- // the pinned signature over a missing body, which the linker never
2072
- // sees because the poison also fenced the call statement.
2282
+ // Eager lowering settles the return ABI before callers use it. A failed
2283
+ // JS body must still have a throwing implementation: later references
2284
+ // (including recursive ones) can already hold its cached signature.
2285
+ const diagsBefore = lowerer.diags.length;
2286
+ // The instance is cached even when a receiver probe requested it.
2287
+ // Its body must retain statement fences instead of dropping failures
2288
+ // into that probe's temporary diagnostic sink and caching empty code.
2289
+ const previousSink = lowerer.diagSink;
2290
+ lowerer.diagSink = null;
2073
2291
  try {
2074
2292
  // Implicit-any instances lower EAGERLY at the call site so their
2075
2293
  // inferred return type is available immediately. They therefore do
@@ -2087,8 +2305,20 @@ function internImplicitInstance(lowerer, blame, info, shapes, argTypes) {
2087
2305
  catch (e) {
2088
2306
  if (!(e instanceof PoisonError))
2089
2307
  throw e;
2090
- inst.implicitState = "done";
2091
- throw e;
2308
+ inst.implicitState = "failed";
2309
+ const types = shapes.map((shape) => shape.type);
2310
+ if (info.member?.kind === "method")
2311
+ types.unshift({ kind: "object", className: info.member.cls.def.name });
2312
+ const fn = lowerer.deferToRuntimeFence(diagsBefore, info.decl, {
2313
+ kind: "function", name: inst.name, returnType: inst.returnType,
2314
+ params: types.map((type, index) => ({ localId: `p.${index}`, name: `p${index}`, type })),
2315
+ });
2316
+ if (!fn)
2317
+ throw e;
2318
+ lowerer.implicitFns.push(fn);
2319
+ }
2320
+ finally {
2321
+ lowerer.diagSink = previousSink;
2092
2322
  }
2093
2323
  inst.implicitState = "done";
2094
2324
  return inst;
@@ -2194,11 +2424,11 @@ export function implicitLocalFnInfoOf(lowerer, decl, fnNode) {
2194
2424
  const implicit = implicitAnyParamSymbolsOf(lowerer, fnNode);
2195
2425
  if (!implicit)
2196
2426
  lowerer.unsupported("SC1090", fnNode, "this function form"); // defensive: the probe proved it
2197
- const stmt = decl.parent.parent;
2427
+ const stmt = decl.parent?.parent;
2198
2428
  const info = {
2199
2429
  decl: fnNode,
2200
2430
  baseName: name,
2201
- qualifiedName: lowerer.qualify(decl.getSourceFile(), nsPathPrefix(stmt, decl) + `${name}%l${decl.getStart()}`),
2431
+ qualifiedName: lowerer.qualify(decl.getSourceFile(), nsPathPrefix(stmt ?? decl, decl) + `${name}%l${decl.getStart()}`),
2202
2432
  typeParams: [],
2203
2433
  instances: new Map(),
2204
2434
  implicitParams: implicit,
@@ -2409,6 +2639,7 @@ function makeTimerArgsThunk(lowerer, cbNode, argNodes, what, loc) {
2409
2639
  kind: "dynCall",
2410
2640
  callee: { kind: "varRef", localId: "f.0", type: DYN, loc },
2411
2641
  calleeName: "callback",
2642
+ receiver: { kind: "libCall", fn: "dyn.this", args: [], type: DYN, loc },
2412
2643
  args: args.map((_, i) => ({ kind: "varRef", localId: `a${i}.0`, type: DYN, loc })),
2413
2644
  type: DYN,
2414
2645
  loc,
@@ -2573,7 +2804,12 @@ export function lowerTimersMemberCall(lowerer, expr, member, loc) {
2573
2804
  return null;
2574
2805
  }
2575
2806
  function ffiSourceParams(binding) {
2576
- return binding.params.filter((param) => !isFfiContextParam(param));
2807
+ const params = [];
2808
+ for (const param of binding.params) {
2809
+ if (!isFfiContextParam(param))
2810
+ params.push(param);
2811
+ }
2812
+ return params;
2577
2813
  }
2578
2814
  function ffiParamDisplay(param) {
2579
2815
  return isFfiCallbackParam(param)
@@ -2590,7 +2826,11 @@ function ffiCallbackInputDiagnostic(lowerer, descriptor, callbackType) {
2590
2826
  const signatures = lowerer.checker.getCallSignatures(callbackType);
2591
2827
  if (signatures.length !== 1)
2592
2828
  return null;
2593
- const nativeParams = descriptor.callback.params.filter((param) => !isFfiContextParam(param));
2829
+ const nativeParams = [];
2830
+ for (const param of descriptor.callback.params) {
2831
+ if (!isFfiContextParam(param))
2832
+ nativeParams.push(param);
2833
+ }
2594
2834
  let nativeIndex = 0;
2595
2835
  const params = signatures[0].getParameters();
2596
2836
  for (let i = 0; i < params.length; i++) {
@@ -2608,12 +2848,13 @@ function ffiCallbackInputDiagnostic(lowerer, descriptor, callbackType) {
2608
2848
  }
2609
2849
  if (nativeClass === "bytes")
2610
2850
  continue;
2611
- const domain = nativeClass === "bool"
2851
+ const wide = nativeClass === "i64" || nativeClass === "u64" || nativeClass === "pointer";
2852
+ const domain = wide ? "bigint" : nativeClass === "bool"
2612
2853
  ? "boolean"
2613
2854
  : nativeClass === "cstring" || nativeClass === "string"
2614
2855
  ? "string"
2615
2856
  : "number";
2616
- const coversDomain = nativeClass === "bool"
2857
+ const coversDomain = wide ? (paramType.flags & ts.TypeFlags.BigInt) !== 0 : nativeClass === "bool"
2617
2858
  ? (paramType.flags & ts.TypeFlags.Boolean) !== 0
2618
2859
  : nativeClass === "cstring" || nativeClass === "string"
2619
2860
  ? (paramType.flags & ts.TypeFlags.String) !== 0
@@ -2636,8 +2877,9 @@ function ffiCallbackInputDiagnostic(lowerer, descriptor, callbackType) {
2636
2877
  function ffiReturnDomainDiagnostic(lowerer, nativeClass, returnType) {
2637
2878
  if (nativeClass === "void")
2638
2879
  return null;
2639
- const domain = nativeClass === "bool" ? "boolean" : "number";
2640
- const coversDomain = nativeClass === "bool"
2880
+ const wide = nativeClass === "i64" || nativeClass === "u64" || nativeClass === "pointer";
2881
+ const domain = wide ? "bigint" : nativeClass === "bool" ? "boolean" : "number";
2882
+ const coversDomain = wide ? (returnType.flags & ts.TypeFlags.BigInt) !== 0 : nativeClass === "bool"
2641
2883
  ? (returnType.flags & ts.TypeFlags.Boolean) !== 0
2642
2884
  : (returnType.flags & ts.TypeFlags.Number) !== 0;
2643
2885
  return coversDomain
@@ -2745,7 +2987,7 @@ function libraryCallbackOwnsFile(lowerer, file) {
2745
2987
  export function validateFfiImports(lowerer) {
2746
2988
  const diagnostics = [];
2747
2989
  const symbolsByName = new Map();
2748
- const configuredNames = new Set(lowerer.ffiImports.map((binding) => binding.name));
2990
+ const configuredNames = new Set(lowerer.ffiImports.filter(binding => binding.library === undefined).map((binding) => binding.name));
2749
2991
  const candidates = new Map();
2750
2992
  if (configuredNames.size === 0)
2751
2993
  return { diagnostics, symbolsByName };
@@ -2775,6 +3017,8 @@ export function validateFfiImports(lowerer) {
2775
3017
  });
2776
3018
  }
2777
3019
  for (const binding of lowerer.ffiImports) {
3020
+ if (binding.library !== undefined)
3021
+ continue;
2778
3022
  const bySymbol = candidates.get(binding.name);
2779
3023
  if (bySymbol === undefined || bySymbol.size === 0) {
2780
3024
  // A native-manifest binding with no declaration is a broken build
@@ -2822,6 +3066,8 @@ export function lowerFfiCall(lowerer, expr) {
2822
3066
  if (!ts.isIdentifier(expr.expression))
2823
3067
  return null;
2824
3068
  const binding = lowerer.ffiImportsByName.get(expr.expression.text);
3069
+ if (binding?.library !== undefined)
3070
+ return null;
2825
3071
  if (binding === undefined) {
2826
3072
  // LIBRARY mode with a declared callback surface: a CALL of a
2827
3073
  // program-authored signature-only ambient function that names no
@@ -2855,7 +3101,8 @@ export function lowerFfiCall(lowerer, expr) {
2855
3101
  lowerer.pushDiag(signatureFlavor(binding.name, detail, loc));
2856
3102
  throw new PoisonError();
2857
3103
  };
2858
- const symbol = lowerer.resolveValueSymbol(expr.expression) ??
3104
+ const symbol = lowerer.resolveValueSymbol(expr.expression);
3105
+ if (!symbol)
2859
3106
  bindingError("the call has no resolved TypeScript symbol");
2860
3107
  if (lowerer.ffiBindingSymbols !== null) {
2861
3108
  const validSymbols = lowerer.ffiBindingSymbols.get(binding.name);
@@ -2938,7 +3185,7 @@ export function lowerFfiCall(lowerer, expr) {
2938
3185
  }
2939
3186
  // An inline function value at a RELEASE site can never match:
2940
3187
  // lifted lambdas always carry a captures list (even an empty one),
2941
- // so both backends mint a fresh closure per evaluation of the
3188
+ // so the backend creates a fresh closure per evaluation of the
2942
3189
  // expression — the release argument is a pointer no registration
2943
3190
  // holds, a guaranteed runtime trap. Declared functions stay valid
2944
3191
  // here — their value is the interned immortal closure (captures
@@ -3145,6 +3392,18 @@ export function lowerCall(lowerer, expr) {
3145
3392
  }
3146
3393
  const consoleMember = lowerer.consoleCallMember(expr);
3147
3394
  if (consoleMember !== null) {
3395
+ // A namespace returned by user code must evaluate before the log
3396
+ // arguments. Only the global and literal builtin require plumbing
3397
+ // have no receiver evaluation to preserve.
3398
+ const access = ts.isPropertyAccessExpression(expr.expression) ? expr.expression : null;
3399
+ const created = access && ts.isCallExpression(access.expression) ? createRequireSpecOf(lowerer, access.expression) : null;
3400
+ const receiver = access && !lowerer.isStdlibGlobal(access.expression, "console") &&
3401
+ requireSpecOf(access.expression) === null &&
3402
+ created?.spec !== "node:console" && created?.spec !== "console"
3403
+ ? lowerer.lowerExpr(access.expression) : null;
3404
+ const withReceiver = (result) => receiver === null ? result : {
3405
+ kind: "seqExpr", stmts: [{ kind: "exprStmt", expr: receiver, loc }], result, type: result.type, loc,
3406
+ };
3148
3407
  // console.log/info/debug write stdout; console.error and console.warn
3149
3408
  // are one stream in Node (warn IS error, info and debug ARE log) and
3150
3409
  // write stderr with the exact same formatting. Node's formatter is
@@ -3166,13 +3425,13 @@ export function lowerCall(lowerer, expr) {
3166
3425
  (ts.isStringLiteral(expr.arguments[0]) || ts.isNoSubstitutionTemplateLiteral(expr.arguments[0])) &&
3167
3426
  /%[sdifjoOc%]/.test(expr.arguments[0].text)) {
3168
3427
  const formatted = lowerFormatCall(lowerer, expr, loc, false);
3169
- return {
3428
+ return withReceiver({
3170
3429
  kind: "intrinsic",
3171
3430
  name: stdoutMember ? "console.log" : "console.error",
3172
3431
  args: [formatted],
3173
3432
  type: VOID,
3174
3433
  loc,
3175
- };
3434
+ });
3176
3435
  }
3177
3436
  const args = expr.arguments.map((a) => {
3178
3437
  const lowered = lowerer.lowerExpr(a);
@@ -3233,13 +3492,13 @@ export function lowerCall(lowerer, expr) {
3233
3492
  // render fence honestly with the reason.
3234
3493
  return lowerConsoleInspectArg(lowerer, a, lowered, surface, loc);
3235
3494
  });
3236
- return {
3495
+ return withReceiver({
3237
3496
  kind: "intrinsic",
3238
3497
  name: stdoutMember ? "console.log" : "console.error",
3239
3498
  args,
3240
3499
  type: VOID,
3241
3500
  loc,
3242
- };
3501
+ });
3243
3502
  }
3244
3503
  // The timer globals — setTimeout/clearTimeout, setInterval/
3245
3504
  // clearInterval, setImmediate/clearImmediate. Provenance-checked (a
@@ -3390,25 +3649,12 @@ export function lowerCall(lowerer, expr) {
3390
3649
  lowerer.noLowering(`BigInt with ${expr.arguments.length} arguments`, expr);
3391
3650
  }
3392
3651
  const argNode = expr.arguments[0];
3393
- const arg = lowerer.lowerExpr(argNode);
3394
- if (arg.type.kind === "bigint")
3395
- return arg;
3396
- if (arg.type.kind === "string") {
3397
- return { kind: "libCall", fn: "bigint.parse", args: [arg], type: BIGINT_T, loc };
3398
- }
3399
- if (arg.type.kind === "f64") {
3400
- return { kind: "libCall", fn: "bigint.fromF64", args: [arg], type: BIGINT_T, loc };
3401
- }
3402
- if (arg.type.kind === "bool") {
3403
- return {
3404
- kind: "ternary",
3405
- cond: arg,
3406
- then: { kind: "libCall", fn: "bigint.parse", args: [{ kind: "strLit", value: "1", type: STRING, loc }], type: BIGINT_T, loc },
3407
- else_: { kind: "libCall", fn: "bigint.parse", args: [{ kind: "strLit", value: "0", type: STRING, loc }], type: BIGINT_T, loc },
3408
- type: BIGINT_T,
3409
- loc,
3410
- };
3411
- }
3652
+ // Captured optional storage can change after TypeScript's guard.
3653
+ // BigInt consumes the stored value, including its nullish tag.
3654
+ const arg = optionalCallValue(lowerer, argNode) ?? lowerer.lowerExpr(argNode);
3655
+ const converted = lowerBigIntConstructorValue(lowerer, arg, loc);
3656
+ if (converted)
3657
+ return converted;
3412
3658
  lowerer.noLowering(`BigInt of ${lowerer.fmt(arg.type)} values`, argNode, "string, number, boolean, and bigint arguments are supported");
3413
3659
  }
3414
3660
  if (ts.isIdentifier(expr.expression) &&
@@ -3446,6 +3692,9 @@ export function lowerCall(lowerer, expr) {
3446
3692
  if (name === "Number")
3447
3693
  return lowerNumberConstructorValue(lowerer, argNode, loc);
3448
3694
  const arg = lowerer.lowerExpr(argNode);
3695
+ if (name === "String" && arg.type.kind === "dyn") {
3696
+ return { kind: "libCall", fn: "dyn.stringConstructor", args: [arg], type: STRING, loc };
3697
+ }
3449
3698
  if (name === "String")
3450
3699
  return lowerer.ensureString(arg, argNode);
3451
3700
  }
@@ -3463,6 +3712,29 @@ export function lowerCall(lowerer, expr) {
3463
3712
  const code = lowerer.lowerExprExpecting(expr.arguments[0], STRING);
3464
3713
  return { kind: "libCall", fn: "island.eval", args: [code], type: STRING, loc };
3465
3714
  }
3715
+ // Computed calls preserve their evaluated receiver just like dotted
3716
+ // calls, including when the property is keyed by a native symbol.
3717
+ if (ts.isElementAccessExpression(expr.expression) && !lowerer.chainBlocked(expr, expr.expression)) {
3718
+ const access = expr.expression;
3719
+ lowerer.fenceStaticResponseMember(access, "call");
3720
+ lowerer.fenceStaticHeadersMember(access, "call");
3721
+ lowerer.fenceStaticReadableStreamMember(access, "call");
3722
+ const source = tryLowerExpression(lowerer, access.expression);
3723
+ if (source && (source.type.kind === "dyn" || isDynTypedRefType(source.type) &&
3724
+ lowerer.foldedStringKeyOf(access.argumentExpression) === null &&
3725
+ lowerer.mapTypeOf(lowerer.typeOf(access.argumentExpression))?.kind !== "symbol")) {
3726
+ const local = lowerer.declareHiddenLocal("%computedReceiver", DYN);
3727
+ const receiver = varRef(local.id, DYN, loc);
3728
+ const key = lowerer.lowerExprExpecting(access.argumentExpression, DYN);
3729
+ const callee = { kind: "dynKeyGet", value: receiver, key, type: DYN, loc };
3730
+ const args = expr.arguments.map((arg) => lowerer.lowerExprExpecting(ts.isSpreadElement(arg) ? arg.expression : arg, DYN));
3731
+ const spreads = expr.arguments.flatMap((arg, index) => ts.isSpreadElement(arg) ? [{ arg: index, what: arg.expression.getText() }] : []);
3732
+ return { kind: "seqExpr", stmts: [{ kind: "varDecl", localId: local.id, init: lowerer.coerceToExpected(source, DYN), loc }], result: {
3733
+ kind: "dynCall", callee, receiver, calleeName: access.getText(), args,
3734
+ ...(spreads.length > 0 ? { spreads } : {}), type: DYN, loc,
3735
+ }, type: DYN, loc };
3736
+ }
3737
+ }
3466
3738
  // Island calls. A property-access callee whose receiver is an 'any'
3467
3739
  // value is an engine method call (this = receiver, JS-exact); any other
3468
3740
  // 'any'-typed callee is an engine function call. Arguments marshal in;
@@ -4061,6 +4333,9 @@ export function lowerCall(lowerer, expr) {
4061
4333
  let callee = lowerer.lowerExpr(nsMember);
4062
4334
  if (callee.type.kind === "record")
4063
4335
  callee = lowerer.hybridCallUnwrap(callee);
4336
+ const checked = lowerCheckedCallableValue(lowerer, expr, callee, loc);
4337
+ if (checked)
4338
+ return checked;
4064
4339
  if (callee.type.kind !== "func")
4065
4340
  lowerer.badType(expr.expression, lowerer.typeOf(expr.expression));
4066
4341
  const args = completeFuncValueArgs(lowerer, expr, callee.type, loc);
@@ -4114,6 +4389,9 @@ export function lowerCall(lowerer, expr) {
4114
4389
  let callee = lowerer.lowerExpr(nameId);
4115
4390
  if (callee.type.kind === "record")
4116
4391
  callee = lowerer.hybridCallUnwrap(callee);
4392
+ const checked = lowerCheckedCallableValue(lowerer, expr, callee, loc);
4393
+ if (checked)
4394
+ return checked;
4117
4395
  if (callee.type.kind !== "func")
4118
4396
  lowerer.badType(expr.expression, lowerer.typeOf(expr.expression));
4119
4397
  const args = completeFuncValueArgs(lowerer, expr, callee.type, loc);
@@ -4193,6 +4471,7 @@ export function lowerCall(lowerer, expr) {
4193
4471
  // TestContext surface (t.test/t.skip/t.diagnostic), t.assert.*.
4194
4472
  lowerer.lowerTestMethodCall(expr, expr.expression) ??
4195
4473
  lowerer.lowerTimeoutMethodCall(expr, expr.expression) ??
4474
+ lowerArrayPrototypeBorrowCall(lowerer, expr, expr.expression) ??
4196
4475
  lowerObjectOwnPrototypeCall(lowerer, expr, expr.expression) ??
4197
4476
  lowerObjectPrototypeCall(lowerer, expr, expr.expression) ??
4198
4477
  lowerStringPrototypeCall(lowerer, expr, expr.expression) ??
@@ -4200,6 +4479,7 @@ export function lowerCall(lowerer, expr) {
4200
4479
  // Typed-array/Buffer receivers and the Buffer statics — before the
4201
4480
  // island path (bytes never cross the boundary).
4202
4481
  lowerer.lowerBytesMethodCall(expr, expr.expression) ??
4482
+ lowerBytesStaticCall(lowerer, expr, expr.expression) ??
4203
4483
  lowerBufferStaticCallWithNarrowedArg(lowerer, expr, expr.expression) ??
4204
4484
  // URL.revokeObjectURL's zero-argument contract (the one-argument
4205
4485
  // form keeps the fence — createObjectURL does too).
@@ -4267,8 +4547,8 @@ export function lowerCall(lowerer, expr) {
4267
4547
  lowerArrayFromCall(lowerer, expr, expr.expression) ??
4268
4548
  lowerArrayOfCall(lowerer, expr, expr.expression) ??
4269
4549
  lowerer.lowerArrayMethodCall(expr, expr.expression) ??
4270
- // Read-only array methods (slice/map) on TUPLE receivers — the
4271
- // positions snapshot into a fresh array (the for-of stance).
4550
+ // Tuple reads preserve the receiver through argument evaluation;
4551
+ // callbacks read each position when visited.
4272
4552
  lowerTupleReadMethodCall(lowerer, expr, expr.expression) ??
4273
4553
  lowerGenMethodCall(lowerer, expr, expr.expression) ??
4274
4554
  lowerer.lowerMapMethodCall(expr, expr.expression) ??
@@ -4283,6 +4563,18 @@ export function lowerCall(lowerer, expr) {
4283
4563
  lowerObjLitGenericMethodCall(lowerer, expr, expr.expression);
4284
4564
  if (intrinsic)
4285
4565
  return intrinsic;
4566
+ const accessorTarget = lowerer.fieldTarget(expr.expression);
4567
+ if (accessorTarget?.container === "accessor") {
4568
+ const callee = lowerer.fieldGetExpr(accessorTarget, locOf(expr.expression), expr.expression);
4569
+ if (callee.type.kind === "func") {
4570
+ const args = completeFuncValueArgs(lowerer, expr, callee.type, locOf(expr));
4571
+ return { kind: "callValue", callee, args, type: callee.type.ret, loc: locOf(expr) };
4572
+ }
4573
+ if (callee.type.kind === "dyn" && !expr.arguments.some((arg) => ts.isSpreadElement(arg))) {
4574
+ const args = expr.arguments.map((arg) => lowerer.lowerExprExpecting(arg, DYN));
4575
+ return { kind: "dynCall", callee, calleeName: expr.expression.getText(), args, type: DYN, loc: locOf(expr) };
4576
+ }
4577
+ }
4286
4578
  // A method call rooted at an initializer-less ambient `declare
4287
4579
  // const/var` whose declared type has no mapping: Node throws the
4288
4580
  // catchable ReferenceError at the ROOT read before the member, the
@@ -4332,6 +4624,9 @@ export function lowerCall(lowerer, expr) {
4332
4624
  // The element spelling of an unsupported native Web method must fence
4333
4625
  // before lowering the callee into a checked-dynamic keyed read.
4334
4626
  if (ts.isElementAccessExpression(expr.expression)) {
4627
+ const symbolMethod = lowerClassSymbolMethodCall(lowerer, expr);
4628
+ if (symbolMethod)
4629
+ return symbolMethod;
4335
4630
  const headersIterator = lowerer.lowerDynamicHeadersIteratorCall(expr, expr.expression);
4336
4631
  if (headersIterator)
4337
4632
  return headersIterator;
@@ -4347,8 +4642,41 @@ export function lowerCall(lowerer, expr) {
4347
4642
  if (ts.isElementAccessExpression(expr.expression) &&
4348
4643
  !expr.expression.questionDotToken &&
4349
4644
  !expr.questionDotToken &&
4350
- ts.isStringLiteralLike(expr.expression.argumentExpression)) {
4351
- const memberName = expr.expression.argumentExpression.text;
4645
+ (ts.isStringLiteralLike(expr.expression.argumentExpression) || ts.isNumericLiteral(expr.expression.argumentExpression))) {
4646
+ const memberName = ts.isNumericLiteral(expr.expression.argumentExpression)
4647
+ ? String(Number(expr.expression.argumentExpression.text))
4648
+ : expr.expression.argumentExpression.text;
4649
+ const receiverType = lowerer.mapTypeOf(lowerer.typeOf(expr.expression.expression));
4650
+ if (receiverType?.kind === "object") {
4651
+ const info = lowerer.classes.get(receiverType.className);
4652
+ const found = info ? lowerer.findMethodOn(info, memberName) : null;
4653
+ if (info && found) {
4654
+ if (found.declarer.builtinError)
4655
+ return errorToStringCall(lowerer, lowerer.lowerExpr(expr.expression.expression));
4656
+ const virtual = lowerer.overrideBelow(info, memberName);
4657
+ if (found.sig.abstract === true && !virtual) {
4658
+ lowerer.unsupported("SC1090", expr, `calls of the abstract method '${memberName}' with no concrete implementation below the receiver's static class`);
4659
+ }
4660
+ if (virtual)
4661
+ lowerer.noteVirtualEdge(info, memberName);
4662
+ else
4663
+ lowerer.noteEdge(`%${found.declarer.def.name}.${memberName}`);
4664
+ const receiver = lowerer.lowerExpr(expr.expression.expression);
4665
+ const args = lowerer.completeArgs(expr.arguments, found.sig.params, locOf(expr), expr);
4666
+ const callArgs = [lowerer.upcastTo(receiver, virtual ? info.def.name : found.declarer.def.name), ...args];
4667
+ const loc = locOf(expr);
4668
+ if (virtual) {
4669
+ return reconcileOverloadReturn(lowerer, expr, {
4670
+ kind: "virtualCall", className: info.def.name, method: memberName,
4671
+ args: callArgs, type: found.sig.ret, loc,
4672
+ });
4673
+ }
4674
+ return reconcileOverloadReturn(lowerer, expr, {
4675
+ kind: "call", callee: `%${found.declarer.def.name}.${memberName}`,
4676
+ args: callArgs, type: found.sig.ret, loc,
4677
+ });
4678
+ }
4679
+ }
4352
4680
  // ts7's getSymbolAtLocation does not resolve element accesses; the
4353
4681
  // member symbol comes from the receiver's (apparent) type instead —
4354
4682
  // same provenance answer as the dot spelling's name symbol.
@@ -4446,7 +4774,7 @@ export function lowerCall(lowerer, expr) {
4446
4774
  // JS arity exactly (the thunk ignores extras). Result dyn, checked
4447
4775
  // per use like every any-origin value.
4448
4776
  if ((expr.arguments.length > callee.type.params.length || callee.type.rest === true) &&
4449
- isJsSourceFile(expr.getSourceFile()) &&
4777
+ (isJsSourceFile(expr.getSourceFile()) || callee.type.rest === true && callee.type.restAbi === undefined) &&
4450
4778
  !expr.arguments.some((a) => ts.isSpreadElement(a)) &&
4451
4779
  canBoxFuncIntoDyn(callee.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) {
4452
4780
  const args = expr.arguments.map((a) => lowerer.lowerExprExpecting(a, DYN));
@@ -4457,6 +4785,29 @@ export function lowerCall(lowerer, expr) {
4457
4785
  const args = completeFuncValueArgs(lowerer, expr, callee.type, loc);
4458
4786
  return { kind: "callValue", callee, args, type: callee.type.ret, loc };
4459
4787
  }
4788
+ /** Exported checked and variadic callables use the same runtime-arity ABI
4789
+ * whether the caller spells a bare import or a namespace member. */
4790
+ function lowerCheckedCallableValue(lowerer, call, value, loc) {
4791
+ let callee = value;
4792
+ if (callee.type.kind !== "dyn") {
4793
+ if (callee.type.kind !== "func" ||
4794
+ !(callee.type.rest === true && callee.type.restAbi === undefined ||
4795
+ isJsSourceFile(call.getSourceFile()) && call.arguments.length > callee.type.params.length) ||
4796
+ !lowerer.dynConvertible(callee.type))
4797
+ return null;
4798
+ callee = { kind: "dynFrom", value: callee, type: DYN, loc };
4799
+ }
4800
+ if (call.arguments.some(ts.isSpreadElement)) {
4801
+ const spread = lowerSpreadArgsCall(lowerer, call, callee, loc);
4802
+ if (spread)
4803
+ return spread;
4804
+ lowerer.unsupported("SC1090", call, "spread arguments in calls through 'unknown' values");
4805
+ }
4806
+ return {
4807
+ kind: "dynCall", callee, calleeName: call.expression.getText(),
4808
+ args: call.arguments.map((arg) => lowerer.lowerExprExpecting(arg, DYN)), type: DYN, loc,
4809
+ };
4810
+ }
4460
4811
  function lowerRegexMethodCallWithOptionalArg(lowerer, call, access) {
4461
4812
  const lowered = lowerer.lowerRegexMethodCall(call, access);
4462
4813
  if (lowered?.kind !== "regexIntrinsic" || lowered.method !== "test" || call.arguments.length !== 1)
@@ -4478,9 +4829,13 @@ function optionalCallValue(lowerer, node) {
4478
4829
  return lowerer.runtimeOptionalIdentifierValue(node)?.value ?? lowerAbsenceProbe(lowerer, node);
4479
4830
  }
4480
4831
  function lowerBufferStaticCallWithNarrowedArg(lowerer, call, access) {
4481
- const lowered = lowerer.lowerBufferStaticCall(call, access);
4832
+ const result = lowerer.lowerBufferStaticCall(call, access);
4833
+ // The Buffer brand wraps the constructor result. Normalize its source
4834
+ // before restoring that wrapper so narrowed unions never reach bytesNew.
4835
+ const branded = result?.kind === "libCall" && result.fn === "buffer.brand" ? result : null;
4836
+ const lowered = branded ? branded.args[0] : result;
4482
4837
  if (lowered?.kind !== "bytesNew" || !lowered.source || lowered.source.type.kind !== "union")
4483
- return lowered;
4838
+ return result;
4484
4839
  // A callback can store a wider union than the checker sees at this use
4485
4840
  // (including an added undefined arm). Extract the exact arm proven by
4486
4841
  // control-flow narrowing, not merely the union with undefined removed.
@@ -4496,10 +4851,11 @@ function lowerBufferStaticCallWithNarrowedArg(lowerer, call, access) {
4496
4851
  if (!helper) {
4497
4852
  lowerer.unsupported("SC1090", call.arguments[0], "a Buffer constructor argument whose narrowed type is not a stored source arm");
4498
4853
  }
4499
- return {
4854
+ const narrowedValue = {
4500
4855
  ...lowered,
4501
4856
  source: { kind: "call", callee: helper, args: [lowered.source], type: narrowed, loc: lowered.source.loc },
4502
4857
  };
4858
+ return branded ? { ...branded, args: [narrowedValue] } : narrowedValue;
4503
4859
  }
4504
4860
  function lowerOptionalNumberDefault(lowerer, value, dflt, loc) {
4505
4861
  const widened = lowerer.runtimeOptionalWidening(value.type, F64);
@@ -4554,6 +4910,8 @@ function lowerStringMethodCallWithOptionalArgs(lowerer, call, access, receiver,
4554
4910
  ? [1]
4555
4911
  : [];
4556
4912
  for (const index of zeroDefaultArgs) {
4913
+ if (index === undefined)
4914
+ continue;
4557
4915
  const value = args[index];
4558
4916
  if (!value)
4559
4917
  continue;
@@ -4599,6 +4957,8 @@ function lowerNumberConstructorValue(lowerer, argNode, loc) {
4599
4957
  }
4600
4958
  if (arg.type.kind === "string")
4601
4959
  return { kind: "libCall", fn: "num.fromString", args: [arg], type: F64, loc };
4960
+ if (arg.type.kind === "dyn")
4961
+ return { kind: "libCall", fn: "dyn.numberConstructor", args: [arg], type: F64, loc };
4602
4962
  const optionalNumber = lowerOptionalStringNumber(lowerer, arg, loc);
4603
4963
  if (optionalNumber)
4604
4964
  return optionalNumber;
@@ -4609,6 +4969,61 @@ function lowerNumberConstructorValue(lowerer, argNode, loc) {
4609
4969
  ? "unions of numbers, booleans, strings, null, and undefined lower — narrow other arms first"
4610
4970
  : undefined);
4611
4971
  }
4972
+ /** A runtime-optional local retains its full tagged storage even after a
4973
+ * checker guard. Dispatch BigInt by the actual value, including nullish
4974
+ * TypeErrors, rather than interpreting that storage as the narrowed arm. */
4975
+ function lowerBigIntConstructorValue(lowerer, arg, loc) {
4976
+ if (arg.type.kind === "bigint")
4977
+ return arg;
4978
+ if (arg.type.kind === "string")
4979
+ return { kind: "libCall", fn: "bigint.parse", args: [arg], type: BIGINT_T, loc };
4980
+ if (arg.type.kind === "f64")
4981
+ return { kind: "libCall", fn: "bigint.fromF64", args: [arg], type: BIGINT_T, loc };
4982
+ if (arg.type.kind === "bool") {
4983
+ return {
4984
+ kind: "ternary", cond: arg,
4985
+ then: { kind: "libCall", fn: "bigint.parse", args: [{ kind: "strLit", value: "1", type: STRING, loc }], type: BIGINT_T, loc },
4986
+ else_: { kind: "libCall", fn: "bigint.parse", args: [{ kind: "strLit", value: "0", type: STRING, loc }], type: BIGINT_T, loc },
4987
+ type: BIGINT_T, loc,
4988
+ };
4989
+ }
4990
+ if (isUnitType(arg.type)) {
4991
+ const name = arg.type.kind === "nullT" ? "null" : "undefined";
4992
+ return defaultAfterUndefined(arg, nodeThrowExpr(1, "", `Cannot convert ${name} to a BigInt`, BIGINT_T, loc));
4993
+ }
4994
+ if (arg.type.kind !== "union")
4995
+ return null;
4996
+ const unionId = arg.type.unionId;
4997
+ const arms = lowerer.unions.get(unionId)?.arms;
4998
+ if (!arms || !arms.every((arm) => arm.kind === "bigint" || arm.kind === "string" || arm.kind === "f64" || arm.kind === "bool" || isUnitType(arm)))
4999
+ return null;
5000
+ const key = `bigint.scalar:${unionId}`;
5001
+ let helper = lowerer.widthHelpers.get(key);
5002
+ if (!helper) {
5003
+ helper = `%bigint.scalar.${lowerer.widthHelpers.size}`;
5004
+ lowerer.widthHelpers.set(key, helper);
5005
+ const value = varRef("value.0", arg.type, loc);
5006
+ const body = [];
5007
+ arms.forEach((arm, tag) => {
5008
+ const narrowed = isUnitType(arm)
5009
+ ? { kind: "unitLit", unit: arm.kind === "nullT" ? "null" : "undefined", type: arm, loc }
5010
+ : { kind: "unionNarrow", unionId, tag, value, type: arm, loc };
5011
+ const converted = lowerBigIntConstructorValue(lowerer, narrowed, loc);
5012
+ if (!converted)
5013
+ throw new InternalCompilerError("BigInt scalar union has an unsupported arm");
5014
+ const ret = { kind: "return", value: converted, loc };
5015
+ body.push(tag === arms.length - 1 ? ret : {
5016
+ kind: "if", cond: { kind: "unionIsTag", unionId, tag, negated: false, value, type: BOOL, loc },
5017
+ then: [ret], else_: null, loc,
5018
+ });
5019
+ });
5020
+ lowerer.liftedFns.push({
5021
+ name: helper, params: [{ localId: "value.0", name: "value", type: arg.type }],
5022
+ returnType: BIGINT_T, locals: [{ id: "value.0", name: "value", type: arg.type, mutable: false }], body, loc,
5023
+ });
5024
+ }
5025
+ return { kind: "call", callee: helper, args: [arg], type: BIGINT_T, loc };
5026
+ }
4612
5027
  function immediatePrimitiveWrapperToString(lowerer, node) {
4613
5028
  const stringValue = stringWrapperToString(lowerer, node);
4614
5029
  if (stringValue)
@@ -4631,24 +5046,6 @@ function immediatePrimitiveWrapperToString(lowerer, node) {
4631
5046
  : args.length ? lowerNumberConstructorValue(lowerer, args[0], loc) : { kind: "numLit", value: 0, type: F64, loc };
4632
5047
  return lowerer.ensureString(primitive, wrapped);
4633
5048
  }
4634
- function plainObjectCoercionReceiver(lowerer, node) {
4635
- const plainLiteral = (literal) => literal.properties.every((prop) => ts.isPropertyAssignment(prop) &&
4636
- (ts.isIdentifier(prop.name) || ts.isStringLiteral(prop.name) || ts.isNumericLiteral(prop.name)) &&
4637
- prop.name.text !== "__proto__");
4638
- let value = node;
4639
- while (ts.isParenthesizedExpression(value))
4640
- value = value.expression;
4641
- if (ts.isObjectLiteralExpression(value))
4642
- return plainLiteral(value);
4643
- if (!ts.isIdentifier(value))
4644
- return false;
4645
- const symbol = lowerer.resolveValueSymbol(value);
4646
- const decl = symbol ? lowerer.checker.valueDeclarationOf(symbol) : undefined;
4647
- if (!symbol || !decl || !ts.isVariableDeclaration(decl) || !decl.initializer ||
4648
- !ts.isObjectLiteralExpression(decl.initializer) || !plainLiteral(decl.initializer))
4649
- return false;
4650
- return bindingNeverReassigned(lowerer, symbol, decl);
4651
- }
4652
5049
  function objectToStringTag(lowerer, type) {
4653
5050
  switch (type.kind) {
4654
5051
  case "undefinedT":
@@ -4669,7 +5066,7 @@ function objectToStringTag(lowerer, type) {
4669
5066
  case "set": return "Set";
4670
5067
  case "promise": return "Promise";
4671
5068
  case "bytes":
4672
- return ({ u8: "Uint8Array", u32: "Uint32Array", i32: "Int32Array", f32: "Float32Array", f64: "Float64Array" })[type.elem];
5069
+ return BYTES_ELEMENT_NAME[type.elem];
4673
5070
  case "object":
4674
5071
  return type.className === "%Error" || lowerer.isSubclassOf(type.className, "%Error") ? "Error" : null;
4675
5072
  default: return null;
@@ -4691,6 +5088,10 @@ function immediateObjectTagReceiver(lowerer, node) {
4691
5088
  lowerer.isStdlibSymbol(lowerer.resolveValueSymbol(value.expression) ?? undefined)) {
4692
5089
  const name = value.expression.text;
4693
5090
  const args = value.arguments ?? [];
5091
+ // JavaScript dates use checked native handles, so their IR type alone
5092
+ // cannot recover the tag through an immediate Object(...) wrapper.
5093
+ if (name === "Date")
5094
+ return { tag: "Date", effect: lowerer.lowerExpr(value) };
4694
5095
  if (args.length <= 1 && !args.some(ts.isSpreadElement)) {
4695
5096
  if (name === "String") {
4696
5097
  const effect = stringWrapperToString(lowerer, value);
@@ -4738,6 +5139,36 @@ function immediateObjectTagReceiver(lowerer, node) {
4738
5139
  }
4739
5140
  return null;
4740
5141
  }
5142
+ const ARRAY_BORROW_METHODS = new Set([
5143
+ "at", "every", "filter", "find", "findIndex", "findLast", "findLastIndex", "forEach", "includes",
5144
+ "indexOf", "lastIndexOf", "map", "reduce", "reduceRight", "slice", "some",
5145
+ ]);
5146
+ function lowerArrayPrototypeBorrowCall(lowerer, call, access) {
5147
+ if (lowerer.dynamic || !isJsSourceFile(call.getSourceFile()) || call.questionDotToken ||
5148
+ access.questionDotToken || access.name.text !== "call" ||
5149
+ !ts.isPropertyAccessExpression(access.expression) ||
5150
+ call.arguments.some(ts.isSpreadElement))
5151
+ return null;
5152
+ const method = access.expression;
5153
+ if (method.questionDotToken || !ARRAY_BORROW_METHODS.has(method.name.text) ||
5154
+ !ts.isPropertyAccessExpression(method.expression) ||
5155
+ method.expression.questionDotToken || method.expression.name.text !== "prototype" ||
5156
+ !lowerer.isStdlibGlobal(method.expression.expression, "Array") ||
5157
+ !lowerer.isStdlibMember(method))
5158
+ return null;
5159
+ const loc = locOf(call);
5160
+ const receiver = call.arguments[0]
5161
+ ? lowerer.lowerExprExpecting(call.arguments[0], DYN)
5162
+ : { kind: "dynFrom", value: { kind: "unitLit", unit: "undefined", type: UNDEFINED_T, loc }, type: DYN, loc };
5163
+ const args = call.arguments.slice(1).map((arg) => lowerer.lowerExprExpecting(arg, DYN));
5164
+ return {
5165
+ kind: "libCall", fn: "dyn.arrayProtoCall", args: [
5166
+ receiver,
5167
+ { kind: "strLit", value: method.name.text, type: STRING, loc },
5168
+ { kind: "dynArrLit", elems: args, type: DYN, loc },
5169
+ ], type: DYN, loc,
5170
+ };
5171
+ }
4741
5172
  function lowerObjectOwnPrototypeCall(lowerer, call, access) {
4742
5173
  if (lowerer.dynamic || access.name.text !== "call" || !ts.isPropertyAccessExpression(access.expression))
4743
5174
  return null;
@@ -4756,10 +5187,31 @@ function lowerObjectOwnMethodCall(lowerer, call, access) {
4756
5187
  const method = access.name.text;
4757
5188
  if (lowerer.dynamic || call.questionDotToken || access.questionDotToken ||
4758
5189
  (method !== "hasOwnProperty" && method !== "propertyIsEnumerable") ||
4759
- !lowerer.isStdlibMember(access) || call.arguments.some(ts.isSpreadElement))
5190
+ call.arguments.some(ts.isSpreadElement))
4760
5191
  return null;
5192
+ if (!lowerer.isStdlibMember(access)) {
5193
+ const receiver = tryLowerExpression(lowerer, access.expression);
5194
+ if (receiver?.type.kind !== "dyn")
5195
+ return null;
5196
+ }
4761
5197
  return lowerObjectOwnCall(lowerer, call, access.expression, call.arguments[0], call.arguments.slice(1), method);
4762
5198
  }
5199
+ /** ToPropertyKey for the scalar keys represented by native own-key
5200
+ * probes. A lowered array-loop key may carry an undefined arm even when
5201
+ * its checker type is string; that arm spells "undefined" at runtime. */
5202
+ function ownPropertyKey(lowerer, key) {
5203
+ if (key.type.kind === "string")
5204
+ return key;
5205
+ if (key.type.kind === "bigint") {
5206
+ return { kind: "libCall", fn: "bigint.toString", args: [key, numLit(10, key.loc)], type: STRING, loc: key.loc };
5207
+ }
5208
+ const scalar = (type) => type.kind === "string" || type.kind === "f64" || type.kind === "bool" || isUnitType(type);
5209
+ if (key.type.kind === "f64" || key.type.kind === "bool" || key.type.kind === "dyn" ||
5210
+ (key.type.kind === "union" && lowerer.unions.get(key.type.unionId)?.arms.every(scalar))) {
5211
+ return { kind: "toString", operand: key, type: STRING, loc: key.loc };
5212
+ }
5213
+ return null;
5214
+ }
4763
5215
  function lowerObjectOwnCall(lowerer, call, receiverNode, keyNode, extraNodes, method) {
4764
5216
  const enumerable = method === "propertyIsEnumerable";
4765
5217
  const loc = locOf(call);
@@ -4792,14 +5244,18 @@ function lowerObjectOwnCall(lowerer, call, receiverNode, keyNode, extraNodes, me
4792
5244
  stmts.push({ kind: "exprStmt", expr: effect, loc: locOf(extra) });
4793
5245
  }
4794
5246
  let key = keyRef;
5247
+ if (receiverRef.type.kind === "dyn" && keyRef && (keyRef.type.kind === "symbol" || keyRef.type.kind === "dyn")) {
5248
+ const result = { kind: "libCall", fn: enumerable ? "dyn.propertyIsEnumerableComputed" : "dyn.hasOwnComputed", args: [receiverRef, lowerer.coerceToExpected(keyRef, DYN)], type: BOOL, loc };
5249
+ return { kind: "seqExpr", stmts, result, type: BOOL, loc };
5250
+ }
4795
5251
  if (!keyNode || rawKey?.type.kind === "undefinedT" || rawKey?.type.kind === "void") {
4796
5252
  key = { kind: "strLit", value: "undefined", type: STRING, loc };
4797
5253
  }
4798
5254
  else if (rawKey?.type.kind === "nullT") {
4799
5255
  key = { kind: "strLit", value: "null", type: STRING, loc };
4800
5256
  }
4801
- else if (key && (key.type.kind === "f64" || key.type.kind === "bool" || key.type.kind === "bigint")) {
4802
- key = { kind: "toString", operand: key, type: STRING, loc };
5257
+ else if (key) {
5258
+ key = ownPropertyKey(lowerer, key);
4803
5259
  }
4804
5260
  if (!key || key.type.kind !== "string") {
4805
5261
  lowerer.noLowering("Object.prototype." + method + " with this property key", keyNode ?? call);
@@ -4811,13 +5267,13 @@ function lowerObjectOwnCall(lowerer, call, receiverNode, keyNode, extraNodes, me
4811
5267
  }
4812
5268
  else if (type.kind === "record") {
4813
5269
  const shape = lowerer.shapes.get(type.shapeId);
4814
- if (!shape || shape.tuple || shape.indexValue || shapeHasAccessorSlots(shape)) {
5270
+ if (!shape || shape.tuple || shapeHasAccessorSlots(shape)) {
4815
5271
  lowerer.noLowering("Object.prototype." + method + " over this record shape", receiverNode ?? call);
4816
5272
  }
4817
5273
  result = { kind: "call", callee: recordHasOwnHelper(lowerer, type.shapeId, loc), args: [receiverRef, key], type: BOOL, loc };
4818
5274
  }
4819
- else if (type.kind === "dyn" && !enumerable) {
4820
- result = { kind: "libCall", fn: "dyn.hasOwn", args: [receiverRef, key], type: BOOL, loc };
5275
+ else if (type.kind === "dyn") {
5276
+ result = { kind: "libCall", fn: enumerable ? "dyn.propertyIsEnumerable" : "dyn.hasOwn", args: [receiverRef, key], type: BOOL, loc };
4821
5277
  }
4822
5278
  else if (type.kind === "string" || type.kind === "array") {
4823
5279
  const needleLocal = lowerer.declareHiddenLocal("%ownIndex", F64);
@@ -4886,6 +5342,52 @@ function lowerObjectPrototypeCall(lowerer, call, access) {
4886
5342
  : { kind: "strLit", value: "[object " + tag + "]", type: STRING, loc };
4887
5343
  return { kind: "seqExpr", stmts, result, type: STRING, loc };
4888
5344
  }
5345
+ /** Function.call evaluates all arguments before RequireObjectCoercible and
5346
+ * ToString. Stabilize them before reusing the ordinary string method lowering,
5347
+ * so a boxed nullish receiver or a coercion hook cannot reorder effects. */
5348
+ function lowerDynamicStringPrototypeCall(lowerer, call, methodAccess, receiver, method) {
5349
+ const loc = locOf(call);
5350
+ const receiverLocal = lowerer.declareHiddenLocal("%stringCallReceiver", receiver.type);
5351
+ const stmts = [{ kind: "varDecl", localId: receiverLocal.id, init: receiver, loc }];
5352
+ const receiverRef = varRef(receiverLocal.id, receiver.type, loc);
5353
+ const converted = {
5354
+ kind: "ternary",
5355
+ cond: { kind: "dynTest", test: "nullish", value: receiverRef, type: BOOL, loc },
5356
+ then: nodeThrowExpr(1, "", `String.prototype.${method} called on null or undefined`, STRING, loc),
5357
+ else_: { kind: "libCall", fn: "dyn.toStringCoerce", args: [receiverRef], type: STRING, loc },
5358
+ type: STRING, loc,
5359
+ };
5360
+ const overrides = [];
5361
+ try {
5362
+ for (const node of call.arguments.slice(1)) {
5363
+ const undefinedValue = lowerStaticallyUndefinedArgument(lowerer, node);
5364
+ const value = undefinedValue ?? lowerer.lowerExpr(node);
5365
+ let ref;
5366
+ if (undefinedValue || isUnitType(value.type) || value.type.kind === "void") {
5367
+ stmts.push({ kind: "exprStmt", expr: value, loc: value.loc });
5368
+ const nullUnit = !undefinedValue && value.type.kind === "nullT";
5369
+ ref = { kind: "unitLit", unit: nullUnit ? "null" : "undefined", type: nullUnit ? value.type : UNDEFINED_T, loc: value.loc };
5370
+ }
5371
+ else {
5372
+ const local = lowerer.declareHiddenLocal("%stringCallArg", value.type);
5373
+ stmts.push({ kind: "varDecl", localId: local.id, init: value, loc: value.loc });
5374
+ ref = varRef(local.id, value.type, value.loc);
5375
+ }
5376
+ overrides.push({ node, previous: lowerer.chainRecvByNode.get(node) });
5377
+ lowerer.chainRecvByNode.set(node, ref);
5378
+ }
5379
+ const result = lowerStringMethodCallWithOptionalArgs(lowerer, call, methodAccess, () => converted, call.arguments.slice(1));
5380
+ return result ? { kind: "seqExpr", stmts, result, type: result.type, loc } : null;
5381
+ }
5382
+ finally {
5383
+ for (const override of overrides) {
5384
+ if (override.previous)
5385
+ lowerer.chainRecvByNode.set(override.node, override.previous);
5386
+ else
5387
+ lowerer.chainRecvByNode.delete(override.node);
5388
+ }
5389
+ }
5390
+ }
4889
5391
  function lowerStringPrototypeCall(lowerer, call, access) {
4890
5392
  if (access.name.text !== "call" || !ts.isPropertyAccessExpression(access.expression))
4891
5393
  return null;
@@ -4928,6 +5430,9 @@ function lowerStringPrototypeCall(lowerer, call, access) {
4928
5430
  loc,
4929
5431
  };
4930
5432
  }
5433
+ if (receiverType.kind === "dyn") {
5434
+ return lowerDynamicStringPrototypeCall(lowerer, call, methodAccess, receiverValue, method);
5435
+ }
4931
5436
  const padding = entry?.method === "padStart" || entry?.method === "padEnd";
4932
5437
  const scalar = receiverType.kind === "string" || receiverType.kind === "f64" ||
4933
5438
  receiverType.kind === "bool" || receiverType.kind === "bigint" ||
@@ -4936,10 +5441,8 @@ function lowerStringPrototypeCall(lowerer, call, access) {
4936
5441
  // padding uses a helper that delays conversion until every argument is ready.
4937
5442
  const objectWithoutMethodArgs = entry?.maxArgs === 0 && call.arguments.length === 1 &&
4938
5443
  (receiverType.kind === "record" || receiverType.kind === "array" || receiverType.kind === "object");
4939
- const dynObjectWithoutMethodArgs = entry?.maxArgs === 0 && call.arguments.length === 1 &&
4940
- receiverType.kind === "dyn" && plainObjectCoercionReceiver(lowerer, receiverNode);
4941
- if (!scalar && !objectWithoutMethodArgs && !dynObjectWithoutMethodArgs && !(padding && receiverType.kind === "dyn")) {
4942
- return lowerer.noLowering(`String.prototype.${methodAccess.name.text}.call with ${lowerer.fmt(receiverType)} receivers`, call);
5444
+ if (!scalar && !objectWithoutMethodArgs) {
5445
+ lowerer.noLowering(`String.prototype.${methodAccess.name.text}.call with ${lowerer.fmt(receiverType)} receivers`, call);
4943
5446
  }
4944
5447
  if (indexMethod)
4945
5448
  return lowerStringIndexCall(lowerer, call, indexMethod, receiverValue, receiverNode, call.arguments.slice(1));
@@ -4951,9 +5454,7 @@ function lowerStringPrototypeCall(lowerer, call, access) {
4951
5454
  if (entry.method === "split") {
4952
5455
  return lowerStringSplitCall(lowerer, call, receiverValue, receiverNode, call.arguments.slice(1));
4953
5456
  }
4954
- const receiver = dynObjectWithoutMethodArgs
4955
- ? { kind: "libCall", fn: "dyn.toStringCoerce", args: [receiverValue], type: STRING, loc }
4956
- : lowerer.ensureString(receiverValue, receiverNode);
5457
+ const receiver = lowerer.ensureString(receiverValue, receiverNode);
4957
5458
  return lowerStringMethodCallWithOptionalArgs(lowerer, call, methodAccess, () => receiver, call.arguments.slice(1));
4958
5459
  }
4959
5460
  function lowerScalarUnionNumber(lowerer, arg, node, loc) {
@@ -5127,13 +5628,18 @@ function spreadNeedsRuntimeArity(lowerer, shapes, argNodes) {
5127
5628
  position += tuple.fields.length;
5128
5629
  continue;
5129
5630
  }
5130
- if (restAt < 0 || position < restAt || shapes[restAt].mode !== "rest")
5131
- return true;
5631
+ if (restAt < 0 || position < restAt || shapes[restAt].mode !== "rest") {
5632
+ return !canCompleteRuntimeSpread(lowerer, shapes);
5633
+ }
5132
5634
  }
5133
5635
  position++;
5134
5636
  }
5135
5637
  return false;
5136
5638
  }
5639
+ function canCompleteRuntimeSpread(lowerer, shapes) {
5640
+ return shapes.length > 0 && shapes.every((shape) => shape.mode !== "islandRest" && shape.callDefault === undefined &&
5641
+ canDynCheckTo(shape.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id)));
5642
+ }
5137
5643
  /** METHOD calls on dyn receivers (`pkg.name.replace(...)`, `rawName.split`,
5138
5644
  * `ws.packages.filter(...)` — JSON.parse-derived values): validate the
5139
5645
  * receiver's dyn kind, extract, and ride the STATIC method machinery — the
@@ -5171,6 +5677,27 @@ function lowerDynReceiverMethodCall(lowerer, call, access) {
5171
5677
  // tsc types the return by the evolved shape, the binding lowered
5172
5678
  // dyn): probe the lowering and claim exactly the dyn results.
5173
5679
  const probed = tryLowerExpression(lowerer, access.expression);
5680
+ if (isJsSourceFile(call.getSourceFile()) && probed?.type.kind === "func" &&
5681
+ !["call", "apply", "bind", "toString", "valueOf", "constructor"].includes(access.name.text) &&
5682
+ canBoxFuncIntoDyn(probed.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) {
5683
+ const loc = locOf(call);
5684
+ const fnName = jsFuncNameOf(access.expression);
5685
+ const boxed = { kind: "dynFrom", value: probed, type: DYN, loc, ...(fnName !== null ? { fnName } : {}) };
5686
+ const local = lowerer.declareHiddenLocal("%callableReceiver", DYN);
5687
+ const receiver = { kind: "varRef", localId: local.id, type: DYN, loc };
5688
+ const member = {
5689
+ kind: "dynKeyGet", value: receiver,
5690
+ key: { kind: "strLit", value: access.name.text, type: STRING, loc }, type: DYN, loc,
5691
+ };
5692
+ if (call.arguments.some(ts.isSpreadElement)) {
5693
+ lowerer.unsupported("SC1090", call, "spread arguments in callable property calls");
5694
+ }
5695
+ return {
5696
+ kind: "seqExpr", stmts: [{ kind: "varDecl", localId: local.id, init: boxed, loc }],
5697
+ result: { kind: "dynCall", callee: member, receiver, calleeName: access.getText(),
5698
+ args: call.arguments.map((arg) => lowerer.lowerExprExpecting(arg, DYN)), type: DYN, loc }, type: DYN, loc,
5699
+ };
5700
+ }
5174
5701
  if (probed?.type.kind !== "dyn")
5175
5702
  return null;
5176
5703
  recv = probed;
@@ -5178,11 +5705,30 @@ function lowerDynReceiverMethodCall(lowerer, call, access) {
5178
5705
  // A checker-`any` receiver that already lowered to a real STRING (the
5179
5706
  // chained form — `cfg.host.trim().toLowerCase()`, where the first step
5180
5707
  // extracted): no validation needed, ride the string tables directly.
5708
+ if (recv.type.kind === "union" && lowerer.stripUndefinedArm(recv.type).kind === "string") {
5709
+ const present = lowerer.runtimeOptionalPropertyReceiver(access.expression, recv, STRING, access.name.text);
5710
+ if (present)
5711
+ recv = present;
5712
+ }
5181
5713
  if (recv.type.kind === "string") {
5182
5714
  return lowerRegexMethodCall(lowerer, call, access, () => recv) ?? lowerStringMethodCall(lowerer, call, access, () => recv);
5183
5715
  }
5184
5716
  if (recv.type.kind !== "dyn")
5185
5717
  return null;
5718
+ if (lowerer.mapTypeOf(recvTs)?.kind === "classval") {
5719
+ return lowerStaticMethodCall(lowerer, call, access);
5720
+ }
5721
+ const ownCallable = !checkerUntyped && (() => {
5722
+ const prop = lowerer.checker.getPropertyOfType(recvTs, access.name.text);
5723
+ if (prop === undefined)
5724
+ return false;
5725
+ // getPropertyOfType includes inherited Object.prototype members.
5726
+ // Those are not stored members of a checked-dynamic object, so
5727
+ // dynKeyGet cannot stand in for JavaScript's prototype lookup. Only
5728
+ // an authored declaration can justify the own-member path.
5729
+ const authored = lowerer.checker.declarationsOf(prop).some((decl) => !lowerer.isStdlibFile(decl.getSourceFile()));
5730
+ return authored && lowerer.checker.getCallSignatures(lowerer.checker.getTypeOfSymbol(prop)).length > 0;
5731
+ })();
5186
5732
  // Typed-destination filter first (validated extraction into a real
5187
5733
  // T[]); an untyped destination falls through to the runtime dispatch
5188
5734
  // below (the survivors stay dyn values).
@@ -5198,34 +5744,21 @@ function lowerDynReceiverMethodCall(lowerer, call, access) {
5198
5744
  // these, "the receiver is a string, or the call throws V8's TypeError"
5199
5745
  // IS Node's semantics for every possible dyn value. Shared names would
5200
5746
  // need a receiver-kind dispatch — they keep the fence.
5201
- if (DYN_STRING_ONLY_METHODS.has(access.name.text)) {
5747
+ if (DYN_STRING_ONLY_METHODS.has(access.name.text) && !ownCallable) {
5202
5748
  const checked = () => dynStringReceiver(lowerer, recv, access);
5203
5749
  return lowerRegexMethodCall(lowerer, call, access, checked) ?? lowerStringMethodCall(lowerer, call, access, checked);
5204
5750
  }
5205
- // toString() is a shared prototype name with its OWN receiver-kind
5206
- // dispatched runtime lowering (dyn.toString: Buffer-flavored bytes
5207
- // decode per the encoding — a stream chunk's common consumption —
5208
- // and strings/numbers/booleans/arrays/objects answer JS-exactly).
5209
- // The optional argument is a literal encoding (meaningful for bytes;
5210
- // JS ignores extra toString arguments on the other kinds, and so
5211
- // does the runtime dispatch).
5751
+ // The argument is a radix for bigint and an encoding for Buffer.
5752
+ // Preserve its runtime value so receiver dispatch can choose correctly.
5212
5753
  if (access.name.text === "toString" && call.arguments.length <= 1) {
5213
- const enc = call.arguments[0]
5214
- ? bufEncoding(lowerer, "toString", call.arguments[0])
5215
- : "utf8";
5216
- // The source spelling rides along for the ONE receiver whose
5217
- // prototype lacks toString: a null-prototype dictionary throws
5218
- // Node's "<spelling> is not a function" at runtime.
5754
+ const argument = call.arguments[0];
5219
5755
  return {
5220
- kind: "libCall",
5221
- fn: "dyn.toString",
5222
- args: [
5756
+ kind: "libCall", fn: "dyn.toString", args: [
5223
5757
  recv,
5224
- { kind: "strLit", value: enc, type: STRING, loc: locOf(call) },
5758
+ argument ? lowerer.lowerExprExpecting(argument, DYN)
5759
+ : dynUndefinedExpr(locOf(call)),
5225
5760
  { kind: "strLit", value: access.getText(), type: STRING, loc: locOf(call) },
5226
- ],
5227
- type: STRING,
5228
- loc: locOf(call),
5761
+ ], type: STRING, loc: locOf(call),
5229
5762
  };
5230
5763
  }
5231
5764
  // SHARED prototype names with a runtime dispatch (scr_dyn_invoke):
@@ -5256,17 +5789,6 @@ function lowerDynReceiverMethodCall(lowerer, call, access) {
5256
5789
  // its name overlaps a primitive prototype (`colors.bold(...)`): the
5257
5790
  // source value was compiled from that object shape, while genuinely
5258
5791
  // untyped/any receivers retain the runtime-kind ambiguity and fence.
5259
- const ownCallable = !checkerUntyped && (() => {
5260
- const prop = lowerer.checker.getPropertyOfType(recvTs, access.name.text);
5261
- if (prop === undefined)
5262
- return false;
5263
- // getPropertyOfType includes inherited Object.prototype members.
5264
- // Those are not stored members of a checked-dynamic object, so
5265
- // dynKeyGet cannot stand in for JavaScript's prototype lookup. Only
5266
- // an authored declaration can justify the own-member path.
5267
- const authored = lowerer.checker.declarationsOf(prop).some((decl) => !lowerer.isStdlibFile(decl.getSourceFile()));
5268
- return authored && lowerer.checker.getCallSignatures(lowerer.checker.getTypeOfSymbol(prop)).length > 0;
5269
- })();
5270
5792
  if (DYN_PROTO_METHOD_NAMES.has(access.name.text) && !ownCallable)
5271
5793
  return null;
5272
5794
  // Optional forms (`obj.cb?.()`, `obj?.cb()`) belong to the chain
@@ -5277,15 +5799,20 @@ function lowerDynReceiverMethodCall(lowerer, call, access) {
5277
5799
  if (call.arguments.some((a) => ts.isSpreadElement(a))) {
5278
5800
  lowerer.unsupported("SC1090", call, "spread arguments in calls through 'unknown' values");
5279
5801
  }
5802
+ const receiverLocal = lowerer.declareHiddenLocal("%dynCallReceiver", DYN);
5803
+ const receiver = { kind: "varRef", localId: receiverLocal.id, type: DYN, loc };
5280
5804
  const member = {
5281
5805
  kind: "dynKeyGet",
5282
5806
  key: { kind: "strLit", value: access.name.text, type: STRING, loc: locOf(access) },
5283
- value: recv,
5807
+ value: receiver,
5284
5808
  type: DYN,
5285
5809
  loc: locOf(access),
5286
5810
  };
5287
5811
  const args = call.arguments.map((a) => lowerer.lowerExprExpecting(a, DYN));
5288
- return { kind: "dynCall", callee: member, calleeName: access.getText(), args, type: DYN, loc };
5812
+ return {
5813
+ kind: "seqExpr", stmts: [{ kind: "varDecl", localId: receiverLocal.id, init: recv, loc }],
5814
+ result: { kind: "dynCall", callee: member, receiver, calleeName: access.getText(), args, type: DYN, loc }, type: DYN, loc,
5815
+ };
5289
5816
  }
5290
5817
  /** Prototype method names of the checked-dynamic tree-representable kinds (String, Array,
5291
5818
  * Object, Function, Number prototypes): a dyn receiver call on one of
@@ -5312,7 +5839,8 @@ const DYN_PROTO_METHOD_NAMES = new Set([
5312
5839
  * is-not-a-function where the kind's prototype lacks the name, and
5313
5840
  * fences LOUDLY on real-but-unimplemented pairs. */
5314
5841
  const DYN_DISPATCH_METHODS = new Set([
5315
- "apply", "call",
5842
+ "segment", "containing", "resolvedOptions", "test", "exec",
5843
+ "apply", "bind", "call",
5316
5844
  "push", "pop", "shift", "unshift", "slice", "at",
5317
5845
  "indexOf", "lastIndexOf", "includes", "join", "concat", "reverse", "sort",
5318
5846
  "forEach", "map", "filter", "some", "every", "find", "findIndex",
@@ -5330,7 +5858,7 @@ const DYN_DISPATCH_METHODS = new Set([
5330
5858
  "setEncoding", "setDefaultEncoding", "setTimeout", "read", "isPaused",
5331
5859
  "writeHead", "setHeader", "getHeader", "hasHeader", "removeHeader",
5332
5860
  "getHeaders", "getHeaderNames", "appendHeader", "flushHeaders",
5333
- "append", "delete", "get", "getSetCookie", "has", "set",
5861
+ "add", "append", "delete", "get", "getSetCookie", "has", "set",
5334
5862
  "writeContinue", "writeEarlyHints", "cork", "uncork", "addTrailers",
5335
5863
  "ref", "unref", "address", "setNoDelay", "setKeepAlive", "connect",
5336
5864
  "resetAndDestroy", "destroySoon",
@@ -5368,7 +5896,7 @@ const DYN_DISPATCH_METHODS = new Set([
5368
5896
  ]);
5369
5897
  export function lowerDynDispatchMethodCall(lowerer, call, access, recv, arrayReceiver) {
5370
5898
  const method = access.name.text;
5371
- if (!DYN_DISPATCH_METHODS.has(method) || call.questionDotToken || access.questionDotToken)
5899
+ if ((!DYN_DISPATCH_METHODS.has(method) && !isJsSourceFile(call.getSourceFile())) || lowerer.chainBlocked(call, access))
5372
5900
  return null;
5373
5901
  if (call.arguments.some((arg) => ts.isSpreadElement(arg))) {
5374
5902
  lowerer.unsupported("SC1090", call, "spread arguments in calls through 'unknown' values");
@@ -5494,7 +6022,8 @@ function lowerArrayIsArrayCall(lowerer, call, access) {
5494
6022
  // over side-effect-free reads (the operand re-evaluates/drops, the
5495
6023
  // `in`-operator fold discipline). dyn/caught/jsval arms have no
5496
6024
  // static tag answer and keep the narrow-first fence.
5497
- const def = lowerer.unions.get(arg.type.unionId);
6025
+ const unionId = arg.type.unionId;
6026
+ const def = lowerer.unions.get(unionId);
5498
6027
  const opaque = !def || def.arms.some((a) => a.kind === "dyn" || a.kind === "caught" || a.kind === "jsval");
5499
6028
  const arrayTags = lowerer.arrayValueTags(arg.type.unionId);
5500
6029
  const freeRead = arg.kind === "varRef" || arg.kind === "recordGet" || arg.kind === "fieldGet";
@@ -5506,7 +6035,7 @@ function lowerArrayIsArrayCall(lowerer, call, access) {
5506
6035
  }
5507
6036
  if (!opaque && freeRead && arrayTags.length > 1) {
5508
6037
  return arrayTags
5509
- .map((tag) => ({ kind: "unionIsTag", unionId: arg.type.unionId, tag, negated: false, value: arg, type: BOOL, loc }))
6038
+ .map((tag) => ({ kind: "unionIsTag", unionId: unionId, tag, negated: false, value: arg, type: BOOL, loc }))
5510
6039
  .reduce((left, right) => ({ kind: "logical", op: "||", left, right, type: BOOL, loc }));
5511
6040
  }
5512
6041
  lowerer.unsupported("SC1090", argNode, `Array.isArray on '${lowerer.fmt(arg.type)}' values (narrow first: check a discriminant field, or compare with '!== undefined'/'!== null' for unit arms)`);
@@ -5727,6 +6256,13 @@ function lowerClassHasOwnPropertyCall(lowerer, call, access) {
5727
6256
  else
5728
6257
  return null; // computed static names — the answer isn't static
5729
6258
  }
6259
+ if (!own.has(key)) {
6260
+ const loc = locOf(call);
6261
+ const data = classStaticDataFor(lowerer, info, key, loc);
6262
+ if (data)
6263
+ return { kind: "libCall", fn: "dyn.hasOwn", args: [data,
6264
+ { kind: "strLit", value: key, type: STRING, loc }], type: BOOL, loc };
6265
+ }
5730
6266
  return { kind: "boolLit", value: own.has(key), type: BOOL, loc: locOf(call) };
5731
6267
  }
5732
6268
  /** Side-effect-free receiver test for the CONSTANT primitive-prototype
@@ -5941,6 +6477,12 @@ function implicitReceiverOverloadReturn(lowerer, expr) {
5941
6477
  function reconcileOverloadReturn(lowerer, expr, call) {
5942
6478
  const rsig = lowerer.checker.getResolvedSignature(expr);
5943
6479
  const rdecl = rsig ? lowerer.checker.signatureDeclaration(rsig) : undefined;
6480
+ // Fluent JS overrides share the base's return ABI, but their result
6481
+ // still has the receiver's subclass layout at the call site.
6482
+ if (call.type.kind === "object" && rdecl && ts.isMethodDeclaration(rdecl) &&
6483
+ isJsSourceFile(rdecl.getSourceFile()) && returnsOnlyThis(rdecl)) {
6484
+ call = lowerer.maybeNarrow(call, expr);
6485
+ }
5944
6486
  const resolvedOverload = rsig && rdecl &&
5945
6487
  (ts.isFunctionDeclaration(rdecl) || ts.isMethodDeclaration(rdecl)) &&
5946
6488
  !rdecl.body
@@ -6147,7 +6689,7 @@ export function lowerTaggedTemplate(lowerer, expr) {
6147
6689
  }
6148
6690
  function loweredTemplateStrings(lowerer, expr, cooked, loc) {
6149
6691
  // Normal runtime construction keeps this array aligned with the current
6150
- // ScrArr layout in both backends. The old static-header IR node encoded the
6692
+ // ScrArr layout in the backend. The old static-header IR node encoded the
6151
6693
  // pre-sparse layout in LLVM and crashed as soon as a tag read its strings.
6152
6694
  const type = arrayOf(STRING);
6153
6695
  const key = `templateStringsGlobal:${loc.file}:${expr.template.getStart()}`;
@@ -6204,7 +6746,7 @@ export function isTopLevelFnSymbol(lowerer, ident) {
6204
6746
  const decl = symbol ? lowerer.checker.declarationsOf(symbol)[0] : undefined;
6205
6747
  return (!!decl &&
6206
6748
  ts.isFunctionDeclaration(decl) &&
6207
- (ts.isSourceFile(decl.parent) || lowerer.nsBlocks.get(decl.parent) === "flattened"));
6749
+ (ts.isSourceFile(decl.parent) || (decl.parent !== undefined && lowerer.nsBlocks.get(decl.parent) === "flattened")));
6208
6750
  }
6209
6751
  /** Nested `function name(...) {...}`: declare the mutable function binding
6210
6752
  * before lowering its body, then initialize it with the lifted closure.
@@ -6246,6 +6788,22 @@ export function lowerNestedFunctionDecl(lowerer, stmt) {
6246
6788
  export function lambdaSignature(lowerer, node) {
6247
6789
  if (!node.body)
6248
6790
  lowerer.unsupported("SC1090", node, "function overload signatures");
6791
+ // A JS replacement of a native stream's write method receives the
6792
+ // actual call tuple, including overloads and omitted arguments. Node's
6793
+ // contextual overload signature cannot define this closure's ABI.
6794
+ if (isJsSourceFile(node.getSourceFile()) && !node.type &&
6795
+ (ts.isFunctionExpression(node) || ts.isArrowFunction(node)) &&
6796
+ node.parameters.every((param) => !param.type && !param.dotDotDotToken && !param.initializer) &&
6797
+ ts.isBinaryExpression(node.parent) && node.parent.right === node &&
6798
+ node.parent.operatorToken.kind === ts.SyntaxKind.EqualsToken &&
6799
+ ts.isPropertyAccessExpression(node.parent.left) && node.parent.left.name.text === "write" &&
6800
+ lowerer.isStdlibMember(node.parent.left)) {
6801
+ const receiver = lowerer.lowerExpr(node.parent.left.expression);
6802
+ if (receiver.type.kind === "dyn") {
6803
+ const shapes = node.parameters.map(() => ({ type: DYN, mode: "required" }));
6804
+ return { shapes, funcType: funcTypeFromParamShapes(shapes, DYN) };
6805
+ }
6806
+ }
6249
6807
  if (node.typeParameters) {
6250
6808
  // Generic function-like forms monomorphize only where a static home
6251
6809
  // exists: top-level generic function declarations, generic methods
@@ -6271,8 +6829,8 @@ export function lambdaSignature(lowerer, node) {
6271
6829
  : lowerer.declaredReturnType(node, node);
6272
6830
  ret = lowerer.runtimeOptionalFunctionReturnType(node, ret);
6273
6831
  // A contextually-typed arrow/function EXPRESSION whose slot signature
6274
- // returns a UNION the inferred return doesn't spell adopts the slot's
6275
- // return as its ABI: `(n) => work()` (inferring Promise<void>) against
6832
+ // returns a composite type the inferred return doesn't spell adopts
6833
+ // the slot's return as its ABI: `(n) => work()` (inferring Promise<void>) against
6276
6834
  // an `(n) => Promise<void> | void` field must RETURN that union — the
6277
6835
  // body's returns coerce into it per return site (arm values wrap;
6278
6836
  // width-coercible records rebuild into their arm — the runJobs
@@ -6286,6 +6844,9 @@ export function lambdaSignature(lowerer, node) {
6286
6844
  // returns coerce; the spawn-wrapper ABI still returns a promise).
6287
6845
  // jsval-returning bodies stay out (adoption would force validated
6288
6846
  // exits the writer never asked for).
6847
+ // Array and record returns also need the destination during literal
6848
+ // construction: a callback building IrStmt[] must wrap each element at
6849
+ // that recursive layout instead of first inferring narrower arrays.
6289
6850
  const isAsyncLike = !ts.isMethodDeclaration(node) &&
6290
6851
  node.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword) === true;
6291
6852
  const innerRet = isAsyncLike && ret.kind === "promise" ? ret.inner : ret;
@@ -6310,8 +6871,8 @@ export function lambdaSignature(lowerer, node) {
6310
6871
  ? lowerer.mapTypeOf(lowerer.checker.getReturnTypeOfSignature(ctxSigs[0]))
6311
6872
  : null;
6312
6873
  const ctxRet = isAsyncLike && ctxRetRaw?.kind === "promise" ? ctxRetRaw.inner : ctxRetRaw;
6313
- if (ctxRet?.kind === "union" &&
6314
- (innerRet.kind === "void" ? lowerer.armTag(ctxRet.unionId, UNDEFINED_T) >= 0 : true)) {
6874
+ if ((ctxRet?.kind === "union" || ctxRet?.kind === "array" || ctxRet?.kind === "record") &&
6875
+ (innerRet.kind !== "void" || (ctxRet.kind === "union" && lowerer.armTag(ctxRet.unionId, UNDEFINED_T) >= 0))) {
6315
6876
  ret = isAsyncLike ? { kind: "promise", inner: ctxRet } : ctxRet;
6316
6877
  }
6317
6878
  // A VOID slot discards the callback's result (TS's void-returning
@@ -6331,24 +6892,27 @@ export function lambdaSignature(lowerer, node) {
6331
6892
  ret = VOID;
6332
6893
  }
6333
6894
  }
6895
+ ret = lowerer.contextualFunctionReturns.get(node) ?? ret;
6334
6896
  // A plain JS function reading `arguments` receives one hidden dyn
6335
6897
  // array. With named parameters, the array contains every actual
6336
6898
  // argument and only ES modules are admitted: sloppy-mode arguments
6337
6899
  // alias named parameters. Arrows inherit the enclosing `arguments`.
6338
6900
  const hasRest = shapes.some((s) => s.mode === "rest" || s.mode === "dynRest" || s.mode === "islandRest");
6339
6901
  const usesArguments = !hasRest &&
6340
- (ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node)) &&
6902
+ (ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node) || ts.isMethodDeclaration(node)) &&
6341
6903
  isJsSourceFile(node.getSourceFile()) &&
6342
6904
  bodyReadsArguments(node);
6343
- if (usesArguments && node.parameters.length > 0) {
6344
- if (!isNodeEsmFile(node.getSourceFile())) {
6345
- lowerer.unsupported("SC1090", node, "parameterized 'arguments' outside an ES module (sloppy-mode parameter aliases)");
6905
+ if (usesArguments) {
6906
+ if (node.parameters.length > 0 || ts.isMethodDeclaration(node)) {
6907
+ const classMethod = ts.isMethodDeclaration(node) &&
6908
+ (ts.isClassDeclaration(node.parent) || ts.isClassExpression(node.parent));
6909
+ if (!classMethod && !isNodeEsmFile(node.getSourceFile(), lowerer.program)) {
6910
+ lowerer.unsupported("SC1090", node, "parameterized 'arguments' outside an ES module (sloppy-mode parameter aliases)");
6911
+ }
6346
6912
  }
6347
6913
  shapes.push({ type: DYN, mode: "arguments" });
6348
6914
  }
6349
6915
  const funcType = funcTypeFromParamShapes(shapes, ret);
6350
- if (usesArguments)
6351
- funcType.rest = true;
6352
6916
  return { shapes, funcType };
6353
6917
  }
6354
6918
  /** Lifts an arrow function / function expression / nested declaration /
@@ -6398,10 +6962,17 @@ export function lowerLambda(lowerer, node) {
6398
6962
  lowerer.fnStack.push(fnCtx);
6399
6963
  try {
6400
6964
  const { params, prologue } = lowerer.declareParams(node.parameters, shapes);
6965
+ // Checked JavaScript functions take their receiver from the call site.
6966
+ // Store it as this function's binding so escaping arrows capture it,
6967
+ // and a method nested inside another method never captures its owner.
6968
+ if (isJsSourceFile(node.getSourceFile()) && !ts.isArrowFunction(node)) {
6969
+ const receiver = lowerer.declareThis(DYN);
6970
+ prologue.unshift({ kind: "varDecl", localId: receiver.id, init: { kind: "libCall", fn: "dyn.this", args: [], type: DYN, loc }, loc });
6971
+ }
6401
6972
  // The synthetic trailing dyn-array param carries `arguments`.
6402
6973
  // Parameterized functions receive all actual arguments; zero-param
6403
6974
  // functions receive the same array through their rest ABI.
6404
- if (funcType.rest && !shapes.some((s) => s.mode === "dynRest" || s.mode === "islandRest")) {
6975
+ if (funcType.rest && funcType.restAbi === undefined && !shapes.some((s) => s.mode === "dynRest" || s.mode === "islandRest")) {
6405
6976
  const argsLocal = lowerer.declareHiddenLocal("%arguments", DYN);
6406
6977
  params.push({ localId: argsLocal.id, name: "%arguments", type: DYN });
6407
6978
  fnCtx.argumentsLocal = argsLocal;
@@ -6438,7 +7009,9 @@ export function lowerLambda(lowerer, node) {
6438
7009
  }
6439
7010
  }
6440
7011
  else {
6441
- let value = lowerer.lowerExpr(bodyExpr);
7012
+ // Concise and block bodies use the same destination layout for
7013
+ // fresh literals. Async bodies must inspect promises first.
7014
+ let value = isAsync ? lowerer.lowerExpr(bodyExpr) : lowerer.lowerExprExpecting(bodyExpr, bodyReturn);
6442
7015
  // An async concise body whose value is itself a promise
6443
7016
  // (`async () => p`): the async machinery RESOLVES the returned
6444
7017
  // thenable into the function's own promise — lowerReturnValue's
@@ -6468,6 +7041,8 @@ export function lowerLambda(lowerer, node) {
6468
7041
  const ctx = lowerer.ctx;
6469
7042
  const lifted = {
6470
7043
  name: fnName,
7044
+ sourceName: jsFuncNameOf(node) ?? "<anonymous>",
7045
+ ...(!isAsync && !isGenerator && (ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node)) ? { ownsPrototype: true } : {}),
6471
7046
  params,
6472
7047
  returnType: bodyReturn,
6473
7048
  locals: ctx.locals,
@@ -6810,10 +7385,12 @@ export function lowerPromiseMethodCall(lowerer, call, access) {
6810
7385
  }));
6811
7386
  }
6812
7387
  else {
7388
+ if (settled.type.kind !== "dyn" &&
7389
+ !canConvertToDyn(settled.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) {
7390
+ lowerer.unsupported("SC1090", fulfilledNode, "then fulfillment values that cannot cross the checked-dynamic boundary");
7391
+ }
6813
7392
  const arg = settled.type.kind === "dyn" ? settled
6814
- : canConvertToDyn(settled.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))
6815
- ? { kind: "dynFrom", value: settled, type: DYN, loc }
6816
- : lowerer.unsupported("SC1090", fulfilledNode, "then fulfillment values that cannot cross the checked-dynamic boundary");
7393
+ : { kind: "dynFrom", value: settled, type: DYN, loc };
6817
7394
  body.push(...resultOf({
6818
7395
  kind: "dynCall",
6819
7396
  callee: { kind: "varRef", localId: fLocal.id, type: DYN, loc },
@@ -7677,7 +8254,8 @@ export function recordKeysArrayCall(lowerer, receiver, argIr, shape, loc) {
7677
8254
  loc,
7678
8255
  };
7679
8256
  const finalize = () => {
7680
- const current = lowerer.shapes.get(argIr.shapeId) ?? shape;
8257
+ const latest = lowerer.shapes.get(argIr.shapeId);
8258
+ const current = latest !== undefined ? latest : shape;
7681
8259
  const body = [
7682
8260
  { kind: "varDecl", localId: "out.0", init: { kind: "arrayLit", elems: [], type: resultT, loc }, loc },
7683
8261
  ];
@@ -7727,10 +8305,11 @@ export function recordKeysArrayCall(lowerer, receiver, argIr, shape, loc) {
7727
8305
  return { kind: "call", callee: helper, args: [receiver], type: resultT, loc };
7728
8306
  }
7729
8307
  /** Interned `%obj.hasOwn.<n>(r, k)` — Object.hasOwn's membership walk
7730
- * over a signature-free record shape: the key compares against each
8308
+ * over a record shape: the key compares against each
7731
8309
  * declared field name, undefined-armed fields answering by their tag
7732
8310
  * (a key is own exactly when Object.keys would list it — the two share
7733
- * the guard), everything else true, no match false. */
8311
+ * the guard), everything else true. Unmatched keys probe the overflow
8312
+ * map when present, so explicit undefined values remain own keys. */
7734
8313
  function recordHasOwnHelper(lowerer, shapeId, loc) {
7735
8314
  const key = `obj.hasOwn:${shapeId}`;
7736
8315
  const existing = lowerer.arrHofHelpers.get(key);
@@ -7764,7 +8343,10 @@ function recordHasOwnHelper(lowerer, shapeId, loc) {
7764
8343
  loc,
7765
8344
  });
7766
8345
  }
7767
- body.push({ kind: "return", value: { kind: "boolLit", value: false, type: BOOL, loc }, loc });
8346
+ const fallback = shape.indexValue
8347
+ ? { kind: "recordOvfHas", obj: rRef, shapeId, key: kRef, type: BOOL, loc }
8348
+ : { kind: "boolLit", value: false, type: BOOL, loc };
8349
+ body.push({ kind: "return", value: fallback, loc });
7768
8350
  lowerer.liftedFns.push({
7769
8351
  name: helper,
7770
8352
  params: [
@@ -7944,6 +8526,42 @@ function lowerObjectStaticCall(lowerer, call, access) {
7944
8526
  if (!lowerer.isStdlibGlobal(access.expression, "Object"))
7945
8527
  return null;
7946
8528
  const member = access.name.text;
8529
+ if ((member === "getOwnPropertyNames" || member === "getOwnPropertySymbols" || member === "getOwnPropertyDescriptors") && call.arguments.length === 1 &&
8530
+ !call.arguments.some(ts.isSpreadElement) && !lowerer.dynamic) {
8531
+ let object = lowerer.lowerExpr(call.arguments[0]);
8532
+ if (object.type.kind === "string" || object.type.kind === "f64" ||
8533
+ object.type.kind === "bool" || isUnitType(object.type))
8534
+ object = { kind: "dynFrom", value: object, type: DYN, loc: locOf(call) };
8535
+ if (object.type.kind === "dyn")
8536
+ return { kind: "libCall", fn: member === "getOwnPropertyNames" ? "dyn.getOwnPropertyNames" : member === "getOwnPropertySymbols" ? "dyn.getOwnPropertySymbols" : "dyn.getOwnPropertyDescriptors", args: [object], type: DYN, loc: locOf(call) };
8537
+ }
8538
+ if ((member === "getPrototypeOf" || member === "setPrototypeOf") &&
8539
+ call.arguments.length === (member === "getPrototypeOf" ? 1 : 2) &&
8540
+ !call.arguments.some(ts.isSpreadElement) && !lowerer.dynamic) {
8541
+ let object = lowerer.lowerExpr(call.arguments[0]);
8542
+ if (object.type.kind === "func") {
8543
+ const fnName = jsFuncNameOf(call.arguments[0]);
8544
+ object = { kind: "dynFrom", value: object, type: DYN, loc: locOf(call),
8545
+ ...(fnName !== null ? { fnName } : {}) };
8546
+ }
8547
+ if (object.type.kind === "dyn") {
8548
+ const loc = locOf(call);
8549
+ if (member === "getPrototypeOf")
8550
+ return { kind: "libCall", fn: "dyn.getPrototype", args: [object], type: DYN, loc };
8551
+ const prototype = lowerer.lowerExprExpecting(call.arguments[1], DYN);
8552
+ if (prototype.type.kind === "dyn")
8553
+ return { kind: "libCall", fn: "dyn.setPrototype", args: [object, prototype], type: DYN, loc };
8554
+ }
8555
+ }
8556
+ if (member === "getOwnPropertyDescriptor" && call.arguments.length === 2) {
8557
+ const [receiver, key] = call.arguments;
8558
+ if (receiver && key && ts.isPropertyAccessExpression(receiver) && receiver.name.text === "prototype" &&
8559
+ lowerer.isStdlibGlobal(receiver.expression, "ArrayBuffer") && ts.isStringLiteral(key) && key.text === "byteLength") {
8560
+ const loc = locOf(call);
8561
+ const getter = lowerer.lowerNativeCallableValue({ fn: "arrayBuffer.byteLengthGetter", params: [], result: F64, valueParams: [] }, "get ArrayBuffer.prototype.byteLength", loc);
8562
+ return { kind: "libCall", fn: "arrayBuffer.byteLengthDescriptor", args: [lowerer.coerceToExpected(getter, DYN)], type: DYN, loc };
8563
+ }
8564
+ }
7947
8565
  const cacheKeys = lowerRequireCacheKeys(lowerer, call, member);
7948
8566
  if (cacheKeys)
7949
8567
  return cacheKeys;
@@ -8045,23 +8663,14 @@ function lowerObjectStaticCall(lowerer, call, access) {
8045
8663
  }
8046
8664
  lowerer.noLowering(`Object.is over '${lowerer.fmt(left.type)}' and '${lowerer.fmt(right.type)}' operands`, call, "the operands must share one comparable kind (numbers, strings, booleans, units, one union shape, or one reference type)");
8047
8665
  }
8048
- // Object.create — the null-prototype DICTIONARY (`Object.create(null)`
8049
- // then keyed assignment, the memo-table idiom prettier's index/
8050
- // group-mode maps spell) and, under --dynamic, the engine's own
8051
- // Object.create for engine-held prototypes. Everything else is a
8052
- // NAMED fence: the compiled representations have no prototype chain,
8053
- // and the own-copy stand-in would answer WRONG observably — Node's
8054
- // Object.keys/inspect/JSON of the created object list NO own keys,
8055
- // and mutating the prototype afterwards is visible through the
8056
- // created object (live delegation), which no copy can honor.
8666
+ // Native checked objects retain a live prototype and can install an
8667
+ // own-property descriptor table during creation. Engine-held values
8668
+ // use the engine's Object.create path below.
8057
8669
  if (member === "create") {
8058
8670
  if (call.arguments.some((a) => ts.isSpreadElement(a))) {
8059
8671
  lowerer.noLowering("Object.create with spread arguments", call);
8060
8672
  }
8061
- if (call.arguments.length >= 2) {
8062
- lowerer.noLowering("Object.create with a properties-descriptor argument", call, "create first, then assign: const o = Object.create(null); o.k = v");
8063
- }
8064
- if (call.arguments.length !== 1) {
8673
+ if (call.arguments.length < 1 || call.arguments.length > 2) {
8065
8674
  lowerer.noLowering(`Object.create with ${call.arguments.length} arguments`, call);
8066
8675
  }
8067
8676
  const loc = locOf(call);
@@ -8070,6 +8679,8 @@ function lowerObjectStaticCall(lowerer, call, access) {
8070
8679
  protoNode = protoNode.expression;
8071
8680
  const nullProto = protoNode.kind === ts.SyntaxKind.NullKeyword;
8072
8681
  if (lowerer.dynamic) {
8682
+ if (call.arguments.length === 2)
8683
+ lowerer.noLowering("Object.create with properties under --dynamic", call);
8073
8684
  // The checker types the result `any` — an ENGINE value under
8074
8685
  // --dynamic — and the engine's own Object.create answers with
8075
8686
  // REAL prototype semantics: reads delegate LIVE, writes shadow,
@@ -8090,15 +8701,40 @@ function lowerObjectStaticCall(lowerer, call, access) {
8090
8701
  }
8091
8702
  lowerer.noLowering(`Object.create over '${lowerer.fmt(proto.type)}' prototypes`, call, "prototype reads delegate LIVE in Node (mutating the prototype shows through the created object), which the boundary's deep copy cannot honor — only null and engine-held ('any') prototypes lower");
8092
8703
  }
8093
- if (nullProto) {
8704
+ if (nullProto && call.arguments.length === 1) {
8094
8705
  return { kind: "libCall", fn: "dyn.objCreateNullProto", args: [], type: DYN, loc };
8095
8706
  }
8096
- const proto = lowerer.lowerExpr(protoNode);
8097
- lowerer.noLowering(`Object.create over '${lowerer.fmt(proto.type)}' prototypes`, call, "the compiled representations have no prototype chain, and an own-copy would answer wrong observably (Node lists NO own keys on the created object, and prototype mutations show through it live) — only Object.create(null) lowers");
8707
+ let proto = nullProto
8708
+ ? { kind: "dynFrom", value: { kind: "unitLit", unit: "null", type: NULL_T, loc }, type: DYN, loc }
8709
+ : ts.isObjectLiteralExpression(protoNode)
8710
+ ? lowerer.lowerExprExpecting(protoNode, DYN)
8711
+ : lowerer.lowerExpr(protoNode);
8712
+ if (isUnitType(proto.type) || proto.type.kind === "f64" || proto.type.kind === "bool" || proto.type.kind === "string")
8713
+ proto = { kind: "dynFrom", value: proto, type: DYN, loc };
8714
+ if (proto.type.kind === "dyn") {
8715
+ if (call.arguments.length === 1)
8716
+ return { kind: "libCall", fn: "dyn.objCreate", args: [proto], type: DYN, loc };
8717
+ const descriptors = lowerer.lowerExprExpecting(call.arguments[1], DYN);
8718
+ if (descriptors.type.kind === "dyn")
8719
+ return { kind: "libCall", fn: "dyn.objCreateWithProperties", args: [proto, descriptors], type: DYN, loc };
8720
+ }
8721
+ lowerer.noLowering(`Object.create over '${lowerer.fmt(proto.type)}' prototypes`, call);
8098
8722
  }
8099
8723
  // `Object.assign(fn, { props })` whose RESULT type maps to the hybrid
8100
8724
  // (function-with-properties) record: the chalk-shape CONSTRUCTOR.
8101
8725
  if (member === "assign") {
8726
+ const prototype = lowerClassPrototypeAssign(lowerer, call);
8727
+ if (prototype)
8728
+ return prototype;
8729
+ if (isJsSourceFile(call.getSourceFile()) && call.arguments.length > 0 && !call.arguments.some(ts.isSpreadElement)) {
8730
+ const target = tryLowerExpression(lowerer, call.arguments[0]);
8731
+ if (target?.type.kind === "func" && lowerer.dynConvertible(target.type)) {
8732
+ const loc = locOf(call);
8733
+ return { kind: "libCall", fn: "dyn.assignAll", args: [lowerer.coerceToExpected(target, DYN),
8734
+ { kind: "dynArrLit", elems: call.arguments.slice(1).map((arg) => lowerer.lowerExprExpecting(arg, DYN)), type: DYN, loc },
8735
+ ], type: DYN, loc };
8736
+ }
8737
+ }
8102
8738
  const hybrid = lowerObjectAssignHybrid(lowerer, call);
8103
8739
  if (hybrid)
8104
8740
  return hybrid;
@@ -8145,7 +8781,9 @@ function lowerObjectStaticCall(lowerer, call, access) {
8145
8781
  if (tProbe?.type.kind === "dyn") {
8146
8782
  const loc = locOf(call);
8147
8783
  const target = lowerer.lowerExpr(call.arguments[0]);
8148
- const source = lowerer.coerceToExpected(lowerer.lowerExpr(call.arguments[1]), DYN);
8784
+ const rawSource = lowerer.lowerExpr(call.arguments[1]);
8785
+ fenceSymbolFieldCopy(lowerer, call.arguments[1], rawSource.type);
8786
+ const source = lowerer.coerceToExpected(rawSource, DYN);
8149
8787
  if (target.type.kind === "dyn" && source.type.kind === "dyn") {
8150
8788
  return { kind: "libCall", fn: "dyn.assign", args: [target, source], type: DYN, loc };
8151
8789
  }
@@ -8222,7 +8860,9 @@ function lowerObjectStaticCall(lowerer, call, access) {
8222
8860
  const argNode = sources[i];
8223
8861
  const spread = ts.isSpreadElement(argNode);
8224
8862
  const srcNode = spread ? argNode.expression : argNode;
8225
- const src = lowerer.coerceToExpected(lowerer.lowerExpr(srcNode), DYN);
8863
+ const rawSource = lowerer.lowerExpr(srcNode);
8864
+ fenceSymbolFieldCopy(lowerer, srcNode, rawSource.type, spread);
8865
+ const src = lowerer.coerceToExpected(rawSource, DYN);
8226
8866
  if (src.type.kind !== "dyn") {
8227
8867
  ok = false;
8228
8868
  break;
@@ -8259,22 +8899,75 @@ function lowerObjectStaticCall(lowerer, call, access) {
8259
8899
  }
8260
8900
  return null;
8261
8901
  }
8902
+ if ((member === "defineProperty" && call.arguments.length === 3) ||
8903
+ (member === "getOwnPropertyDescriptor" && call.arguments.length === 2)) {
8904
+ if (call.arguments.some((a) => ts.isSpreadElement(a)))
8905
+ return null;
8906
+ let target = tryLowerExpression(lowerer, call.arguments[0]);
8907
+ if (target && member === "defineProperty") {
8908
+ const native = lowerClassDataDescriptor(lowerer, call, member, target);
8909
+ if (native)
8910
+ return native;
8911
+ }
8912
+ if (target && member === "getOwnPropertyDescriptor" && isDynTypedRefType(target.type)) {
8913
+ const descriptor = lowerClassDescriptorRead(lowerer, call, target);
8914
+ if (descriptor)
8915
+ return descriptor;
8916
+ target = lowerer.coerceToExpected(target, DYN);
8917
+ }
8918
+ // Error.cause owns a live data-property slot shared with its checked
8919
+ // view. Other native fields do not yet synchronize descriptor edits.
8920
+ const keyNode = call.arguments[1];
8921
+ if (target?.type.kind === "object" && target.type.className !== "%DOMException" && lowerer.errorHierarchyClassOf(target.type.className) &&
8922
+ ts.isStringLiteral(keyNode) && keyNode.text === "cause") {
8923
+ target = lowerer.coerceToExpected(target, DYN);
8924
+ }
8925
+ if (target?.type.kind === "func" && lowerer.dynConvertible(target.type)) {
8926
+ const fnName = jsFuncNameOf(call.arguments[0]);
8927
+ target = { kind: "dynFrom", value: target, type: DYN, loc: locOf(call.arguments[0]), ...(fnName !== null ? { fnName } : {}) };
8928
+ }
8929
+ const descriptorPrimitive = member === "getOwnPropertyDescriptor" && target &&
8930
+ (target.type.kind === "bool" || target.type.kind === "f64" || target.type.kind === "string");
8931
+ if (!target || (target.type.kind !== "dyn" && !isUnitType(target.type) && !descriptorPrimitive))
8932
+ return null;
8933
+ if (target.type.kind !== "dyn")
8934
+ target = { kind: "dynFrom", value: target, type: DYN, loc: locOf(call.arguments[0]) };
8935
+ const key = lowerer.lowerExprExpecting(call.arguments[1], DYN);
8936
+ if (key.type.kind !== "dyn")
8937
+ return null;
8938
+ if (member === "getOwnPropertyDescriptor") {
8939
+ return { kind: "libCall", fn: "dyn.getOwnPropertyDescriptor", args: [target, key], type: DYN, loc: locOf(call) };
8940
+ }
8941
+ const descriptor = lowerer.lowerExprExpecting(call.arguments[2], DYN);
8942
+ if (descriptor.type.kind !== "dyn")
8943
+ return null;
8944
+ return { kind: "libCall", fn: "dyn.defineProperty", args: [target, key, descriptor], type: DYN, loc: locOf(call) };
8945
+ }
8262
8946
  // Object.defineProperties over a CHECKED-DYNAMIC target (test/common's
8263
8947
  // _mustCallInner copying name/length onto the mustCall wrapper): the
8264
- // runtime turns each descriptor's `value` into a plain own property on
8265
- // the dyn node (OBJ members; FUNC nodes carry an own-property table) —
8266
- // flags accepted and ignored, accessors throw loudly (SEMANTICS.md).
8948
+ // runtime turns each descriptor's `value` into an own property on
8949
+ // the dyn node (OBJ members preserve attributes; FUNC nodes carry an
8950
+ // own-property table). Accessors use the target as their receiver.
8267
8951
  // The result is the target, like JS. Typed targets keep the fence:
8268
8952
  // static shapes have no property table to extend.
8269
8953
  if (member === "defineProperties" && call.arguments.length === 2 &&
8270
8954
  !call.arguments.some((a) => ts.isSpreadElement(a))) {
8271
8955
  let target = tryLowerExpression(lowerer, call.arguments[0]);
8956
+ if (target) {
8957
+ const native = lowerClassDataDescriptor(lowerer, call, member, target);
8958
+ if (native)
8959
+ return native;
8960
+ }
8272
8961
  // A FUNCTION-typed target boxes through the dyn boundary: the
8273
8962
  // property table lives on the CLOSURE (shared by every box of this
8274
8963
  // function value), so defining through a fresh box sticks — the
8275
8964
  // wrapper returned later reads the same table.
8276
8965
  if (target && target.type.kind === "func" &&
8277
8966
  canBoxFuncIntoDyn(target.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) {
8967
+ const fnName = jsFuncNameOf(call.arguments[0]);
8968
+ target = { kind: "dynFrom", value: target, type: DYN, loc: locOf(call.arguments[0]), ...(fnName !== null ? { fnName } : {}) };
8969
+ }
8970
+ if (target && isUnitType(target.type)) {
8278
8971
  target = { kind: "dynFrom", value: target, type: DYN, loc: locOf(call.arguments[0]) };
8279
8972
  }
8280
8973
  if (target?.type.kind === "dyn") {
@@ -8285,12 +8978,39 @@ function lowerObjectStaticCall(lowerer, call, access) {
8285
8978
  }
8286
8979
  return null;
8287
8980
  }
8981
+ if (["preventExtensions", "isExtensible", "seal", "isSealed"].includes(member) &&
8982
+ call.arguments.length === 1 && !ts.isSpreadElement(call.arguments[0])) {
8983
+ const value = lowerer.lowerExpr(call.arguments[0]);
8984
+ if (value.type.kind === "string" || value.type.kind === "f64" ||
8985
+ value.type.kind === "bool" || value.type.kind === "symbol" || isUnitType(value.type)) {
8986
+ if (member === "preventExtensions" || member === "seal")
8987
+ return value;
8988
+ const loc = locOf(call);
8989
+ const answer = { kind: "boolLit", value: member !== "isExtensible", type: BOOL, loc };
8990
+ return isSafeToDiscard(value) ? answer : {
8991
+ kind: "seqExpr", stmts: [{ kind: "exprStmt", expr: value, loc: value.loc }],
8992
+ result: answer, type: BOOL, loc,
8993
+ };
8994
+ }
8995
+ if (value.type.kind === "dyn") {
8996
+ const operation = {
8997
+ preventExtensions: "dyn.preventExtensions", isExtensible: "dyn.isExtensible",
8998
+ seal: "dyn.seal", isSealed: "dyn.isSealed",
8999
+ };
9000
+ const fn = operation[member];
9001
+ return { kind: "libCall", fn, args: [value], type: member.startsWith("is") ? BOOL : DYN, loc: locOf(call) };
9002
+ }
9003
+ }
8288
9004
  // Object.freeze: on a FRESH literal (object or array) the result IS
8289
9005
  // the argument — no alias exists, so the frozen bit is unobservable
8290
9006
  // (writes through the Readonly<T> result are compile errors, and no
8291
9007
  // other reference can write). Primitives pass through per ES2015.
8292
9008
  // Aliased objects keep a fence: a later write through the original
8293
9009
  // reference would need the runtime frozen bit (strict mode throws).
9010
+ if (member === "isFrozen" && call.arguments.length === 1) {
9011
+ const value = lowerer.lowerExprExpecting(call.arguments[0], DYN);
9012
+ return { kind: "libCall", fn: "dyn.isFrozen", args: [value], type: BOOL, loc: locOf(call) };
9013
+ }
8294
9014
  if (member === "freeze") {
8295
9015
  if (call.arguments.length !== 1 || ts.isSpreadElement(call.arguments[0])) {
8296
9016
  lowerer.noLowering(`Object.freeze with ${call.arguments.length} arguments`, call);
@@ -8300,14 +9020,18 @@ function lowerObjectStaticCall(lowerer, call, access) {
8300
9020
  while (ts.isParenthesizedExpression(inner) || ts.isAsExpression(inner))
8301
9021
  inner = inner.expression;
8302
9022
  const value = lowerer.lowerExpr(argNode);
9023
+ if (value.type.kind === "dyn")
9024
+ return { kind: "libCall", fn: "dyn.freeze", args: [value], type: DYN, loc: locOf(call) };
8303
9025
  if (ts.isObjectLiteralExpression(inner) || ts.isArrayLiteralExpression(inner)) {
8304
9026
  return value; // fresh — freeze is identity here, honestly
8305
9027
  }
8306
9028
  if (value.type.kind === "string" || value.type.kind === "f64" ||
8307
- value.type.kind === "bool" || value.type.kind === "symbol" ||
9029
+ value.type.kind === "bool" || value.type.kind === "symbol" || value.type.kind === "bigint" ||
8308
9030
  isUnitType(value.type)) {
8309
9031
  return value; // ES2015: freeze of a primitive is the primitive
8310
9032
  }
9033
+ if (value.type.kind === "union" && lowerer.unions.get(value.type.unionId)?.arms.every((arm) => isUnitType(arm) || arm.kind === "f64" || arm.kind === "bigint" || arm.kind === "bool" || arm.kind === "string" || arm.kind === "symbol"))
9034
+ return value;
8311
9035
  lowerer.noLowering("Object.freeze of a possibly-aliased value", call, "freeze of a FRESH object/array literal (and of primitives) compiles — frozen-ness is unobservable there; an aliased target's later writes would need the runtime frozen bit");
8312
9036
  }
8313
9037
  // `Object.hasOwn(r, k)` over a RECORD receiver: a record's own-key set
@@ -8316,9 +9040,9 @@ function lowerObjectStaticCall(lowerer, call, access) {
8316
9040
  // fields answer by their runtime tag — the explicit-undefined-is-absent
8317
9041
  // stance: an omitted optional field holds the undefined arm and reads
8318
9042
  // as NOT own, exactly Node's absent key (an EXPLICIT `k: undefined`
8319
- // diverges — documented next to the child-env/JSON rule). Tuple,
8320
- // index-signature (overflow membership lives in the runtime map), and
8321
- // accessor-carrying shapes keep the SC2020 fence; non-record receivers
9043
+ // diverges — documented next to the child-env/JSON rule). Tuple
9044
+ // and accessor-carrying shapes keep the SC2020 fence. Index-signature
9045
+ // records additionally probe the overflow map; non-record receivers
8322
9046
  // do too.
8323
9047
  if (member === "hasOwn" && call.arguments.length === 2 && !call.arguments.some((a) => ts.isSpreadElement(a))) {
8324
9048
  const recvNode = call.arguments[0];
@@ -8327,33 +9051,30 @@ function lowerObjectStaticCall(lowerer, call, access) {
8327
9051
  // A CHECKED-DYNAMIC receiver (the JS file-scope object-literal
8328
9052
  // identity story): the runtime dyn probe — OBJ member presence, ARR
8329
9053
  // index bounds, Node's ToObject TypeError on nullish.
8330
- if (probed?.type.kind === "dyn") {
9054
+ if (probed?.type.kind === "dyn" || (probed && isDynTypedRefType(probed.type)) || (probed?.type.kind === "func" && lowerer.dynConvertible(probed.type))) {
8331
9055
  const loc = locOf(call);
8332
- const receiver = lowerer.lowerExpr(recvNode);
8333
- let key = lowerer.lowerExpr(keyNode);
8334
- if (key.type.kind === "f64" || key.type.kind === "bool" || key.type.kind === "dyn") {
8335
- key = { kind: "toString", operand: key, type: STRING, loc: locOf(keyNode) };
8336
- }
8337
- if (key.type.kind !== "string")
9056
+ const receiver = lowerer.coerceToExpected(probed, DYN);
9057
+ const rawKey = lowerer.lowerExpr(keyNode);
9058
+ if (rawKey.type.kind === "dyn" || rawKey.type.kind === "symbol")
9059
+ return {
9060
+ kind: "libCall", fn: "dyn.hasOwnComputed", args: [receiver, lowerer.coerceToExpected(rawKey, DYN)], type: BOOL, loc,
9061
+ };
9062
+ const key = ownPropertyKey(lowerer, rawKey);
9063
+ if (!key)
8338
9064
  return null;
8339
9065
  return { kind: "libCall", fn: "dyn.hasOwn", args: [receiver, key], type: BOOL, loc };
8340
9066
  }
8341
9067
  if (probed?.type.kind !== "record")
8342
9068
  return null;
8343
9069
  const shape = lowerer.shapes.get(probed.type.shapeId);
8344
- if (!shape || shape.tuple || shape.indexValue || shapeHasAccessorSlots(shape))
9070
+ if (!shape || shape.tuple || shapeHasAccessorSlots(shape))
8345
9071
  return null;
8346
9072
  const loc = locOf(call);
8347
9073
  const receiver = lowerer.lowerExpr(recvNode);
8348
9074
  if (receiver.type.kind !== "record")
8349
9075
  return null; // probe/lower drift: keep the fence
8350
- let key = lowerer.lowerExpr(keyNode);
8351
- // Number/boolean/dyn keys stringify — ToPropertyKey, the keyed-write
8352
- // path's rule; symbol and composite keys keep the fence.
8353
- if (key.type.kind === "f64" || key.type.kind === "bool" || key.type.kind === "dyn") {
8354
- key = { kind: "toString", operand: key, type: STRING, loc: locOf(keyNode) };
8355
- }
8356
- if (key.type.kind !== "string")
9076
+ const key = ownPropertyKey(lowerer, lowerer.lowerExpr(keyNode));
9077
+ if (!key)
8357
9078
  return null;
8358
9079
  const helper = recordHasOwnHelper(lowerer, receiver.type.shapeId, loc);
8359
9080
  return { kind: "call", callee: helper, args: [receiver, key], type: BOOL, loc };
@@ -8415,8 +9136,11 @@ function lowerObjectStaticCall(lowerer, call, access) {
8415
9136
  const isDyn = probed?.type.kind === "dyn";
8416
9137
  // Unit-typed arguments (Object.keys(null)) ride the same runtime
8417
9138
  // walk: it throws Node's catchable TypeError.
8418
- const isUnit = probed !== null && probed !== undefined && isUnitType(probed.type);
8419
- if (isDyn || isUnit) {
9139
+ const isFunction = probed?.type.kind === "func" && lowerer.dynConvertible(probed.type);
9140
+ const isPrimitive = probed !== null && probed !== undefined &&
9141
+ (isUnitType(probed.type) || probed.type.kind === "string" ||
9142
+ probed.type.kind === "f64" || probed.type.kind === "bool");
9143
+ if (isDyn || isPrimitive || isFunction || (probed && isDynTypedRefType(probed.type))) {
8420
9144
  const fn = member === "keys" ? "dyn.objKeys" : member === "values" ? "dyn.objValues" : "dyn.objEntries";
8421
9145
  let v = lowerer.lowerExpr(argNode);
8422
9146
  if (v.type.kind !== "dyn")
@@ -8445,6 +9169,19 @@ function lowerObjectStaticCall(lowerer, call, access) {
8445
9169
  if (shapeHasAccessorSlots(shape)) {
8446
9170
  lowerer.unsupported("SC1090", call, `Object.${member} over a shape carrying get/set accessor properties (Node lists the accessor names${member === "keys" ? "" : " and invokes the getters"} — the static key walk cannot; read the properties explicitly)`);
8447
9171
  }
9172
+ // unknown[] uses the checked-dynamic array representation. Enumerate
9173
+ // a live view of the record so values retain their identities and the
9174
+ // result never pretends to be a native vector or an island array.
9175
+ const enumerationType = lowerer.mapTypeOf(lowerer.typeOf(call));
9176
+ if ((member === "values" || member === "entries") &&
9177
+ (enumerationType?.kind === "dyn" || enumerationType === null && isJsSourceFile(call.getSourceFile()))) {
9178
+ let receiver = lowerer.coerceToExpected(lowerer.lowerExpr(argNode), DYN);
9179
+ if (receiver.type.kind !== "dyn")
9180
+ lowerer.badType(argNode, lowerer.typeOf(argNode));
9181
+ if (receiver.kind === "dynFrom" && receiver.value.type.kind === "record")
9182
+ receiver = { ...receiver, liveRef: true };
9183
+ return { kind: "libCall", fn: member === "values" ? "dyn.objValues" : "dyn.objEntries", args: [receiver], type: DYN, loc: locOf(call) };
9184
+ }
8448
9185
  if (shape.indexValue) {
8449
9186
  // Index-signature (overflow-carrying) shapes: the runtime walk —
8450
9187
  // declared fields first, then the overflow in JS own-key order
@@ -8455,7 +9192,7 @@ function lowerObjectStaticCall(lowerer, call, access) {
8455
9192
  const resultT = lowerer.irTypeOf(call);
8456
9193
  if (resultT.kind !== "array")
8457
9194
  lowerer.badType(call, lowerer.typeOf(call)); // defensive
8458
- const receiver = lowerer.lowerExpr(argNode);
9195
+ const receiver = objectEnumerationReceiver(lowerer, lowerer.lowerExpr(argNode), argIr, loc);
8459
9196
  if (member === "keys") {
8460
9197
  // The keys walk is shared with for-in (which iterates exactly the
8461
9198
  // keys Object.keys answers — one construction, one intern key).
@@ -8497,7 +9234,8 @@ function lowerObjectStaticCall(lowerer, call, access) {
8497
9234
  loc,
8498
9235
  };
8499
9236
  const finalize = () => {
8500
- const current = lowerer.shapes.get(argIr.shapeId) ?? shape;
9237
+ const latest = lowerer.shapes.get(argIr.shapeId);
9238
+ const current = latest !== undefined ? latest : shape;
8501
9239
  const body = [
8502
9240
  { kind: "varDecl", localId: "out.0", init: { kind: "arrayLit", elems: [], type: resultT, loc }, loc },
8503
9241
  ];
@@ -8651,6 +9389,8 @@ export function lowerFunction(lowerer, decl) {
8651
9389
  appendImplicitUndefinedReturn(lowerer, body, bodyReturn, locOf(decl));
8652
9390
  const fn = {
8653
9391
  name: sig.name,
9392
+ sourceName: decl.name?.text ?? "<anonymous>",
9393
+ ...(!sig.isAsync && !sig.generator ? { ownsPrototype: true } : {}),
8654
9394
  params,
8655
9395
  returnType: bodyReturn,
8656
9396
  locals: lowerer.ctx.locals,
@@ -8775,8 +9515,27 @@ function lowerObjectAssignHybrid(lowerer, call) {
8775
9515
  export function lowerRecordFieldCall(lowerer, call, access) {
8776
9516
  if (lowerer.chainBlocked(call))
8777
9517
  return null;
8778
- if (lowerer.mapTypeOf(lowerer.typeOf(access.expression))?.kind !== "record")
8779
- return null;
9518
+ const stored = ts.isIdentifier(access.expression)
9519
+ ? lowerer.peekLocal(access.expression)?.type ?? lowerer.globalOf(access.expression)?.type : undefined;
9520
+ const receiverType = stored?.kind === "record" ? stored : lowerer.mapTypeOf(lowerer.typeOf(access.expression));
9521
+ if (receiverType?.kind !== "record" && receiverType?.kind !== "union")
9522
+ return null;
9523
+ // A union of records can share a closure-valued field. Its normal
9524
+ // property read performs the tag dispatch before arguments evaluate.
9525
+ // Class methods retain their vtable path and must not lose `this`.
9526
+ if (receiverType.kind === "union") {
9527
+ const arms = lowerer.unions.get(receiverType.unionId)?.arms;
9528
+ if (!arms?.every((arm) => arm.kind === "record"))
9529
+ return null;
9530
+ if (!arms.every((arm) => arm.kind === "record" &&
9531
+ lowerer.shapes.get(arm.shapeId)?.fields.some((field) => field.name === access.name.text && field.type.kind === "func")))
9532
+ return null;
9533
+ const callee = lowerer.lowerUnionProperty(access);
9534
+ if (callee?.type.kind !== "func")
9535
+ return null;
9536
+ const args = completeFuncValueArgs(lowerer, call, callee.type, locOf(call));
9537
+ return { kind: "callValue", callee, args, type: callee.type.ret, loc: locOf(call) };
9538
+ }
8780
9539
  const target = lowerer.fieldTarget(access);
8781
9540
  let callee = target ? lowerer.fieldGetExpr(target, locOf(access), access) : null;
8782
9541
  if (!callee)
@@ -8975,7 +9734,7 @@ function nullishValueUnitOf(lowerer, sym) {
8975
9734
  // the no-storage family never claims it.
8976
9735
  if (!decl || !ts.isVariableDeclaration(decl) || !ts.isIdentifier(decl.name) ||
8977
9736
  decl.getSourceFile().isDeclarationFile || decl.initializer === undefined ||
8978
- !ts.isVariableStatement(decl.parent.parent)) {
9737
+ !ts.isVariableStatement(decl.parent?.parent)) {
8979
9738
  return null;
8980
9739
  }
8981
9740
  const unit = nullishExprUnitOf(lowerer, decl.initializer);
@@ -9161,7 +9920,7 @@ export function deadUnmappableBinding(lowerer, sym, decl) {
9161
9920
  // lowerVarDeclList's contract requires a lowered statement for it, so
9162
9921
  // the no-storage family never claims it (catch bindings sit outside a
9163
9922
  // variable statement too and stay out the same way).
9164
- if (!ts.isVariableStatement(decl.parent.parent))
9923
+ if (!ts.isVariableStatement(decl.parent?.parent))
9165
9924
  return false;
9166
9925
  const sf = decl.getSourceFile();
9167
9926
  if (sf.isDeclarationFile || isJsSourceFile(sf))
@@ -9339,11 +10098,11 @@ export function bindingGenericFnInfoOf(lowerer, decl, fnNode) {
9339
10098
  lowerer.unsupported("SC1031", param);
9340
10099
  }
9341
10100
  }
9342
- const stmt = decl.parent.parent; // declarator → list → statement (nsPathPrefix wants the statement)
10101
+ const stmt = decl.parent?.parent; // declarator → list → statement (nsPathPrefix wants the statement)
9343
10102
  const info = {
9344
10103
  decl: fnNode,
9345
10104
  baseName: name,
9346
- qualifiedName: lowerer.qualify(decl.getSourceFile(), nsPathPrefix(stmt, decl) + name),
10105
+ qualifiedName: lowerer.qualify(decl.getSourceFile(), nsPathPrefix(stmt ?? decl, decl) + name),
9347
10106
  typeParams,
9348
10107
  instances: new Map(),
9349
10108
  };
@@ -9475,6 +10234,88 @@ function arrowSignatureOf(lowerer, node) {
9475
10234
  const declaration = lowerer.checker.signatureDeclaration(signatures[0]);
9476
10235
  return declaration !== undefined && ts.isArrowFunction(declaration) ? signatures[0] : null;
9477
10236
  }
10237
+ /** An inline arrow has lexical `this` and no observable own properties
10238
+ * before binding. With no preset arguments, a fresh forwarding closure
10239
+ * preserves its completed ABI, defaults and captured environment. Keep
10240
+ * other receivers and rest/preset-argument forms on the named fence. */
10241
+ function lowerInlineArrowBind(lowerer, call, access) {
10242
+ if (access.name.text !== "bind" || call.arguments.length > 1 || call.arguments.some(ts.isSpreadElement))
10243
+ return null;
10244
+ let arrow = access.expression;
10245
+ while (ts.isParenthesizedExpression(arrow))
10246
+ arrow = arrow.expression;
10247
+ if (!ts.isArrowFunction(arrow))
10248
+ return null;
10249
+ const callee = lowerer.lowerExpr(access.expression);
10250
+ if (callee.type.kind !== "func" || callee.type.rest ||
10251
+ !canBoxFuncIntoDyn(callee.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id)))
10252
+ return null;
10253
+ const type = callee.type;
10254
+ const loc = locOf(call);
10255
+ const firstDefault = arrow.parameters.findIndex((p) => p.initializer !== undefined);
10256
+ const length = firstDefault < 0 ? arrow.parameters.length : firstDefault;
10257
+ const key = `arrow.bind:${typeKey(type)}:${length}`;
10258
+ const existing = lowerer.arrHofHelpers.get(key);
10259
+ const name = existing ?? `%arrow.bind.${lowerer.arrHofHelpers.size}`;
10260
+ if (!existing) {
10261
+ lowerer.arrHofHelpers.set(key, name);
10262
+ lowerer.freshClosureAdapters.add(name);
10263
+ const impl = `${name}.impl`;
10264
+ const captured = { id: "f.0", name: "f", type, mutable: false, boxed: true };
10265
+ const params = type.params.map((type, i) => ({ localId: `p.${i}`, name: `p${i}`, type }));
10266
+ const invoked = {
10267
+ kind: "callValue",
10268
+ callee: { kind: "varRef", localId: captured.id, type, loc },
10269
+ args: params.map((p) => ({ kind: "varRef", localId: p.localId, type: p.type, loc })),
10270
+ type: type.ret,
10271
+ loc,
10272
+ };
10273
+ lowerer.liftedFns.push({
10274
+ name: impl,
10275
+ params,
10276
+ returnType: type.ret,
10277
+ captures: [{ localId: captured.id, name: captured.name, type }],
10278
+ locals: [captured, ...params.map((p) => ({ id: p.localId, name: p.name, type: p.type, mutable: false }))],
10279
+ body: [type.ret.kind === "void" ? { kind: "exprStmt", expr: invoked, loc } : { kind: "return", value: invoked, loc }],
10280
+ loc,
10281
+ });
10282
+ const bound = { kind: "varRef", localId: "bound.0", type, loc };
10283
+ const str = (value) => ({ kind: "strLit", value, type: STRING, loc });
10284
+ const descriptor = (value) => ({
10285
+ kind: "dynObjLit", fields: [{ key: str("value"), value: { kind: "dynFrom", value, type: DYN, loc } }], type: DYN, loc,
10286
+ });
10287
+ lowerer.liftedFns.push({
10288
+ name,
10289
+ params: [{ localId: captured.id, name: captured.name, type }],
10290
+ returnType: type,
10291
+ locals: [captured, { id: "bound.0", name: "bound", type, mutable: false }],
10292
+ body: [
10293
+ { kind: "varDecl", localId: "bound.0", init: { kind: "closure", fnName: impl, captures: [captured.id], type, loc }, loc },
10294
+ // Store metadata on the closure so aliases and repeated dyn boxes
10295
+ // observe the bound name and source arity, including defaults.
10296
+ { kind: "exprStmt", expr: {
10297
+ kind: "libCall", fn: "dyn.defineProps", args: [
10298
+ { kind: "dynFrom", value: bound, type: DYN, loc },
10299
+ { kind: "dynObjLit", fields: [
10300
+ { key: str("name"), value: descriptor(str("bound ")) },
10301
+ { key: str("length"), value: descriptor({ kind: "numLit", value: length, type: F64, loc }) },
10302
+ ], type: DYN, loc },
10303
+ ], type: DYN, loc,
10304
+ }, loc },
10305
+ { kind: "return", value: bound, loc },
10306
+ ],
10307
+ loc,
10308
+ });
10309
+ }
10310
+ const saved = lowerer.declareHiddenLocal("%bindFn", type);
10311
+ const stmts = [{ kind: "varDecl", localId: saved.id, init: callee, loc }];
10312
+ // The receiver is ignored by the arrow, but its effects and throws
10313
+ // happen after creating the arrow and before returning the bound value.
10314
+ if (call.arguments[0])
10315
+ stmts.push(lowerer.lowerExprStatement(call.arguments[0]));
10316
+ const result = { kind: "call", callee: name, args: [{ kind: "varRef", localId: saved.id, type, loc }], type, loc };
10317
+ return { kind: "seqExpr", stmts, result, type, loc };
10318
+ }
9478
10319
  /** `arrow.apply(thisArg, dynArgs)` for a fixed-arity compiled arrow. Arrows
9479
10320
  * ignore `thisArg` and surplus arguments by language definition; declared
9480
10321
  * parameters validate from the dynamic array in order. */
@@ -9553,7 +10394,6 @@ function lowerObjLitGenericMethodCall(lowerer, call, access) {
9553
10394
  thisT.kind !== "dyn" &&
9554
10395
  thisT.kind !== "jsval" &&
9555
10396
  (!thisArg || ts.isIdentifier(thisArg) || ts.isLiteralExpression(thisArg) ||
9556
- thisArg.kind === ts.SyntaxKind.UndefinedKeyword ||
9557
10397
  thisArg.kind === ts.SyntaxKind.NullKeyword ||
9558
10398
  isUnitType(thisT));
9559
10399
  if (provablyNot) {
@@ -9592,19 +10432,25 @@ function lowerObjLitGenericMethodCall(lowerer, call, access) {
9592
10432
  }
9593
10433
  const found = objLitGenericFnNodeOf(lowerer, propSym);
9594
10434
  if (!found) {
10435
+ const arrowBind = lowerInlineArrowBind(lowerer, call, access);
10436
+ if (arrowBind !== null)
10437
+ return arrowBind;
9595
10438
  const arrowApply = lowerArrowFunctionApply(lowerer, call, access);
9596
10439
  if (arrowApply !== null)
9597
10440
  return arrowApply;
9598
- // Function.prototype.apply/call/bind spelled through a FUNCTION
9599
- // receiver: compiled functions are direct calls with no runtime
9600
- // `this`/arguments object to re-route — name the working spelling
9601
- // instead of a class-receiver hint (or an SC2020 recitation) no
9602
- // function value can follow. Before the stdlib decline: these ARE
9603
- // stdlib members (CallableFunction), but the pointed message is
9604
- // the honest one.
10441
+ // Convertible native callables use the checked invocation boundary
10442
+ // for Function.prototype methods, including their call-time receiver.
9605
10443
  if ((name === "apply" || name === "call" || name === "bind") &&
9606
10444
  lowerer.checker.getCallSignatures(recvT).length > 0) {
9607
- lowerer.unsupported("SC1090", call, `Function.prototype.${name} on a compiled function value (compiled calls are direct — no runtime 'this' or arguments object exists to re-route; spell the call directly: '${access.expression.getText()}(...)')`);
10445
+ const value = tryLowerExpression(lowerer, access.expression);
10446
+ if (value?.type.kind === "func" && lowerer.dynConvertible(value.type) && !call.arguments.some(ts.isSpreadElement)) {
10447
+ const loc = locOf(call);
10448
+ return {
10449
+ kind: "dynInvoke", recv: { kind: "dynFrom", value, type: DYN, loc }, method: name,
10450
+ calleeName: access.getText(), args: call.arguments.map((arg) => lowerer.lowerExprExpecting(arg, DYN)), type: DYN, loc,
10451
+ };
10452
+ }
10453
+ lowerer.unsupported("SC1090", call, `Function.prototype.${name} on a function whose signature cannot cross the checked-value boundary (call '${access.expression.getText()}(...)' directly)`);
9608
10454
  }
9609
10455
  // STANDARD-LIBRARY generic members (Promise.then, Object.
9610
10456
  // defineProperty, Array-augmentation methods) are the lib fence's
@@ -9641,7 +10487,16 @@ function lowerObjLitGenericMethodCall(lowerer, call, access) {
9641
10487
  export function lowerObjectMethodCall(lowerer, call, access) {
9642
10488
  if (lowerer.chainBlocked(access, call))
9643
10489
  return null;
9644
- const mappedReceiver = lowerer.mapTypeOf(lowerer.typeOf(access.expression));
10490
+ let mappedReceiver = lowerer.mapTypeOf(lowerer.typeOf(access.expression));
10491
+ // A specialized JS parameter can expose a native field whose checker
10492
+ // type still belongs to the unspecialized body (plane.normal.dot()).
10493
+ // Use the lowered receiver's representation and retain its evaluation.
10494
+ const probe = mappedReceiver?.kind !== "object" && (lowerer.implicitParamTypes !== null || ts.isNewExpression(access.expression) ||
10495
+ isJsSourceFile(call.getSourceFile()) && ts.isCallExpression(access.expression))
10496
+ ? tryLowerExpression(lowerer, access.expression) : null;
10497
+ const specializedReceiver = probe?.type.kind === "object" ? probe : null;
10498
+ if (specializedReceiver)
10499
+ mappedReceiver = specializedReceiver.type;
9645
10500
  if (mappedReceiver?.kind === "union") {
9646
10501
  const dispatched = lowerUnionObjectMethodCall(lowerer, call, access, mappedReceiver) ??
9647
10502
  lowerUnionObjectDynFieldCall(lowerer, call, access, mappedReceiver);
@@ -9654,15 +10509,16 @@ export function lowerObjectMethodCall(lowerer, call, access) {
9654
10509
  ? (() => {
9655
10510
  const arms = lowerer.unions.get(mappedReceiver.unionId)?.arms ?? [];
9656
10511
  const objects = arms.filter((arm) => arm.kind === "object");
9657
- return objects.length === 1 && arms.every((arm) => arm.kind === "object" || isUnitType(arm))
9658
- ? objects[0]
10512
+ const object = objects[0];
10513
+ return objects.length === 1 && object?.kind === "object" && arms.every((arm) => arm.kind === "object" || isUnitType(arm))
10514
+ ? object
9659
10515
  : null;
9660
10516
  })()
9661
10517
  : null;
9662
10518
  if (receiverIr === null)
9663
10519
  return null;
9664
10520
  const lowerReceiver = () => {
9665
- const receiver = lowerer.lowerExpr(access.expression);
10521
+ const receiver = specializedReceiver ?? lowerer.lowerExpr(access.expression);
9666
10522
  const optional = lowerer.runtimeOptionalPropertyReceiver(access.expression, receiver, receiverIr, access.name.text);
9667
10523
  if (optional !== null)
9668
10524
  return optional;
@@ -9671,7 +10527,7 @@ export function lowerObjectMethodCall(lowerer, call, access) {
9671
10527
  if (helper !== null)
9672
10528
  return { kind: "call", callee: helper, args: [receiver], type: receiverIr, loc: locOf(access.expression) };
9673
10529
  }
9674
- return receiver;
10530
+ return receiver.type.kind === "dyn" ? lowerer.coerceInto(access.expression, receiver, receiverIr) : receiver;
9675
10531
  };
9676
10532
  const info = lowerer.classes.get(receiverIr.className);
9677
10533
  if (!info)
@@ -9698,7 +10554,7 @@ export function lowerObjectMethodCall(lowerer, call, access) {
9698
10554
  if (info && !found) {
9699
10555
  const gfound = findGenericMethodOn(lowerer, info, access.name.text);
9700
10556
  if (gfound)
9701
- return lowerClassGenericMethodCall(lowerer, call, access, info, gfound);
10557
+ return lowerClassGenericMethodCall(lowerer, call, access, info, gfound, lowerReceiver());
9702
10558
  }
9703
10559
  // A FUNC-, nullable-FUNC-, or DYN-typed FIELD in call position:
9704
10560
  // `this.cb()` — the ctor-assigned callback field (countdown.js's
@@ -9714,13 +10570,22 @@ export function lowerObjectMethodCall(lowerer, call, access) {
9714
10570
  ? (() => {
9715
10571
  const arms = lowerer.unions.get(fieldType.unionId)?.arms ?? [];
9716
10572
  const funcs = arms.filter((arm) => arm.kind === "func");
9717
- return funcs.length === 1 && arms.every((arm) => arm.kind === "func" || isUnitType(arm))
9718
- ? funcs[0]
10573
+ const func = funcs[0];
10574
+ return funcs.length === 1 && func?.kind === "func" && arms.every((arm) => arm.kind === "func" || isUnitType(arm))
10575
+ ? func
9719
10576
  : null;
9720
10577
  })()
9721
10578
  : null;
9722
10579
  if (fieldType && (callableType !== null || fieldType.kind === "dyn")) {
9723
10580
  const target = lowerer.fieldTarget(access);
10581
+ if (!target)
10582
+ return null;
10583
+ const loc = locOf(call);
10584
+ const receiverLocal = lowerer.declareHiddenLocal("%callReceiver", target.obj.type);
10585
+ const init = { kind: "varDecl", localId: receiverLocal.id, init: target.obj, loc };
10586
+ target.obj = { kind: "varRef", localId: receiverLocal.id, type: receiverLocal.type, loc };
10587
+ const receiver = lowerer.coerceToExpected(target.obj, DYN);
10588
+ const finish = (result) => ({ kind: "seqExpr", stmts: [init], result, type: result.type, loc });
9724
10589
  let callee = target ? lowerer.fieldGetExpr(target, locOf(access), access) : null;
9725
10590
  if (callee?.type.kind === "union" && callableType !== null) {
9726
10591
  const helper = lowerer.narrowedArmHelper(callee.type.unionId, callableType, locOf(access));
@@ -9729,15 +10594,24 @@ export function lowerObjectMethodCall(lowerer, call, access) {
9729
10594
  }
9730
10595
  }
9731
10596
  if (callee?.type.kind === "func") {
10597
+ if ((callee.type.rest === true && callee.type.restAbi === undefined || call.arguments.length > callee.type.params.length) &&
10598
+ isJsSourceFile(call.getSourceFile()) && lowerer.dynConvertible(callee.type)) {
10599
+ const boxed = { kind: "dynFrom", value: callee, type: DYN, loc };
10600
+ const spread = lowerSpreadArgsCall(lowerer, call, boxed, loc);
10601
+ if (spread?.kind === "dynCall")
10602
+ return finish({ ...spread, receiver });
10603
+ const args = call.arguments.map((arg) => lowerer.lowerExprExpecting(arg, DYN));
10604
+ return finish({ kind: "dynCall", callee: boxed, receiver, calleeName: access.getText(), args, type: DYN, loc });
10605
+ }
9732
10606
  const args = completeFuncValueArgs(lowerer, call, callee.type, locOf(call));
9733
- return { kind: "callValue", callee, args, type: callee.type.ret, loc: locOf(call) };
10607
+ return finish({ kind: "callValue", callee, receiver, args, type: callee.type.ret, loc });
9734
10608
  }
9735
10609
  if (callee?.type.kind === "dyn") {
9736
10610
  if (call.arguments.some((a) => ts.isSpreadElement(a))) {
9737
10611
  lowerer.unsupported("SC1090", call, "spread arguments in calls through 'unknown' values");
9738
10612
  }
9739
10613
  const args = call.arguments.map((a) => lowerer.lowerExprExpecting(a, DYN));
9740
- return { kind: "dynCall", callee, calleeName: access.getText(), args, type: DYN, loc: locOf(call) };
10614
+ return finish({ kind: "dynCall", callee, receiver, calleeName: access.getText(), args, type: DYN, loc });
9741
10615
  }
9742
10616
  }
9743
10617
  return null;
@@ -9745,18 +10619,25 @@ export function lowerObjectMethodCall(lowerer, call, access) {
9745
10619
  if (!info || !found)
9746
10620
  return null;
9747
10621
  const method = access.name.text;
9748
- if (found.declarer.builtinError) {
9749
- // The one builtin method: Error.prototype.toString, a runtime
9750
- // implementation called directly (overriding it is fenced, so no
9751
- // dispatch can ever be needed). Receiver BORROWED by the libCall.
10622
+ if (isClassCallback(lowerer, info, method)) {
10623
+ const loc = locOf(call);
9752
10624
  const receiver = lowerReceiver();
9753
- return {
9754
- kind: "libCall",
9755
- fn: "error.toString",
9756
- args: [lowerer.upcastTo(receiver, found.declarer.def.name)],
9757
- type: STRING,
9758
- loc: locOf(call),
9759
- };
10625
+ const local = lowerer.declareHiddenLocal("%callbackReceiver", receiver.type);
10626
+ const value = { kind: "varRef", localId: local.id, type: receiver.type, loc };
10627
+ const args = lowerer.completeArgs(call.arguments, found.sig.params, loc, call);
10628
+ const virtual = lowerer.overrideBelow(info, method);
10629
+ if (virtual)
10630
+ lowerer.noteVirtualEdge(info, method);
10631
+ else
10632
+ lowerer.noteEdge(`%${found.declarer.def.name}.${method}`);
10633
+ const fallback = virtual
10634
+ ? { kind: "virtualCall", className: info.def.name, method, args: [lowerer.upcastTo(value, info.def.name), ...args], type: found.sig.ret, loc }
10635
+ : { kind: "call", callee: `%${found.declarer.def.name}.${method}`, args: [lowerer.upcastTo(value, found.declarer.def.name), ...args], type: found.sig.ret, loc };
10636
+ const result = classCallbackCall(lowerer, value, method, call.arguments.map((arg) => lowerer.lowerExprExpecting(arg, DYN)), fallback, loc);
10637
+ return { kind: "seqExpr", stmts: [{ kind: "varDecl", localId: local.id, init: receiver, loc }], result, type: result.type, loc };
10638
+ }
10639
+ if (found.declarer.builtinError) {
10640
+ return errorToStringCall(lowerer, lowerReceiver());
9760
10641
  }
9761
10642
  // An ABSTRACT nearest declaration with no concrete override below the
9762
10643
  // static class: no implementation exists for a direct call to target.
@@ -9829,7 +10710,10 @@ function lowerUnionObjectMethodCall(lowerer, call, access, receiverT) {
9829
10710
  function paramAbisEqual(left, right) {
9830
10711
  return left.length === right.length && left.every((shape, i) => {
9831
10712
  const other = right[i];
9832
- return other !== undefined && shape.mode === other.mode && typeEquals(shape.type, other.type);
10713
+ return other !== undefined && typeEquals(shape.type, other.type) &&
10714
+ (shape.mode === other.mode || shape.type.kind === "dyn" &&
10715
+ (shape.mode === "required" || shape.mode === "omittable") &&
10716
+ (other.mode === "required" || other.mode === "omittable"));
9833
10717
  });
9834
10718
  }
9835
10719
  /** The JS-class sibling of union method dispatch: every arm stores the
@@ -9854,6 +10738,8 @@ function lowerUnionObjectDynFieldCall(lowerer, call, access, receiverT) {
9854
10738
  const loc = locOf(call);
9855
10739
  const receiver = lowerer.coerceInto(access.expression, lowerer.lowerExpr(access.expression), receiverT);
9856
10740
  const key = `${receiverT.unionId}:dyn-field:${field}`;
10741
+ const receiverLocal = lowerer.declareHiddenLocal("%unionCallReceiver", receiverT);
10742
+ const receiverRef = varRef(receiverLocal.id, receiverT, loc);
9857
10743
  let helper = lowerer.unionCallHelpers.get(key);
9858
10744
  if (!helper) {
9859
10745
  helper = `%union.call.${lowerer.unionCallHelpers.size}`;
@@ -9906,9 +10792,12 @@ function lowerUnionObjectDynFieldCall(lowerer, call, access, receiverT) {
9906
10792
  const locals = params.map((param) => ({ id: param.localId, name: param.name, type: param.type, mutable: false }));
9907
10793
  lowerer.liftedFns.push({ name: helper, params, returnType: DYN, locals, body, loc });
9908
10794
  }
9909
- const callee = { kind: "call", callee: helper, args: [receiver], type: DYN, loc };
10795
+ const callee = { kind: "call", callee: helper, args: [receiverRef], type: DYN, loc };
9910
10796
  const args = call.arguments.map((arg) => lowerer.lowerExprExpecting(arg, DYN));
9911
- return { kind: "dynCall", callee, calleeName: access.getText(), args, type: DYN, loc };
10797
+ return {
10798
+ kind: "seqExpr", stmts: [{ kind: "varDecl", localId: receiverLocal.id, init: receiver, loc }],
10799
+ result: { kind: "dynCall", callee, receiver: lowerer.coerceToExpected(receiverRef, DYN), calleeName: access.getText(), args, type: DYN, loc }, type: DYN, loc,
10800
+ };
9912
10801
  }
9913
10802
  function unionObjectMethodHelper(lowerer, sourceCall, receiverT, method, plans, shapes, resultT, loc) {
9914
10803
  const key = `${receiverT.unionId}:${method}:${shapes.map((shape) => `${shape.mode}:${typeKey(shape.type)}`).join(",")}:${typeKey(resultT)}`;
@@ -9930,13 +10819,7 @@ function unionObjectMethodHelper(lowerer, sourceCall, receiverT, method, plans,
9930
10819
  };
9931
10820
  let invoke;
9932
10821
  if (plan.found.declarer.builtinError) {
9933
- invoke = {
9934
- kind: "libCall",
9935
- fn: "error.toString",
9936
- args: [lowerer.upcastTo(concrete, plan.found.declarer.def.name)],
9937
- type: STRING,
9938
- loc,
9939
- };
10822
+ invoke = errorToStringCall(lowerer, concrete);
9940
10823
  }
9941
10824
  else if (lowerer.overrideBelow(plan.info, method)) {
9942
10825
  lowerer.noteVirtualEdge(plan.info, method);