@scriptc/compiler 0.1.6 → 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 (1060) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +73 -25
  2. package/ambient/scriptc-overrides.d.ts +10 -6
  3. package/ambient/scriptc.d.ts +28 -5
  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/debug-symbols.d.ts +8 -0
  16. package/dist/backend/debug-symbols.js +52 -0
  17. package/dist/backend/debug-symbols.js.map +1 -0
  18. package/dist/backend/executable-features.d.ts +4 -0
  19. package/dist/backend/executable-features.js +42 -0
  20. package/dist/backend/executable-features.js.map +1 -0
  21. package/dist/backend/external-c.d.ts +5 -27
  22. package/dist/backend/external-c.js +5 -40
  23. package/dist/backend/external-c.js.map +1 -1
  24. package/dist/backend/ffi-callbacks.d.ts +2 -3
  25. package/dist/backend/ffi-callbacks.js +2 -3
  26. package/dist/backend/ffi-callbacks.js.map +1 -1
  27. package/dist/backend/library-identity-markers.d.ts +4 -9
  28. package/dist/backend/library-identity-markers.js +11 -49
  29. package/dist/backend/library-identity-markers.js.map +1 -1
  30. package/dist/backend/library-pack.d.ts +5 -0
  31. package/dist/backend/library-pack.js +123 -0
  32. package/dist/backend/library-pack.js.map +1 -0
  33. package/dist/backend/link-plan-core.d.ts +20 -0
  34. package/dist/backend/link-plan-core.js +18 -0
  35. package/dist/backend/link-plan-core.js.map +1 -0
  36. package/dist/backend/link-plan.d.ts +2 -1
  37. package/dist/backend/link-plan.js +18 -17
  38. package/dist/backend/link-plan.js.map +1 -1
  39. package/dist/backend/link-trace.d.ts +2 -0
  40. package/dist/backend/link-trace.js +24 -0
  41. package/dist/backend/link-trace.js.map +1 -0
  42. package/dist/backend/linker.js +9 -1
  43. package/dist/backend/linker.js.map +1 -1
  44. package/dist/backend/literals.d.ts +9 -0
  45. package/dist/backend/literals.js +35 -0
  46. package/dist/backend/literals.js.map +1 -0
  47. package/dist/backend/literals.test.d.ts +1 -0
  48. package/dist/backend/literals.test.js +53 -0
  49. package/dist/backend/literals.test.js.map +1 -0
  50. package/dist/backend/llvm/blocks.d.ts +4 -0
  51. package/dist/backend/llvm/blocks.js +25 -4
  52. package/dist/backend/llvm/blocks.js.map +1 -1
  53. package/dist/backend/llvm/blocks.test.d.ts +1 -0
  54. package/dist/backend/llvm/blocks.test.js +91 -0
  55. package/dist/backend/llvm/blocks.test.js.map +1 -0
  56. package/dist/backend/llvm/classes.d.ts +14 -8
  57. package/dist/backend/llvm/classes.js +70 -28
  58. package/dist/backend/llvm/classes.js.map +1 -1
  59. package/dist/backend/llvm/common.d.ts +5 -1
  60. package/dist/backend/llvm/common.js +45 -4
  61. package/dist/backend/llvm/common.js.map +1 -1
  62. package/dist/backend/llvm/debug-info.d.ts +32 -0
  63. package/dist/backend/llvm/debug-info.js +198 -0
  64. package/dist/backend/llvm/debug-info.js.map +1 -0
  65. package/dist/backend/llvm/debug-info.test.d.ts +1 -0
  66. package/dist/backend/llvm/debug-info.test.js +110 -0
  67. package/dist/backend/llvm/debug-info.test.js.map +1 -0
  68. package/dist/backend/llvm/dyn.d.ts +16 -2
  69. package/dist/backend/llvm/dyn.js +498 -175
  70. package/dist/backend/llvm/dyn.js.map +1 -1
  71. package/dist/backend/llvm/emitter.d.ts +598 -1
  72. package/dist/backend/llvm/emitter.js +739 -409
  73. package/dist/backend/llvm/emitter.js.map +1 -1
  74. package/dist/backend/llvm/emitter.test.d.ts +1 -0
  75. package/dist/backend/llvm/emitter.test.js +179 -0
  76. package/dist/backend/llvm/emitter.test.js.map +1 -0
  77. package/dist/backend/llvm/expr-async.js +23 -14
  78. package/dist/backend/llvm/expr-async.js.map +1 -1
  79. package/dist/backend/llvm/expr-bytes.d.ts +1 -1
  80. package/dist/backend/llvm/expr-bytes.js +32 -14
  81. package/dist/backend/llvm/expr-bytes.js.map +1 -1
  82. package/dist/backend/llvm/expr-callbacks.d.ts +1 -1
  83. package/dist/backend/llvm/expr-callbacks.js +25 -22
  84. package/dist/backend/llvm/expr-callbacks.js.map +1 -1
  85. package/dist/backend/llvm/expr-calls.js +136 -35
  86. package/dist/backend/llvm/expr-calls.js.map +1 -1
  87. package/dist/backend/llvm/expr-containers.d.ts +1 -1
  88. package/dist/backend/llvm/expr-containers.js +43 -14
  89. package/dist/backend/llvm/expr-containers.js.map +1 -1
  90. package/dist/backend/llvm/expr-context.d.ts +5 -260
  91. package/dist/backend/llvm/expr-control.js +9 -5
  92. package/dist/backend/llvm/expr-control.js.map +1 -1
  93. package/dist/backend/llvm/expr-dispatch.d.ts +1 -1
  94. package/dist/backend/llvm/expr-dispatch.js +2 -0
  95. package/dist/backend/llvm/expr-dispatch.js.map +1 -1
  96. package/dist/backend/llvm/expr-dynamic.js +72 -74
  97. package/dist/backend/llvm/expr-dynamic.js.map +1 -1
  98. package/dist/backend/llvm/expr-island.d.ts +1 -1
  99. package/dist/backend/llvm/expr-island.js +11 -7
  100. package/dist/backend/llvm/expr-island.js.map +1 -1
  101. package/dist/backend/llvm/expr-primitives.d.ts +1 -1
  102. package/dist/backend/llvm/expr-primitives.js +51 -30
  103. package/dist/backend/llvm/expr-primitives.js.map +1 -1
  104. package/dist/backend/llvm/expr-primitives.test.js +1 -1
  105. package/dist/backend/llvm/expr-records.d.ts +5 -1
  106. package/dist/backend/llvm/expr-records.js +43 -4
  107. package/dist/backend/llvm/expr-records.js.map +1 -1
  108. package/dist/backend/llvm/expr-stream-bridges.d.ts +4 -4
  109. package/dist/backend/llvm/expr-stream-bridges.js +102 -121
  110. package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
  111. package/dist/backend/llvm/expr-stream-bridges.test.d.ts +1 -0
  112. package/dist/backend/llvm/expr-stream-bridges.test.js +55 -0
  113. package/dist/backend/llvm/expr-stream-bridges.test.js.map +1 -0
  114. package/dist/backend/llvm/expr-stream-callbacks.d.ts +1 -1
  115. package/dist/backend/llvm/expr-stream-callbacks.js +12 -12
  116. package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
  117. package/dist/backend/llvm/layouts.d.ts +19 -0
  118. package/dist/backend/llvm/layouts.js +12 -0
  119. package/dist/backend/llvm/layouts.js.map +1 -0
  120. package/dist/backend/llvm/lib-abi.d.ts +19 -0
  121. package/dist/backend/llvm/lib-abi.js +82 -0
  122. package/dist/backend/llvm/lib-abi.js.map +1 -0
  123. package/dist/backend/llvm/lib-connect.d.ts +2 -0
  124. package/dist/backend/llvm/lib-connect.js +51 -0
  125. package/dist/backend/llvm/lib-connect.js.map +1 -0
  126. package/dist/backend/llvm/lib-datagram.d.ts +2 -0
  127. package/dist/backend/llvm/lib-datagram.js +135 -0
  128. package/dist/backend/llvm/lib-datagram.js.map +1 -0
  129. package/dist/backend/llvm/lib-dispatch.js +50 -6
  130. package/dist/backend/llvm/lib-dispatch.js.map +1 -1
  131. package/dist/backend/llvm/lib-filesystem.js +59 -18
  132. package/dist/backend/llvm/lib-filesystem.js.map +1 -1
  133. package/dist/backend/llvm/lib-http2.d.ts +2 -0
  134. package/dist/backend/llvm/lib-http2.js +215 -0
  135. package/dist/backend/llvm/lib-http2.js.map +1 -0
  136. package/dist/backend/llvm/lib-lookup.d.ts +2 -0
  137. package/dist/backend/llvm/lib-lookup.js +39 -0
  138. package/dist/backend/llvm/lib-lookup.js.map +1 -0
  139. package/dist/backend/llvm/lib-network.js +25 -2
  140. package/dist/backend/llvm/lib-network.js.map +1 -1
  141. package/dist/backend/llvm/lib-process.js +21 -16
  142. package/dist/backend/llvm/lib-process.js.map +1 -1
  143. package/dist/backend/llvm/lib-shared.js +125 -1
  144. package/dist/backend/llvm/lib-shared.js.map +1 -1
  145. package/dist/backend/llvm/lib-stream.js +3 -2
  146. package/dist/backend/llvm/lib-stream.js.map +1 -1
  147. package/dist/backend/llvm/lib-test.d.ts +2 -0
  148. package/dist/backend/llvm/lib-test.js +34 -0
  149. package/dist/backend/llvm/lib-test.js.map +1 -0
  150. package/dist/backend/llvm/lib-tls.d.ts +2 -0
  151. package/dist/backend/llvm/lib-tls.js +82 -0
  152. package/dist/backend/llvm/lib-tls.js.map +1 -0
  153. package/dist/backend/llvm/shapes.d.ts +10 -9
  154. package/dist/backend/llvm/shapes.js +35 -130
  155. package/dist/backend/llvm/shapes.js.map +1 -1
  156. package/dist/backend/llvm/split.js +4 -1
  157. package/dist/backend/llvm/split.js.map +1 -1
  158. package/dist/backend/llvm/split.test.js +26 -1
  159. package/dist/backend/llvm/split.test.js.map +1 -1
  160. package/dist/backend/llvm/unsupported.d.ts +1 -0
  161. package/dist/backend/llvm/unsupported.js +1 -2
  162. package/dist/backend/llvm/unsupported.js.map +1 -1
  163. package/dist/backend/llvm/walkers.js +1 -7
  164. package/dist/backend/llvm/walkers.js.map +1 -1
  165. package/dist/backend/mangle.d.ts +2 -2
  166. package/dist/backend/mangle.js +16 -5
  167. package/dist/backend/mangle.js.map +1 -1
  168. package/dist/backend/{c/may-throw.d.ts → may-throw.d.ts} +1 -1
  169. package/dist/backend/{c/may-throw.js → may-throw.js} +51 -46
  170. package/dist/backend/may-throw.js.map +1 -0
  171. package/dist/backend/may-throw.test.d.ts +1 -0
  172. package/dist/backend/may-throw.test.js +58 -0
  173. package/dist/backend/may-throw.test.js.map +1 -0
  174. package/dist/backend/native-codegen-core.d.ts +22 -0
  175. package/dist/backend/native-codegen-core.js +44 -0
  176. package/dist/backend/native-codegen-core.js.map +1 -0
  177. package/dist/backend/native-codegen.d.ts +3 -19
  178. package/dist/backend/native-codegen.js +5 -44
  179. package/dist/backend/native-codegen.js.map +1 -1
  180. package/dist/backend/native-codegen.test.js +2 -2
  181. package/dist/backend/native-codegen.test.js.map +1 -1
  182. package/dist/backend/native-link-info-core.d.ts +94 -0
  183. package/dist/backend/native-link-info-core.js +62 -0
  184. package/dist/backend/native-link-info-core.js.map +1 -0
  185. package/dist/backend/native-link-info.d.ts +3 -88
  186. package/dist/backend/native-link-info.js +12 -243
  187. package/dist/backend/native-link-info.js.map +1 -1
  188. package/dist/backend/native-link-info.test.js +41 -146
  189. package/dist/backend/native-link-info.test.js.map +1 -1
  190. package/dist/backend/native-toolchain.d.ts +10 -25
  191. package/dist/backend/native-toolchain.js +89 -219
  192. package/dist/backend/native-toolchain.js.map +1 -1
  193. package/dist/backend/native-toolchain.test.js +15 -5
  194. package/dist/backend/native-toolchain.test.js.map +1 -1
  195. package/dist/backend/native-tools.d.ts +24 -0
  196. package/dist/backend/native-tools.js +33 -0
  197. package/dist/backend/native-tools.js.map +1 -0
  198. package/dist/backend/object-localize.js +19 -8
  199. package/dist/backend/object-localize.js.map +1 -1
  200. package/dist/backend/object-localize.test.js +22 -0
  201. package/dist/backend/object-localize.test.js.map +1 -1
  202. package/dist/backend/runtime-abi.d.ts +2 -2
  203. package/dist/backend/runtime-abi.js +2 -2
  204. package/dist/backend/runtime-pack-core.d.ts +101 -0
  205. package/dist/backend/runtime-pack-core.js +172 -0
  206. package/dist/backend/runtime-pack-core.js.map +1 -0
  207. package/dist/backend/runtime-pack-native.d.ts +21 -0
  208. package/dist/backend/runtime-pack-native.js +70 -0
  209. package/dist/backend/runtime-pack-native.js.map +1 -0
  210. package/dist/backend/runtime-pack-targets.test.js +1 -1
  211. package/dist/backend/runtime-pack.d.ts +3 -83
  212. package/dist/backend/runtime-pack.js +8 -151
  213. package/dist/backend/runtime-pack.js.map +1 -1
  214. package/dist/backend/runtime-pack.test.js +24 -1
  215. package/dist/backend/runtime-pack.test.js.map +1 -1
  216. package/dist/backend/source-locations.d.ts +12 -0
  217. package/dist/backend/source-locations.js +32 -0
  218. package/dist/backend/source-locations.js.map +1 -0
  219. package/dist/backend/source-locations.test.d.ts +1 -0
  220. package/dist/backend/source-locations.test.js +16 -0
  221. package/dist/backend/source-locations.test.js.map +1 -0
  222. package/dist/backend/target-diagnostics.d.ts +22 -0
  223. package/dist/backend/target-diagnostics.js +108 -0
  224. package/dist/backend/target-diagnostics.js.map +1 -0
  225. package/dist/backend/target-platform.d.ts +15 -0
  226. package/dist/backend/target-platform.js +72 -0
  227. package/dist/backend/target-platform.js.map +1 -0
  228. package/dist/backend/targets.d.ts +13 -4
  229. package/dist/backend/targets.js +95 -30
  230. package/dist/backend/targets.js.map +1 -1
  231. package/dist/backend/targets.test.js +65 -4
  232. package/dist/backend/targets.test.js.map +1 -1
  233. package/dist/backend/toolchain-environment.d.ts +6 -0
  234. package/dist/backend/toolchain-environment.js +99 -0
  235. package/dist/backend/toolchain-environment.js.map +1 -0
  236. package/dist/backend/vendor-archives.d.ts +1 -9
  237. package/dist/backend/vendor-archives.js +2 -9
  238. package/dist/backend/vendor-archives.js.map +1 -1
  239. package/dist/backend/vendor-inputs.d.ts +9 -0
  240. package/dist/backend/vendor-inputs.js +10 -0
  241. package/dist/backend/vendor-inputs.js.map +1 -0
  242. package/dist/backend/warm-cache.d.ts +3 -0
  243. package/dist/backend/warm-cache.js +41 -0
  244. package/dist/backend/warm-cache.js.map +1 -0
  245. package/dist/cli/command.d.ts +3 -0
  246. package/dist/cli/command.js +328 -0
  247. package/dist/cli/command.js.map +1 -0
  248. package/dist/cli/host.d.ts +24 -0
  249. package/dist/cli/host.js +2 -0
  250. package/dist/cli/host.js.map +1 -0
  251. package/dist/cli/output-options.d.ts +26 -0
  252. package/dist/cli/output-options.js +60 -0
  253. package/dist/cli/output-options.js.map +1 -0
  254. package/dist/cli/paths.d.ts +12 -0
  255. package/dist/cli/paths.js +42 -0
  256. package/dist/cli/paths.js.map +1 -0
  257. package/dist/cli/usage.d.ts +74 -0
  258. package/dist/cli/usage.js +86 -0
  259. package/dist/cli/usage.js.map +1 -0
  260. package/dist/cli/wasi-paths.d.ts +8 -0
  261. package/dist/cli/wasi-paths.js +41 -0
  262. package/dist/cli/wasi-paths.js.map +1 -0
  263. package/dist/cli/wasi-runner.d.ts +2 -0
  264. package/dist/cli/wasi-runner.js +28 -0
  265. package/dist/cli/wasi-runner.js.map +1 -0
  266. package/dist/compat/fetch-profile.js +3 -3
  267. package/dist/compat/fetch-profile.js.map +1 -1
  268. package/dist/compile-types.d.ts +162 -0
  269. package/dist/compile-types.js +2 -0
  270. package/dist/compile-types.js.map +1 -0
  271. package/dist/coverage/report.js +11 -5
  272. package/dist/coverage/report.js.map +1 -1
  273. package/dist/coverage/surface-manifest.js +5 -2
  274. package/dist/coverage/surface-manifest.js.map +1 -1
  275. package/dist/diagnostics/diagnostic.d.ts +4 -0
  276. package/dist/diagnostics/diagnostic.js +15 -3
  277. package/dist/diagnostics/diagnostic.js.map +1 -1
  278. package/dist/executable/executable-cache.d.ts +3 -4
  279. package/dist/executable/executable-cache.js +33 -10
  280. package/dist/executable/executable-cache.js.map +1 -1
  281. package/dist/executable/executable-cache.test.js +38 -16
  282. package/dist/executable/executable-cache.test.js.map +1 -1
  283. package/dist/executable/prepare.d.ts +14 -0
  284. package/dist/executable/prepare.js +66 -0
  285. package/dist/executable/prepare.js.map +1 -0
  286. package/dist/ffi/ffi-manifest.d.ts +11 -4
  287. package/dist/ffi/ffi-manifest.js +170 -58
  288. package/dist/ffi/ffi-manifest.js.map +1 -1
  289. package/dist/ffi/ffi-manifest.test.d.ts +1 -0
  290. package/dist/ffi/ffi-manifest.test.js +111 -0
  291. package/dist/ffi/ffi-manifest.test.js.map +1 -0
  292. package/dist/format-integer.d.ts +3 -0
  293. package/dist/format-integer.js +14 -0
  294. package/dist/format-integer.js.map +1 -0
  295. package/dist/frontend/analysis.d.ts +5 -0
  296. package/dist/frontend/analysis.js +88 -0
  297. package/dist/frontend/analysis.js.map +1 -0
  298. package/dist/frontend/arguments-usage.d.ts +4 -0
  299. package/dist/frontend/arguments-usage.js +40 -0
  300. package/dist/frontend/arguments-usage.js.map +1 -0
  301. package/dist/frontend/binding-source.d.ts +4 -0
  302. package/dist/frontend/binding-source.js +18 -0
  303. package/dist/frontend/binding-source.js.map +1 -0
  304. package/dist/frontend/builtin-modules.d.ts +1 -1
  305. package/dist/frontend/builtin-modules.js +1 -1
  306. package/dist/frontend/builtin-modules.js.map +1 -1
  307. package/dist/frontend/cjs-lexer.d.ts +4 -25
  308. package/dist/frontend/cjs-lexer.js +6 -806
  309. package/dist/frontend/cjs-lexer.js.map +1 -1
  310. package/dist/frontend/cjs-resolve.d.ts +5 -0
  311. package/dist/frontend/cjs-resolve.js +429 -0
  312. package/dist/frontend/cjs-resolve.js.map +1 -0
  313. package/dist/frontend/cjs-syntax.d.ts +26 -0
  314. package/dist/frontend/cjs-syntax.js +806 -0
  315. package/dist/frontend/cjs-syntax.js.map +1 -0
  316. package/dist/frontend/comptime-node.d.ts +4 -0
  317. package/dist/frontend/comptime-node.js +16 -0
  318. package/dist/frontend/comptime-node.js.map +1 -0
  319. package/dist/frontend/comptime-node.test.d.ts +1 -0
  320. package/dist/frontend/comptime-node.test.js +37 -0
  321. package/dist/frontend/comptime-node.test.js.map +1 -0
  322. package/dist/frontend/dts-paths.d.ts +3 -4
  323. package/dist/frontend/dts-paths.js +15 -8
  324. package/dist/frontend/dts-paths.js.map +1 -1
  325. package/dist/frontend/fork-target.js +2 -2
  326. package/dist/frontend/fork-target.js.map +1 -1
  327. package/dist/frontend/helper-tokens.d.ts +1 -0
  328. package/dist/frontend/helper-tokens.js +147 -0
  329. package/dist/frontend/helper-tokens.js.map +1 -0
  330. package/dist/frontend/helper-tokens.test.d.ts +1 -0
  331. package/dist/frontend/helper-tokens.test.js +35 -0
  332. package/dist/frontend/helper-tokens.test.js.map +1 -0
  333. package/dist/frontend/inferred-js-diagnostics.d.ts +5 -0
  334. package/dist/frontend/inferred-js-diagnostics.js +69 -0
  335. package/dist/frontend/inferred-js-diagnostics.js.map +1 -0
  336. package/dist/frontend/inferred-js-diagnostics.test.d.ts +1 -0
  337. package/dist/frontend/inferred-js-diagnostics.test.js +58 -0
  338. package/dist/frontend/inferred-js-diagnostics.test.js.map +1 -0
  339. package/dist/frontend/input-tracker.d.ts +5 -2
  340. package/dist/frontend/input-tracker.js +24 -3
  341. package/dist/frontend/input-tracker.js.map +1 -1
  342. package/dist/frontend/input-tracker.test.js +23 -0
  343. package/dist/frontend/input-tracker.test.js.map +1 -1
  344. package/dist/frontend/lib-contract.js +32 -24
  345. package/dist/frontend/lib-contract.js.map +1 -1
  346. package/dist/frontend/literal-values.d.ts +4 -0
  347. package/dist/frontend/literal-values.js +21 -0
  348. package/dist/frontend/literal-values.js.map +1 -0
  349. package/dist/frontend/literal-values.test.d.ts +1 -0
  350. package/dist/frontend/literal-values.test.js +91 -0
  351. package/dist/frontend/literal-values.test.js.map +1 -0
  352. package/dist/frontend/lowering/abstract-equality.d.ts +1 -1
  353. package/dist/frontend/lowering/abstract-equality.js +3 -0
  354. package/dist/frontend/lowering/abstract-equality.js.map +1 -1
  355. package/dist/frontend/lowering/array-indexed-mutation.js +11 -6
  356. package/dist/frontend/lowering/array-indexed-mutation.js.map +1 -1
  357. package/dist/frontend/lowering/array-values.d.ts +4 -1
  358. package/dist/frontend/lowering/array-values.js +43 -1
  359. package/dist/frontend/lowering/array-values.js.map +1 -1
  360. package/dist/frontend/lowering/callback-arg.js +1 -0
  361. package/dist/frontend/lowering/callback-arg.js.map +1 -1
  362. package/dist/frontend/lowering/class-callbacks.d.ts +12 -0
  363. package/dist/frontend/lowering/class-callbacks.js +63 -0
  364. package/dist/frontend/lowering/class-callbacks.js.map +1 -0
  365. package/dist/frontend/lowering/class-descriptors.d.ts +9 -0
  366. package/dist/frontend/lowering/class-descriptors.js +73 -0
  367. package/dist/frontend/lowering/class-descriptors.js.map +1 -0
  368. package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +41 -0
  369. package/dist/frontend/lowering/class-dynamic-dispatch.js +803 -0
  370. package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -0
  371. package/dist/frontend/lowering/class-dynamic-dispatch.test.d.ts +1 -0
  372. package/dist/frontend/lowering/class-dynamic-dispatch.test.js +92 -0
  373. package/dist/frontend/lowering/class-dynamic-dispatch.test.js.map +1 -0
  374. package/dist/frontend/lowering/class-instance-constructor.d.ts +7 -0
  375. package/dist/frontend/lowering/class-instance-constructor.js +64 -0
  376. package/dist/frontend/lowering/class-instance-constructor.js.map +1 -0
  377. package/dist/frontend/lowering/class-method-values.d.ts +10 -0
  378. package/dist/frontend/lowering/class-method-values.js +170 -0
  379. package/dist/frontend/lowering/class-method-values.js.map +1 -0
  380. package/dist/frontend/lowering/class-prototypes.d.ts +16 -0
  381. package/dist/frontend/lowering/class-prototypes.js +134 -0
  382. package/dist/frontend/lowering/class-prototypes.js.map +1 -0
  383. package/dist/frontend/lowering/class-static-data.d.ts +6 -0
  384. package/dist/frontend/lowering/class-static-data.js +56 -0
  385. package/dist/frontend/lowering/class-static-data.js.map +1 -0
  386. package/dist/frontend/lowering/containers/buffer-numeric-methods.d.ts +4 -0
  387. package/dist/frontend/lowering/containers/buffer-numeric-methods.js +26 -0
  388. package/dist/frontend/lowering/containers/buffer-numeric-methods.js.map +1 -0
  389. package/dist/frontend/lowering/containers/bytes.d.ts +11 -7
  390. package/dist/frontend/lowering/containers/bytes.js +164 -155
  391. package/dist/frontend/lowering/containers/bytes.js.map +1 -1
  392. package/dist/frontend/lowering/containers/string-and-regexp.d.ts +2 -2
  393. package/dist/frontend/lowering/containers/string-and-regexp.js +39 -16
  394. package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
  395. package/dist/frontend/lowering/containers/string-replacement.d.ts +7 -0
  396. package/dist/frontend/lowering/containers/string-replacement.js +217 -0
  397. package/dist/frontend/lowering/containers/string-replacement.js.map +1 -0
  398. package/dist/frontend/lowering/error-methods.d.ts +11 -0
  399. package/dist/frontend/lowering/error-methods.js +78 -0
  400. package/dist/frontend/lowering/error-methods.js.map +1 -0
  401. package/dist/frontend/lowering/expressions/global-symbols.d.ts +6 -0
  402. package/dist/frontend/lowering/expressions/global-symbols.js +11 -0
  403. package/dist/frontend/lowering/expressions/global-symbols.js.map +1 -0
  404. package/dist/frontend/lowering/expressions/native-proxy.d.ts +7 -0
  405. package/dist/frontend/lowering/expressions/native-proxy.js +49 -0
  406. package/dist/frontend/lowering/expressions/native-proxy.js.map +1 -0
  407. package/dist/frontend/lowering/expressions/nullish-assignment.d.ts +6 -0
  408. package/dist/frontend/lowering/expressions/nullish-assignment.js +124 -0
  409. package/dist/frontend/lowering/expressions/nullish-assignment.js.map +1 -0
  410. package/dist/frontend/lowering/expressions/object-literals.d.ts +8 -8
  411. package/dist/frontend/lowering/expressions/object-literals.js +485 -185
  412. package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
  413. package/dist/frontend/lowering/expressions/optional-chains.d.ts +5 -6
  414. package/dist/frontend/lowering/expressions/optional-chains.js +27 -14
  415. package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
  416. package/dist/frontend/lowering/expressions/try-lower-expression.js +1 -0
  417. package/dist/frontend/lowering/expressions/try-lower-expression.js.map +1 -1
  418. package/dist/frontend/lowering/expressions/union-field-write.d.ts +8 -0
  419. package/dist/frontend/lowering/expressions/union-field-write.js +71 -0
  420. package/dist/frontend/lowering/expressions/union-field-write.js.map +1 -0
  421. package/dist/frontend/lowering/function-context.d.ts +93 -0
  422. package/dist/frontend/lowering/function-context.js +103 -0
  423. package/dist/frontend/lowering/function-context.js.map +1 -0
  424. package/dist/frontend/lowering/generator-delegation.d.ts +7 -0
  425. package/dist/frontend/lowering/generator-delegation.js +85 -0
  426. package/dist/frontend/lowering/generator-delegation.js.map +1 -0
  427. package/dist/frontend/lowering/generator-dynamic-dispatch.d.ts +10 -0
  428. package/dist/frontend/lowering/generator-dynamic-dispatch.js +105 -0
  429. package/dist/frontend/lowering/generator-dynamic-dispatch.js.map +1 -0
  430. package/dist/frontend/lowering/lib-boundary.d.ts +2 -1
  431. package/dist/frontend/lowering/lib-boundary.js +59 -20
  432. package/dist/frontend/lowering/lib-boundary.js.map +1 -1
  433. package/dist/frontend/lowering/lib-boundary.test.d.ts +1 -0
  434. package/dist/frontend/lowering/lib-boundary.test.js +45 -0
  435. package/dist/frontend/lowering/lib-boundary.test.js.map +1 -0
  436. package/dist/frontend/lowering/lower-array-sort.d.ts +1 -1
  437. package/dist/frontend/lowering/lower-assert.d.ts +1 -1
  438. package/dist/frontend/lowering/lower-assert.js.map +1 -1
  439. package/dist/frontend/lowering/lower-async-iteration.d.ts +1 -1
  440. package/dist/frontend/lowering/lower-async-iteration.js.map +1 -1
  441. package/dist/frontend/lowering/lower-builtin-values.d.ts +12 -0
  442. package/dist/frontend/lowering/lower-builtin-values.js +139 -0
  443. package/dist/frontend/lowering/lower-builtin-values.js.map +1 -0
  444. package/dist/frontend/lowering/lower-builtins.d.ts +27 -41
  445. package/dist/frontend/lowering/lower-builtins.js +553 -346
  446. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  447. package/dist/frontend/lowering/lower-calls.d.ts +22 -26
  448. package/dist/frontend/lowering/lower-calls.js +1373 -380
  449. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  450. package/dist/frontend/lowering/lower-classes.d.ts +83 -45
  451. package/dist/frontend/lowering/lower-classes.js +952 -339
  452. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  453. package/dist/frontend/lowering/lower-comptime.d.ts +1 -1
  454. package/dist/frontend/lowering/lower-comptime.js +23 -32
  455. package/dist/frontend/lowering/lower-comptime.js.map +1 -1
  456. package/dist/frontend/lowering/lower-containers.d.ts +27 -32
  457. package/dist/frontend/lowering/lower-containers.js +796 -151
  458. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  459. package/dist/frontend/lowering/lower-dgram.d.ts +1 -1
  460. package/dist/frontend/lowering/lower-dgram.js.map +1 -1
  461. package/dist/frontend/lowering/lower-enums.d.ts +1 -1
  462. package/dist/frontend/lowering/lower-enums.js.map +1 -1
  463. package/dist/frontend/lowering/lower-event-emitter.d.ts +30 -1
  464. package/dist/frontend/lowering/lower-event-emitter.js +58 -26
  465. package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
  466. package/dist/frontend/lowering/lower-expando.d.ts +7 -1
  467. package/dist/frontend/lowering/lower-expando.js +14 -6
  468. package/dist/frontend/lowering/lower-expando.js.map +1 -1
  469. package/dist/frontend/lowering/lower-exprs.d.ts +35 -11
  470. package/dist/frontend/lowering/lower-exprs.js +1785 -790
  471. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  472. package/dist/frontend/lowering/lower-generators.d.ts +2 -5
  473. package/dist/frontend/lowering/lower-generators.js +77 -46
  474. package/dist/frontend/lowering/lower-generators.js.map +1 -1
  475. package/dist/frontend/lowering/lower-global-value.d.ts +7 -0
  476. package/dist/frontend/lowering/lower-global-value.js +17 -0
  477. package/dist/frontend/lowering/lower-global-value.js.map +1 -0
  478. package/dist/frontend/lowering/lower-inspect.d.ts +1 -1
  479. package/dist/frontend/lowering/lower-inspect.js +17 -8
  480. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  481. package/dist/frontend/lowering/lower-island.d.ts +5 -8
  482. package/dist/frontend/lowering/lower-island.js +34 -23
  483. package/dist/frontend/lowering/lower-island.js.map +1 -1
  484. package/dist/frontend/lowering/lower-mixins.d.ts +2 -2
  485. package/dist/frontend/lowering/lower-mixins.js +5 -3
  486. package/dist/frontend/lowering/lower-mixins.js.map +1 -1
  487. package/dist/frontend/lowering/lower-modules.d.ts +1 -1
  488. package/dist/frontend/lowering/lower-modules.js +252 -38
  489. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  490. package/dist/frontend/lowering/lower-namespaces.d.ts +1 -1
  491. package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
  492. package/dist/frontend/lowering/lower-node-module.d.ts +1 -1
  493. package/dist/frontend/lowering/lower-node-module.js +13 -10
  494. package/dist/frontend/lowering/lower-node-module.js.map +1 -1
  495. package/dist/frontend/lowering/lower-server.d.ts +1 -1
  496. package/dist/frontend/lowering/lower-server.js +6 -10
  497. package/dist/frontend/lowering/lower-server.js.map +1 -1
  498. package/dist/frontend/lowering/lower-stmts.d.ts +10 -14
  499. package/dist/frontend/lowering/lower-stmts.js +731 -532
  500. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  501. package/dist/frontend/lowering/lower-stream.d.ts +1 -1
  502. package/dist/frontend/lowering/lower-stream.js +19 -10
  503. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  504. package/dist/frontend/lowering/lower-test.d.ts +1 -1
  505. package/dist/frontend/lowering/lower-test.js.map +1 -1
  506. package/dist/frontend/lowering/lower-url.d.ts +6 -0
  507. package/dist/frontend/lowering/lower-url.js +77 -0
  508. package/dist/frontend/lowering/lower-url.js.map +1 -0
  509. package/dist/frontend/lowering/lowerer.d.ts +113 -189
  510. package/dist/frontend/lowering/lowerer.js +1033 -663
  511. package/dist/frontend/lowering/lowerer.js.map +1 -1
  512. package/dist/frontend/lowering/lowerer.test.d.ts +1 -0
  513. package/dist/frontend/lowering/lowerer.test.js +26 -0
  514. package/dist/frontend/lowering/lowerer.test.js.map +1 -0
  515. package/dist/frontend/lowering/native-ffi.d.ts +5 -0
  516. package/dist/frontend/lowering/native-ffi.js +40 -0
  517. package/dist/frontend/lowering/native-ffi.js.map +1 -0
  518. package/dist/frontend/lowering/object-enumeration-receiver.d.ts +7 -0
  519. package/dist/frontend/lowering/object-enumeration-receiver.js +33 -0
  520. package/dist/frontend/lowering/object-enumeration-receiver.js.map +1 -0
  521. package/dist/frontend/lowering/object-factory-new.d.ts +8 -0
  522. package/dist/frontend/lowering/object-factory-new.js +68 -0
  523. package/dist/frontend/lowering/object-factory-new.js.map +1 -0
  524. package/dist/frontend/lowering/optional-arguments.js +6 -1
  525. package/dist/frontend/lowering/optional-arguments.js.map +1 -1
  526. package/dist/frontend/lowering/pairs-snapshot.js +2 -1
  527. package/dist/frontend/lowering/pairs-snapshot.js.map +1 -1
  528. package/dist/frontend/lowering/runtime-optional-locals.d.ts +14 -0
  529. package/dist/frontend/lowering/runtime-optional-locals.js +41 -0
  530. package/dist/frontend/lowering/runtime-optional-locals.js.map +1 -0
  531. package/dist/frontend/lowering/runtime-optional-locals.test.d.ts +1 -0
  532. package/dist/frontend/lowering/runtime-optional-locals.test.js +85 -0
  533. package/dist/frontend/lowering/runtime-optional-locals.test.js.map +1 -0
  534. package/dist/frontend/lowering/sanitize-class-types.d.ts +8 -0
  535. package/dist/frontend/lowering/sanitize-class-types.js +79 -0
  536. package/dist/frontend/lowering/sanitize-class-types.js.map +1 -0
  537. package/dist/frontend/lowering/sanitize-class-types.test.d.ts +1 -0
  538. package/dist/frontend/lowering/sanitize-class-types.test.js +60 -0
  539. package/dist/frontend/lowering/sanitize-class-types.test.js.map +1 -0
  540. package/dist/frontend/lowering/static-this.d.ts +5 -1
  541. package/dist/frontend/lowering/static-this.js +28 -2
  542. package/dist/frontend/lowering/static-this.js.map +1 -1
  543. package/dist/frontend/lowering/string-index.d.ts +7 -0
  544. package/dist/frontend/lowering/string-index.js +39 -0
  545. package/dist/frontend/lowering/string-index.js.map +1 -0
  546. package/dist/frontend/lowering/surfaces.d.ts +9 -4
  547. package/dist/frontend/lowering/surfaces.js +98 -35
  548. package/dist/frontend/lowering/surfaces.js.map +1 -1
  549. package/dist/frontend/lowering/symbol-fields.d.ts +22 -0
  550. package/dist/frontend/lowering/symbol-fields.js +183 -0
  551. package/dist/frontend/lowering/symbol-fields.js.map +1 -0
  552. package/dist/frontend/lowering/symbol-methods.d.ts +7 -0
  553. package/dist/frontend/lowering/symbol-methods.js +30 -0
  554. package/dist/frontend/lowering/symbol-methods.js.map +1 -0
  555. package/dist/frontend/lowering/text-decoder-encoding.d.ts +10 -0
  556. package/dist/frontend/lowering/text-decoder-encoding.js +77 -0
  557. package/dist/frontend/lowering/text-decoder-encoding.js.map +1 -0
  558. package/dist/frontend/lowering/text-decoder-encoding.test.d.ts +1 -0
  559. package/dist/frontend/lowering/text-decoder-encoding.test.js +38 -0
  560. package/dist/frontend/lowering/text-decoder-encoding.test.js.map +1 -0
  561. package/dist/frontend/lowering/union-narrow.d.ts +9 -0
  562. package/dist/frontend/lowering/union-narrow.js +59 -0
  563. package/dist/frontend/lowering/union-narrow.js.map +1 -0
  564. package/dist/frontend/lowering/union-narrow.test.d.ts +1 -0
  565. package/dist/frontend/lowering/union-narrow.test.js +72 -0
  566. package/dist/frontend/lowering/union-narrow.test.js.map +1 -0
  567. package/dist/frontend/lowering/union-retag.d.ts +43 -0
  568. package/dist/frontend/lowering/union-retag.js +259 -0
  569. package/dist/frontend/lowering/union-retag.js.map +1 -0
  570. package/dist/frontend/lowering/union-retag.test.d.ts +1 -0
  571. package/dist/frontend/lowering/union-retag.test.js +405 -0
  572. package/dist/frontend/lowering/union-retag.test.js.map +1 -0
  573. package/dist/frontend/lowering/unregistered-class-types.d.ts +14 -0
  574. package/dist/frontend/lowering/unregistered-class-types.js +94 -0
  575. package/dist/frontend/lowering/unregistered-class-types.js.map +1 -0
  576. package/dist/frontend/lowering/unregistered-class-types.test.d.ts +1 -0
  577. package/dist/frontend/lowering/unregistered-class-types.test.js +65 -0
  578. package/dist/frontend/lowering/unregistered-class-types.test.js.map +1 -0
  579. package/dist/frontend/lowering/width-lift.d.ts +40 -0
  580. package/dist/frontend/lowering/width-lift.js +2 -0
  581. package/dist/frontend/lowering/width-lift.js.map +1 -0
  582. package/dist/frontend/module-syntax.d.ts +58 -0
  583. package/dist/frontend/module-syntax.js +123 -0
  584. package/dist/frontend/module-syntax.js.map +1 -0
  585. package/dist/frontend/module-syntax.test.d.ts +1 -0
  586. package/dist/frontend/module-syntax.test.js +78 -0
  587. package/dist/frontend/module-syntax.test.js.map +1 -0
  588. package/dist/frontend/npm-fetch-analysis.d.ts +17 -0
  589. package/dist/frontend/npm-fetch-analysis.js +100 -0
  590. package/dist/frontend/npm-fetch-analysis.js.map +1 -0
  591. package/dist/frontend/npm-fetch-analysis.test.d.ts +1 -0
  592. package/dist/frontend/npm-fetch-analysis.test.js +107 -0
  593. package/dist/frontend/npm-fetch-analysis.test.js.map +1 -0
  594. package/dist/frontend/npm-fetch-node.d.ts +2 -0
  595. package/dist/frontend/npm-fetch-node.js +12 -0
  596. package/dist/frontend/npm-fetch-node.js.map +1 -0
  597. package/dist/frontend/npm-fetch-syntax.d.ts +6 -0
  598. package/dist/frontend/npm-fetch-syntax.js +207 -0
  599. package/dist/frontend/npm-fetch-syntax.js.map +1 -0
  600. package/dist/frontend/npm-node.d.ts +10 -0
  601. package/dist/frontend/npm-node.js +14 -0
  602. package/dist/frontend/npm-node.js.map +1 -0
  603. package/dist/frontend/npm-static-bundled-cjs.d.ts +8 -0
  604. package/dist/frontend/npm-static-bundled-cjs.js +236 -0
  605. package/dist/frontend/npm-static-bundled-cjs.js.map +1 -0
  606. package/dist/frontend/npm-static-bundled-cjs.test.d.ts +1 -0
  607. package/dist/frontend/npm-static-bundled-cjs.test.js +69 -0
  608. package/dist/frontend/npm-static-bundled-cjs.test.js.map +1 -0
  609. package/dist/frontend/npm-static-declaration-syntax.d.ts +57 -0
  610. package/dist/frontend/npm-static-declaration-syntax.js +944 -0
  611. package/dist/frontend/npm-static-declaration-syntax.js.map +1 -0
  612. package/dist/frontend/npm-static-declarations.d.ts +11 -39
  613. package/dist/frontend/npm-static-declarations.js +22 -561
  614. package/dist/frontend/npm-static-declarations.js.map +1 -1
  615. package/dist/frontend/npm-static-declarations.test.js +245 -6
  616. package/dist/frontend/npm-static-declarations.test.js.map +1 -1
  617. package/dist/frontend/npm-static-prune.d.ts +1 -1
  618. package/dist/frontend/npm-static-prune.js +5 -4
  619. package/dist/frontend/npm-static-prune.js.map +1 -1
  620. package/dist/frontend/npm-static-prune.test.js +1 -1
  621. package/dist/frontend/npm-static-prune.test.js.map +1 -1
  622. package/dist/frontend/npm-static-rewrite-host.d.ts +4 -0
  623. package/dist/frontend/npm-static-rewrite-host.js +179 -0
  624. package/dist/frontend/npm-static-rewrite-host.js.map +1 -0
  625. package/dist/frontend/npm-static-rewrite-syntax.d.ts +16 -0
  626. package/dist/frontend/npm-static-rewrite-syntax.js +905 -0
  627. package/dist/frontend/npm-static-rewrite-syntax.js.map +1 -0
  628. package/dist/frontend/npm-static-rewrite.d.ts +0 -5
  629. package/dist/frontend/npm-static-rewrite.js +2 -1079
  630. package/dist/frontend/npm-static-rewrite.js.map +1 -1
  631. package/dist/frontend/npm-static-subtyping.d.ts +5 -0
  632. package/dist/frontend/npm-static-subtyping.js +55 -0
  633. package/dist/frontend/npm-static-subtyping.js.map +1 -0
  634. package/dist/frontend/npm-static-subtyping.test.d.ts +1 -0
  635. package/dist/frontend/npm-static-subtyping.test.js +58 -0
  636. package/dist/frontend/npm-static-subtyping.test.js.map +1 -0
  637. package/dist/frontend/npm-static.d.ts +7 -15
  638. package/dist/frontend/npm-static.js +19 -28
  639. package/dist/frontend/npm-static.js.map +1 -1
  640. package/dist/frontend/npm.d.ts +8 -69
  641. package/dist/frontend/npm.js +21 -361
  642. package/dist/frontend/npm.js.map +1 -1
  643. package/dist/frontend/npm.test.js +2 -2
  644. package/dist/frontend/npm.test.js.map +1 -1
  645. package/dist/frontend/pipeline-native.d.ts +6 -0
  646. package/dist/frontend/pipeline-native.js +32 -0
  647. package/dist/frontend/pipeline-native.js.map +1 -0
  648. package/dist/frontend/pipeline.d.ts +54 -0
  649. package/dist/frontend/pipeline.js +382 -0
  650. package/dist/frontend/pipeline.js.map +1 -0
  651. package/dist/frontend/pipeline.test.d.ts +1 -0
  652. package/dist/frontend/pipeline.test.js +77 -0
  653. package/dist/frontend/pipeline.test.js.map +1 -0
  654. package/dist/frontend/program-analysis.d.ts +10 -0
  655. package/dist/frontend/program-analysis.js +14 -0
  656. package/dist/frontend/program-analysis.js.map +1 -0
  657. package/dist/frontend/program-node.d.ts +9 -0
  658. package/dist/frontend/program-node.js +48 -0
  659. package/dist/frontend/program-node.js.map +1 -0
  660. package/dist/frontend/program.d.ts +43 -19
  661. package/dist/frontend/program.js +556 -197
  662. package/dist/frontend/program.js.map +1 -1
  663. package/dist/frontend/program.test.d.ts +1 -0
  664. package/dist/frontend/program.test.js +202 -0
  665. package/dist/frontend/program.test.js.map +1 -0
  666. package/dist/frontend/provenance-core.d.ts +9 -0
  667. package/dist/frontend/provenance-core.js +435 -0
  668. package/dist/frontend/provenance-core.js.map +1 -0
  669. package/dist/frontend/provenance.d.ts +0 -4
  670. package/dist/frontend/provenance.js +4 -459
  671. package/dist/frontend/provenance.js.map +1 -1
  672. package/dist/frontend/resolve.d.ts +3 -1
  673. package/dist/frontend/resolve.js +6 -3
  674. package/dist/frontend/resolve.js.map +1 -1
  675. package/dist/frontend/runtime-resolve.d.ts +4 -3
  676. package/dist/frontend/runtime-resolve.js +22 -18
  677. package/dist/frontend/runtime-resolve.js.map +1 -1
  678. package/dist/frontend/runtime-resolve.test.js +53 -0
  679. package/dist/frontend/runtime-resolve.test.js.map +1 -1
  680. package/dist/frontend/services-node.d.ts +5 -0
  681. package/dist/frontend/services-node.js +19 -0
  682. package/dist/frontend/services-node.js.map +1 -0
  683. package/dist/frontend/services-node.test.d.ts +1 -0
  684. package/dist/frontend/services-node.test.js +70 -0
  685. package/dist/frontend/services-node.test.js.map +1 -0
  686. package/dist/frontend/services.d.ts +44 -0
  687. package/dist/frontend/services.js +90 -0
  688. package/dist/frontend/services.js.map +1 -0
  689. package/dist/frontend/services.test.d.ts +1 -0
  690. package/dist/frontend/services.test.js +174 -0
  691. package/dist/frontend/services.test.js.map +1 -0
  692. package/dist/frontend/ts7/adapter.d.ts +3 -3
  693. package/dist/frontend/ts7/adapter.js +14 -31
  694. package/dist/frontend/ts7/adapter.js.map +1 -1
  695. package/dist/frontend/ts7/api.d.ts +16 -0
  696. package/dist/frontend/ts7/api.js +24 -0
  697. package/dist/frontend/ts7/api.js.map +1 -0
  698. package/dist/frontend/ts7/ast-bytes.d.ts +31 -0
  699. package/dist/frontend/ts7/ast-bytes.js +137 -0
  700. package/dist/frontend/ts7/ast-bytes.js.map +1 -0
  701. package/dist/frontend/ts7/ast-bytes.test.d.ts +1 -0
  702. package/dist/frontend/ts7/ast-bytes.test.js +73 -0
  703. package/dist/frontend/ts7/ast-bytes.test.js.map +1 -0
  704. package/dist/frontend/ts7/ast-guards.generated.d.ts +353 -0
  705. package/dist/frontend/ts7/ast-guards.generated.js +1951 -0
  706. package/dist/frontend/ts7/ast-guards.generated.js.map +1 -0
  707. package/dist/frontend/ts7/ast-guards.test.d.ts +1 -0
  708. package/dist/frontend/ts7/ast-guards.test.js +43 -0
  709. package/dist/frontend/ts7/ast-guards.test.js.map +1 -0
  710. package/dist/frontend/ts7/ast-node.d.ts +194 -0
  711. package/dist/frontend/ts7/ast-node.js +448 -0
  712. package/dist/frontend/ts7/ast-node.js.map +1 -0
  713. package/dist/frontend/ts7/ast-node.test.d.ts +1 -0
  714. package/dist/frontend/ts7/ast-node.test.js +266 -0
  715. package/dist/frontend/ts7/ast-node.test.js.map +1 -0
  716. package/dist/frontend/ts7/ast-schema.generated.d.ts +503 -0
  717. package/dist/frontend/ts7/ast-schema.generated.js +1446 -0
  718. package/dist/frontend/ts7/ast-schema.generated.js.map +1 -0
  719. package/dist/frontend/ts7/ast-text.d.ts +6 -0
  720. package/dist/frontend/ts7/ast-text.js +124 -0
  721. package/dist/frontend/ts7/ast-text.js.map +1 -0
  722. package/dist/frontend/ts7/ast-text.test.d.ts +1 -0
  723. package/dist/frontend/ts7/ast-text.test.js +38 -0
  724. package/dist/frontend/ts7/ast-text.test.js.map +1 -0
  725. package/dist/frontend/ts7/ast-tokens.generated.d.ts +2 -0
  726. package/dist/frontend/ts7/ast-tokens.generated.js +155 -0
  727. package/dist/frontend/ts7/ast-tokens.generated.js.map +1 -0
  728. package/dist/frontend/ts7/ast-types.d.ts +42 -0
  729. package/dist/frontend/ts7/ast-types.generated.d.ts +1615 -0
  730. package/dist/frontend/ts7/ast-types.generated.js +5 -0
  731. package/dist/frontend/ts7/ast-types.generated.js.map +1 -0
  732. package/dist/frontend/ts7/ast-types.js +3 -0
  733. package/dist/frontend/ts7/ast-types.js.map +1 -0
  734. package/dist/frontend/ts7/ast-wire.d.ts +58 -0
  735. package/dist/frontend/ts7/ast-wire.js +267 -0
  736. package/dist/frontend/ts7/ast-wire.js.map +1 -0
  737. package/dist/frontend/ts7/ast-wire.test.d.ts +1 -0
  738. package/dist/frontend/ts7/ast-wire.test.js +151 -0
  739. package/dist/frontend/ts7/ast-wire.test.js.map +1 -0
  740. package/dist/frontend/ts7/ast.d.ts +14 -14
  741. package/dist/frontend/ts7/ast.js +21 -15
  742. package/dist/frontend/ts7/ast.js.map +1 -1
  743. package/dist/frontend/ts7/census-check.js +1 -0
  744. package/dist/frontend/ts7/census-check.js.map +1 -1
  745. package/dist/frontend/ts7/checker-cache.d.ts +48 -0
  746. package/dist/frontend/ts7/checker-cache.js +92 -0
  747. package/dist/frontend/ts7/checker-cache.js.map +1 -0
  748. package/dist/frontend/ts7/checker.d.ts +19 -46
  749. package/dist/frontend/ts7/checker.js +231 -161
  750. package/dist/frontend/ts7/checker.js.map +1 -1
  751. package/dist/frontend/ts7/checker.test.d.ts +1 -0
  752. package/dist/frontend/ts7/checker.test.js +335 -0
  753. package/dist/frontend/ts7/checker.test.js.map +1 -0
  754. package/dist/frontend/ts7/enums.d.ts +4 -27
  755. package/dist/frontend/ts7/enums.generated.d.ts +878 -0
  756. package/dist/frontend/ts7/enums.generated.js +1313 -0
  757. package/dist/frontend/ts7/enums.generated.js.map +1 -0
  758. package/dist/frontend/ts7/enums.js +4 -45
  759. package/dist/frontend/ts7/enums.js.map +1 -1
  760. package/dist/frontend/ts7/enums.test.d.ts +1 -0
  761. package/dist/frontend/ts7/enums.test.js +48 -0
  762. package/dist/frontend/ts7/enums.test.js.map +1 -0
  763. package/dist/frontend/ts7/native-api.d.ts +10 -0
  764. package/dist/frontend/ts7/native-api.js +10 -0
  765. package/dist/frontend/ts7/native-api.js.map +1 -0
  766. package/dist/frontend/ts7/native-host.d.ts +2 -0
  767. package/dist/frontend/ts7/native-host.js +11 -0
  768. package/dist/frontend/ts7/native-host.js.map +1 -0
  769. package/dist/frontend/ts7/native-process.d.ts +14 -0
  770. package/dist/frontend/ts7/native-process.js +62 -0
  771. package/dist/frontend/ts7/native-process.js.map +1 -0
  772. package/dist/frontend/ts7/program-adapter.d.ts +10 -98
  773. package/dist/frontend/ts7/program-adapter.js +16 -310
  774. package/dist/frontend/ts7/program-adapter.js.map +1 -1
  775. package/dist/frontend/ts7/program-host.d.ts +115 -0
  776. package/dist/frontend/ts7/program-host.js +347 -0
  777. package/dist/frontend/ts7/program-host.js.map +1 -0
  778. package/dist/frontend/ts7/program-host.test.d.ts +1 -0
  779. package/dist/frontend/ts7/program-host.test.js +207 -0
  780. package/dist/frontend/ts7/program-host.test.js.map +1 -0
  781. package/dist/frontend/ts7/rpc-api.d.ts +12 -0
  782. package/dist/frontend/ts7/rpc-api.js +23 -0
  783. package/dist/frontend/ts7/rpc-api.js.map +1 -0
  784. package/dist/frontend/ts7/rpc-client.d.ts +27 -0
  785. package/dist/frontend/ts7/rpc-client.js +102 -0
  786. package/dist/frontend/ts7/rpc-client.js.map +1 -0
  787. package/dist/frontend/ts7/rpc-client.test.d.ts +1 -0
  788. package/dist/frontend/ts7/rpc-client.test.js +133 -0
  789. package/dist/frontend/ts7/rpc-client.test.js.map +1 -0
  790. package/dist/frontend/ts7/rpc-filesystem.d.ts +16 -0
  791. package/dist/frontend/ts7/rpc-filesystem.js +42 -0
  792. package/dist/frontend/ts7/rpc-filesystem.js.map +1 -0
  793. package/dist/frontend/ts7/rpc-filesystem.test.d.ts +1 -0
  794. package/dist/frontend/ts7/rpc-filesystem.test.js +89 -0
  795. package/dist/frontend/ts7/rpc-filesystem.test.js.map +1 -0
  796. package/dist/frontend/ts7/rpc-process.d.ts +2 -0
  797. package/dist/frontend/ts7/rpc-process.js +148 -0
  798. package/dist/frontend/ts7/rpc-process.js.map +1 -0
  799. package/dist/frontend/ts7/rpc-process.test.d.ts +1 -0
  800. package/dist/frontend/ts7/rpc-process.test.js +29 -0
  801. package/dist/frontend/ts7/rpc-process.test.js.map +1 -0
  802. package/dist/frontend/ts7/rpc-wire.d.ts +46 -0
  803. package/dist/frontend/ts7/rpc-wire.js +195 -0
  804. package/dist/frontend/ts7/rpc-wire.js.map +1 -0
  805. package/dist/frontend/ts7/rpc-wire.test.d.ts +1 -0
  806. package/dist/frontend/ts7/rpc-wire.test.js +168 -0
  807. package/dist/frontend/ts7/rpc-wire.test.js.map +1 -0
  808. package/dist/frontend/ts7/semantic-checker.d.ts +137 -0
  809. package/dist/frontend/ts7/semantic-checker.js +221 -0
  810. package/dist/frontend/ts7/semantic-checker.js.map +1 -0
  811. package/dist/frontend/ts7/semantic-checker.test.d.ts +1 -0
  812. package/dist/frontend/ts7/semantic-checker.test.js +119 -0
  813. package/dist/frontend/ts7/semantic-checker.test.js.map +1 -0
  814. package/dist/frontend/ts7/semantic-json.d.ts +5 -0
  815. package/dist/frontend/ts7/semantic-json.js +52 -0
  816. package/dist/frontend/ts7/semantic-json.js.map +1 -0
  817. package/dist/frontend/ts7/semantic-json.test.d.ts +1 -0
  818. package/dist/frontend/ts7/semantic-json.test.js +42 -0
  819. package/dist/frontend/ts7/semantic-json.test.js.map +1 -0
  820. package/dist/frontend/ts7/semantic-model.d.ts +222 -0
  821. package/dist/frontend/ts7/semantic-model.js +423 -0
  822. package/dist/frontend/ts7/semantic-model.js.map +1 -0
  823. package/dist/frontend/ts7/semantic-model.test.d.ts +1 -0
  824. package/dist/frontend/ts7/semantic-model.test.js +322 -0
  825. package/dist/frontend/ts7/semantic-model.test.js.map +1 -0
  826. package/dist/frontend/ts7/semantic-schema.generated.d.ts +283 -0
  827. package/dist/frontend/ts7/semantic-schema.generated.js +222 -0
  828. package/dist/frontend/ts7/semantic-schema.generated.js.map +1 -0
  829. package/dist/frontend/ts7/semantic-types.d.ts +5 -0
  830. package/dist/frontend/ts7/semantic-types.js +2 -0
  831. package/dist/frontend/ts7/semantic-types.js.map +1 -0
  832. package/dist/frontend/ts7/session-cache.d.ts +17 -0
  833. package/dist/frontend/ts7/session-cache.js +97 -0
  834. package/dist/frontend/ts7/session-cache.js.map +1 -0
  835. package/dist/frontend/ts7/session-cache.test.d.ts +1 -0
  836. package/dist/frontend/ts7/session-cache.test.js +87 -0
  837. package/dist/frontend/ts7/session-cache.test.js.map +1 -0
  838. package/dist/frontend/ts7/session-path.d.ts +18 -0
  839. package/dist/frontend/ts7/session-path.js +203 -0
  840. package/dist/frontend/ts7/session-path.js.map +1 -0
  841. package/dist/frontend/ts7/session-path.test.d.ts +1 -0
  842. package/dist/frontend/ts7/session-path.test.js +34 -0
  843. package/dist/frontend/ts7/session-path.test.js.map +1 -0
  844. package/dist/frontend/ts7/session-schema.generated.d.ts +167 -0
  845. package/dist/frontend/ts7/session-schema.generated.js +5 -0
  846. package/dist/frontend/ts7/session-schema.generated.js.map +1 -0
  847. package/dist/frontend/ts7/session-timing.d.ts +50 -0
  848. package/dist/frontend/ts7/session-timing.js +61 -0
  849. package/dist/frontend/ts7/session-timing.js.map +1 -0
  850. package/dist/frontend/ts7/session-timing.test.d.ts +1 -0
  851. package/dist/frontend/ts7/session-timing.test.js +52 -0
  852. package/dist/frontend/ts7/session-timing.test.js.map +1 -0
  853. package/dist/frontend/ts7/session.d.ts +105 -0
  854. package/dist/frontend/ts7/session.js +233 -0
  855. package/dist/frontend/ts7/session.js.map +1 -0
  856. package/dist/frontend/ts7/session.test.d.ts +1 -0
  857. package/dist/frontend/ts7/session.test.js +215 -0
  858. package/dist/frontend/ts7/session.test.js.map +1 -0
  859. package/dist/frontend/ts7/source-parser-node.d.ts +6 -0
  860. package/dist/frontend/ts7/source-parser-node.js +15 -0
  861. package/dist/frontend/ts7/source-parser-node.js.map +1 -0
  862. package/dist/frontend/ts7/source-parser.d.ts +25 -0
  863. package/dist/frontend/ts7/source-parser.js +96 -0
  864. package/dist/frontend/ts7/source-parser.js.map +1 -0
  865. package/dist/frontend/ts7/source-parser.test.d.ts +1 -0
  866. package/dist/frontend/ts7/source-parser.test.js +151 -0
  867. package/dist/frontend/ts7/source-parser.test.js.map +1 -0
  868. package/dist/frontend/ts7/syntax.d.ts +3 -0
  869. package/dist/frontend/ts7/syntax.js +4 -0
  870. package/dist/frontend/ts7/syntax.js.map +1 -0
  871. package/dist/frontend/tsc-codes.js +3 -0
  872. package/dist/frontend/tsc-codes.js.map +1 -1
  873. package/dist/frontend/type-mapper.d.ts +29 -19
  874. package/dist/frontend/type-mapper.js +713 -306
  875. package/dist/frontend/type-mapper.js.map +1 -1
  876. package/dist/frontend/type-mapper.test.d.ts +1 -0
  877. package/dist/frontend/type-mapper.test.js +207 -0
  878. package/dist/frontend/type-mapper.test.js.map +1 -0
  879. package/dist/frontend/union-discriminants.d.ts +16 -0
  880. package/dist/frontend/union-discriminants.js +98 -0
  881. package/dist/frontend/union-discriminants.js.map +1 -0
  882. package/dist/frontend/union-discriminants.test.d.ts +1 -0
  883. package/dist/frontend/union-discriminants.test.js +182 -0
  884. package/dist/frontend/union-discriminants.test.js.map +1 -0
  885. package/dist/index.d.ts +7 -197
  886. package/dist/index.js +369 -1567
  887. package/dist/index.js.map +1 -1
  888. package/dist/ir/analysis.d.ts +16 -4
  889. package/dist/ir/analysis.js +25 -6
  890. package/dist/ir/analysis.js.map +1 -1
  891. package/dist/ir/analysis.test.js +15 -2
  892. package/dist/ir/analysis.test.js.map +1 -1
  893. package/dist/ir/constant-tables.js +67 -49
  894. package/dist/ir/constant-tables.js.map +1 -1
  895. package/dist/ir/constant-tables.test.js +1 -1
  896. package/dist/ir/control-flow.d.ts +6 -0
  897. package/dist/ir/control-flow.js +142 -0
  898. package/dist/ir/control-flow.js.map +1 -0
  899. package/dist/ir/control-flow.test.d.ts +1 -0
  900. package/dist/ir/control-flow.test.js +113 -0
  901. package/dist/ir/control-flow.test.js.map +1 -0
  902. package/dist/ir/integer-loops.js +7 -18
  903. package/dist/ir/integer-loops.js.map +1 -1
  904. package/dist/ir/integer-ranges.js +53 -27
  905. package/dist/ir/integer-ranges.js.map +1 -1
  906. package/dist/ir/ir.d.ts +309 -164
  907. package/dist/ir/ir.js +588 -879
  908. package/dist/ir/ir.js.map +1 -1
  909. package/dist/ir/ir.test.js +127 -1
  910. package/dist/ir/ir.test.js.map +1 -1
  911. package/dist/ir/scalar-records.js +165 -134
  912. package/dist/ir/scalar-records.js.map +1 -1
  913. package/dist/ir/scalar-records.test.js +1 -1
  914. package/dist/ir/serialize.d.ts +4 -2
  915. package/dist/ir/serialize.js +19 -12
  916. package/dist/ir/serialize.js.map +1 -1
  917. package/dist/ir/serialize.test.d.ts +1 -0
  918. package/dist/ir/serialize.test.js +53 -0
  919. package/dist/ir/serialize.test.js.map +1 -0
  920. package/dist/ir/traverse.d.ts +41 -0
  921. package/dist/ir/traverse.js +660 -0
  922. package/dist/ir/traverse.js.map +1 -0
  923. package/dist/ir/traverse.test.d.ts +1 -0
  924. package/dist/ir/traverse.test.js +242 -0
  925. package/dist/ir/traverse.test.js.map +1 -0
  926. package/dist/ir/validate.js +1956 -1496
  927. package/dist/ir/validate.js.map +1 -1
  928. package/dist/ir/validate.test.js +476 -2
  929. package/dist/ir/validate.test.js.map +1 -1
  930. package/dist/library/cache-primitives.d.ts +2 -3
  931. package/dist/library/cache-primitives.js +4 -6
  932. package/dist/library/cache-primitives.js.map +1 -1
  933. package/dist/library/compiler-self-identity.d.ts +1 -1
  934. package/dist/library/compiler-self-identity.js +31 -15
  935. package/dist/library/compiler-self-identity.js.map +1 -1
  936. package/dist/library/compiler-self-identity.test.d.ts +1 -0
  937. package/dist/library/compiler-self-identity.test.js +93 -0
  938. package/dist/library/compiler-self-identity.test.js.map +1 -0
  939. package/dist/library/fence-eval.js +2 -2
  940. package/dist/library/fence-eval.js.map +1 -1
  941. package/dist/library/int-infer.js +7 -6
  942. package/dist/library/int-infer.js.map +1 -1
  943. package/dist/library/int-infer.test.js +4 -4
  944. package/dist/library/library-cache.d.ts +3 -2
  945. package/dist/library/library-cache.js +5 -17
  946. package/dist/library/library-cache.js.map +1 -1
  947. package/dist/library/library-cache.test.js +54 -41
  948. package/dist/library/library-cache.test.js.map +1 -1
  949. package/dist/library/library-profile.d.ts +3 -1
  950. package/dist/library/library-profile.js +15 -6
  951. package/dist/library/library-profile.js.map +1 -1
  952. package/dist/library/prepare.d.ts +15 -0
  953. package/dist/library/prepare.js +584 -0
  954. package/dist/library/prepare.js.map +1 -0
  955. package/dist/library/semantic-source.d.ts +1 -1
  956. package/dist/library/semantic-source.js +8 -6
  957. package/dist/library/semantic-source.js.map +1 -1
  958. package/dist/library/sidecar-validate.js +4 -4
  959. package/dist/library/sidecar-validate.js.map +1 -1
  960. package/dist/library/sidecar.d.ts +2 -0
  961. package/dist/library/sidecar.js +10 -3
  962. package/dist/library/sidecar.js.map +1 -1
  963. package/dist/native/cache.d.ts +11 -0
  964. package/dist/native/cache.js +113 -0
  965. package/dist/native/cache.js.map +1 -0
  966. package/dist/native/cache.test.d.ts +1 -0
  967. package/dist/native/cache.test.js +66 -0
  968. package/dist/native/cache.test.js.map +1 -0
  969. package/dist/native/cli.d.ts +1 -0
  970. package/dist/native/cli.js +112 -0
  971. package/dist/native/cli.js.map +1 -0
  972. package/dist/native/compiler.d.ts +15 -0
  973. package/dist/native/compiler.js +336 -0
  974. package/dist/native/compiler.js.map +1 -0
  975. package/dist/native/compiler.test.d.ts +1 -0
  976. package/dist/native/compiler.test.js +174 -0
  977. package/dist/native/compiler.test.js.map +1 -0
  978. package/dist/native/comptime.d.ts +5 -0
  979. package/dist/native/comptime.js +73 -0
  980. package/dist/native/comptime.js.map +1 -0
  981. package/dist/native/comptime.test.d.ts +1 -0
  982. package/dist/native/comptime.test.js +65 -0
  983. package/dist/native/comptime.test.js.map +1 -0
  984. package/dist/native/executable-cache.d.ts +26 -0
  985. package/dist/native/executable-cache.js +228 -0
  986. package/dist/native/executable-cache.js.map +1 -0
  987. package/dist/native/executable-cache.test.d.ts +1 -0
  988. package/dist/native/executable-cache.test.js +151 -0
  989. package/dist/native/executable-cache.test.js.map +1 -0
  990. package/dist/native/file-identity.d.ts +4 -0
  991. package/dist/native/file-identity.js +14 -0
  992. package/dist/native/file-identity.js.map +1 -0
  993. package/dist/native/file-identity.test.d.ts +1 -0
  994. package/dist/native/file-identity.test.js +43 -0
  995. package/dist/native/file-identity.test.js.map +1 -0
  996. package/dist/native/library.d.ts +22 -0
  997. package/dist/native/library.js +83 -0
  998. package/dist/native/library.js.map +1 -0
  999. package/dist/native/prepare.d.ts +21 -0
  1000. package/dist/native/prepare.js +174 -0
  1001. package/dist/native/prepare.js.map +1 -0
  1002. package/dist/native/prepare.test.d.ts +1 -0
  1003. package/dist/native/prepare.test.js +70 -0
  1004. package/dist/native/prepare.test.js.map +1 -0
  1005. package/dist/native/sanitizer.d.ts +11 -0
  1006. package/dist/native/sanitizer.js +135 -0
  1007. package/dist/native/sanitizer.js.map +1 -0
  1008. package/dist/native/sanitizer.test.d.ts +1 -0
  1009. package/dist/native/sanitizer.test.js +58 -0
  1010. package/dist/native/sanitizer.test.js.map +1 -0
  1011. package/dist/native/task.d.ts +4 -0
  1012. package/dist/native/task.js +16 -0
  1013. package/dist/native/task.js.map +1 -0
  1014. package/dist/native/task.test.d.ts +1 -0
  1015. package/dist/native/task.test.js +17 -0
  1016. package/dist/native/task.test.js.map +1 -0
  1017. package/dist/native/toolchain.d.ts +45 -0
  1018. package/dist/native/toolchain.js +74 -0
  1019. package/dist/native/toolchain.js.map +1 -0
  1020. package/dist/native/toolchain.test.d.ts +1 -0
  1021. package/dist/native/toolchain.test.js +33 -0
  1022. package/dist/native/toolchain.test.js.map +1 -0
  1023. package/dist/startup-cache.d.ts +1 -1
  1024. package/dist/startup-cache.js +2 -5
  1025. package/dist/startup-cache.js.map +1 -1
  1026. package/dist/timing.d.ts +4 -0
  1027. package/dist/timing.js +19 -0
  1028. package/dist/timing.js.map +1 -0
  1029. package/dist/wasi-paths.js +10 -7
  1030. package/dist/wasi-paths.js.map +1 -1
  1031. package/package.json +28 -19
  1032. package/surface-manifest.json +171 -18
  1033. package/dist/backend/c/async.d.ts +0 -171
  1034. package/dist/backend/c/async.js +0 -1317
  1035. package/dist/backend/c/async.js.map +0 -1
  1036. package/dist/backend/c/c-emitter.d.ts +0 -531
  1037. package/dist/backend/c/c-emitter.js +0 -1917
  1038. package/dist/backend/c/c-emitter.js.map +0 -1
  1039. package/dist/backend/c/exprs.d.ts +0 -15
  1040. package/dist/backend/c/exprs.js +0 -8803
  1041. package/dist/backend/c/exprs.js.map +0 -1
  1042. package/dist/backend/c/island.d.ts +0 -45
  1043. package/dist/backend/c/island.js +0 -281
  1044. package/dist/backend/c/island.js.map +0 -1
  1045. package/dist/backend/c/may-throw.js.map +0 -1
  1046. package/dist/backend/c/shapes.d.ts +0 -142
  1047. package/dist/backend/c/shapes.js +0 -603
  1048. package/dist/backend/c/shapes.js.map +0 -1
  1049. package/dist/backend/c/stmts.d.ts +0 -76
  1050. package/dist/backend/c/stmts.js +0 -1084
  1051. package/dist/backend/c/stmts.js.map +0 -1
  1052. package/dist/backend/c/types.d.ts +0 -71
  1053. package/dist/backend/c/types.js +0 -459
  1054. package/dist/backend/c/types.js.map +0 -1
  1055. package/dist/backend/c/types.test.js +0 -32
  1056. package/dist/backend/c/types.test.js.map +0 -1
  1057. package/dist/backend/c/walkers.d.ts +0 -134
  1058. package/dist/backend/c/walkers.js +0 -1773
  1059. package/dist/backend/c/walkers.js.map +0 -1
  1060. /package/dist/backend/{c/types.test.d.ts → cycle-analysis.test.d.ts} +0 -0
