@scriptc/compiler 0.1.7 → 0.2.1

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 (1043) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +98 -39
  2. package/ambient/scriptc-overrides.d.ts +10 -6
  3. package/ambient/scriptc.d.ts +15 -0
  4. package/dist/backend/build-cache.d.ts +1 -3
  5. package/dist/backend/build-cache.js +3 -22
  6. package/dist/backend/build-cache.js.map +1 -1
  7. package/dist/backend/cache-root.d.ts +3 -0
  8. package/dist/backend/cache-root.js +23 -0
  9. package/dist/backend/cache-root.js.map +1 -0
  10. package/dist/backend/cycle-analysis.d.ts +15 -0
  11. package/dist/backend/cycle-analysis.js +108 -0
  12. package/dist/backend/cycle-analysis.js.map +1 -0
  13. package/dist/backend/cycle-analysis.test.js +124 -0
  14. package/dist/backend/cycle-analysis.test.js.map +1 -0
  15. package/dist/backend/executable-features.d.ts +4 -0
  16. package/dist/backend/executable-features.js +42 -0
  17. package/dist/backend/executable-features.js.map +1 -0
  18. package/dist/backend/external-c.d.ts +5 -27
  19. package/dist/backend/external-c.js +5 -40
  20. package/dist/backend/external-c.js.map +1 -1
  21. package/dist/backend/ffi-callbacks.d.ts +2 -3
  22. package/dist/backend/ffi-callbacks.js +2 -3
  23. package/dist/backend/ffi-callbacks.js.map +1 -1
  24. package/dist/backend/library-identity-markers.d.ts +4 -9
  25. package/dist/backend/library-identity-markers.js +11 -49
  26. package/dist/backend/library-identity-markers.js.map +1 -1
  27. package/dist/backend/library-pack.d.ts +5 -0
  28. package/dist/backend/library-pack.js +123 -0
  29. package/dist/backend/library-pack.js.map +1 -0
  30. package/dist/backend/link-plan-core.d.ts +20 -0
  31. package/dist/backend/link-plan-core.js +18 -0
  32. package/dist/backend/link-plan-core.js.map +1 -0
  33. package/dist/backend/link-plan.d.ts +1 -1
  34. package/dist/backend/link-plan.js +16 -17
  35. package/dist/backend/link-plan.js.map +1 -1
  36. package/dist/backend/link-trace.d.ts +2 -0
  37. package/dist/backend/link-trace.js +24 -0
  38. package/dist/backend/link-trace.js.map +1 -0
  39. package/dist/backend/linker.js +1 -1
  40. package/dist/backend/linker.js.map +1 -1
  41. package/dist/backend/literals.d.ts +9 -0
  42. package/dist/backend/literals.js +35 -0
  43. package/dist/backend/literals.js.map +1 -0
  44. package/dist/backend/literals.test.d.ts +1 -0
  45. package/dist/backend/literals.test.js +53 -0
  46. package/dist/backend/literals.test.js.map +1 -0
  47. package/dist/backend/llvm/blocks.d.ts +2 -0
  48. package/dist/backend/llvm/blocks.js +9 -4
  49. package/dist/backend/llvm/blocks.js.map +1 -1
  50. package/dist/backend/llvm/blocks.test.d.ts +1 -0
  51. package/dist/backend/llvm/blocks.test.js +91 -0
  52. package/dist/backend/llvm/blocks.test.js.map +1 -0
  53. package/dist/backend/llvm/classes.d.ts +14 -8
  54. package/dist/backend/llvm/classes.js +88 -30
  55. package/dist/backend/llvm/classes.js.map +1 -1
  56. package/dist/backend/llvm/common.d.ts +5 -1
  57. package/dist/backend/llvm/common.js +45 -4
  58. package/dist/backend/llvm/common.js.map +1 -1
  59. package/dist/backend/llvm/debug-info.js +2 -7
  60. package/dist/backend/llvm/debug-info.js.map +1 -1
  61. package/dist/backend/llvm/debug-info.test.d.ts +1 -0
  62. package/dist/backend/llvm/debug-info.test.js +110 -0
  63. package/dist/backend/llvm/debug-info.test.js.map +1 -0
  64. package/dist/backend/llvm/dyn.d.ts +21 -2
  65. package/dist/backend/llvm/dyn.js +647 -251
  66. package/dist/backend/llvm/dyn.js.map +1 -1
  67. package/dist/backend/llvm/emitter.d.ts +596 -1
  68. package/dist/backend/llvm/emitter.js +769 -425
  69. package/dist/backend/llvm/emitter.js.map +1 -1
  70. package/dist/backend/llvm/emitter.test.d.ts +1 -0
  71. package/dist/backend/llvm/emitter.test.js +179 -0
  72. package/dist/backend/llvm/emitter.test.js.map +1 -0
  73. package/dist/backend/llvm/expr-async.js +23 -14
  74. package/dist/backend/llvm/expr-async.js.map +1 -1
  75. package/dist/backend/llvm/expr-bytes.d.ts +2 -2
  76. package/dist/backend/llvm/expr-bytes.js +60 -31
  77. package/dist/backend/llvm/expr-bytes.js.map +1 -1
  78. package/dist/backend/llvm/expr-callbacks.d.ts +1 -1
  79. package/dist/backend/llvm/expr-callbacks.js +25 -22
  80. package/dist/backend/llvm/expr-callbacks.js.map +1 -1
  81. package/dist/backend/llvm/expr-calls.js +136 -35
  82. package/dist/backend/llvm/expr-calls.js.map +1 -1
  83. package/dist/backend/llvm/expr-containers.d.ts +1 -1
  84. package/dist/backend/llvm/expr-containers.js +43 -14
  85. package/dist/backend/llvm/expr-containers.js.map +1 -1
  86. package/dist/backend/llvm/expr-context.d.ts +5 -260
  87. package/dist/backend/llvm/expr-control.js +10 -6
  88. package/dist/backend/llvm/expr-control.js.map +1 -1
  89. package/dist/backend/llvm/expr-dispatch.d.ts +1 -1
  90. package/dist/backend/llvm/expr-dispatch.js +2 -0
  91. package/dist/backend/llvm/expr-dispatch.js.map +1 -1
  92. package/dist/backend/llvm/expr-dynamic.js +78 -81
  93. package/dist/backend/llvm/expr-dynamic.js.map +1 -1
  94. package/dist/backend/llvm/expr-island.d.ts +1 -1
  95. package/dist/backend/llvm/expr-island.js +11 -7
  96. package/dist/backend/llvm/expr-island.js.map +1 -1
  97. package/dist/backend/llvm/expr-primitives.d.ts +1 -1
  98. package/dist/backend/llvm/expr-primitives.js +62 -31
  99. package/dist/backend/llvm/expr-primitives.js.map +1 -1
  100. package/dist/backend/llvm/expr-primitives.test.js +1 -1
  101. package/dist/backend/llvm/expr-records.d.ts +5 -1
  102. package/dist/backend/llvm/expr-records.js +54 -7
  103. package/dist/backend/llvm/expr-records.js.map +1 -1
  104. package/dist/backend/llvm/expr-stream-bridges.d.ts +4 -4
  105. package/dist/backend/llvm/expr-stream-bridges.js +220 -131
  106. package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
  107. package/dist/backend/llvm/expr-stream-bridges.test.d.ts +1 -0
  108. package/dist/backend/llvm/expr-stream-bridges.test.js +55 -0
  109. package/dist/backend/llvm/expr-stream-bridges.test.js.map +1 -0
  110. package/dist/backend/llvm/expr-stream-callbacks.d.ts +1 -1
  111. package/dist/backend/llvm/expr-stream-callbacks.js +12 -12
  112. package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
  113. package/dist/backend/llvm/layouts.d.ts +19 -0
  114. package/dist/backend/llvm/layouts.js +12 -0
  115. package/dist/backend/llvm/layouts.js.map +1 -0
  116. package/dist/backend/llvm/lib-abi.d.ts +19 -0
  117. package/dist/backend/llvm/lib-abi.js +82 -0
  118. package/dist/backend/llvm/lib-abi.js.map +1 -0
  119. package/dist/backend/llvm/lib-connect.d.ts +2 -0
  120. package/dist/backend/llvm/lib-connect.js +51 -0
  121. package/dist/backend/llvm/lib-connect.js.map +1 -0
  122. package/dist/backend/llvm/lib-datagram.d.ts +2 -0
  123. package/dist/backend/llvm/lib-datagram.js +135 -0
  124. package/dist/backend/llvm/lib-datagram.js.map +1 -0
  125. package/dist/backend/llvm/lib-dispatch.js +50 -6
  126. package/dist/backend/llvm/lib-dispatch.js.map +1 -1
  127. package/dist/backend/llvm/lib-filesystem.js +30 -18
  128. package/dist/backend/llvm/lib-filesystem.js.map +1 -1
  129. package/dist/backend/llvm/lib-http2.d.ts +2 -0
  130. package/dist/backend/llvm/lib-http2.js +215 -0
  131. package/dist/backend/llvm/lib-http2.js.map +1 -0
  132. package/dist/backend/llvm/lib-lookup.d.ts +2 -0
  133. package/dist/backend/llvm/lib-lookup.js +39 -0
  134. package/dist/backend/llvm/lib-lookup.js.map +1 -0
  135. package/dist/backend/llvm/lib-network.js +25 -2
  136. package/dist/backend/llvm/lib-network.js.map +1 -1
  137. package/dist/backend/llvm/lib-process.js +44 -19
  138. package/dist/backend/llvm/lib-process.js.map +1 -1
  139. package/dist/backend/llvm/lib-shared.js +162 -3
  140. package/dist/backend/llvm/lib-shared.js.map +1 -1
  141. package/dist/backend/llvm/lib-stream.js +3 -2
  142. package/dist/backend/llvm/lib-stream.js.map +1 -1
  143. package/dist/backend/llvm/lib-test.d.ts +2 -0
  144. package/dist/backend/llvm/lib-test.js +34 -0
  145. package/dist/backend/llvm/lib-test.js.map +1 -0
  146. package/dist/backend/llvm/lib-tls.d.ts +2 -0
  147. package/dist/backend/llvm/lib-tls.js +82 -0
  148. package/dist/backend/llvm/lib-tls.js.map +1 -0
  149. package/dist/backend/llvm/shapes.d.ts +10 -9
  150. package/dist/backend/llvm/shapes.js +42 -131
  151. package/dist/backend/llvm/shapes.js.map +1 -1
  152. package/dist/backend/llvm/unsupported.d.ts +1 -0
  153. package/dist/backend/llvm/unsupported.js +1 -2
  154. package/dist/backend/llvm/unsupported.js.map +1 -1
  155. package/dist/backend/llvm/walkers.js +1 -7
  156. package/dist/backend/llvm/walkers.js.map +1 -1
  157. package/dist/backend/mangle.d.ts +2 -2
  158. package/dist/backend/mangle.js +16 -5
  159. package/dist/backend/mangle.js.map +1 -1
  160. package/dist/backend/{c/may-throw.d.ts → may-throw.d.ts} +1 -1
  161. package/dist/backend/{c/may-throw.js → may-throw.js} +51 -46
  162. package/dist/backend/may-throw.js.map +1 -0
  163. package/dist/backend/may-throw.test.d.ts +1 -0
  164. package/dist/backend/may-throw.test.js +58 -0
  165. package/dist/backend/may-throw.test.js.map +1 -0
  166. package/dist/backend/native-codegen-core.d.ts +22 -0
  167. package/dist/backend/native-codegen-core.js +44 -0
  168. package/dist/backend/native-codegen-core.js.map +1 -0
  169. package/dist/backend/native-codegen.d.ts +3 -19
  170. package/dist/backend/native-codegen.js +5 -44
  171. package/dist/backend/native-codegen.js.map +1 -1
  172. package/dist/backend/native-codegen.test.js +2 -2
  173. package/dist/backend/native-codegen.test.js.map +1 -1
  174. package/dist/backend/native-link-info-core.d.ts +94 -0
  175. package/dist/backend/native-link-info-core.js +62 -0
  176. package/dist/backend/native-link-info-core.js.map +1 -0
  177. package/dist/backend/native-link-info.d.ts +3 -88
  178. package/dist/backend/native-link-info.js +12 -243
  179. package/dist/backend/native-link-info.js.map +1 -1
  180. package/dist/backend/native-link-info.test.js +41 -146
  181. package/dist/backend/native-link-info.test.js.map +1 -1
  182. package/dist/backend/native-toolchain.d.ts +12 -30
  183. package/dist/backend/native-toolchain.js +83 -233
  184. package/dist/backend/native-toolchain.js.map +1 -1
  185. package/dist/backend/native-toolchain.test.js +77 -5
  186. package/dist/backend/native-toolchain.test.js.map +1 -1
  187. package/dist/backend/native-tools.d.ts +24 -0
  188. package/dist/backend/native-tools.js +33 -0
  189. package/dist/backend/native-tools.js.map +1 -0
  190. package/dist/backend/object-localize.js +19 -8
  191. package/dist/backend/object-localize.js.map +1 -1
  192. package/dist/backend/object-localize.test.js +22 -0
  193. package/dist/backend/object-localize.test.js.map +1 -1
  194. package/dist/backend/runtime-abi.d.ts +2 -2
  195. package/dist/backend/runtime-abi.js +2 -2
  196. package/dist/backend/runtime-pack-core.d.ts +101 -0
  197. package/dist/backend/runtime-pack-core.js +172 -0
  198. package/dist/backend/runtime-pack-core.js.map +1 -0
  199. package/dist/backend/runtime-pack-native.d.ts +21 -0
  200. package/dist/backend/runtime-pack-native.js +73 -0
  201. package/dist/backend/runtime-pack-native.js.map +1 -0
  202. package/dist/backend/runtime-pack-targets.test.js +1 -1
  203. package/dist/backend/runtime-pack.d.ts +3 -83
  204. package/dist/backend/runtime-pack.js +8 -151
  205. package/dist/backend/runtime-pack.js.map +1 -1
  206. package/dist/backend/runtime-pack.test.js +24 -1
  207. package/dist/backend/runtime-pack.test.js.map +1 -1
  208. package/dist/backend/target-diagnostics.d.ts +22 -0
  209. package/dist/backend/target-diagnostics.js +108 -0
  210. package/dist/backend/target-diagnostics.js.map +1 -0
  211. package/dist/backend/target-platform.d.ts +15 -0
  212. package/dist/backend/target-platform.js +72 -0
  213. package/dist/backend/target-platform.js.map +1 -0
  214. package/dist/backend/targets.d.ts +13 -4
  215. package/dist/backend/targets.js +103 -34
  216. package/dist/backend/targets.js.map +1 -1
  217. package/dist/backend/targets.test.js +72 -4
  218. package/dist/backend/targets.test.js.map +1 -1
  219. package/dist/backend/toolchain-environment.d.ts +6 -0
  220. package/dist/backend/toolchain-environment.js +99 -0
  221. package/dist/backend/toolchain-environment.js.map +1 -0
  222. package/dist/backend/vendor-archives.d.ts +1 -9
  223. package/dist/backend/vendor-archives.js +2 -9
  224. package/dist/backend/vendor-archives.js.map +1 -1
  225. package/dist/backend/vendor-inputs.d.ts +9 -0
  226. package/dist/backend/vendor-inputs.js +10 -0
  227. package/dist/backend/vendor-inputs.js.map +1 -0
  228. package/dist/backend/warm-cache.d.ts +3 -0
  229. package/dist/backend/warm-cache.js +41 -0
  230. package/dist/backend/warm-cache.js.map +1 -0
  231. package/dist/cli/command.d.ts +3 -0
  232. package/dist/cli/command.js +328 -0
  233. package/dist/cli/command.js.map +1 -0
  234. package/dist/cli/host.d.ts +24 -0
  235. package/dist/cli/host.js +2 -0
  236. package/dist/cli/host.js.map +1 -0
  237. package/dist/cli/output-options.d.ts +26 -0
  238. package/dist/cli/output-options.js +60 -0
  239. package/dist/cli/output-options.js.map +1 -0
  240. package/dist/cli/paths.d.ts +12 -0
  241. package/dist/cli/paths.js +42 -0
  242. package/dist/cli/paths.js.map +1 -0
  243. package/dist/cli/usage.d.ts +74 -0
  244. package/dist/cli/usage.js +86 -0
  245. package/dist/cli/usage.js.map +1 -0
  246. package/dist/cli/wasi-paths.d.ts +8 -0
  247. package/dist/cli/wasi-paths.js +41 -0
  248. package/dist/cli/wasi-paths.js.map +1 -0
  249. package/dist/cli/wasi-runner.d.ts +2 -0
  250. package/dist/cli/wasi-runner.js +28 -0
  251. package/dist/cli/wasi-runner.js.map +1 -0
  252. package/dist/compat/fetch-profile.js +37 -7
  253. package/dist/compat/fetch-profile.js.map +1 -1
  254. package/dist/compile-types.d.ts +162 -0
  255. package/dist/compile-types.js +2 -0
  256. package/dist/compile-types.js.map +1 -0
  257. package/dist/coverage/report.js +11 -5
  258. package/dist/coverage/report.js.map +1 -1
  259. package/dist/coverage/surface-manifest.js +5 -2
  260. package/dist/coverage/surface-manifest.js.map +1 -1
  261. package/dist/diagnostics/diagnostic.js +5 -10
  262. package/dist/diagnostics/diagnostic.js.map +1 -1
  263. package/dist/executable/executable-cache.d.ts +3 -4
  264. package/dist/executable/executable-cache.js +5 -6
  265. package/dist/executable/executable-cache.js.map +1 -1
  266. package/dist/executable/executable-cache.test.js +16 -17
  267. package/dist/executable/executable-cache.test.js.map +1 -1
  268. package/dist/executable/prepare.d.ts +14 -0
  269. package/dist/executable/prepare.js +66 -0
  270. package/dist/executable/prepare.js.map +1 -0
  271. package/dist/ffi/ffi-manifest.d.ts +11 -4
  272. package/dist/ffi/ffi-manifest.js +170 -58
  273. package/dist/ffi/ffi-manifest.js.map +1 -1
  274. package/dist/ffi/ffi-manifest.test.d.ts +1 -0
  275. package/dist/ffi/ffi-manifest.test.js +111 -0
  276. package/dist/ffi/ffi-manifest.test.js.map +1 -0
  277. package/dist/format-integer.d.ts +3 -0
  278. package/dist/format-integer.js +14 -0
  279. package/dist/format-integer.js.map +1 -0
  280. package/dist/frontend/analysis.d.ts +5 -0
  281. package/dist/frontend/analysis.js +88 -0
  282. package/dist/frontend/analysis.js.map +1 -0
  283. package/dist/frontend/arguments-usage.d.ts +1 -3
  284. package/dist/frontend/arguments-usage.js.map +1 -1
  285. package/dist/frontend/builtin-modules.d.ts +1 -1
  286. package/dist/frontend/builtin-modules.js +1 -1
  287. package/dist/frontend/builtin-modules.js.map +1 -1
  288. package/dist/frontend/cjs-lexer.d.ts +4 -25
  289. package/dist/frontend/cjs-lexer.js +6 -806
  290. package/dist/frontend/cjs-lexer.js.map +1 -1
  291. package/dist/frontend/cjs-resolve.d.ts +5 -0
  292. package/dist/frontend/cjs-resolve.js +429 -0
  293. package/dist/frontend/cjs-resolve.js.map +1 -0
  294. package/dist/frontend/cjs-syntax.d.ts +26 -0
  295. package/dist/frontend/cjs-syntax.js +806 -0
  296. package/dist/frontend/cjs-syntax.js.map +1 -0
  297. package/dist/frontend/comptime-node.d.ts +4 -0
  298. package/dist/frontend/comptime-node.js +16 -0
  299. package/dist/frontend/comptime-node.js.map +1 -0
  300. package/dist/frontend/comptime-node.test.d.ts +1 -0
  301. package/dist/frontend/comptime-node.test.js +37 -0
  302. package/dist/frontend/comptime-node.test.js.map +1 -0
  303. package/dist/frontend/dts-paths.d.ts +3 -4
  304. package/dist/frontend/dts-paths.js +15 -8
  305. package/dist/frontend/dts-paths.js.map +1 -1
  306. package/dist/frontend/fork-target.js +2 -2
  307. package/dist/frontend/fork-target.js.map +1 -1
  308. package/dist/frontend/helper-tokens.d.ts +1 -0
  309. package/dist/frontend/helper-tokens.js +147 -0
  310. package/dist/frontend/helper-tokens.js.map +1 -0
  311. package/dist/frontend/helper-tokens.test.d.ts +1 -0
  312. package/dist/frontend/helper-tokens.test.js +35 -0
  313. package/dist/frontend/helper-tokens.test.js.map +1 -0
  314. package/dist/frontend/inferred-js-diagnostics.d.ts +5 -0
  315. package/dist/frontend/inferred-js-diagnostics.js +69 -0
  316. package/dist/frontend/inferred-js-diagnostics.js.map +1 -0
  317. package/dist/frontend/inferred-js-diagnostics.test.d.ts +1 -0
  318. package/dist/frontend/inferred-js-diagnostics.test.js +58 -0
  319. package/dist/frontend/inferred-js-diagnostics.test.js.map +1 -0
  320. package/dist/frontend/input-tracker.d.ts +5 -2
  321. package/dist/frontend/input-tracker.js +24 -3
  322. package/dist/frontend/input-tracker.js.map +1 -1
  323. package/dist/frontend/input-tracker.test.js +23 -0
  324. package/dist/frontend/input-tracker.test.js.map +1 -1
  325. package/dist/frontend/lib-contract.js +32 -24
  326. package/dist/frontend/lib-contract.js.map +1 -1
  327. package/dist/frontend/literal-values.d.ts +4 -0
  328. package/dist/frontend/literal-values.js +21 -0
  329. package/dist/frontend/literal-values.js.map +1 -0
  330. package/dist/frontend/literal-values.test.d.ts +1 -0
  331. package/dist/frontend/literal-values.test.js +91 -0
  332. package/dist/frontend/literal-values.test.js.map +1 -0
  333. package/dist/frontend/lowering/abstract-equality.d.ts +1 -1
  334. package/dist/frontend/lowering/abstract-equality.js +3 -0
  335. package/dist/frontend/lowering/abstract-equality.js.map +1 -1
  336. package/dist/frontend/lowering/array-indexed-mutation.js +11 -6
  337. package/dist/frontend/lowering/array-indexed-mutation.js.map +1 -1
  338. package/dist/frontend/lowering/array-values.d.ts +4 -1
  339. package/dist/frontend/lowering/array-values.js +43 -1
  340. package/dist/frontend/lowering/array-values.js.map +1 -1
  341. package/dist/frontend/lowering/callback-arg.js +1 -0
  342. package/dist/frontend/lowering/callback-arg.js.map +1 -1
  343. package/dist/frontend/lowering/class-callbacks.d.ts +12 -0
  344. package/dist/frontend/lowering/class-callbacks.js +74 -0
  345. package/dist/frontend/lowering/class-callbacks.js.map +1 -0
  346. package/dist/frontend/lowering/class-construction.d.ts +12 -0
  347. package/dist/frontend/lowering/class-construction.js +156 -0
  348. package/dist/frontend/lowering/class-construction.js.map +1 -0
  349. package/dist/frontend/lowering/class-descriptors.d.ts +10 -0
  350. package/dist/frontend/lowering/class-descriptors.js +114 -0
  351. package/dist/frontend/lowering/class-descriptors.js.map +1 -0
  352. package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +51 -0
  353. package/dist/frontend/lowering/class-dynamic-dispatch.js +1158 -0
  354. package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -0
  355. package/dist/frontend/lowering/class-dynamic-dispatch.test.d.ts +1 -0
  356. package/dist/frontend/lowering/class-dynamic-dispatch.test.js +93 -0
  357. package/dist/frontend/lowering/class-dynamic-dispatch.test.js.map +1 -0
  358. package/dist/frontend/lowering/class-instance-constructor.d.ts +7 -0
  359. package/dist/frontend/lowering/class-instance-constructor.js +67 -0
  360. package/dist/frontend/lowering/class-instance-constructor.js.map +1 -0
  361. package/dist/frontend/lowering/class-method-values.d.ts +13 -0
  362. package/dist/frontend/lowering/class-method-values.js +235 -0
  363. package/dist/frontend/lowering/class-method-values.js.map +1 -0
  364. package/dist/frontend/lowering/class-prototypes.d.ts +19 -0
  365. package/dist/frontend/lowering/class-prototypes.js +242 -0
  366. package/dist/frontend/lowering/class-prototypes.js.map +1 -0
  367. package/dist/frontend/lowering/class-runtime-statics.d.ts +8 -0
  368. package/dist/frontend/lowering/class-runtime-statics.js +66 -0
  369. package/dist/frontend/lowering/class-runtime-statics.js.map +1 -0
  370. package/dist/frontend/lowering/class-static-data.d.ts +6 -0
  371. package/dist/frontend/lowering/class-static-data.js +56 -0
  372. package/dist/frontend/lowering/class-static-data.js.map +1 -0
  373. package/dist/frontend/lowering/containers/buffer-numeric-methods.d.ts +4 -0
  374. package/dist/frontend/lowering/containers/buffer-numeric-methods.js +26 -0
  375. package/dist/frontend/lowering/containers/buffer-numeric-methods.js.map +1 -0
  376. package/dist/frontend/lowering/containers/bytes.d.ts +11 -7
  377. package/dist/frontend/lowering/containers/bytes.js +208 -163
  378. package/dist/frontend/lowering/containers/bytes.js.map +1 -1
  379. package/dist/frontend/lowering/containers/string-and-regexp.d.ts +2 -2
  380. package/dist/frontend/lowering/containers/string-and-regexp.js +58 -63
  381. package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
  382. package/dist/frontend/lowering/containers/string-replacement.d.ts +7 -0
  383. package/dist/frontend/lowering/containers/string-replacement.js +217 -0
  384. package/dist/frontend/lowering/containers/string-replacement.js.map +1 -0
  385. package/dist/frontend/lowering/error-methods.d.ts +14 -0
  386. package/dist/frontend/lowering/error-methods.js +177 -0
  387. package/dist/frontend/lowering/error-methods.js.map +1 -0
  388. package/dist/frontend/lowering/expressions/global-symbols.d.ts +6 -0
  389. package/dist/frontend/lowering/expressions/global-symbols.js +11 -0
  390. package/dist/frontend/lowering/expressions/global-symbols.js.map +1 -0
  391. package/dist/frontend/lowering/expressions/native-proxy.d.ts +7 -0
  392. package/dist/frontend/lowering/expressions/native-proxy.js +51 -0
  393. package/dist/frontend/lowering/expressions/native-proxy.js.map +1 -0
  394. package/dist/frontend/lowering/expressions/nullish-assignment.d.ts +6 -0
  395. package/dist/frontend/lowering/expressions/nullish-assignment.js +132 -0
  396. package/dist/frontend/lowering/expressions/nullish-assignment.js.map +1 -0
  397. package/dist/frontend/lowering/expressions/object-literals.d.ts +8 -8
  398. package/dist/frontend/lowering/expressions/object-literals.js +509 -183
  399. package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
  400. package/dist/frontend/lowering/expressions/optional-chains.d.ts +3 -4
  401. package/dist/frontend/lowering/expressions/optional-chains.js +88 -24
  402. package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
  403. package/dist/frontend/lowering/expressions/try-lower-expression.js +1 -0
  404. package/dist/frontend/lowering/expressions/try-lower-expression.js.map +1 -1
  405. package/dist/frontend/lowering/expressions/union-field-write.d.ts +8 -0
  406. package/dist/frontend/lowering/expressions/union-field-write.js +71 -0
  407. package/dist/frontend/lowering/expressions/union-field-write.js.map +1 -0
  408. package/dist/frontend/lowering/function-context.d.ts +101 -0
  409. package/dist/frontend/lowering/function-context.js +109 -0
  410. package/dist/frontend/lowering/function-context.js.map +1 -0
  411. package/dist/frontend/lowering/generator-delegation.d.ts +7 -0
  412. package/dist/frontend/lowering/generator-delegation.js +85 -0
  413. package/dist/frontend/lowering/generator-delegation.js.map +1 -0
  414. package/dist/frontend/lowering/generator-dynamic-dispatch.d.ts +11 -0
  415. package/dist/frontend/lowering/generator-dynamic-dispatch.js +143 -0
  416. package/dist/frontend/lowering/generator-dynamic-dispatch.js.map +1 -0
  417. package/dist/frontend/lowering/lib-boundary.d.ts +4 -1
  418. package/dist/frontend/lowering/lib-boundary.js +112 -20
  419. package/dist/frontend/lowering/lib-boundary.js.map +1 -1
  420. package/dist/frontend/lowering/lib-boundary.test.d.ts +1 -0
  421. package/dist/frontend/lowering/lib-boundary.test.js +45 -0
  422. package/dist/frontend/lowering/lib-boundary.test.js.map +1 -0
  423. package/dist/frontend/lowering/lower-array-sort.d.ts +1 -1
  424. package/dist/frontend/lowering/lower-assert.d.ts +1 -1
  425. package/dist/frontend/lowering/lower-assert.js.map +1 -1
  426. package/dist/frontend/lowering/lower-async-iteration.d.ts +1 -1
  427. package/dist/frontend/lowering/lower-async-iteration.js.map +1 -1
  428. package/dist/frontend/lowering/lower-builtin-values.d.ts +18 -0
  429. package/dist/frontend/lowering/lower-builtin-values.js +249 -0
  430. package/dist/frontend/lowering/lower-builtin-values.js.map +1 -0
  431. package/dist/frontend/lowering/lower-builtins.d.ts +33 -46
  432. package/dist/frontend/lowering/lower-builtins.js +676 -365
  433. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  434. package/dist/frontend/lowering/lower-calls.d.ts +28 -22
  435. package/dist/frontend/lowering/lower-calls.js +1660 -412
  436. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  437. package/dist/frontend/lowering/lower-classes.d.ts +95 -57
  438. package/dist/frontend/lowering/lower-classes.js +1491 -404
  439. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  440. package/dist/frontend/lowering/lower-comptime.d.ts +1 -1
  441. package/dist/frontend/lowering/lower-comptime.js +23 -32
  442. package/dist/frontend/lowering/lower-comptime.js.map +1 -1
  443. package/dist/frontend/lowering/lower-containers.d.ts +36 -32
  444. package/dist/frontend/lowering/lower-containers.js +925 -181
  445. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  446. package/dist/frontend/lowering/lower-dgram.d.ts +1 -1
  447. package/dist/frontend/lowering/lower-dgram.js +3 -2
  448. package/dist/frontend/lowering/lower-dgram.js.map +1 -1
  449. package/dist/frontend/lowering/lower-enums.d.ts +1 -1
  450. package/dist/frontend/lowering/lower-enums.js.map +1 -1
  451. package/dist/frontend/lowering/lower-event-emitter.d.ts +30 -1
  452. package/dist/frontend/lowering/lower-event-emitter.js +58 -26
  453. package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
  454. package/dist/frontend/lowering/lower-expando.d.ts +7 -1
  455. package/dist/frontend/lowering/lower-expando.js +14 -6
  456. package/dist/frontend/lowering/lower-expando.js.map +1 -1
  457. package/dist/frontend/lowering/lower-exprs.d.ts +37 -13
  458. package/dist/frontend/lowering/lower-exprs.js +2163 -863
  459. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  460. package/dist/frontend/lowering/lower-generators.d.ts +2 -5
  461. package/dist/frontend/lowering/lower-generators.js +88 -46
  462. package/dist/frontend/lowering/lower-generators.js.map +1 -1
  463. package/dist/frontend/lowering/lower-global-value.d.ts +7 -0
  464. package/dist/frontend/lowering/lower-global-value.js +17 -0
  465. package/dist/frontend/lowering/lower-global-value.js.map +1 -0
  466. package/dist/frontend/lowering/lower-inspect.d.ts +1 -1
  467. package/dist/frontend/lowering/lower-inspect.js +17 -8
  468. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  469. package/dist/frontend/lowering/lower-island.d.ts +7 -8
  470. package/dist/frontend/lowering/lower-island.js +66 -33
  471. package/dist/frontend/lowering/lower-island.js.map +1 -1
  472. package/dist/frontend/lowering/lower-mixins.d.ts +2 -2
  473. package/dist/frontend/lowering/lower-mixins.js +5 -3
  474. package/dist/frontend/lowering/lower-mixins.js.map +1 -1
  475. package/dist/frontend/lowering/lower-modules.d.ts +1 -1
  476. package/dist/frontend/lowering/lower-modules.js +445 -39
  477. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  478. package/dist/frontend/lowering/lower-modules.test.d.ts +1 -0
  479. package/dist/frontend/lowering/lower-modules.test.js +39 -0
  480. package/dist/frontend/lowering/lower-modules.test.js.map +1 -0
  481. package/dist/frontend/lowering/lower-namespaces.d.ts +1 -1
  482. package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
  483. package/dist/frontend/lowering/lower-node-module.d.ts +1 -1
  484. package/dist/frontend/lowering/lower-node-module.js +13 -10
  485. package/dist/frontend/lowering/lower-node-module.js.map +1 -1
  486. package/dist/frontend/lowering/lower-server.d.ts +1 -1
  487. package/dist/frontend/lowering/lower-server.js +6 -10
  488. package/dist/frontend/lowering/lower-server.js.map +1 -1
  489. package/dist/frontend/lowering/lower-stmts.d.ts +17 -17
  490. package/dist/frontend/lowering/lower-stmts.js +855 -514
  491. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  492. package/dist/frontend/lowering/lower-stream.d.ts +1 -1
  493. package/dist/frontend/lowering/lower-stream.js +20 -11
  494. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  495. package/dist/frontend/lowering/lower-test.d.ts +1 -1
  496. package/dist/frontend/lowering/lower-test.js.map +1 -1
  497. package/dist/frontend/lowering/lower-url.d.ts +6 -0
  498. package/dist/frontend/lowering/lower-url.js +77 -0
  499. package/dist/frontend/lowering/lower-url.js.map +1 -0
  500. package/dist/frontend/lowering/lowerer.d.ts +140 -190
  501. package/dist/frontend/lowering/lowerer.js +1193 -712
  502. package/dist/frontend/lowering/lowerer.js.map +1 -1
  503. package/dist/frontend/lowering/lowerer.test.d.ts +1 -0
  504. package/dist/frontend/lowering/lowerer.test.js +172 -0
  505. package/dist/frontend/lowering/lowerer.test.js.map +1 -0
  506. package/dist/frontend/lowering/native-ffi.d.ts +5 -0
  507. package/dist/frontend/lowering/native-ffi.js +40 -0
  508. package/dist/frontend/lowering/native-ffi.js.map +1 -0
  509. package/dist/frontend/lowering/object-enumeration-receiver.d.ts +7 -0
  510. package/dist/frontend/lowering/object-enumeration-receiver.js +33 -0
  511. package/dist/frontend/lowering/object-enumeration-receiver.js.map +1 -0
  512. package/dist/frontend/lowering/object-factory-new.d.ts +8 -0
  513. package/dist/frontend/lowering/object-factory-new.js +68 -0
  514. package/dist/frontend/lowering/object-factory-new.js.map +1 -0
  515. package/dist/frontend/lowering/optional-arguments.js +6 -1
  516. package/dist/frontend/lowering/optional-arguments.js.map +1 -1
  517. package/dist/frontend/lowering/pairs-snapshot.js +2 -1
  518. package/dist/frontend/lowering/pairs-snapshot.js.map +1 -1
  519. package/dist/frontend/lowering/runtime-optional-locals.d.ts +14 -0
  520. package/dist/frontend/lowering/runtime-optional-locals.js +41 -0
  521. package/dist/frontend/lowering/runtime-optional-locals.js.map +1 -0
  522. package/dist/frontend/lowering/runtime-optional-locals.test.d.ts +1 -0
  523. package/dist/frontend/lowering/runtime-optional-locals.test.js +85 -0
  524. package/dist/frontend/lowering/runtime-optional-locals.test.js.map +1 -0
  525. package/dist/frontend/lowering/sanitize-class-types.d.ts +8 -0
  526. package/dist/frontend/lowering/sanitize-class-types.js +79 -0
  527. package/dist/frontend/lowering/sanitize-class-types.js.map +1 -0
  528. package/dist/frontend/lowering/sanitize-class-types.test.d.ts +1 -0
  529. package/dist/frontend/lowering/sanitize-class-types.test.js +60 -0
  530. package/dist/frontend/lowering/sanitize-class-types.test.js.map +1 -0
  531. package/dist/frontend/lowering/static-this.d.ts +5 -1
  532. package/dist/frontend/lowering/static-this.js +28 -2
  533. package/dist/frontend/lowering/static-this.js.map +1 -1
  534. package/dist/frontend/lowering/string-index.d.ts +7 -0
  535. package/dist/frontend/lowering/string-index.js +39 -0
  536. package/dist/frontend/lowering/string-index.js.map +1 -0
  537. package/dist/frontend/lowering/surfaces.d.ts +10 -3
  538. package/dist/frontend/lowering/surfaces.js +86 -37
  539. package/dist/frontend/lowering/surfaces.js.map +1 -1
  540. package/dist/frontend/lowering/symbol-fields.d.ts +22 -0
  541. package/dist/frontend/lowering/symbol-fields.js +183 -0
  542. package/dist/frontend/lowering/symbol-fields.js.map +1 -0
  543. package/dist/frontend/lowering/symbol-methods.d.ts +7 -0
  544. package/dist/frontend/lowering/symbol-methods.js +30 -0
  545. package/dist/frontend/lowering/symbol-methods.js.map +1 -0
  546. package/dist/frontend/lowering/text-decoder-encoding.d.ts +12 -0
  547. package/dist/frontend/lowering/text-decoder-encoding.js +82 -0
  548. package/dist/frontend/lowering/text-decoder-encoding.js.map +1 -0
  549. package/dist/frontend/lowering/text-decoder-encoding.test.d.ts +1 -0
  550. package/dist/frontend/lowering/text-decoder-encoding.test.js +38 -0
  551. package/dist/frontend/lowering/text-decoder-encoding.test.js.map +1 -0
  552. package/dist/frontend/lowering/union-narrow.d.ts +9 -0
  553. package/dist/frontend/lowering/union-narrow.js +59 -0
  554. package/dist/frontend/lowering/union-narrow.js.map +1 -0
  555. package/dist/frontend/lowering/union-narrow.test.d.ts +1 -0
  556. package/dist/frontend/lowering/union-narrow.test.js +72 -0
  557. package/dist/frontend/lowering/union-narrow.test.js.map +1 -0
  558. package/dist/frontend/lowering/union-retag.d.ts +43 -0
  559. package/dist/frontend/lowering/union-retag.js +259 -0
  560. package/dist/frontend/lowering/union-retag.js.map +1 -0
  561. package/dist/frontend/lowering/union-retag.test.d.ts +1 -0
  562. package/dist/frontend/lowering/union-retag.test.js +405 -0
  563. package/dist/frontend/lowering/union-retag.test.js.map +1 -0
  564. package/dist/frontend/lowering/unregistered-class-types.d.ts +14 -0
  565. package/dist/frontend/lowering/unregistered-class-types.js +94 -0
  566. package/dist/frontend/lowering/unregistered-class-types.js.map +1 -0
  567. package/dist/frontend/lowering/unregistered-class-types.test.d.ts +1 -0
  568. package/dist/frontend/lowering/unregistered-class-types.test.js +65 -0
  569. package/dist/frontend/lowering/unregistered-class-types.test.js.map +1 -0
  570. package/dist/frontend/lowering/width-lift.d.ts +40 -0
  571. package/dist/frontend/lowering/width-lift.js +2 -0
  572. package/dist/frontend/lowering/width-lift.js.map +1 -0
  573. package/dist/frontend/module-syntax.d.ts +58 -0
  574. package/dist/frontend/module-syntax.js +123 -0
  575. package/dist/frontend/module-syntax.js.map +1 -0
  576. package/dist/frontend/module-syntax.test.d.ts +1 -0
  577. package/dist/frontend/module-syntax.test.js +78 -0
  578. package/dist/frontend/module-syntax.test.js.map +1 -0
  579. package/dist/frontend/npm-fetch-analysis.d.ts +17 -0
  580. package/dist/frontend/npm-fetch-analysis.js +100 -0
  581. package/dist/frontend/npm-fetch-analysis.js.map +1 -0
  582. package/dist/frontend/npm-fetch-analysis.test.d.ts +1 -0
  583. package/dist/frontend/npm-fetch-analysis.test.js +107 -0
  584. package/dist/frontend/npm-fetch-analysis.test.js.map +1 -0
  585. package/dist/frontend/npm-fetch-node.d.ts +2 -0
  586. package/dist/frontend/npm-fetch-node.js +12 -0
  587. package/dist/frontend/npm-fetch-node.js.map +1 -0
  588. package/dist/frontend/npm-fetch-syntax.d.ts +6 -0
  589. package/dist/frontend/npm-fetch-syntax.js +207 -0
  590. package/dist/frontend/npm-fetch-syntax.js.map +1 -0
  591. package/dist/frontend/npm-node.d.ts +10 -0
  592. package/dist/frontend/npm-node.js +14 -0
  593. package/dist/frontend/npm-node.js.map +1 -0
  594. package/dist/frontend/npm-static-bundled-cjs.d.ts +8 -0
  595. package/dist/frontend/npm-static-bundled-cjs.js +236 -0
  596. package/dist/frontend/npm-static-bundled-cjs.js.map +1 -0
  597. package/dist/frontend/npm-static-bundled-cjs.test.d.ts +1 -0
  598. package/dist/frontend/npm-static-bundled-cjs.test.js +69 -0
  599. package/dist/frontend/npm-static-bundled-cjs.test.js.map +1 -0
  600. package/dist/frontend/npm-static-declaration-syntax.d.ts +57 -0
  601. package/dist/frontend/npm-static-declaration-syntax.js +944 -0
  602. package/dist/frontend/npm-static-declaration-syntax.js.map +1 -0
  603. package/dist/frontend/npm-static-declarations.d.ts +11 -39
  604. package/dist/frontend/npm-static-declarations.js +22 -561
  605. package/dist/frontend/npm-static-declarations.js.map +1 -1
  606. package/dist/frontend/npm-static-declarations.test.js +245 -6
  607. package/dist/frontend/npm-static-declarations.test.js.map +1 -1
  608. package/dist/frontend/npm-static-prune.d.ts +1 -1
  609. package/dist/frontend/npm-static-prune.js +121 -38
  610. package/dist/frontend/npm-static-prune.js.map +1 -1
  611. package/dist/frontend/npm-static-prune.test.js +9 -1
  612. package/dist/frontend/npm-static-prune.test.js.map +1 -1
  613. package/dist/frontend/npm-static-rewrite-host.d.ts +4 -0
  614. package/dist/frontend/npm-static-rewrite-host.js +179 -0
  615. package/dist/frontend/npm-static-rewrite-host.js.map +1 -0
  616. package/dist/frontend/npm-static-rewrite-syntax.d.ts +16 -0
  617. package/dist/frontend/npm-static-rewrite-syntax.js +905 -0
  618. package/dist/frontend/npm-static-rewrite-syntax.js.map +1 -0
  619. package/dist/frontend/npm-static-rewrite.d.ts +0 -5
  620. package/dist/frontend/npm-static-rewrite.js +2 -1079
  621. package/dist/frontend/npm-static-rewrite.js.map +1 -1
  622. package/dist/frontend/npm-static-subtyping.d.ts +5 -0
  623. package/dist/frontend/npm-static-subtyping.js +55 -0
  624. package/dist/frontend/npm-static-subtyping.js.map +1 -0
  625. package/dist/frontend/npm-static-subtyping.test.d.ts +1 -0
  626. package/dist/frontend/npm-static-subtyping.test.js +58 -0
  627. package/dist/frontend/npm-static-subtyping.test.js.map +1 -0
  628. package/dist/frontend/npm-static.d.ts +7 -15
  629. package/dist/frontend/npm-static.js +19 -28
  630. package/dist/frontend/npm-static.js.map +1 -1
  631. package/dist/frontend/npm.d.ts +8 -69
  632. package/dist/frontend/npm.js +21 -361
  633. package/dist/frontend/npm.js.map +1 -1
  634. package/dist/frontend/npm.test.js +2 -2
  635. package/dist/frontend/npm.test.js.map +1 -1
  636. package/dist/frontend/pipeline-native.d.ts +6 -0
  637. package/dist/frontend/pipeline-native.js +32 -0
  638. package/dist/frontend/pipeline-native.js.map +1 -0
  639. package/dist/frontend/pipeline.d.ts +54 -0
  640. package/dist/frontend/pipeline.js +382 -0
  641. package/dist/frontend/pipeline.js.map +1 -0
  642. package/dist/frontend/pipeline.test.d.ts +1 -0
  643. package/dist/frontend/pipeline.test.js +77 -0
  644. package/dist/frontend/pipeline.test.js.map +1 -0
  645. package/dist/frontend/program-analysis.d.ts +10 -0
  646. package/dist/frontend/program-analysis.js +14 -0
  647. package/dist/frontend/program-analysis.js.map +1 -0
  648. package/dist/frontend/program-node.d.ts +9 -0
  649. package/dist/frontend/program-node.js +48 -0
  650. package/dist/frontend/program-node.js.map +1 -0
  651. package/dist/frontend/program.d.ts +39 -20
  652. package/dist/frontend/program.js +393 -189
  653. package/dist/frontend/program.js.map +1 -1
  654. package/dist/frontend/program.test.js +105 -2
  655. package/dist/frontend/program.test.js.map +1 -1
  656. package/dist/frontend/provenance-core.d.ts +9 -0
  657. package/dist/frontend/provenance-core.js +435 -0
  658. package/dist/frontend/provenance-core.js.map +1 -0
  659. package/dist/frontend/provenance.d.ts +0 -4
  660. package/dist/frontend/provenance.js +4 -459
  661. package/dist/frontend/provenance.js.map +1 -1
  662. package/dist/frontend/resolve.d.ts +3 -1
  663. package/dist/frontend/resolve.js +6 -3
  664. package/dist/frontend/resolve.js.map +1 -1
  665. package/dist/frontend/runtime-resolve.d.ts +4 -3
  666. package/dist/frontend/runtime-resolve.js +22 -18
  667. package/dist/frontend/runtime-resolve.js.map +1 -1
  668. package/dist/frontend/runtime-resolve.test.js +53 -0
  669. package/dist/frontend/runtime-resolve.test.js.map +1 -1
  670. package/dist/frontend/services-node.d.ts +5 -0
  671. package/dist/frontend/services-node.js +19 -0
  672. package/dist/frontend/services-node.js.map +1 -0
  673. package/dist/frontend/services-node.test.d.ts +1 -0
  674. package/dist/frontend/services-node.test.js +70 -0
  675. package/dist/frontend/services-node.test.js.map +1 -0
  676. package/dist/frontend/services.d.ts +44 -0
  677. package/dist/frontend/services.js +90 -0
  678. package/dist/frontend/services.js.map +1 -0
  679. package/dist/frontend/services.test.d.ts +1 -0
  680. package/dist/frontend/services.test.js +174 -0
  681. package/dist/frontend/services.test.js.map +1 -0
  682. package/dist/frontend/ts7/adapter.d.ts +3 -3
  683. package/dist/frontend/ts7/adapter.js +14 -31
  684. package/dist/frontend/ts7/adapter.js.map +1 -1
  685. package/dist/frontend/ts7/api.d.ts +16 -0
  686. package/dist/frontend/ts7/api.js +24 -0
  687. package/dist/frontend/ts7/api.js.map +1 -0
  688. package/dist/frontend/ts7/ast-bytes.d.ts +31 -0
  689. package/dist/frontend/ts7/ast-bytes.js +137 -0
  690. package/dist/frontend/ts7/ast-bytes.js.map +1 -0
  691. package/dist/frontend/ts7/ast-bytes.test.d.ts +1 -0
  692. package/dist/frontend/ts7/ast-bytes.test.js +73 -0
  693. package/dist/frontend/ts7/ast-bytes.test.js.map +1 -0
  694. package/dist/frontend/ts7/ast-guards.generated.d.ts +353 -0
  695. package/dist/frontend/ts7/ast-guards.generated.js +1951 -0
  696. package/dist/frontend/ts7/ast-guards.generated.js.map +1 -0
  697. package/dist/frontend/ts7/ast-guards.test.d.ts +1 -0
  698. package/dist/frontend/ts7/ast-guards.test.js +43 -0
  699. package/dist/frontend/ts7/ast-guards.test.js.map +1 -0
  700. package/dist/frontend/ts7/ast-node.d.ts +194 -0
  701. package/dist/frontend/ts7/ast-node.js +448 -0
  702. package/dist/frontend/ts7/ast-node.js.map +1 -0
  703. package/dist/frontend/ts7/ast-node.test.d.ts +1 -0
  704. package/dist/frontend/ts7/ast-node.test.js +266 -0
  705. package/dist/frontend/ts7/ast-node.test.js.map +1 -0
  706. package/dist/frontend/ts7/ast-schema.generated.d.ts +503 -0
  707. package/dist/frontend/ts7/ast-schema.generated.js +1446 -0
  708. package/dist/frontend/ts7/ast-schema.generated.js.map +1 -0
  709. package/dist/frontend/ts7/ast-text.d.ts +6 -0
  710. package/dist/frontend/ts7/ast-text.js +124 -0
  711. package/dist/frontend/ts7/ast-text.js.map +1 -0
  712. package/dist/frontend/ts7/ast-text.test.d.ts +1 -0
  713. package/dist/frontend/ts7/ast-text.test.js +38 -0
  714. package/dist/frontend/ts7/ast-text.test.js.map +1 -0
  715. package/dist/frontend/ts7/ast-tokens.generated.d.ts +2 -0
  716. package/dist/frontend/ts7/ast-tokens.generated.js +155 -0
  717. package/dist/frontend/ts7/ast-tokens.generated.js.map +1 -0
  718. package/dist/frontend/ts7/ast-types.d.ts +42 -0
  719. package/dist/frontend/ts7/ast-types.generated.d.ts +1615 -0
  720. package/dist/frontend/ts7/ast-types.generated.js +5 -0
  721. package/dist/frontend/ts7/ast-types.generated.js.map +1 -0
  722. package/dist/frontend/ts7/ast-types.js +3 -0
  723. package/dist/frontend/ts7/ast-types.js.map +1 -0
  724. package/dist/frontend/ts7/ast-wire.d.ts +58 -0
  725. package/dist/frontend/ts7/ast-wire.js +267 -0
  726. package/dist/frontend/ts7/ast-wire.js.map +1 -0
  727. package/dist/frontend/ts7/ast-wire.test.d.ts +1 -0
  728. package/dist/frontend/ts7/ast-wire.test.js +151 -0
  729. package/dist/frontend/ts7/ast-wire.test.js.map +1 -0
  730. package/dist/frontend/ts7/ast.d.ts +14 -14
  731. package/dist/frontend/ts7/ast.js +25 -18
  732. package/dist/frontend/ts7/ast.js.map +1 -1
  733. package/dist/frontend/ts7/census-check.js +1 -0
  734. package/dist/frontend/ts7/census-check.js.map +1 -1
  735. package/dist/frontend/ts7/checker-cache.d.ts +48 -0
  736. package/dist/frontend/ts7/checker-cache.js +92 -0
  737. package/dist/frontend/ts7/checker-cache.js.map +1 -0
  738. package/dist/frontend/ts7/checker.d.ts +19 -46
  739. package/dist/frontend/ts7/checker.js +231 -161
  740. package/dist/frontend/ts7/checker.js.map +1 -1
  741. package/dist/frontend/ts7/checker.test.d.ts +1 -0
  742. package/dist/frontend/ts7/checker.test.js +335 -0
  743. package/dist/frontend/ts7/checker.test.js.map +1 -0
  744. package/dist/frontend/ts7/enums.d.ts +4 -27
  745. package/dist/frontend/ts7/enums.generated.d.ts +878 -0
  746. package/dist/frontend/ts7/enums.generated.js +1313 -0
  747. package/dist/frontend/ts7/enums.generated.js.map +1 -0
  748. package/dist/frontend/ts7/enums.js +4 -45
  749. package/dist/frontend/ts7/enums.js.map +1 -1
  750. package/dist/frontend/ts7/enums.test.d.ts +1 -0
  751. package/dist/frontend/ts7/enums.test.js +48 -0
  752. package/dist/frontend/ts7/enums.test.js.map +1 -0
  753. package/dist/frontend/ts7/native-api.d.ts +10 -0
  754. package/dist/frontend/ts7/native-api.js +10 -0
  755. package/dist/frontend/ts7/native-api.js.map +1 -0
  756. package/dist/frontend/ts7/native-host.d.ts +2 -0
  757. package/dist/frontend/ts7/native-host.js +11 -0
  758. package/dist/frontend/ts7/native-host.js.map +1 -0
  759. package/dist/frontend/ts7/native-process.d.ts +14 -0
  760. package/dist/frontend/ts7/native-process.js +62 -0
  761. package/dist/frontend/ts7/native-process.js.map +1 -0
  762. package/dist/frontend/ts7/program-adapter.d.ts +10 -98
  763. package/dist/frontend/ts7/program-adapter.js +16 -310
  764. package/dist/frontend/ts7/program-adapter.js.map +1 -1
  765. package/dist/frontend/ts7/program-host.d.ts +115 -0
  766. package/dist/frontend/ts7/program-host.js +347 -0
  767. package/dist/frontend/ts7/program-host.js.map +1 -0
  768. package/dist/frontend/ts7/program-host.test.d.ts +1 -0
  769. package/dist/frontend/ts7/program-host.test.js +207 -0
  770. package/dist/frontend/ts7/program-host.test.js.map +1 -0
  771. package/dist/frontend/ts7/rpc-api.d.ts +12 -0
  772. package/dist/frontend/ts7/rpc-api.js +23 -0
  773. package/dist/frontend/ts7/rpc-api.js.map +1 -0
  774. package/dist/frontend/ts7/rpc-client.d.ts +27 -0
  775. package/dist/frontend/ts7/rpc-client.js +102 -0
  776. package/dist/frontend/ts7/rpc-client.js.map +1 -0
  777. package/dist/frontend/ts7/rpc-client.test.d.ts +1 -0
  778. package/dist/frontend/ts7/rpc-client.test.js +133 -0
  779. package/dist/frontend/ts7/rpc-client.test.js.map +1 -0
  780. package/dist/frontend/ts7/rpc-filesystem.d.ts +16 -0
  781. package/dist/frontend/ts7/rpc-filesystem.js +42 -0
  782. package/dist/frontend/ts7/rpc-filesystem.js.map +1 -0
  783. package/dist/frontend/ts7/rpc-filesystem.test.d.ts +1 -0
  784. package/dist/frontend/ts7/rpc-filesystem.test.js +89 -0
  785. package/dist/frontend/ts7/rpc-filesystem.test.js.map +1 -0
  786. package/dist/frontend/ts7/rpc-process.d.ts +2 -0
  787. package/dist/frontend/ts7/rpc-process.js +148 -0
  788. package/dist/frontend/ts7/rpc-process.js.map +1 -0
  789. package/dist/frontend/ts7/rpc-process.test.d.ts +1 -0
  790. package/dist/frontend/ts7/rpc-process.test.js +29 -0
  791. package/dist/frontend/ts7/rpc-process.test.js.map +1 -0
  792. package/dist/frontend/ts7/rpc-wire.d.ts +46 -0
  793. package/dist/frontend/ts7/rpc-wire.js +195 -0
  794. package/dist/frontend/ts7/rpc-wire.js.map +1 -0
  795. package/dist/frontend/ts7/rpc-wire.test.d.ts +1 -0
  796. package/dist/frontend/ts7/rpc-wire.test.js +168 -0
  797. package/dist/frontend/ts7/rpc-wire.test.js.map +1 -0
  798. package/dist/frontend/ts7/semantic-checker.d.ts +137 -0
  799. package/dist/frontend/ts7/semantic-checker.js +221 -0
  800. package/dist/frontend/ts7/semantic-checker.js.map +1 -0
  801. package/dist/frontend/ts7/semantic-checker.test.d.ts +1 -0
  802. package/dist/frontend/ts7/semantic-checker.test.js +119 -0
  803. package/dist/frontend/ts7/semantic-checker.test.js.map +1 -0
  804. package/dist/frontend/ts7/semantic-json.d.ts +5 -0
  805. package/dist/frontend/ts7/semantic-json.js +47 -0
  806. package/dist/frontend/ts7/semantic-json.js.map +1 -0
  807. package/dist/frontend/ts7/semantic-json.test.d.ts +1 -0
  808. package/dist/frontend/ts7/semantic-json.test.js +42 -0
  809. package/dist/frontend/ts7/semantic-json.test.js.map +1 -0
  810. package/dist/frontend/ts7/semantic-model.d.ts +222 -0
  811. package/dist/frontend/ts7/semantic-model.js +423 -0
  812. package/dist/frontend/ts7/semantic-model.js.map +1 -0
  813. package/dist/frontend/ts7/semantic-model.test.d.ts +1 -0
  814. package/dist/frontend/ts7/semantic-model.test.js +322 -0
  815. package/dist/frontend/ts7/semantic-model.test.js.map +1 -0
  816. package/dist/frontend/ts7/semantic-schema.generated.d.ts +283 -0
  817. package/dist/frontend/ts7/semantic-schema.generated.js +222 -0
  818. package/dist/frontend/ts7/semantic-schema.generated.js.map +1 -0
  819. package/dist/frontend/ts7/semantic-types.d.ts +5 -0
  820. package/dist/frontend/ts7/semantic-types.js +2 -0
  821. package/dist/frontend/ts7/semantic-types.js.map +1 -0
  822. package/dist/frontend/ts7/session-cache.d.ts +17 -0
  823. package/dist/frontend/ts7/session-cache.js +97 -0
  824. package/dist/frontend/ts7/session-cache.js.map +1 -0
  825. package/dist/frontend/ts7/session-cache.test.d.ts +1 -0
  826. package/dist/frontend/ts7/session-cache.test.js +87 -0
  827. package/dist/frontend/ts7/session-cache.test.js.map +1 -0
  828. package/dist/frontend/ts7/session-path.d.ts +18 -0
  829. package/dist/frontend/ts7/session-path.js +203 -0
  830. package/dist/frontend/ts7/session-path.js.map +1 -0
  831. package/dist/frontend/ts7/session-path.test.d.ts +1 -0
  832. package/dist/frontend/ts7/session-path.test.js +34 -0
  833. package/dist/frontend/ts7/session-path.test.js.map +1 -0
  834. package/dist/frontend/ts7/session-schema.generated.d.ts +167 -0
  835. package/dist/frontend/ts7/session-schema.generated.js +5 -0
  836. package/dist/frontend/ts7/session-schema.generated.js.map +1 -0
  837. package/dist/frontend/ts7/session-timing.d.ts +50 -0
  838. package/dist/frontend/ts7/session-timing.js +61 -0
  839. package/dist/frontend/ts7/session-timing.js.map +1 -0
  840. package/dist/frontend/ts7/session-timing.test.d.ts +1 -0
  841. package/dist/frontend/ts7/session-timing.test.js +52 -0
  842. package/dist/frontend/ts7/session-timing.test.js.map +1 -0
  843. package/dist/frontend/ts7/session.d.ts +105 -0
  844. package/dist/frontend/ts7/session.js +233 -0
  845. package/dist/frontend/ts7/session.js.map +1 -0
  846. package/dist/frontend/ts7/session.test.d.ts +1 -0
  847. package/dist/frontend/ts7/session.test.js +215 -0
  848. package/dist/frontend/ts7/session.test.js.map +1 -0
  849. package/dist/frontend/ts7/source-parser-node.d.ts +6 -0
  850. package/dist/frontend/ts7/source-parser-node.js +15 -0
  851. package/dist/frontend/ts7/source-parser-node.js.map +1 -0
  852. package/dist/frontend/ts7/source-parser.d.ts +25 -0
  853. package/dist/frontend/ts7/source-parser.js +96 -0
  854. package/dist/frontend/ts7/source-parser.js.map +1 -0
  855. package/dist/frontend/ts7/source-parser.test.d.ts +1 -0
  856. package/dist/frontend/ts7/source-parser.test.js +151 -0
  857. package/dist/frontend/ts7/source-parser.test.js.map +1 -0
  858. package/dist/frontend/ts7/syntax.d.ts +3 -0
  859. package/dist/frontend/ts7/syntax.js +4 -0
  860. package/dist/frontend/ts7/syntax.js.map +1 -0
  861. package/dist/frontend/tsc-codes.js +3 -0
  862. package/dist/frontend/tsc-codes.js.map +1 -1
  863. package/dist/frontend/type-mapper.d.ts +34 -18
  864. package/dist/frontend/type-mapper.js +552 -131
  865. package/dist/frontend/type-mapper.js.map +1 -1
  866. package/dist/frontend/type-mapper.test.js +146 -2
  867. package/dist/frontend/type-mapper.test.js.map +1 -1
  868. package/dist/frontend/union-discriminants.d.ts +16 -0
  869. package/dist/frontend/union-discriminants.js +98 -0
  870. package/dist/frontend/union-discriminants.js.map +1 -0
  871. package/dist/frontend/union-discriminants.test.d.ts +1 -0
  872. package/dist/frontend/union-discriminants.test.js +182 -0
  873. package/dist/frontend/union-discriminants.test.js.map +1 -0
  874. package/dist/index.d.ts +7 -198
  875. package/dist/index.js +369 -1572
  876. package/dist/index.js.map +1 -1
  877. package/dist/ir/analysis.d.ts +16 -4
  878. package/dist/ir/analysis.js +23 -4
  879. package/dist/ir/analysis.js.map +1 -1
  880. package/dist/ir/analysis.test.js +15 -2
  881. package/dist/ir/analysis.test.js.map +1 -1
  882. package/dist/ir/constant-tables.js +67 -49
  883. package/dist/ir/constant-tables.js.map +1 -1
  884. package/dist/ir/constant-tables.test.js +1 -1
  885. package/dist/ir/control-flow.d.ts +6 -0
  886. package/dist/ir/control-flow.js +142 -0
  887. package/dist/ir/control-flow.js.map +1 -0
  888. package/dist/ir/control-flow.test.d.ts +1 -0
  889. package/dist/ir/control-flow.test.js +113 -0
  890. package/dist/ir/control-flow.test.js.map +1 -0
  891. package/dist/ir/integer-loops.js +7 -18
  892. package/dist/ir/integer-loops.js.map +1 -1
  893. package/dist/ir/integer-ranges.js +53 -27
  894. package/dist/ir/integer-ranges.js.map +1 -1
  895. package/dist/ir/ir.d.ts +334 -176
  896. package/dist/ir/ir.js +710 -903
  897. package/dist/ir/ir.js.map +1 -1
  898. package/dist/ir/ir.test.js +162 -1
  899. package/dist/ir/ir.test.js.map +1 -1
  900. package/dist/ir/scalar-records.js +165 -134
  901. package/dist/ir/scalar-records.js.map +1 -1
  902. package/dist/ir/scalar-records.test.js +1 -1
  903. package/dist/ir/serialize.d.ts +4 -2
  904. package/dist/ir/serialize.js +33 -14
  905. package/dist/ir/serialize.js.map +1 -1
  906. package/dist/ir/serialize.test.d.ts +1 -0
  907. package/dist/ir/serialize.test.js +57 -0
  908. package/dist/ir/serialize.test.js.map +1 -0
  909. package/dist/ir/traverse.d.ts +41 -0
  910. package/dist/ir/traverse.js +660 -0
  911. package/dist/ir/traverse.js.map +1 -0
  912. package/dist/ir/traverse.test.d.ts +1 -0
  913. package/dist/ir/traverse.test.js +242 -0
  914. package/dist/ir/traverse.test.js.map +1 -0
  915. package/dist/ir/validate.js +2018 -1498
  916. package/dist/ir/validate.js.map +1 -1
  917. package/dist/ir/validate.test.js +536 -2
  918. package/dist/ir/validate.test.js.map +1 -1
  919. package/dist/library/cache-primitives.d.ts +2 -3
  920. package/dist/library/cache-primitives.js +4 -6
  921. package/dist/library/cache-primitives.js.map +1 -1
  922. package/dist/library/fence-eval.js +2 -2
  923. package/dist/library/fence-eval.js.map +1 -1
  924. package/dist/library/int-infer.js +7 -6
  925. package/dist/library/int-infer.js.map +1 -1
  926. package/dist/library/int-infer.test.js +4 -4
  927. package/dist/library/library-cache.d.ts +3 -2
  928. package/dist/library/library-cache.js +5 -17
  929. package/dist/library/library-cache.js.map +1 -1
  930. package/dist/library/library-cache.test.js +54 -41
  931. package/dist/library/library-cache.test.js.map +1 -1
  932. package/dist/library/library-profile.d.ts +3 -1
  933. package/dist/library/library-profile.js +15 -6
  934. package/dist/library/library-profile.js.map +1 -1
  935. package/dist/library/prepare.d.ts +15 -0
  936. package/dist/library/prepare.js +584 -0
  937. package/dist/library/prepare.js.map +1 -0
  938. package/dist/library/semantic-source.d.ts +1 -1
  939. package/dist/library/semantic-source.js +8 -6
  940. package/dist/library/semantic-source.js.map +1 -1
  941. package/dist/library/sidecar-validate.js +4 -4
  942. package/dist/library/sidecar-validate.js.map +1 -1
  943. package/dist/library/sidecar.d.ts +2 -0
  944. package/dist/library/sidecar.js +10 -3
  945. package/dist/library/sidecar.js.map +1 -1
  946. package/dist/native/cache.d.ts +11 -0
  947. package/dist/native/cache.js +113 -0
  948. package/dist/native/cache.js.map +1 -0
  949. package/dist/native/cache.test.d.ts +1 -0
  950. package/dist/native/cache.test.js +66 -0
  951. package/dist/native/cache.test.js.map +1 -0
  952. package/dist/native/cli.d.ts +1 -0
  953. package/dist/native/cli.js +112 -0
  954. package/dist/native/cli.js.map +1 -0
  955. package/dist/native/compiler.d.ts +15 -0
  956. package/dist/native/compiler.js +336 -0
  957. package/dist/native/compiler.js.map +1 -0
  958. package/dist/native/compiler.test.d.ts +1 -0
  959. package/dist/native/compiler.test.js +174 -0
  960. package/dist/native/compiler.test.js.map +1 -0
  961. package/dist/native/comptime.d.ts +5 -0
  962. package/dist/native/comptime.js +73 -0
  963. package/dist/native/comptime.js.map +1 -0
  964. package/dist/native/comptime.test.d.ts +1 -0
  965. package/dist/native/comptime.test.js +65 -0
  966. package/dist/native/comptime.test.js.map +1 -0
  967. package/dist/native/executable-cache.d.ts +26 -0
  968. package/dist/native/executable-cache.js +228 -0
  969. package/dist/native/executable-cache.js.map +1 -0
  970. package/dist/native/executable-cache.test.d.ts +1 -0
  971. package/dist/native/executable-cache.test.js +151 -0
  972. package/dist/native/executable-cache.test.js.map +1 -0
  973. package/dist/native/file-identity.d.ts +4 -0
  974. package/dist/native/file-identity.js +14 -0
  975. package/dist/native/file-identity.js.map +1 -0
  976. package/dist/native/file-identity.test.d.ts +1 -0
  977. package/dist/native/file-identity.test.js +43 -0
  978. package/dist/native/file-identity.test.js.map +1 -0
  979. package/dist/native/library.d.ts +22 -0
  980. package/dist/native/library.js +83 -0
  981. package/dist/native/library.js.map +1 -0
  982. package/dist/native/prepare.d.ts +21 -0
  983. package/dist/native/prepare.js +174 -0
  984. package/dist/native/prepare.js.map +1 -0
  985. package/dist/native/prepare.test.d.ts +1 -0
  986. package/dist/native/prepare.test.js +70 -0
  987. package/dist/native/prepare.test.js.map +1 -0
  988. package/dist/native/sanitizer.d.ts +11 -0
  989. package/dist/native/sanitizer.js +137 -0
  990. package/dist/native/sanitizer.js.map +1 -0
  991. package/dist/native/sanitizer.test.d.ts +1 -0
  992. package/dist/native/sanitizer.test.js +58 -0
  993. package/dist/native/sanitizer.test.js.map +1 -0
  994. package/dist/native/task.d.ts +4 -0
  995. package/dist/native/task.js +16 -0
  996. package/dist/native/task.js.map +1 -0
  997. package/dist/native/task.test.d.ts +1 -0
  998. package/dist/native/task.test.js +17 -0
  999. package/dist/native/task.test.js.map +1 -0
  1000. package/dist/native/toolchain.d.ts +45 -0
  1001. package/dist/native/toolchain.js +94 -0
  1002. package/dist/native/toolchain.js.map +1 -0
  1003. package/dist/native/toolchain.test.d.ts +1 -0
  1004. package/dist/native/toolchain.test.js +85 -0
  1005. package/dist/native/toolchain.test.js.map +1 -0
  1006. package/dist/startup-cache.d.ts +1 -1
  1007. package/dist/startup-cache.js +2 -5
  1008. package/dist/startup-cache.js.map +1 -1
  1009. package/dist/timing.d.ts +4 -0
  1010. package/dist/timing.js +19 -0
  1011. package/dist/timing.js.map +1 -0
  1012. package/dist/wasi-paths.js +10 -7
  1013. package/dist/wasi-paths.js.map +1 -1
  1014. package/package.json +28 -19
  1015. package/surface-manifest.json +107 -98
  1016. package/dist/backend/c/async.d.ts +0 -171
  1017. package/dist/backend/c/async.js +0 -1317
  1018. package/dist/backend/c/async.js.map +0 -1
  1019. package/dist/backend/c/c-emitter.d.ts +0 -536
  1020. package/dist/backend/c/c-emitter.js +0 -1932
  1021. package/dist/backend/c/c-emitter.js.map +0 -1
  1022. package/dist/backend/c/exprs.d.ts +0 -15
  1023. package/dist/backend/c/exprs.js +0 -8847
  1024. package/dist/backend/c/exprs.js.map +0 -1
  1025. package/dist/backend/c/island.d.ts +0 -45
  1026. package/dist/backend/c/island.js +0 -281
  1027. package/dist/backend/c/island.js.map +0 -1
  1028. package/dist/backend/c/may-throw.js.map +0 -1
  1029. package/dist/backend/c/shapes.d.ts +0 -142
  1030. package/dist/backend/c/shapes.js +0 -603
  1031. package/dist/backend/c/shapes.js.map +0 -1
  1032. package/dist/backend/c/stmts.d.ts +0 -76
  1033. package/dist/backend/c/stmts.js +0 -1108
  1034. package/dist/backend/c/stmts.js.map +0 -1
  1035. package/dist/backend/c/types.d.ts +0 -71
  1036. package/dist/backend/c/types.js +0 -459
  1037. package/dist/backend/c/types.js.map +0 -1
  1038. package/dist/backend/c/types.test.js +0 -32
  1039. package/dist/backend/c/types.test.js.map +0 -1
  1040. package/dist/backend/c/walkers.d.ts +0 -134
  1041. package/dist/backend/c/walkers.js +0 -1772
  1042. package/dist/backend/c/walkers.js.map +0 -1
  1043. /package/dist/backend/{c/types.test.d.ts → cycle-analysis.test.d.ts} +0 -0