@@ -1,27 +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";
9
+ import { bodyReadsArguments } from "../arguments-usage.js";
7
10
  import { lowerGenMethodCall } from "./lower-generators.js";
8
- 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";
9
- import { isJsSourceFile, isNodeEsmFile, locOf } from "../program.js";
10
- 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";
11
17
  import { PoisonError, dynFallbackType, dynUndefinedExpr, importCallHandleType, jsFuncNameOf, newFnCtx, nodeThrowExpr, staticImportNamespaceType } from "./lowerer.js";
12
18
  import { enforceLibBoundary } from "./lib-boundary.js";
13
19
  import { NARROW_FIRST, STRING_INDEX_METHODS, STR_METHODS, builtinFenceHintOf, builtinModuleFnOf } from "./surfaces.js";
14
20
  import { ffiBindingDiag, ffiSignatureDiag, libCallbackDiag, requiresDynamicDiag } from "../../diagnostics/diagnostic.js";
15
21
  import { mixinFnShapeOf } from "./lower-mixins.js";
16
22
  import { dynStringReceiver, lowerArrayConstructor, lowerArrayFromCall, lowerArrayOfCall, lowerDynArrayFilterCall, lowerDynArrayFlatMapCall, lowerGroupByStaticCall, lowerIteratorHelperCall, lowerObjectAssignIndexShape, lowerObjectFromEntriesCall, lowerObjectIterOverIndexShape, lowerTupleReadMethodCall } from "./lower-containers.js";