@@ -5,25 +5,228 @@ import { InternalCompilerError } from "../../errors.js";
5
5
  * accessor access, upcasts, `new` expressions, and the builtin Error
6
6
  * hierarchy registration. */
7
7
  import * as ts from "../ts7/adapter.js";
8
- import { BOOL, DATE_T, DYN, F64, bytesOf, JSVAL, RUNTIME_EMITTER_CLASS, RUNTIME_ERROR_CLASSES, RUNTIME_STREAM_CLASSES, STRING, UNDEFINED_T, URL_T, VOID, arrayOf, isSupportedMapKey, isSupportedMapValue, isSupportedSetElem, isUnitType, typeEquals } from "../../ir/ir.js";
9
- import { MAX_GENERIC_INSTANCES, appendImplicitUndefinedReturn, generatorMeta, genericCallInstance, implicitAnyParamSymbolsOf, implicitCallInstance, implicitMonoFile, omittedArgFor } from "./lower-calls.js";
10
- import { isGenericCallableMemberType, typeKey } from "../type-mapper.js";
8
+ import { BOOL, DATE_T, DYN, F64, bytesOf, JSVAL, RUNTIME_EMITTER_CLASS, RUNTIME_ERROR_CLASSES, RUNTIME_STREAM_CLASSES, STRING, UNDEFINED_T, VOID, arrayOf, isSupportedMapKey, isSupportedMapValue, isSupportedSetElem, isUnitType, typeEquals } from "../../ir/ir.js";
9
+ import { MAX_GENERIC_INSTANCES, appendImplicitUndefinedReturn, bodyReadsArguments, generatorMeta, genericCallInstance, hasExplicitJsDocReturn, implicitAnyParamSymbolsOf, implicitCallInstance, implicitMonoFile, omittedArgFor } from "./lower-calls.js";
10
+ import { isGenericCallableMemberType, jsOpenObjectType, typeKey, withUnitArm } from "../type-mapper.js";
11
11
  import { cjsClassExprWholeExportOf, isCjsJsFile, isJsSourceFile, isModuleExportsAccess, isNodeTypesPath, locOf } from "../program.js";
12
- import { PoisonError, dynFallbackType, dynUndefinedExpr, newFnCtx, own } from "./lowerer.js";
13
- import { lowerArrayConstructor, lowerMapSeedArrayNew } from "./lower-containers.js";
12
+ import { PoisonError, dynFallbackType, dynUndefinedExpr, newFnCtx, nodeThrowExpr, own } from "./lowerer.js";
13
+ import { lowerArrayConstructor, lowerMapSeedNew, lowerObjectConstructor, lowerSetSeedNew } from "./lower-containers.js";
14
14
  import { bufEncoding } from "./containers/bytes.js";
15
15
  import { isSafeToRepeat } from "./expressions/evaluation-safety.js";
16
- import { lowerSearchParamsNew } from "./lower-builtins.js";
16
+ import { lowerSearchParamsNew, lowerTextCodecNew } from "./lower-builtins.js";
17
17
  import { requiresDynamicPackageDiag, unsupportedDiag } from "../../diagnostics/diagnostic.js";
18
18
  import { STREAM_API_MEMBERS, STREAM_PROP_MEMBERS, UNDERSCORE_METHODS, lowerStreamNew, lowerStreamSuperCall, streamCtorShape } from "./lower-stream.js";
19
19
  import { emitOverrideShapeReason, emitSpecSuperForward, emitterRooted, lowerEmitterSuperCall } from "./lower-event-emitter.js";
20
20
  import { declSymbolOf } from "./lower-modules.js";
21
- import { uniqueSymbolKeyOf } from "./lower-exprs.js";
21
+ import { classSymbolKeyOf, classSymbolKeyOfSymbol, symbolFieldDisplayName } from "./symbol-fields.js";
22
+ import { builtinFenceHintOf } from "./surfaces.js";
22
23
  import { lowerHttpAgentNew, lowerHttpServerNew } from "./lower-server.js";
23
24
  import { ambientNsRootOf, ambientUndefReadType, ambientUndefVarRootOf, ambientUndefinedFnSymbolOf, fenceEarlyAliasUse, fenceEarlyNsMemberRef, nsMemberIdentOf, nsUndefRead } from "./lower-namespaces.js";
24
25
  import { mixinResultBindingClassOf } from "./lower-mixins.js";
25
- import { rejectStaticThis } from "./static-this.js";
26
- import { staticForkString } from "../fork-target.js";
26
+ import { hasLexicalPrivateReference, hasStaticThis, rejectStaticThis } from "./static-this.js";
27
+ import { lowerUrlNew } from "./lower-url.js";
28
+ import { isNativeProxyInitializer, lowerNativeProxy } from "./expressions/native-proxy.js";
29
+ import { classStaticDataFor } from "./class-static-data.js";
30
+ import { lowerObjectFactoryNew } from "./object-factory-new.js";
31
+ import { tryLowerExpression } from "./expressions/try-lower-expression.js";
32
+ import { lowerInstanceConstructorNew } from "./class-instance-constructor.js";
33
+ import { classPrototypeData } from "./class-prototypes.js";
34
+ import { checkedClassConstruction } from "./class-construction.js";
35
+ import { initializeRuntimeStatics, hasRuntimeStatics } from "./class-runtime-statics.js";
36
+ export function returnsOnlyThis(member) {
37
+ const body = member.body;
38
+ const last = body?.statements.at(-1);
39
+ if (!body || !last || !ts.isReturnStatement(last))
40
+ return false;
41
+ let valid = true;
42
+ const visit = (node) => {
43
+ if (ts.isFunctionLike(node))
44
+ return;
45
+ if (ts.isReturnStatement(node)) {
46
+ let value = node.expression;
47
+ while (value && ts.isParenthesizedExpression(value))
48
+ value = value.expression;
49
+ if (!value || value.kind !== ts.SyntaxKind.ThisKeyword)
50
+ valid = false;
51
+ }
52
+ node.forEachChild(visit);
53
+ };
54
+ body.forEachChild(visit);
55
+ return valid;
56
+ }
57
+ function functionLocalClass(decl) {
58
+ for (let parent = decl.parent; parent && !ts.isSourceFile(parent); parent = parent.parent) {
59
+ if (ts.isFunctionLike(parent))
60
+ return true;
61
+ }
62
+ return false;
63
+ }
64
+ export function storedClassValueType(lowerer, expression, visiting = new Set()) {
65
+ if (visiting.has(expression))
66
+ return null;
67
+ visiting.add(expression);
68
+ if (ts.isParenthesizedExpression(expression))
69
+ return storedClassValueType(lowerer, expression.expression, visiting);
70
+ if (ts.isClassExpression(expression) && !functionLocalClass(expression) && !lowerer.collectingExprClasses.has(expression)) {
71
+ const info = lowerer.lowerClassExpressionInfo(expression);
72
+ return { kind: "classval", className: info.def.name };
73
+ }
74
+ if (ts.isPropertyAccessExpression(expression) && !expression.questionDotToken) {
75
+ const member = nsMemberIdentOf(lowerer, expression);
76
+ if (member)
77
+ return storedClassValueType(lowerer, member, visiting);
78
+ }
79
+ if (expression.kind === ts.SyntaxKind.ThisKeyword) {
80
+ const stored = lowerer.resolveThis();
81
+ if (stored?.type.kind === "classval")
82
+ return stored.type;
83
+ }
84
+ if (ts.isIdentifier(expression)) {
85
+ const stored = lowerer.peekLocal(expression) ?? lowerer.globalOf(expression);
86
+ if (stored?.type.kind === "classval" && lowerer.classes.has(stored.type.className))
87
+ return stored.type;
88
+ const symbol = lowerer.resolveValueSymbol(expression);
89
+ const declaration = symbol && lowerer.checker.declarationsOf(symbol).find((decl) => ts.isVariableDeclaration(decl) && decl.initializer && (ts.getCombinedNodeFlags(decl) & ts.NodeFlags.Const) !== 0);
90
+ if (declaration && ts.isVariableDeclaration(declaration) && declaration.initializer) {
91
+ const value = storedClassValueType(lowerer, declaration.initializer, visiting);
92
+ if (value?.kind === "classval")
93
+ return value;
94
+ }
95
+ }
96
+ const type = lowerer.typeOf(expression);
97
+ const mapped = lowerer.mapTypeOf(type);
98
+ if (mapped?.kind === "classval" && !lowerer.classes.has(mapped.className)) {
99
+ for (const signature of lowerer.checker.getConstructSignatures(type)) {
100
+ const constructor = lowerer.checker.signatureDeclaration(signature);
101
+ const declaration = constructor && ts.isConstructorDeclaration(constructor) ? constructor.parent : undefined;
102
+ if (declaration && ts.isClassExpression(declaration) && !functionLocalClass(declaration) &&
103
+ !lowerer.collectingExprClasses.has(declaration)) {
104
+ const info = lowerer.lowerClassExpressionInfo(declaration);
105
+ return { kind: "classval", className: info.def.name };
106
+ }
107
+ }
108
+ }
109
+ if (mapped?.kind === "classval" || !ts.isCallExpression(expression))
110
+ return mapped;
111
+ let callee = expression.expression;
112
+ let calls = 1;
113
+ const aliases = new Set();
114
+ for (;;) {
115
+ if (aliases.has(callee))
116
+ break;
117
+ aliases.add(callee);
118
+ if (ts.isParenthesizedExpression(callee)) {
119
+ callee = callee.expression;
120
+ continue;
121
+ }
122
+ if (ts.isCallExpression(callee)) {
123
+ calls++;
124
+ callee = callee.expression;
125
+ continue;
126
+ }
127
+ if (ts.isPropertyAccessExpression(callee)) {
128
+ const member = nsMemberIdentOf(lowerer, callee);
129
+ if (member) {
130
+ callee = member;
131
+ continue;
132
+ }
133
+ }
134
+ if (ts.isIdentifier(callee)) {
135
+ const symbol = lowerer.resolveValueSymbol(callee);
136
+ const declaration = symbol && lowerer.checker.declarationsOf(symbol).find((decl) => ts.isVariableDeclaration(decl) && decl.initializer && (ts.getCombinedNodeFlags(decl) & ts.NodeFlags.Const) !== 0);
137
+ if (declaration && ts.isVariableDeclaration(declaration) && declaration.initializer) {
138
+ callee = declaration.initializer;
139
+ continue;
140
+ }
141
+ }
142
+ break;
143
+ }
144
+ if ((ts.isArrowFunction(callee) || ts.isFunctionExpression(callee)) && isJsSourceFile(callee.getSourceFile()) &&
145
+ !callee.typeParameters?.length && !lowerer.preparingClassFactories.has(callee)) {
146
+ const signature = lowerer.checker.getSignatureFromDeclaration(callee);
147
+ let result = signature && lowerer.checker.getReturnTypeOfSignature(signature);
148
+ for (let i = 1; result && i < calls; i++) {
149
+ const signatures = lowerer.checker.getCallSignatures(result);
150
+ result = signatures.length === 1 ? lowerer.checker.getReturnTypeOfSignature(signatures[0]) : undefined;
151
+ }
152
+ if (result && lowerer.checker.getConstructSignatures(result).length > 0) {
153
+ const returned = (value) => {
154
+ let type = value.type;
155
+ for (let i = 0; i < calls && type.kind === "func"; i++)
156
+ type = type.ret;
157
+ return type.kind === "classval" ? type : null;
158
+ };
159
+ const home = callee.parent;
160
+ const generic = ts.isVariableDeclaration(home) && ts.isIdentifier(home.name) ? lowerer.genericFnOf(home.name) : null;
161
+ if (generic?.implicitParams && ts.isVariableDeclaration(home) && ts.isIdentifier(home.name)) {
162
+ const factory = lowerer.lowerGenericFnValue(home.name, generic);
163
+ const type = returned(factory);
164
+ if (type)
165
+ return type;
166
+ }
167
+ lowerer.preparingClassFactories.add(callee);
168
+ const collecting = lowerer.collecting, sink = lowerer.diagSink;
169
+ lowerer.collecting = false;
170
+ lowerer.diagSink = null;
171
+ try {
172
+ const factory = lowerer.preparedClassFactories.get(callee) ?? lowerer.lowerLambda(callee);
173
+ lowerer.preparedClassFactories.set(callee, factory);
174
+ const type = returned(factory);
175
+ if (type)
176
+ return type;
177
+ }
178
+ finally {
179
+ lowerer.collecting = collecting;
180
+ lowerer.diagSink = sink;
181
+ lowerer.preparingClassFactories.delete(callee);
182
+ }
183
+ }
184
+ }
185
+ // A checked call can erase its returned constructor's ABI while the
186
+ // checker still identifies the class declaration. Collect that class in
187
+ // its factory's lexical scope before choosing the derived native layout.
188
+ // Cache the module-level closure so its captures and lifted bodies are
189
+ // exactly the ones used when the declaration executes.
190
+ for (const signature of lowerer.checker.getConstructSignatures(type)) {
191
+ const declaration = lowerer.checker.signatureDeclaration(signature);
192
+ const cls = declaration && ts.isConstructorDeclaration(declaration) ? declaration.parent : null;
193
+ if (!cls || (!ts.isClassExpression(cls) && !ts.isClassDeclaration(cls)))
194
+ continue;
195
+ let factory;
196
+ for (let parent = cls.parent; parent && !ts.isSourceFile(parent); parent = parent.parent) {
197
+ if (ts.isArrowFunction(parent) || ts.isFunctionExpression(parent))
198
+ factory = parent;
199
+ else if (ts.isFunctionLike(parent)) {
200
+ factory = undefined;
201
+ break;
202
+ }
203
+ }
204
+ if (!factory || !isJsSourceFile(factory.getSourceFile()) || factory.typeParameters?.length ||
205
+ !ts.isVariableDeclaration(factory.parent) || factory.parent.initializer !== factory ||
206
+ !ts.isVariableDeclarationList(factory.parent.parent) || !(factory.parent.parent.flags & ts.NodeFlags.Const) ||
207
+ !ts.isVariableStatement(factory.parent.parent.parent) || !ts.isSourceFile(factory.parent.parent.parent.parent) ||
208
+ lowerer.preparingClassFactories.has(factory))
209
+ continue;
210
+ if (!lowerer.preparedClassFactories.has(factory)) {
211
+ lowerer.preparingClassFactories.add(factory);
212
+ const collecting = lowerer.collecting, sink = lowerer.diagSink;
213
+ lowerer.collecting = false;
214
+ lowerer.diagSink = null;
215
+ try {
216
+ lowerer.preparedClassFactories.set(factory, lowerer.lowerLambda(factory));
217
+ }
218
+ finally {
219
+ lowerer.collecting = collecting;
220
+ lowerer.diagSink = sink;
221
+ lowerer.preparingClassFactories.delete(factory);
222
+ }
223
+ }
224
+ const resolved = lowerer.mapTypeOf(type);
225
+ if (resolved?.kind === "classval")
226
+ return resolved;
227
+ }
228
+ return mapped;
229
+ }
27
230
  /** The KEY symbol behind a LATE-BOUND (`__@name@id`) property: resolved
28
231
  * from the argument of the element-access assignment that declared it
29
232
  * (`this[kLimit] = v` — the declaration list holds the BinaryExpression
@@ -92,8 +295,8 @@ function symbolSlotReturnType(lowerer, fnLike, symbolFields, fields) {
92
295
  return null;
93
296
  if (e.expression.kind !== ts.SyntaxKind.ThisKeyword)
94
297
  return null;
95
- const key = uniqueSymbolKeyOf(lowerer, e.argumentExpression);
96
- const fieldName = key ? symbolFields.get(key.sym) : undefined;
298
+ const key = classSymbolKeyOf(lowerer, e.argumentExpression);
299
+ const fieldName = key ? symbolFields.get(key.identity) : undefined;
97
300
  const t = fieldName !== undefined ? fields.get(fieldName) : undefined;
98
301
  if (t === undefined || t.kind === "dyn")
99
302
  return null;
@@ -103,7 +306,7 @@ function symbolSlotReturnType(lowerer, fnLike, symbolFields, fields) {
103
306
  }
104
307
  return out;
105
308
  }
106
- /** The builtin Error hierarchy (Error + TypeError/RangeError/SyntaxError)
309
+ /** The builtin Error hierarchy
107
310
  * as eagerly-registered ClassInfos: mapType names them the moment a lib
108
311
  * Error type appears, so the infos must exist before any lowering. They
109
312
  * are runtime-provided — no decl, no lowerable bodies; `new`/super()/
@@ -126,11 +329,20 @@ export function registerBuiltinErrorClasses(lowerer) {
126
329
  // subclass declaring its own `code` field lays out AFTER it,
127
330
  // never colliding), and it is NOT in the fields map below: the
128
331
  // READ has its own `string | undefined` lowering (error.code),
129
- // never a plain-string field access.
332
+ // never a plain-string field access. `%cause` is the following
333
+ // owned dyn slot; NULL means absent, dyn undefined means present.
130
334
  fields: [
131
335
  { name: "name", type: STRING },
132
336
  { name: "message", type: STRING },
133
337
  { name: "%code", type: STRING },
338
+ { name: "%cause", type: DYN },
339
+ { name: "%causeEnumerable", type: BOOL },
340
+ { name: "%messagePresent", type: BOOL },
341
+ { name: "%messageEnumerable", type: BOOL },
342
+ { name: "%namePresent", type: BOOL },
343
+ { name: "%nameEnumerable", type: BOOL },
344
+ { name: "%stackFrames", type: STRING },
345
+ { name: "%stack", type: STRING },
134
346
  ],
135
347
  loc,
136
348
  },
@@ -148,10 +360,9 @@ export function registerBuiltinErrorClasses(lowerer) {
148
360
  decl: null,
149
361
  builtinError: true,
150
362
  ctor: null,
151
- // Display shape of `new Error(message?)`. Construction and super()
152
- // never complete against this — errorMessageArg owns those (the
153
- // runtime ABI is one plain string; "" when omitted, like Node).
154
- ctorParams: [{ type: STRING, mode: "omittable" }],
363
+ // Inherited constructors forward both raw arguments. The runtime
364
+ // applies the undefined message default and InstallErrorCause.
365
+ ctorParams: [{ type: DYN, mode: "omittable" }, { type: DYN, mode: "omittable" }],
155
366
  base,
156
367
  subclasses: [],
157
368
  throwingSetters: [],
@@ -278,17 +489,64 @@ export function builtinStreamInfoOf(lowerer, symbol) {
278
489
  });
279
490
  return declared ? (lowerer.classes.get(irName) ?? null) : null;
280
491
  }
492
+ /** A dictionary lookup may be absent even when its checker type is a
493
+ * required reference. Keep literal nullish fallbacks in inferred JS storage. */
494
+ function jsFieldInitializerType(lowerer, type, expression) {
495
+ let node = expression;
496
+ while (ts.isParenthesizedExpression(node))
497
+ node = node.expression;
498
+ if (ts.isFunctionExpression(node) || ts.isArrowFunction(node)) {
499
+ const ret = lowerer.declaredReturnType(node, node);
500
+ const arms = type.kind === "union" ? lowerer.unions.get(type.unionId)?.arms ?? [] : [type];
501
+ // Inferred arithmetic may return a checked Number or BigInt. Preserve
502
+ // the callable when its native return ABI differs from the checker slot.
503
+ if (arms.some((arm) => arm.kind === "func" && !typeEquals(arm.ret, ret)))
504
+ return DYN;
505
+ }
506
+ if (node.kind === ts.SyntaxKind.NullKeyword)
507
+ return withUnitArm(type, "nullT", lowerer.unions) ?? type;
508
+ const inferred = lowerer.typeOf(node);
509
+ for (const arm of inferred.isUnionType() ? ts.constituentTypes(inferred) : [inferred]) {
510
+ if ((arm.flags & ts.TypeFlags.Undefined) !== 0)
511
+ type = lowerer.withUndefinedArmOf(type) ?? type;
512
+ if ((arm.flags & ts.TypeFlags.Null) !== 0)
513
+ type = withUnitArm(type, "nullT", lowerer.unions) ?? type;
514
+ }
515
+ if (ts.isConditionalExpression(node)) {
516
+ return jsFieldInitializerType(lowerer, jsFieldInitializerType(lowerer, type, node.whenTrue), node.whenFalse);
517
+ }
518
+ if (ts.isBinaryExpression(node)) {
519
+ if (node.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken)
520
+ type = jsFieldInitializerType(lowerer, type, node.left);
521
+ if (node.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken ||
522
+ node.operatorToken.kind === ts.SyntaxKind.BarBarToken ||
523
+ node.operatorToken.kind === ts.SyntaxKind.QuestionQuestionToken)
524
+ return jsFieldInitializerType(lowerer, type, node.right);
525
+ }
526
+ return type;
527
+ }
281
528
  /** The undefined-armed union of a JS class property's inferred type — the
282
529
  * honest slot for a field first assigned outside the constructor's top
283
530
  * level (undefined until the write runs, Node-exact). Null when the
284
- * inference is unmappable, checked-dynamic (dyn stays out of class
285
- * fields — KEEP NARROW), or an arm-less kind that cannot join a union
531
+ * inference is unmappable or an arm-less kind that cannot join a union
286
532
  * (genResultRecord's list, including scalar-backed Date values). */
287
533
  function undefArmedFieldType(lowerer, p) {
288
534
  const t = lowerer.checker.getTypeOfSymbol(p);
289
- const mapped = lowerer.mapTypeOf(t);
290
- if (!mapped || mapped.kind === "void" || mapped.kind === "dyn")
535
+ const site = lowerer.checker.declarationsOf(p)[0];
536
+ let mapped = lowerer.mapTypeOf(t) ?? (site ? dynFallbackType(lowerer, site, t) : null);
537
+ if (mapped && site)
538
+ mapped = jsOpenObjectType(site, mapped, lowerer.shapes, lowerer.unions);
539
+ if (!mapped || mapped.kind === "void")
291
540
  return null;
541
+ for (const declaration of lowerer.checker.declarationsOf(p)) {
542
+ const assignment = ts.isBinaryExpression(declaration) ? declaration : declaration.parent;
543
+ if (assignment && ts.isBinaryExpression(assignment) && assignment.operatorToken.kind === ts.SyntaxKind.EqualsToken) {
544
+ mapped = jsFieldInitializerType(lowerer, mapped, assignment.right);
545
+ }
546
+ }
547
+ // An implicit JS value already carries undefined in its native box.
548
+ if (mapped.kind === "dyn")
549
+ return mapped;
292
550
  const byKey = new Map();
293
551
  const arms = mapped.kind === "union" ? (lowerer.unions.get(mapped.unionId)?.arms ?? []) : [mapped];
294
552
  for (const a of arms) {
@@ -539,7 +797,7 @@ function inferredEmptyCollectionFieldType(lowerer, decl, field, initializer) {
539
797
  if (collection === "Map" && node.expression.name.text === "set" && node.arguments.length === 2) {
540
798
  const key = mappedArgument(node.arguments[0]);
541
799
  const value = mappedArgument(node.arguments[1]);
542
- if (key !== null && value !== null && isSupportedMapKey(key) && isSupportedMapValue(value)) {
800
+ if (key !== null && value !== null && isSupportedMapKey(key, key.kind === "union" ? lowerer.unions.get(key.unionId)?.arms : undefined) && isSupportedMapValue(value)) {
543
801
  mapKeys.push(key);
544
802
  mapValues.push(value);
545
803
  }
@@ -548,7 +806,7 @@ function inferredEmptyCollectionFieldType(lowerer, decl, field, initializer) {
548
806
  (node.expression.name.text === "add" || node.expression.name.text === "has" || node.expression.name.text === "delete") &&
549
807
  node.arguments.length === 1) {
550
808
  const element = mappedArgument(node.arguments[0]);
551
- if (element !== null && isSupportedSetElem(element))
809
+ if (element !== null && isSupportedSetElem(element, element.kind === "union" ? lowerer.unions.get(element.unionId)?.arms : undefined))
552
810
  setElements.push(element);
553
811
  }
554
812
  return undefined;
@@ -708,7 +966,25 @@ mixin) {
708
966
  // so the base's ClassInfo already exists here. An INSTANTIATION's
709
967
  // base is its family (whose base is the declared one) — the heritage
710
968
  // clause resolved when the family collected.
711
- let base = inst ? inst.family : mixin ? mixin.base : null;
969
+ const computedBase = lowerer.computedClassBases.get(lowerer.classNamer(decl));
970
+ let base = inst ? inst.family : mixin ? mixin.base : computedBase?.classInfo ?? null;
971
+ let callableBase;
972
+ let factoryBaseExpression;
973
+ const adoptCallableBase = (expression) => {
974
+ if (familyMode || inst || mixin)
975
+ return false;
976
+ if (lowerer.computedCallableBases.has(decl)) {
977
+ callableBase = { expression, constructorId: `%g.${className}.base`, prototypeId: `%g.${className}.basePrototype` };
978
+ return true;
979
+ }
980
+ const signatures = lowerer.checker.getCallSignatures(lowerer.typeOf(expression));
981
+ const source = signatures.length === 1 ? lowerer.checker.signatureDeclaration(signatures[0]) : undefined;
982
+ if (!source || !isJsSourceFile(source.getSourceFile()) ||
983
+ !(ts.isFunctionDeclaration(source) || ts.isFunctionExpression(source)))
984
+ return false;
985
+ callableBase = { expression, constructorId: `%g.${className}.base`, prototypeId: `%g.${className}.basePrototype` };
986
+ return true;
987
+ };
712
988
  // A family whose `extends` clause mentions its OWN type parameters
713
989
  // (`class D<T> extends Box<T>`) would need a different base per
714
990
  // instantiation — no single family interval can sit above all of
@@ -739,7 +1015,7 @@ mixin) {
739
1015
  }
740
1016
  }
741
1017
  }
742
- for (const clause of inst || mixin ? [] : (decl.heritageClauses ?? [])) {
1018
+ for (const clause of inst || mixin || computedBase ? [] : (decl.heritageClauses ?? [])) {
743
1019
  // `implements` is pure type-world: tsc checked the conformance and
744
1020
  // the clause erases — nothing about the runtime class changes.
745
1021
  // (Assigning an instance INTO an interface-typed slot is a separate
@@ -754,6 +1030,14 @@ mixin) {
754
1030
  const resolved = memberSym && memberSym.flags & ts.SymbolFlags.Alias
755
1031
  ? lowerer.checker.getAliasedSymbol(memberSym)
756
1032
  : memberSym;
1033
+ const globalError = !t.expression.questionDotToken && lowerer.isStdlibGlobal(t.expression.expression, "globalThis")
1034
+ ? lowerer.builtinErrorInfoOf(resolved) : null;
1035
+ if (globalError && globalError.def.name !== "%DOMException") {
1036
+ if (t.typeArguments)
1037
+ lowerer.unsupported("SC1090", t, "extending generic classes");
1038
+ base = globalError;
1039
+ continue;
1040
+ }
757
1041
  const emitterBase = lowerer.builtinEmitterInfoOf(resolved);
758
1042
  const streamBaseNs = builtinStreamInfoOf(lowerer, resolved);
759
1043
  if (emitterBase || streamBaseNs) {
@@ -768,14 +1052,18 @@ mixin) {
768
1052
  // (the class statement evaluates at its init position; a base
769
1053
  // block below it would still be uninitialized in Node).
770
1054
  if (!t.expression.questionDotToken && nsMemberIdentOf(lowerer, t.expression)) {
771
- if (t.typeArguments)
772
- lowerer.unsupported("SC1090", t, "extending generic classes");
773
1055
  if (memberSym)
774
1056
  fenceEarlyNsMemberRef(lowerer, t.expression, memberSym);
775
- const nsBase = resolved ? lowerer.classBySymbol.get(resolved) : undefined;
1057
+ const stored = storedClassValueType(lowerer, t.expression);
1058
+ const nsBase = (resolved ? lowerer.classBySymbol.get(resolved) : undefined) ??
1059
+ (stored?.kind === "classval" ? lowerer.classes.get(stored.className) : undefined);
776
1060
  if (!nsBase) {
1061
+ if (adoptCallableBase(t.expression))
1062
+ continue;
777
1063
  lowerer.unsupported("SC1090", t, `extending the namespace member '${t.expression.name.text}' (no class lowering)`);
778
1064
  }
1065
+ if (t.typeArguments)
1066
+ lowerer.unsupported("SC1090", t, "extending generic classes");
779
1067
  base = nsBase;
780
1068
  continue;
781
1069
  }
@@ -840,8 +1128,17 @@ mixin) {
840
1128
  base = mixinBase;
841
1129
  continue;
842
1130
  }
1131
+ const stored = storedClassValueType(lowerer, t.expression);
1132
+ const factoryBase = stored?.kind === "classval" ? lowerer.classes.get(stored.className) : undefined;
1133
+ if (factoryBase) {
1134
+ base = factoryBase;
1135
+ factoryBaseExpression = t.expression;
1136
+ continue;
1137
+ }
843
1138
  }
844
1139
  if (!t || !ts.isIdentifier(t.expression)) {
1140
+ if (t && adoptCallableBase(t.expression))
1141
+ continue;
845
1142
  lowerer.unsupported("SC1090", clause, "extending computed expressions");
846
1143
  }
847
1144
  const symbol = lowerer.resolveValueSymbol(t.expression);
@@ -880,7 +1177,11 @@ mixin) {
880
1177
  // A const BINDING of a mixin call (`const Tagged = M(Base);
881
1178
  // class D extends Tagged {}`): the binding pins that call's
882
1179
  // instantiation — collected on demand (lower-mixins.ts).
883
- mixinResultBindingClassOf(lowerer, symbol) ?? null;
1180
+ mixinResultBindingClassOf(lowerer, symbol) ??
1181
+ (() => {
1182
+ const stored = storedClassValueType(lowerer, t.expression);
1183
+ return stored?.kind === "classval" ? lowerer.classes.get(stored.className) : null;
1184
+ })() ?? null;
884
1185
  // `extends Box<number>` — a GENERIC program class as the base: the
885
1186
  // base is the concrete INSTANTIATION, resolved through the heritage
886
1187
  // type (mapType registers/reuses `Box%0`).
@@ -898,13 +1199,43 @@ mixin) {
898
1199
  lowerer.unsupported("SC1090", t, "extending generic classes");
899
1200
  base = named;
900
1201
  if (!base) {
1202
+ if (adoptCallableBase(t.expression))
1203
+ continue;
901
1204
  lowerer.unsupported("SC1090", t, `extending classes not declared in the program ('${t.expression.text}')`);
902
1205
  }
903
1206
  }
1207
+ if (base?.localClass && !functionLocalClass(decl) && !computedBase && !factoryBaseExpression) {
1208
+ const heritage = decl.heritageClauses?.find((clause) => clause.token === ts.SyntaxKind.ExtendsKeyword)?.types[0];
1209
+ if (heritage)
1210
+ factoryBaseExpression = heritage.expression;
1211
+ else
1212
+ lowerer.unsupported("SC1090", decl, "extending a function-local class outside a function");
1213
+ }
1214
+ if (lowerer.collectingExprClasses.has(decl)) {
1215
+ for (let parent = base; parent; parent = parent.base) {
1216
+ if (parent.builtinEmitter || parent.builtinStream !== undefined) {
1217
+ lowerer.unsupported("SC1090", decl, "classes extending builtin bases as values (the inherited runtime constructor has no class-value adapter)");
1218
+ }
1219
+ }
1220
+ }
904
1221
  const fields = new Map(base ? base.fields : []);
905
- const symbolFields = new Map(base?.symbolFields ?? []);
1222
+ const errorRooted = (() => {
1223
+ for (let c = base; c; c = c.base)
1224
+ if (c.builtinError)
1225
+ return true;
1226
+ return false;
1227
+ })();
1228
+ const symbolFields = new Map();
1229
+ if (base?.symbolFields)
1230
+ for (const [symbol, name] of base.symbolFields)
1231
+ symbolFields.set(symbol, name);
1232
+ const symbolMethods = new Map();
1233
+ if (base?.symbolMethods)
1234
+ for (const [symbol, name] of base.symbolMethods)
1235
+ symbolMethods.set(symbol, name);
906
1236
  const fieldOrder = [];
907
1237
  const methods = new Map();
1238
+ const methodEntryFences = new Map();
908
1239
  // Own accessor declarations ("get:x"/"set:x" → node), for the
909
1240
  // partial-override analysis below (diagnostics need the node).
910
1241
  const accessorNodes = new Map();
@@ -929,6 +1260,8 @@ mixin) {
929
1260
  const staticFields = [];
930
1261
  const staticMethods = new Map();
931
1262
  const staticBlocks = [];
1263
+ const runtimeStatics = [];
1264
+ const runtimePrototypeMembers = [];
932
1265
  // GENERIC methods (own type parameters), instance and static: only
933
1266
  // the SYNTAX is checked here — parameter/return types mention the
934
1267
  // type parameters and cannot map yet; bodies lower per call-site
@@ -977,6 +1310,18 @@ mixin) {
977
1310
  });