17
- import { bufEncoding } from "./containers/bytes.js";
23
+ import { lowerBytesStaticCall } from "./containers/bytes.js";
18
24
  import { lowerRegexMethodCall, lowerStringIndexCall, lowerStringMethodCall, lowerStringPaddingCall, lowerStringSplitCall } from "./containers/string-and-regexp.js";
19
- 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";
20
26
  import { lowerAbsenceProbe, lowerPromiseAllTupleCall, lowerPromiseRejectCall, stringWrapperToString, templateRawTextOf } from "./lower-exprs.js";
21
27
  import { isSafeToDiscard } from "./expressions/evaluation-safety.js";
22
28
  import { tryLowerExpression } from "./expressions/try-lower-expression.js";
23
29
  import { httpClientFnBindingOf, isStreamUndefCallExpr, lowerCompatReqStreamOptionalCall, lowerHttpClientFnCall } from "./lower-server.js";
24
- 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";
25
32
  import { emitterRooted, lowerEmitterMethodCall } from "./lower-event-emitter.js";
26
33
  import { lowerConsoleInspectArg, lowerFormatCall } from "./lower-inspect.js";
27
34
  import { STREAM_API_MEMBERS, lowerStreamMethodCall, lowerStreamModuleCall, lowerStreamStaticCall, streamSidesOf } from "./lower-stream.js";