978
1311
  };
979
1312
  for (const member of decl.members) {
1313
+ if (functionLocalClass(decl) && isJsSourceFile(decl.getSourceFile()) &&
1314
+ (ts.isClassStaticBlockDeclaration(member) || ts.getModifiers(member)?.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword))) {
1315
+ runtimeStatics.push(member);
1316
+ continue;
1317
+ }
1318
+ if (functionLocalClass(decl) && isJsSourceFile(decl.getSourceFile()) &&
1319
+ (ts.isMethodDeclaration(member) || ts.isAccessor(member)) && member.body &&
1320
+ !ts.isPrivateIdentifier(member.name)) {
1321
+ runtimePrototypeMembers.push(member);
1322
+ if (ts.isComputedPropertyName(member.name) && classMemberNameOf(lowerer, member.name) === null)
1323
+ continue;
1324
+ }
980
1325
  if (ts.isClassStaticBlockDeclaration(member)) {
981
1326
  // Statics live on the FAMILY (JS has one class, one static
982
1327
  // storage, however many instantiations exist) — instantiations
@@ -1026,7 +1371,8 @@ mixin) {
1026
1371
  const type = lowerer.irTypeOf(member.name);
1027
1372
  if (type.kind === "void")
1028
1373
  lowerer.badType(member.name, lowerer.typeOf(member.name));
1029
- if (type.kind === "dyn") {
1374
+ if (type.kind === "dyn" && !isJsSourceFile(member.getSourceFile()) &&
1375
+ (member.type !== undefined || (lowerer.typeOf(member.name).flags & ts.TypeFlags.Any) === 0)) {
1030
1376
  lowerer.unsupported("SC1090", member.name, "'unknown'-typed static fields");
1031
1377
  }
1032
1378
  staticFields.push({
@@ -1043,10 +1389,22 @@ mixin) {
1043
1389
  if (ts.isMethodDeclaration(member) &&
1044
1390
  (ts.isIdentifier(member.name) || ts.isPrivateIdentifier(member.name)) &&
1045
1391
  member.body &&
1046
- member.typeParameters === undefined &&
1047
- member.asteriskToken === undefined) {
1392
+ member.typeParameters === undefined) {
1048
1393
  const { shapes, funcType: ft } = lowerer.lambdaSignature(member);
1394
+ if (member.asteriskToken !== undefined && ft.ret.kind !== "generator") {
1395
+ lowerer.badType(member.name, lowerer.typeOf(member.name));
1396
+ }
1049
1397
  staticMethods.set(member.name.text, { params: shapes, ret: ft.ret, member });
1398
+ if (implicitMonoFile(decl.getSourceFile()) && !functionLocalClass(decl) &&
1399
+ inst === undefined && decl.typeParameters === undefined) {
1400
+ const implicit = implicitAnyParamSymbolsOf(lowerer, member, true);
1401
+ if (implicit)
1402
+ genericStatics.set(member.name.text, {
1403
+ decl: member, baseName: member.name.text,
1404
+ qualifiedName: `%${className}.static:${member.name.text}%implicit`,
1405
+ typeParams: [], instances: new Map(), implicitParams: implicit,
1406
+ });
1407
+ }
1050
1408
  }
1051
1409
  // GENERIC static methods monomorphize like top-level generic
1052
1410
  // functions (`%C.static:m%n`), async ones included — a generic
@@ -1075,6 +1433,16 @@ mixin) {
1075
1433
  // 7's ClassElement base carries no `name`; read it structurally
1076
1434
  // (every named member kind stores a PropertyName there).
1077
1435
  const memberName = member.name;
1436
+ if (errorRooted && memberName && classMemberNameOf(lowerer, memberName) === "cause") {
1437
+ if (ts.isPropertyDeclaration(member) && !member.modifiers?.some((m) => m.kind === ts.SyntaxKind.StaticKeyword)) {
1438
+ if (!isJsSourceFile(member.getSourceFile()))
1439
+ lowerer.unsupported("SC1090", memberName, "redeclaring Error.cause (pass the cause in the Error constructor options)");
1440
+ fieldOrder.push({ name: "cause", type: DYN, initializer: member.initializer,
1441
+ ...(member.initializer ? {} : { undefinedInitializer: locOf(member) }), redeclared: true, errorCause: true });
1442
+ continue;
1443
+ }
1444
+ lowerer.unsupported("SC1090", memberName, "Error.cause accessors");
1445
+ }
1078
1446
  // #PRIVATE members compile: their names ('#m') are unspellable by
1079
1447
  // any public identifier, so they ride the ordinary fields/methods
1080
1448
  // maps collision-free — with the base-chain walks doubling as
@@ -1187,6 +1555,40 @@ mixin) {
1187
1555
  // get/set pair — declare the field and accessors explicitly.
1188
1556
  lowerer.unsupported("SC1090", member, "auto-accessor fields ('accessor x')");
1189
1557
  }
1558
+ if (ts.isComputedPropertyName(member.name) || ts.isStringLiteralLike(member.name) || ts.isNumericLiteral(member.name)) {
1559
+ const symbolKey = ts.isComputedPropertyName(member.name) ? classSymbolKeyOf(lowerer, member.name.expression) : null;
1560
+ const stringKey = ts.isComputedPropertyName(member.name) ? lowerer.foldedStringKeyOf(member.name.expression)
1561
+ : ts.isNumericLiteral(member.name) ? String(Number(member.name.text)) : member.name.text;
1562
+ const fieldName = symbolKey?.fieldName ?? stringKey;
1563
+ if (fieldName === null || (!member.initializer && !isJsSourceFile(member.getSourceFile()))) {
1564
+ lowerer.unsupported("SC1090", member, "computed class fields without an initializer and a stable string, number, or module-level literal Symbol()/Symbol.for() key");
1565
+ }
1566
+ const declared = lowerer.typeOf(member);
1567
+ const inferred = member.type || !member.initializer ? declared : lowerer.checker.getBaseTypeOfLiteralType(lowerer.typeOf(member.initializer));
1568
+ const mapped = member.initializer ? lowerer.mapTypeOf(inferred) ?? dynFallbackType(lowerer, member, inferred) : DYN;
1569
+ const type = mapped?.kind === "record" && isJsSourceFile(member.getSourceFile()) && !member.type
1570
+ ? DYN : mapped ? jsOpenObjectType(member, mapped, lowerer.shapes, lowerer.unions) : null;
1571
+ if (!type || type.kind === "void" || (type.kind === "dyn" && !isJsSourceFile(member.getSourceFile())))
1572
+ lowerer.badType(member, inferred);
1573
+ const undefinedInitializer = !member.initializer ? locOf(member) : undefined;
1574
+ const previous = fields.get(fieldName);
1575
+ if (previous) {
1576
+ if (symbolKey && !symbolFields.has(symbolKey.identity)) {
1577
+ lowerer.unsupported("SC1090", member.name, `distinct keys sharing the printable name '${symbolFieldDisplayName(fieldName)}' in one class`);
1578
+ }
1579
+ if (!typeEquals(previous, type)) {
1580
+ lowerer.unsupported("SC1090", member.name, "redeclaring computed fields at a different type");
1581
+ }
1582
+ fieldOrder.push({ name: fieldName, type, initializer: member.initializer, ...(undefinedInitializer ? { undefinedInitializer } : {}), redeclared: true });
1583
+ }
1584
+ else {
1585
+ fields.set(fieldName, type);
1586
+ fieldOrder.push({ name: fieldName, type, initializer: member.initializer, ...(undefinedInitializer ? { undefinedInitializer } : {}) });
1587
+ }
1588
+ if (symbolKey)
1589
+ symbolFields.set(symbolKey.identity, fieldName);
1590
+ continue;
1591
+ }
1190
1592
  // #private fields ride the ordinary field machinery — the '#'
1191
1593
  // name is unspellable publicly, so the slot never collides, and
1192
1594
  // enumeration surfaces (inspect) exclude it like Node.
@@ -1232,14 +1634,27 @@ mixin) {
1232
1634
  // undefined arm (undefFieldInitLineC — Node defines the property
1233
1635
  // as undefined on construction, verified), and reads/writes ride
1234
1636
  // the ordinary undefined-armed union machinery.
1235
- const type = lowerer.irTypeOf(member.name);
1637
+ let type = lowerer.irTypeOf(member.name);
1638
+ // Unannotated JavaScript callback slots retain the original
1639
+ // callable and its receiver instead of adapting its signature.
1640
+ if (isJsSourceFile(member.getSourceFile()) && !member.type &&
1641
+ !/@type\b/.test(member.getSourceFile().text.slice(member.pos, member.getStart())) &&
1642
+ (type.kind === "func" || type.kind === "record") && lowerer.dynConvertible(type))
1643
+ type = DYN;
1644
+ // JS permits reads before a constructor's first assignment even
1645
+ // when its inferred field type omits undefined.
1646
+ if (isJsSourceFile(member.getSourceFile()) && !member.initializer && type.kind !== "dyn") {
1647
+ type = lowerer.withUndefinedArmOf(type) ?? DYN;
1648
+ }
1236
1649
  if (type.kind === "void")
1237
1650
  lowerer.badType(member.name, lowerer.typeOf(member.name));
1238
- // dyn stays out of class fields (KEEP NARROW; record
1239
- // fields and array elements are unmappable via mapType already).
1240
- if (type.kind === "dyn") {
1651
+ // Bundled JS declares fields without annotations before assigning
1652
+ // them in the constructor. Use the same native checked-dynamic
1653
+ // storage as implicit constructor-assigned JS fields.
1654
+ if (type.kind === "dyn" && !isJsSourceFile(member.getSourceFile())) {
1241
1655
  lowerer.unsupported("SC1090", member.name, "'unknown'-typed class fields");
1242
1656
  }
1657
+ const undefinedInitializer = type.kind === "dyn" && !member.initializer ? locOf(member) : undefined;
1243
1658
  if (fields.has(member.name.text)) {
1244
1659
  // REDECLARING an inherited field: Node [[Define]]s the OWN
1245
1660
  // property again when THIS class's field initializers run
@@ -1249,13 +1664,12 @@ mixin) {
1249
1664
  // slot, no new slot, no layout change (the `class
1250
1665
  // ConfigError extends Error { name = "ConfigError" }`; the
1251
1666
  // builtin Error prefix included — reads, toString, and throw
1252
- // reports all answer the overwritten name like Node). A BARE
1253
- // redeclare writes undefined in Node (`class B extends A
1254
- // { x; }` reads undefined!) and a type-changing redeclare has
1255
- // no single slot type — both keep the fence.
1667
+ // reports all answer the overwritten name like Node). A bare
1668
+ // JS dyn redeclaration resets the existing slot to undefined.
1669
+ // Other bare or type-changing redeclarations keep the fence.
1256
1670
  const baseType = fields.get(member.name.text);
1257
- if (member.initializer && typeEquals(type, baseType)) {
1258
- fieldOrder.push({ name: member.name.text, type, initializer: member.initializer, redeclared: true });
1671
+ if ((member.initializer || type.kind === "dyn") && typeEquals(type, baseType)) {
1672
+ fieldOrder.push({ name: member.name.text, type, initializer: member.initializer, ...(undefinedInitializer ? { undefinedInitializer } : {}), redeclared: true });
1259
1673
  continue;
1260
1674
  }
1261
1675
  lowerer.unsupported("SC1090", member.name, member.initializer
@@ -1280,7 +1694,7 @@ mixin) {
1280
1694
  // (the constructor may be declared later in the class body).
1281
1695
  const admitsUndefined = (type.kind === "union" &&
1282
1696
  (lowerer.unions.get(type.unionId)?.arms.some((a) => a.kind === "undefinedT") ?? false)) ||
1283
- type.kind === "jsval";
1697
+ type.kind === "jsval" || type.kind === "dyn";
1284
1698
  if (!member.initializer && !admitsUndefined) {
1285
1699
  const opts = lowerer.program.getCompilerOptions();
1286
1700
  const spi = opts.strictPropertyInitialization ?? opts.strict ?? false;
@@ -1300,7 +1714,7 @@ mixin) {
1300
1714
  }
1301
1715
  }
1302
1716
  fields.set(member.name.text, type);
1303
- fieldOrder.push({ name: member.name.text, type, initializer: member.initializer });
1717
+ fieldOrder.push({ name: member.name.text, type, initializer: member.initializer, ...(undefinedInitializer ? { undefinedInitializer } : {}) });
1304
1718
  }
1305
1719
  else if (ts.isConstructorDeclaration(member)) {
1306
1720
  // A body-less constructor is an OVERLOAD SIGNATURE: type-world,
@@ -1344,6 +1758,9 @@ mixin) {
1344
1758
  lowerer.unsupported("SC1090", p, "this parameter property form");
1345
1759
  }
1346
1760
  const name = p.name.text;
1761
+ if (errorRooted && name === "cause") {
1762
+ lowerer.unsupported("SC1090", p.name, "redeclaring Error.cause (pass the cause in the Error constructor options)");
1763
+ }
1347
1764
  const shape = lowerer.paramShape(p);
1348
1765
  const type = shape.bodyType ?? shape.type;
1349
1766
  if (type.kind === "void")
@@ -1368,15 +1785,18 @@ mixin) {
1368
1785
  const mName = classMemberNameOf(lowerer, member.name);
1369
1786
  if (mName === null)
1370
1787
  lowerer.unsupported("SC1090", member, "computed method names");
1371
- // Sync PUBLIC generator methods stay fenced because virtualCall
1372
- // dispatch cannot hold spawn wrappers. Async generator methods
1373
- // use the existing static async-method dispatch discipline;
1374
- // overrides fence below. #private generators are always direct.
1375
- const asyncGenerator = member.asteriskToken !== undefined &&
1376
- member.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword) === true;
1377
- if (member.asteriskToken !== undefined && !asyncGenerator && !ts.isPrivateIdentifier(member.name)) {
1378
- lowerer.unsupported("SC1071", member, "generator methods (a #private generator method compiles — privates never dispatch dynamically; or declare a module-level function* and call it from the method)");
1788
+ if (ts.isComputedPropertyName(member.name)) {
1789
+ const key = classSymbolKeyOf(lowerer, member.name.expression);
1790
+ if (key) {
1791
+ if ([...symbolMethods, ...symbolFields].some(([identity, name]) => name === mName && identity !== key.identity)) {
1792
+ lowerer.unsupported("SC1090", member.name, `distinct symbol keys sharing the printable name '${symbolFieldDisplayName(mName)}' in one class`);
1793
+ }
1794
+ symbolMethods.set(key.identity, mName);
1795
+ }
1379
1796
  }
1797
+ // Generator calls use their spawn wrapper. Public methods are
1798
+ // direct calls only when no subclass overrides the method;
1799
+ // override chains involving generators fence below.
1380
1800
  // An ABSTRACT method is a signature with no body — type-world,
1381
1801
  // except that it declares the vtable slot: calls through
1382
1802
  // base-typed receivers are ordinary virtual dispatch, and tsc
@@ -1431,20 +1851,9 @@ mixin) {
1431
1851
  collectGenericMember(member, false);
1432
1852
  continue;
1433
1853
  }
1434
- // Async METHODS in JS classes simply do not COLLECT — each call
1435
- // fences at its own site (the JS deferral stance, the
1436
- // async-static precedent above), so a class whose driven
1437
- // surface is synchronous still compiles (commander: parse()
1438
- // works, parseAsync() traps where called). TS async methods
1439
- // collect below like any method: the body is an async
1440
- // IrFunction (fiber spawn wrapper, `this` as param 0), calls
1441
- // dispatch STATICALLY — override chains fence (the vtable slot
1442
- // machinery has no fiber-spawn story), so every call site is a
1443
- // direct call the emitter routes through the spawn wrapper.
1444
- if (member.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword) &&
1445
- isJsSourceFile(decl.getSourceFile())) {
1446
- continue;
1447
- }
1854
+ // Async methods collect with the same direct-call spawn wrapper
1855
+ // for JavaScript and TypeScript classes. Override chains remain
1856
+ // fenced below because vtable slots cannot enter that wrapper.
1448
1857
  // IMPLICIT-ANY monomorphization (npm-static JS): a method whose
1449
1858
  // signature carries bindable untyped params collects like a
1450
1859
  // GENERIC method — into genericMethods, no vtable slot, one
@@ -1454,13 +1863,14 @@ mixin) {
1454
1863
  // dispatch worlds could meet: an inherited declaration of the
1455
1864
  // name (the override stays on the vtable), a shadowed field, or
1456
1865
  // a generic-class instantiation's member.
1457
- if (implicitMonoFile(decl.getSourceFile()) &&
1866
+ if (implicitMonoFile(decl.getSourceFile()) && !functionLocalClass(decl) &&
1458
1867
  ts.isIdentifier(member.name) &&
1868
+ !lowerer.virtualJsMethods.has(member) && !lowerer.prototypeMethodAccesses.has(member.name.text) &&
1459
1869
  inst === undefined && decl.typeParameters === undefined &&
1460
1870
  !fields.has(member.name.text) &&
1461
1871
  !lowerer.findMethodOn(base, member.name.text) &&
1462
1872
  !findGenericMethodOn(lowerer, base, member.name.text)) {
1463
- const implicit = implicitAnyParamSymbolsOf(lowerer, member);
1873
+ const implicit = implicitAnyParamSymbolsOf(lowerer, member, true);
1464
1874
  if (implicit) {
1465
1875
  genericMethods.set(member.name.text, {
1466
1876
  decl: member,
@@ -1474,6 +1884,31 @@ mixin) {
1474
1884
  }
1475
1885
  }
1476
1886
  const { shapes, funcType: ft } = lowerer.lambdaSignature(member);
1887
+ // JS inference may retain only a symbol sentinel while a method
1888
+ // also returns values from an untyped mutable field or local.
1889
+ if (isJsSourceFile(member.getSourceFile()) && !member.type && !hasExplicitJsDocReturn(member) && ft.ret.kind === "symbol")
1890
+ ft.ret = DYN;
1891
+ if (isJsSourceFile(member.getSourceFile()) && lowerer.prototypeMethodAccesses.has(mName) &&
1892
+ !lowerer.findMethodOn(base, mName)?.declarer.def.runtime &&
1893
+ shapes.every((p) => p.mode === "required" || p.mode === "omittable")) {
1894
+ for (const shape of shapes) {
1895
+ shape.type = DYN;
1896
+ if (shape.bodyType)
1897
+ shape.bodyType = DYN;
1898
+ }
1899
+ ft.params = shapes.map((shape) => shape.type);
1900
+ if (ft.ret.kind !== "void")
1901
+ ft.ret = DYN;
1902
+ }
1903
+ // JS subclasses can add parameters to a method. Reserve checked
1904
+ // argument slots in the base before constructing its vtable; shorter
1905
+ // bodies ignore them and omitted call arguments become undefined.
1906
+ const virtualArity = lowerer.virtualJsMethodArity.get(member) ?? shapes.length;
1907
+ if (virtualArity > shapes.length && !bodyReadsArguments(member) &&
1908
+ shapes.every((p) => p.type.kind === "dyn" && (p.mode === "required" || p.mode === "omittable"))) {
1909
+ while (shapes.length < virtualArity)
1910
+ shapes.push({ type: DYN, mode: "omittable" });
1911
+ }
1477
1912
  if (fields.has(mName)) {
1478
1913
  lowerer.unsupported("SC1090", member.name, "methods shadowing inherited fields");
1479
1914
  }
@@ -1499,17 +1934,78 @@ mixin) {
1499
1934
  // against the STATIC receiver's shape, so `m(x?: number)` and
1500
1935
  // `m(x: number | undefined)` interchange soundly in overrides.
1501
1936
  const overridden = lowerer.findMethodOn(base, mName);
1502
- if (overridden?.declarer.builtinError) {
1503
- // Error.prototype.toString is a runtime implementation with no
1504
- // vtable slot — calls to it are direct, so an override could
1505
- // never be reached through a base-typed receiver.
1506
- lowerer.unsupported("SC1090", member.name, `overriding the builtin Error method '${mName}'`);
1937
+ if (overridden && isJsSourceFile(member.getSourceFile())) {
1938
+ // An unannotated JS override can return a checked value into
1939
+ // the inherited native ABI, just as its untyped parameters do.
1940
+ // Body lowering inserts the conversion at each return.
1941
+ if (!member.type && ft.ret.kind === "dyn" && overridden.sig.ret.kind !== "dyn" &&
1942
+ !overridden.sig.async && !overridden.sig.gen)
1943
+ ft.ret = overridden.sig.ret;
1944
+ // Fluent overrides return the same native receiver. Keep the
1945
+ // inherited return ABI and upcast `this` when lowering returns.
1946
+ if (overridden.sig.ret.kind === "object" && base &&
1947
+ (base.def.name === overridden.sig.ret.className || lowerer.isSubclassOf(base.def.name, overridden.sig.ret.className)) &&
1948
+ returnsOnlyThis(member))
1949
+ ft.ret = overridden.sig.ret;
1950
+ // An unannotated JS parameter can use the base's typed ABI.
1951
+ // Defaults stay local to each declaration, so only inherited
1952
+ // required/optional slots participate in this refinement.
1953
+ for (let i = 0; i < shapes.length; i++) {
1954
+ const parameter = member.parameters[i];
1955
+ const inherited = overridden.sig.params[i];
1956
+ if (parameter && inherited && !parameter.type && !parameter.initializer && !parameter.dotDotDotToken &&
1957
+ shapes[i].type.kind === "dyn" && inherited.type.kind !== "dyn" &&
1958
+ (inherited.mode === "required" || inherited.mode === "omittable")) {
1959
+ shapes[i] = { ...inherited };
1960
+ }
1961
+ }
1962
+ }
1963
+ // JS overrides may ignore trailing arguments. Retain the base's
1964
+ // checked-value ABI slots as unused parameters, and let shorter
1965
+ // calls fill them with undefined. Typed tails and rest/arguments
1966
+ // readers keep the exact-signature fence.
1967
+ if (overridden && isJsSourceFile(member.getSourceFile()) &&
1968
+ shapes.length < overridden.sig.params.length &&
1969
+ !bodyReadsArguments(member) &&
1970
+ shapes.every((p, i) => (p.mode === "required" || p.mode === "omittable") && typeEquals(p.type, overridden.sig.params[i].type)) &&
1971
+ overridden.sig.params.slice(shapes.length).every((p) => p.type.kind === "dyn" && (p.mode === "required" || p.mode === "omittable"))) {
1972
+ shapes.push(...overridden.sig.params.slice(shapes.length).map((p) => ({ type: p.type, mode: "omittable" })));
1507
1973
  }
1508
1974
  if (overridden &&
1509
1975
  (overridden.sig.params.length !== shapes.length ||
1510
1976
  !overridden.sig.params.every((p, i) => typeEquals(p.type, shapes[i].type)) ||
1511
1977
  !typeEquals(overridden.sig.ret, ft.ret))) {
1512
- lowerer.unsupported("SC1090", member.name, "overriding a method with a different signature (parameter and return types must match the base declaration exactly)");
1978
+ const fencedJsOverride = isJsSourceFile(member.getSourceFile()) &&
1979
+ overridden.declarer.decl !== null && isJsSourceFile(overridden.declarer.decl.getSourceFile()) &&
1980
+ member.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword) !== true &&
1981
+ overridden.sig.async !== true &&
1982
+ member.asteriskToken === undefined && overridden.sig.gen === undefined;
1983
+ if (fencedJsOverride) {
1984
+ // A dormant JS method must not poison the whole class. Keep
1985
+ // the inherited call/dispatch ABI and refuse at method entry;
1986
+ // lowering this body with the base signature would change JS.
1987
+ const returnOnly = overridden.sig.params.length === shapes.length &&
1988
+ overridden.sig.params.every((p, i) => typeEquals(p.type, shapes[i].type)) &&
1989
+ !member.parameters.some((parameter, index) => {
1990
+ if (!parameter.initializer)
1991
+ return false;
1992
+ const baseMember = overridden.declarer.decl?.members.find((candidate) => ts.isMethodDeclaration(candidate) && classMemberNameOf(lowerer, candidate.name) === mName);
1993
+ const inherited = baseMember && ts.isMethodDeclaration(baseMember) ? baseMember.parameters[index]?.initializer : undefined;
1994
+ if (!inherited)
1995
+ return false;
1996
+ const ownType = lowerer.mapTypeOf(lowerer.typeOf(parameter.initializer));
1997
+ const baseType = lowerer.mapTypeOf(lowerer.typeOf(inherited));
1998
+ return ownType !== null && baseType !== null && !typeEquals(ownType, baseType);
1999
+ });
2000
+ methodEntryFences.set(mName, unsupportedDiag("SC1090", locOf(member.name), returnOnly
2001
+ ? `overriding method '${mName}' with a different return type (the native return type must match the base declaration exactly)`
2002
+ : `overriding method '${mName}' with a different signature (the native parameter and return types must match the base declaration exactly)`));
2003
+ shapes.splice(0, shapes.length, ...overridden.sig.params);
2004
+ ft.ret = overridden.sig.ret;
2005
+ }
2006
+ else {
2007
+ lowerer.unsupported("SC1090", member.name, "overriding a method with a different signature (parameter and return types must match the base declaration exactly)");
2008
+ }
1513
2009
  }
1514
2010
  const asyncMember = member.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword) === true;
1515
2011
  // Async methods dispatch STATICALLY (the body enters through its
@@ -1519,7 +2015,10 @@ mixin) {
1519
2015
  if (overridden && (asyncMember || overridden.sig.async === true)) {
1520
2016
  lowerer.unsupported("SC1090", member.name, `overriding ${overridden.sig.async === true ? "the async method" : "a method with an async method"} '${mName}' (async methods dispatch statically — the vtable slot machinery has no fiber-spawn story)`);
1521
2017
  }
1522
- // A #private GENERATOR method carries its channels on the sig:
2018
+ if (overridden && (member.asteriskToken !== undefined || overridden.sig.gen !== undefined)) {
2019
+ lowerer.unsupported("SC1090", member.name, `overriding the generator method '${mName}' (generator methods dispatch statically — a virtual slot cannot enter their spawn wrapper)`);
2020
+ }
2021
+ // A GENERATOR method carries its channels on the sig:
1523
2022
  // the body lowers as a generator IrFunction (`this` as param 0),
1524
2023
  // and every call — direct by construction — enters through the
1525
2024
  // emitted gen-spawn wrapper, answering the suspended generator.
@@ -1552,9 +2051,19 @@ mixin) {
1552
2051
  const isGet = ts.isGetAccessor(member);
1553
2052
  // #private accessors collect as "get:#x"/"set:#x" — the same
1554
2053
  // reserved spelling, one more unspellable segment.
1555
- if (!ts.isIdentifier(member.name) && !ts.isPrivateIdentifier(member.name)) {
2054
+ const prop = classMemberNameOf(lowerer, member.name);
2055
+ if (prop === null) {
1556
2056
  lowerer.unsupported("SC1090", member, "computed accessor names");
1557
2057
  }
2058
+ if (ts.isComputedPropertyName(member.name)) {
2059
+ const key = classSymbolKeyOf(lowerer, member.name.expression);
2060
+ if (key) {
2061
+ if ([...symbolMethods, ...symbolFields].some(([identity, name]) => name === prop && identity !== key.identity)) {
2062
+ lowerer.unsupported("SC1090", member.name, `distinct symbol keys sharing the printable name '${symbolFieldDisplayName(prop)}' in one class`);
2063
+ }
2064
+ symbolMethods.set(key.identity, prop);
2065
+ }
2066
+ }
1558
2067
  // ABSTRACT accessors are the abstract-method story with property
1559
2068
  // syntax: body-less by definition, they enter `methods` (marked
1560
2069
  // abstract) as their "get:x"/"set:x" halves — slot declaration
@@ -1562,9 +2071,8 @@ mixin) {
1562
2071
  const abstractAccessor = ts.getModifiers(member)?.some((m) => m.kind === ts.SyntaxKind.AbstractKeyword) === true;
1563
2072
  if (!member.body && !abstractAccessor)
1564
2073
  lowerer.unsupported("SC1090", member, "bodyless accessors");
1565
- const prop = member.name.text;
1566
2074
  const mName = `${isGet ? "get" : "set"}:${prop}`;
1567
- if (fields.has(prop)) {
2075
+ if (fields.has(prop) && !((prop === "message" || prop === "name") && base && (base.def.name === "%Error" || lowerer.isSubclassOf(base.def.name, "%Error")))) {
1568
2076
  // tsc rejects field/accessor mixing (TS2610/2611); defensive.
1569
2077
  lowerer.unsupported("SC1090", member.name, "accessors sharing a name with a field");
1570
2078
  }
@@ -1609,7 +2117,7 @@ mixin) {
1609
2117
  lowerer.unsupported("SC1090", member, "index signatures");
1610
2118
  }
1611
2119
  else if (!ts.isSemicolonClassElement(member)) {
1612
- lowerer.unsupported("SC1090", member, `syntax '${ts.SyntaxKind[member.kind]}'`);
2120
+ lowerer.unsupported("SC1090", member, `syntax '${ts.syntaxKindName(member.kind)}'`);
1613
2121
  }
1614
2122
  }
1615
2123
  // Parameter properties join the shape FIRST among own fields —
@@ -1724,6 +2232,9 @@ mixin) {
1724
2232
  // forbids via strictPropertyInitialization — so they keep a named
1725
2233
  // fence instead of a silent undefined.
1726
2234
  if (isJsSourceFile(decl.getSourceFile())) {
2235
+ const hasAccessor = (name) => methods.has(`get:${name}`) || methods.has(`set:${name}`) ||
2236
+ lowerer.findMethodOn(base, `get:${name}`) !== null ||
2237
+ lowerer.findMethodOn(base, `set:${name}`) !== null;
1727
2238
  // Named classes (declarations and self-binding expressions) resolve
1728
2239
  // by name; the nameless default-export declaration by its module's
1729
2240
  // default-export symbol.
@@ -1755,9 +2266,11 @@ mixin) {
1755
2266
  lhs.expression.kind === ts.SyntaxKind.ThisKeyword) {
1756
2267
  const assign = lhs;
1757
2268
  const name = assign.name.text;
2269
+ if (errorRooted && name === "cause")
2270
+ continue;
1758
2271
  // Later assignments to an already-declared field (own or
1759
2272
  // inherited) are writes, not declarations.
1760
- if (fields.has(name))
2273
+ if (fields.has(name) || hasAccessor(name))
1761
2274
  continue;
1762
2275
  if (methods.has(name) || lowerer.findMethodOn(base, name)) {
1763
2276
  lowerer.unsupported("SC1090", assign, "constructor-assigned fields shadowing methods");
@@ -1772,11 +2285,16 @@ mixin) {
1772
2285
  // TS-annotated `unknown` fields keep their fence (KEEP NARROW
1773
2286
  // applies where an annotation could say better).
1774
2287
  let type = t ? (lowerer.mapTypeOf(t) ?? dynFallbackType(lowerer, assign, t)) : null;
2288
+ if (t && (t.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined)) !== 0 && isJsSourceFile(decl.getSourceFile()))
2289
+ type = DYN;
2290
+ if (type)
2291
+ type = jsOpenObjectType(assign, type, lowerer.shapes, lowerer.unions);
1775
2292
  if (type?.kind === "dyn") {
1776
2293
  type = inferredEmptyCollectionFieldType(lowerer, decl, name, rhs) ?? type;
1777
2294
  }
1778
2295
  if (!type || type.kind === "void")
1779
2296
  lowerer.badType(assign, t ?? lowerer.typeOf(assign));
2297
+ type = jsFieldInitializerType(lowerer, type, rhs);
1780
2298
  // A JSDoc claim the BODY contradicts (`@type {Command}`
1781
2299
  // assigned `undefined` — the lazy-init idiom): the
1782
2300
  // representation follows the body — the field widens to the
@@ -1801,7 +2319,7 @@ mixin) {
1801
2319
  continue;
1802
2320
  }
1803
2321
  // `this[kLimit] = v` at the constructor's top level with a
1804
- // STATICALLY-RESOLVABLE unique-symbol key (uniqueSymbolKeyOf's
2322
+ // STATICALLY-RESOLVABLE symbol key (classSymbolKeyOf's
1805
2323
  // contract — the countdown.js idiom): the key is a compile-time
1806
2324
  // identity, so the member is an ordinary hidden field of the
1807
2325
  // static layout under Node's inspect spelling; no runtime
@@ -1811,19 +2329,30 @@ mixin) {
1811
2329
  // late-bound fence below.
1812
2330
  if (lhs && ts.isElementAccessExpression(lhs) &&
1813
2331
  lhs.expression.kind === ts.SyntaxKind.ThisKeyword) {
1814
- const key = uniqueSymbolKeyOf(lowerer, lhs.argumentExpression);
1815
- if (!key)
2332
+ const key = classSymbolKeyOf(lowerer, lhs.argumentExpression);
2333
+ const stringKey = lowerer.foldedStringKeyOf(lhs.argumentExpression);
2334
+ const fieldName = key?.fieldName ?? stringKey;
2335
+ if (fieldName === null) {
2336
+ if (lowerer.mapTypeOf(lowerer.typeOf(lhs.argumentExpression))?.kind === "symbol") {
2337
+ lowerer.unsupported("SC1090", lhs, "symbol-keyed class fields require a stable module-level key");
2338
+ }
2339
+ continue;
2340
+ }
2341
+ if (!key && (fields.has(fieldName) || hasAccessor(fieldName)))
1816
2342
  continue;
2343
+ if (!key && (methods.has(fieldName) || lowerer.findMethodOn(base, fieldName))) {
2344
+ lowerer.unsupported("SC1090", lhs, "constructor-assigned fields shadowing methods");
2345
+ }
1817
2346
  // A key already declared (own or inherited) makes later
1818
2347
  // assignments writes, not declarations.
1819
- if (symbolFields.has(key.sym))
2348
+ if (key && symbolFields.has(key.identity))
1820
2349
  continue;
1821
- if (fields.has(key.fieldName)) {
2350
+ if (fields.has(fieldName)) {
1822
2351
  // Two DISTINCT Symbol(...) consts with one description in
1823
2352
  // one layout would need one printable name for two slots.
1824
- lowerer.unsupported("SC1090", lhs, `distinct symbol keys sharing the printable name '${key.fieldName}' in one class`);
2353
+ lowerer.unsupported("SC1090", lhs, `distinct symbol keys sharing the printable name '${symbolFieldDisplayName(fieldName)}' in one class`);
1825
2354
  }
1826
- const propSym = lateBoundByKey.get(key.sym);
2355
+ const propSym = key ? lateBoundByKey.get(key.sym) : instType ? lowerer.checker.getPropertyOfType(instType, fieldName) : undefined;
1827
2356
  // tsgo does not synthesize the late-bound `__@name@id`
1828
2357
  // property for a JS `this[k] = v` declaration (the finding-5
1829
2358
  // family: no expando/late-bound synthesis in its stricter
@@ -1838,12 +2367,15 @@ mixin) {
1838
2367
  : rhs
1839
2368
  ? lowerer.checker.getBaseTypeOfLiteralType(lowerer.checker.getTypeAtLocation(rhs))
1840
2369
  : undefined;
1841
- const type = t ? (lowerer.mapTypeOf(t) ?? dynFallbackType(lowerer, lhs, t)) : null;
2370
+ let type = t ? (lowerer.mapTypeOf(t) ?? dynFallbackType(lowerer, lhs, t)) : null;
2371
+ if (type)
2372
+ type = jsOpenObjectType(lhs, type, lowerer.shapes, lowerer.unions);
1842
2373
  if (!type || type.kind === "void")
1843
2374
  lowerer.badType(lhs, t ?? lowerer.typeOf(lhs));
1844
- fields.set(key.fieldName, type);
1845
- symbolFields.set(key.sym, key.fieldName);
1846
- fieldOrder.push({ name: key.fieldName, type, initializer: undefined });
2375
+ fields.set(fieldName, type);
2376
+ if (key)
2377
+ symbolFields.set(key.identity, fieldName);
2378
+ fieldOrder.push({ name: fieldName, type, initializer: undefined });
1847
2379
  }
1848
2380
  }
1849
2381
  }
@@ -1853,9 +2385,11 @@ mixin) {
1853
2385
  // static layouts cannot represent. Named fence, at the first
1854
2386
  // assignment site.
1855
2387
  for (const p of instType ? lowerer.checker.getPropertiesOfType(instType) : []) {
2388
+ if (errorRooted && p.name === "cause")
2389
+ continue;
1856
2390
  if (fields.has(p.name) || methods.has(p.name))
1857
2391
  continue;
1858
- if (methods.has(`get:${p.name}`) || methods.has(`set:${p.name}`))
2392
+ if (hasAccessor(p.name))
1859
2393
  continue;
1860
2394
  if (base && (base.fields.has(p.name) || lowerer.findMethodOn(base, p.name)))
1861
2395
  continue;
@@ -1866,14 +2400,15 @@ mixin) {
1866
2400
  // Late-bound properties: the ones the scan above collected are
1867
2401
  // real fields under their printable names — skip. The rest keep
1868
2402
  // a fence that names the supported form: keys that are runtime
1869
- // identities (symbol parameters, Symbol.for consts, computed
2403
+ // identities (symbol parameters, mutable bindings, computed
1870
2404
  // descriptions) or assignments outside the constructor's top
1871
2405
  // level.
1872
2406
  if (p.name.startsWith("__@")) {
1873
2407
  const keySym = lateBoundKeySymOf(lowerer, p);
1874
- if (keySym && symbolFields.has(keySym))
2408
+ const key = keySym ? classSymbolKeyOfSymbol(lowerer, keySym) : null;
2409
+ if (key && symbolFields.has(key.identity))
1875
2410
  continue;
1876
- lowerer.unsupported("SC1090", site, "symbol-keyed class fields outside the supported form (a module-level `const k = Symbol('desc')` key, assigned unconditionally at the top of the constructor)");
2411
+ lowerer.unsupported("SC1090", site, "symbol-keyed class fields outside the supported form (a stable module-level literal Symbol()/Symbol.for() key, assigned unconditionally at the top of the constructor)");
1877
2412
  }
1878
2413
  // JS classes: a property first assigned in a method or a
1879
2414
  // conditional constructor position holds `undefined` until the
@@ -1888,6 +2423,11 @@ mixin) {
1888
2423
  if (isJsSourceFile(decl.getSourceFile())) {
1889
2424
  const armed = undefArmedFieldType(lowerer, p);
1890
2425
  if (armed !== null) {
2426
+ // Unknown JS properties use the instance bag: they do not
2427
+ // exist until assigned, and a subclass may declare the same
2428
+ // name as an ordinary layout field.
2429
+ if (armed.kind === "dyn")
2430
+ continue;
1891
2431
  fields.set(p.name, armed);
1892
2432
  fieldOrder.push({ name: p.name, type: armed, initializer: undefined });
1893
2433
  continue;
@@ -1925,8 +2465,14 @@ mixin) {
1925
2465
  // synthesized constructor forwards the same params to super).
1926
2466
  const ctorParams = ctor && !mixinForwarding
1927
2467
  ? lowerer.paramShapes(ctor.parameters)
1928
- : (base?.ctorParams ?? []);
2468
+ : (base?.ctorParams ?? (callableBase ? [{ type: DYN, mode: "dynRest" }] : []));
2469
+ if (ctor && !mixinForwarding && isJsSourceFile(ctor.getSourceFile()) &&
2470
+ !ctorParams.some((shape) => shape.mode === "rest" || shape.mode === "dynRest" || shape.mode === "islandRest") && bodyReadsArguments(ctor)) {
2471
+ ctorParams.push({ type: DYN, mode: "arguments" });
2472
+ }
1929
2473
  const info = {
2474
+ ...(runtimeStatics.length ? { runtimeStatics } : {}),
2475
+ ...(runtimePrototypeMembers.length ? { runtimePrototypeMembers } : {}),
1930
2476
  def: {
1931
2477
  name: className,
1932
2478
  // The JS-observable .name (the class object's name string and
@@ -1935,6 +2481,9 @@ mixin) {
1935
2481
  // INSTANTIATION prints its family's name — JS has one `Box`.
1936
2482
  jsName: jsNameOverride ?? decl.name?.text ?? "",
1937
2483
  ...(base ? { base: base.def.name } : {}),
2484
+ jsLength: ctor?.parameters.findIndex((parameter) => parameter.initializer || parameter.dotDotDotToken) === -1
2485
+ ? ctor.parameters.length
2486
+ : Math.max(0, ctor?.parameters.findIndex((parameter) => parameter.initializer || parameter.dotDotDotToken) ?? 0),
1938
2487
  // Layout order: the base chain's fields as an IDENTICAL prefix,
1939
2488
  // then this class's own — what makes an upcast a reinterpret.
1940
2489
  // Redeclared INHERITED fields contribute no slot (their
@@ -1955,18 +2504,22 @@ mixin) {
1955
2504
  fields,
1956
2505
  fieldOrder,
1957
2506
  methods,
2507
+ ...(methodEntryFences.size > 0 ? { methodEntryFences } : {}),
1958
2508
  decl,
1959
2509
  ...(emitOverride !== undefined ? { emitOverride } : {}),
1960
2510
  ctor,
1961
2511
  ctorParams,
1962
2512
  ...(paramProps.length > 0 ? { paramProps } : {}),
1963
2513
  base,
2514
+ ...(callableBase ? { callableBase } : {}),
2515
+ ...(factoryBaseExpression ? { factoryBaseExpression } : {}),
1964
2516
  subclasses: [],
1965
2517
  throwingSetters,
1966
2518
  staticFields,
1967
2519
  ...(staticMethods.size > 0 ? { staticMethods } : {}),
1968
2520
  ...(staticBlocks.length > 0 ? { staticBlocks } : {}),
1969
2521
  ...(symbolFields.size > 0 ? { symbolFields } : {}),
2522
+ ...(symbolMethods.size > 0 ? { symbolMethods } : {}),
1970
2523
  ...(classDecoratorNodes.length > 0 ? { classDecorators: { nodes: classDecoratorNodes } } : {}),
1971
2524
  ...(deferredInitFields.size > 0 ? { deferredInitFields } : {}),
1972
2525
  };
@@ -2020,6 +2573,17 @@ mixin) {
2020
2573
  if (base)
2021
2574
  base.subclasses.push(info);
2022
2575
  lowerer.classes.set(className, info);
2576
+ if (computedBase && !functionLocalClass(decl)) {
2577
+ info.def.baseValueGlobal = `%g.${className}.computedBase`;
2578
+ lowerer.globalsList.push({ id: info.def.baseValueGlobal, name: `${className} base`, type: computedBase.value.type, mutable: false });
2579
+ }
2580
+ if (factoryBaseExpression && !functionLocalClass(decl)) {
2581
+ info.def.baseValueGlobal = `%g.${className}.computedBase`;
2582
+ lowerer.globalsList.push({ id: info.def.baseValueGlobal, name: `${className} base`, type: { kind: "classval", className: base.def.name }, mutable: false });
2583
+ }
2584
+ if (callableBase && !functionLocalClass(decl)) {
2585
+ lowerer.globalsList.push({ id: callableBase.constructorId, name: `${className} base`, type: DYN, mutable: false }, { id: callableBase.prototypeId, name: `${className} base prototype`, type: DYN, mutable: false });
2586
+ }
2023
2587
  // A NAMED class binds its name (declarations in their scope, class
2024
2588
  // expressions inside their own bodies — tsc resolves both to this
2025
2589
  // symbol); a nameless default-export declaration binds its module's
@@ -2051,7 +2615,7 @@ mixin) {
2051
2615
  * unmapped, the fenced-JS-class story. Null answers (unmappable type
2052
2616
  * arguments, the instance cap, an uncollected family) make the whole
2053
2617
  * reference unmappable — per-site diagnostics own the fence. */
2054
- export function genericClassInstanceType(lowerer, decl, ref) {
2618
+ export function genericClassInstanceType(lowerer, decl, ref, mapArgument) {
2055
2619
  const gci = lowerer.genericClassByDecl.get(decl);
2056
2620
  if (!gci) {
2057
2621
  // The family never collected (a deferred/poisoned declaration): the
@@ -2078,7 +2642,7 @@ export function genericClassInstanceType(lowerer, decl, ref) {
2078
2642
  const mapped = [];
2079
2643
  if (args.length === gci.typeParams.length) {
2080
2644
  for (const a of args) {
2081
- const m = lowerer.mapTypeOf(a);
2645
+ const m = lowerer.mapTypeOf(a, mapArgument);
2082
2646
  if (!m || m.kind === "void") {
2083
2647
  // An UNBOUND type parameter argument (`Box<T>` outside any
2084
2648
  // instantiation) stays honestly unmapped — nothing concrete is
@@ -2207,10 +2771,28 @@ function withInstanceBindings(lowerer, info, fn) {
2207
2771
  * field, like fieldInitStmts; a block lowers as the block statement it
2208
2772
  * is, so its statements poison individually inside lowerStmts. */
2209
2773
  export function lowerStaticFieldInits(lowerer, info) {
2774
+ if (info.localClass)
2775
+ return [];
2210
2776
  // Mixin instantiations lower their initializers under the
2211
2777
  // instantiation's bindings/context (a no-op for everything else —
2212
2778
  // generic FAMILIES own their statics and carry no genericInstance).
2213
- return withInstanceBindings(lowerer, info, () => lowerStaticFieldInitsInner(lowerer, info));
2779
+ const diagsBefore = lowerer.diags.length;
2780
+ try {
2781
+ return withInstanceBindings(lowerer, info, () => lowerStaticFieldInitsInner(lowerer, info));
2782
+ }
2783
+ catch (error) {
2784
+ // Heritage and decorators run before the per-field recovery below.
2785
+ // Keep their refusal attached to the class declaration instead of
2786
+ // letting a poisoned initializer escape the module lowering pass.
2787
+ if (!(error instanceof PoisonError))
2788
+ throw error;
2789
+ if (info.decl && isJsSourceFile(info.decl.getSourceFile()) && lowerer.diagSink === null) {
2790
+ const fence = lowerer.deferToRuntimeFence(diagsBefore, info.decl, { kind: "statement" });
2791
+ if (fence)
2792
+ return [fence];
2793
+ }
2794
+ return [];
2795
+ }
2214
2796
  }
2215
2797
  function lowerStaticFieldInitsInner(lowerer, info) {
2216
2798
  // Decoration first: TC39 evaluates decorator expressions, creates the
@@ -2218,6 +2800,39 @@ function lowerStaticFieldInitsInner(lowerer, info) {
2218
2800
  // initializers and static blocks (verified against Node — the
2219
2801
  // decorated result is what `this`/the class name mean inside them).
2220
2802
  const out = [...lowerClassDecoration(lowerer, info)];
2803
+ const computedBase = info.decl ? lowerer.computedClassBases.get(lowerer.classNamer(info.decl)) : undefined;
2804
+ if (info.factoryBaseExpression && info.def.baseValueGlobal) {
2805
+ const loc = locOf(info.factoryBaseExpression);
2806
+ const type = { kind: "classval", className: info.base.def.name };
2807
+ out.push({ kind: "assign", localId: info.def.baseValueGlobal, value: lowerer.lowerExprExpecting(info.factoryBaseExpression, type), loc });
2808
+ out.push({ kind: "exprStmt", expr: { kind: "libCall", fn: "dyn.classInherit", args: [
2809
+ lowerer.coerceToExpected(classValueRef(lowerer, info, info.decl), DYN),
2810
+ lowerer.coerceToExpected({ kind: "varRef", localId: info.def.baseValueGlobal, type, loc }, DYN),
2811
+ ], type: DYN, loc }, loc });
2812
+ }
2813
+ if (computedBase && info.def.baseValueGlobal) {
2814
+ const loc = computedBase.value.loc;
2815
+ out.push({ kind: "assign", localId: info.def.baseValueGlobal, value: computedBase.value, loc });
2816
+ out.push({ kind: "exprStmt", expr: { kind: "libCall", fn: "dyn.classInherit", args: [
2817
+ lowerer.coerceToExpected(classValueRef(lowerer, info, info.decl), DYN),
2818
+ lowerer.coerceToExpected({ kind: "varRef", localId: info.def.baseValueGlobal, type: computedBase.value.type, loc }, DYN),
2819
+ ], type: DYN, loc }, loc });
2820
+ }
2821
+ if (info.callableBase) {
2822
+ const { expression, constructorId, prototypeId } = info.callableBase;
2823
+ const loc = locOf(expression);
2824
+ out.push({ kind: "assign", localId: constructorId, value: info.decl && lowerer.computedCallableBases.has(info.decl)
2825
+ ? lowerer.coerceToExpected(lowerer.computedCallableBases.get(info.decl), DYN)
2826
+ : lowerer.lowerExprExpecting(expression, DYN), loc }, { kind: "assign", localId: prototypeId, value: { kind: "libCall", fn: "dyn.classBasePrototype",
2827
+ args: [{ kind: "varRef", localId: constructorId, type: DYN, loc }], type: DYN, loc }, loc });
2828
+ const prototype = classPrototypeData(lowerer, info, loc);
2829
+ if (prototype)
2830
+ out.push({ kind: "exprStmt", expr: prototype, loc });
2831
+ out.push({ kind: "exprStmt", expr: { kind: "libCall", fn: "dyn.classInherit", args: [
2832
+ lowerer.coerceToExpected(classValueRef(lowerer, info, info.decl), DYN),
2833
+ { kind: "varRef", localId: constructorId, type: DYN, loc },
2834
+ ], type: DYN, loc }, loc });
2835
+ }
2221
2836
  const items = [
2222
2837
  ...info.staticFields.map((f) => ({ pos: f.initializer.getStart(), kind: "field", f })),
2223
2838
  ...(info.staticBlocks ?? []).map((b) => ({ pos: b.getStart(), kind: "block", b })),
@@ -2232,13 +2847,25 @@ function lowerStaticFieldInitsInner(lowerer, info) {
2232
2847
  const f = item.f;
2233
2848
  lowerer.stats.statementsTotal++;
2234
2849
  lowerer.bumpFileStat(locOf(f.initializer).file, "total");
2850
+ const diagsBefore = lowerer.diags.length;
2235
2851
  try {
2236
- // `this` in a static field initializer names the CLASS (like a
2237
- // static block's), with arrows transparent and this-binding
2238
- // function forms opaque — the static-block rule verbatim, named
2239
- // here so the generic outside-a-method fence never fires first.
2240
- rejectStaticThis(lowerer, f.initializer, () => "'this' in static field initializers (it names the class — reference the class by name instead)", true);
2241
- const value = lowerer.lowerExprExpecting(f.initializer, f.type);
2852
+ const previousThis = lowerer.ctx.thisLocal;
2853
+ const receiver = f.initializer.kind === ts.SyntaxKind.ThisKeyword || hasStaticThis(f.initializer)
2854
+ ? lowerer.declareHiddenLocal("%staticThis", { kind: "classval", className: info.def.name }) : null;
2855
+ if (receiver) {
2856
+ lowerer.noteEdge(`%${info.def.name}.constructor`);
2857
+ out.push({ kind: "varDecl", localId: receiver.id, init: { kind: "classRef", className: info.def.name,
2858
+ type: receiver.type, loc: locOf(f.initializer) }, loc: locOf(f.initializer) });
2859
+ }
2860
+ let value;
2861
+ try {
2862
+ if (receiver)
2863
+ lowerer.ctx.thisLocal = receiver;
2864
+ value = lowerer.lowerExprExpecting(f.initializer, f.type);
2865
+ }
2866
+ finally {
2867
+ lowerer.ctx.thisLocal = previousThis;
2868
+ }
2242
2869
  out.push({ kind: "assign", localId: f.globalId, value, loc: locOf(f.initializer) });
2243
2870
  }
2244
2871
  catch (e) {
@@ -2246,6 +2873,11 @@ function lowerStaticFieldInitsInner(lowerer, info) {
2246
2873
  throw e;
2247
2874
  lowerer.stats.statementsFailed++;
2248
2875
  lowerer.bumpFileStat(locOf(f.initializer).file, "failed");
2876
+ if (isJsSourceFile(f.initializer.getSourceFile()) && lowerer.diagSink === null) {
2877
+ const fence = lowerer.deferToRuntimeFence(diagsBefore, f.initializer, { kind: "statement" });
2878
+ if (fence)
2879
+ out.push(fence);
2880
+ }
2249
2881
  }
2250
2882
  }
2251
2883
  return out;
@@ -2520,6 +3152,14 @@ function staticMethodValue(lowerer, declarer, name, sig, blame, loc) {
2520
3152
  export function classValueRef(lowerer, info, blame) {
2521
3153
  const display = info.def.name.replace(/^%|^%m\d+\./, "");
2522
3154
  fenceDecorationThrows(lowerer, info, blame);
3155
+ if (info.localClass && ts.isIdentifier(blame)) {
3156
+ const stored = lowerer.resolveLocal(blame);
3157
+ if (stored)
3158
+ return lowerer.coerceToExpected({ kind: "varRef", localId: stored.id, type: stored.type, loc: locOf(blame) }, { kind: "classval", className: info.def.name });
3159
+ }
3160
+ if (info.localClass && !ts.isClassExpression(blame) && !ts.isClassDeclaration(blame)) {
3161
+ lowerer.unsupported("SC1090", blame, "named self references inside function-local classes");
3162
+ }
2523
3163
  if (info.generic) {
2524
3164
  // `typeof Box` — the uninstantiated FAMILY as a value: no thunk, no
2525
3165
  // single constructor ABI. INSTANTIATIONS have class objects
@@ -2529,10 +3169,10 @@ export function classValueRef(lowerer, info, blame) {
2529
3169
  if (info.builtinError || info.builtinEmitter || info.builtinStream !== undefined) {
2530
3170
  lowerer.unsupported("SC1090", blame, `builtin classes as values ('${display}' is runtime-provided — reference program-declared classes instead)`);
2531
3171
  }
2532
- if (lowerer.inheritsBuiltinErrorCtor(info) || lowerer.inheritsBuiltinEmitterCtor(info) ||
3172
+ if (lowerer.inheritsBuiltinEmitterCtor(info) ||
2533
3173
  inheritsBuiltinStreamCtor(lowerer, info) ||
2534
3174
  (() => { for (let c = info.base; c; c = c.base)
2535
- if (c.builtinError || c.builtinEmitter || c.builtinStream !== undefined)
3175
+ if (c.builtinEmitter || c.builtinStream !== undefined)
2536
3176
  return true; return false; })()) {
2537
3177
  lowerer.unsupported("SC1090", blame, `classes extending builtin bases as values ('${display}' inherits a runtime-provided constructor)`);
2538
3178
  }
@@ -2554,6 +3194,26 @@ export function ctorAbiEquals(lowerer, sub, sup) {
2554
3194
  const b = sup.ctorParams;
2555
3195
  return a.length === b.length && a.every((p, i) => p.mode === b[i].mode && typeEquals(p.type, b[i].type));
2556
3196
  }
3197
+ /** Writable storage for an own static field named through its exact class.
3198
+ * Inherited writes create a new subclass property in JS, so they must not
3199
+ * update the declaring class's global. */
3200
+ export function staticFieldWriteTarget(lowerer, access) {
3201
+ if (access.questionDotToken || (!ts.isIdentifier(access.expression) && access.expression.kind !== ts.SyntaxKind.ThisKeyword))
3202
+ return null;
3203
+ const info = lowerer.exactClassOfReceiver(access.expression);
3204
+ if (!info)
3205
+ return null;
3206
+ const found = lowerer.findStaticOn(info, access.name.text);
3207
+ if (!found?.field)
3208
+ return null;
3209
+ if (found.declarer !== info) {
3210
+ lowerer.unsupported("SC1090", access, `assigning the inherited static '${access.name.text}' through a subclass name (JS creates an OWN property on the subclass — assign through '${found.declarer.def.jsName ?? found.declarer.def.name}' instead)`);
3211
+ }
3212
+ if (found.field.readonly) {
3213
+ lowerer.unsupported("SC1090", access, `assigning the readonly static '${access.name.text}'`);
3214
+ }
3215
+ return { id: found.field.globalId, type: found.field.type };
3216
+ }
2557
3217
  /** `C.x` where C is a class declared in the program and x a static
2558
3218
  * member of its chain: field reads are the module global, static
2559
3219
  * methods become interned closures, and `.name` folds to the class's
@@ -2561,17 +3221,20 @@ export function ctorAbiEquals(lowerer, sub, sup) {
2561
3221
  * fall through to the ordinary chain so the static fence or the
2562
3222
  * generic member rejection names the site. */
2563
3223
  export function lowerStaticFieldRead(lowerer, expr) {
3224
+ if (expr.name.text === "prototype")
3225
+ return null;
2564
3226
  if (expr.questionDotToken)
2565
3227
  return null;
2566
- if (!ts.isIdentifier(expr.expression))
3228
+ if (!ts.isIdentifier(expr.expression) && expr.expression.kind !== ts.SyntaxKind.ThisKeyword)
2567
3229
  return null;
2568
- const symbol = lowerer.resolveValueSymbol(expr.expression);
3230
+ const symbol = ts.isIdentifier(expr.expression) ? lowerer.resolveValueSymbol(expr.expression) : null;
2569
3231
  const info = (symbol ? lowerer.classBySymbol.get(symbol) : undefined) ??
2570
3232
  // A require binding over `module.exports = class {…}` (the alias
2571
3233
  // lands on the expression's own symbol): resolve/collect on demand,
2572
3234
  // or `C.name` below would fall through to paths that answer for
2573
3235
  // stdlib globals instead of this class.
2574
3236
  propertyAssignedClassInfoOf(lowerer, symbol) ??
3237
+ exactClassOfReceiver(lowerer, expr.expression) ??
2575
3238
  undefined;
2576
3239
  if (!info)
2577
3240
  return null;
@@ -2584,6 +3247,9 @@ export function lowerStaticFieldRead(lowerer, expr) {
2584
3247
  return null;
2585
3248
  const loc = locOf(expr);
2586
3249
  const found = findStaticOn(lowerer, info, expr.name.text);
3250
+ if (hasRuntimeStatics(info) && !found?.field)
3251
+ return { kind: "dynKeyGet", value: lowerer.coerceToExpected(classValueRef(lowerer, info, expr.expression), DYN),
3252
+ key: { kind: "strLit", value: expr.name.text, type: STRING, loc }, type: DYN, loc };
2587
3253
  // A #private static resolves only through the DECLARING class's own
2588
3254
  // name: in JS the brand lives on that one constructor object, so
2589
3255
  // `D.#s` (a subclass receiver) throws Node's TypeError instead of
@@ -2611,6 +3277,12 @@ export function lowerStaticFieldRead(lowerer, expr) {
2611
3277
  if (expr.name.text === "name" && info.def.jsName !== undefined) {
2612
3278
  return { kind: "strLit", value: info.def.jsName, type: STRING, loc };
2613
3279
  }
3280
+ if (info.callableBase)
3281
+ return { kind: "dynKeyGet", value: lowerer.coerceToExpected(classValueRef(lowerer, info, expr.expression), DYN),
3282
+ key: { kind: "strLit", value: expr.name.text, type: STRING, loc }, type: DYN, loc };
3283
+ const data = classStaticDataFor(lowerer, info, expr.name.text, loc);
3284
+ if (data)
3285
+ return { kind: "dynKeyGet", value: data, key: { kind: "strLit", value: expr.name.text, type: STRING, loc }, type: DYN, loc };
2614
3286
  return null;
2615
3287
  }
2616
3288
  /** NamedEvaluation's answer for a class expression's `.name`: its own
@@ -2635,19 +3307,12 @@ function namedEvaluationName(expr) {
2635
3307
  return p.name.text;
2636
3308
  return "";
2637
3309
  }
2638
- /** A class EXPRESSION's ClassInfo: collection on first encounter (the
2639
- * declaration path over the shared ClassLikeDeclaration machinery, with
2640
- * NamedEvaluation supplying the runtime .name), idempotent per node —
2641
- * tryLowerExpression's speculative visits and the heritage recursion reuse the
2642
- * first collection. The honest v1 boundary is TOP-LEVEL evaluation
2643
- * positions only: each evaluation of a class expression in JS mints a
2644
- * DISTINCT class (fresh identity, fresh statics), and one immortal
2645
- * class object is exact only for expressions that evaluate exactly
2646
- * once. Statics-bearing expressions additionally restrict to positions
2647
- * where "immediately before the enclosing statement" IS the evaluation
2648
- * point (lowerFileInit drains pendingClassExprInits there). */
3310
+ /** Collect a class expression once per enclosing specialization. Function-local
3311
+ * evaluations allocate fresh constructor objects; top-level expressions use
3312
+ * immortal templates. Static initialization remains limited to whole top-level
3313
+ * initializers, where pendingClassExprInits preserves its evaluation point. */
2649
3314
  export function lowerClassExpressionInfo(lowerer, expr) {
2650
- const cached = lowerer.exprClassInfoByNode.get(expr);
3315
+ const cached = lowerer.exprClassInfoByName.get(lowerer.classNamer(expr));
2651
3316
  if (cached)
2652
3317
  return cached;
2653
3318
  // Reentrancy guard: heritage resolution can DEMAND another class
@@ -2660,16 +3325,41 @@ export function lowerClassExpressionInfo(lowerer, expr) {
2660
3325
  if (lowerer.collectingExprClasses.has(expr)) {
2661
3326
  lowerer.unsupported("SC1090", expr, "class expressions whose extends chain re-enters their own collection (a cyclic base through property assignments)");
2662
3327
  }
2663
- if (lowerer.instantiationContext) {
2664
- lowerer.unsupported("SC1090", expr, "class expressions inside generic functions (each instantiation would need its own class)");
2665
- }
2666
- for (let p = expr.parent; !ts.isSourceFile(p); p = p.parent) {
2667
- if (ts.isFunctionLike(p) || ts.isClassStaticBlockDeclaration(p)) {
2668
- lowerer.unsupported("SC1090", expr, "class expressions inside functions (each evaluation creates a DISTINCT class in JS — fresh identity, fresh statics; declare the class at top level)");
3328
+ let local = false;
3329
+ for (let p = expr.parent; p !== undefined && !ts.isSourceFile(p); p = p.parent) {
3330
+ if (ts.isClassStaticBlockDeclaration(p)) {
3331
+ lowerer.unsupported("SC1090", expr, "class expressions inside static blocks");
2669
3332
  }
3333
+ if (ts.isFunctionLike(p))
3334
+ local = true;
3335
+ }
3336
+ if (local && expr.members.some((member) => member.name && ts.isPrivateIdentifier(member.name))) {
3337
+ lowerer.unsupported("SC1090", expr, "function-local classes with private brands");
3338
+ }
3339
+ if (local && (expr.typeParameters?.length ||
3340
+ decoratorNodesOf(expr).length || expr.members.some((member) => decoratorNodesOf(member).length ||
3341
+ (!isJsSourceFile(expr.getSourceFile()) && (ts.isClassStaticBlockDeclaration(member) ||
3342
+ ts.getModifiers(member)?.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword))) ||
3343
+ (ts.isMethodDeclaration(member) && member.typeParameters?.length)))) {
3344
+ lowerer.unsupported("SC1090", expr, "function-local classes with statics, decorators, or generic members");
2670
3345
  }
2671
3346
  lowerer.collectingExprClasses.add(expr);
2672
3347
  try {
3348
+ if (local && lowerer.fnStack.length > 0 && !lowerer.computedClassBases.has(lowerer.classNamer(expr))) {
3349
+ const heritage = expr.heritageClauses?.find((clause) => clause.token === ts.SyntaxKind.ExtendsKeyword)?.types[0]?.expression;
3350
+ if (heritage && (ts.isCallExpression(heritage) ||
3351
+ ts.isIdentifier(heritage) && (lowerer.peekLocal(heritage) ?? lowerer.globalOf(heritage)) != null)) {
3352
+ let value = lowerer.lowerExpr(heritage);
3353
+ const known = value.type.kind === "dyn" ? storedClassValueType(lowerer, heritage) : null;
3354
+ if (known?.kind === "classval")
3355
+ value = lowerer.coerceToExpected(value, known);
3356
+ const base = value.type.kind === "classval" ? lowerer.classes.get(value.type.className) : undefined;
3357
+ if (base)
3358
+ lowerer.computedClassBases.set(lowerer.classNamer(expr), { value, classInfo: base });
3359
+ else if (value.type.kind === "dyn" || value.type.kind === "func")
3360
+ lowerer.computedCallableBases.set(expr, value);
3361
+ }
3362
+ }
2673
3363
  lowerer.collectClassShapeInner(expr, namedEvaluationName(expr));
2674
3364
  }
2675
3365
  finally {
@@ -2678,7 +3368,17 @@ export function lowerClassExpressionInfo(lowerer, expr) {
2678
3368
  const info = lowerer.classes.get(lowerer.classNamer(expr));
2679
3369
  if (!info)
2680
3370
  throw new PoisonError(); // collection poisoned and reported
2681
- lowerer.exprClassInfoByNode.set(expr, info);
3371
+ if (local) {
3372
+ info.def.localCaptures = [];
3373
+ info.def.fields.push({ name: `%classEnvironment:${info.def.name}`, type: { kind: "classval", className: info.def.name } });
3374
+ info.localClass = { context: null, bodies: new Map(), captureSources: [], ready: false };
3375
+ if (info.base?.localClass) {
3376
+ const baseExpression = expr.heritageClauses?.find((clause) => clause.token === ts.SyntaxKind.ExtendsKeyword)?.types[0]?.expression;
3377
+ if (baseExpression)
3378
+ info.localClass.baseExpression = baseExpression;
3379
+ }
3380
+ }
3381
+ lowerer.exprClassInfoByName.set(info.def.name, info);
2682
3382
  lowerer.exprClasses.push(info);
2683
3383
  lowerer.onExprClassCollected?.(info);
2684
3384
  // Static field initializers and static blocks run when the class
@@ -2688,7 +3388,7 @@ export function lowerClassExpressionInfo(lowerer, expr) {
2688
3388
  // drains it), which is JS's order for whole-initializer positions.
2689
3389
  // Anything subtler (multi-declarator statements, arguments evaluated
2690
3390
  // after other side effects) is a named fence, never a reordering.
2691
- if (info.staticFields.length > 0 || (info.staticBlocks?.length ?? 0) > 0) {
3391
+ if (!local && (info.callableBase || info.def.baseValueGlobal || info.staticFields.length > 0 || (info.staticBlocks?.length ?? 0) > 0)) {
2692
3392
  let holder = expr.parent;
2693
3393
  while (ts.isParenthesizedExpression(holder) || ts.isClassExpression(holder) ||
2694
3394
  ts.isHeritageClause(holder) || ts.isExpressionWithTypeArguments(holder)) {
@@ -2708,7 +3408,6 @@ export function lowerClassExpressionInfo(lowerer, expr) {
2708
3408
  if (!wholeInit) {
2709
3409
  lowerer.unsupported("SC1090", expr, "class expressions with static initializers or static blocks outside a whole-initializer position (their declaration-time code must run exactly where the expression evaluates — bind the class in its own top-level `const C = class …` statement)");
2710
3410
  }
2711
- lowerer.pendingClassExprInits.push(...lowerer.lowerStaticFieldInits(info));
2712
3411
  }
2713
3412
  return info;
2714
3413
  }
@@ -2733,7 +3432,77 @@ export function lowerClassExpression(lowerer, expr) {
2733
3432
  }
2734
3433
  }
2735
3434
  }
2736
- return classValueRef(lowerer, lowerClassExpressionInfo(lowerer, expr), expr);
3435
+ const info = lowerClassExpressionInfo(lowerer, expr);
3436
+ if (!info.localClass && !info.expressionInitializationEmitted &&
3437
+ (info.callableBase || info.def.baseValueGlobal || info.staticFields.length > 0 || (info.staticBlocks?.length ?? 0) > 0)) {
3438
+ info.expressionInitializationEmitted = true;
3439
+ lowerer.pendingClassExprInits.push(...lowerer.lowerStaticFieldInits(info));
3440
+ }
3441
+ if (info.localClass && !info.localClass.ready) {
3442
+ const context = newFnCtx(true, null, null, VOID);
3443
+ info.localClass.context = context;
3444
+ lowerer.fnStack.push(context);
3445
+ try {
3446
+ const bodies = lowerClassMembers(lowerer, info);
3447
+ for (const body of bodies)
3448
+ info.localClass.bodies.set(body.name, body);
3449
+ info.def.localCaptures = context.captures;
3450
+ info.localClass.captureSources = context.captureSources;
3451
+ if (info.localClass.baseExpression && info.base) {
3452
+ info.def.localBaseCapture = info.def.localCaptures.length;
3453
+ info.def.localCaptures.push({ localId: "%base", name: "base", type: { kind: "classval", className: info.base.def.name } });
3454
+ }
3455
+ info.localClass.ready = true;
3456
+ lowerer.onExprClassCollected?.(info);
3457
+ }
3458
+ finally {
3459
+ lowerer.fnStack.pop();
3460
+ info.localClass.context = null;
3461
+ }
3462
+ }
3463
+ const value = classValueRef(lowerer, info, expr);
3464
+ if (info.localClass && info.callableBase && value.kind === "classRef") {
3465
+ const loc = locOf(expr);
3466
+ const base = lowerer.lowerExprExpecting(info.callableBase.expression, DYN);
3467
+ const baseLocal = lowerer.declareHiddenLocal("%classBase", DYN);
3468
+ const clsLocal = lowerer.declareHiddenLocal("%classValue", value.type);
3469
+ const baseRef = { kind: "varRef", localId: baseLocal.id, type: DYN, loc };
3470
+ const clsRef = { kind: "varRef", localId: clsLocal.id, type: value.type, loc };
3471
+ const boxed = { kind: "dynFrom", value: clsRef, type: DYN, loc };
3472
+ info.localPrototypeData = true;
3473
+ return initializeRuntimeStatics(lowerer, info, { kind: "seqExpr", stmts: [
3474
+ { kind: "varDecl", localId: baseLocal.id, init: base, loc },
3475
+ { kind: "varDecl", localId: clsLocal.id, init: { ...value, captures: info.localClass.captureSources }, loc },
3476
+ { kind: "exprStmt", expr: { kind: "libCall", fn: "dyn.classInherit", args: [boxed, baseRef], type: DYN, loc }, loc },
3477
+ { kind: "exprStmt", expr: { kind: "libCall", fn: "dyn.classPrototype", args: [boxed,
3478
+ { kind: "libCall", fn: "dyn.classBasePrototype", args: [baseRef], type: DYN, loc },
3479
+ ], type: DYN, loc }, loc },
3480
+ ], result: clsRef, type: value.type, loc });
3481
+ }
3482
+ if (info.localClass?.baseExpression && info.base && value.kind === "classRef") {
3483
+ const loc = locOf(expr);
3484
+ const base = lowerer.lowerExprExpecting(info.localClass.baseExpression, { kind: "classval", className: info.base.def.name });
3485
+ const baseLocal = lowerer.declareHiddenLocal("%classBase", base.type);
3486
+ baseLocal.boxed = true;
3487
+ const clsLocal = lowerer.declareHiddenLocal("%classValue", value.type);
3488
+ const baseRef = { kind: "varRef", localId: baseLocal.id, type: base.type, loc };
3489
+ const clsRef = { kind: "varRef", localId: clsLocal.id, type: value.type, loc };
3490
+ const basePrototype = classPrototypeData(lowerer, info.base, loc, baseRef);
3491
+ info.localPrototypeData = true;
3492
+ return initializeRuntimeStatics(lowerer, info, { kind: "seqExpr", stmts: [
3493
+ { kind: "varDecl", localId: baseLocal.id, init: base, loc },
3494
+ { kind: "varDecl", localId: clsLocal.id, init: { ...value, captures: [...info.localClass.captureSources, baseLocal.id] }, loc },
3495
+ { kind: "exprStmt", expr: { kind: "libCall", fn: "dyn.classInherit", args: [
3496
+ { kind: "dynFrom", value: clsRef, type: DYN, loc }, { kind: "dynFrom", value: baseRef, type: DYN, loc },
3497
+ ], type: DYN, loc }, loc },
3498
+ { kind: "exprStmt", expr: { kind: "libCall", fn: "dyn.classPrototype", args: [
3499
+ { kind: "dynFrom", value: clsRef, type: DYN, loc }, basePrototype,
3500
+ ], type: DYN, loc }, loc },
3501
+ ], result: clsRef, type: value.type, loc });
3502
+ }
3503
+ return initializeRuntimeStatics(lowerer, info, info.localClass && value.kind === "classRef"
3504
+ ? { ...value, captures: info.localClass.captureSources }
3505
+ : value);
2737
3506
  }
2738
3507
  /** The EXACT class a receiver expression is statically known to BE (not
2739
3508
  * merely be typed by): the class name itself, or a `const` binding
@@ -2742,6 +3511,12 @@ export function lowerClassExpression(lowerer, expr) {
2742
3511
  * hit the declaring class's storage exactly (the shadowing hazards of
2743
3512
  * general class values don't arise). Null for everything else. */
2744
3513
  export function exactClassOfReceiver(lowerer, expr) {
3514
+ // A class-valued lexical this is introduced only for an exact static
3515
+ // receiver specialization; ordinary instance this remains an object.
3516
+ if (expr.kind === ts.SyntaxKind.ThisKeyword) {
3517
+ const receiver = lowerer.resolveThis();
3518
+ return receiver?.type.kind === "classval" ? lowerer.classes.get(receiver.type.className) ?? null : null;
3519
+ }
2745
3520
  if (!ts.isIdentifier(expr))
2746
3521
  return null;
2747
3522
  const symbol = lowerer.resolveValueSymbol(expr);
@@ -2764,7 +3539,7 @@ export function exactClassOfReceiver(lowerer, expr) {
2764
3539
  while (ts.isParenthesizedExpression(init))
2765
3540
  init = init.expression;
2766
3541
  if (ts.isClassExpression(init))
2767
- return lowerer.exprClassInfoByNode.get(init) ?? null;
3542
+ return lowerer.exprClassInfoByName.get(lowerer.classNamer(init)) ?? null;
2768
3543
  if (ts.isIdentifier(init)) {
2769
3544
  const initSym = lowerer.resolveValueSymbol(init);
2770
3545
  const aliased = initSym ? (lowerer.classBySymbol.get(initSym) ?? null) : null;
@@ -2880,12 +3655,37 @@ function countAssignmentsTo(assign) {
2880
3655
  export function lowerStaticMethodCall(lowerer, call, access) {
2881
3656
  if (access.questionDotToken)
2882
3657
  return null;
3658
+ if (access.expression.kind === ts.SyntaxKind.ThisKeyword) {
3659
+ const receiver = lowerer.resolveThis();
3660
+ const info = receiver?.type.kind === "classval" ? lowerer.classes.get(receiver.type.className) : undefined;
3661
+ if (info)
3662
+ return staticCallOn(lowerer, call, access, info, false);
3663
+ }
2883
3664
  // `module.exports.describe()` in a module whose whole export IS a
2884
3665
  // class expression: the receiver is exactly that class (the kept
2885
3666
  // export assignment pins it) — the direct-name rules apply.
2886
3667
  if (!ts.isIdentifier(access.expression)) {
2887
- if (!isModuleExportsAccess(access.expression) || !isCjsJsFile(access.getSourceFile())) {
2888
- return null;
3668
+ if (!isModuleExportsAccess(access.expression) || !isCjsJsFile(access.getSourceFile(), lowerer.program)) {
3669
+ let receiverType = lowerer.mapTypeOf(lowerer.typeOf(access.expression));
3670
+ if (receiverType?.kind !== "classval" && isJsSourceFile(call.getSourceFile()) && ts.isCallExpression(access.expression)) {
3671
+ const receiver = tryLowerExpression(lowerer, access.expression);
3672
+ if (receiver?.type.kind === "classval")
3673
+ receiverType = receiver.type;
3674
+ }
3675
+ if (receiverType?.kind !== "classval")
3676
+ return null;
3677
+ const info = lowerer.classes.get(receiverType.className);
3678
+ if (!info)
3679
+ return null;
3680
+ const result = staticCallOn(lowerer, call, access, info, true);
3681
+ if (!result)
3682
+ return null;
3683
+ // Evaluate and validate the receiver before evaluating arguments.
3684
+ // A typed checker projection cannot turn a replaced field into a call
3685
+ // to the class that originally occupied it.
3686
+ const receiver = lowerer.lowerExprExpecting(access.expression, receiverType);
3687
+ return { kind: "seqExpr", stmts: [{ kind: "exprStmt", expr: receiver, loc: locOf(access.expression) }],
3688
+ result, type: result.type, loc: locOf(call) };
2889
3689
  }
2890
3690
  const whole = cjsClassExprWholeExportOf(access.getSourceFile());
2891
3691
  if (!whole)
@@ -2928,6 +3728,10 @@ function classValueIsExactlyOwn(lowerer, recv, info) {
2928
3728
  }
2929
3729
  function staticCallOn(lowerer, call, access, info, throughValue) {
2930
3730
  const loc = locOf(call);
3731
+ if (hasRuntimeStatics(info) && !findStaticOn(lowerer, info, access.name.text)?.field || info.callableBase && !findStaticOn(lowerer, info, access.name.text) && !findGenericStaticOn(lowerer, info, access.name.text))
3732
+ return { kind: "dynInvoke", recv: lowerer.lowerExprExpecting(access.expression, DYN),
3733
+ method: access.name.text, calleeName: access.name.text,
3734
+ args: call.arguments.map((argument) => lowerer.lowerExprExpecting(argument, DYN)), type: DYN, loc };
2931
3735
  // #private statics: through-a-VALUE receiver the call devirtualizes
2932
3736
  // exactly when the value can only BE the declaring class
2933
3737
  // (classValueIsExactlyOwn — a slot that could hold a descendant at
@@ -2951,13 +3755,19 @@ function staticCallOn(lowerer, call, access, info, throughValue) {
2951
3755
  if (throughValue && staticShadowBelow(lowerer, info, access.name.text)) {
2952
3756
  lowerer.unsupported("SC1090", call, `calling the static member '${access.name.text}' through a class value (a subclass of '${info.def.name.replace(/^%|^%m\d+\./, "")}' redeclares it, so the runtime class decides which declaration answers)`);
2953
3757
  }
2954
- const instance = genericCallInstance(lowerer, call, gfound.info);
3758
+ const instance = genericCallInstance(lowerer, call, staticMethodForReceiver(lowerer, access, gfound.info, info, throughValue));
2955
3759
  const args = lowerer.completeArgs(call.arguments, instance.params, loc, call);
2956
3760
  return { kind: "call", callee: instance.name, args, type: instance.returnType, loc };
2957
3761
  }
2958
3762
  if (throughValue && staticShadowBelow(lowerer, info, access.name.text)) {
2959
3763
  lowerer.unsupported("SC1090", call, `calling the static member '${access.name.text}' through a class value (a subclass of '${info.def.name.replace(/^%|^%m\d+\./, "")}' redeclares it, so the runtime class decides which declaration answers)`);
2960
3764
  }
3765
+ const specialized = findGenericStaticOn(lowerer, info, access.name.text);
3766
+ if (specialized?.declarer === found.declarer && specialized.info.implicitParams) {
3767
+ const instance = implicitCallInstance(lowerer, call, staticMethodForReceiver(lowerer, access, specialized.info, info, throughValue));
3768
+ const args = lowerer.completeArgs(call.arguments, instance.params, loc, call);
3769
+ return { kind: "call", callee: instance.name, args, type: instance.returnType, loc };
3770
+ }
2961
3771
  if (found.field !== undefined) {
2962
3772
  // A func-typed static field in call position: read the global,
2963
3773
  // call through the value (the ctor-assigned-callback pattern).
@@ -2973,13 +3783,44 @@ function staticCallOn(lowerer, call, access, info, throughValue) {
2973
3783
  }
2974
3784
  args.push(absent);
2975
3785
  }
2976
- return { kind: "callValue", callee, args, type: found.field.type.ret, loc };
3786
+ return { kind: "callValue", callee, receiver: lowerer.lowerExprExpecting(access.expression, DYN), args, type: found.field.type.ret, loc };
3787
+ }
3788
+ if (found.method.member.body && hasStaticThis(found.method.member)) {
3789
+ const generic = found.method.receiverInfo ??= {
3790
+ decl: found.method.member, baseName: access.name.text,
3791
+ qualifiedName: `%${found.declarer.def.name}.static:${access.name.text}`,
3792
+ typeParams: [], instances: new Map(), member: { cls: found.declarer, kind: "static" },
3793
+ };
3794
+ const instance = genericCallInstance(lowerer, call, staticMethodForReceiver(lowerer, access, generic, info, throughValue));
3795
+ return { kind: "call", callee: instance.name,
3796
+ args: lowerer.completeArgs(call.arguments, instance.params, loc, call), type: instance.returnType, loc };
2977
3797
  }
2978
3798
  const fnName = `%${found.declarer.def.name}.static:${access.name.text}`;
2979
3799
  lowerer.noteEdge(fnName);
2980
3800
  const args = lowerer.completeArgs(call.arguments, found.method.params, loc, call);
2981
3801
  return { kind: "call", callee: fnName, args, type: found.method.ret, loc };
2982
3802
  }
3803
+ function staticMethodForReceiver(lowerer, access, method, receiver, throughValue) {
3804
+ if (!hasStaticThis(method.decl))
3805
+ return method;
3806
+ // A private name in the inherited body belongs to the declaring class,
3807
+ // even when the receiver declares a different private with that spelling.
3808
+ // Do not resolve it by receiver name until the static ABI tracks the brand.
3809
+ if (method.member && method.member.cls !== receiver && hasLexicalPrivateReference(method.decl)) {
3810
+ lowerer.unsupported("SC1090", access, "private member references in an inherited receiver-dependent static method");
3811
+ }
3812
+ if (throughValue && !classValueIsExactlyOwn(lowerer, access.expression, receiver)) {
3813
+ lowerer.unsupported("SC1090", access, "receiver-dependent static methods through a polymorphic class value");
3814
+ }
3815
+ const instances = method.receiverSpecializations ??= new Map();
3816
+ let specialized = instances.get(receiver.def.name);
3817
+ if (!specialized) {
3818
+ specialized = { ...method, qualifiedName: `${method.qualifiedName}%on.${receiver.def.name}`,
3819
+ instances: new Map(), staticReceiver: receiver, receiverSpecializations: new Map() };
3820
+ instances.set(receiver.def.name, specialized);
3821
+ }
3822
+ return specialized;
3823
+ }
2983
3824
  /** Static member access through a class VALUE (`X.m` where X is
2984
3825
  * classval-typed): devirtualized — the member resolves against the
2985
3826
  * static class's chain, exact when no strict descendant redeclares it
@@ -2990,11 +3831,15 @@ function staticCallOn(lowerer, call, access, info, throughValue) {
2990
3831
  export function lowerClassValueProperty(lowerer, expr) {
2991
3832
  if (expr.questionDotToken)
2992
3833
  return null;
2993
- const recvT = lowerer.mapTypeOf(lowerer.typeOf(expr.expression));
3834
+ const recvT = storedClassValueType(lowerer, expr.expression);
2994
3835
  if (recvT?.kind !== "classval")
2995
3836
  return null;
2996
3837
  const loc = locOf(expr);
2997
3838
  const member = expr.name.text;
3839
+ const info = lowerer.classes.get(recvT.className);
3840
+ if (info && (hasRuntimeStatics(info) && !findStaticOn(lowerer, info, member)?.field || info.callableBase && !findStaticOn(lowerer, info, member)))
3841
+ return { kind: "dynKeyGet", value: lowerer.lowerExprExpecting(expr.expression, DYN),
3842
+ key: { kind: "strLit", value: member, type: STRING, loc }, type: DYN, loc };
2998
3843
  // `X.name` reads the RUNTIME class object's stored name — the one
2999
3844
  // genuinely dynamic member. It CONSUMES the receiver (no evaluation
3000
3845
  // is discarded), so any receiver expression is fine here.
@@ -3004,11 +3849,14 @@ export function lowerClassValueProperty(lowerer, expr) {
3004
3849
  return null;
3005
3850
  return { kind: "libCall", fn: "class.name", args: [recv], type: STRING, loc };
3006
3851
  }
3852
+ if (!info)
3853
+ return null;
3007
3854
  if (!ts.isIdentifier(expr.expression) &&
3855
+ expr.expression.kind !== ts.SyntaxKind.ThisKeyword &&
3008
3856
  // `module.exports.label` in a class-replaced CJS module: the
3009
3857
  // receiver is the exact exported class, and the read is
3010
3858
  // side-effect-free — as bindable as an identifier.
3011
- !(isModuleExportsAccess(expr.expression) && isCjsJsFile(expr.getSourceFile()))) {
3859
+ !(isModuleExportsAccess(expr.expression) && isCjsJsFile(expr.getSourceFile(), lowerer.program))) {
3012
3860
  // Devirtualized reads DISCARD the receiver value, so only
3013
3861
  // side-effect-free receivers are claimed (the instanceOf fold
3014
3862
  // rule); computed ones meet the pointed fence with a bindable fix.
@@ -3016,9 +3864,6 @@ export function lowerClassValueProperty(lowerer, expr) {
3016
3864
  }
3017
3865
  // The direct class-name spelling resolved in lowerStaticFieldRead;
3018
3866
  // reaching here means the receiver is a classval-typed BINDING.
3019
- const info = lowerer.classes.get(recvT.className);
3020
- if (!info)
3021
- return null;
3022
3867
  const found = findStaticOn(lowerer, info, member);
3023
3868
  if (!found) {
3024
3869
  lowerer.unsupported("SC1090", expr, `the static member '${member}' of class '${info.def.name.replace(/^%|^%m\d+\./, "")}' (static accessors and initializer-less static fields have no lowering, and Function members like .call/.bind/.prototype have no value form)`);
@@ -3110,9 +3955,75 @@ export function findGenericMethodOn(lowerer, info, name) {
3110
3955
  * method `name` — overrideBelow's twin: generic methods have no vtable
3111
3956
  * slot, so a call that could reach an override compiles only when the
3112
3957
  * receiver's runtime class is statically exact. */
3113
- function genericOverrideBelow(lowerer, info, name) {
3958
+ export function genericOverrideBelow(lowerer, info, name) {
3114
3959
  return info.subclasses.some((s) => s.genericMethods?.has(name) === true || genericOverrideBelow(lowerer, s, name));
3115
3960
  }
3961
+ /** Discover overrides before choosing inferred method ABIs. Class collection
3962
+ * visits bases first, including imported bases and class expressions, so the
3963
+ * collected subclass graph cannot answer this question yet. The checker
3964
+ * hierarchy identifies the original declarations through aliases as well. */
3965
+ export function collectVirtualJsMethods(lowerer, files) {
3966
+ // Record named prototype accesses before collecting method signatures.
3967
+ // Those slots need a callable ABI even when JavaScript would otherwise
3968
+ // specialize each call independently.
3969
+ for (const file of files)
3970
+ ts.walkPreorder(file, (node) => {
3971
+ if (!ts.isPropertyAccessExpression(node) && !ts.isElementAccessExpression(node))
3972
+ return;
3973
+ const name = ts.isPropertyAccessExpression(node) ? node.name.text
3974
+ : ts.isStringLiteralLike(node.argumentExpression) ? node.argumentExpression.text : null;
3975
+ if (name === null)
3976
+ return;
3977
+ const prototype = ts.isPropertyAccessExpression(node.expression) && node.expression.name.text === "prototype";
3978
+ const assigned = ts.isBinaryExpression(node.parent) && node.parent.left === node && node.parent.operatorToken.kind === ts.SyntaxKind.EqualsToken;
3979
+ const symbol = !assigned ? undefined : ts.isPropertyAccessExpression(node)
3980
+ ? lowerer.checker.getSymbolAtLocation(node.name)
3981
+ : lowerer.checker.getPropertyOfType(lowerer.typeOf(node.expression), name);
3982
+ if (prototype || symbol && lowerer.checker.declarationsOf(symbol).some(ts.isMethodDeclaration)) {
3983
+ lowerer.prototypeMethodAccesses.set(name, node);
3984
+ }
3985
+ });
3986
+ const visit = (node) => {
3987
+ if (ts.isClassDeclaration(node) || ts.isClassExpression(node)) {
3988
+ const members = node.members.filter((member) => ts.isMethodDeclaration(member) && ts.isIdentifier(member.name) &&
3989
+ !member.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword));
3990
+ if (node.heritageClauses?.length && members.length > 0) {
3991
+ const symbol = lowerer.typeOf(node).getSymbol();
3992
+ const instance = symbol ? lowerer.checker.getDeclaredTypeOfSymbol(symbol) : null;
3993
+ const seen = new Set();
3994
+ const markBases = (type) => {
3995
+ const target = type.isTypeReference() ? type.getTarget() : type;
3996
+ if (target === undefined || !target.isClassOrInterface() || seen.has(target))
3997
+ return;
3998
+ seen.add(target);
3999
+ for (const base of lowerer.checker.getBaseTypes(target)) {
4000
+ for (const member of members) {
4001
+ if (!ts.isIdentifier(member.name))
4002
+ continue;
4003
+ const property = lowerer.checker.getPropertyOfType(base, member.name.text);
4004
+ for (const declaration of property ? lowerer.checker.declarationsOf(property) : []) {
4005
+ if (ts.isMethodDeclaration(declaration) && isJsSourceFile(declaration.getSourceFile())) {
4006
+ lowerer.virtualJsMethods.add(declaration);
4007
+ if (isJsSourceFile(member.getSourceFile()) && !member.typeParameters &&
4008
+ !member.asteriskToken && !member.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword) &&
4009
+ !bodyReadsArguments(member) &&
4010
+ member.parameters.every((p) => !p.initializer && !p.dotDotDotToken)) {
4011
+ lowerer.virtualJsMethodArity.set(declaration, Math.max(lowerer.virtualJsMethodArity.get(declaration) ?? 0, member.parameters.length));
4012
+ }
4013
+ }
4014
+ }
4015
+ }
4016
+ markBases(base);
4017
+ }
4018
+ };
4019
+ if (instance)
4020
+ markBases(instance);
4021
+ }
4022
+ }
4023
+ };
4024
+ for (const file of files)
4025
+ ts.walkPreorder(file, visit);
4026
+ }
3116
4027
  /** The receiver's EXACT runtime class, when the expression proves it: a
3117
4028
  * `new C(...)` expression directly, or a const binding initialized with
3118
4029
  * one (the binding can never be reassigned to a subclass instance).
@@ -3274,13 +4185,20 @@ function mixinForwardingCtor(lowerer, ctor) {
3274
4185
  return !extraRef;
3275
4186
  }
3276
4187
  export function lowerClassMembers(lowerer, info) {
4188
+ // Local class bodies are lowered when their expression captures its
4189
+ // lexical environment. Type collection alone can discover a class in
4190
+ // an owner skipped by the coverage remainder; it must not relower the
4191
+ // constructor without that environment.
4192
+ if (info.localClass && info.localClass.context === null) {
4193
+ return [...info.localClass.bodies.values()];
4194
+ }
3277
4195
  const out = [];
3278
4196
  const className = info.def.name;
3279
4197
  // Generic-class INSTANTIATIONS (and mixin instantiations) are
3280
4198
  // demand-driven like generic-fn instances, not reachability units:
3281
4199
  // they are never registered as units, so wantBody's name-keyed gate
3282
4200
  // cannot apply — every member of a demanded instantiation lowers.
3283
- const always = info.genericInstance !== undefined || info.mixinInstance !== undefined;
4201
+ const always = info.genericInstance !== undefined || info.mixinInstance !== undefined || info.localClass !== undefined;
3284
4202
  // A FAMILY has no constructor function at all (nothing constructs it;
3285
4203
  // construction resolves to instantiations) and declares no instance
3286
4204
  // members — only its statics lower below.
@@ -3290,12 +4208,22 @@ export function lowerClassMembers(lowerer, info) {
3290
4208
  // signature-blocked function (lowerStaticMethod's rule) instead of
3291
4209
  // crashing the whole lowering.
3292
4210
  if (!info.generic && (always || lowerer.wantBody(`%${className}.constructor`))) {
4211
+ const diagsBefore = lowerer.diags.length;
3293
4212
  try {
3294
4213
  out.push(lowerer.lowerClassCtor(info));
3295
4214
  }
3296
4215
  catch (e) {
3297
4216
  if (!(e instanceof PoisonError))
3298
4217
  throw e;
4218
+ if (info.decl && isJsSourceFile(info.decl.getSourceFile())) {
4219
+ const types = [{ kind: "object", className }, ...info.ctorParams.map((param) => param.type)];
4220
+ const fallback = lowerer.deferToRuntimeFence(diagsBefore, info.ctor ?? info.decl, {
4221
+ kind: "function", name: `%${className}.constructor`, returnType: VOID,
4222
+ params: types.map((type, index) => ({ localId: `p.${index}`, name: index === 0 ? "this" : `p${index}`, type })),
4223
+ });
4224
+ if (fallback)
4225
+ out.push(fallback);
4226
+ }
3299
4227
  }
3300
4228
  }
3301
4229
  for (const { mName, member } of lowerer.classMethodMembers(info)) {
@@ -3311,13 +4239,14 @@ export function lowerClassMembers(lowerer, info) {
3311
4239
  throw e;
3312
4240
  }
3313
4241
  }
3314
- for (const name of info.staticMethods?.keys() ?? []) {
3315
- if (!lowerer.wantBody(`%${className}.static:${name}`))
3316
- continue;
3317
- const fn = lowerStaticMethod(lowerer, info, name);
3318
- if (fn)
3319
- out.push(fn);
3320
- }
4242
+ if (info.staticMethods)
4243
+ for (const [name] of info.staticMethods) {
4244
+ if (!lowerer.wantBody(`%${className}.static:${name}`))
4245
+ continue;
4246
+ const fn = lowerStaticMethod(lowerer, info, name);
4247
+ if (fn)
4248
+ out.push(fn);
4249
+ }
3321
4250
  for (const prop of info.throwingSetters) {
3322
4251
  if (always || lowerer.wantBody(`%${className}.set:${prop}`))
3323
4252
  out.push(lowerer.throwingSetterFn(info, prop));
@@ -3329,14 +4258,29 @@ export function lowerClassMembers(lowerer, info) {
3329
4258
  * the base's signature — forward every param to super(), then run own
3330
4259
  * field initializers. */
3331
4260
  export function lowerClassCtor(lowerer, info) {
4261
+ const cached = info.localClass?.bodies.get(`%${info.def.name}.constructor`);
4262
+ if (cached)
4263
+ return cached;
3332
4264
  return withInstanceBindings(lowerer, info, () => lowerClassCtorInner(lowerer, info));
3333
4265
  }
4266
+ function classCaptureParams(info, context) {
4267
+ if (!info.localClass)
4268
+ return {};
4269
+ const environment = info.localClass.context;
4270
+ if (!environment)
4271
+ throw new InternalCompilerError("local class lowered outside its lexical environment");
4272
+ return { classCaptures: (context.captures ?? []).map((capture, index) => {
4273
+ if (!capture)
4274
+ throw new InternalCompilerError("missing local class capture");
4275
+ return { ...capture, slot: environment.captures.findIndex((entry) => entry.localId === context.captureSources[index]) };
4276
+ }) };
4277
+ }
3334
4278
  function lowerClassCtorInner(lowerer, info) {
3335
4279
  const className = info.def.name;
3336
4280
  const thisType = { kind: "object", className };
3337
4281
  const prevClass = lowerer.currentClass;
3338
4282
  lowerer.currentClass = info;
3339
- lowerer.fnStack.push(newFnCtx(false, null, null, VOID));
4283
+ lowerer.fnStack.push(newFnCtx(info.localClass !== undefined, null, null, VOID));
3340
4284
  try {
3341
4285
  const thisLocal = lowerer.declareThis(thisType);
3342
4286
  const params = [{ localId: thisLocal.id, name: "this", type: thisType }];
@@ -3365,8 +4309,13 @@ function lowerClassCtorInner(lowerer, info) {
3365
4309
  // defaults on entry, ahead of everything the body does.
3366
4310
  const declared = lowerer.declareParams(info.ctor.parameters, info.ctorParams);
3367
4311
  params.push(...declared.params);
4312
+ if (info.ctorParams.at(-1)?.mode === "arguments") {
4313
+ const local = lowerer.declareHiddenLocal("%arguments", DYN);
4314
+ params.push({ localId: local.id, name: local.name, type: DYN });
4315
+ lowerer.ctx.argumentsLocal = local;
4316
+ }
3368
4317
  body.push(...declared.prologue);
3369
- if (!ctorBase) {
4318
+ if (!ctorBase && !info.callableBase) {
3370
4319
  // Node's base-class order: field initializers run at the start
3371
4320
  // of construction, the parameter-property assignments open the
3372
4321
  // constructor body (probed — a field initializer reading a
@@ -3381,7 +4330,7 @@ function lowerClassCtorInner(lowerer, info) {
3381
4330
  }
3382
4331
  }
3383
4332
  else {
3384
- if (ctorBase) {
4333
+ if (ctorBase || info.callableBase) {
3385
4334
  // Synthetic forwarding params (the inherited ABI signature).
3386
4335
  // Nothing references them by symbol — only the super call below,
3387
4336
  // which forwards the already-completed values UNCHANGED (defaults
@@ -3411,6 +4360,7 @@ function lowerClassCtorInner(lowerer, info) {
3411
4360
  params,
3412
4361
  returnType: VOID,
3413
4362
  locals: lowerer.ctx.locals,
4363
+ ...classCaptureParams(info, lowerer.ctx),
3414
4364
  body,
3415
4365
  loc: locOf(info.ctor ?? info.decl),
3416
4366
  };
@@ -3450,7 +4400,7 @@ export function classMemberNameOf(lowerer, name) {
3450
4400
  return `sym:${member}`;
3451
4401
  }
3452
4402
  }
3453
- return lowerer.foldedStringKeyOf(name.expression);
4403
+ return classSymbolKeyOf(lowerer, name.expression)?.fieldName ?? lowerer.foldedStringKeyOf(name.expression);
3454
4404
  }
3455
4405
  export function classIteratorOf(lowerer, t) {
3456
4406
  if (t.kind !== "object")
@@ -3651,12 +4601,17 @@ export function classIteratorRestDrainCall(lowerer, cit, itVal, loc) {
3651
4601
  * (accessors are methods with property syntax: "get:x"/"set:x" entries —
3652
4602
  * see collectClassShape). */
3653
4603
  export function lowerClassMethodMember(lowerer, info, fnLike) {
4604
+ if (info.localClass?.ready) {
4605
+ const member = classMemberNameOf(lowerer, fnLike.name);
4606
+ const name = ts.isMethodDeclaration(fnLike) ? member : `${ts.isGetAccessor(fnLike) ? "get" : "set"}:${member}`;
4607
+ return info.localClass.bodies.get(`%${info.def.name}.${name}`) ?? null;
4608
+ }
3654
4609
  return withInstanceBindings(lowerer, info, () => lowerClassMethodMemberInner(lowerer, info, fnLike));
3655
4610
  }
3656
4611
  function lowerClassMethodMemberInner(lowerer, info, fnLike) {
3657
4612
  const className = info.def.name;
3658
4613
  const thisType = { kind: "object", className };
3659
- const memberName = ts.isMethodDeclaration(fnLike) ? classMemberNameOf(lowerer, fnLike.name) : ts.isIdentifier(fnLike.name) || ts.isPrivateIdentifier(fnLike.name) ? fnLike.name.text : null;
4614
+ const memberName = classMemberNameOf(lowerer, fnLike.name);
3660
4615
  if (memberName === null)
3661
4616
  return null;
3662
4617
  const mName = ts.isMethodDeclaration(fnLike)
@@ -3665,6 +4620,21 @@ function lowerClassMethodMemberInner(lowerer, info, fnLike) {
3665
4620
  const sig = info.methods.get(mName);
3666
4621
  if (!sig || !fnLike.body)
3667
4622
  return null;
4623
+ const entryFence = info.methodEntryFences?.get(mName);
4624
+ if (entryFence) {
4625
+ lowerer.runtimeFences.push(entryFence);
4626
+ return lowerer.deferToRuntimeFence(lowerer.diags.length, fnLike.name, {
4627
+ kind: "function",
4628
+ name: `%${className}.${mName}`,
4629
+ params: [
4630
+ { localId: "this.0", name: "this", type: thisType },
4631
+ ...sig.params.map((p, i) => ({ localId: `p.${i}`, name: `p${i}`, type: p.type })),
4632
+ ],
4633
+ returnType: sig.ret,
4634
+ fallback: entryFence,
4635
+ allowDiagSink: true,
4636
+ });
4637
+ }
3668
4638
  const prevClass = lowerer.currentClass;
3669
4639
  lowerer.currentClass = info;
3670
4640
  // ASYNC methods: the module function is an async IrFunction — its
@@ -3674,18 +4644,16 @@ function lowerClassMethodMemberInner(lowerer, info, fnLike) {
3674
4644
  // spawn's argument pack). Dispatch is static by construction — the
3675
4645
  // override fence at collection keeps async methods out of vtables.
3676
4646
  const isAsync = sig.async === true;
3677
- // #PRIVATE GENERATOR methods: the module function is a generator
3678
- // IrFunction — the body returns the TReturn channel, yields ride
3679
- // ctx.generator, and every call (direct by construction — privates
3680
- // never virtualize) enters through the emitted gen-spawn wrapper with
3681
- // `this` in the argument pack, answering the suspended generator.
4647
+ // GENERATOR methods: the module function returns the TReturn channel,
4648
+ // yields ride ctx.generator, and direct calls enter through the emitted
4649
+ // gen-spawn wrapper with `this` in the argument pack.
3682
4650
  const genCh = sig.gen !== undefined && sig.ret.kind === "generator" ? sig.gen : null;
3683
4651
  const bodyReturn = genCh !== null
3684
4652
  ? lowerer.genBodyReturnType(sig.ret)
3685
4653
  : isAsync && sig.ret.kind === "promise"
3686
4654
  ? sig.ret.inner
3687
4655
  : sig.ret;
3688
- const fnCtx = newFnCtx(false, null, null, bodyReturn);
4656
+ const fnCtx = newFnCtx(info.localClass !== undefined, null, null, bodyReturn);
3689
4657
  fnCtx.isAsync = isAsync;
3690
4658
  if (genCh !== null)
3691
4659
  fnCtx.generator = genCh;
@@ -3697,6 +4665,15 @@ function lowerClassMethodMemberInner(lowerer, info, fnLike) {
3697
4665
  // (JS allows this in method defaults; it is param 0 here).
3698
4666
  const declared = lowerer.declareParams(fnLike.parameters, sig.params);
3699
4667
  params.push(...declared.params);
4668
+ // A shorter JS override still implements every inherited ABI slot.
4669
+ // These tail parameters have no source binding or default prologue.
4670
+ for (const shape of sig.params.slice(declared.params.length)) {
4671
+ const name = shape.mode === "arguments" ? "%arguments" : "%ignored";
4672
+ const local = lowerer.declareHiddenLocal(name, shape.type);
4673
+ params.push({ localId: local.id, name, type: shape.type });
4674
+ if (shape.mode === "arguments")
4675
+ fnCtx.argumentsLocal = local;
4676
+ }
3700
4677
  const body = [...declared.prologue, ...lowerer.lowerStmts(fnLike.body.statements)];
3701
4678
  appendImplicitUndefinedReturn(lowerer, body, bodyReturn, locOf(fnLike));
3702
4679
  const fn = {
@@ -3704,6 +4681,7 @@ function lowerClassMethodMemberInner(lowerer, info, fnLike) {
3704
4681
  params,
3705
4682
  returnType: bodyReturn,
3706
4683
  locals: lowerer.ctx.locals,
4684
+ ...classCaptureParams(info, lowerer.ctx),
3707
4685
  body,
3708
4686
  loc: locOf(fnLike),
3709
4687
  };
@@ -3729,18 +4707,31 @@ export function lowerStaticMethod(lowerer, info, name) {
3729
4707
  const entry = info.staticMethods?.get(name);
3730
4708
  if (!entry?.member.body)
3731
4709
  return null;
3732
- // Async statics: an async IrFunction like any module function — the
3733
- // body returns the promise's INNER type, calls enter through the
3734
- // fiber spawn wrapper (callTargetC routes by fn.async).
3735
- const isAsync = entry.member.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword) === true &&
3736
- entry.ret.kind === "promise";
3737
- const bodyReturn = isAsync && entry.ret.kind === "promise" ? entry.ret.inner : entry.ret;
4710
+ const isAsync = entry.member.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword) === true;
4711
+ const isGenerator = entry.member.asteriskToken !== undefined;
4712
+ if (isGenerator && (entry.ret.kind !== "generator" || (entry.ret.async === true) !== isAsync)) {
4713
+ lowerer.badType(entry.member.name, lowerer.typeOf(entry.member.name));
4714
+ }
4715
+ if (isAsync && !isGenerator && entry.ret.kind !== "promise") {
4716
+ lowerer.badType(entry.member.name, lowerer.typeOf(entry.member.name));
4717
+ }
4718
+ const genCh = isGenerator && entry.ret.kind === "generator" ? generatorMeta(lowerer, entry.ret) : null;
4719
+ const bodyReturn = genCh !== null
4720
+ ? lowerer.genBodyReturnType(entry.ret)
4721
+ : isAsync && entry.ret.kind === "promise" ? entry.ret.inner : entry.ret;
3738
4722
  const fnCtx = newFnCtx(false, null, null, bodyReturn);
3739
4723
  fnCtx.isAsync = isAsync;
4724
+ if (genCh !== null)
4725
+ fnCtx.generator = genCh;
3740
4726
  lowerer.fnStack.push(fnCtx);
3741
4727
  try {
3742
4728
  rejectStaticThis(lowerer, entry.member.body, (keyword) => `'${keyword}' in static methods (it names the RECEIVER class — a dynamic value; reference the class by name instead)`);
3743
4729
  const declared = lowerer.declareParams(entry.member.parameters, entry.params);
4730
+ if (entry.params.at(-1)?.mode === "arguments") {
4731
+ const local = lowerer.declareHiddenLocal("%arguments", DYN);
4732
+ declared.params.push({ localId: local.id, name: "%arguments", type: DYN });
4733
+ fnCtx.argumentsLocal = local;
4734
+ }
3744
4735
  const body = [...declared.prologue, ...lowerer.lowerStmts(entry.member.body.statements)];
3745
4736
  appendImplicitUndefinedReturn(lowerer, body, bodyReturn, locOf(entry.member));
3746
4737
  const fn = {
@@ -3753,6 +4744,8 @@ export function lowerStaticMethod(lowerer, info, name) {
3753
4744
  };
3754
4745
  if (isAsync)
3755
4746
  fn.async = true;
4747
+ if (genCh !== null)
4748
+ fn.generator = genCh;
3756
4749
  return fn;
3757
4750
  }
3758
4751
  catch (e) {
@@ -3827,10 +4820,29 @@ export function fieldInitStmts(lowerer, info, thisLocal) {
3827
4820
  const out = [];
3828
4821
  const thisType = { kind: "object", className: info.def.name };
3829
4822
  for (const f of info.fieldOrder) {
4823
+ if (f.errorCause) {
4824
+ const loc = f.initializer ? locOf(f.initializer) : f.undefinedInitializer;
4825
+ const value = f.initializer ? lowerer.lowerExprExpecting(f.initializer, DYN) : dynUndefinedExpr(loc);
4826
+ out.push({ kind: "exprStmt", expr: { kind: "libCall", fn: "error.defineCause",
4827
+ args: [{ kind: "varRef", localId: thisLocal.id, type: thisType, loc }, value], type: VOID, loc }, loc });
4828
+ continue;
4829
+ }
4830
+ if (f.undefinedInitializer) {
4831
+ const loc = f.undefinedInitializer;
4832
+ out.push({
4833
+ kind: "fieldSet",
4834
+ obj: { kind: "varRef", localId: thisLocal.id, type: thisType, loc },
4835
+ className: info.def.name,
4836
+ field: f.name,
4837
+ value: dynUndefinedExpr(loc),
4838
+ loc,
4839
+ });
4840
+ }
3830
4841
  if (!f.initializer)
3831
4842
  continue;
3832
4843
  lowerer.stats.statementsTotal++;
3833
4844
  lowerer.bumpFileStat(locOf(f.initializer).file, "total");
4845
+ const diagsBefore = lowerer.diags.length;
3834
4846
  try {
3835
4847
  const value = lowerer.lowerExprExpecting(f.initializer, f.type);
3836
4848
  out.push({
@@ -3847,6 +4859,11 @@ export function fieldInitStmts(lowerer, info, thisLocal) {
3847
4859
  throw e;
3848
4860
  lowerer.stats.statementsFailed++;
3849
4861
  lowerer.bumpFileStat(locOf(f.initializer).file, "failed");
4862
+ if (isJsSourceFile(f.initializer.getSourceFile()) && lowerer.diagSink === null) {
4863
+ const fence = lowerer.deferToRuntimeFence(diagsBefore, f.initializer, { kind: "statement" });
4864
+ if (fence)
4865
+ out.push(fence);
4866
+ }
3850
4867
  }
3851
4868
  }
3852
4869
  return out;
@@ -3882,80 +4899,93 @@ function paramPropInitStmts(lowerer, info, thisLocal) {
3882
4899
  }
3883
4900
  return out;
3884
4901
  }
3885
- /** A derived constructor's body: statements lower as usual EXCEPT the
3886
- * top-level `super(...)` statement, which becomes a direct call to the
3887
- * base constructor over the same `this`, immediately followed by this
3888
- * class's field initializers (JS runs them when super returns). tsc
3889
- * guarantees a super call exists and runs before any this-use; the
3890
- * supported form is a top-level expression statement — anywhere else
3891
- * (conditionals, expression positions) is rejected, not misordered. */
3892
- export function lowerDerivedCtorBody(lowerer, info, thisLocal,
3893
- /** Mixin forwarding-constructor mode: `super(...args)` forwards these
3894
- * pre-declared synthetic params directly (the spread never lowers —
3895
- * the base's ABI is this constructor's ABI). */
3896
- forward) {
3897
- const out = [];
4902
+ /** Super statements initialize the base and then the derived fields on
4903
+ * whichever control-flow path executes. Repeated calls are explicitly
4904
+ * refused until native layouts can allocate a second receiver. */
4905
+ export function lowerDerivedCtorBody(lowerer, info, thisLocal, forward) {
3898
4906
  let superSeen = false;
3899
- for (const stmt of info.ctor.body.statements) {
3900
- const superCall = ts.isExpressionStatement(stmt) &&
3901
- ts.isCallExpression(stmt.expression) &&
3902
- stmt.expression.expression.kind === ts.SyntaxKind.SuperKeyword
3903
- ? stmt.expression
3904
- : null;
3905
- if (!superCall) {
3906
- out.push(...lowerer.lowerStmts([stmt]));
3907
- continue;
4907
+ const initialized = lowerer.declareHiddenLocal("%superInitialized", BOOL);
4908
+ initialized.mutable = true;
4909
+ const context = lowerer.ctx;
4910
+ const previous = context.superCall;
4911
+ const previousInitialized = context.superInitialized;
4912
+ context.superInitialized = initialized;
4913
+ context.superCall = (superCall) => {
4914
+ if (!ts.isExpressionStatement(superCall.parent))
4915
+ lowerer.unsupported("SC1090", superCall, "super() in an expression position");
4916
+ superSeen = true;
4917
+ const loc = locOf(superCall);
4918
+ const statements = [{ kind: "if", cond: { kind: "varRef", localId: initialized.id, type: BOOL, loc }, then: [{ kind: "exprStmt", expr: nodeThrowExpr(0, "SC2020", "repeated super() calls require a fresh receiver and are not supported yet", DYN, loc), loc }], else_: null, loc }];
4919
+ if (info.callableBase) {
4920
+ if (superCall.arguments.some(ts.isSpreadElement))
4921
+ lowerer.unsupported("SC1090", superCall, "spreading explicit super arguments into an ordinary constructor");
4922
+ const pack = { kind: "dynArrLit", elems: superCall.arguments.map((arg) => lowerer.lowerExprExpecting(arg, DYN)), type: DYN, loc };
4923
+ statements.push(lowerer.superCallStmt(info, thisLocal, [pack], loc));
3908
4924
  }
3909
- if (!lowerer.suppressStats) {
3910
- lowerer.stats.statementsTotal++;
3911
- lowerer.bumpFileStat(locOf(stmt).file, "total");
3912
- }
3913
- try {
3914
- if (superSeen)
3915
- lowerer.unsupported("SC1090", stmt, "multiple super() calls");
3916
- superSeen = true;
4925
+ else {
3917
4926
  const base = superBaseOf(info);
3918
- if (base.builtinEmitter && superCall.arguments.length > 0) {
3919
- // @types/node admits super({ captureRejections }) — no lowering.
4927
+ if (base.builtinEmitter && superCall.arguments.length > 0)
3920
4928
  lowerer.unsupported("SC1090", superCall, "EventEmitter constructor options ('captureRejections')");
3921
- }
3922
4929
  if (base.builtinStream) {
3923
- // super(options?) into a runtime stream base: the stream spoke
3924
- // parses the options and binds overridden underscore methods.
3925
- out.push(...lowerStreamSuperCall(lowerer, info, base, superCall.arguments, thisLocal, locOf(stmt), stmt));
3926
- out.push(...lowerer.fieldInitStmts(info, thisLocal));
3927
- out.push(...paramPropInitStmts(lowerer, info, thisLocal));
3928
- continue;
4930
+ statements.push(...lowerStreamSuperCall(lowerer, info, base, superCall.arguments, thisLocal, loc, superCall));
3929
4931
  }
3930
- const args = forward !== undefined
3931
- ? forward
3932
- : base.builtinError
3933
- ? [lowerer.errorMessageArg(superCall.arguments, locOf(stmt), stmt)]
3934
- : base.builtinEmitter
3935
- ? []
3936
- : lowerer.completeArgs(superCall.arguments, base.ctorParams, locOf(stmt), stmt);
3937
- out.push(lowerer.superCallStmt(info, thisLocal, args, locOf(stmt)));
3938
- // super() returns → field initializers → parameter-property
3939
- // assignments (Node's order, probed) → the rest of the body.
3940
- out.push(...lowerer.fieldInitStmts(info, thisLocal));
3941
- out.push(...paramPropInitStmts(lowerer, info, thisLocal));
3942
- }
3943
- catch (e) {
3944
- if (!(e instanceof PoisonError))
3945
- throw e;
3946
- if (!lowerer.suppressStats) {
3947
- lowerer.stats.statementsFailed++;
3948
- lowerer.bumpFileStat(locOf(stmt).file, "failed");
4932
+ else {
4933
+ const surplusSpread = forward === undefined && !base.builtinError && !base.builtinEmitter &&
4934
+ base.ctorParams.length === 0 && superCall.arguments.some(ts.isSpreadElement);
4935
+ if (surplusSpread) {
4936
+ const evaluated = lowerer.completeArgs(superCall.arguments, [{ mode: "dynRest", type: DYN }], loc, superCall);
4937
+ for (const value of evaluated)
4938
+ statements.push({ kind: "exprStmt", expr: value, loc });
4939
+ }
4940
+ const surplus = forward === undefined && !base.builtinError && !base.builtinEmitter &&
4941
+ !base.ctorParams.some((param) => param.mode === "rest" || param.mode === "dynRest" || param.mode === "islandRest") &&
4942
+ !superCall.arguments.some(ts.isSpreadElement) && superCall.arguments.length > base.ctorParams.length;
4943
+ let args = surplusSpread ? [] : forward !== undefined ? forward : base.builtinError
4944
+ ? lowerer.errorConstructorArgs(superCall.arguments, loc, superCall) : base.builtinEmitter ? []
4945
+ : lowerer.completeArgs(surplus ? superCall.arguments.slice(0, base.ctorParams.length) : superCall.arguments, base.ctorParams, loc, superCall);
4946
+ if (surplus) {
4947
+ args = args.map((arg) => {
4948
+ const local = lowerer.declareHiddenLocal("%superArgument", arg.type);
4949
+ statements.push({ kind: "varDecl", localId: local.id, init: arg, loc });
4950
+ return { kind: "varRef", localId: local.id, type: arg.type, loc };
4951
+ });
4952
+ for (const argument of superCall.arguments.slice(base.ctorParams.length)) {
4953
+ statements.push({ kind: "exprStmt", expr: lowerer.lowerExpr(argument), loc: locOf(argument) });
4954
+ }
4955
+ }
4956
+ statements.push(lowerer.superCallStmt(info, thisLocal, args, loc));
3949
4957
  }
3950
4958
  }
4959
+ statements.push({ kind: "assign", localId: initialized.id, value: { kind: "boolLit", value: true, type: BOOL, loc }, loc });
4960
+ delete context.superInitialized;
4961
+ try {
4962
+ statements.push(...lowerer.fieldInitStmts(info, thisLocal), ...paramPropInitStmts(lowerer, info, thisLocal));
4963
+ }
4964
+ finally {
4965
+ context.superInitialized = initialized;
4966
+ }
4967
+ const result = { kind: "varRef", localId: thisLocal.id, type: thisLocal.type, loc };
4968
+ return { kind: "seqExpr", stmts: statements.map((statement) => statement.kind === "runtimeFence"
4969
+ ? { kind: "exprStmt", expr: nodeThrowExpr(0, statement.code, statement.message, DYN, statement.loc), loc: statement.loc }
4970
+ : statement), result, type: result.type, loc };
4971
+ };
4972
+ try {
4973
+ const result = lowerer.lowerStmts(info.ctor.body.statements);
4974
+ result.push({ kind: "if", cond: { kind: "unary", op: "!", operand: { kind: "varRef", localId: initialized.id, type: BOOL, loc: locOf(info.ctor) }, type: BOOL, loc: locOf(info.ctor) }, then: [{ kind: "exprStmt", expr: nodeThrowExpr(5, "", "Must call super constructor in derived class before accessing 'this' or returning from derived constructor", DYN, locOf(info.ctor)), loc: locOf(info.ctor) }], else_: null, loc: locOf(info.ctor) });
4975
+ if (!superSeen)
4976
+ lowerer.pushDiag(unsupportedDiag("SC1090", locOf(info.ctor), "derived constructors without a lowered super() call"));
4977
+ return [{ kind: "varDecl", localId: initialized.id, init: { kind: "boolLit", value: false, type: BOOL, loc: locOf(info.ctor) }, loc: locOf(info.ctor) }, ...result];
3951
4978
  }
3952
- if (!superSeen) {
3953
- // tsc guarantees the call exists somewhere; if it wasn't a top-level
3954
- // statement the per-site rejection above already fired — this is the
3955
- // constructor-level backstop so a half-initialized ctor never emits.
3956
- lowerer.pushDiag(unsupportedDiag("SC1090", locOf(info.ctor), "super() calls anywhere but as a top-level constructor statement"));
4979
+ finally {
4980
+ if (previous)
4981
+ context.superCall = previous;
4982
+ else
4983
+ delete context.superCall;
4984
+ if (previousInitialized)
4985
+ context.superInitialized = previousInitialized;
4986
+ else
4987
+ delete context.superInitialized;
3957
4988
  }
3958
- return out;
3959
4989
  }
3960
4990
  /** `super(args)` → direct call of the base constructor with the SAME
3961
4991
  * `this` (upcast; retained by the varRef read — the callee owns and
@@ -3968,6 +4998,15 @@ export function superCallStmt(lowerer, info, thisLocal, args, loc) {
3968
4998
  type: { kind: "object", className: info.def.name },
3969
4999
  loc,
3970
5000
  };
5001
+ if (info.callableBase)
5002
+ return {
5003
+ kind: "exprStmt", expr: { kind: "libCall", fn: "dyn.classSuper",
5004
+ args: [info.localClass ? { kind: "libCall", fn: "dyn.getPrototype", args: [
5005
+ { kind: "dynFrom", value: { kind: "fieldGet", obj: thisRef, className: info.def.name,
5006
+ field: `%classEnvironment:${info.def.name}`, type: { kind: "classval", className: info.def.name }, loc }, type: DYN, loc },
5007
+ ], type: DYN, loc } : { kind: "varRef", localId: info.callableBase.constructorId, type: DYN, loc },
5008
+ lowerer.coerceToExpected(thisRef, DYN), args[0]], type: VOID, loc }, loc,
5009
+ };
3971
5010
  if (base.builtinError) {
3972
5011
  // super(message) into the runtime-provided Error constructor: stamps
3973
5012
  // name/message on the (already-allocated) object. Receiver + message
@@ -3977,7 +5016,7 @@ export function superCallStmt(lowerer, info, thisLocal, args, loc) {
3977
5016
  kind: "exprStmt",
3978
5017
  expr: {
3979
5018
  kind: "libCall",
3980
- fn: "error.ctor",
5019
+ fn: "error.ctorOptions",
3981
5020
  args: [lowerer.upcastTo(thisRef, base.def.name), ...args],
3982
5021
  type: VOID,
3983
5022
  loc,
@@ -4081,9 +5120,22 @@ export function lowerSuperMethodCall(lowerer, call, access) {
4081
5120
  const thisLocal = lowerer.resolveThis();
4082
5121
  if (!thisLocal)
4083
5122
  lowerer.unsupported("SC1080", access);
4084
- lowerer.noteEdge(`%${found.declarer.def.name}.${access.name.text}`);
4085
5123
  const loc = locOf(call);
4086
5124
  const thisRef = { kind: "varRef", localId: thisLocal.id, type: thisLocal.type, loc };
5125
+ if (lowerer.prototypeMethodAccesses.has(access.name.text)) {
5126
+ const prototype = classPrototypeData(lowerer, cls.base, loc);
5127
+ if (prototype) {
5128
+ const callee = { kind: "dynKeyGet", value: prototype,
5129
+ key: { kind: "strLit", value: access.name.text, type: STRING, loc }, type: DYN, loc };
5130
+ const value = { kind: "dynCall", callee, receiver: lowerer.coerceToExpected(thisRef, DYN),
5131
+ calleeName: access.getText(), args: call.arguments.map((arg) => lowerer.lowerExprExpecting(arg, DYN)), type: DYN, loc };
5132
+ return found.sig.ret.kind === "void" ? value : lowerer.coerceToExpected(value, found.sig.ret);
5133
+ }
5134
+ }
5135
+ if (found.declarer.builtinError) {
5136
+ return { kind: "libCall", fn: "error.toString", args: [lowerer.upcastTo(thisRef, "%Error")], type: STRING, loc };
5137
+ }
5138
+ lowerer.noteEdge(`%${found.declarer.def.name}.${access.name.text}`);
4087
5139
  const args = lowerer.completeArgs(call.arguments, found.sig.params, loc, call);
4088
5140
  return {
4089
5141
  kind: "call",
@@ -4163,8 +5215,8 @@ export function lowerSuperAccessorWrite(lowerer, access, rhs, loc) {
4163
5215
  }
4164
5216
  /** True when `info`'s EFFECTIVE constructor — its own, or the one
4165
5217
  * inherited through ctor-less bases — is a builtin error class's. Such
4166
- * classes construct with the error message rule, and their synthesized
4167
- * constructors forward one plain string to error.ctor. */
5218
+ * classes construct with the error argument rule, and their synthesized
5219
+ * constructors forward both checked-dynamic values to error.ctorOptions. */
4168
5220
  export function inheritsBuiltinErrorCtor(lowerer, info) {
4169
5221
  for (let c = info; c; c = c.base) {
4170
5222
  if (c.builtinError)
@@ -4201,25 +5253,18 @@ function inheritsBuiltinStreamCtor(lowerer, info) {
4201
5253
  }
4202
5254
  return false;
4203
5255
  }
4204
- /** `new C(args)` for a class declared in the program (imports resolve
4205
- * through aliases, so cross-module classes construct too). */
4206
- /** The single message argument of a builtin Error construction or
4207
- * super() call: "" when omitted or explicitly undefined (Node's message
4208
- * property default), the string otherwise. The lib signature's second
4209
- * parameter (options/cause) has no lowering. */
4210
- export function errorMessageArg(lowerer, args, loc, blame) {
4211
- if (args.length > 1) {
4212
- lowerer.unsupported("SC1090", args[1] ?? blame, "Error constructor options ('cause')");
4213
- }
4214
- if (args.length === 0)
4215
- return { kind: "strLit", value: "", type: STRING, loc };
4216
- const value = lowerer.lowerExpr(args[0]);
4217
- if (value.type.kind === "string")
4218
- return value;
4219
- if (value.kind === "unitLit" && value.unit === "undefined") {
4220
- return { kind: "strLit", value: "", type: STRING, loc };
4221
- }
4222
- lowerer.unsupported("SC1090", args[0], `Error messages of type '${lowerer.fmt(value.type)}' (the message must be a string)`);
5256
+ /** Preserve argument evaluation order and option presence through builtin
5257
+ * and inherited Error constructors. Checked-dynamic conversion retains
5258
+ * Error identity and distinguishes a missing cause from undefined. */
5259
+ export function errorConstructorArgs(lowerer, args, loc, blame) {
5260
+ if (args.length > 2)
5261
+ lowerer.unsupported("SC1090", blame, "Error constructors with more than two arguments");
5262
+ return [0, 1].map((i) => {
5263
+ const arg = args[i];
5264
+ if (!arg)
5265
+ return dynUndefinedExpr(loc);
5266
+ return lowerer.lowerExprExpecting(arg, DYN);
5267
+ });
4223
5268
  }
4224
5269
  /** `new C(...)` of a registered PROGRAM class — the shared tail of the
4225
5270
  * identifier and namespace-qualified construction forms. */
@@ -4252,6 +5297,8 @@ function fenceDecorationThrows(lowerer, info, blame) {
4252
5297
  function lowerProgramClassNew(lowerer, expr, declaredInfo, loc) {
4253
5298
  const info = genericNewTarget(lowerer, expr, declaredInfo);
4254
5299
  fenceDecorationThrows(lowerer, info, expr);
5300
+ if (info.localClass)
5301
+ lowerer.unsupported("SC1090", expr, "construction through a function-local class's internal name");
4255
5302
  lowerer.noteEdge(`%${info.def.name}.constructor`);
4256
5303
  // A ctor-less chain into an EventEmitter base inherits `new C()` —
4257
5304
  // zero arguments (the options bag fences, like the super() form).
@@ -4263,12 +5310,16 @@ function lowerProgramClassNew(lowerer, expr, declaredInfo, loc) {
4263
5310
  if (lowerer.inheritsBuiltinEmitterCtor(info) && (expr.arguments ?? []).length > 0) {
4264
5311
  lowerer.unsupported("SC1090", expr.arguments[0], "EventEmitter constructor options ('captureRejections')");
4265
5312
  }
4266
- // A ctor-less chain into a builtin error base inherits `new
4267
- // C(message?)` — completed by the error rule (one plain string),
4268
- // not the general ABI completion.
5313
+ // A ctor-less chain into a builtin error base inherits both arguments;
5314
+ // each synthesized constructor forwards the same pair to its base.
4269
5315
  const args = lowerer.inheritsBuiltinErrorCtor(info)
4270
- ? [lowerer.errorMessageArg(expr.arguments ?? [], loc, expr)]
5316
+ ? lowerer.errorConstructorArgs(expr.arguments ?? [], loc, expr)
4271
5317
  : lowerer.completeArgs(expr.arguments ?? [], info.ctorParams, loc, expr);
5318
+ for (let current = info; current; current = current.base) {
5319
+ if (current.def.baseValueGlobal)
5320
+ return { kind: "newValue", callee: classValueRef(lowerer, info, expr),
5321
+ args, type: { kind: "object", className: info.def.name }, loc };
5322
+ }
4272
5323
  return {
4273
5324
  kind: "new",
4274
5325
  className: info.def.name,
@@ -4290,6 +5341,68 @@ function assignedThisFieldType(lowerer, expr) {
4290
5341
  }
4291
5342
  export function lowerNew(lowerer, expr) {
4292
5343
  const loc = locOf(expr);
5344
+ const instanceConstructor = lowerInstanceConstructorNew(lowerer, expr);
5345
+ if (instanceConstructor)
5346
+ return instanceConstructor;
5347
+ const objectFactory = lowerObjectFactoryNew(lowerer, expr);
5348
+ if (objectFactory)
5349
+ return objectFactory;
5350
+ if (ts.isIdentifier(expr.expression)) {
5351
+ const symbol = lowerer.resolveValueSymbol(expr.expression);
5352
+ const declaration = symbol && lowerer.checker.declarationsOf(symbol).find((node) => ts.isFunctionDeclaration(node) && node.body !== undefined);
5353
+ if (declaration && ts.isFunctionDeclaration(declaration) && declaration.body) {
5354
+ const last = declaration.body.statements.at(-1);
5355
+ if (last && ts.isReturnStatement(last) && last.expression && ts.isObjectLiteralExpression(last.expression)) {
5356
+ lowerer.unsupported("SC1090", expr, "object-returning constructors that observe this or return mixed primitive/object values");
5357
+ }
5358
+ }
5359
+ }
5360
+ let selected = expr.expression;
5361
+ while (ts.isParenthesizedExpression(selected))
5362
+ selected = selected.expression;
5363
+ if (ts.isConditionalExpression(selected)) {
5364
+ const yes = exactClassOfReceiver(lowerer, selected.whenTrue);
5365
+ const no = exactClassOfReceiver(lowerer, selected.whenFalse);
5366
+ if (yes && no && !yes.classDecorators && !no.classDecorators) {
5367
+ const yesType = { kind: "object", className: yes.def.name };
5368
+ const noType = { kind: "object", className: no.def.name };
5369
+ const type = yes === no ? yesType : { kind: "union", unionId: lowerer.unions.intern([yesType, noType].sort((a, b) => typeKey(a) < typeKey(b) ? -1 : 1)) };
5370
+ return { kind: "ternary", cond: lowerer.lowerCondition(selected.condition),
5371
+ then: lowerer.coerceInto(expr, lowerProgramClassNew(lowerer, expr, yes, loc), type),
5372
+ else_: lowerer.coerceInto(expr, lowerProgramClassNew(lowerer, expr, no, loc), type), type, loc };
5373
+ }
5374
+ }
5375
+ if (ts.isPropertyAccessExpression(expr.expression) && expr.expression.name.text === "Segmenter" &&
5376
+ lowerer.isStdlibGlobal(expr.expression.expression, "Intl")) {
5377
+ const args = expr.arguments ?? [];
5378
+ const undefinedArg = (arg) => (lowerer.typeOf(arg).flags & ts.TypeFlags.Undefined) !== 0;
5379
+ if (args.length > 2 || (args[0] && !undefinedArg(args[0]))) {
5380
+ lowerer.noLowering("Intl.Segmenter locale negotiation", expr, "omit the locale or pass undefined for default Unicode grapheme segmentation");
5381
+ }
5382
+ const options = args[1];
5383
+ if (options && !undefinedArg(options) &&
5384
+ !(ts.isObjectLiteralExpression(options) && options.properties.every((property) => ts.isPropertyAssignment(property) &&
5385
+ (ts.isIdentifier(property.name) || ts.isStringLiteral(property.name)) && property.name.text === "granularity" &&
5386
+ ts.isStringLiteral(property.initializer) && property.initializer.text === "grapheme"))) {
5387
+ lowerer.noLowering("Intl.Segmenter options", options, 'the native segmenter supports default options and { granularity: "grapheme" }; word and sentence segmentation remain unsupported');
5388
+ }
5389
+ // Explicit undefined expressions can carry effects; retain argument order.
5390
+ const stmts = args.map((arg) => {
5391
+ const value = lowerer.lowerExpr(arg);
5392
+ return { kind: "exprStmt", expr: value.type.kind === "void" ? value : lowerer.coerceInto(arg, value, DYN), loc: locOf(arg) };
5393
+ });
5394
+ const result = { kind: "libCall", fn: "intl.segmenterNew", args: [], type: DYN, loc };
5395
+ return stmts.length ? { kind: "seqExpr", stmts, result, type: DYN, loc } : result;
5396
+ }
5397
+ const consoleCtor = ts.isIdentifier(expr.expression)
5398
+ ? lowerer.builtinImportOf(expr.expression)
5399
+ : ts.isPropertyAccessExpression(expr.expression) &&
5400
+ lowerer.builtinNamespaceModuleOf(expr.expression.expression) === "console"
5401
+ ? { module: "console", member: expr.expression.name.text }
5402
+ : null;
5403
+ if (consoleCtor?.module === "console" && consoleCtor.member === "Console") {
5404
+ lowerer.noLowering("new console.Console", expr, builtinFenceHintOf("console", "Console"));
5405
+ }
4293
5406
  // `new X(...)` where X is a package-declared class, in a static build:
4294
5407
  // the per-package requires-dynamic diagnostic (the constructor runs in
4295
5408
  // the embedded engine). Under --dynamic, X is jsval-typed and lowers
@@ -4356,9 +5469,11 @@ export function lowerNew(lowerer, expr) {
4356
5469
  if (info?.classDecorators?.valueGlobalId !== undefined) {
4357
5470
  lowerer.unsupported("SC1090", expr, "constructing a decorated class through a qualified name (a replacing decorator rebinds the class name — construct through the bare name)");
4358
5471
  }
4359
- if (info)
5472
+ if (info && !info.localClass)
4360
5473
  return lowerProgramClassNew(lowerer, expr, info, loc);
4361
- lowerer.unsupported("SC1090", expr, `constructing '${expr.expression.name.text}' (a namespace member with no class lowering)`);
5474
+ // A namespace export can hold a class returned by a factory.
5475
+ // Let the class-value path below preserve that constructor's
5476
+ // lexical environment instead of requiring a class declaration.
4362
5477
  }
4363
5478
  // `new B.C()` where B is an AMBIENT namespace (fundule merges
4364
5479
  // included): Node evaluates the callee first and throws
@@ -4381,7 +5496,7 @@ export function lowerNew(lowerer, expr) {
4381
5496
  // member-export symbol's; the class collects on demand (a body
4382
5497
  // lowering ahead of the assignment statement).
4383
5498
  if (!expr.expression.questionDotToken &&
4384
- ((isCjsJsFile(expr.getSourceFile()) &&
5499
+ ((isCjsJsFile(expr.getSourceFile(), lowerer.program) &&
4385
5500
  (isModuleExportsAccess(expr.expression.expression) ||
4386
5501
  (ts.isIdentifier(expr.expression.expression) &&
4387
5502
  expr.expression.expression.text === "exports" &&
@@ -4444,12 +5559,20 @@ export function lowerNew(lowerer, expr) {
4444
5559
  if (agent)
4445
5560
  return agent;
4446
5561
  }
4447
- if (ts.isIdentifier(expr.expression)) {
5562
+ if (ts.isIdentifier(expr.expression) || ts.isPropertyAccessExpression(expr.expression) && ts.isIdentifier(expr.expression.name) &&
5563
+ lowerer.isStdlibGlobal(expr.expression.expression, "globalThis")) {
4448
5564
  // `import C = N.C; new C()` — the alias's own source-order guards
4449
5565
  // (a no-op for every non-import= binding).
4450
- fenceEarlyAliasUse(lowerer, expr.expression, expr);
4451
- const symbol = lowerer.resolveValueSymbol(expr.expression);
4452
- // `new Error(msg?)` (and TypeError/RangeError/SyntaxError): the
5566
+ if (ts.isIdentifier(expr.expression))
5567
+ fenceEarlyAliasUse(lowerer, expr.expression, expr);
5568
+ const identifier = ts.isIdentifier(expr.expression) ? expr.expression : expr.expression.name;
5569
+ const symbol = ts.isIdentifier(identifier) ? lowerer.resolveValueSymbol(identifier) : null;
5570
+ if (ts.isIdentifier(identifier) && lowerer.isStdlibGlobal(identifier, "Array")) {
5571
+ return lowerArrayConstructor(lowerer, expr, expr.arguments ?? []);
5572
+ }
5573
+ if (isNativeProxyInitializer(lowerer, expr))
5574
+ return lowerNativeProxy(lowerer, expr);
5575
+ // `new Error(msg?)` and its standard subclasses: the
4453
5576
  // runtime-provided classes construct through one libCall — the result
4454
5577
  // TYPE names which builtin, and the message completes to "" exactly
4455
5578
  // like Node's message property default.
@@ -4487,11 +5610,11 @@ export function lowerNew(lowerer, expr) {
4487
5610
  };
4488
5611
  }
4489
5612
  if (errInfo) {
4490
- const msg = lowerer.errorMessageArg(expr.arguments ?? [], loc, expr);
5613
+ const args = lowerer.errorConstructorArgs(expr.arguments ?? [], loc, expr);
4491
5614
  return {
4492
5615
  kind: "libCall",
4493
- fn: "error.new",
4494
- args: [msg],
5616
+ fn: "error.newOptions",
5617
+ args,
4495
5618
  type: { kind: "object", className: errInfo.def.name },
4496
5619
  loc,
4497
5620
  };
@@ -4519,25 +5642,40 @@ export function lowerNew(lowerer, expr) {
4519
5642
  return lowerStreamNew(lowerer, expr, streamInfo);
4520
5643
  // `new URL(input)`: the WHATWG URL class (stdlib/@types provenance —
4521
5644
  // a user's own `class URL` resolves through classBySymbol below).
4522
- // One string argument; invalid input throws a catchable TypeError
4523
- // ("Invalid URL"), like Node. The lib's base-argument form
4524
- // typechecks and is fenced here.
5645
+ // Invalid input or base throws a catchable TypeError ("Invalid URL").
4525
5646
  // `new RegExp(pattern, flags?)`: runtime construction over the same
4526
5647
  // libregexp engine the literals ride. The pattern compiles EAGERLY,
4527
5648
  // so bad input throws Node's catchable SyntaxError at construction.
4528
- // String arguments only (Node also accepts a RegExp to copy — that
4529
- // form keeps the fence).
5649
+ // Checked arguments retain native regexes and perform runtime coercion.
4530
5650
  if (symbol && symbol.name === "RegExp" && lowerer.isStdlibSymbol(symbol)) {
4531
5651
  const args = expr.arguments ?? [];
4532
5652
  if (args.length > 2) {
4533
5653
  lowerer.noLowering(`new RegExp with ${args.length} arguments`, expr);
4534
5654
  }
5655
+ if (args.some(ts.isSpreadElement))
5656
+ lowerer.noLowering("new RegExp with spread arguments", expr);
5657
+ const values = args.map((arg) => lowerer.lowerExpr(arg));
5658
+ if (values.some((value) => value.type.kind === "dyn" || value.type.kind === "regex")) {
5659
+ const checked = [0, 1].map((index) => values[index]
5660
+ ? lowerer.coerceInto(args[index], values[index], DYN)
5661
+ : { kind: "dynFrom", value: { kind: "unitLit", unit: "undefined", type: UNDEFINED_T, loc }, type: DYN, loc });
5662
+ return { kind: "libCall", fn: "regex.newChecked", args: checked, type: { kind: "regex" }, loc };
5663
+ }
4535
5664
  const strArg = (a, what) => {
4536
5665
  if (!a)
4537
5666
  return { kind: "strLit", value: "", type: STRING, loc };
4538
- const v = lowerer.lowerExpr(a);
5667
+ const v = values[args.indexOf(a)];
5668
+ const empty = { kind: "strLit", value: "", type: STRING, loc };
5669
+ if (v.type.kind === "undefinedT") {
5670
+ if (v.kind === "unitLit")
5671
+ return empty;
5672
+ return { kind: "seqExpr", stmts: [{ kind: "exprStmt", expr: lowerer.coerceToExpected(v, DYN), loc: locOf(a) }], result: empty, type: STRING, loc };
5673
+ }
5674
+ if (v.type.kind === "union" && lowerer.unions.get(v.type.unionId)?.arms.every((arm) => arm.kind === "string" || arm.kind === "undefinedT")) {
5675
+ return { kind: "nullish", left: v, right: empty, type: STRING, loc: locOf(a) };
5676
+ }
4539
5677
  if (v.type.kind !== "string") {
4540
- lowerer.noLowering(`new RegExp with a '${lowerer.fmt(v.type)}' ${what}`, a, "string arguments are the lowered form (a RegExp copy or ToString coercion has no lowering)");
5678
+ lowerer.noLowering(`new RegExp with a '${lowerer.fmt(v.type)}' ${what}`, a, "string or undefined arguments are the lowered form (a RegExp copy or ToString coercion has no lowering)");
4541
5679
  }
4542
5680
  return v;
4543
5681
  };
@@ -4546,25 +5684,7 @@ export function lowerNew(lowerer, expr) {
4546
5684
  return { kind: "libCall", fn: "regex.new", args: [pattern, flags], type: { kind: "regex" }, loc };
4547
5685
  }
4548
5686
  if (symbol && symbol.name === "URL" && lowerer.isStdlibSymbol(symbol)) {
4549
- const args = expr.arguments ?? [];
4550
- if (args.length === 2) {
4551
- const folded = staticForkString(lowerer.program, expr);
4552
- if (folded === null) {
4553
- lowerer.noLowering("new URL with a runtime-valued base", expr, "a relative literal or statically resolvable template against import.meta.url compiles", symbol);
4554
- }
4555
- return {
4556
- kind: "libCall",
4557
- fn: "url.new",
4558
- args: [{ kind: "strLit", value: folded, type: STRING, loc }],
4559
- type: URL_T,
4560
- loc,
4561
- };
4562
- }
4563
- if (args.length !== 1) {
4564
- lowerer.noLowering(`new URL with ${args.length} argument${args.length === 1 ? "" : "s"}`, expr, "one absolute-URL string, or a static relative input against import.meta.url, is supported", symbol);
4565
- }
4566
- const input = lowerer.lowerExprExpecting(args[0], STRING);
4567
- return { kind: "libCall", fn: "url.new", args: [input], type: URL_T, loc };
5687
+ return lowerUrlNew(lowerer, expr);
4568
5688
  }
4569
5689
  // `new URLSearchParams(init?)`: the WHATWG list (stdlib provenance —
4570
5690
  // see lowerSearchParamsNew for the lowered init shapes).
@@ -4580,6 +5700,11 @@ export function lowerNew(lowerer, expr) {
4580
5700
  if (args.some(ts.isSpreadElement) || args.length > 1) {
4581
5701
  lowerer.noLowering(`new Date with ${args.length} arguments`, expr, "new Date(), new Date(milliseconds), and new Date(dateString) are supported; the local-time year/month field constructor has no lowering", symbol);
4582
5702
  }
5703
+ if (isJsSourceFile(expr.getSourceFile())) {
5704
+ return { kind: "libCall", fn: "date.nativeNew", args: [
5705
+ { kind: "dynArrLit", elems: args.map((arg) => lowerer.lowerExprExpecting(arg, DYN)), type: DYN, loc },
5706
+ ], type: DYN, loc };
5707
+ }
4583
5708
  if (args.length === 0) {
4584
5709
  return { kind: "libCall", fn: "date.newNow", args: [], type: DATE_T, loc };
4585
5710
  }
@@ -4620,14 +5745,8 @@ export function lowerNew(lowerer, expr) {
4620
5745
  loc,
4621
5746
  };
4622
5747
  }
4623
- // Encoder objects likewise never exist: lowerTextCodecCall claims
4624
- // composed calls before the receiver lowers, while the same-scope
4625
- // const store-then-call declaration is erased before reaching here.
4626
5748
  if (symbol && (symbol.name === "TextDecoder" || symbol.name === "TextEncoder") && lowerer.isStdlibSymbol(symbol)) {
4627
- lowerer.noLowering(`new ${symbol.name}`, expr, `${symbol.name} values have no representation — a same-scope const store-then-call or the composed form compiles: ` +
4628
- (symbol.name === "TextDecoder"
4629
- ? "new TextDecoder().decode(bytes)"
4630
- : "new TextEncoder().encode(s)"), symbol);
5749
+ return lowerTextCodecNew(lowerer, expr, symbol.name);
4631
5750
  }
4632
5751
  // `new Uint8Array(...)` / `new Uint32Array(...)` / `new
4633
5752
  // Float32Array(...)` / `new Float64Array(...)`: the typed-array
@@ -4646,7 +5765,7 @@ export function lowerNew(lowerer, expr) {
4646
5765
  // A rebindable decorated name constructs through its VALUE (the
4647
5766
  // classval-typed path below — newValue through the decoration
4648
5767
  // result's construct thunk), never the declaration directly.
4649
- if (info && info.classDecorators?.valueGlobalId === undefined) {
5768
+ if (info && !info.localClass && info.classDecorators?.valueGlobalId === undefined) {
4650
5769
  return lowerProgramClassNew(lowerer, expr, info, loc);
4651
5770
  }
4652
5771
  // `new Map<K, V>()`: the lib Map constructor. The SEEDED forms: an
@@ -4654,27 +5773,17 @@ export function lowerNew(lowerer, expr) {
4654
5773
  // (`new Map([[k, v], ...])`) — each pair's key/value lower as
4655
5774
  // ordinary K/V-typed expressions and the backend set()s them in
4656
5775
  // order, so the tuple array never exists as a value — and a
4657
- // `[K, V][]`-typed tuple-array VALUE (lowerMapSeedArrayNew: a
5776
+ // `[K, V][]`-typed tuple-array VALUE (lowerMapSeedNew: a
4658
5777
  // construct-and-set loop, pairs in array order, duplicates
4659
- // overwrite). Other seeds — another Map, general iterables — keep
4660
- // the fence: never silently an empty map. Unsupported key/value
5778
+ // overwrite). Matching Maps copy their entries; nullish seeds make
5779
+ // empty Maps. General iterable seeds retain a fence. Unsupported key/value
4661
5780
  // types get their half named specifically instead of the component
4662
5781
  // fence (SC2009, which names Map slots at value positions elsewhere).
4663
5782
  // Both Array() and new Array() share the elements/count lowering.
4664
- // `new Object()` — the spec's OrdinaryObjectCreate, exactly what the
4665
- // `{}` literal builds (fresh reference identity, no own properties) —
4666
- // lowers as the empty record. The ARGUMENT form is Object(x): it
4667
- // returns its argument for objects and BOXES primitives — the wrapper
4668
- // story with no lowering — so it keeps the constructor fence.
4669
- if (symbol?.name === "Object" &&
4670
- lowerer.isStdlibSymbol(symbol) &&
4671
- (expr.arguments ?? []).length === 0) {
4672
- return {
4673
- kind: "recordLit",
4674
- fields: [],
4675
- type: { kind: "record", shapeId: lowerer.shapes.intern([]) },
4676
- loc,
4677
- };
5783
+ if (symbol?.name === "Object" && lowerer.isStdlibSymbol(symbol)) {
5784
+ const object = lowerObjectConstructor(lowerer, expr.arguments ?? [], loc);
5785
+ if (object)
5786
+ return object;
4678
5787
  }
4679
5788
  if (symbol?.name === "Array" && lowerer.isStdlibSymbol(symbol)) {
4680
5789
  return lowerArrayConstructor(lowerer, expr, expr.arguments ?? []);
@@ -4688,16 +5797,29 @@ export function lowerNew(lowerer, expr) {
4688
5797
  : null;
4689
5798
  let tsType = lowerer.typeOf(expr);
4690
5799
  let mapped = lowerer.mapTypeOf(tsType);
5800
+ if (mapped === null && isJsSourceFile(expr.getSourceFile()))
5801
+ mapped = lowerer.irTypeOf(expr);
4691
5802
  const fieldType = assignedThisFieldType(lowerer, expr);
4692
5803
  if (mapped?.kind !== "map" && fieldType?.kind === "map")
4693
5804
  mapped = fieldType;
5805
+ // A fresh map built from pair literals can use its destination's
5806
+ // layout directly. Inference may otherwise split record values
5807
+ // into incompatible shapes (for example a nullable field), even
5808
+ // though every seed fits the declared value type. Existing map or
5809
+ // tuple-array values retain their own representation.
5810
+ let parent = expr.parent;
5811
+ while (ts.isParenthesizedExpression(parent))
5812
+ parent = parent.parent;
5813
+ // `satisfies` checks a view but retains the expression's own type.
5814
+ const contextualSeed = !ts.isSatisfiesExpression(parent) && (expr.typeArguments?.length ?? 0) === 0 &&
5815
+ (entriesLit !== null || (expr.arguments?.length ?? 0) === 0);
4694
5816
  // JavaScript's `new Map()` has no type-argument syntax: the no-arg
4695
5817
  // constructor overload pins Map<any, any> whatever the JSDoc says
4696
5818
  // (`@type` on the declaration types the VARIABLE, not this
4697
5819
  // expression). The CONTEXTUAL type carries the annotation — adopt
4698
5820
  // it when it is a supported map. TS type arguments keep winning:
4699
5821
  // their expression type already maps.
4700
- if (mapped?.kind !== "map") {
5822
+ if (mapped?.kind !== "map" || contextualSeed) {
4701
5823
  const ctx = lowerer.checker.getContextualType(expr);
4702
5824
  const ctxMapped = ctx ? lowerer.mapTypeOf(ctx) : null;
4703
5825
  if (ctx && ctxMapped?.kind === "map") {
@@ -4706,28 +5828,29 @@ export function lowerNew(lowerer, expr) {
4706
5828
  }
4707
5829
  }
4708
5830
  if (seedArg && !entriesLit && mapped?.kind === "map") {
4709
- const seeded = lowerMapSeedArrayNew(lowerer, seedArg, mapped);
5831
+ const seeded = lowerMapSeedNew(lowerer, seedArg, mapped);
4710
5832
  if (seeded)
4711
5833
  return seeded;
4712
5834
  }
4713
5835
  if ((expr.arguments?.length ?? 0) > 0 && !entriesLit) {
4714
5836
  lowerer.noLowering("new Map(entries)", expr, "supported seeds: an array literal of [key, value] pair literals, or a " +
4715
- "[K, V][]-typed tuple-array value — construct the Map empty and set() " +
4716
- "each entry otherwise");
5837
+ "[K, V][]-typed tuple-array value, a matching Map, or null/undefined");
4717
5838
  }
4718
5839
  if (mapped?.kind === "map") {
4719
5840
  if (!entriesLit)
4720
5841
  return { kind: "mapNew", type: mapped, loc };
4721
5842
  const seed = entriesLit.map((pair) => ({
4722
- key: lowerer.lowerExprExpecting(pair.elements[0], mapped.key),
4723
- value: lowerer.lowerExprExpecting(pair.elements[1], mapped.value),
5843
+ key: lowerer.lowerCollectionKey(pair.elements[0], mapped.key),
5844
+ value: mapped.value.kind === "dyn"
5845
+ ? lowerer.lowerCollectionKey(pair.elements[1], mapped.value)
5846
+ : lowerer.lowerExprExpecting(pair.elements[1], mapped.value),
4724
5847
  }));
4725
5848
  return { kind: "mapNew", seed, type: mapped, loc };
4726
5849
  }
4727
5850
  const targs = lowerer.checker.getTypeArguments(tsType);
4728
5851
  // JAVASCRIPT `new Map()` whose arguments never resolved past
4729
5852
  // Map<any, any> (no annotation, no contextual type, no seed): the
4730
- // WeakMap stance below — the VALUE lowers as an opaque dyn object
5853
+ // The VALUE lowers as an opaque dyn object
4731
5854
  // (identity and truthiness are real), and every reached METHOD use
4732
5855
  // meets its own per-site fence at runtime. The formatter's
4733
5856
  // config-cache shape: module init constructs the caches
@@ -4740,34 +5863,35 @@ export function lowerNew(lowerer, expr) {
4740
5863
  return { kind: "dynObjLit", type: DYN, loc };
4741
5864
  }
4742
5865
  const keyIr = targs[0] ? lowerer.mapTypeOf(targs[0]) : null;
4743
- if (targs[0] && (!keyIr || !isSupportedMapKey(keyIr))) {
5866
+ if (targs[0] && (!keyIr || !isSupportedMapKey(keyIr, keyIr.kind === "union" ? lowerer.unions.get(keyIr.unionId)?.arms : undefined))) {
4744
5867
  lowerer.unsupported("SC1090", expr, `Map keys of type '${lowerer.checker.typeToString(targs[0])}' ` +
4745
- `(Map keys must be string or number)`);
5868
+ `(Map keys must be numbers, strings, identity references, or unions of identity references)`);
4746
5869
  }
4747
5870
  if (targs[1]) {
4748
5871
  lowerer.unsupported("SC1090", expr, `Map values of type '${lowerer.checker.typeToString(targs[1])}' ` +
4749
5872
  `(Map values must be number, string, boolean, records, class instances, ` +
4750
- `arrays, promises, or unions of those — not functions, Maps, 'unknown', or 'any')`);
5873
+ `arrays, promises, Maps, Sets, or unions of those — not functions, 'unknown', or 'any')`);
4751
5874
  }
4752
5875
  lowerer.badType(expr, tsType);
4753
5876
  }
4754
- // `new Set<T>()`: Map's sibling. The SEEDED form lowers for arrays
4755
- // and fixed tuples of legal elements — literal or variable — as
4756
- // construct + bulk add (duplicates collapse, insertion order
4757
- // preserved, exactly JS). Other iterables keep the fence.
4758
- // Unsupported element types are named specifically.
4759
- // `new WeakMap()` / `new WeakSet()` in JAVASCRIPT sources: no weak
4760
- // container exists in the value model, but harness code constructs
4761
- // one unconditionally and touches it only on paths tests don't
4762
- // reach — the value lowers as an opaque dyn object (identity only;
4763
- // every reached METHOD use meets its own per-site fence → runtime
4764
- // fence). TypeScript keeps the compile fence.
4765
- if ((symbol?.name === "WeakMap" || symbol?.name === "WeakSet") &&
4766
- lowerer.isStdlibSymbol(symbol) &&
4767
- isJsSourceFile(expr.getSourceFile()) &&
4768
- (expr.arguments?.length ?? 0) === 0) {
4769
- return { kind: "dynObjLit", type: DYN, loc };
5877
+ // Weak containers share checked native key identities and lifetime hooks.
5878
+ if ((symbol?.name === "WeakMap" || symbol?.name === "WeakSet") && lowerer.isStdlibSymbol(symbol)) {
5879
+ const args = expr.arguments ?? [];
5880
+ if (args.length > 1 || args.some(ts.isSpreadElement)) {
5881
+ lowerer.unsupported("SC1090", expr, `${symbol.name} construction with surplus or spread arguments`);
5882
+ }
5883
+ if (lowerer.dynamic) {
5884
+ const ctor = { kind: "jsOp", op: "globalGet", name: symbol.name, args: [], type: JSVAL, loc };
5885
+ return { kind: "jsOp", op: "construct", args: [ctor, ...args.map((arg) => lowerer.jsvalIn(lowerer.lowerExpr(arg), arg))], type: JSVAL, loc };
5886
+ }
5887
+ return {
5888
+ kind: "libCall", fn: symbol.name === "WeakMap" ? "weakMap.new" : "weakSet.new",
5889
+ args: [args[0] ? lowerer.lowerExprExpecting(args[0], DYN) : dynUndefinedExpr(loc)],
5890
+ type: DYN, loc,
5891
+ };
4770
5892
  }
5893
+ // `new Set<T>()`: construct + bulk add from native arrays, tuples,
5894
+ // or strings. Duplicates collapse in insertion order.
4771
5895
  if (symbol?.name === "Set" && lowerer.isStdlibSymbol(symbol)) {
4772
5896
  const tsType = lowerer.typeOf(expr);
4773
5897
  let mapped = lowerer.mapTypeOf(tsType);
@@ -4775,55 +5899,13 @@ export function lowerNew(lowerer, expr) {
4775
5899
  if (mapped?.kind !== "set" && fieldType?.kind === "set")
4776
5900
  mapped = fieldType;
4777
5901
  if (mapped?.kind === "set" && (expr.arguments?.length ?? 0) === 1) {
4778
- const argNode = expr.arguments[0];
4779
- // An array LITERAL seed builds element-wise (its contextual type
4780
- // is the lib constructor's `readonly T[] | Iterable<T> | null`
4781
- // union — unmappable, so the generic literal path can't type it);
4782
- // an array-typed VALUE seed lowers as itself.
4783
- if (ts.isArrayLiteralExpression(argNode) && !argNode.elements.some(ts.isSpreadElement)) {
4784
- const elems = argNode.elements.map((el) => lowerer.lowerExprExpecting(el, mapped.elem));
4785
- const seed = { kind: "arrayLit", elems, type: arrayOf(mapped.elem), loc };
4786
- return { kind: "setNew", seed, type: mapped, loc };
4787
- }
4788
- if (!ts.isSpreadElement(argNode)) {
4789
- const argIr = lowerer.mapTypeOf(lowerer.typeOf(argNode));
4790
- if (argIr?.kind === "array" && typeEquals(argIr.elem, mapped.elem)) {
4791
- let seed = lowerer.lowerExpr(argNode);
4792
- // A T[]-DECLARED seed whose value is an island handle (a
4793
- // package's exported array — the binding never held a
4794
- // static array): the VALIDATED exit copies the engine
4795
- // array out (strict elements, the catchable TypeError on a
4796
- // lying handle), and the bulk add proceeds on the copy —
4797
- // construction reads the seed once, so the aliasing
4798
- // divergence has nothing to observe.
4799
- if (seed.type.kind === "jsval" && lowerer.boundaryExitSafe(arrayOf(mapped.elem))) {
4800
- seed = { kind: "jsExit", value: seed, type: arrayOf(mapped.elem), loc: seed.loc };
4801
- }
4802
- if (typeEquals(seed.type, arrayOf(mapped.elem))) {
4803
- return { kind: "setNew", seed, type: mapped, loc };
4804
- }
4805
- // Any other lowered kind falls through to the named fence
4806
- // below — never a mistyped seed into the validator.
4807
- }
4808
- // Fixed tuples use record storage, not T[] storage. Snapshot
4809
- // their legal elements into an array before bulk insertion;
4810
- // the helper takes the tuple as one argument, so an effectful
4811
- // seed expression is evaluated exactly once.
4812
- if (argIr?.kind === "record") {
4813
- const shape = lowerer.shapes.get(argIr.shapeId);
4814
- if (shape?.tuple && shape.fields.every((field) => typeEquals(field.type, mapped.elem))) {
4815
- const seedType = { kind: "array", elem: mapped.elem };
4816
- const helper = lowerer.tupleArrayWidthHelper(argIr.shapeId, seedType, loc);
4817
- if (helper) {
4818
- const tuple = lowerer.lowerExpr(argNode);
4819
- if (typeEquals(tuple.type, argIr)) {
4820
- const seed = { kind: "call", callee: helper, args: [tuple], type: seedType, loc };
4821
- return { kind: "setNew", seed, type: mapped, loc };
4822
- }
4823
- }
4824
- }
4825
- }
4826
- }
5902
+ const seeded = lowerSetSeedNew(lowerer, expr.arguments[0], mapped);
5903
+ if (seeded)
5904
+ return seeded;
5905
+ }
5906
+ if (!mapped && isJsSourceFile(expr.getSourceFile()) && (expr.arguments?.length ?? 0) <= 1 && !expr.arguments?.some(ts.isSpreadElement)) {
5907
+ return { kind: "libCall", fn: "dyn.nativeSetNew", args: [expr.arguments?.[0]
5908
+ ? lowerer.lowerExprExpecting(expr.arguments[0], DYN) : dynUndefinedExpr(loc)], type: DYN, loc };
4827
5909
  }
4828
5910
  // JavaScript's identity-Set idiom: `new Set([setTimeout, atob,
4829
5911
  // ...])` — the element TYPE (a union of stdlib signatures) has no
@@ -4847,15 +5929,15 @@ export function lowerNew(lowerer, expr) {
4847
5929
  }
4848
5930
  }
4849
5931
  if ((expr.arguments?.length ?? 0) > 0) {
4850
- lowerer.noLowering("new Set(values)", expr, "construct the Set empty and add() each value — only an array or fixed tuple of " +
4851
- "already-legal elements (string or number) seeds a Set");
5932
+ lowerer.noLowering("new Set(values)", expr, "construct the Set empty and add() each value — only nullish values or a matching Set, string, array, or fixed tuple of " +
5933
+ "already-legal elements (numbers, strings, or identity references) seeds a Set");
4852
5934
  }
4853
5935
  if (mapped?.kind === "set")
4854
5936
  return { kind: "setNew", type: mapped, loc };
4855
5937
  const targs = lowerer.checker.getTypeArguments(tsType);
4856
5938
  if (targs[0]) {
4857
5939
  lowerer.unsupported("SC1090", expr, `Set elements of type '${lowerer.checker.typeToString(targs[0])}' ` +
4858
- `(Set elements must be string or number — Map's key kinds — or a server handle, which stores under reference identity)`);
5940
+ `(Set elements must be numbers, strings, identity references, or unions of identity references)`);
4859
5941
  }
4860
5942
  lowerer.badType(expr, tsType);
4861
5943
  }
@@ -4961,16 +6043,14 @@ export function lowerNew(lowerer, expr) {
4961
6043
  String: "boxed wrapper objects have no lowering — use the string primitive (the box is only distinguishable via typeof/identity, which nothing here can honor)",
4962
6044
  Number: "boxed wrapper objects have no lowering — use the number primitive",
4963
6045
  Boolean: "boxed wrapper objects have no lowering — use the boolean primitive",
4964
- WeakMap: "weak collections observe garbage collection, which reference counting never exposes — a strong Map behaves identically in-language: use Map",
4965
- WeakSet: "weak collections observe garbage collection, which reference counting never exposes — a strong Set behaves identically in-language: use Set",
4966
6046
  WeakRef: "deref()-after-collect exposes GC timing — genuinely dynamic; hold a strong reference instead",
4967
6047
  FinalizationRegistry: "finalization callbacks expose GC timing — genuinely dynamic; release resources explicitly instead",
4968
6048
  SharedArrayBuffer: "no shared-memory threads exist in a compiled program — Uint8Array is the byte storage",
4969
- ArrayBuffer: "no free-standing ArrayBuffer value exists — typed arrays own their storage: allocate the view directly (new Uint8Array(n)), or erase a fresh buffer into one (new Uint8Array(new ArrayBuffer(n)), new DataView(new ArrayBuffer(n), ...))",
4970
- Proxy: "property-access metaprogramming has no static lowering (every property read must resolve at compile time)",
6049
+ ArrayBuffer: "native ArrayBuffer construction supports fixed-length storage; resizable buffers remain unsupported",
6050
+ Proxy: "native Proxy construction requires checked-native plain targets and handlers",
4971
6051
  Function: "runtime code generation cannot be compiled ahead of time (the eval stance) — write the function",
4972
6052
  };
4973
- lowerer.noLowering(`new ${expr.expression.text}`, expr, ctorHints[expr.expression.text], symbol);
6053
+ lowerer.noLowering(`new ${expr.expression.text}`, expr, ctorHints[ts.isIdentifier(expr.expression) ? expr.expression.text : expr.expression.name.text], symbol);
4974
6054
  }
4975
6055
  }
4976
6056
  // `new crypto.X509Certificate(data)` — the Dirent-style data record:
@@ -5055,7 +6135,7 @@ export function lowerNew(lowerer, expr) {
5055
6135
  // callee (unannotated heterogeneous registries) keeps a pointed
5056
6136
  // fence — annotate the slot with the common constructor type.
5057
6137
  {
5058
- const calleeT = lowerer.mapTypeOf(lowerer.typeOf(expr.expression));
6138
+ const calleeT = storedClassValueType(lowerer, expr.expression);
5059
6139
  if (calleeT?.kind === "classval") {
5060
6140
  let info = lowerer.classes.get(calleeT.className);
5061
6141
  if (!info && ts.isPropertyAccessExpression(expr.expression) && ts.isIdentifier(expr.expression.name)) {
@@ -5083,6 +6163,8 @@ export function lowerNew(lowerer, expr) {
5083
6163
  lowerer.unsupported("SC1090", expr, "constructing through a class value of an uninstantiated generic type (annotate the slot with a concrete instantiation — e.g. 'new (v: number) => Box<number>')");
5084
6164
  }
5085
6165
  const callee = lowerer.lowerExpr(expr.expression);
6166
+ if (callee.type.kind === "dyn")
6167
+ return checkedClassConstruction(lowerer, callee, (expr.arguments ?? []).map((arg) => lowerer.lowerExprExpecting(arg, DYN)), loc);
5086
6168
  if (callee.type.kind !== "classval")
5087
6169
  lowerer.badType(expr.expression, lowerer.typeOf(expr.expression));
5088
6170
  lowerer.noteEdge(`%${info.def.name}.constructor`);
@@ -5132,6 +6214,11 @@ export function lowerNew(lowerer, expr) {
5132
6214
  }
5133
6215
  }
5134
6216
  }
6217
+ // Checked construction supports emitted classes and builtin typed arrays.
6218
+ const callee = tryLowerExpression(lowerer, expr.expression);
6219
+ if (callee && (callee.type.kind === "dyn" || callee.type.kind === "func" && lowerer.dynConvertible(callee.type)) && !(expr.arguments ?? []).some(ts.isSpreadElement)) {
6220
+ return checkedClassConstruction(lowerer, lowerer.coerceToExpected(callee, DYN), (expr.arguments ?? []).map((arg) => lowerer.lowerExprExpecting(arg, DYN)), loc);
6221
+ }
5135
6222
  lowerer.unsupported("SC1090", expr, "constructing values other than classes declared in the program");
5136
6223
  }
5137
6224
  /** A getter/setter invocation over an accessor target's receiver — the