@@ -29,10 +36,14 @@ import { ambientNsRootOf, ambientUndefReadType, ambientUndefVarRootOf, ambientUn
29
36
  import { declSymbolOf } from "./lower-modules.js";
30
37
  import { expandoMemberRead } from "./lower-expando.js";
31
38
  import { npmStaticPackageOfPath } from "../npm-static.js";
32
- import { countedFor, varRef } from "../../ir/build.js";
39
+ import { countedFor, numLit, varRef } from "../../ir/build.js";
33
40
  import { rejectStaticThis } from "./static-this.js";
34
41
  import { fenceNodeModuleMutationCall, lowerRequireCacheKeys } from "./lower-node-module.js";
35
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";
46
+ export { bodyReadsArguments };
36
47
  /** The one func-type projection of completed parameter shapes. Typed rest
37
48
  * parameters keep their packed array as the trailing native ABI slot and
38
49
  * mark the value variadic so indirect call sites run completeArgs before
@@ -49,11 +60,7 @@ export function funcTypeFromParamShapes(shapes, ret) {
49
60
  ret,
50
61
  ...(typedRest || dynRest || islandRest || argumentsAll ? { rest: true } : {}),
51
62
  ...(argumentsAll ? { argumentsAll: true } : {}),
52
- ...(typedRest
53
- ? { restAbi: "typed" }
54
- : islandRest
55
- ? { restAbi: "jsval" }
56
- : {}),
63
+ ...(typedRest || islandRest ? { restAbi: typedRest ? "typed" : "jsval" } : {}),
57
64
  };
58
65
  }
59
66
  /** Registers `const alias = overloadedDeclaration` as a compile-time
@@ -116,6 +123,11 @@ export const MAX_GENERIC_INSTANCES = 100;
116
123
  * - `...xs: T[]`: the ABI type is the array; call sites pack the surplus.
117
124
  */
118
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
+ }
119
131
  const moduleNs = lowerer.moduleNsParamOverrides.get(param);
120
132
  if (moduleNs !== undefined) {
121
133
  return { type: moduleNs, mode: param.questionToken ? "omittable" : "required" };
@@ -157,21 +169,7 @@ export function paramShape(lowerer, param) {
157
169
  // default when the argument was omitted or undefined, then the
158
170
  // pattern destructures the picked value (declareParams).
159
171
  const raw = lowerer.irTypeOf(param.name);
160
- // A DYNAMIC-TIER pattern source (`function f({} = a)` with
161
- // `a: any` — jsval for island values, dyn for the checked-dynamic
162
- // dyn): the slot holds its tier's undefined DIRECTLY, so the ABI
163
- // is the slot itself — no synthesized union; the prologue tests
164
- // undefined at runtime (declareParams).
165
- if (raw.kind === "dyn" || raw.kind === "jsval") {
166
- return { type: raw, mode: "omittable", bodyType: raw };
167
- }
168
- const bodyType = lowerer.stripUndefinedArm(raw);
169
- lowerer.checkDefaultParamBodyType(param, bodyType);
170
- const abi = bodyType.kind === "union" ? lowerer.withUndefinedArmOf(bodyType) : lowerer.withUndefinedArm(bodyType);
171
- if (!abi) {
172
- lowerer.badType(param.name, lowerer.typeOf(param.name)); // defensive: unknown union id
173
- }
174
- return { type: abi, mode: "omittable", bodyType };
172
+ return defaultParameterShape(lowerer, param, raw);
175
173
  }
176
174
  return { type: lowerer.runtimeOptionalBindingType(param.name, lowerer.irTypeOf(param.name)), mode: "required" };
177
175
  }
@@ -205,41 +203,12 @@ export function paramShape(lowerer, param) {
205
203
  }
206
204
  if (param.initializer) {
207
205
  const raw = lowerer.irTypeOf(param.name);
208
- // A DYNAMIC-TIER defaulted param (`function f(x = a)` with `a: any`
209
- // — tsc types x any; jsval for island values, dyn for the checked-
210
- // dynamic dyn): the slot holds its tier's undefined directly, so
211
- // the ABI is the slot itself and the prologue's default test is the
212
- // runtime undefined test (declareParams).
213
- if (raw.kind === "dyn" || raw.kind === "jsval") {
214
- return { type: raw, mode: "omittable", bodyType: raw };
215
- }
216
- // A default that may ITSELF be undefined (`x = process.env.FOO`):
217
- // tsc keeps undefined in the body's type, so there is nothing to
218
- // narrow — the ABI union IS the body type and the prologue passes a
219
- // present argument through unchanged (declareParams's pass-through
220
- // branch). The generic strip-and-narrow below would demand a
221
- // `string`-typed default and fence on the union re-tag.
222
- if (lowerer.bareUndefinedArmedUnion(raw)) {
223
- const initT = lowerer.mapTypeOf(lowerer.typeOf(param.initializer));
224
- if (initT && (initT.kind === "undefinedT" || lowerer.bareUndefinedArmedUnion(initT))) {
225
- return { type: raw, mode: "omittable", bodyType: raw };
226
- }
227
- }
228
- const bodyType = lowerer.stripUndefinedArm(raw);
229
- lowerer.checkDefaultParamBodyType(param, bodyType);
230
- // A UNION body type (`tlds: string | string[] = "localhost"`) arms
231
- // the ABI with undefined ON TOP of the body's arms; the prologue
232
- // re-tags a present argument back into the body union (undefined
233
- // sorts last among arm typeKeys in practice, so the mapping is
234
- // usually the identity prefix — the interned retag helper handles
235
- // any order).
236
- const abi = bodyType.kind === "union" ? lowerer.withUndefinedArmOf(bodyType) : lowerer.withUndefinedArm(bodyType);
237
- if (!abi) {
238
- lowerer.badType(param.name, lowerer.typeOf(param.name)); // defensive: unknown union id
239
- }
240
- return { type: abi, mode: "omittable", bodyType };
206
+ return defaultParameterShape(lowerer, param, raw);
241
207
  }
242
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
+ }
243
212
  if (param.questionToken && !lowerer.bareUndefinedArmedUnion(type) && type.kind !== "dyn" && type.kind !== "jsval") {
244
213
  // `x?: unknown` where unknown came from an annotation: undefined is
245
214
  // absorbed into the hole type, so no undefined ARM exists — but a
@@ -267,7 +236,7 @@ export function paramShapes(lowerer, params, signature, blameOf) {
267
236
  return params.map((declParam, i) => {
268
237
  const symbol = signature.getParameters()[i];
269
238
  const tsType = symbol ? lowerer.checker.getTypeOfSymbol(symbol) : lowerer.typeOf(declParam.name);
270
- 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);
271
240
  if (!mapped || mapped.kind === "void")
272
241
  lowerer.badType(blameOf?.(declParam, i) ?? declParam.name, tsType);
273
242
  if (declParam.dotDotDotToken) {
@@ -275,30 +244,46 @@ export function paramShapes(lowerer, params, signature, blameOf) {
275
244
  lowerer.badType(blameOf?.(declParam, i) ?? declParam.name, tsType);
276
245
  return { type: mapped, mode: "rest" };
277
246
  }
278
- if (declParam.initializer) {
279
- if (mapped.kind === "dyn" || mapped.kind === "jsval") {
280
- return { type: mapped, mode: "omittable", bodyType: mapped };
281
- }
282
- const bodyType = lowerer.stripUndefinedArm(mapped);
283
- lowerer.checkDefaultParamBodyType(declParam, bodyType);
284
- return { type: lowerer.withUndefinedArm(bodyType), mode: "omittable", bodyType };
285
- }
247
+ if (declParam.initializer)
248
+ return defaultParameterShape(lowerer, declParam, mapped);
286
249
  if (declParam.questionToken && !lowerer.bareUndefinedArmedUnion(mapped)) {
287
250
  lowerer.unsupported("SC1090", declParam, `optional parameters of type '${lowerer.fmt(mapped)}'`);
288
251
  }
289
252
  return { type: mapped, mode: declParam.questionToken ? "omittable" : "required" };
290
253
  });
291
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
+ }
292
278
  /** The fences on a defaulted parameter's body type: it becomes the value
293
279
  * arm of the synthesized `T | undefined` ABI union, so it must be a valid
294
- * 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
295
281
  * the prologue's own undefined-tag check (never a user narrowing, which
296
- * 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 =
297
283
  * defaultRunner` and `skip: Set<string> = new Set()` arm like any ref
298
284
  * kind — the nullable-callback union shape, built by the compiler. */
299
285
  export function checkDefaultParamBodyType(lowerer, param, bodyType) {
300
286
  if (bodyType.kind === "void" ||
301
- bodyType.kind === "map" ||
302
287
  bodyType.kind === "regex" ||
303
288
  bodyType.kind === "date" ||
304
289
  bodyType.kind === "dyn" ||
@@ -334,7 +319,62 @@ export function completeArgs(lowerer, argNodes, shapes, loc, blame,
334
319
  * coercion an ordinary argument gets (coerceInto against its shape,
335
320
  * DYN conversion in a dyn rest, element coercion in a typed rest). */
336
321
  leading) {
337
- 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);
338
378
  const sources = leading?.map((ir) => ({ ir })) ?? [];
339
379
  for (const arg of argNodes) {
340
380
  if (!ts.isSpreadElement(arg)) {
@@ -397,9 +437,20 @@ leading) {
397
437
  lowerer.unsupported("SC1090", source, "spread arguments into fixed parameter positions (a spread can only fill a rest parameter)");
398
438
  }
399
439
  const slotType = i < restAt ? positional[i].type : DYN;
400
- const value = isIr(source)
401
- ? lowerer.coerceInto(blame, source.ir, slotType)
402
- : 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);
403
454
  const saved = lowerer.declareHiddenLocal("%callArg", slotType);
404
455
  stmts.push({ kind: "varDecl", localId: saved.id, init: value, loc: value.loc });
405
456
  return { kind: "varRef", localId: saved.id, type: slotType, loc: value.loc };
@@ -407,7 +458,7 @@ leading) {
407
458
  const fixed = positional.map((shape, i) => {
408
459
  if (i < passed.length)
409
460
  return passed[i];
410
- if (shape.mode === "omittable")
461
+ if (shape.mode === "omittable" || lowerer.bareUndefinedArmedUnion(shape.type))
411
462
  return shape.callDefault ?? lowerer.undefinedArgFor(shape.type, loc, blame);
412
463
  if (shape.type.kind === "dyn")
413
464
  return { kind: "dynFrom", value: { kind: "unitLit", unit: "undefined", type: UNDEFINED_T, loc }, type: DYN, loc };
@@ -432,9 +483,19 @@ leading) {
432
483
  // completion has no home for that. Spreads fill REST slots only.
433
484
  lowerer.unsupported("SC1090", arg, "spread arguments into fixed parameter positions (a spread can only fill a rest parameter)");
434
485
  }
435
- 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
+ }
436
496
  return lowerer.lowerExprExpecting(arg, shape.type);
437
- if (shape.mode !== "omittable") {
497
+ }
498
+ if (shape.mode !== "omittable" && !lowerer.bareUndefinedArmedUnion(shape.type)) {
438
499
  // A missing argument for a CHECKED-DYNAMIC param (an implicit-any
439
500
  // JS signature called short — `mustCall(fn)` with `expected`
440
501
  // omitted): JS fills undefined, and the dyn slot holds exactly
@@ -688,7 +749,9 @@ export function requireExactArityValue(lowerer, blame, contextual, shapes, funcT
688
749
  // slot): judge by the expression's OWN completed type; the slot's
689
750
  // coercion still enforces (or adapts) the flow it lands in.
690
751
  if (mappedFn?.kind !== "func" && contextual) {
691
- 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);
692
755
  }
693
756
  if (mappedFn && typeEquals(mappedFn, funcType))
694
757
  return;
@@ -808,6 +871,10 @@ export function declaredReturnType(lowerer, decl, blame) {
808
871
  if (!sig)
809
872
  lowerer.unsupported("SC1090", decl, "this function form");
810
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;
811
878
  // A body that always throws infers `never` — as a RETURN type that is
812
879
  // void with a stronger guarantee (`() => never` is assignable to
813
880
  // `() => void`), and throw-only callbacks are ordinary code
@@ -815,10 +882,34 @@ export function declaredReturnType(lowerer, decl, blame) {
815
882
  if (retTsType.flags & ts.TypeFlags.Never)
816
883
  return VOID;
817
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
+ }
818
908
  if (isJsSourceFile(decl.getSourceFile()) &&
819
909
  !hasExplicitJsDocReturn(decl) &&
820
910
  mappedReturn !== null &&
821
911
  promiseCarriesDyn(lowerer, mappedReturn) &&
912
+ !decl.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.AsyncKeyword) &&
822
913
  decl.parameters.some((param) => {
823
914
  const mapped = lowerer.mapTypeOf(lowerer.typeOf(param.name));
824
915
  return mapped === null || mapped.kind === "dyn";
@@ -850,14 +941,19 @@ export function declaredReturnType(lowerer, decl, blame) {
850
941
  // checked-dynamic (or none): a lambda with RECORD-typed parameters
851
942
  // (a reduce reducer over a typed array) legitimately returns its
852
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;
853
948
  if (isJsSourceFile(decl.getSourceFile()) &&
854
949
  decl.type === undefined &&
855
- lowerer.mapTypeOf(retTsType)?.kind === "record" &&
950
+ recordReturn?.kind === "record" &&
951
+ lowerer.dynConvertible(recordReturn) &&
856
952
  decl.parameters.every((p) => {
857
953
  const mt = lowerer.mapTypeOf(lowerer.typeOf(p));
858
954
  return mt === null || mt.kind === "dyn";
859
955
  })) {
860
- return DYN;
956
+ return asyncReturn ? { kind: "promise", inner: DYN } : DYN;
861
957
  }
862
958
  const returnType = lowerer.mapTypeOf(retTsType);
863
959
  if (!returnType) {
@@ -882,7 +978,7 @@ export function declaredReturnType(lowerer, decl, blame) {
882
978
  * other unmappable type (the caller's badType reports those). */
883
979
  function fenceGenericSignatureResult(lowerer, blame, t) {
884
980
  const parts = t.isUnionType() ? ts.constituentTypes(t) : [t];
885
- 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))) {
886
982
  return;
887
983
  }
888
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)`);
@@ -959,7 +1055,7 @@ export function collectSignatureInner(lowerer, decl) {
959
1055
  if (!params.some((sh) => sh.mode === "rest" || sh.mode === "dynRest" || sh.mode === "islandRest") &&
960
1056
  isJsSourceFile(decl.getSourceFile()) &&
961
1057
  bodyReadsArguments(decl)) {
962
- if (decl.parameters.length > 0 && !isNodeEsmFile(decl.getSourceFile())) {
1058
+ if (decl.parameters.length > 0 && !isNodeEsmFile(decl.getSourceFile(), lowerer.program)) {
963
1059
  lowerer.unsupported("SC1090", decl, "parameterized 'arguments' outside an ES module (sloppy-mode parameter aliases)");
964
1060
  }
965
1061
  params.push({ type: DYN, mode: decl.parameters.length > 0 ? "arguments" : "dynRest" });
@@ -1191,7 +1287,7 @@ export function inferTypeParamBindings(lowerer, expr, info, rsig, tsBindings) {
1191
1287
  return;
1192
1288
  const taT = lowerer.checker.getTypeFromTypeNode(ta);
1193
1289
  const mapped = lowerer.mapTypeOf(taT);
1194
- if (mapped && mapped.kind !== "void") {
1290
+ if (mapped) {
1195
1291
  bindings.set(tp, mapped);
1196
1292
  tsBindings?.set(tp, taT);
1197
1293
  }
@@ -1211,7 +1307,7 @@ function bindDefaultTypeParams(lowerer, typeParams, typeParamDecls, bindings, ts
1211
1307
  return;
1212
1308
  const defT = lowerer.checker.getTypeFromTypeNode(tpDecl.defaultType);
1213
1309
  const mapped = lowerer.mapTypeOf(defT);
1214
- if (mapped && mapped.kind !== "void") {
1310
+ if (mapped) {
1215
1311
  bindings.set(tp, mapped);
1216
1312
  tsBindings?.set(tp, defT);
1217
1313
  }
@@ -1253,7 +1349,10 @@ function unifySignatureBindings(lowerer, info, rsig, bindings, tsBindings) {
1253
1349
  }
1254
1350
  if (!bindings.has(sym)) {
1255
1351
  const mapped = lowerer.mapTypeOf(inst);
1256
- 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)
1257
1356
  bindings.set(sym, mapped);
1258
1357
  }
1259
1358
  }
@@ -1268,10 +1367,20 @@ function unifySignatureBindings(lowerer, info, rsig, bindings, tsBindings) {
1268
1367
  // unbound type parameter surfaces as a mapping diagnostic later).
1269
1368
  if (declared.isUnionType()) {
1270
1369
  const unitFlags = ts.TypeFlags.Undefined | ts.TypeFlags.Null;
1271
- const dParts = ts.constituentTypes(declared).filter((t) => !(t.flags & unitFlags));
1272
- 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];
1273
1374
  if (dParts.length === 1 && iParts.length === 1)
1274
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
+ }
1275
1384
  return;
1276
1385
  }
1277
1386
  // Instantiations of the SAME generic ALIAS (Partial<T> vs
@@ -1424,16 +1533,21 @@ export function lowerGenericInstance(lowerer, info, inst) {
1424
1533
  fnCtx.generator = generatorMeta(lowerer, inst.returnType);
1425
1534
  }
1426
1535
  lowerer.fnStack.push(fnCtx);
1536
+ lowerer.localClassInstantiations.push({ owner: decl, name: inst.name });
1427
1537
  try {
1428
- // STATIC generic methods: `this`/`super` name the RECEIVER class (a
1429
- // dynamic value) — the lowerStaticMethod fence, applied here because
1430
- // generic statics have no non-generic lowering pass. Arrow functions
1431
- // are transparent (they inherit the method's `this`); this-binding
1432
- // 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.
1433
1541
  if (info.member?.kind === "static" && decl.body) {
1434
- 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);
1435
1543
  }
1436
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
+ }
1437
1551
  if (cls && info.member.kind === "method") {
1438
1552
  // Instance methods take `this` as param 0, exactly like plain
1439
1553
  // `%C.method` functions (lowerClassMethodMemberInner).
@@ -1445,7 +1559,7 @@ export function lowerGenericInstance(lowerer, info, inst) {
1445
1559
  // threaded — a default mentioning T resolves like any body expression.
1446
1560
  const declared = lowerer.declareParams(decl.parameters, inst.params);
1447
1561
  params.push(...declared.params);
1448
- const body = [...declared.prologue];
1562
+ const body = [...receiverInit, ...declared.prologue];
1449
1563
  const bodyBlock = blockBodyOf(decl);
1450
1564
  if (bodyBlock) {
1451
1565
  body.push(...lowerer.lowerStmts(bodyBlock.statements));
@@ -1488,6 +1602,8 @@ export function lowerGenericInstance(lowerer, info, inst) {
1488
1602
  }
1489
1603
  const fn = {
1490
1604
  name: inst.name,
1605
+ sourceName: info.baseName,
1606
+ ...(!isAsync && !decl.asteriskToken && (ts.isFunctionDeclaration(decl) || ts.isFunctionExpression(decl)) ? { ownsPrototype: true } : {}),
1491
1607
  params,
1492
1608
  returnType: bodyReturn,
1493
1609
  locals: lowerer.ctx.locals,
@@ -1507,6 +1623,7 @@ export function lowerGenericInstance(lowerer, info, inst) {
1507
1623
  lowerer.typeParamTsBindings = prevTsBindings;
1508
1624
  lowerer.implicitParamTypes = prevImplicit;
1509
1625
  lowerer.instantiationContext = prevContext;
1626
+ lowerer.localClassInstantiations.pop();
1510
1627
  lowerer.suppressStats = prevSuppress;
1511
1628
  }
1512
1629
  }
@@ -1529,7 +1646,6 @@ function resolveInferredReturn(lowerer, inst, infer, body, decl) {
1529
1646
  // returning — JS answers undefined.
1530
1647
  const last = body[body.length - 1];
1531
1648
  const mayFallThrough = !last || !(last.kind === "return" || last.kind === "throw" || last.kind === "rethrow" || last.kind === "runtimeFence");
1532
- const valued = infer.entries.filter((e) => e.stmt.kind === "return" && e.stmt.value !== null && e.stmt.value !== undefined);
1533
1649
  const sawBare = mayFallThrough || infer.entries.some((e) => e.stmt.kind === "return" && (e.stmt.value === null || e.stmt.value === undefined));
1534
1650
  let final;
1535
1651
  if (inst.returnPinned) {
@@ -1537,16 +1653,19 @@ function resolveInferredReturn(lowerer, inst, infer, body, decl) {
1537
1653
  }
1538
1654
  else {
1539
1655
  const distinct = [];
1540
- for (const e of valued) {
1541
- if (!distinct.some((t) => typeEquals(t, e.stmt.value.type)))
1542
- 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);
1543
1662
  }
1544
1663
  if (distinct.length === 0) {
1545
1664
  final = DYN; // no valued return: JS completes with undefined — the dyn undefined, today's slot
1546
1665
  }
1547
1666
  else if (distinct.length === 1) {
1548
1667
  const t = distinct[0];
1549
- 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);
1550
1669
  }
1551
1670
  else {
1552
1671
  final = DYN; // disagreeing returns: the checked-dynamic join
@@ -1557,23 +1676,24 @@ function resolveInferredReturn(lowerer, inst, infer, body, decl) {
1557
1676
  for (const e of infer.entries) {
1558
1677
  if (e.stmt.kind !== "return")
1559
1678
  continue;
1560
- 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.
1561
1681
  const diagsBefore = lowerer.diags.length;
1562
1682
  try {
1563
- if (st.value === null || st.value === undefined) {
1683
+ if (e.stmt.value === null || e.stmt.value === undefined) {
1564
1684
  if (final.kind === "dyn")
1565
- st.value = dynUndefinedExpr(st.loc);
1685
+ e.stmt.value = dynUndefinedExpr(e.stmt.loc);
1566
1686
  else if (final.kind === "union") {
1567
- const wrapped = lowerer.wrappedUndefined(final, st.loc);
1687
+ const wrapped = lowerer.wrappedUndefined(final, e.stmt.loc);
1568
1688
  if (!wrapped) {
1569
1689
  lowerer.unsupported("SC1090", e.node ?? decl, `bare 'return' in a function whose inferred return type is '${lowerer.fmt(final)}'`);
1570
1690
  }
1571
- st.value = wrapped;
1691
+ e.stmt.value = wrapped;
1572
1692
  }
1573
1693
  // void final: bare return stands as-is
1574
1694
  }
1575
- else if (!typeEquals(st.value.type, final)) {
1576
- 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);
1577
1697
  }
1578
1698
  }
1579
1699
  catch (err) {
@@ -1588,7 +1708,7 @@ function resolveInferredReturn(lowerer, inst, infer, body, decl) {
1588
1708
  lowerer.diags.push(...ice);
1589
1709
  lowerer.runtimeFences.push(...captured.filter((d) => d.code !== "SC9001"));
1590
1710
  const first = captured.find((d) => d.code !== "SC9001");
1591
- const mutable = st;
1711
+ const mutable = e.stmt;
1592
1712
  delete mutable["value"];
1593
1713
  mutable["kind"] = "runtimeFence";
1594
1714
  mutable["code"] = first?.code ?? "SC1090";
@@ -1846,10 +1966,12 @@ function broadPromiseParam(lowerer, type) {
1846
1966
  }
1847
1967
  /** The implicit-type-parameter slots of a JS function-like: parallel to
1848
1968
  * decl.parameters, the param SYMBOL where the slot is a bindable
1849
- * implicit-any param (identifier-named, no annotation/JSDoc type, not
1850
- * rest/optional/defaulted, never written), null elsewhere. Null overall
1851
- * when nothing qualifies — the declaration keeps today's path. */
1852
- 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) {
1853
1975
  if (!decl.body)
1854
1976
  return null;
1855
1977
  if (decl.asteriskToken)
@@ -1875,7 +1997,9 @@ export function implicitAnyParamSymbolsOf(lowerer, decl) {
1875
1997
  const broadFunction = lowerer.checker.typeToString(t) === "Function";
1876
1998
  const broadArray = lowerer.checkerAnyArrayType(t);
1877
1999
  const broadPromise = broadPromiseParam(lowerer, t);
1878
- 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)
1879
2003
  return null;
1880
2004
  const sym = lowerer.checker.getSymbolAtLocation(param.name);
1881
2005
  if (!sym)
@@ -1894,6 +2018,11 @@ export function implicitAnyParamSymbolsOf(lowerer, decl) {
1894
2018
  * selects return INFERENCE with DYN as the recursion pin. */
1895
2019
  function implicitDeclaredReturn(lowerer, info) {
1896
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;
1897
2026
  const broadCallbackSymbols = new Set(info.decl.parameters.flatMap((param, index) => {
1898
2027
  const symbol = info.implicitParams?.[index];
1899
2028
  return symbol !== null && symbol !== undefined &&
@@ -1913,7 +2042,10 @@ function implicitDeclaredReturn(lowerer, info) {
1913
2042
  expression = expression.expression;
1914
2043
  if (ts.isCallExpression(expression) &&
1915
2044
  ts.isIdentifier(expression.expression) &&
1916
- broadCallbackSymbols.has(lowerer.checker.getSymbolAtLocation(expression.expression) ?? {})) {
2045
+ (() => {
2046
+ const symbol = lowerer.checker.getSymbolAtLocation(expression.expression);
2047
+ return symbol !== undefined && broadCallbackSymbols.has(symbol);
2048
+ })()) {
1917
2049
  returnsBroadCallback = true;
1918
2050
  return "stop";
1919
2051
  }
@@ -1928,7 +2060,12 @@ function implicitDeclaredReturn(lowerer, info) {
1928
2060
  const retTs = lowerer.checker.getReturnTypeOfSignature(declSig);
1929
2061
  if (retTs.flags & ts.TypeFlags.Any)
1930
2062
  return null;
2063
+ if (retTs.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined))
2064
+ return DYN;
1931
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;
1932
2069
  const elem = lowerer.checker.getTypeArguments(retTs)[0];
1933
2070
  // An implicit-any parameter poisons an inferred array result to
1934
2071
  // any[] even when this instance's body produces one concrete
@@ -1939,6 +2076,11 @@ function implicitDeclaredReturn(lowerer, info) {
1939
2076
  return null;
1940
2077
  }
1941
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;
1942
2084
  if (mapped !== null && promiseCarriesDyn(lowerer, mapped) && !hasExplicitJsDocReturn(info.decl))
1943
2085
  return null;
1944
2086
  return mapped;
@@ -1970,6 +2112,30 @@ function bindableImplicitIr(t) {
1970
2112
  t.kind !== "void" && t.kind !== "dyn" && t.kind !== "jsval" &&
1971
2113
  t.kind !== "caught" && t.kind !== "undefinedT" && t.kind !== "nullT");
1972
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
+ }
1973
2139
  /** The instance a CALL of an implicit-any function-like names: each
1974
2140
  * bindable implicit param takes the call's WIDENED argument checker type
1975
2141
  * when it maps statically (DYN otherwise — today's slot), typed params
@@ -1992,19 +2158,52 @@ export function implicitCallInstance(lowerer, call, info) {
1992
2158
  bound = declared.type;
1993
2159
  const arg = call.arguments[i];
1994
2160
  if (arg && !ts.isSpreadElement(arg)) {
1995
- const runtimeLocal = ts.isIdentifier(arg) ? lowerer.peekLocal(arg) : null;
1996
- if (runtimeLocal?.type.kind === "dyn") {
2161
+ const stored = storedImplicitArgumentType(lowerer, arg);
2162
+ if (stored?.kind === "dyn") {
1997
2163
  bound = DYN;
1998
2164
  argTypes.set(sym, lowerer.checker.getUnknownType());
1999
2165
  shapes.push({ type: bound, mode: "required" });
2000
2166
  return;
2001
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
+ }
2002
2176
  // The argument's own checker type, literal-widened ('add' binds
2003
2177
  // string) — typeOf consults the ACTIVE instance's bindings, so a
2004
2178
  // bound param forwarded into another implicit call transitively
2005
2179
  // instantiates it (this._initCommandGroup(command)).
2006
2180
  const t = lowerer.checker.getBaseTypeOfLiteralType(lowerer.typeOf(arg));
2007
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
+ }
2008
2207
  if (ts.isArrowFunction(arg) &&
2009
2208
  arg.type === undefined &&
2010
2209
  mapped?.kind === "func" &&
@@ -2029,15 +2228,32 @@ export function implicitCallInstance(lowerer, call, info) {
2029
2228
  /** The all-dyn DEFAULT instance — today's compiled body exactly: what a
2030
2229
  * VALUE reference of an implicit-any function names (indirect calls
2031
2230
  * carry no per-site types to bind). */
2032
- function implicitDefaultInstance(lowerer, blame, info) {
2231
+ export function implicitDefaultInstance(lowerer, blame, info) {
2033
2232
  const shapes = info.decl.parameters.map((param, i) => info.implicitParams[i] ? { type: DYN, mode: "required" } : lowerer.paramShape(param));
2034
- 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);
2035
2244
  }
2036
2245
  function internImplicitInstance(lowerer, blame, info, shapes, argTypes) {
2037
2246
  const key = shapes.map((s) => typeKey(s.type)).join(",");
2038
2247
  let inst = info.instances.get(key);
2039
- 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;
2040
2255
  return inst;
2256
+ }
2041
2257
  if (info.instances.size >= MAX_GENERIC_INSTANCES) {
2042
2258
  lowerer.unsupported("SC1090", blame, `unbounded implicit-any instantiation ('${info.baseName}' exceeded ` +
2043
2259
  `${MAX_GENERIC_INSTANCES} instances — polymorphic recursion?)`);
@@ -2063,11 +2279,15 @@ function internImplicitInstance(lowerer, blame, info, shapes, argTypes) {
2063
2279
  ...(declared === null ? { implicitInferReturn: true } : {}),
2064
2280
  };
2065
2281
  info.instances.set(key, inst);
2066
- // EAGER lowering (nested, the lambda discipline): the call site needs
2067
- // the settled return type NOW. A body-level poison (a fenced parameter
2068
- // form) skips the function like lowerFunction's rule — calls then meet
2069
- // the pinned signature over a missing body, which the linker never
2070
- // 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;
2071
2291
  try {
2072
2292
  // Implicit-any instances lower EAGERLY at the call site so their
2073
2293
  // inferred return type is available immediately. They therefore do
@@ -2085,8 +2305,20 @@ function internImplicitInstance(lowerer, blame, info, shapes, argTypes) {
2085
2305
  catch (e) {
2086
2306
  if (!(e instanceof PoisonError))
2087
2307
  throw e;
2088
- inst.implicitState = "done";
2089
- 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;
2090
2322
  }
2091
2323
  inst.implicitState = "done";
2092
2324
  return inst;
@@ -2192,11 +2424,11 @@ export function implicitLocalFnInfoOf(lowerer, decl, fnNode) {
2192
2424
  const implicit = implicitAnyParamSymbolsOf(lowerer, fnNode);
2193
2425
  if (!implicit)
2194
2426
  lowerer.unsupported("SC1090", fnNode, "this function form"); // defensive: the probe proved it
2195
- const stmt = decl.parent.parent;
2427
+ const stmt = decl.parent?.parent;
2196
2428
  const info = {
2197
2429
  decl: fnNode,
2198
2430
  baseName: name,
2199
- 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()}`),
2200
2432
  typeParams: [],
2201
2433
  instances: new Map(),
2202
2434
  implicitParams: implicit,
@@ -2407,6 +2639,7 @@ function makeTimerArgsThunk(lowerer, cbNode, argNodes, what, loc) {
2407
2639
  kind: "dynCall",
2408
2640
  callee: { kind: "varRef", localId: "f.0", type: DYN, loc },
2409
2641
  calleeName: "callback",
2642
+ receiver: { kind: "libCall", fn: "dyn.this", args: [], type: DYN, loc },
2410
2643
  args: args.map((_, i) => ({ kind: "varRef", localId: `a${i}.0`, type: DYN, loc })),
2411
2644
  type: DYN,
2412
2645
  loc,
@@ -2571,7 +2804,12 @@ export function lowerTimersMemberCall(lowerer, expr, member, loc) {
2571
2804
  return null;
2572
2805
  }
2573
2806
  function ffiSourceParams(binding) {
2574
- 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;
2575
2813
  }
2576
2814
  function ffiParamDisplay(param) {
2577
2815
  return isFfiCallbackParam(param)
@@ -2588,7 +2826,11 @@ function ffiCallbackInputDiagnostic(lowerer, descriptor, callbackType) {
2588
2826
  const signatures = lowerer.checker.getCallSignatures(callbackType);
2589
2827
  if (signatures.length !== 1)
2590
2828
  return null;
2591
- 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
+ }
2592
2834
  let nativeIndex = 0;
2593
2835
  const params = signatures[0].getParameters();
2594
2836
  for (let i = 0; i < params.length; i++) {
@@ -2606,12 +2848,13 @@ function ffiCallbackInputDiagnostic(lowerer, descriptor, callbackType) {
2606
2848
  }
2607
2849
  if (nativeClass === "bytes")
2608
2850
  continue;
2609
- const domain = nativeClass === "bool"
2851
+ const wide = nativeClass === "i64" || nativeClass === "u64" || nativeClass === "pointer";
2852
+ const domain = wide ? "bigint" : nativeClass === "bool"
2610
2853
  ? "boolean"
2611
2854
  : nativeClass === "cstring" || nativeClass === "string"
2612
2855
  ? "string"
2613
2856
  : "number";
2614
- const coversDomain = nativeClass === "bool"
2857
+ const coversDomain = wide ? (paramType.flags & ts.TypeFlags.BigInt) !== 0 : nativeClass === "bool"
2615
2858
  ? (paramType.flags & ts.TypeFlags.Boolean) !== 0
2616
2859
  : nativeClass === "cstring" || nativeClass === "string"
2617
2860
  ? (paramType.flags & ts.TypeFlags.String) !== 0
@@ -2634,8 +2877,9 @@ function ffiCallbackInputDiagnostic(lowerer, descriptor, callbackType) {
2634
2877
  function ffiReturnDomainDiagnostic(lowerer, nativeClass, returnType) {
2635
2878
  if (nativeClass === "void")
2636
2879
  return null;
2637
- const domain = nativeClass === "bool" ? "boolean" : "number";
2638
- 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"
2639
2883
  ? (returnType.flags & ts.TypeFlags.Boolean) !== 0
2640
2884
  : (returnType.flags & ts.TypeFlags.Number) !== 0;
2641
2885
  return coversDomain
@@ -2743,7 +2987,7 @@ function libraryCallbackOwnsFile(lowerer, file) {
2743
2987
  export function validateFfiImports(lowerer) {
2744
2988
  const diagnostics = [];
2745
2989
  const symbolsByName = new Map();
2746
- 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));
2747
2991
  const candidates = new Map();
2748
2992
  if (configuredNames.size === 0)
2749
2993
  return { diagnostics, symbolsByName };
@@ -2773,6 +3017,8 @@ export function validateFfiImports(lowerer) {
2773
3017
  });
2774
3018
  }
2775
3019
  for (const binding of lowerer.ffiImports) {
3020
+ if (binding.library !== undefined)
3021
+ continue;
2776
3022
  const bySymbol = candidates.get(binding.name);
2777
3023
  if (bySymbol === undefined || bySymbol.size === 0) {
2778
3024
  // A native-manifest binding with no declaration is a broken build
@@ -2820,6 +3066,8 @@ export function lowerFfiCall(lowerer, expr) {
2820
3066
  if (!ts.isIdentifier(expr.expression))
2821
3067
  return null;
2822
3068
  const binding = lowerer.ffiImportsByName.get(expr.expression.text);
3069
+ if (binding?.library !== undefined)
3070
+ return null;
2823
3071
  if (binding === undefined) {
2824
3072
  // LIBRARY mode with a declared callback surface: a CALL of a
2825
3073
  // program-authored signature-only ambient function that names no
@@ -2853,7 +3101,8 @@ export function lowerFfiCall(lowerer, expr) {
2853
3101
  lowerer.pushDiag(signatureFlavor(binding.name, detail, loc));
2854
3102
  throw new PoisonError();
2855
3103
  };
2856
- const symbol = lowerer.resolveValueSymbol(expr.expression) ??
3104
+ const symbol = lowerer.resolveValueSymbol(expr.expression);
3105
+ if (!symbol)
2857
3106
  bindingError("the call has no resolved TypeScript symbol");
2858
3107
  if (lowerer.ffiBindingSymbols !== null) {
2859
3108
  const validSymbols = lowerer.ffiBindingSymbols.get(binding.name);
@@ -2936,7 +3185,7 @@ export function lowerFfiCall(lowerer, expr) {
2936
3185
  }
2937
3186
  // An inline function value at a RELEASE site can never match:
2938
3187
  // lifted lambdas always carry a captures list (even an empty one),
2939
- // so both backends mint a fresh closure per evaluation of the
3188
+ // so the backend creates a fresh closure per evaluation of the
2940
3189
  // expression — the release argument is a pointer no registration
2941
3190
  // holds, a guaranteed runtime trap. Declared functions stay valid
2942
3191
  // here — their value is the interned immortal closure (captures
@@ -3143,6 +3392,18 @@ export function lowerCall(lowerer, expr) {
3143
3392
  }
3144
3393
  const consoleMember = lowerer.consoleCallMember(expr);
3145
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
+ };
3146
3407
  // console.log/info/debug write stdout; console.error and console.warn
3147
3408
  // are one stream in Node (warn IS error, info and debug ARE log) and
3148
3409
  // write stderr with the exact same formatting. Node's formatter is
@@ -3164,13 +3425,13 @@ export function lowerCall(lowerer, expr) {
3164
3425
  (ts.isStringLiteral(expr.arguments[0]) || ts.isNoSubstitutionTemplateLiteral(expr.arguments[0])) &&
3165
3426
  /%[sdifjoOc%]/.test(expr.arguments[0].text)) {
3166
3427
  const formatted = lowerFormatCall(lowerer, expr, loc, false);
3167
- return {
3428
+ return withReceiver({
3168
3429
  kind: "intrinsic",
3169
3430
  name: stdoutMember ? "console.log" : "console.error",
3170
3431
  args: [formatted],
3171
3432
  type: VOID,
3172
3433
  loc,
3173
- };
3434
+ });
3174
3435
  }
3175
3436
  const args = expr.arguments.map((a) => {
3176
3437
  const lowered = lowerer.lowerExpr(a);
@@ -3231,13 +3492,13 @@ export function lowerCall(lowerer, expr) {
3231
3492
  // render fence honestly with the reason.
3232
3493
  return lowerConsoleInspectArg(lowerer, a, lowered, surface, loc);
3233
3494
  });
3234
- return {
3495
+ return withReceiver({
3235
3496
  kind: "intrinsic",
3236
3497
  name: stdoutMember ? "console.log" : "console.error",
3237
3498
  args,
3238
3499
  type: VOID,
3239
3500
  loc,
3240
- };
3501
+ });
3241
3502
  }
3242
3503
  // The timer globals — setTimeout/clearTimeout, setInterval/
3243
3504
  // clearInterval, setImmediate/clearImmediate. Provenance-checked (a
@@ -3388,25 +3649,12 @@ export function lowerCall(lowerer, expr) {
3388
3649
  lowerer.noLowering(`BigInt with ${expr.arguments.length} arguments`, expr);
3389
3650
  }
3390
3651
  const argNode = expr.arguments[0];
3391
- const arg = lowerer.lowerExpr(argNode);
3392
- if (arg.type.kind === "bigint")
3393
- return arg;
3394
- if (arg.type.kind === "string") {
3395
- return { kind: "libCall", fn: "bigint.parse", args: [arg], type: BIGINT_T, loc };
3396
- }
3397
- if (arg.type.kind === "f64") {
3398
- return { kind: "libCall", fn: "bigint.fromF64", args: [arg], type: BIGINT_T, loc };
3399
- }
3400
- if (arg.type.kind === "bool") {
3401
- return {
3402
- kind: "ternary",
3403
- cond: arg,
3404
- then: { kind: "libCall", fn: "bigint.parse", args: [{ kind: "strLit", value: "1", type: STRING, loc }], type: BIGINT_T, loc },
3405
- else_: { kind: "libCall", fn: "bigint.parse", args: [{ kind: "strLit", value: "0", type: STRING, loc }], type: BIGINT_T, loc },
3406
- type: BIGINT_T,
3407
- loc,
3408
- };
3409
- }
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;
3410
3658
  lowerer.noLowering(`BigInt of ${lowerer.fmt(arg.type)} values`, argNode, "string, number, boolean, and bigint arguments are supported");
3411
3659
  }
3412
3660
  if (ts.isIdentifier(expr.expression) &&
@@ -3444,6 +3692,9 @@ export function lowerCall(lowerer, expr) {
3444
3692
  if (name === "Number")
3445
3693
  return lowerNumberConstructorValue(lowerer, argNode, loc);
3446
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
+ }
3447
3698
  if (name === "String")
3448
3699
  return lowerer.ensureString(arg, argNode);
3449
3700
  }
@@ -3461,6 +3712,29 @@ export function lowerCall(lowerer, expr) {
3461
3712
  const code = lowerer.lowerExprExpecting(expr.arguments[0], STRING);
3462
3713
  return { kind: "libCall", fn: "island.eval", args: [code], type: STRING, loc };
3463
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
+ }
3464
3738
  // Island calls. A property-access callee whose receiver is an 'any'
3465
3739
  // value is an engine method call (this = receiver, JS-exact); any other
3466
3740
  // 'any'-typed callee is an engine function call. Arguments marshal in;
@@ -4059,6 +4333,9 @@ export function lowerCall(lowerer, expr) {
4059
4333
  let callee = lowerer.lowerExpr(nsMember);
4060
4334
  if (callee.type.kind === "record")
4061
4335
  callee = lowerer.hybridCallUnwrap(callee);
4336
+ const checked = lowerCheckedCallableValue(lowerer, expr, callee, loc);
4337
+ if (checked)
4338
+ return checked;
4062
4339
  if (callee.type.kind !== "func")
4063
4340
  lowerer.badType(expr.expression, lowerer.typeOf(expr.expression));
4064
4341
  const args = completeFuncValueArgs(lowerer, expr, callee.type, loc);
@@ -4112,6 +4389,9 @@ export function lowerCall(lowerer, expr) {
4112
4389
  let callee = lowerer.lowerExpr(nameId);
4113
4390
  if (callee.type.kind === "record")
4114
4391
  callee = lowerer.hybridCallUnwrap(callee);
4392
+ const checked = lowerCheckedCallableValue(lowerer, expr, callee, loc);
4393
+ if (checked)
4394
+ return checked;
4115
4395
  if (callee.type.kind !== "func")
4116
4396
  lowerer.badType(expr.expression, lowerer.typeOf(expr.expression));
4117
4397
  const args = completeFuncValueArgs(lowerer, expr, callee.type, loc);
@@ -4191,6 +4471,7 @@ export function lowerCall(lowerer, expr) {
4191
4471
  // TestContext surface (t.test/t.skip/t.diagnostic), t.assert.*.
4192
4472
  lowerer.lowerTestMethodCall(expr, expr.expression) ??
4193
4473
  lowerer.lowerTimeoutMethodCall(expr, expr.expression) ??
4474
+ lowerArrayPrototypeBorrowCall(lowerer, expr, expr.expression) ??
4194
4475
  lowerObjectOwnPrototypeCall(lowerer, expr, expr.expression) ??
4195
4476
  lowerObjectPrototypeCall(lowerer, expr, expr.expression) ??
4196
4477
  lowerStringPrototypeCall(lowerer, expr, expr.expression) ??
@@ -4198,6 +4479,7 @@ export function lowerCall(lowerer, expr) {
4198
4479
  // Typed-array/Buffer receivers and the Buffer statics — before the
4199
4480
  // island path (bytes never cross the boundary).
4200
4481
  lowerer.lowerBytesMethodCall(expr, expr.expression) ??
4482
+ lowerBytesStaticCall(lowerer, expr, expr.expression) ??
4201
4483
  lowerBufferStaticCallWithNarrowedArg(lowerer, expr, expr.expression) ??
4202
4484
  // URL.revokeObjectURL's zero-argument contract (the one-argument
4203
4485
  // form keeps the fence — createObjectURL does too).
@@ -4265,8 +4547,8 @@ export function lowerCall(lowerer, expr) {
4265
4547
  lowerArrayFromCall(lowerer, expr, expr.expression) ??
4266
4548
  lowerArrayOfCall(lowerer, expr, expr.expression) ??
4267
4549
  lowerer.lowerArrayMethodCall(expr, expr.expression) ??
4268
- // Read-only array methods (slice/map) on TUPLE receivers — the
4269
- // 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.
4270
4552
  lowerTupleReadMethodCall(lowerer, expr, expr.expression) ??
4271
4553
  lowerGenMethodCall(lowerer, expr, expr.expression) ??
4272
4554
  lowerer.lowerMapMethodCall(expr, expr.expression) ??
@@ -4281,6 +4563,18 @@ export function lowerCall(lowerer, expr) {
4281
4563
  lowerObjLitGenericMethodCall(lowerer, expr, expr.expression);
4282
4564
  if (intrinsic)
4283
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
+ }
4284
4578
  // A method call rooted at an initializer-less ambient `declare
4285
4579
  // const/var` whose declared type has no mapping: Node throws the
4286
4580
  // catchable ReferenceError at the ROOT read before the member, the
@@ -4330,6 +4624,9 @@ export function lowerCall(lowerer, expr) {
4330
4624
  // The element spelling of an unsupported native Web method must fence
4331
4625
  // before lowering the callee into a checked-dynamic keyed read.
4332
4626
  if (ts.isElementAccessExpression(expr.expression)) {
4627
+ const symbolMethod = lowerClassSymbolMethodCall(lowerer, expr);
4628
+ if (symbolMethod)
4629
+ return symbolMethod;
4333
4630
  const headersIterator = lowerer.lowerDynamicHeadersIteratorCall(expr, expr.expression);
4334
4631
  if (headersIterator)
4335
4632
  return headersIterator;
@@ -4345,8 +4642,41 @@ export function lowerCall(lowerer, expr) {
4345
4642
  if (ts.isElementAccessExpression(expr.expression) &&
4346
4643
  !expr.expression.questionDotToken &&
4347
4644
  !expr.questionDotToken &&
4348
- ts.isStringLiteralLike(expr.expression.argumentExpression)) {
4349
- 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
+ }
4350
4680
  // ts7's getSymbolAtLocation does not resolve element accesses; the
4351
4681
  // member symbol comes from the receiver's (apparent) type instead —
4352
4682
  // same provenance answer as the dot spelling's name symbol.
@@ -4444,7 +4774,7 @@ export function lowerCall(lowerer, expr) {
4444
4774
  // JS arity exactly (the thunk ignores extras). Result dyn, checked
4445
4775
  // per use like every any-origin value.
4446
4776
  if ((expr.arguments.length > callee.type.params.length || callee.type.rest === true) &&
4447
- isJsSourceFile(expr.getSourceFile()) &&
4777
+ (isJsSourceFile(expr.getSourceFile()) || callee.type.rest === true && callee.type.restAbi === undefined) &&
4448
4778
  !expr.arguments.some((a) => ts.isSpreadElement(a)) &&
4449
4779
  canBoxFuncIntoDyn(callee.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) {
4450
4780
  const args = expr.arguments.map((a) => lowerer.lowerExprExpecting(a, DYN));
@@ -4455,6 +4785,29 @@ export function lowerCall(lowerer, expr) {
4455
4785
  const args = completeFuncValueArgs(lowerer, expr, callee.type, loc);
4456
4786
  return { kind: "callValue", callee, args, type: callee.type.ret, loc };
4457
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
+ }
4458
4811
  function lowerRegexMethodCallWithOptionalArg(lowerer, call, access) {
4459
4812
  const lowered = lowerer.lowerRegexMethodCall(call, access);
4460
4813
  if (lowered?.kind !== "regexIntrinsic" || lowered.method !== "test" || call.arguments.length !== 1)
@@ -4476,9 +4829,13 @@ function optionalCallValue(lowerer, node) {
4476
4829
  return lowerer.runtimeOptionalIdentifierValue(node)?.value ?? lowerAbsenceProbe(lowerer, node);
4477
4830
  }
4478
4831
  function lowerBufferStaticCallWithNarrowedArg(lowerer, call, access) {
4479
- 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;
4480
4837
  if (lowered?.kind !== "bytesNew" || !lowered.source || lowered.source.type.kind !== "union")
4481
- return lowered;
4838
+ return result;
4482
4839
  // A callback can store a wider union than the checker sees at this use
4483
4840
  // (including an added undefined arm). Extract the exact arm proven by
4484
4841
  // control-flow narrowing, not merely the union with undefined removed.
@@ -4494,10 +4851,11 @@ function lowerBufferStaticCallWithNarrowedArg(lowerer, call, access) {
4494
4851
  if (!helper) {
4495
4852
  lowerer.unsupported("SC1090", call.arguments[0], "a Buffer constructor argument whose narrowed type is not a stored source arm");
4496
4853
  }
4497
- return {
4854
+ const narrowedValue = {
4498
4855
  ...lowered,
4499
4856
  source: { kind: "call", callee: helper, args: [lowered.source], type: narrowed, loc: lowered.source.loc },
4500
4857
  };
4858
+ return branded ? { ...branded, args: [narrowedValue] } : narrowedValue;
4501
4859
  }
4502
4860
  function lowerOptionalNumberDefault(lowerer, value, dflt, loc) {
4503
4861
  const widened = lowerer.runtimeOptionalWidening(value.type, F64);
@@ -4552,6 +4910,8 @@ function lowerStringMethodCallWithOptionalArgs(lowerer, call, access, receiver,
4552
4910
  ? [1]
4553
4911
  : [];
4554
4912
  for (const index of zeroDefaultArgs) {
4913
+ if (index === undefined)
4914
+ continue;
4555
4915
  const value = args[index];
4556
4916
  if (!value)
4557
4917
  continue;
@@ -4597,6 +4957,8 @@ function lowerNumberConstructorValue(lowerer, argNode, loc) {
4597
4957
  }
4598
4958
  if (arg.type.kind === "string")
4599
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 };
4600
4962
  const optionalNumber = lowerOptionalStringNumber(lowerer, arg, loc);
4601
4963
  if (optionalNumber)
4602
4964
  return optionalNumber;
@@ -4607,6 +4969,61 @@ function lowerNumberConstructorValue(lowerer, argNode, loc) {
4607
4969
  ? "unions of numbers, booleans, strings, null, and undefined lower — narrow other arms first"
4608
4970
  : undefined);
4609
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
+ }
4610
5027
  function immediatePrimitiveWrapperToString(lowerer, node) {
4611
5028
  const stringValue = stringWrapperToString(lowerer, node);
4612
5029
  if (stringValue)
@@ -4629,24 +5046,6 @@ function immediatePrimitiveWrapperToString(lowerer, node) {
4629
5046
  : args.length ? lowerNumberConstructorValue(lowerer, args[0], loc) : { kind: "numLit", value: 0, type: F64, loc };
4630
5047
  return lowerer.ensureString(primitive, wrapped);
4631
5048
  }
4632
- function plainObjectCoercionReceiver(lowerer, node) {
4633
- const plainLiteral = (literal) => literal.properties.every((prop) => ts.isPropertyAssignment(prop) &&
4634
- (ts.isIdentifier(prop.name) || ts.isStringLiteral(prop.name) || ts.isNumericLiteral(prop.name)) &&
4635
- prop.name.text !== "__proto__");
4636
- let value = node;
4637
- while (ts.isParenthesizedExpression(value))
4638
- value = value.expression;
4639
- if (ts.isObjectLiteralExpression(value))
4640
- return plainLiteral(value);
4641
- if (!ts.isIdentifier(value))
4642
- return false;
4643
- const symbol = lowerer.resolveValueSymbol(value);
4644
- const decl = symbol ? lowerer.checker.valueDeclarationOf(symbol) : undefined;
4645
- if (!symbol || !decl || !ts.isVariableDeclaration(decl) || !decl.initializer ||
4646
- !ts.isObjectLiteralExpression(decl.initializer) || !plainLiteral(decl.initializer))
4647
- return false;
4648
- return bindingNeverReassigned(lowerer, symbol, decl);
4649
- }
4650
5049
  function objectToStringTag(lowerer, type) {
4651
5050
  switch (type.kind) {
4652
5051
  case "undefinedT":
@@ -4667,7 +5066,7 @@ function objectToStringTag(lowerer, type) {
4667
5066
  case "set": return "Set";
4668
5067
  case "promise": return "Promise";
4669
5068
  case "bytes":
4670
- return ({ u8: "Uint8Array", u32: "Uint32Array", i32: "Int32Array", f32: "Float32Array", f64: "Float64Array" })[type.elem];
5069
+ return BYTES_ELEMENT_NAME[type.elem];
4671
5070
  case "object":
4672
5071
  return type.className === "%Error" || lowerer.isSubclassOf(type.className, "%Error") ? "Error" : null;
4673
5072
  default: return null;
@@ -4689,6 +5088,10 @@ function immediateObjectTagReceiver(lowerer, node) {
4689
5088
  lowerer.isStdlibSymbol(lowerer.resolveValueSymbol(value.expression) ?? undefined)) {
4690
5089
  const name = value.expression.text;
4691
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) };
4692
5095
  if (args.length <= 1 && !args.some(ts.isSpreadElement)) {
4693
5096
  if (name === "String") {
4694
5097
  const effect = stringWrapperToString(lowerer, value);
@@ -4736,6 +5139,36 @@ function immediateObjectTagReceiver(lowerer, node) {
4736
5139
  }
4737
5140
  return null;
4738
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
+ }
4739
5172
  function lowerObjectOwnPrototypeCall(lowerer, call, access) {
4740
5173
  if (lowerer.dynamic || access.name.text !== "call" || !ts.isPropertyAccessExpression(access.expression))
4741
5174
  return null;
@@ -4754,10 +5187,31 @@ function lowerObjectOwnMethodCall(lowerer, call, access) {
4754
5187
  const method = access.name.text;
4755
5188
  if (lowerer.dynamic || call.questionDotToken || access.questionDotToken ||
4756
5189
  (method !== "hasOwnProperty" && method !== "propertyIsEnumerable") ||
4757
- !lowerer.isStdlibMember(access) || call.arguments.some(ts.isSpreadElement))
5190
+ call.arguments.some(ts.isSpreadElement))
4758
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
+ }
4759
5197
  return lowerObjectOwnCall(lowerer, call, access.expression, call.arguments[0], call.arguments.slice(1), method);
4760
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
+ }
4761
5215
  function lowerObjectOwnCall(lowerer, call, receiverNode, keyNode, extraNodes, method) {
4762
5216
  const enumerable = method === "propertyIsEnumerable";
4763
5217
  const loc = locOf(call);
@@ -4790,14 +5244,18 @@ function lowerObjectOwnCall(lowerer, call, receiverNode, keyNode, extraNodes, me
4790
5244
  stmts.push({ kind: "exprStmt", expr: effect, loc: locOf(extra) });
4791
5245
  }
4792
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
+ }
4793
5251
  if (!keyNode || rawKey?.type.kind === "undefinedT" || rawKey?.type.kind === "void") {
4794
5252
  key = { kind: "strLit", value: "undefined", type: STRING, loc };
4795
5253
  }
4796
5254
  else if (rawKey?.type.kind === "nullT") {
4797
5255
  key = { kind: "strLit", value: "null", type: STRING, loc };
4798
5256
  }
4799
- else if (key && (key.type.kind === "f64" || key.type.kind === "bool" || key.type.kind === "bigint")) {
4800
- key = { kind: "toString", operand: key, type: STRING, loc };
5257
+ else if (key) {
5258
+ key = ownPropertyKey(lowerer, key);
4801
5259
  }
4802
5260
  if (!key || key.type.kind !== "string") {
4803
5261
  lowerer.noLowering("Object.prototype." + method + " with this property key", keyNode ?? call);
@@ -4809,13 +5267,13 @@ function lowerObjectOwnCall(lowerer, call, receiverNode, keyNode, extraNodes, me
4809
5267
  }
4810
5268
  else if (type.kind === "record") {
4811
5269
  const shape = lowerer.shapes.get(type.shapeId);
4812
- if (!shape || shape.tuple || shape.indexValue || shapeHasAccessorSlots(shape)) {
5270
+ if (!shape || shape.tuple || shapeHasAccessorSlots(shape)) {
4813
5271
  lowerer.noLowering("Object.prototype." + method + " over this record shape", receiverNode ?? call);
4814
5272
  }
4815
5273
  result = { kind: "call", callee: recordHasOwnHelper(lowerer, type.shapeId, loc), args: [receiverRef, key], type: BOOL, loc };
4816
5274
  }
4817
- else if (type.kind === "dyn" && !enumerable) {
4818
- 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 };
4819
5277
  }
4820
5278
  else if (type.kind === "string" || type.kind === "array") {
4821
5279
  const needleLocal = lowerer.declareHiddenLocal("%ownIndex", F64);
@@ -4884,6 +5342,52 @@ function lowerObjectPrototypeCall(lowerer, call, access) {
4884
5342
  : { kind: "strLit", value: "[object " + tag + "]", type: STRING, loc };
4885
5343
  return { kind: "seqExpr", stmts, result, type: STRING, loc };
4886
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
+ }
4887
5391
  function lowerStringPrototypeCall(lowerer, call, access) {
4888
5392
  if (access.name.text !== "call" || !ts.isPropertyAccessExpression(access.expression))
4889
5393
  return null;
@@ -4926,6 +5430,9 @@ function lowerStringPrototypeCall(lowerer, call, access) {
4926
5430
  loc,
4927
5431
  };
4928
5432
  }
5433
+ if (receiverType.kind === "dyn") {
5434
+ return lowerDynamicStringPrototypeCall(lowerer, call, methodAccess, receiverValue, method);
5435
+ }
4929
5436
  const padding = entry?.method === "padStart" || entry?.method === "padEnd";
4930
5437
  const scalar = receiverType.kind === "string" || receiverType.kind === "f64" ||
4931
5438
  receiverType.kind === "bool" || receiverType.kind === "bigint" ||
@@ -4934,10 +5441,8 @@ function lowerStringPrototypeCall(lowerer, call, access) {
4934
5441
  // padding uses a helper that delays conversion until every argument is ready.
4935
5442
  const objectWithoutMethodArgs = entry?.maxArgs === 0 && call.arguments.length === 1 &&
4936
5443
  (receiverType.kind === "record" || receiverType.kind === "array" || receiverType.kind === "object");
4937
- const dynObjectWithoutMethodArgs = entry?.maxArgs === 0 && call.arguments.length === 1 &&
4938
- receiverType.kind === "dyn" && plainObjectCoercionReceiver(lowerer, receiverNode);
4939
- if (!scalar && !objectWithoutMethodArgs && !dynObjectWithoutMethodArgs && !(padding && receiverType.kind === "dyn")) {
4940
- 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);
4941
5446
  }
4942
5447
  if (indexMethod)
4943
5448
  return lowerStringIndexCall(lowerer, call, indexMethod, receiverValue, receiverNode, call.arguments.slice(1));
@@ -4949,9 +5454,7 @@ function lowerStringPrototypeCall(lowerer, call, access) {
4949
5454
  if (entry.method === "split") {
4950
5455
  return lowerStringSplitCall(lowerer, call, receiverValue, receiverNode, call.arguments.slice(1));
4951
5456
  }
4952
- const receiver = dynObjectWithoutMethodArgs
4953
- ? { kind: "libCall", fn: "dyn.toStringCoerce", args: [receiverValue], type: STRING, loc }
4954
- : lowerer.ensureString(receiverValue, receiverNode);
5457
+ const receiver = lowerer.ensureString(receiverValue, receiverNode);
4955
5458
  return lowerStringMethodCallWithOptionalArgs(lowerer, call, methodAccess, () => receiver, call.arguments.slice(1));
4956
5459
  }
4957
5460
  function lowerScalarUnionNumber(lowerer, arg, node, loc) {
@@ -5125,13 +5628,18 @@ function spreadNeedsRuntimeArity(lowerer, shapes, argNodes) {
5125
5628
  position += tuple.fields.length;
5126
5629
  continue;
5127
5630
  }
5128
- if (restAt < 0 || position < restAt || shapes[restAt].mode !== "rest")
5129
- return true;
5631
+ if (restAt < 0 || position < restAt || shapes[restAt].mode !== "rest") {
5632
+ return !canCompleteRuntimeSpread(lowerer, shapes);
5633
+ }
5130
5634
  }
5131
5635
  position++;
5132
5636
  }
5133
5637
  return false;
5134
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
+ }
5135
5643
  /** METHOD calls on dyn receivers (`pkg.name.replace(...)`, `rawName.split`,
5136
5644
  * `ws.packages.filter(...)` — JSON.parse-derived values): validate the
5137
5645
  * receiver's dyn kind, extract, and ride the STATIC method machinery — the
@@ -5169,6 +5677,27 @@ function lowerDynReceiverMethodCall(lowerer, call, access) {
5169
5677
  // tsc types the return by the evolved shape, the binding lowered
5170
5678
  // dyn): probe the lowering and claim exactly the dyn results.
5171
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
+ }
5172
5701
  if (probed?.type.kind !== "dyn")
5173
5702
  return null;
5174
5703
  recv = probed;
@@ -5176,11 +5705,30 @@ function lowerDynReceiverMethodCall(lowerer, call, access) {
5176
5705
  // A checker-`any` receiver that already lowered to a real STRING (the
5177
5706
  // chained form — `cfg.host.trim().toLowerCase()`, where the first step
5178
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
+ }
5179
5713
  if (recv.type.kind === "string") {
5180
5714
  return lowerRegexMethodCall(lowerer, call, access, () => recv) ?? lowerStringMethodCall(lowerer, call, access, () => recv);
5181
5715
  }
5182
5716
  if (recv.type.kind !== "dyn")
5183
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
+ })();
5184
5732
  // Typed-destination filter first (validated extraction into a real
5185
5733
  // T[]); an untyped destination falls through to the runtime dispatch
5186
5734
  // below (the survivors stay dyn values).
@@ -5196,34 +5744,21 @@ function lowerDynReceiverMethodCall(lowerer, call, access) {
5196
5744
  // these, "the receiver is a string, or the call throws V8's TypeError"
5197
5745
  // IS Node's semantics for every possible dyn value. Shared names would
5198
5746
  // need a receiver-kind dispatch — they keep the fence.
5199
- if (DYN_STRING_ONLY_METHODS.has(access.name.text)) {
5747
+ if (DYN_STRING_ONLY_METHODS.has(access.name.text) && !ownCallable) {
5200
5748
  const checked = () => dynStringReceiver(lowerer, recv, access);
5201
5749
  return lowerRegexMethodCall(lowerer, call, access, checked) ?? lowerStringMethodCall(lowerer, call, access, checked);
5202
5750
  }
5203
- // toString() is a shared prototype name with its OWN receiver-kind
5204
- // dispatched runtime lowering (dyn.toString: Buffer-flavored bytes
5205
- // decode per the encoding — a stream chunk's common consumption —
5206
- // and strings/numbers/booleans/arrays/objects answer JS-exactly).
5207
- // The optional argument is a literal encoding (meaningful for bytes;
5208
- // JS ignores extra toString arguments on the other kinds, and so
5209
- // 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.
5210
5753
  if (access.name.text === "toString" && call.arguments.length <= 1) {
5211
- const enc = call.arguments[0]
5212
- ? bufEncoding(lowerer, "toString", call.arguments[0])
5213
- : "utf8";
5214
- // The source spelling rides along for the ONE receiver whose
5215
- // prototype lacks toString: a null-prototype dictionary throws
5216
- // Node's "<spelling> is not a function" at runtime.
5754
+ const argument = call.arguments[0];
5217
5755
  return {
5218
- kind: "libCall",
5219
- fn: "dyn.toString",
5220
- args: [
5756
+ kind: "libCall", fn: "dyn.toString", args: [
5221
5757
  recv,
5222
- { kind: "strLit", value: enc, type: STRING, loc: locOf(call) },
5758
+ argument ? lowerer.lowerExprExpecting(argument, DYN)
5759
+ : dynUndefinedExpr(locOf(call)),
5223
5760
  { kind: "strLit", value: access.getText(), type: STRING, loc: locOf(call) },
5224
- ],
5225
- type: STRING,
5226
- loc: locOf(call),
5761
+ ], type: STRING, loc: locOf(call),
5227
5762
  };
5228
5763
  }
5229
5764
  // SHARED prototype names with a runtime dispatch (scr_dyn_invoke):
@@ -5254,17 +5789,6 @@ function lowerDynReceiverMethodCall(lowerer, call, access) {
5254
5789
  // its name overlaps a primitive prototype (`colors.bold(...)`): the
5255
5790
  // source value was compiled from that object shape, while genuinely
5256
5791
  // untyped/any receivers retain the runtime-kind ambiguity and fence.
5257
- const ownCallable = !checkerUntyped && (() => {
5258
- const prop = lowerer.checker.getPropertyOfType(recvTs, access.name.text);
5259
- if (prop === undefined)
5260
- return false;
5261
- // getPropertyOfType includes inherited Object.prototype members.
5262
- // Those are not stored members of a checked-dynamic object, so
5263
- // dynKeyGet cannot stand in for JavaScript's prototype lookup. Only
5264
- // an authored declaration can justify the own-member path.
5265
- const authored = lowerer.checker.declarationsOf(prop).some((decl) => !lowerer.isStdlibFile(decl.getSourceFile()));
5266
- return authored && lowerer.checker.getCallSignatures(lowerer.checker.getTypeOfSymbol(prop)).length > 0;
5267
- })();
5268
5792
  if (DYN_PROTO_METHOD_NAMES.has(access.name.text) && !ownCallable)
5269
5793
  return null;
5270
5794
  // Optional forms (`obj.cb?.()`, `obj?.cb()`) belong to the chain
@@ -5275,15 +5799,20 @@ function lowerDynReceiverMethodCall(lowerer, call, access) {
5275
5799
  if (call.arguments.some((a) => ts.isSpreadElement(a))) {
5276
5800
  lowerer.unsupported("SC1090", call, "spread arguments in calls through 'unknown' values");
5277
5801
  }
5802
+ const receiverLocal = lowerer.declareHiddenLocal("%dynCallReceiver", DYN);
5803
+ const receiver = { kind: "varRef", localId: receiverLocal.id, type: DYN, loc };
5278
5804
  const member = {
5279
5805
  kind: "dynKeyGet",
5280
5806
  key: { kind: "strLit", value: access.name.text, type: STRING, loc: locOf(access) },
5281
- value: recv,
5807
+ value: receiver,
5282
5808
  type: DYN,
5283
5809
  loc: locOf(access),
5284
5810
  };
5285
5811
  const args = call.arguments.map((a) => lowerer.lowerExprExpecting(a, DYN));
5286
- 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
+ };
5287
5816
  }
5288
5817
  /** Prototype method names of the checked-dynamic tree-representable kinds (String, Array,
5289
5818
  * Object, Function, Number prototypes): a dyn receiver call on one of
@@ -5310,7 +5839,8 @@ const DYN_PROTO_METHOD_NAMES = new Set([
5310
5839
  * is-not-a-function where the kind's prototype lacks the name, and
5311
5840
  * fences LOUDLY on real-but-unimplemented pairs. */
5312
5841
  const DYN_DISPATCH_METHODS = new Set([
5313
- "apply", "call",
5842
+ "segment", "containing", "resolvedOptions", "test", "exec",
5843
+ "apply", "bind", "call",
5314
5844
  "push", "pop", "shift", "unshift", "slice", "at",
5315
5845
  "indexOf", "lastIndexOf", "includes", "join", "concat", "reverse", "sort",
5316
5846
  "forEach", "map", "filter", "some", "every", "find", "findIndex",
@@ -5328,7 +5858,7 @@ const DYN_DISPATCH_METHODS = new Set([
5328
5858
  "setEncoding", "setDefaultEncoding", "setTimeout", "read", "isPaused",
5329
5859
  "writeHead", "setHeader", "getHeader", "hasHeader", "removeHeader",
5330
5860
  "getHeaders", "getHeaderNames", "appendHeader", "flushHeaders",
5331
- "append", "delete", "get", "getSetCookie", "has", "set",
5861
+ "add", "append", "delete", "get", "getSetCookie", "has", "set",
5332
5862
  "writeContinue", "writeEarlyHints", "cork", "uncork", "addTrailers",
5333
5863
  "ref", "unref", "address", "setNoDelay", "setKeepAlive", "connect",
5334
5864
  "resetAndDestroy", "destroySoon",
@@ -5366,7 +5896,7 @@ const DYN_DISPATCH_METHODS = new Set([
5366
5896
  ]);
5367
5897
  export function lowerDynDispatchMethodCall(lowerer, call, access, recv, arrayReceiver) {
5368
5898
  const method = access.name.text;
5369
- if (!DYN_DISPATCH_METHODS.has(method) || call.questionDotToken || access.questionDotToken)
5899
+ if ((!DYN_DISPATCH_METHODS.has(method) && !isJsSourceFile(call.getSourceFile())) || lowerer.chainBlocked(call, access))
5370
5900
  return null;
5371
5901
  if (call.arguments.some((arg) => ts.isSpreadElement(arg))) {
5372
5902
  lowerer.unsupported("SC1090", call, "spread arguments in calls through 'unknown' values");
@@ -5492,7 +6022,8 @@ function lowerArrayIsArrayCall(lowerer, call, access) {
5492
6022
  // over side-effect-free reads (the operand re-evaluates/drops, the
5493
6023
  // `in`-operator fold discipline). dyn/caught/jsval arms have no
5494
6024
  // static tag answer and keep the narrow-first fence.
5495
- const def = lowerer.unions.get(arg.type.unionId);
6025
+ const unionId = arg.type.unionId;
6026
+ const def = lowerer.unions.get(unionId);
5496
6027
  const opaque = !def || def.arms.some((a) => a.kind === "dyn" || a.kind === "caught" || a.kind === "jsval");
5497
6028
  const arrayTags = lowerer.arrayValueTags(arg.type.unionId);
5498
6029
  const freeRead = arg.kind === "varRef" || arg.kind === "recordGet" || arg.kind === "fieldGet";
@@ -5504,7 +6035,7 @@ function lowerArrayIsArrayCall(lowerer, call, access) {
5504
6035
  }
5505
6036
  if (!opaque && freeRead && arrayTags.length > 1) {
5506
6037
  return arrayTags
5507
- .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 }))
5508
6039
  .reduce((left, right) => ({ kind: "logical", op: "||", left, right, type: BOOL, loc }));
5509
6040
  }
5510
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)`);
@@ -5725,6 +6256,13 @@ function lowerClassHasOwnPropertyCall(lowerer, call, access) {
5725
6256
  else
5726
6257
  return null; // computed static names — the answer isn't static
5727
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
+ }
5728
6266
  return { kind: "boolLit", value: own.has(key), type: BOOL, loc: locOf(call) };
5729
6267
  }
5730
6268
  /** Side-effect-free receiver test for the CONSTANT primitive-prototype
@@ -5939,6 +6477,12 @@ function implicitReceiverOverloadReturn(lowerer, expr) {
5939
6477
  function reconcileOverloadReturn(lowerer, expr, call) {
5940
6478
  const rsig = lowerer.checker.getResolvedSignature(expr);
5941
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
+ }
5942
6486
  const resolvedOverload = rsig && rdecl &&
5943
6487
  (ts.isFunctionDeclaration(rdecl) || ts.isMethodDeclaration(rdecl)) &&
5944
6488
  !rdecl.body
@@ -6145,7 +6689,7 @@ export function lowerTaggedTemplate(lowerer, expr) {
6145
6689
  }
6146
6690
  function loweredTemplateStrings(lowerer, expr, cooked, loc) {
6147
6691
  // Normal runtime construction keeps this array aligned with the current
6148
- // 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
6149
6693
  // pre-sparse layout in LLVM and crashed as soon as a tag read its strings.
6150
6694
  const type = arrayOf(STRING);
6151
6695
  const key = `templateStringsGlobal:${loc.file}:${expr.template.getStart()}`;
@@ -6202,7 +6746,7 @@ export function isTopLevelFnSymbol(lowerer, ident) {
6202
6746
  const decl = symbol ? lowerer.checker.declarationsOf(symbol)[0] : undefined;
6203
6747
  return (!!decl &&
6204
6748
  ts.isFunctionDeclaration(decl) &&
6205
- (ts.isSourceFile(decl.parent) || lowerer.nsBlocks.get(decl.parent) === "flattened"));
6749
+ (ts.isSourceFile(decl.parent) || (decl.parent !== undefined && lowerer.nsBlocks.get(decl.parent) === "flattened")));
6206
6750
  }
6207
6751
  /** Nested `function name(...) {...}`: declare the mutable function binding
6208
6752
  * before lowering its body, then initialize it with the lifted closure.
@@ -6244,6 +6788,22 @@ export function lowerNestedFunctionDecl(lowerer, stmt) {
6244
6788
  export function lambdaSignature(lowerer, node) {
6245
6789
  if (!node.body)
6246
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
+ }
6247
6807
  if (node.typeParameters) {
6248
6808
  // Generic function-like forms monomorphize only where a static home
6249
6809
  // exists: top-level generic function declarations, generic methods
@@ -6269,8 +6829,8 @@ export function lambdaSignature(lowerer, node) {
6269
6829
  : lowerer.declaredReturnType(node, node);
6270
6830
  ret = lowerer.runtimeOptionalFunctionReturnType(node, ret);
6271
6831
  // A contextually-typed arrow/function EXPRESSION whose slot signature
6272
- // returns a UNION the inferred return doesn't spell adopts the slot's
6273
- // 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
6274
6834
  // an `(n) => Promise<void> | void` field must RETURN that union — the
6275
6835
  // body's returns coerce into it per return site (arm values wrap;
6276
6836
  // width-coercible records rebuild into their arm — the runJobs
@@ -6284,6 +6844,9 @@ export function lambdaSignature(lowerer, node) {
6284
6844
  // returns coerce; the spawn-wrapper ABI still returns a promise).
6285
6845
  // jsval-returning bodies stay out (adoption would force validated
6286
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.
6287
6850
  const isAsyncLike = !ts.isMethodDeclaration(node) &&
6288
6851
  node.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword) === true;
6289
6852
  const innerRet = isAsyncLike && ret.kind === "promise" ? ret.inner : ret;
@@ -6308,8 +6871,8 @@ export function lambdaSignature(lowerer, node) {
6308
6871
  ? lowerer.mapTypeOf(lowerer.checker.getReturnTypeOfSignature(ctxSigs[0]))
6309
6872
  : null;
6310
6873
  const ctxRet = isAsyncLike && ctxRetRaw?.kind === "promise" ? ctxRetRaw.inner : ctxRetRaw;
6311
- if (ctxRet?.kind === "union" &&
6312
- (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))) {
6313
6876
  ret = isAsyncLike ? { kind: "promise", inner: ctxRet } : ctxRet;
6314
6877
  }
6315
6878
  // A VOID slot discards the callback's result (TS's void-returning
@@ -6329,51 +6892,29 @@ export function lambdaSignature(lowerer, node) {
6329
6892
  ret = VOID;
6330
6893
  }
6331
6894
  }
6895
+ ret = lowerer.contextualFunctionReturns.get(node) ?? ret;
6332
6896
  // A plain JS function reading `arguments` receives one hidden dyn
6333
6897
  // array. With named parameters, the array contains every actual
6334
6898
  // argument and only ES modules are admitted: sloppy-mode arguments
6335
6899
  // alias named parameters. Arrows inherit the enclosing `arguments`.
6336
6900
  const hasRest = shapes.some((s) => s.mode === "rest" || s.mode === "dynRest" || s.mode === "islandRest");
6337
6901
  const usesArguments = !hasRest &&
6338
- (ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node)) &&
6902
+ (ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node) || ts.isMethodDeclaration(node)) &&
6339
6903
  isJsSourceFile(node.getSourceFile()) &&
6340
6904
  bodyReadsArguments(node);
6341
- if (usesArguments && node.parameters.length > 0) {
6342
- if (!isNodeEsmFile(node.getSourceFile())) {
6343
- 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
+ }
6344
6912
  }
6345
6913
  shapes.push({ type: DYN, mode: "arguments" });
6346
6914
  }
6347
6915
  const funcType = funcTypeFromParamShapes(shapes, ret);
6348
- if (usesArguments)
6349
- funcType.rest = true;
6350
6916
  return { shapes, funcType };
6351
6917
  }
6352
- /** Does this function's OWN body read `arguments`? Nested plain functions
6353
- * and methods have their own `arguments` (the walk skips them); arrows
6354
- * see the enclosing one (the walk descends). Exported for the lowerer's
6355
- * dynFallbackType: tsgo does not synthesize the `arguments` rest
6356
- * parameter into inferred signatures (5.9.3 did — its param-count
6357
- * mismatch was the detector), so the 7 world asks the BODY directly. */
6358
- export function bodyReadsArguments(fn) {
6359
- let found = false;
6360
- if (fn.body === undefined)
6361
- return false;
6362
- // Iterative walk (walkPreorder): function bodies can hold pathologically
6363
- // deep expression chains that a recursive visit would die on.
6364
- ts.walkPreorder(fn.body, (n) => {
6365
- if (ts.isIdentifier(n) && n.text === "arguments" && !(ts.isPropertyAccessExpression(n.parent) && n.parent.name === n)) {
6366
- found = true;
6367
- return "stop";
6368
- }
6369
- if ((ts.isFunctionExpression(n) || ts.isFunctionDeclaration(n) || ts.isMethodDeclaration(n)) &&
6370
- n !== fn) {
6371
- return "skip"; // own `arguments` scope
6372
- }
6373
- return undefined;
6374
- });
6375
- return found;
6376
- }
6377
6918
  /** Lifts an arrow function / function expression / nested declaration /
6378
6919
  * object-literal shorthand method to a module-level function and yields
6379
6920
  * the `closure` expression creating it. */
@@ -6421,10 +6962,17 @@ export function lowerLambda(lowerer, node) {
6421
6962
  lowerer.fnStack.push(fnCtx);
6422
6963
  try {
6423
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
+ }
6424
6972
  // The synthetic trailing dyn-array param carries `arguments`.
6425
6973
  // Parameterized functions receive all actual arguments; zero-param
6426
6974
  // functions receive the same array through their rest ABI.
6427
- 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")) {
6428
6976
  const argsLocal = lowerer.declareHiddenLocal("%arguments", DYN);
6429
6977
  params.push({ localId: argsLocal.id, name: "%arguments", type: DYN });
6430
6978
  fnCtx.argumentsLocal = argsLocal;
@@ -6461,7 +7009,9 @@ export function lowerLambda(lowerer, node) {
6461
7009
  }
6462
7010
  }
6463
7011
  else {
6464
- 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);
6465
7015
  // An async concise body whose value is itself a promise
6466
7016
  // (`async () => p`): the async machinery RESOLVES the returned
6467
7017
  // thenable into the function's own promise — lowerReturnValue's
@@ -6491,6 +7041,8 @@ export function lowerLambda(lowerer, node) {
6491
7041
  const ctx = lowerer.ctx;
6492
7042
  const lifted = {
6493
7043
  name: fnName,
7044
+ sourceName: jsFuncNameOf(node) ?? "<anonymous>",
7045
+ ...(!isAsync && !isGenerator && (ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node)) ? { ownsPrototype: true } : {}),
6494
7046
  params,
6495
7047
  returnType: bodyReturn,
6496
7048
  locals: ctx.locals,
@@ -6569,9 +7121,8 @@ export function lowerLambda(lowerer, node) {
6569
7121
  * becomes the catch binding, and a handler VALUE would need a
6570
7122
  * caught-typed closure parameter, which cannot exist. finally takes
6571
7123
  * any () => void closure (its callback sees no arguments). then takes
6572
- * exactly one FULFILLMENT handler (any closure value of the settled
6573
- * value's type — the two-argument onRejected form stays fenced toward
6574
- * .catch); a promise-returning handler flattens through the async
7124
+ * a fulfillment handler and optionally a rejection handler; a
7125
+ * promise-returning handler flattens through the async
6575
7126
  * return path, a receiver rejection passes through untouched (the
6576
7127
  * wrapper's await re-throws it), and a handler throw rejects the
6577
7128
  * result — the spec's onFulfilled rules by construction. Null for
@@ -6670,9 +7221,9 @@ export function lowerPromiseMethodCall(lowerer, call, access) {
6670
7221
  };
6671
7222
  const passthrough = call.arguments.length === 0 ||
6672
7223
  (call.arguments.length === 1 && isAbsentHandler(call.arguments[0]));
6673
- if (call.arguments.length !== 1 && !passthrough) {
7224
+ if (call.arguments.length !== 1 && !passthrough && !(member === "then" && call.arguments.length === 2)) {
6674
7225
  lowerer.noLowering(`${member} with ${call.arguments.length} arguments`, call, member === "then"
6675
- ? "the supported form takes exactly one fulfillment handler — chain .catch(...) for the rejection half"
7226
+ ? "the supported form takes a fulfillment handler and an optional rejection handler"
6676
7227
  : `the supported form takes exactly one ${member === "catch" ? "inline handler" : "callback"}`);
6677
7228
  }
6678
7229
  // The receiver evaluates FIRST, in the enclosing function, like JS.
@@ -6744,6 +7295,142 @@ export function lowerPromiseMethodCall(lowerer, call, access) {
6744
7295
  }
6745
7296
  }
6746
7297
  if (member === "then") {
7298
+ if (call.arguments.length === 2) {
7299
+ const fulfilledNode = call.arguments[0];
7300
+ const rejectedNode = call.arguments[1];
7301
+ const fulfilledAbsent = isAbsentHandler(fulfilledNode);
7302
+ const rejectedAbsent = isAbsentHandler(rejectedNode);
7303
+ const resultT = lowerer.mapTypeOf(lowerer.typeOf(call));
7304
+ if (resultT?.kind !== "promise") {
7305
+ lowerer.noLowering("then with these handlers", call, "the result must be a representable promise");
7306
+ }
7307
+ const R = resultT.inner;
7308
+ if (!fulfilledAbsent && inner.kind === "jsval")
7309
+ markJsvalHandlerParams(lowerer, fulfilledNode);
7310
+ if (!fulfilledAbsent && inner.kind === "moduleNs")
7311
+ markModuleNsHandlerParams(lowerer, fulfilledNode, inner);
7312
+ const boxHandler = (node, allowDirect) => {
7313
+ const value = lowerer.lowerExpr(node);
7314
+ if (allowDirect && value.type.kind === "func" && value.type.params.length <= 1 &&
7315
+ (value.type.params.length === 0 || (inner.kind !== "void" && typeEquals(value.type.params[0], inner)))) {
7316
+ return { value, direct: true, returnsPromise: value.type.ret.kind === "promise" };
7317
+ }
7318
+ if (value.type.kind === "dyn")
7319
+ return { value, direct: false, returnsPromise: false };
7320
+ if (value.type.kind === "func" && value.type.params.length <= 1 &&
7321
+ canBoxFuncIntoDyn(value.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) {
7322
+ return { value: { kind: "dynFrom", value, type: DYN, loc }, direct: false, returnsPromise: value.type.ret.kind === "promise" };
7323
+ }
7324
+ lowerer.unsupported("SC1090", node, "then handlers that cannot be called with one value");
7325
+ };
7326
+ // Evaluate both callback expressions before the wrapper runs, in source order.
7327
+ const fulfilled = fulfilledAbsent ? null : boxHandler(fulfilledNode, true);
7328
+ const rejected = rejectedAbsent ? null : boxHandler(rejectedNode, false);
7329
+ const fnName = `%fn${lowerer.lambdaCounter++}_then2`;
7330
+ const paramTypes = [promT, ...(fulfilled ? [fulfilled.value.type] : []), ...(rejected ? [DYN] : [])];
7331
+ const funcType = { kind: "func", params: paramTypes, ret: resultT };
7332
+ const fnCtx = newFnCtx(true, null, funcType, R);
7333
+ fnCtx.isAsync = true;
7334
+ lowerer.fnStack.push(fnCtx);
7335
+ try {
7336
+ const pLocal = lowerer.declareHiddenLocal("p", promT);
7337
+ const fLocal = fulfilled ? lowerer.declareHiddenLocal("f", fulfilled.value.type) : null;
7338
+ const rLocal = rejected ? lowerer.declareHiddenLocal("r", DYN) : null;
7339
+ const eLocal = lowerer.declareHiddenLocal("e", CAUGHT);
7340
+ const vLocal = inner.kind === "void" ? null : lowerer.declareHiddenLocal("v", inner);
7341
+ const awaitE = {
7342
+ kind: "awaitExpr",
7343
+ value: { kind: "varRef", localId: pLocal.id, type: promT, loc },
7344
+ type: inner,
7345
+ loc,
7346
+ };
7347
+ const tryBody = vLocal
7348
+ ? [{ kind: "varDecl", localId: vLocal.id, init: awaitE, loc }]
7349
+ : [{ kind: "exprStmt", expr: awaitE, loc }];
7350
+ const resultOf = (value, returnsPromise = false) => {
7351
+ const settled = value.type.kind === "promise"
7352
+ ? { kind: "awaitExpr", value, type: value.type.inner, loc }
7353
+ : returnsPromise
7354
+ ? { kind: "libCall", fn: "async.awaitDyn", args: [value], type: DYN, loc }
7355
+ : value;
7356
+ return R.kind === "void"
7357
+ ? [{ kind: "exprStmt", expr: settled, loc }, { kind: "return", value: null, loc }]
7358
+ : [{ kind: "return", value: lowerer.coerceInto(call, settled, R), loc }];
7359
+ };
7360
+ const rejectedCall = rLocal ? {
7361
+ kind: "dynCall",
7362
+ callee: { kind: "varRef", localId: rLocal.id, type: DYN, loc },
7363
+ calleeName: jsFuncNameOf(rejectedNode) ?? "onRejected",
7364
+ args: [{ kind: "caughtToDyn", value: { kind: "varRef", localId: eLocal.id, type: CAUGHT, loc }, type: DYN, loc }],
7365
+ type: DYN,
7366
+ loc,
7367
+ } : null;
7368
+ const catchBody = rejectedCall
7369
+ ? resultOf(rejectedCall, rejected?.returnsPromise)
7370
+ : [{ kind: "rethrow", localId: eLocal.id, loc }];
7371
+ const body = [{ kind: "tryCatch", tryBody, catchBody, catchLocalId: eLocal.id, finallyBody: null, loc }];
7372
+ // The fulfillment callback sits after the catch so a throw from it
7373
+ // rejects the result instead of reaching onRejected.
7374
+ if (fLocal) {
7375
+ const settled = vLocal
7376
+ ? { kind: "varRef", localId: vLocal.id, type: inner, loc }
7377
+ : dynUndefinedExpr(loc);
7378
+ if (fulfilled.direct && fLocal.type.kind === "func") {
7379
+ body.push(...resultOf({
7380
+ kind: "callValue",
7381
+ callee: { kind: "varRef", localId: fLocal.id, type: fLocal.type, loc },
7382
+ args: fLocal.type.params.length === 0 ? [] : [settled],
7383
+ type: fLocal.type.ret,
7384
+ loc,
7385
+ }));
7386
+ }
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
+ }
7392
+ const arg = settled.type.kind === "dyn" ? settled
7393
+ : { kind: "dynFrom", value: settled, type: DYN, loc };
7394
+ body.push(...resultOf({
7395
+ kind: "dynCall",
7396
+ callee: { kind: "varRef", localId: fLocal.id, type: DYN, loc },
7397
+ calleeName: jsFuncNameOf(fulfilledNode) ?? "onFulfilled",
7398
+ args: [arg], type: DYN, loc,
7399
+ }, fulfilled?.returnsPromise));
7400
+ }
7401
+ }
7402
+ else if (vLocal) {
7403
+ body.push(...resultOf({ kind: "varRef", localId: vLocal.id, type: inner, loc }));
7404
+ }
7405
+ else if (R.kind === "void") {
7406
+ body.push({ kind: "return", value: null, loc });
7407
+ }
7408
+ else {
7409
+ body.push({ kind: "return", value: lowerer.coerceInto(call, dynUndefinedExpr(loc), R), loc });
7410
+ }
7411
+ const ctx = lowerer.ctx;
7412
+ const lifted = {
7413
+ name: fnName,
7414
+ params: [
7415
+ { localId: pLocal.id, name: pLocal.name, type: promT },
7416
+ ...(fLocal ? [{ localId: fLocal.id, name: fLocal.name, type: fLocal.type }] : []),
7417
+ ...(rLocal ? [{ localId: rLocal.id, name: rLocal.name, type: DYN }] : []),
7418
+ ],
7419
+ returnType: R,
7420
+ locals: ctx.locals,
7421
+ captures: ctx.captures,
7422
+ body,
7423
+ loc,
7424
+ async: true,
7425
+ };
7426
+ lowerer.liftedFns.push(lifted);
7427
+ const closure = { kind: "closure", fnName, captures: ctx.captureSources, type: funcType, loc };
7428
+ return { kind: "callValue", callee: closure, args: [receiver, ...(fulfilled ? [fulfilled.value] : []), ...(rejected ? [rejected.value] : [])], type: resultT, loc };
7429
+ }
7430
+ finally {
7431
+ lowerer.fnStack.pop();
7432
+ }
7433
+ }
6747
7434
  // The settled value is an island HANDLE: an inline handler's
6748
7435
  // unannotated parameter binds it as jsval, whatever the checker's
6749
7436
  // contextual type spelled (a module-namespace type has no mapping —
@@ -7567,7 +8254,8 @@ export function recordKeysArrayCall(lowerer, receiver, argIr, shape, loc) {
7567
8254
  loc,
7568
8255
  };
7569
8256
  const finalize = () => {
7570
- const current = lowerer.shapes.get(argIr.shapeId) ?? shape;
8257
+ const latest = lowerer.shapes.get(argIr.shapeId);
8258
+ const current = latest !== undefined ? latest : shape;
7571
8259
  const body = [
7572
8260
  { kind: "varDecl", localId: "out.0", init: { kind: "arrayLit", elems: [], type: resultT, loc }, loc },
7573
8261
  ];
@@ -7617,10 +8305,11 @@ export function recordKeysArrayCall(lowerer, receiver, argIr, shape, loc) {
7617
8305
  return { kind: "call", callee: helper, args: [receiver], type: resultT, loc };
7618
8306
  }
7619
8307
  /** Interned `%obj.hasOwn.<n>(r, k)` — Object.hasOwn's membership walk
7620
- * over a signature-free record shape: the key compares against each
8308
+ * over a record shape: the key compares against each
7621
8309
  * declared field name, undefined-armed fields answering by their tag
7622
8310
  * (a key is own exactly when Object.keys would list it — the two share
7623
- * 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. */
7624
8313
  function recordHasOwnHelper(lowerer, shapeId, loc) {
7625
8314
  const key = `obj.hasOwn:${shapeId}`;
7626
8315
  const existing = lowerer.arrHofHelpers.get(key);
@@ -7654,7 +8343,10 @@ function recordHasOwnHelper(lowerer, shapeId, loc) {
7654
8343
  loc,
7655
8344
  });
7656
8345
  }
7657
- 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 });
7658
8350
  lowerer.liftedFns.push({
7659
8351
  name: helper,
7660
8352
  params: [
@@ -7834,6 +8526,42 @@ function lowerObjectStaticCall(lowerer, call, access) {
7834
8526
  if (!lowerer.isStdlibGlobal(access.expression, "Object"))
7835
8527
  return null;
7836
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
+ }
7837
8565
  const cacheKeys = lowerRequireCacheKeys(lowerer, call, member);
7838
8566
  if (cacheKeys)
7839
8567
  return cacheKeys;
@@ -7935,23 +8663,14 @@ function lowerObjectStaticCall(lowerer, call, access) {
7935
8663
  }
7936
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)");
7937
8665
  }
7938
- // Object.create — the null-prototype DICTIONARY (`Object.create(null)`
7939
- // then keyed assignment, the memo-table idiom prettier's index/
7940
- // group-mode maps spell) and, under --dynamic, the engine's own
7941
- // Object.create for engine-held prototypes. Everything else is a
7942
- // NAMED fence: the compiled representations have no prototype chain,
7943
- // and the own-copy stand-in would answer WRONG observably — Node's
7944
- // Object.keys/inspect/JSON of the created object list NO own keys,
7945
- // and mutating the prototype afterwards is visible through the
7946
- // 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.
7947
8669
  if (member === "create") {
7948
8670
  if (call.arguments.some((a) => ts.isSpreadElement(a))) {
7949
8671
  lowerer.noLowering("Object.create with spread arguments", call);
7950
8672
  }
7951
- if (call.arguments.length >= 2) {
7952
- lowerer.noLowering("Object.create with a properties-descriptor argument", call, "create first, then assign: const o = Object.create(null); o.k = v");
7953
- }
7954
- if (call.arguments.length !== 1) {
8673
+ if (call.arguments.length < 1 || call.arguments.length > 2) {
7955
8674
  lowerer.noLowering(`Object.create with ${call.arguments.length} arguments`, call);
7956
8675
  }
7957
8676
  const loc = locOf(call);
@@ -7960,6 +8679,8 @@ function lowerObjectStaticCall(lowerer, call, access) {
7960
8679
  protoNode = protoNode.expression;
7961
8680
  const nullProto = protoNode.kind === ts.SyntaxKind.NullKeyword;
7962
8681
  if (lowerer.dynamic) {
8682
+ if (call.arguments.length === 2)
8683
+ lowerer.noLowering("Object.create with properties under --dynamic", call);
7963
8684
  // The checker types the result `any` — an ENGINE value under
7964
8685
  // --dynamic — and the engine's own Object.create answers with
7965
8686
  // REAL prototype semantics: reads delegate LIVE, writes shadow,
@@ -7980,15 +8701,40 @@ function lowerObjectStaticCall(lowerer, call, access) {
7980
8701
  }
7981
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");
7982
8703
  }
7983
- if (nullProto) {
8704
+ if (nullProto && call.arguments.length === 1) {
7984
8705
  return { kind: "libCall", fn: "dyn.objCreateNullProto", args: [], type: DYN, loc };
7985
8706
  }
7986
- const proto = lowerer.lowerExpr(protoNode);
7987
- 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);
7988
8722
  }
7989
8723
  // `Object.assign(fn, { props })` whose RESULT type maps to the hybrid
7990
8724
  // (function-with-properties) record: the chalk-shape CONSTRUCTOR.
7991
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
+ }
7992
8738
  const hybrid = lowerObjectAssignHybrid(lowerer, call);
7993
8739
  if (hybrid)
7994
8740
  return hybrid;
@@ -8035,7 +8781,9 @@ function lowerObjectStaticCall(lowerer, call, access) {
8035
8781
  if (tProbe?.type.kind === "dyn") {
8036
8782
  const loc = locOf(call);
8037
8783
  const target = lowerer.lowerExpr(call.arguments[0]);
8038
- 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);
8039
8787
  if (target.type.kind === "dyn" && source.type.kind === "dyn") {
8040
8788
  return { kind: "libCall", fn: "dyn.assign", args: [target, source], type: DYN, loc };
8041
8789
  }
@@ -8112,7 +8860,9 @@ function lowerObjectStaticCall(lowerer, call, access) {
8112
8860
  const argNode = sources[i];
8113
8861
  const spread = ts.isSpreadElement(argNode);
8114
8862
  const srcNode = spread ? argNode.expression : argNode;
8115
- 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);
8116
8866
  if (src.type.kind !== "dyn") {
8117
8867
  ok = false;
8118
8868
  break;
@@ -8149,22 +8899,75 @@ function lowerObjectStaticCall(lowerer, call, access) {
8149
8899
  }
8150
8900
  return null;
8151
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
+ }
8152
8946
  // Object.defineProperties over a CHECKED-DYNAMIC target (test/common's
8153
8947
  // _mustCallInner copying name/length onto the mustCall wrapper): the
8154
- // runtime turns each descriptor's `value` into a plain own property on
8155
- // the dyn node (OBJ members; FUNC nodes carry an own-property table) —
8156
- // 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.
8157
8951
  // The result is the target, like JS. Typed targets keep the fence:
8158
8952
  // static shapes have no property table to extend.
8159
8953
  if (member === "defineProperties" && call.arguments.length === 2 &&
8160
8954
  !call.arguments.some((a) => ts.isSpreadElement(a))) {
8161
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
+ }
8162
8961
  // A FUNCTION-typed target boxes through the dyn boundary: the
8163
8962
  // property table lives on the CLOSURE (shared by every box of this
8164
8963
  // function value), so defining through a fresh box sticks — the
8165
8964
  // wrapper returned later reads the same table.
8166
8965
  if (target && target.type.kind === "func" &&
8167
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)) {
8168
8971
  target = { kind: "dynFrom", value: target, type: DYN, loc: locOf(call.arguments[0]) };
8169
8972
  }
8170
8973
  if (target?.type.kind === "dyn") {
@@ -8175,12 +8978,39 @@ function lowerObjectStaticCall(lowerer, call, access) {
8175
8978
  }
8176
8979
  return null;
8177
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
+ }
8178
9004
  // Object.freeze: on a FRESH literal (object or array) the result IS
8179
9005
  // the argument — no alias exists, so the frozen bit is unobservable
8180
9006
  // (writes through the Readonly<T> result are compile errors, and no
8181
9007
  // other reference can write). Primitives pass through per ES2015.
8182
9008
  // Aliased objects keep a fence: a later write through the original
8183
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
+ }
8184
9014
  if (member === "freeze") {
8185
9015
  if (call.arguments.length !== 1 || ts.isSpreadElement(call.arguments[0])) {
8186
9016
  lowerer.noLowering(`Object.freeze with ${call.arguments.length} arguments`, call);
@@ -8190,14 +9020,18 @@ function lowerObjectStaticCall(lowerer, call, access) {
8190
9020
  while (ts.isParenthesizedExpression(inner) || ts.isAsExpression(inner))
8191
9021
  inner = inner.expression;
8192
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) };
8193
9025
  if (ts.isObjectLiteralExpression(inner) || ts.isArrayLiteralExpression(inner)) {
8194
9026
  return value; // fresh — freeze is identity here, honestly
8195
9027
  }
8196
9028
  if (value.type.kind === "string" || value.type.kind === "f64" ||
8197
- value.type.kind === "bool" || value.type.kind === "symbol" ||
9029
+ value.type.kind === "bool" || value.type.kind === "symbol" || value.type.kind === "bigint" ||
8198
9030
  isUnitType(value.type)) {
8199
9031
  return value; // ES2015: freeze of a primitive is the primitive
8200
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;
8201
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");
8202
9036
  }
8203
9037
  // `Object.hasOwn(r, k)` over a RECORD receiver: a record's own-key set
@@ -8206,9 +9040,9 @@ function lowerObjectStaticCall(lowerer, call, access) {
8206
9040
  // fields answer by their runtime tag — the explicit-undefined-is-absent
8207
9041
  // stance: an omitted optional field holds the undefined arm and reads
8208
9042
  // as NOT own, exactly Node's absent key (an EXPLICIT `k: undefined`
8209
- // diverges — documented next to the child-env/JSON rule). Tuple,
8210
- // index-signature (overflow membership lives in the runtime map), and
8211
- // 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
8212
9046
  // do too.
8213
9047
  if (member === "hasOwn" && call.arguments.length === 2 && !call.arguments.some((a) => ts.isSpreadElement(a))) {
8214
9048
  const recvNode = call.arguments[0];
@@ -8217,33 +9051,30 @@ function lowerObjectStaticCall(lowerer, call, access) {
8217
9051
  // A CHECKED-DYNAMIC receiver (the JS file-scope object-literal
8218
9052
  // identity story): the runtime dyn probe — OBJ member presence, ARR
8219
9053
  // index bounds, Node's ToObject TypeError on nullish.
8220
- if (probed?.type.kind === "dyn") {
9054
+ if (probed?.type.kind === "dyn" || (probed && isDynTypedRefType(probed.type)) || (probed?.type.kind === "func" && lowerer.dynConvertible(probed.type))) {
8221
9055
  const loc = locOf(call);
8222
- const receiver = lowerer.lowerExpr(recvNode);
8223
- let key = lowerer.lowerExpr(keyNode);
8224
- if (key.type.kind === "f64" || key.type.kind === "bool" || key.type.kind === "dyn") {
8225
- key = { kind: "toString", operand: key, type: STRING, loc: locOf(keyNode) };
8226
- }
8227
- 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)
8228
9064
  return null;
8229
9065
  return { kind: "libCall", fn: "dyn.hasOwn", args: [receiver, key], type: BOOL, loc };
8230
9066
  }
8231
9067
  if (probed?.type.kind !== "record")
8232
9068
  return null;
8233
9069
  const shape = lowerer.shapes.get(probed.type.shapeId);
8234
- if (!shape || shape.tuple || shape.indexValue || shapeHasAccessorSlots(shape))
9070
+ if (!shape || shape.tuple || shapeHasAccessorSlots(shape))
8235
9071
  return null;
8236
9072
  const loc = locOf(call);
8237
9073
  const receiver = lowerer.lowerExpr(recvNode);
8238
9074
  if (receiver.type.kind !== "record")
8239
9075
  return null; // probe/lower drift: keep the fence
8240
- let key = lowerer.lowerExpr(keyNode);
8241
- // Number/boolean/dyn keys stringify — ToPropertyKey, the keyed-write
8242
- // path's rule; symbol and composite keys keep the fence.
8243
- if (key.type.kind === "f64" || key.type.kind === "bool" || key.type.kind === "dyn") {
8244
- key = { kind: "toString", operand: key, type: STRING, loc: locOf(keyNode) };
8245
- }
8246
- if (key.type.kind !== "string")
9076
+ const key = ownPropertyKey(lowerer, lowerer.lowerExpr(keyNode));
9077
+ if (!key)
8247
9078
  return null;
8248
9079
  const helper = recordHasOwnHelper(lowerer, receiver.type.shapeId, loc);
8249
9080
  return { kind: "call", callee: helper, args: [receiver, key], type: BOOL, loc };
@@ -8305,8 +9136,11 @@ function lowerObjectStaticCall(lowerer, call, access) {
8305
9136
  const isDyn = probed?.type.kind === "dyn";
8306
9137
  // Unit-typed arguments (Object.keys(null)) ride the same runtime
8307
9138
  // walk: it throws Node's catchable TypeError.
8308
- const isUnit = probed !== null && probed !== undefined && isUnitType(probed.type);
8309
- 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))) {
8310
9144
  const fn = member === "keys" ? "dyn.objKeys" : member === "values" ? "dyn.objValues" : "dyn.objEntries";
8311
9145
  let v = lowerer.lowerExpr(argNode);
8312
9146
  if (v.type.kind !== "dyn")
@@ -8335,6 +9169,19 @@ function lowerObjectStaticCall(lowerer, call, access) {
8335
9169
  if (shapeHasAccessorSlots(shape)) {
8336
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)`);
8337
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
+ }
8338
9185
  if (shape.indexValue) {
8339
9186
  // Index-signature (overflow-carrying) shapes: the runtime walk —
8340
9187
  // declared fields first, then the overflow in JS own-key order
@@ -8345,7 +9192,7 @@ function lowerObjectStaticCall(lowerer, call, access) {
8345
9192
  const resultT = lowerer.irTypeOf(call);
8346
9193
  if (resultT.kind !== "array")
8347
9194
  lowerer.badType(call, lowerer.typeOf(call)); // defensive
8348
- const receiver = lowerer.lowerExpr(argNode);
9195
+ const receiver = objectEnumerationReceiver(lowerer, lowerer.lowerExpr(argNode), argIr, loc);
8349
9196
  if (member === "keys") {
8350
9197
  // The keys walk is shared with for-in (which iterates exactly the
8351
9198
  // keys Object.keys answers — one construction, one intern key).
@@ -8387,7 +9234,8 @@ function lowerObjectStaticCall(lowerer, call, access) {
8387
9234
  loc,
8388
9235
  };
8389
9236
  const finalize = () => {
8390
- const current = lowerer.shapes.get(argIr.shapeId) ?? shape;
9237
+ const latest = lowerer.shapes.get(argIr.shapeId);
9238
+ const current = latest !== undefined ? latest : shape;
8391
9239
  const body = [
8392
9240
  { kind: "varDecl", localId: "out.0", init: { kind: "arrayLit", elems: [], type: resultT, loc }, loc },
8393
9241
  ];
@@ -8541,6 +9389,8 @@ export function lowerFunction(lowerer, decl) {
8541
9389
  appendImplicitUndefinedReturn(lowerer, body, bodyReturn, locOf(decl));
8542
9390
  const fn = {
8543
9391
  name: sig.name,
9392
+ sourceName: decl.name?.text ?? "<anonymous>",
9393
+ ...(!sig.isAsync && !sig.generator ? { ownsPrototype: true } : {}),
8544
9394
  params,
8545
9395
  returnType: bodyReturn,
8546
9396
  locals: lowerer.ctx.locals,
@@ -8665,8 +9515,27 @@ function lowerObjectAssignHybrid(lowerer, call) {
8665
9515
  export function lowerRecordFieldCall(lowerer, call, access) {
8666
9516
  if (lowerer.chainBlocked(call))
8667
9517
  return null;
8668
- if (lowerer.mapTypeOf(lowerer.typeOf(access.expression))?.kind !== "record")
8669
- 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
+ }
8670
9539
  const target = lowerer.fieldTarget(access);
8671
9540
  let callee = target ? lowerer.fieldGetExpr(target, locOf(access), access) : null;
8672
9541
  if (!callee)
@@ -8865,7 +9734,7 @@ function nullishValueUnitOf(lowerer, sym) {
8865
9734
  // the no-storage family never claims it.
8866
9735
  if (!decl || !ts.isVariableDeclaration(decl) || !ts.isIdentifier(decl.name) ||
8867
9736
  decl.getSourceFile().isDeclarationFile || decl.initializer === undefined ||
8868
- !ts.isVariableStatement(decl.parent.parent)) {
9737
+ !ts.isVariableStatement(decl.parent?.parent)) {
8869
9738
  return null;
8870
9739
  }
8871
9740
  const unit = nullishExprUnitOf(lowerer, decl.initializer);
@@ -9051,7 +9920,7 @@ export function deadUnmappableBinding(lowerer, sym, decl) {
9051
9920
  // lowerVarDeclList's contract requires a lowered statement for it, so
9052
9921
  // the no-storage family never claims it (catch bindings sit outside a
9053
9922
  // variable statement too and stay out the same way).
9054
- if (!ts.isVariableStatement(decl.parent.parent))
9923
+ if (!ts.isVariableStatement(decl.parent?.parent))
9055
9924
  return false;
9056
9925
  const sf = decl.getSourceFile();
9057
9926
  if (sf.isDeclarationFile || isJsSourceFile(sf))
@@ -9229,11 +10098,11 @@ export function bindingGenericFnInfoOf(lowerer, decl, fnNode) {
9229
10098
  lowerer.unsupported("SC1031", param);
9230
10099
  }
9231
10100
  }
9232
- 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)
9233
10102
  const info = {
9234
10103
  decl: fnNode,
9235
10104
  baseName: name,
9236
- qualifiedName: lowerer.qualify(decl.getSourceFile(), nsPathPrefix(stmt, decl) + name),
10105
+ qualifiedName: lowerer.qualify(decl.getSourceFile(), nsPathPrefix(stmt ?? decl, decl) + name),
9237
10106
  typeParams,
9238
10107
  instances: new Map(),
9239
10108
  };
@@ -9365,6 +10234,88 @@ function arrowSignatureOf(lowerer, node) {
9365
10234
  const declaration = lowerer.checker.signatureDeclaration(signatures[0]);
9366
10235
  return declaration !== undefined && ts.isArrowFunction(declaration) ? signatures[0] : null;
9367
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
+ }
9368
10319
  /** `arrow.apply(thisArg, dynArgs)` for a fixed-arity compiled arrow. Arrows
9369
10320
  * ignore `thisArg` and surplus arguments by language definition; declared
9370
10321
  * parameters validate from the dynamic array in order. */
@@ -9443,7 +10394,6 @@ function lowerObjLitGenericMethodCall(lowerer, call, access) {
9443
10394
  thisT.kind !== "dyn" &&
9444
10395
  thisT.kind !== "jsval" &&
9445
10396
  (!thisArg || ts.isIdentifier(thisArg) || ts.isLiteralExpression(thisArg) ||
9446
- thisArg.kind === ts.SyntaxKind.UndefinedKeyword ||
9447
10397
  thisArg.kind === ts.SyntaxKind.NullKeyword ||
9448
10398
  isUnitType(thisT));
9449
10399
  if (provablyNot) {
@@ -9482,19 +10432,25 @@ function lowerObjLitGenericMethodCall(lowerer, call, access) {
9482
10432
  }
9483
10433
  const found = objLitGenericFnNodeOf(lowerer, propSym);
9484
10434
  if (!found) {
10435
+ const arrowBind = lowerInlineArrowBind(lowerer, call, access);
10436
+ if (arrowBind !== null)
10437
+ return arrowBind;
9485
10438
  const arrowApply = lowerArrowFunctionApply(lowerer, call, access);
9486
10439
  if (arrowApply !== null)
9487
10440
  return arrowApply;
9488
- // Function.prototype.apply/call/bind spelled through a FUNCTION
9489
- // receiver: compiled functions are direct calls with no runtime
9490
- // `this`/arguments object to re-route — name the working spelling
9491
- // instead of a class-receiver hint (or an SC2020 recitation) no
9492
- // function value can follow. Before the stdlib decline: these ARE
9493
- // stdlib members (CallableFunction), but the pointed message is
9494
- // the honest one.
10441
+ // Convertible native callables use the checked invocation boundary
10442
+ // for Function.prototype methods, including their call-time receiver.
9495
10443
  if ((name === "apply" || name === "call" || name === "bind") &&
9496
10444
  lowerer.checker.getCallSignatures(recvT).length > 0) {
9497
- 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)`);
9498
10454
  }
9499
10455
  // STANDARD-LIBRARY generic members (Promise.then, Object.
9500
10456
  // defineProperty, Array-augmentation methods) are the lib fence's
@@ -9531,7 +10487,16 @@ function lowerObjLitGenericMethodCall(lowerer, call, access) {
9531
10487
  export function lowerObjectMethodCall(lowerer, call, access) {
9532
10488
  if (lowerer.chainBlocked(access, call))
9533
10489
  return null;
9534
- 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;
9535
10500
  if (mappedReceiver?.kind === "union") {
9536
10501
  const dispatched = lowerUnionObjectMethodCall(lowerer, call, access, mappedReceiver) ??
9537
10502
  lowerUnionObjectDynFieldCall(lowerer, call, access, mappedReceiver);
@@ -9544,15 +10509,16 @@ export function lowerObjectMethodCall(lowerer, call, access) {
9544
10509
  ? (() => {
9545
10510
  const arms = lowerer.unions.get(mappedReceiver.unionId)?.arms ?? [];
9546
10511
  const objects = arms.filter((arm) => arm.kind === "object");
9547
- return objects.length === 1 && arms.every((arm) => arm.kind === "object" || isUnitType(arm))
9548
- ? 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
9549
10515
  : null;
9550
10516
  })()
9551
10517
  : null;
9552
10518
  if (receiverIr === null)
9553
10519
  return null;
9554
10520
  const lowerReceiver = () => {
9555
- const receiver = lowerer.lowerExpr(access.expression);
10521
+ const receiver = specializedReceiver ?? lowerer.lowerExpr(access.expression);
9556
10522
  const optional = lowerer.runtimeOptionalPropertyReceiver(access.expression, receiver, receiverIr, access.name.text);
9557
10523
  if (optional !== null)
9558
10524
  return optional;
@@ -9561,7 +10527,7 @@ export function lowerObjectMethodCall(lowerer, call, access) {
9561
10527
  if (helper !== null)
9562
10528
  return { kind: "call", callee: helper, args: [receiver], type: receiverIr, loc: locOf(access.expression) };
9563
10529
  }
9564
- return receiver;
10530
+ return receiver.type.kind === "dyn" ? lowerer.coerceInto(access.expression, receiver, receiverIr) : receiver;
9565
10531
  };
9566
10532
  const info = lowerer.classes.get(receiverIr.className);
9567
10533
  if (!info)
@@ -9588,7 +10554,7 @@ export function lowerObjectMethodCall(lowerer, call, access) {
9588
10554
  if (info && !found) {
9589
10555
  const gfound = findGenericMethodOn(lowerer, info, access.name.text);
9590
10556
  if (gfound)
9591
- return lowerClassGenericMethodCall(lowerer, call, access, info, gfound);
10557
+ return lowerClassGenericMethodCall(lowerer, call, access, info, gfound, lowerReceiver());
9592
10558
  }
9593
10559
  // A FUNC-, nullable-FUNC-, or DYN-typed FIELD in call position:
9594
10560
  // `this.cb()` — the ctor-assigned callback field (countdown.js's
@@ -9604,13 +10570,22 @@ export function lowerObjectMethodCall(lowerer, call, access) {
9604
10570
  ? (() => {
9605
10571
  const arms = lowerer.unions.get(fieldType.unionId)?.arms ?? [];
9606
10572
  const funcs = arms.filter((arm) => arm.kind === "func");
9607
- return funcs.length === 1 && arms.every((arm) => arm.kind === "func" || isUnitType(arm))
9608
- ? 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
9609
10576
  : null;
9610
10577
  })()
9611
10578
  : null;
9612
10579
  if (fieldType && (callableType !== null || fieldType.kind === "dyn")) {
9613
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 });
9614
10589
  let callee = target ? lowerer.fieldGetExpr(target, locOf(access), access) : null;
9615
10590
  if (callee?.type.kind === "union" && callableType !== null) {
9616
10591
  const helper = lowerer.narrowedArmHelper(callee.type.unionId, callableType, locOf(access));
@@ -9619,15 +10594,24 @@ export function lowerObjectMethodCall(lowerer, call, access) {
9619
10594
  }
9620
10595
  }
9621
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
+ }
9622
10606
  const args = completeFuncValueArgs(lowerer, call, callee.type, locOf(call));
9623
- 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 });
9624
10608
  }
9625
10609
  if (callee?.type.kind === "dyn") {
9626
10610
  if (call.arguments.some((a) => ts.isSpreadElement(a))) {
9627
10611
  lowerer.unsupported("SC1090", call, "spread arguments in calls through 'unknown' values");
9628
10612
  }
9629
10613
  const args = call.arguments.map((a) => lowerer.lowerExprExpecting(a, DYN));
9630
- 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 });
9631
10615
  }
9632
10616
  }
9633
10617
  return null;
@@ -9635,18 +10619,25 @@ export function lowerObjectMethodCall(lowerer, call, access) {
9635
10619
  if (!info || !found)
9636
10620
  return null;
9637
10621
  const method = access.name.text;
9638
- if (found.declarer.builtinError) {
9639
- // The one builtin method: Error.prototype.toString, a runtime
9640
- // implementation called directly (overriding it is fenced, so no
9641
- // dispatch can ever be needed). Receiver BORROWED by the libCall.
10622
+ if (isClassCallback(lowerer, info, method)) {
10623
+ const loc = locOf(call);
9642
10624
  const receiver = lowerReceiver();
9643
- return {
9644
- kind: "libCall",
9645
- fn: "error.toString",
9646
- args: [lowerer.upcastTo(receiver, found.declarer.def.name)],
9647
- type: STRING,
9648
- loc: locOf(call),
9649
- };
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());
9650
10641
  }
9651
10642
  // An ABSTRACT nearest declaration with no concrete override below the
9652
10643
  // static class: no implementation exists for a direct call to target.
@@ -9719,7 +10710,10 @@ function lowerUnionObjectMethodCall(lowerer, call, access, receiverT) {
9719
10710
  function paramAbisEqual(left, right) {
9720
10711
  return left.length === right.length && left.every((shape, i) => {
9721
10712
  const other = right[i];
9722
- 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"));
9723
10717
  });
9724
10718
  }
9725
10719
  /** The JS-class sibling of union method dispatch: every arm stores the
@@ -9744,6 +10738,8 @@ function lowerUnionObjectDynFieldCall(lowerer, call, access, receiverT) {
9744
10738
  const loc = locOf(call);
9745
10739
  const receiver = lowerer.coerceInto(access.expression, lowerer.lowerExpr(access.expression), receiverT);
9746
10740
  const key = `${receiverT.unionId}:dyn-field:${field}`;
10741
+ const receiverLocal = lowerer.declareHiddenLocal("%unionCallReceiver", receiverT);
10742
+ const receiverRef = varRef(receiverLocal.id, receiverT, loc);
9747
10743
  let helper = lowerer.unionCallHelpers.get(key);
9748
10744
  if (!helper) {
9749
10745
  helper = `%union.call.${lowerer.unionCallHelpers.size}`;
@@ -9796,9 +10792,12 @@ function lowerUnionObjectDynFieldCall(lowerer, call, access, receiverT) {
9796
10792
  const locals = params.map((param) => ({ id: param.localId, name: param.name, type: param.type, mutable: false }));
9797
10793
  lowerer.liftedFns.push({ name: helper, params, returnType: DYN, locals, body, loc });
9798
10794
  }
9799
- const callee = { kind: "call", callee: helper, args: [receiver], type: DYN, loc };
10795
+ const callee = { kind: "call", callee: helper, args: [receiverRef], type: DYN, loc };
9800
10796
  const args = call.arguments.map((arg) => lowerer.lowerExprExpecting(arg, DYN));
9801
- 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
+ };
9802
10801
  }
9803
10802
  function unionObjectMethodHelper(lowerer, sourceCall, receiverT, method, plans, shapes, resultT, loc) {
9804
10803
  const key = `${receiverT.unionId}:${method}:${shapes.map((shape) => `${shape.mode}:${typeKey(shape.type)}`).join(",")}:${typeKey(resultT)}`;
@@ -9820,13 +10819,7 @@ function unionObjectMethodHelper(lowerer, sourceCall, receiverT, method, plans,
9820
10819
  };
9821
10820
  let invoke;
9822
10821
  if (plan.found.declarer.builtinError) {
9823
- invoke = {
9824
- kind: "libCall",
9825
- fn: "error.toString",
9826
- args: [lowerer.upcastTo(concrete, plan.found.declarer.def.name)],
9827
- type: STRING,
9828
- loc,
9829
- };
10822
+ invoke = errorToStringCall(lowerer, concrete);
9830
10823
  }
9831
10824
  else if (lowerer.overrideBelow(plan.info, method)) {
9832
10825
  lowerer.noteVirtualEdge(plan.info, method);