@geastack/compiler 1.0.15

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 (966) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +149 -0
  3. package/dist/cli-analyze.d.ts +1 -0
  4. package/dist/cli-analyze.js +61 -0
  5. package/dist/cli-coverage.d.ts +1 -0
  6. package/dist/cli-coverage.js +329 -0
  7. package/dist/cli-emit.d.ts +10 -0
  8. package/dist/cli-emit.js +398 -0
  9. package/dist/cli-module-graph.d.ts +18 -0
  10. package/dist/cli-module-graph.js +123 -0
  11. package/dist/cli-package-source.d.ts +5 -0
  12. package/dist/cli-package-source.js +116 -0
  13. package/dist/cli-project.d.ts +2 -0
  14. package/dist/cli-project.js +60 -0
  15. package/dist/cli.d.ts +2 -0
  16. package/dist/cli.js +199 -0
  17. package/dist/compiler.d.ts +228 -0
  18. package/dist/compiler.js +1029 -0
  19. package/dist/conversion/algebra.d.ts +218 -0
  20. package/dist/conversion/algebra.js +155 -0
  21. package/dist/conversion/build.d.ts +67 -0
  22. package/dist/conversion/build.js +1378 -0
  23. package/dist/conversion/derive.d.ts +37 -0
  24. package/dist/conversion/derive.js +260 -0
  25. package/dist/conversion/graph-validation.d.ts +8 -0
  26. package/dist/conversion/graph-validation.js +97 -0
  27. package/dist/conversion/native-callable-adapter.d.ts +13 -0
  28. package/dist/conversion/native-callable-adapter.js +53 -0
  29. package/dist/conversion/native-class-reference.d.ts +12 -0
  30. package/dist/conversion/native-class-reference.js +39 -0
  31. package/dist/conversion/native-payload-transport.d.ts +25 -0
  32. package/dist/conversion/native-payload-transport.js +33 -0
  33. package/dist/conversion/native-selection.d.ts +49 -0
  34. package/dist/conversion/native-selection.js +135 -0
  35. package/dist/conversion/native-sum.d.ts +42 -0
  36. package/dist/conversion/native-sum.js +115 -0
  37. package/dist/conversion/nodes.d.ts +55 -0
  38. package/dist/conversion/nodes.js +91 -0
  39. package/dist/conversion/operand-view.d.ts +14 -0
  40. package/dist/conversion/operand-view.js +20 -0
  41. package/dist/conversion/record-view.d.ts +157 -0
  42. package/dist/conversion/record-view.js +273 -0
  43. package/dist/conversion/registry.d.ts +217 -0
  44. package/dist/conversion/registry.js +1 -0
  45. package/dist/diagnostics/model.d.ts +76 -0
  46. package/dist/diagnostics/model.js +60 -0
  47. package/dist/diagnostics/sweep.d.ts +31 -0
  48. package/dist/diagnostics/sweep.js +112 -0
  49. package/dist/identity/ids.d.ts +179 -0
  50. package/dist/identity/ids.js +212 -0
  51. package/dist/ir/absent-class-arm.d.ts +48 -0
  52. package/dist/ir/absent-class-arm.js +157 -0
  53. package/dist/ir/borrow-effects.d.ts +23 -0
  54. package/dist/ir/borrow-effects.js +151 -0
  55. package/dist/ir/borrowed-call-arguments.d.ts +40 -0
  56. package/dist/ir/borrowed-call-arguments.js +117 -0
  57. package/dist/ir/build.d.ts +168 -0
  58. package/dist/ir/build.js +459 -0
  59. package/dist/ir/call-dispatch.d.ts +38 -0
  60. package/dist/ir/call-dispatch.js +502 -0
  61. package/dist/ir/call-entry.d.ts +142 -0
  62. package/dist/ir/call-entry.js +386 -0
  63. package/dist/ir/callable-class-flow.d.ts +27 -0
  64. package/dist/ir/callable-class-flow.js +1386 -0
  65. package/dist/ir/callable-field-slots.d.ts +22 -0
  66. package/dist/ir/callable-field-slots.js +166 -0
  67. package/dist/ir/callable-identity-demand.d.ts +52 -0
  68. package/dist/ir/callable-identity-demand.js +460 -0
  69. package/dist/ir/callable-member-candidates.d.ts +9 -0
  70. package/dist/ir/callable-member-candidates.js +39 -0
  71. package/dist/ir/callable-records.d.ts +21 -0
  72. package/dist/ir/callable-records.js +411 -0
  73. package/dist/ir/captures.d.ts +26 -0
  74. package/dist/ir/captures.js +335 -0
  75. package/dist/ir/certificate.d.ts +45 -0
  76. package/dist/ir/certificate.js +47 -0
  77. package/dist/ir/certify/carrier-keys.d.ts +73 -0
  78. package/dist/ir/certify/carrier-keys.js +221 -0
  79. package/dist/ir/certify/function-source.d.ts +4 -0
  80. package/dist/ir/certify/function-source.js +28 -0
  81. package/dist/ir/certify/has-property-key.d.ts +88 -0
  82. package/dist/ir/certify/has-property-key.js +116 -0
  83. package/dist/ir/certify/instanceof-key.d.ts +24 -0
  84. package/dist/ir/certify/instanceof-key.js +35 -0
  85. package/dist/ir/certify/property-access-keys.d.ts +172 -0
  86. package/dist/ir/certify/property-access-keys.js +291 -0
  87. package/dist/ir/certify/property-access.d.ts +3 -0
  88. package/dist/ir/certify/property-access.js +597 -0
  89. package/dist/ir/certify/runtime-helper.d.ts +3 -0
  90. package/dist/ir/certify/runtime-helper.js +326 -0
  91. package/dist/ir/certify/typeof-operand.d.ts +14 -0
  92. package/dist/ir/certify/typeof-operand.js +16 -0
  93. package/dist/ir/certify.d.ts +123 -0
  94. package/dist/ir/certify.js +481 -0
  95. package/dist/ir/class-evaluation.d.ts +26 -0
  96. package/dist/ir/class-evaluation.js +50 -0
  97. package/dist/ir/class-static-fields.d.ts +60 -0
  98. package/dist/ir/class-static-fields.js +108 -0
  99. package/dist/ir/construct-entry.d.ts +26 -0
  100. package/dist/ir/construct-entry.js +117 -0
  101. package/dist/ir/dead-values.d.ts +90 -0
  102. package/dist/ir/dead-values.js +184 -0
  103. package/dist/ir/deferral.d.ts +99 -0
  104. package/dist/ir/deferral.js +409 -0
  105. package/dist/ir/dense-loops.d.ts +230 -0
  106. package/dist/ir/dense-loops.js +697 -0
  107. package/dist/ir/dominance.d.ts +82 -0
  108. package/dist/ir/dominance.js +268 -0
  109. package/dist/ir/emission-representations.d.ts +71 -0
  110. package/dist/ir/emission-representations.js +350 -0
  111. package/dist/ir/facts.d.ts +218 -0
  112. package/dist/ir/facts.js +181 -0
  113. package/dist/ir/fixed-data-definition.d.ts +19 -0
  114. package/dist/ir/fixed-data-definition.js +49 -0
  115. package/dist/ir/generator-split.d.ts +38 -0
  116. package/dist/ir/generator-split.js +329 -0
  117. package/dist/ir/hoist.d.ts +55 -0
  118. package/dist/ir/hoist.js +375 -0
  119. package/dist/ir/instantiation.d.ts +61 -0
  120. package/dist/ir/instantiation.js +137 -0
  121. package/dist/ir/integer-storage.d.ts +170 -0
  122. package/dist/ir/integer-storage.js +822 -0
  123. package/dist/ir/integers.d.ts +161 -0
  124. package/dist/ir/integers.js +539 -0
  125. package/dist/ir/integrity-restrictions.d.ts +50 -0
  126. package/dist/ir/integrity-restrictions.js +118 -0
  127. package/dist/ir/local-iterators.d.ts +4 -0
  128. package/dist/ir/local-iterators.js +27 -0
  129. package/dist/ir/lower-allocation.d.ts +4 -0
  130. package/dist/ir/lower-allocation.js +325 -0
  131. package/dist/ir/lower-completion.d.ts +15 -0
  132. package/dist/ir/lower-completion.js +25 -0
  133. package/dist/ir/lower-destructuring.d.ts +5 -0
  134. package/dist/ir/lower-destructuring.js +693 -0
  135. package/dist/ir/lower-element.d.ts +29 -0
  136. package/dist/ir/lower-element.js +111 -0
  137. package/dist/ir/lower-exceptions.d.ts +47 -0
  138. package/dist/ir/lower-exceptions.js +92 -0
  139. package/dist/ir/lower-flow.d.ts +137 -0
  140. package/dist/ir/lower-flow.js +600 -0
  141. package/dist/ir/lower-graph.d.ts +218 -0
  142. package/dist/ir/lower-graph.js +687 -0
  143. package/dist/ir/lower-invocation.d.ts +4 -0
  144. package/dist/ir/lower-invocation.js +514 -0
  145. package/dist/ir/lower-narrow.d.ts +53 -0
  146. package/dist/ir/lower-narrow.js +320 -0
  147. package/dist/ir/lower-operands.d.ts +272 -0
  148. package/dist/ir/lower-operands.js +461 -0
  149. package/dist/ir/lower-property.d.ts +21 -0
  150. package/dist/ir/lower-property.js +132 -0
  151. package/dist/ir/lower-protocol.d.ts +11 -0
  152. package/dist/ir/lower-protocol.js +118 -0
  153. package/dist/ir/lower-short-circuit.d.ts +41 -0
  154. package/dist/ir/lower-short-circuit.js +63 -0
  155. package/dist/ir/lower.d.ts +82 -0
  156. package/dist/ir/lower.js +1346 -0
  157. package/dist/ir/model.d.ts +1474 -0
  158. package/dist/ir/model.js +6 -0
  159. package/dist/ir/native-absent-property.d.ts +3 -0
  160. package/dist/ir/native-absent-property.js +13 -0
  161. package/dist/ir/native-array-transport.d.ts +7 -0
  162. package/dist/ir/native-array-transport.js +46 -0
  163. package/dist/ir/native-callable-bind.d.ts +9 -0
  164. package/dist/ir/native-callable-bind.js +30 -0
  165. package/dist/ir/native-carrier-predicate.d.ts +34 -0
  166. package/dist/ir/native-carrier-predicate.js +49 -0
  167. package/dist/ir/native-class-accessor.d.ts +18 -0
  168. package/dist/ir/native-class-accessor.js +52 -0
  169. package/dist/ir/native-class-construction.d.ts +16 -0
  170. package/dist/ir/native-class-construction.js +71 -0
  171. package/dist/ir/native-class-initialization.d.ts +15 -0
  172. package/dist/ir/native-class-initialization.js +56 -0
  173. package/dist/ir/native-class-origins.d.ts +13 -0
  174. package/dist/ir/native-class-origins.js +237 -0
  175. package/dist/ir/native-dictionary-transport.d.ts +6 -0
  176. package/dist/ir/native-dictionary-transport.js +37 -0
  177. package/dist/ir/native-enumeration.d.ts +14 -0
  178. package/dist/ir/native-enumeration.js +26 -0
  179. package/dist/ir/native-equality.d.ts +10 -0
  180. package/dist/ir/native-equality.js +18 -0
  181. package/dist/ir/native-field-owner.d.ts +37 -0
  182. package/dist/ir/native-field-owner.js +183 -0
  183. package/dist/ir/native-fixed-layout.d.ts +41 -0
  184. package/dist/ir/native-fixed-layout.js +232 -0
  185. package/dist/ir/native-host-construction.d.ts +53 -0
  186. package/dist/ir/native-host-construction.js +62 -0
  187. package/dist/ir/native-key-query.d.ts +4 -0
  188. package/dist/ir/native-key-query.js +38 -0
  189. package/dist/ir/native-merge-transport.d.ts +25 -0
  190. package/dist/ir/native-merge-transport.js +71 -0
  191. package/dist/ir/native-record-index-transport.d.ts +11 -0
  192. package/dist/ir/native-record-index-transport.js +34 -0
  193. package/dist/ir/native-record-index.d.ts +12 -0
  194. package/dist/ir/native-record-index.js +27 -0
  195. package/dist/ir/native-reflect-field.d.ts +5 -0
  196. package/dist/ir/native-reflect-field.js +33 -0
  197. package/dist/ir/native-sequence-transport.d.ts +7 -0
  198. package/dist/ir/native-sequence-transport.js +53 -0
  199. package/dist/ir/numeric-intrinsics.d.ts +13 -0
  200. package/dist/ir/numeric-intrinsics.js +57 -0
  201. package/dist/ir/object-value-conversions.d.ts +20 -0
  202. package/dist/ir/object-value-conversions.js +50 -0
  203. package/dist/ir/physical-class-reflection.d.ts +9 -0
  204. package/dist/ir/physical-class-reflection.js +57 -0
  205. package/dist/ir/presence-proof.d.ts +42 -0
  206. package/dist/ir/presence-proof.js +490 -0
  207. package/dist/ir/program-facts.d.ts +106 -0
  208. package/dist/ir/program-facts.js +319 -0
  209. package/dist/ir/proven-branches.d.ts +16 -0
  210. package/dist/ir/proven-branches.js +219 -0
  211. package/dist/ir/queries.d.ts +41 -0
  212. package/dist/ir/queries.js +213 -0
  213. package/dist/ir/reflection-demand.d.ts +64 -0
  214. package/dist/ir/reflection-demand.js +1394 -0
  215. package/dist/ir/refusal.d.ts +43 -0
  216. package/dist/ir/refusal.js +28 -0
  217. package/dist/ir/shake.d.ts +37 -0
  218. package/dist/ir/shake.js +1078 -0
  219. package/dist/ir/static-callables.d.ts +11 -0
  220. package/dist/ir/static-callables.js +163 -0
  221. package/dist/ir/string-layout-reuse.d.ts +13 -0
  222. package/dist/ir/string-layout-reuse.js +39 -0
  223. package/dist/ir/string-length-reuse.d.ts +8 -0
  224. package/dist/ir/string-length-reuse.js +47 -0
  225. package/dist/ir/transfer.d.ts +78 -0
  226. package/dist/ir/transfer.js +270 -0
  227. package/dist/ir/type-query-results.d.ts +25 -0
  228. package/dist/ir/type-query-results.js +96 -0
  229. package/dist/ir/typed-property-access.d.ts +100 -0
  230. package/dist/ir/typed-property-access.js +161 -0
  231. package/dist/ir/verify.d.ts +19 -0
  232. package/dist/ir/verify.js +355 -0
  233. package/dist/plugins/apple/constructors.d.ts +112 -0
  234. package/dist/plugins/apple/constructors.js +217 -0
  235. package/dist/plugins/apple/host.d.ts +181 -0
  236. package/dist/plugins/apple/host.js +262 -0
  237. package/dist/plugins/apple/jsx.d.ts +2 -0
  238. package/dist/plugins/apple/jsx.js +293 -0
  239. package/dist/plugins/apple/members.d.ts +16 -0
  240. package/dist/plugins/apple/members.js +190 -0
  241. package/dist/plugins/apple/plugin.d.ts +2 -0
  242. package/dist/plugins/apple/plugin.js +156 -0
  243. package/dist/plugins/gea/component-classes.d.ts +25 -0
  244. package/dist/plugins/gea/component-classes.js +162 -0
  245. package/dist/plugins/gea/component-inline.d.ts +13 -0
  246. package/dist/plugins/gea/component-inline.js +532 -0
  247. package/dist/plugins/gea/constructors.d.ts +23 -0
  248. package/dist/plugins/gea/constructors.js +100 -0
  249. package/dist/plugins/gea/contract.d.ts +150 -0
  250. package/dist/plugins/gea/contract.js +195 -0
  251. package/dist/plugins/gea/element-ref.d.ts +31 -0
  252. package/dist/plugins/gea/element-ref.js +45 -0
  253. package/dist/plugins/gea/host.d.ts +520 -0
  254. package/dist/plugins/gea/host.js +762 -0
  255. package/dist/plugins/gea/lower.d.ts +6 -0
  256. package/dist/plugins/gea/lower.js +195 -0
  257. package/dist/plugins/gea/members.d.ts +22 -0
  258. package/dist/plugins/gea/members.js +221 -0
  259. package/dist/plugins/gea/plugin.d.ts +22 -0
  260. package/dist/plugins/gea/plugin.js +307 -0
  261. package/dist/plugins/gea/prelude.d.ts +78 -0
  262. package/dist/plugins/gea/prelude.js +153 -0
  263. package/dist/plugins/gea/producer.d.ts +5 -0
  264. package/dist/plugins/gea/producer.js +52 -0
  265. package/dist/plugins/gea/reactive-slots.d.ts +49 -0
  266. package/dist/plugins/gea/reactive-slots.js +578 -0
  267. package/dist/plugins/gea/render-bridge.d.ts +6 -0
  268. package/dist/plugins/gea/render-bridge.js +281 -0
  269. package/dist/plugins/gea/slots.d.ts +15 -0
  270. package/dist/plugins/gea/slots.js +36 -0
  271. package/dist/plugins/gea/template-analysis.d.ts +151 -0
  272. package/dist/plugins/gea/template-analysis.js +346 -0
  273. package/dist/plugins/gea/user-agent-styles.d.ts +9 -0
  274. package/dist/plugins/gea/user-agent-styles.js +94 -0
  275. package/dist/plugins/installed.d.ts +19 -0
  276. package/dist/plugins/installed.js +21 -0
  277. package/dist/plugins/load.d.ts +7 -0
  278. package/dist/plugins/load.js +207 -0
  279. package/dist/plugins/model.d.ts +735 -0
  280. package/dist/plugins/model.js +47 -0
  281. package/dist/plugins/webgl/host.d.ts +77 -0
  282. package/dist/plugins/webgl/host.js +162 -0
  283. package/dist/plugins/webgl/plugin.d.ts +40 -0
  284. package/dist/plugins/webgl/plugin.js +99 -0
  285. package/dist/preflight/obligations.d.ts +206 -0
  286. package/dist/preflight/obligations.js +36 -0
  287. package/dist/preflight/report.d.ts +20 -0
  288. package/dist/preflight/report.js +61 -0
  289. package/dist/preflight/run.d.ts +39 -0
  290. package/dist/preflight/run.js +403 -0
  291. package/dist/project-preparation.d.ts +33 -0
  292. package/dist/project-preparation.js +314 -0
  293. package/dist/projection/abi.d.ts +82 -0
  294. package/dist/projection/abi.js +349 -0
  295. package/dist/projection/apply-arguments.d.ts +12 -0
  296. package/dist/projection/apply-arguments.js +20 -0
  297. package/dist/projection/bindings.d.ts +250 -0
  298. package/dist/projection/bindings.js +340 -0
  299. package/dist/projection/callee.d.ts +196 -0
  300. package/dist/projection/callee.js +444 -0
  301. package/dist/projection/class-property-presence.d.ts +28 -0
  302. package/dist/projection/class-property-presence.js +58 -0
  303. package/dist/projection/class-prototype.d.ts +5 -0
  304. package/dist/projection/class-prototype.js +23 -0
  305. package/dist/projection/class-storage.d.ts +26 -0
  306. package/dist/projection/class-storage.js +236 -0
  307. package/dist/projection/classes.d.ts +283 -0
  308. package/dist/projection/classes.js +944 -0
  309. package/dist/projection/coercions.d.ts +20 -0
  310. package/dist/projection/coercions.js +33 -0
  311. package/dist/projection/dispatch.d.ts +167 -0
  312. package/dist/projection/dispatch.js +379 -0
  313. package/dist/projection/fields.d.ts +123 -0
  314. package/dist/projection/fields.js +383 -0
  315. package/dist/projection/instance-test.d.ts +78 -0
  316. package/dist/projection/instance-test.js +156 -0
  317. package/dist/projection/slots.d.ts +146 -0
  318. package/dist/projection/slots.js +663 -0
  319. package/dist/projection/synthesized-abi.d.ts +61 -0
  320. package/dist/projection/synthesized-abi.js +94 -0
  321. package/dist/representation/array-index.d.ts +14 -0
  322. package/dist/representation/array-index.js +17 -0
  323. package/dist/representation/callable-object.d.ts +3 -0
  324. package/dist/representation/callable-object.js +6 -0
  325. package/dist/representation/collections.d.ts +84 -0
  326. package/dist/representation/collections.js +139 -0
  327. package/dist/representation/derive.d.ts +159 -0
  328. package/dist/representation/derive.js +2546 -0
  329. package/dist/representation/difference.d.ts +30 -0
  330. package/dist/representation/difference.js +240 -0
  331. package/dist/representation/field-descriptor-policy.d.ts +19 -0
  332. package/dist/representation/field-descriptor-policy.js +39 -0
  333. package/dist/representation/function-constructor.d.ts +13 -0
  334. package/dist/representation/function-constructor.js +9 -0
  335. package/dist/representation/host-abi.d.ts +32 -0
  336. package/dist/representation/host-abi.js +97 -0
  337. package/dist/representation/host-templates.d.ts +67 -0
  338. package/dist/representation/host-templates.js +94 -0
  339. package/dist/representation/intersection.d.ts +84 -0
  340. package/dist/representation/intersection.js +149 -0
  341. package/dist/representation/literal-destination.d.ts +43 -0
  342. package/dist/representation/literal-destination.js +133 -0
  343. package/dist/representation/merge.d.ts +18 -0
  344. package/dist/representation/merge.js +83 -0
  345. package/dist/representation/model.d.ts +1160 -0
  346. package/dist/representation/model.js +1019 -0
  347. package/dist/representation/numeric-index.d.ts +13 -0
  348. package/dist/representation/numeric-index.js +29 -0
  349. package/dist/representation/object-shape.d.ts +109 -0
  350. package/dist/representation/object-shape.js +123 -0
  351. package/dist/representation/optional.d.ts +12 -0
  352. package/dist/representation/optional.js +87 -0
  353. package/dist/representation/plan.d.ts +60 -0
  354. package/dist/representation/plan.js +78 -0
  355. package/dist/representation/policies.d.ts +589 -0
  356. package/dist/representation/policies.js +107 -0
  357. package/dist/representation/primitive-domain.d.ts +1 -0
  358. package/dist/representation/primitive-domain.js +1 -0
  359. package/dist/representation/primitives.d.ts +44 -0
  360. package/dist/representation/primitives.js +78 -0
  361. package/dist/representation/publish.d.ts +49 -0
  362. package/dist/representation/publish.js +648 -0
  363. package/dist/representation/record-fields.d.ts +96 -0
  364. package/dist/representation/record-fields.js +116 -0
  365. package/dist/representation/template-object.d.ts +11 -0
  366. package/dist/representation/template-object.js +26 -0
  367. package/dist/representation/union.d.ts +30 -0
  368. package/dist/representation/union.js +324 -0
  369. package/dist/representation/value-records.d.ts +3 -0
  370. package/dist/representation/value-records.js +307 -0
  371. package/dist/representation/verify.d.ts +17 -0
  372. package/dist/representation/verify.js +221 -0
  373. package/dist/semantics/alias-this-field-declaration-transform.d.ts +4 -0
  374. package/dist/semantics/alias-this-field-declaration-transform.js +207 -0
  375. package/dist/semantics/ambient-type-realization-transform.d.ts +62 -0
  376. package/dist/semantics/ambient-type-realization-transform.js +168 -0
  377. package/dist/semantics/ambient.d.ts +24 -0
  378. package/dist/semantics/ambient.js +119 -0
  379. package/dist/semantics/borrowed-builtin-call-bind-source-transform.d.ts +4 -0
  380. package/dist/semantics/borrowed-builtin-call-bind-source-transform.js +341 -0
  381. package/dist/semantics/callable-origins.d.ts +46 -0
  382. package/dist/semantics/callable-origins.js +354 -0
  383. package/dist/semantics/class-alias.d.ts +7 -0
  384. package/dist/semantics/class-alias.js +37 -0
  385. package/dist/semantics/class-heritage.d.ts +34 -0
  386. package/dist/semantics/class-heritage.js +104 -0
  387. package/dist/semantics/commonjs-wrapper.d.ts +69 -0
  388. package/dist/semantics/commonjs-wrapper.js +231 -0
  389. package/dist/semantics/constructor-slot-subclasses.d.ts +28 -0
  390. package/dist/semantics/constructor-slot-subclasses.js +112 -0
  391. package/dist/semantics/declaration-overlay-transform.d.ts +35 -0
  392. package/dist/semantics/declaration-overlay-transform.js +2157 -0
  393. package/dist/semantics/define-property-source-transform.d.ts +4 -0
  394. package/dist/semantics/define-property-source-transform.js +437 -0
  395. package/dist/semantics/diagnostic-source-preparation.d.ts +24 -0
  396. package/dist/semantics/diagnostic-source-preparation.js +82 -0
  397. package/dist/semantics/documentation-ranges.d.ts +22 -0
  398. package/dist/semantics/documentation-ranges.js +36 -0
  399. package/dist/semantics/dynamic-fallback.d.ts +86 -0
  400. package/dist/semantics/dynamic-fallback.js +249 -0
  401. package/dist/semantics/frontend-timing.d.ts +6 -0
  402. package/dist/semantics/frontend-timing.js +35 -0
  403. package/dist/semantics/frontend.d.ts +504 -0
  404. package/dist/semantics/frontend.js +1157 -0
  405. package/dist/semantics/host-declaration-provenance.d.ts +11 -0
  406. package/dist/semantics/host-declaration-provenance.js +18 -0
  407. package/dist/semantics/host-methods.d.ts +24 -0
  408. package/dist/semantics/host-methods.js +74 -0
  409. package/dist/semantics/host-protocols.d.ts +429 -0
  410. package/dist/semantics/host-protocols.js +1501 -0
  411. package/dist/semantics/inherited-accessor.d.ts +7 -0
  412. package/dist/semantics/inherited-accessor.js +48 -0
  413. package/dist/semantics/interface-families.d.ts +70 -0
  414. package/dist/semantics/interface-families.js +180 -0
  415. package/dist/semantics/interface-implementors.d.ts +53 -0
  416. package/dist/semantics/interface-implementors.js +87 -0
  417. package/dist/semantics/jsdoc-namepath-transform.d.ts +4 -0
  418. package/dist/semantics/jsdoc-namepath-transform.js +85 -0
  419. package/dist/semantics/model/coverage.d.ts +68 -0
  420. package/dist/semantics/model/coverage.js +73 -0
  421. package/dist/semantics/model/edges.d.ts +103 -0
  422. package/dist/semantics/model/edges.js +20 -0
  423. package/dist/semantics/model/graph.d.ts +55 -0
  424. package/dist/semantics/model/graph.js +129 -0
  425. package/dist/semantics/model/operands.d.ts +159 -0
  426. package/dist/semantics/model/operands.js +26 -0
  427. package/dist/semantics/model/operations.d.ts +496 -0
  428. package/dist/semantics/model/operations.js +2 -0
  429. package/dist/semantics/model/primitive-domain.d.ts +26 -0
  430. package/dist/semantics/model/primitive-domain.js +38 -0
  431. package/dist/semantics/model/selected-signature.d.ts +261 -0
  432. package/dist/semantics/model/selected-signature.js +55 -0
  433. package/dist/semantics/model/structural-type-table.d.ts +93 -0
  434. package/dist/semantics/model/structural-type-table.js +237 -0
  435. package/dist/semantics/model/structural-types.d.ts +367 -0
  436. package/dist/semantics/model/structural-types.js +200 -0
  437. package/dist/semantics/module-resolution.d.ts +23 -0
  438. package/dist/semantics/module-resolution.js +227 -0
  439. package/dist/semantics/new-callee-class-tag-source-transform.d.ts +4 -0
  440. package/dist/semantics/new-callee-class-tag-source-transform.js +64 -0
  441. package/dist/semantics/node-project.d.ts +13 -0
  442. package/dist/semantics/node-project.js +107 -0
  443. package/dist/semantics/node-source-hooks.d.ts +1 -0
  444. package/dist/semantics/node-source-hooks.js +63 -0
  445. package/dist/semantics/normalize/absent-globals.d.ts +143 -0
  446. package/dist/semantics/normalize/absent-globals.js +191 -0
  447. package/dist/semantics/normalize/arguments-objects.d.ts +43 -0
  448. package/dist/semantics/normalize/arguments-objects.js +60 -0
  449. package/dist/semantics/normalize/asserted-arm-absence.d.ts +28 -0
  450. package/dist/semantics/normalize/asserted-arm-absence.js +61 -0
  451. package/dist/semantics/normalize/assignment-patterns.d.ts +70 -0
  452. package/dist/semantics/normalize/assignment-patterns.js +147 -0
  453. package/dist/semantics/normalize/bag-absence.d.ts +8 -0
  454. package/dist/semantics/normalize/bag-absence.js +42 -0
  455. package/dist/semantics/normalize/binding-fixpoint.d.ts +36 -0
  456. package/dist/semantics/normalize/binding-fixpoint.js +140 -0
  457. package/dist/semantics/normalize/callback-parameter-contracts.d.ts +16 -0
  458. package/dist/semantics/normalize/callback-parameter-contracts.js +91 -0
  459. package/dist/semantics/normalize/cells/agreement.d.ts +46 -0
  460. package/dist/semantics/normalize/cells/agreement.js +34 -0
  461. package/dist/semantics/normalize/cells/candidates.d.ts +17 -0
  462. package/dist/semantics/normalize/cells/candidates.js +35 -0
  463. package/dist/semantics/normalize/cells/facts.d.ts +19 -0
  464. package/dist/semantics/normalize/cells/facts.js +90 -0
  465. package/dist/semantics/normalize/cells/index.d.ts +10 -0
  466. package/dist/semantics/normalize/cells/index.js +6 -0
  467. package/dist/semantics/normalize/cells/model.d.ts +98 -0
  468. package/dist/semantics/normalize/cells/model.js +2 -0
  469. package/dist/semantics/normalize/cells/policies/bag.d.ts +44 -0
  470. package/dist/semantics/normalize/cells/policies/bag.js +114 -0
  471. package/dist/semantics/normalize/cells/policies/collection.d.ts +42 -0
  472. package/dist/semantics/normalize/cells/policies/collection.js +218 -0
  473. package/dist/semantics/normalize/cells/policies/field.d.ts +28 -0
  474. package/dist/semantics/normalize/cells/policies/field.js +40 -0
  475. package/dist/semantics/normalize/cells/policies/index.d.ts +49 -0
  476. package/dist/semantics/normalize/cells/policies/index.js +58 -0
  477. package/dist/semantics/normalize/cells/policies/local.d.ts +18 -0
  478. package/dist/semantics/normalize/cells/policies/local.js +37 -0
  479. package/dist/semantics/normalize/cells/policies/parameter.d.ts +28 -0
  480. package/dist/semantics/normalize/cells/policies/parameter.js +39 -0
  481. package/dist/semantics/normalize/cells/policies/return.d.ts +26 -0
  482. package/dist/semantics/normalize/cells/policies/return.js +45 -0
  483. package/dist/semantics/normalize/cells/policies/shared.d.ts +33 -0
  484. package/dist/semantics/normalize/cells/policies/shared.js +45 -0
  485. package/dist/semantics/normalize/cells/policy.d.ts +72 -0
  486. package/dist/semantics/normalize/cells/policy.js +18 -0
  487. package/dist/semantics/normalize/cells/registry.d.ts +14 -0
  488. package/dist/semantics/normalize/cells/registry.js +17 -0
  489. package/dist/semantics/normalize/census-refusal.d.ts +62 -0
  490. package/dist/semantics/normalize/census-refusal.js +27 -0
  491. package/dist/semantics/normalize/census.d.ts +109 -0
  492. package/dist/semantics/normalize/census.js +667 -0
  493. package/dist/semantics/normalize/collection-bindings.d.ts +278 -0
  494. package/dist/semantics/normalize/collection-bindings.js +677 -0
  495. package/dist/semantics/normalize/commonjs-module-record.d.ts +21 -0
  496. package/dist/semantics/normalize/commonjs-module-record.js +289 -0
  497. package/dist/semantics/normalize/commonjs-require.d.ts +13 -0
  498. package/dist/semantics/normalize/commonjs-require.js +1527 -0
  499. package/dist/semantics/normalize/contribution.d.ts +63 -0
  500. package/dist/semantics/normalize/contribution.js +172 -0
  501. package/dist/semantics/normalize/dead-typeof-guards.d.ts +64 -0
  502. package/dist/semantics/normalize/dead-typeof-guards.js +152 -0
  503. package/dist/semantics/normalize/deferred-intrinsic-protocols.d.ts +57 -0
  504. package/dist/semantics/normalize/deferred-intrinsic-protocols.js +109 -0
  505. package/dist/semantics/normalize/derived-expression-type.d.ts +1070 -0
  506. package/dist/semantics/normalize/derived-expression-type.js +3463 -0
  507. package/dist/semantics/normalize/evaluation-order.d.ts +16 -0
  508. package/dist/semantics/normalize/evaluation-order.js +37 -0
  509. package/dist/semantics/normalize/field-bindings.d.ts +167 -0
  510. package/dist/semantics/normalize/field-bindings.js +1125 -0
  511. package/dist/semantics/normalize/flow/array-element-continuation.d.ts +27 -0
  512. package/dist/semantics/normalize/flow/array-element-continuation.js +1452 -0
  513. package/dist/semantics/normalize/flow/callable-array-origins.d.ts +42 -0
  514. package/dist/semantics/normalize/flow/callable-array-origins.js +318 -0
  515. package/dist/semantics/normalize/flow/callable-completions.d.ts +45 -0
  516. package/dist/semantics/normalize/flow/callable-completions.js +82 -0
  517. package/dist/semantics/normalize/flow/callable-reach.d.ts +237 -0
  518. package/dist/semantics/normalize/flow/callable-reach.js +7174 -0
  519. package/dist/semantics/normalize/flow/class-family-member-read.d.ts +16 -0
  520. package/dist/semantics/normalize/flow/class-family-member-read.js +992 -0
  521. package/dist/semantics/normalize/flow/collection-value-continuation.d.ts +21 -0
  522. package/dist/semantics/normalize/flow/collection-value-continuation.js +192 -0
  523. package/dist/semantics/normalize/flow/component-solver.d.ts +199 -0
  524. package/dist/semantics/normalize/flow/component-solver.js +587 -0
  525. package/dist/semantics/normalize/flow/computed-key-set.d.ts +84 -0
  526. package/dist/semantics/normalize/flow/computed-key-set.js +660 -0
  527. package/dist/semantics/normalize/flow/export-importers.d.ts +24 -0
  528. package/dist/semantics/normalize/flow/export-importers.js +269 -0
  529. package/dist/semantics/normalize/flow/host-text-sink.d.ts +25 -0
  530. package/dist/semantics/normalize/flow/host-text-sink.js +87 -0
  531. package/dist/semantics/normalize/flow/intrinsic-array-callback-frames.d.ts +84 -0
  532. package/dist/semantics/normalize/flow/intrinsic-array-callback-frames.js +180 -0
  533. package/dist/semantics/normalize/flow/intrinsic-data-definition.d.ts +35 -0
  534. package/dist/semantics/normalize/flow/intrinsic-data-definition.js +140 -0
  535. package/dist/semantics/normalize/flow/invocation-facts.d.ts +98 -0
  536. package/dist/semantics/normalize/flow/invocation-facts.js +257 -0
  537. package/dist/semantics/normalize/flow/member-call-forwarding.d.ts +122 -0
  538. package/dist/semantics/normalize/flow/member-call-forwarding.js +835 -0
  539. package/dist/semantics/normalize/flow/model.d.ts +357 -0
  540. package/dist/semantics/normalize/flow/model.js +177 -0
  541. package/dist/semantics/normalize/flow/native-collection-protocol.d.ts +24 -0
  542. package/dist/semantics/normalize/flow/native-collection-protocol.js +252 -0
  543. package/dist/semantics/normalize/flow/node-path-token.d.ts +3 -0
  544. package/dist/semantics/normalize/flow/node-path-token.js +53 -0
  545. package/dist/semantics/normalize/flow/object-binding-continuation.d.ts +11 -0
  546. package/dist/semantics/normalize/flow/object-binding-continuation.js +42 -0
  547. package/dist/semantics/normalize/flow/origin-authority.d.ts +56 -0
  548. package/dist/semantics/normalize/flow/origin-authority.js +2 -0
  549. package/dist/semantics/normalize/flow/owned-class-receivers.d.ts +35 -0
  550. package/dist/semantics/normalize/flow/owned-class-receivers.js +191 -0
  551. package/dist/semantics/normalize/flow/parameter-values.d.ts +27 -0
  552. package/dist/semantics/normalize/flow/parameter-values.js +251 -0
  553. package/dist/semantics/normalize/flow/proof-hypotheses.d.ts +66 -0
  554. package/dist/semantics/normalize/flow/proof-hypotheses.js +162 -0
  555. package/dist/semantics/normalize/flow/record-alias-closure.d.ts +27 -0
  556. package/dist/semantics/normalize/flow/record-alias-closure.js +298 -0
  557. package/dist/semantics/normalize/flow/seeded-origins.d.ts +43 -0
  558. package/dist/semantics/normalize/flow/seeded-origins.js +54 -0
  559. package/dist/semantics/normalize/flow/source-class-data.d.ts +132 -0
  560. package/dist/semantics/normalize/flow/source-class-data.js +838 -0
  561. package/dist/semantics/normalize/flow/source-class-instanceof.d.ts +13 -0
  562. package/dist/semantics/normalize/flow/source-class-instanceof.js +37 -0
  563. package/dist/semantics/normalize/flow/source-class-static-data.d.ts +16 -0
  564. package/dist/semantics/normalize/flow/source-class-static-data.js +47 -0
  565. package/dist/semantics/normalize/flow/source-construction-frames.d.ts +12 -0
  566. package/dist/semantics/normalize/flow/source-construction-frames.js +118 -0
  567. package/dist/semantics/normalize/flow/source-invocation-frame-layout.d.ts +34 -0
  568. package/dist/semantics/normalize/flow/source-invocation-frame-layout.js +78 -0
  569. package/dist/semantics/normalize/flow/source-invocation-receiver.d.ts +37 -0
  570. package/dist/semantics/normalize/flow/source-invocation-receiver.js +95 -0
  571. package/dist/semantics/normalize/flow/source-prototype-method-identity.d.ts +23 -0
  572. package/dist/semantics/normalize/flow/source-prototype-method-identity.js +81 -0
  573. package/dist/semantics/normalize/flow/source-record-data.d.ts +29 -0
  574. package/dist/semantics/normalize/flow/source-record-data.js +626 -0
  575. package/dist/semantics/normalize/flow/source-value-session.d.ts +77 -0
  576. package/dist/semantics/normalize/flow/source-value-session.js +3089 -0
  577. package/dist/semantics/normalize/flow/targets.d.ts +118 -0
  578. package/dist/semantics/normalize/flow/targets.js +405 -0
  579. package/dist/semantics/normalize/flow/value-flow.d.ts +36 -0
  580. package/dist/semantics/normalize/flow/value-flow.js +823 -0
  581. package/dist/semantics/normalize/flow/value-provenance.d.ts +31 -0
  582. package/dist/semantics/normalize/flow/value-provenance.js +112 -0
  583. package/dist/semantics/normalize/gating.d.ts +51 -0
  584. package/dist/semantics/normalize/gating.js +560 -0
  585. package/dist/semantics/normalize/generic-function-choice.d.ts +31 -0
  586. package/dist/semantics/normalize/generic-function-choice.js +115 -0
  587. package/dist/semantics/normalize/global-host-mutations.d.ts +51 -0
  588. package/dist/semantics/normalize/global-host-mutations.js +5989 -0
  589. package/dist/semantics/normalize/host-effect-contracts.d.ts +77 -0
  590. package/dist/semantics/normalize/host-effect-contracts.js +143 -0
  591. package/dist/semantics/normalize/host-mutation-computed-keys.d.ts +38 -0
  592. package/dist/semantics/normalize/host-mutation-computed-keys.js +26 -0
  593. package/dist/semantics/normalize/host-mutation-key-reader.d.ts +66 -0
  594. package/dist/semantics/normalize/host-mutation-key-reader.js +192 -0
  595. package/dist/semantics/normalize/host-mutation-keys.d.ts +114 -0
  596. package/dist/semantics/normalize/host-mutation-keys.js +183 -0
  597. package/dist/semantics/normalize/identities.d.ts +172 -0
  598. package/dist/semantics/normalize/identities.js +426 -0
  599. package/dist/semantics/normalize/implicit-arguments-tuple.d.ts +97 -0
  600. package/dist/semantics/normalize/implicit-arguments-tuple.js +197 -0
  601. package/dist/semantics/normalize/implicit-arguments.d.ts +11 -0
  602. package/dist/semantics/normalize/implicit-arguments.js +39 -0
  603. package/dist/semantics/normalize/instantiation.d.ts +73 -0
  604. package/dist/semantics/normalize/instantiation.js +399 -0
  605. package/dist/semantics/normalize/intrinsic-property-call.d.ts +18 -0
  606. package/dist/semantics/normalize/intrinsic-property-call.js +69 -0
  607. package/dist/semantics/normalize/intrinsic-prototype.d.ts +41 -0
  608. package/dist/semantics/normalize/intrinsic-prototype.js +87 -0
  609. package/dist/semantics/normalize/intrinsic-static-member.d.ts +14 -0
  610. package/dist/semantics/normalize/intrinsic-static-member.js +23 -0
  611. package/dist/semantics/normalize/jsdoc-type-names.d.ts +32 -0
  612. package/dist/semantics/normalize/jsdoc-type-names.js +512 -0
  613. package/dist/semantics/normalize/keyof.d.ts +32 -0
  614. package/dist/semantics/normalize/keyof.js +110 -0
  615. package/dist/semantics/normalize/local-bindings.d.ts +176 -0
  616. package/dist/semantics/normalize/local-bindings.js +1826 -0
  617. package/dist/semantics/normalize/logical-result-type.d.ts +16 -0
  618. package/dist/semantics/normalize/logical-result-type.js +102 -0
  619. package/dist/semantics/normalize/namespace-paths.d.ts +57 -0
  620. package/dist/semantics/normalize/namespace-paths.js +108 -0
  621. package/dist/semantics/normalize/normalize.d.ts +57 -0
  622. package/dist/semantics/normalize/normalize.js +68 -0
  623. package/dist/semantics/normalize/object-bag-bindings.d.ts +305 -0
  624. package/dist/semantics/normalize/object-bag-bindings.js +1290 -0
  625. package/dist/semantics/normalize/omitted-stated-parameter.d.ts +53 -0
  626. package/dist/semantics/normalize/omitted-stated-parameter.js +59 -0
  627. package/dist/semantics/normalize/open-type-form.d.ts +10 -0
  628. package/dist/semantics/normalize/open-type-form.js +32 -0
  629. package/dist/semantics/normalize/parameter-bindings.d.ts +361 -0
  630. package/dist/semantics/normalize/parameter-bindings.js +3339 -0
  631. package/dist/semantics/normalize/parameter-slot.d.ts +264 -0
  632. package/dist/semantics/normalize/parameter-slot.js +491 -0
  633. package/dist/semantics/normalize/physical-overload-result.d.ts +77 -0
  634. package/dist/semantics/normalize/physical-overload-result.js +99 -0
  635. package/dist/semantics/normalize/primitive-property-absence.d.ts +12 -0
  636. package/dist/semantics/normalize/primitive-property-absence.js +60 -0
  637. package/dist/semantics/normalize/producer-context.d.ts +376 -0
  638. package/dist/semantics/normalize/producer-context.js +1 -0
  639. package/dist/semantics/normalize/producers/allocations.d.ts +3 -0
  640. package/dist/semantics/normalize/producers/allocations.js +863 -0
  641. package/dist/semantics/normalize/producers/binding-kind.d.ts +37 -0
  642. package/dist/semantics/normalize/producers/binding-kind.js +36 -0
  643. package/dist/semantics/normalize/producers/bindings.d.ts +85 -0
  644. package/dist/semantics/normalize/producers/bindings.js +710 -0
  645. package/dist/semantics/normalize/producers/boundary.d.ts +34 -0
  646. package/dist/semantics/normalize/producers/boundary.js +123 -0
  647. package/dist/semantics/normalize/producers/class-lifecycle.d.ts +3 -0
  648. package/dist/semantics/normalize/producers/class-lifecycle.js +902 -0
  649. package/dist/semantics/normalize/producers/computations.d.ts +3 -0
  650. package/dist/semantics/normalize/producers/computations.js +613 -0
  651. package/dist/semantics/normalize/producers/control-loops.d.ts +30 -0
  652. package/dist/semantics/normalize/producers/control-loops.js +91 -0
  653. package/dist/semantics/normalize/producers/control.d.ts +30 -0
  654. package/dist/semantics/normalize/producers/control.js +923 -0
  655. package/dist/semantics/normalize/producers/declaration-lifecycle.d.ts +3 -0
  656. package/dist/semantics/normalize/producers/declaration-lifecycle.js +390 -0
  657. package/dist/semantics/normalize/producers/destructuring.d.ts +45 -0
  658. package/dist/semantics/normalize/producers/destructuring.js +1180 -0
  659. package/dist/semantics/normalize/producers/dynamic-language.d.ts +3 -0
  660. package/dist/semantics/normalize/producers/dynamic-language.js +70 -0
  661. package/dist/semantics/normalize/producers/erasure.d.ts +51 -0
  662. package/dist/semantics/normalize/producers/erasure.js +90 -0
  663. package/dist/semantics/normalize/producers/installed.d.ts +3 -0
  664. package/dist/semantics/normalize/producers/installed.js +55 -0
  665. package/dist/semantics/normalize/producers/invocations.d.ts +35 -0
  666. package/dist/semantics/normalize/producers/invocations.js +1796 -0
  667. package/dist/semantics/normalize/producers/iteration-yield.d.ts +59 -0
  668. package/dist/semantics/normalize/producers/iteration-yield.js +235 -0
  669. package/dist/semantics/normalize/producers/jsx.d.ts +3 -0
  670. package/dist/semantics/normalize/producers/jsx.js +360 -0
  671. package/dist/semantics/normalize/producers/mint.d.ts +39 -0
  672. package/dist/semantics/normalize/producers/mint.js +44 -0
  673. package/dist/semantics/normalize/producers/nullish.d.ts +16 -0
  674. package/dist/semantics/normalize/producers/nullish.js +27 -0
  675. package/dist/semantics/normalize/producers/object-assignment.d.ts +8 -0
  676. package/dist/semantics/normalize/producers/object-assignment.js +204 -0
  677. package/dist/semantics/normalize/producers/object-tag.d.ts +9 -0
  678. package/dist/semantics/normalize/producers/object-tag.js +119 -0
  679. package/dist/semantics/normalize/producers/optional-chain.d.ts +44 -0
  680. package/dist/semantics/normalize/producers/optional-chain.js +75 -0
  681. package/dist/semantics/normalize/producers/properties.d.ts +21 -0
  682. package/dist/semantics/normalize/producers/properties.js +1053 -0
  683. package/dist/semantics/normalize/producers/protocol.d.ts +67 -0
  684. package/dist/semantics/normalize/producers/protocol.js +695 -0
  685. package/dist/semantics/normalize/producers/references.d.ts +53 -0
  686. package/dist/semantics/normalize/producers/references.js +1027 -0
  687. package/dist/semantics/normalize/producers/shared.d.ts +561 -0
  688. package/dist/semantics/normalize/producers/shared.js +1683 -0
  689. package/dist/semantics/normalize/producers/spread-arguments.d.ts +72 -0
  690. package/dist/semantics/normalize/producers/spread-arguments.js +375 -0
  691. package/dist/semantics/normalize/producers/tagged-template.d.ts +5 -0
  692. package/dist/semantics/normalize/producers/tagged-template.js +307 -0
  693. package/dist/semantics/normalize/producers/tuple-spread.d.ts +189 -0
  694. package/dist/semantics/normalize/producers/tuple-spread.js +279 -0
  695. package/dist/semantics/normalize/property-key-domain.d.ts +36 -0
  696. package/dist/semantics/normalize/property-key-domain.js +150 -0
  697. package/dist/semantics/normalize/reachability.d.ts +189 -0
  698. package/dist/semantics/normalize/reachability.js +1057 -0
  699. package/dist/semantics/normalize/reassigned-bindings.d.ts +13 -0
  700. package/dist/semantics/normalize/reassigned-bindings.js +41 -0
  701. package/dist/semantics/normalize/record-storage-families.d.ts +11 -0
  702. package/dist/semantics/normalize/record-storage-families.js +109 -0
  703. package/dist/semantics/normalize/return-bindings.d.ts +260 -0
  704. package/dist/semantics/normalize/return-bindings.js +1311 -0
  705. package/dist/semantics/normalize/return-paths.d.ts +2 -0
  706. package/dist/semantics/normalize/return-paths.js +28 -0
  707. package/dist/semantics/normalize/script-global-redefinition.d.ts +44 -0
  708. package/dist/semantics/normalize/script-global-redefinition.js +75 -0
  709. package/dist/semantics/normalize/specialization.d.ts +201 -0
  710. package/dist/semantics/normalize/specialization.js +1824 -0
  711. package/dist/semantics/normalize/structural-array-element.d.ts +176 -0
  712. package/dist/semantics/normalize/structural-array-element.js +700 -0
  713. package/dist/semantics/normalize/structural-array-read.d.ts +13 -0
  714. package/dist/semantics/normalize/structural-array-read.js +124 -0
  715. package/dist/semantics/normalize/structural-callable.d.ts +12 -0
  716. package/dist/semantics/normalize/structural-callable.js +82 -0
  717. package/dist/semantics/normalize/structural-creation-order.d.ts +32 -0
  718. package/dist/semantics/normalize/structural-creation-order.js +111 -0
  719. package/dist/semantics/normalize/structural-declarations.d.ts +395 -0
  720. package/dist/semantics/normalize/structural-declarations.js +968 -0
  721. package/dist/semantics/normalize/structural-declared-body.d.ts +25 -0
  722. package/dist/semantics/normalize/structural-declared-body.js +147 -0
  723. package/dist/semantics/normalize/structural-generics.d.ts +56 -0
  724. package/dist/semantics/normalize/structural-generics.js +120 -0
  725. package/dist/semantics/normalize/structural-indexed-access.d.ts +11 -0
  726. package/dist/semantics/normalize/structural-indexed-access.js +126 -0
  727. package/dist/semantics/normalize/structural-instantiated-member.d.ts +64 -0
  728. package/dist/semantics/normalize/structural-instantiated-member.js +407 -0
  729. package/dist/semantics/normalize/structural-joins.d.ts +44 -0
  730. package/dist/semantics/normalize/structural-joins.js +143 -0
  731. package/dist/semantics/normalize/structural-layout-relevance.d.ts +29 -0
  732. package/dist/semantics/normalize/structural-layout-relevance.js +391 -0
  733. package/dist/semantics/normalize/structural-layout-type.d.ts +11 -0
  734. package/dist/semantics/normalize/structural-layout-type.js +1468 -0
  735. package/dist/semantics/normalize/structural-leaves.d.ts +49 -0
  736. package/dist/semantics/normalize/structural-leaves.js +125 -0
  737. package/dist/semantics/normalize/structural-local-union.d.ts +13 -0
  738. package/dist/semantics/normalize/structural-local-union.js +133 -0
  739. package/dist/semantics/normalize/structural-members.d.ts +26 -0
  740. package/dist/semantics/normalize/structural-members.js +84 -0
  741. package/dist/semantics/normalize/structural-mutable-method.d.ts +15 -0
  742. package/dist/semantics/normalize/structural-mutable-method.js +109 -0
  743. package/dist/semantics/normalize/structural-parts.d.ts +131 -0
  744. package/dist/semantics/normalize/structural-parts.js +737 -0
  745. package/dist/semantics/normalize/structural-receiver.d.ts +66 -0
  746. package/dist/semantics/normalize/structural-receiver.js +551 -0
  747. package/dist/semantics/normalize/structural-rules.d.ts +112 -0
  748. package/dist/semantics/normalize/structural-rules.js +93 -0
  749. package/dist/semantics/normalize/structural-self-reference.d.ts +150 -0
  750. package/dist/semantics/normalize/structural-self-reference.js +494 -0
  751. package/dist/semantics/normalize/structural.d.ts +202 -0
  752. package/dist/semantics/normalize/structural.js +4218 -0
  753. package/dist/semantics/normalize/unreduced-type-form.d.ts +41 -0
  754. package/dist/semantics/normalize/unreduced-type-form.js +53 -0
  755. package/dist/semantics/normalize/unresolvable-names.d.ts +56 -0
  756. package/dist/semantics/normalize/unresolvable-names.js +140 -0
  757. package/dist/semantics/package-sources.d.ts +16 -0
  758. package/dist/semantics/package-sources.js +365 -0
  759. package/dist/semantics/program.d.ts +151 -0
  760. package/dist/semantics/program.js +667 -0
  761. package/dist/semantics/prototype-install-source-transform.d.ts +4 -0
  762. package/dist/semantics/prototype-install-source-transform.js +341 -0
  763. package/dist/semantics/prototype-object-class-source-transform.d.ts +4 -0
  764. package/dist/semantics/prototype-object-class-source-transform.js +525 -0
  765. package/dist/semantics/prototype-reparenting.d.ts +50 -0
  766. package/dist/semantics/prototype-reparenting.js +317 -0
  767. package/dist/semantics/stable-checker.d.ts +10 -0
  768. package/dist/semantics/stable-checker.js +148 -0
  769. package/dist/semantics/subclass-member-overlay-transform.d.ts +35 -0
  770. package/dist/semantics/subclass-member-overlay-transform.js +1418 -0
  771. package/dist/semantics/symbol-keyed-expando-source-transform.d.ts +4 -0
  772. package/dist/semantics/symbol-keyed-expando-source-transform.js +66 -0
  773. package/dist/semantics/this-constructor-source-transform.d.ts +4 -0
  774. package/dist/semantics/this-constructor-source-transform.js +122 -0
  775. package/dist/semantics/uninstantiable-classes.d.ts +22 -0
  776. package/dist/semantics/uninstantiable-classes.js +75 -0
  777. package/dist/targets/cpp/balanced-units.d.ts +3 -0
  778. package/dist/targets/cpp/balanced-units.js +58 -0
  779. package/dist/targets/cpp/borrowed-call-entry.d.ts +30 -0
  780. package/dist/targets/cpp/borrowed-call-entry.js +68 -0
  781. package/dist/targets/cpp/captures.d.ts +68 -0
  782. package/dist/targets/cpp/captures.js +269 -0
  783. package/dist/targets/cpp/class-layout.d.ts +313 -0
  784. package/dist/targets/cpp/class-layout.js +483 -0
  785. package/dist/targets/cpp/class-properties/computed-method-value.d.ts +25 -0
  786. package/dist/targets/cpp/class-properties/computed-method-value.js +22 -0
  787. package/dist/targets/cpp/class-properties/emit-class-properties.d.ts +216 -0
  788. package/dist/targets/cpp/class-properties/emit-class-properties.js +917 -0
  789. package/dist/targets/cpp/class-properties/native-prototype.d.ts +11 -0
  790. package/dist/targets/cpp/class-properties/native-prototype.js +101 -0
  791. package/dist/targets/cpp/class-ref-transport.d.ts +12 -0
  792. package/dist/targets/cpp/class-ref-transport.js +32 -0
  793. package/dist/targets/cpp/conversions.d.ts +3 -0
  794. package/dist/targets/cpp/conversions.js +2027 -0
  795. package/dist/targets/cpp/deferral-safety.d.ts +82 -0
  796. package/dist/targets/cpp/deferral-safety.js +86 -0
  797. package/dist/targets/cpp/direct-call-receivers.d.ts +37 -0
  798. package/dist/targets/cpp/direct-call-receivers.js +79 -0
  799. package/dist/targets/cpp/document.d.ts +74 -0
  800. package/dist/targets/cpp/document.js +106 -0
  801. package/dist/targets/cpp/emit-allocation.d.ts +60 -0
  802. package/dist/targets/cpp/emit-allocation.js +573 -0
  803. package/dist/targets/cpp/emit-arrays.d.ts +119 -0
  804. package/dist/targets/cpp/emit-arrays.js +1047 -0
  805. package/dist/targets/cpp/emit-binding-reference.d.ts +17 -0
  806. package/dist/targets/cpp/emit-binding-reference.js +120 -0
  807. package/dist/targets/cpp/emit-bindings.d.ts +158 -0
  808. package/dist/targets/cpp/emit-bindings.js +769 -0
  809. package/dist/targets/cpp/emit-buffers.d.ts +156 -0
  810. package/dist/targets/cpp/emit-buffers.js +573 -0
  811. package/dist/targets/cpp/emit-callable.d.ts +230 -0
  812. package/dist/targets/cpp/emit-callable.js +2154 -0
  813. package/dist/targets/cpp/emit-carrier-members.d.ts +406 -0
  814. package/dist/targets/cpp/emit-carrier-members.js +1224 -0
  815. package/dist/targets/cpp/emit-coercion.d.ts +26 -0
  816. package/dist/targets/cpp/emit-coercion.js +39 -0
  817. package/dist/targets/cpp/emit-context.d.ts +1882 -0
  818. package/dist/targets/cpp/emit-context.js +904 -0
  819. package/dist/targets/cpp/emit-dynamic-properties.d.ts +174 -0
  820. package/dist/targets/cpp/emit-dynamic-properties.js +1249 -0
  821. package/dist/targets/cpp/emit-equality.d.ts +39 -0
  822. package/dist/targets/cpp/emit-equality.js +472 -0
  823. package/dist/targets/cpp/emit-exceptions.d.ts +104 -0
  824. package/dist/targets/cpp/emit-exceptions.js +513 -0
  825. package/dist/targets/cpp/emit-field-owner.d.ts +4 -0
  826. package/dist/targets/cpp/emit-field-owner.js +27 -0
  827. package/dist/targets/cpp/emit-in.d.ts +31 -0
  828. package/dist/targets/cpp/emit-in.js +426 -0
  829. package/dist/targets/cpp/emit-instanceof.d.ts +19 -0
  830. package/dist/targets/cpp/emit-instanceof.js +601 -0
  831. package/dist/targets/cpp/emit-integers.d.ts +68 -0
  832. package/dist/targets/cpp/emit-integers.js +184 -0
  833. package/dist/targets/cpp/emit-iterator.d.ts +100 -0
  834. package/dist/targets/cpp/emit-iterator.js +1137 -0
  835. package/dist/targets/cpp/emit-json.d.ts +73 -0
  836. package/dist/targets/cpp/emit-json.js +823 -0
  837. package/dist/targets/cpp/emit-jsx.d.ts +74 -0
  838. package/dist/targets/cpp/emit-jsx.js +806 -0
  839. package/dist/targets/cpp/emit-mixed-binary.d.ts +51 -0
  840. package/dist/targets/cpp/emit-mixed-binary.js +60 -0
  841. package/dist/targets/cpp/emit-namespaces.d.ts +101 -0
  842. package/dist/targets/cpp/emit-namespaces.js +133 -0
  843. package/dist/targets/cpp/emit-narrowing.d.ts +738 -0
  844. package/dist/targets/cpp/emit-narrowing.js +3967 -0
  845. package/dist/targets/cpp/emit-native-equality.d.ts +3 -0
  846. package/dist/targets/cpp/emit-native-equality.js +14 -0
  847. package/dist/targets/cpp/emit-native-selection.d.ts +5 -0
  848. package/dist/targets/cpp/emit-native-selection.js +37 -0
  849. package/dist/targets/cpp/emit-object-tag.d.ts +4 -0
  850. package/dist/targets/cpp/emit-object-tag.js +108 -0
  851. package/dist/targets/cpp/emit-owned-record.d.ts +2 -0
  852. package/dist/targets/cpp/emit-owned-record.js +15 -0
  853. package/dist/targets/cpp/emit-presence.d.ts +78 -0
  854. package/dist/targets/cpp/emit-presence.js +376 -0
  855. package/dist/targets/cpp/emit-properties.d.ts +105 -0
  856. package/dist/targets/cpp/emit-properties.js +1640 -0
  857. package/dist/targets/cpp/emit-record-view.d.ts +20 -0
  858. package/dist/targets/cpp/emit-record-view.js +354 -0
  859. package/dist/targets/cpp/emit-return.d.ts +5 -0
  860. package/dist/targets/cpp/emit-return.js +237 -0
  861. package/dist/targets/cpp/emit-sum-widening.d.ts +10 -0
  862. package/dist/targets/cpp/emit-sum-widening.js +69 -0
  863. package/dist/targets/cpp/emit-tonumber.d.ts +38 -0
  864. package/dist/targets/cpp/emit-tonumber.js +177 -0
  865. package/dist/targets/cpp/emit-tostring.d.ts +92 -0
  866. package/dist/targets/cpp/emit-tostring.js +556 -0
  867. package/dist/targets/cpp/emit-typeof.d.ts +49 -0
  868. package/dist/targets/cpp/emit-typeof.js +317 -0
  869. package/dist/targets/cpp/emit-union-properties.d.ts +181 -0
  870. package/dist/targets/cpp/emit-union-properties.js +1281 -0
  871. package/dist/targets/cpp/emit.d.ts +45 -0
  872. package/dist/targets/cpp/emit.js +2225 -0
  873. package/dist/targets/cpp/error-types.d.ts +4 -0
  874. package/dist/targets/cpp/error-types.js +11 -0
  875. package/dist/targets/cpp/function-source-reads.d.ts +72 -0
  876. package/dist/targets/cpp/function-source-reads.js +148 -0
  877. package/dist/targets/cpp/host/atomics.d.ts +25 -0
  878. package/dist/targets/cpp/host/atomics.js +63 -0
  879. package/dist/targets/cpp/host/core-globals.d.ts +108 -0
  880. package/dist/targets/cpp/host/core-globals.js +158 -0
  881. package/dist/targets/cpp/host/dynamic-argument-members.d.ts +42 -0
  882. package/dist/targets/cpp/host/dynamic-argument-members.js +61 -0
  883. package/dist/targets/cpp/host/emit-host-arity.d.ts +139 -0
  884. package/dist/targets/cpp/host/emit-host-arity.js +232 -0
  885. package/dist/targets/cpp/host/emit-host-invoke.d.ts +91 -0
  886. package/dist/targets/cpp/host/emit-host-invoke.js +1105 -0
  887. package/dist/targets/cpp/host/emit-host-object.d.ts +55 -0
  888. package/dist/targets/cpp/host/emit-host-object.js +2206 -0
  889. package/dist/targets/cpp/host/emit-host-properties.d.ts +69 -0
  890. package/dist/targets/cpp/host/emit-host-properties.js +533 -0
  891. package/dist/targets/cpp/host/emit-host-reflect.d.ts +4 -0
  892. package/dist/targets/cpp/host/emit-host-reflect.js +180 -0
  893. package/dist/targets/cpp/host/emit-host-value.d.ts +120 -0
  894. package/dist/targets/cpp/host/emit-host-value.js +392 -0
  895. package/dist/targets/cpp/host/host-members.d.ts +505 -0
  896. package/dist/targets/cpp/host/host-members.js +819 -0
  897. package/dist/targets/cpp/host/host-method-aliases.d.ts +30 -0
  898. package/dist/targets/cpp/host/host-method-aliases.js +76 -0
  899. package/dist/targets/cpp/host/native-protocols.d.ts +47 -0
  900. package/dist/targets/cpp/host/native-protocols.js +183 -0
  901. package/dist/targets/cpp/host/object-protocol.d.ts +351 -0
  902. package/dist/targets/cpp/host/object-protocol.js +671 -0
  903. package/dist/targets/cpp/host-namespace-reads.d.ts +83 -0
  904. package/dist/targets/cpp/host-namespace-reads.js +113 -0
  905. package/dist/targets/cpp/manifest/capabilities.d.ts +39 -0
  906. package/dist/targets/cpp/manifest/capabilities.js +1484 -0
  907. package/dist/targets/cpp/manifest.d.ts +23 -0
  908. package/dist/targets/cpp/manifest.js +113 -0
  909. package/dist/targets/cpp/native-error-base.d.ts +38 -0
  910. package/dist/targets/cpp/native-error-base.js +74 -0
  911. package/dist/targets/cpp/native-narrowing-transport.d.ts +12 -0
  912. package/dist/targets/cpp/native-narrowing-transport.js +151 -0
  913. package/dist/targets/cpp/native-selection-helpers.d.ts +11 -0
  914. package/dist/targets/cpp/native-selection-helpers.js +46 -0
  915. package/dist/targets/cpp/native-symbol-keys.d.ts +8 -0
  916. package/dist/targets/cpp/native-symbol-keys.js +34 -0
  917. package/dist/targets/cpp/ownership.d.ts +43 -0
  918. package/dist/targets/cpp/ownership.js +38 -0
  919. package/dist/targets/cpp/owning-conversion-input.d.ts +14 -0
  920. package/dist/targets/cpp/owning-conversion-input.js +12 -0
  921. package/dist/targets/cpp/property-read-claims.d.ts +62 -0
  922. package/dist/targets/cpp/property-read-claims.js +23 -0
  923. package/dist/targets/cpp/property-store-claims.d.ts +62 -0
  924. package/dist/targets/cpp/property-store-claims.js +26 -0
  925. package/dist/targets/cpp/prototype/emit-prototype-array.d.ts +111 -0
  926. package/dist/targets/cpp/prototype/emit-prototype-array.js +602 -0
  927. package/dist/targets/cpp/prototype/emit-prototype-date.d.ts +133 -0
  928. package/dist/targets/cpp/prototype/emit-prototype-date.js +515 -0
  929. package/dist/targets/cpp/prototype/emit-prototype-error.d.ts +13 -0
  930. package/dist/targets/cpp/prototype/emit-prototype-error.js +54 -0
  931. package/dist/targets/cpp/prototype/emit-prototype-invoke.d.ts +34 -0
  932. package/dist/targets/cpp/prototype/emit-prototype-invoke.js +1003 -0
  933. package/dist/targets/cpp/prototype/emit-prototype-iterator.d.ts +47 -0
  934. package/dist/targets/cpp/prototype/emit-prototype-iterator.js +250 -0
  935. package/dist/targets/cpp/prototype/emit-prototype-promise.d.ts +46 -0
  936. package/dist/targets/cpp/prototype/emit-prototype-promise.js +143 -0
  937. package/dist/targets/cpp/prototype/emit-prototype-regexp.d.ts +335 -0
  938. package/dist/targets/cpp/prototype/emit-prototype-regexp.js +853 -0
  939. package/dist/targets/cpp/prototype/emit-prototype-string.d.ts +42 -0
  940. package/dist/targets/cpp/prototype/emit-prototype-string.js +252 -0
  941. package/dist/targets/cpp/prototype/prototype-method-reads.d.ts +25 -0
  942. package/dist/targets/cpp/prototype/prototype-method-reads.js +182 -0
  943. package/dist/targets/cpp/reactive-dependencies.d.ts +140 -0
  944. package/dist/targets/cpp/reactive-dependencies.js +432 -0
  945. package/dist/targets/cpp/reactive-origins.d.ts +44 -0
  946. package/dist/targets/cpp/reactive-origins.js +82 -0
  947. package/dist/targets/cpp/records.d.ts +277 -0
  948. package/dist/targets/cpp/records.js +2427 -0
  949. package/dist/targets/cpp/recursive-containers.d.ts +43 -0
  950. package/dist/targets/cpp/recursive-containers.js +144 -0
  951. package/dist/targets/cpp/regexp-types.d.ts +56 -0
  952. package/dist/targets/cpp/regexp-types.js +59 -0
  953. package/dist/targets/cpp/substrate.d.ts +125 -0
  954. package/dist/targets/cpp/substrate.js +12 -0
  955. package/dist/targets/cpp/translation-unit.d.ts +219 -0
  956. package/dist/targets/cpp/translation-unit.js +2063 -0
  957. package/dist/targets/cpp/types.d.ts +280 -0
  958. package/dist/targets/cpp/types.js +1135 -0
  959. package/dist/targets/cpp/virtual-methods.d.ts +95 -0
  960. package/dist/targets/cpp/virtual-methods.js +264 -0
  961. package/package.json +95 -0
  962. package/src/targets/cpp/runtime/gea_dynamic_proxy.h +824 -0
  963. package/src/targets/cpp/runtime/gea_eval.h +1376 -0
  964. package/src/targets/cpp/runtime/gea_native_class_prototype.h +44 -0
  965. package/src/targets/cpp/runtime/gea_runtime.h +29222 -0
  966. package/src/targets/cpp/runtime/gea_runtime_builtins.cpp +55 -0
@@ -0,0 +1,4218 @@
1
+ import ts from 'typescript';
2
+ import { prepareStructuralRules, structuralDisagreementsEnabled } from './structural-rules.js';
3
+ import { recordStorageFamilies } from './record-storage-families.js';
4
+ import { emptyDeclaredMemberCensus } from './structural-declarations.js';
5
+ import { createLocalUnionResolver } from './structural-local-union.js';
6
+ import { createMutableMethodResolver } from './structural-mutable-method.js';
7
+ import { structuralArrayReadAt } from './structural-array-read.js';
8
+ import { enclosingArgumentsFunction, implicitArgumentsSlotOf, isArgumentsObjectIdentifier } from './implicit-arguments.js';
9
+ import { createStructuralCallResultResolver, createStructuralConstructResultResolver } from './structural-callable.js';
10
+ import { genericFunctionChoiceMembersOf, genericSourceFunctionDeclarationOf } from './generic-function-choice.js';
11
+ import { accessorSignatureOf, constructorImplementationSignatureOf, implementationSignatureOf, modifierOnlyMappedSourceOf, optionalMethodSignatureOf, declaredValueTypeOf, physicalInitializerTypeOf, physicalOverloadTypeAt, physicalStringObjectTypeAt } from './structural-declarations.js';
12
+ import { createKeyofResolver } from './keyof.js';
13
+ import { constructorInstalledMemberDeclarationsOf } from './flow/source-class-data.js';
14
+ import { arityAdmittedSignature, arrayPredicateNarrowedElementTypeOf, impliedPatternTargetOf, isGlobalObjectInterface, isStandardInterfaceType, isUnusableEvidence, widestOf } from './derived-expression-type.js';
15
+ import { createLeafKeying, literalFor, primitiveFor, symbolKeyDeclarationOf } from './structural-leaves.js';
16
+ import { unwrapErasedExpression } from './producers/erasure.js';
17
+ import { createStructuralParts, selfReferentialCallableShapeOf } from './structural-parts.js';
18
+ import { bodyReadsThis, createReceiverResolver } from './structural-receiver.js';
19
+ import { createMemberRules } from './structural-members.js';
20
+ import { emptyAbsentGlobalCensus } from './absent-globals.js';
21
+ import { createLayoutTypeResolver } from './structural-layout-type.js';
22
+ import { emptyParameterBindingCensus } from './parameter-bindings.js';
23
+ import { emptyCollectionBindingCensus } from './collection-bindings.js';
24
+ import { bagShapeOfType, bagShapeTypeAt, emptyObjectBagCensus } from './object-bag-bindings.js';
25
+ import { indexedAccessMemberTypes } from './structural-indexed-access.js';
26
+ import { joinedCallableOf, joinedIndexUnionOf } from './structural-joins.js';
27
+ import { creationOrderedProperties } from './structural-creation-order.js';
28
+ import { collectionMemberResultTypeAt, contextualArrayConstructTypeAt, inferredArrayElementAt, statedCollectionTypeAt, inferredCollectionTypeArgumentsAt, unstatedNeverArray } from './structural-array-element.js';
29
+ import { createDeclaredBodyResolver } from './structural-declared-body.js';
30
+ import { emptyInstantiationCensus } from './instantiation.js';
31
+ import { emptySpecializationCensus } from './specialization.js';
32
+ import { createTypeParameterSubstitution } from './structural-generics.js';
33
+ import { layoutRelevantParameterIndices } from './structural-layout-relevance.js';
34
+ import { rootSpecialization } from './identities.js';
35
+ import { emptyInterfaceFamilyCensus } from '../interface-families.js';
36
+ import { createInstantiatedMembers } from './structural-instantiated-member.js';
37
+ import { createAliasRecurrence, isSelfReferentialSignal, createViewIndependentRecurrence, selfReferentialKeyOf, selfReferentialShapeOf, selfReferentialSignal } from './structural-self-reference.js';
38
+ import { restParameterArrayElementAt, restParameterUnionOfTuplesElementAt, censusRestElementAt, impliedPatternArrayElementAt } from './parameter-slot.js';
39
+ import { physicalGeneratorOverloadResultAt } from './physical-overload-result.js';
40
+ import { arrayAssignmentPatternSourceExpression, arrayAssignmentTargetOf } from './assignment-patterns.js';
41
+ import { emptyCommonJsModuleRecordCensus } from './commonjs-module-record.js';
42
+ /**
43
+ * The TYPE PARAMETER a reference actually holds, where the checker answered
44
+ * with its base constraint instead.
45
+ *
46
+ * `getTypeAtLocation` on a reference to a `T`-typed binding does not answer
47
+ * `T`. TypeScript computes an APPARENT type for the reference so member
48
+ * lookups and narrowing have a concrete shape to work against, and for an
49
+ * unnarrowed generic that apparent type is the parameter's base constraint --
50
+ * `object` inside hono's `json = <T extends JSONValue | {} | InvalidJSONValue>
51
+ * (object: T) => ... JSON.stringify(object)` reads back as the whole
52
+ * constraint union.
53
+ *
54
+ * That is an ERASURE of the monomorphization, and it disagrees with the cell:
55
+ * the parameter's own declaration is typed `T`, which this copy substitutes to
56
+ * what the call bound, so the binding held `{ hello: string }` while every
57
+ * read of it published the constraint. A `binding-read-conversion` from a
58
+ * record to a ten-armed union is not a conversion any backend should install
59
+ * -- the two carriers describe one value, and only one of them is the value's
60
+ * type.
61
+ *
62
+ * Answered only when the checker's type IS the constraint, object-identical.
63
+ * A reference the flow analysis genuinely narrowed (`typeof object ===
64
+ * 'string'`) reaches a different type, and that narrowing is real.
65
+ */
66
+ const constraintErasedParameterAt = (checker, node) => {
67
+ if (!ts.isIdentifier(node))
68
+ return null;
69
+ const declaration = checker.getSymbolAtLocation(node)?.valueDeclaration;
70
+ if (!declaration)
71
+ return null;
72
+ if (!ts.isParameter(declaration) && !ts.isVariableDeclaration(declaration))
73
+ return null;
74
+ if (declaration.name === node)
75
+ return null;
76
+ const declared = checker.getTypeAtLocation(declaration);
77
+ if ((declared.flags & ts.TypeFlags.TypeParameter) === 0)
78
+ return null;
79
+ return checker.getBaseConstraintOfType(declared) === checker.getTypeAtLocation(node) ? declared : null;
80
+ };
81
+ export const createStructuralMapper = (checker, identities, table, instantiations = emptyInstantiationCensus, specializations = emptySpecializationCensus, parameters = emptyParameterBindingCensus, absent = emptyAbsentGlobalCensus, collections = emptyCollectionBindingCensus, bags = emptyObjectBagCensus, flow, families = emptyInterfaceFamilyCensus, moduleRecords = emptyCommonJsModuleRecordCensus, declaredMembers = emptyDeclaredMemberCensus, isIntrinsicDescriptorCall = () => false) => {
82
+ const storageTypeOf = recordStorageFamilies(checker, flow, parameters);
83
+ // One disagreement list for the WHOLE mapper, for the same reason the caches
84
+ // below are shared: two rules answering for one node is a fact about the rule
85
+ // set, and a per-view list would report it once per copy that asked.
86
+ const disagreements = [];
87
+ // One recurrence stack for the WHOLE mapper: the unfolding it folds crosses specialization views.
88
+ const aliasRecurrence = createAliasRecurrence(checker);
89
+ // One table cache for the WHOLE mapper, for the same reason: a copy's member
90
+ // types are a property of the copy, and every view that passes through it
91
+ // asks the same question.
92
+ const instantiatedMembersFor = createInstantiatedMembers(checker, specializations);
93
+ // And one recurrence key for every view-independent cycle, for the same reason.
94
+ const viewIndependentKeyOf = createViewIndependentRecurrence(checker);
95
+ // The ids those cycles settled on, for every view: a view that enters the
96
+ // same cycle at another member (`State` where the first entered at
97
+ // `State[]`) closes it through these instead of interning a second copy.
98
+ const sharedCompleted = new Map();
99
+ // Every generic class's copies, for every view: a class's copies are the
100
+ // program's, not a view's, and their fillings are closed types, so both
101
+ // answers are the same from every view. `classCopyKeys` is what
102
+ // `classCopies` publishes to the deriver.
103
+ const classCopyKeys = new Map();
104
+ const views = new Map();
105
+ const mapperFor = (path, bindingPath = path) => {
106
+ // Keyed by the copy, owner included, never by the ordinals alone: `copyKeyOf` (identities.ts) says why.
107
+ // Both paths are in the key: two views differing only in what they BIND
108
+ // are two different answers, and sharing one memo hands the second
109
+ // whichever the first settled.
110
+ const key = `${identities.copyKeyOf(path)}|${identities.copyKeyOf(bindingPath)}`;
111
+ const cached = views.get(key);
112
+ if (cached)
113
+ return cached;
114
+ const built = buildMapper(checker, identities.forSpecialization(path), table, instantiations, specializations, path, bindingPath, mapperFor, parameters, absent, collections, bags, flow, storageTypeOf, families, moduleRecords, declaredMembers, isIntrinsicDescriptorCall, aliasRecurrence, instantiatedMembersFor(bindingPath), viewIndependentKeyOf, sharedCompleted, classCopyKeys, disagreements);
115
+ views.set(key, built);
116
+ return built;
117
+ };
118
+ return mapperFor(rootSpecialization);
119
+ };
120
+ const buildMapper = (checker, identities, table, instantiations, specializations, path, bindingPath, mapperFor, parameters, absent, collections, bags, flow, storageTypeOf, families, moduleRecords, declaredMembers, isIntrinsicDescriptorCall, aliasRecurrence, instantiatedMembers, viewIndependentKeyOf, sharedCompleted, classCopyKeys, disagreements) => {
121
+ const { boundByPath, bindingOf: censusBindingOf, substituteTypeParameter } = createTypeParameterSubstitution(identities, instantiations, specializations, bindingPath);
122
+ // A type under translation must resolve to its anchor rather than recursing:
123
+ // `interface Node { next: Node }` would otherwise never terminate.
124
+ const inProgress = new Map();
125
+ const completed = new Map();
126
+ /** Self-reference with no declared name to anchor on -- a recursive type alias. See `structural-self-reference.ts`. */
127
+ const walking = new Set();
128
+ const selfReferential = new Set();
129
+ /**
130
+ * Every memo an in-flight attempt has written, so an unwind can take them
131
+ * back. A stale citation, not a missing one: an unwound frame's memos are
132
+ * keyed by checker type and survive, and the shapes behind them were interned
133
+ * with the ABANDONED anchor inside -- so the retry's correct answer sits in
134
+ * the table unused while the first attempt's conclusion outranks it. lib.dom's
135
+ * `window` is the standing case (`Window & typeof globalThis`, `Window`
136
+ * abandoned partway through): mentioning it at all selected a carrier
137
+ * containing `unresolved(...)`. `null` when nothing is in flight.
138
+ */
139
+ let journal = null;
140
+ const selfReferentialKeys = new Map();
141
+ const unresolved = (reason, fallback) => table.intern({ kind: 'unresolved', reason, ...(fallback ? { fallback } : {}) });
142
+ const { keyOfSymbol } = createLeafKeying(identities, checker);
143
+ const { implicitReceiverOf, declaredMemberSignatureOf } = createReceiverResolver(checker, (node) => layoutTypeAt(node), declaredMembers);
144
+ /**
145
+ * The object half of a `T[K]`, resolved the way this copy resolves a bare `T`.
146
+ *
147
+ * The `TypeParameter` branch of `translate` answers a parameter in three
148
+ * steps -- what this copy binds, what the program-wide census binds, and the
149
+ * author's own DEFAULT -- and only the first of those reached here, so a
150
+ * parameter answered by either of the other two carried a `T[K]` that had
151
+ * nothing left to refuse with. hono's `class Hono<E extends Env = Env, ...>`
152
+ * is the case: nothing writes `Hono<Something>`, so every `E['Bindings']` in
153
+ * `hono-base.ts` and `context.ts` -- 96 obligations, the file's largest
154
+ * single cluster -- asked about a parameter whose answer is its default,
155
+ * `Env`, and got the refusal instead.
156
+ *
157
+ * The default is the language's own substitution, not a guess: a reference
158
+ * that omits the argument IS the default, and the checker has already typed
159
+ * every such reference that way. Answering `T[K]` with anything else would
160
+ * put this layer and the checker into disagreement about one expression.
161
+ *
162
+ * A fourth step is NOT here but at the access itself
163
+ * (`memberTypesThroughBound`): the declared upper bound. It belongs there
164
+ * rather than here because the same rule answers a case this function's
165
+ * shape cannot see -- an object type that is not a parameter at all.
166
+ */
167
+ const resolvedObjectType = (objectType) => {
168
+ const substituted = substituteTypeParameter(objectType);
169
+ if (substituted !== objectType)
170
+ return substituted;
171
+ if ((objectType.flags & ts.TypeFlags.TypeParameter) === 0)
172
+ return objectType;
173
+ const symbol = objectType.getSymbol();
174
+ const declaration = symbol ? identities.declarationOfSymbol(symbol) : null;
175
+ if (!declaration || !ts.isTypeParameterDeclaration(declaration) || !declaration.default)
176
+ return objectType;
177
+ // The instantiated default where the checker has one -- see the type-parameter
178
+ // branch of `translate` below for why the declaration node alone is wrong.
179
+ return checker.getDefaultFromTypeParameter(objectType) ?? checker.getTypeFromTypeNode(declaration.default);
180
+ };
181
+ /**
182
+ * `T & {}` with `T := A | B | undefined` is `(A & {}) | (B & {}) |
183
+ * (undefined & {})`, which is `A | B`.
184
+ *
185
+ * TypeScript distributes an intersection over its union members when it
186
+ * BUILDS one (`getIntersectionType`), so the checker never hands this
187
+ * mapper an intersection with a union member of its own -- until a copy
188
+ * substitutes a union for the type parameter the checker left in place.
189
+ * tsc's `assertIsDefined<T>(value: T)` and `cast<TOut extends TIn, TIn>`
190
+ * narrow `value` to `T & {}`, and every copy bound to a union read an
191
+ * intersection with a union member, which no record layout can hold: ~400
192
+ * rows of "no primitive for an intersection whose member is not a record
193
+ * shape" on the tsc self-compile. This is the checker's own reduction,
194
+ * applied after substitution: distribute, drop `unknown` and the empty
195
+ * object type (both intersect as identity), and reduce a product that pairs
196
+ * an absence with anything else, or two primitives of different domains, to
197
+ * `never`, which the union then drops. Only an UNNAMED intersection
198
+ * distributes: a declared one keeps its name as its layout anchor.
199
+ */
200
+ // A recursive declaration is deliberately visible by id before its shape
201
+ // exists. It is an atomic member until the frame that reserved it completes
202
+ // it; inspecting it here violates the table's anchor protocol, while
203
+ // retaining its id in each distributed product preserves the recurrence.
204
+ const closedShapeAt = (id) => (table.isOpen(id) ? null : table.get(id).shape);
205
+ const distributedIntersectionOf = (members) => {
206
+ if (!members.some((member) => closedShapeAt(member)?.kind === 'union'))
207
+ return null;
208
+ let products = [[]];
209
+ for (const member of members) {
210
+ const shape = closedShapeAt(member);
211
+ const choices = shape?.kind === 'union' ? shape.members : [member];
212
+ products = products.flatMap((product) => choices.map((choice) => [...product, choice]));
213
+ if (products.length > 512)
214
+ return null;
215
+ }
216
+ const arms = [];
217
+ for (const product of products) {
218
+ const arm = reducedIntersectionOf(product);
219
+ if (arm !== null && !arms.includes(arm))
220
+ arms.push(arm);
221
+ }
222
+ const only = arms[0];
223
+ if (only === undefined)
224
+ return typeOf(checker.getNeverType());
225
+ return arms.length === 1 ? only : table.intern({ kind: 'union', members: arms });
226
+ };
227
+ /** One product of the distribution, reduced as the checker reduces an intersection; `null` is `never`. */
228
+ const reducedIntersectionOf = (product) => {
229
+ const isIdentity = (shape) => (shape.kind === 'primitive' && shape.primitive === 'unknown') ||
230
+ (shape.kind === 'object' && shape.members.length === 0 && shape.index.length === 0);
231
+ const kept = [...new Set(product)].filter((member) => {
232
+ const shape = closedShapeAt(member);
233
+ return shape === null || !isIdentity(shape);
234
+ });
235
+ const first = product[0];
236
+ if (kept.length === 0)
237
+ return first ?? null;
238
+ const domains = kept.map((member) => {
239
+ const shape = closedShapeAt(member);
240
+ if (shape === null)
241
+ return null;
242
+ if (shape.kind === 'primitive')
243
+ return shape.primitive;
244
+ if (shape.kind === 'literal')
245
+ return shape.primitive;
246
+ return null;
247
+ });
248
+ if (domains.includes('never'))
249
+ return null;
250
+ const primitives = new Set(domains.flatMap((domain) => (domain === null ? [] : [domain])));
251
+ if (primitives.size > 1)
252
+ return null;
253
+ const absent = [...primitives].some((domain) => domain === 'undefined' || domain === 'null' || domain === 'void');
254
+ if (absent && kept.length > 1)
255
+ return null;
256
+ const only = kept[0];
257
+ if (kept.length === 1 && only !== undefined)
258
+ return only;
259
+ if (kept.some((member) => closedShapeAt(member)?.kind === 'union'))
260
+ return distributedIntersectionOf(kept);
261
+ return table.intern({ kind: 'intersection', members: kept, declaration: null, resolved: null });
262
+ };
263
+ /**
264
+ * The index half of `T[K]`, resolved the way `resolvedObjectType` resolves
265
+ * the object half: the copy's binding first, then the parameter's own
266
+ * constraint. `readPackageJsonField<K extends MatchingKeys<PackageJson,
267
+ * string | undefined>>(json, fieldName: K): PackageJson[K]` (tsc's
268
+ * moduleNameResolver.ts) is the shape -- the OBJECT is a plain interface
269
+ * and only the index is a parameter, which the object-side substitution
270
+ * alone never touched, so every copy refused "an indexed access whose
271
+ * object type is still a type parameter" for an access whose object type
272
+ * never was one. A copy bound to `"types"` reads `PackageJson["types"]`;
273
+ * the value-use copy reads the constraint, the checker-evaluated union of
274
+ * the matching keys, which `keysOf` enumerates as it does any literal
275
+ * union. A union index is left as written for the same enumerator.
276
+ */
277
+ const resolvedIndexType = (indexType) => {
278
+ const substituted = substituteTypeParameter(indexType);
279
+ if (substituted !== indexType)
280
+ return substituted;
281
+ if ((indexType.flags & ts.TypeFlags.TypeParameter) === 0)
282
+ return indexType;
283
+ const bound = checker.getBaseConstraintOfType(indexType);
284
+ return bound && bound !== indexType ? bound : indexType;
285
+ };
286
+ /**
287
+ * Whether a type is, or contains, a form the checker left DEFERRED -- a
288
+ * conditional it could not evaluate, an unresolved indexed access, a
289
+ * substitution. Such a type's base constraint is a fallback rather than a
290
+ * statement, which is the distinction `memberTypesThroughBound` turns on.
291
+ */
292
+ const carriesDeferredForm = (type, depth = 0) => {
293
+ if (depth > 8)
294
+ return false;
295
+ const deferred = ts.TypeFlags.Conditional | ts.TypeFlags.IndexedAccess | ts.TypeFlags.Substitution;
296
+ if ((type.flags & deferred) !== 0)
297
+ return true;
298
+ if (type.isUnion() || type.isIntersection())
299
+ return type.types.some((part) => carriesDeferredForm(part, depth + 1));
300
+ return false;
301
+ };
302
+ /**
303
+ * `T[K]`'s member types read off `T`'s declared UPPER BOUND, for the object
304
+ * types whose own shape cannot answer.
305
+ *
306
+ * A bound is information, not its absence. `E extends Env` states that every
307
+ * `E` this program can produce is an `Env`, so every `E['Bindings']` is one
308
+ * of `Env['Bindings']`'s own members -- and answering with those is
309
+ * answering with a type every instantiation's value satisfies, which is
310
+ * exactly what a storage carrier has to be. The alternative was a bottom
311
+ * carrier, which is not a cell at all.
312
+ *
313
+ * The case that forced it is not a naked parameter, which is why this is not
314
+ * inside `resolvedObjectType`. hono's router chain substitutes `E` with a
315
+ * growing INTERSECTION -- `IfAnyThenEmptyObject<E extends Env ? Env extends
316
+ * E ? {} : E : E> & IfAnyThenEmptyObject<E2 ...> & {}`, one arm per `.get()`
317
+ * in the program -- because every route returns a `Hono` whose environment
318
+ * merges the last one's. Substitution resolves `E` to that intersection
319
+ * perfectly well; what cannot answer `['Bindings']` is the intersection,
320
+ * whose constituents are CONDITIONAL types the checker leaves deferred while
321
+ * `E` is generic. Its base constraint is `{}`, the environment hono's own
322
+ * `BlankEnv` states, and `{}` declares no `Bindings` -- so the access is
323
+ * `undefined`, which is what `indexedAccessMemberTypes` already answers for
324
+ * a missing key on a real object type.
325
+ *
326
+ * `getBaseConstraintOfType` rather than `getConstraintOfType`: a constraint
327
+ * can itself be a type parameter (`<A, B extends A>`), and a carrier needs
328
+ * the bound that is no longer one. A type with no constraint answers
329
+ * `undefined` and the caller keeps its refusal -- nothing was stated, so
330
+ * there is nothing to resolve against. `any`/`unknown` as the bound keeps it
331
+ * too: those are answered above, where the object type itself is the top
332
+ * type, and reaching them through a bound would turn "nothing is stated"
333
+ * into a claim about members.
334
+ */
335
+ const memberTypesThroughBound = (objectType, indexType) => {
336
+ const bound = checker.getBaseConstraintOfType(objectType);
337
+ if (!bound || bound === objectType)
338
+ return null;
339
+ if ((bound.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) !== 0)
340
+ return null;
341
+ // An EMPTY bound over a DEFERRED type states nothing, and must not be read
342
+ // as stating absence. `indexedAccessMemberTypes` answers a missing key with
343
+ // `undefined` -- the language's own answer, and the right one for a real
344
+ // object type that genuinely declares no such member. `{}` arrived at as
345
+ // the constraint of a conditional the checker could not evaluate is a
346
+ // different fact wearing the same shape: it is TypeScript's fallback, not
347
+ // the author's claim. hono's `env: E['Bindings'] = {}` is where the two
348
+ // part company -- in the copy whose object type is the router chain's
349
+ // intersection of deferred conditionals, absence would carrier the field as
350
+ // `undefined`, a cell that provably cannot hold the initializer written on
351
+ // the very same line. `unknown` is what is actually known there, and it is
352
+ // a cell.
353
+ if (carriesDeferredForm(objectType) && bound.getProperties().length === 0 && checker.getIndexInfosOfType(bound).length === 0) {
354
+ return [checker.getUnknownType()];
355
+ }
356
+ return indexedAccessMemberTypes(checker, bound, indexType);
357
+ };
358
+ // `getMinArgumentCount` is checker-internal. The public answer is the count of
359
+ // leading parameters the call site must supply: everything before the first
360
+ // optional, defaulted, or rest parameter.
361
+ const { signatureOf, memberOf, indexesOf, tupleElementsOf } = createStructuralParts({
362
+ parameters,
363
+ checker,
364
+ identities,
365
+ typeOf: (type) => typeOf(type),
366
+ parameterOverrideAt: (parameter) => refusedArrayParameterTypeAt(parameter) ?? prototypeObjectParameterTypeAt(parameter),
367
+ implicitReceiverOf,
368
+ declaredMemberSignatureOf,
369
+ declaredMembers,
370
+ keyOfSymbol,
371
+ // Same wrap the body-side rest-parameter reference below performs
372
+ // (`table.intern({ kind: 'array', element: typeOf(restElement), ... })`)
373
+ // exposed to `structural-parts.ts`'s `parameterOf`, which has no `table`
374
+ // of its own -- see `StructuralPartsInput.internArray`'s doc.
375
+ internArray: (element) => table.intern({ kind: 'array', element, readonly: false, extension: [] }),
376
+ internUnion: (members) => table.intern({ kind: 'union', members }),
377
+ // So `memberOf` can close the same keyed-collection-field gap `typeAt`
378
+ // closes for every other node shape naming the same cell -- see
379
+ // `StructuralPartsInput.collections`'s own doc.
380
+ collections,
381
+ table,
382
+ // The bag census the collection value slot needs -- see
383
+ // `StructuralPartsInput.bags`.
384
+ bags
385
+ });
386
+ const { keeperFor } = createMemberRules(identities);
387
+ /**
388
+ * The shape of a type the LANGUAGE indexes -- a tuple or an Array -- or
389
+ * `null` for anything else.
390
+ *
391
+ * Factored out because there are two places a type can be shaped, and only
392
+ * one of them used to ask this. `Array<T>`'s own members mention
393
+ * `Array<T>` (`concat`, `slice`, `filter` all return one), so an array
394
+ * reached mid-walk is SELF-REFERENTIAL, and the self-referential branch
395
+ * anchored it and then handed it to `buildDeclaredShape` -- which builds
396
+ * the interface's data-only projection, `{ length, [Symbol.unscopables],
397
+ * [number]: T }` with every method dropped. `remember` then cached that
398
+ * against the very `ts.Type` the array branch below owns, so every later
399
+ * mention of the same array got the projection too, and the array branch
400
+ * was never reached again.
401
+ *
402
+ * Reached that way, `Object3D[]` carried as a `native-record-ref`:
403
+ * CubeCamera's `const [ cameraPX, ... ] = cameras` asked for a
404
+ * `destructuring:array-pattern:native-record-ref` helper no manifest
405
+ * claims or should. Measured on the three.js app, 34 shapes and 52 selected
406
+ * carriers were Array projections of this kind, against 4258 honest
407
+ * `array-object` carriers -- an ordering leak, not a systemic
408
+ * misclassification, which is exactly why it survived: most arrays are
409
+ * reached from a position that asks the array branch first.
410
+ *
411
+ * `readonly` is `false` for the array case, as it has always effectively
412
+ * been: the old expression was `isArrayLikeType(type) && !isArrayType(type)`
413
+ * evaluated INSIDE an `isArrayType` branch, so it could not be anything
414
+ * else. A `readonly T[]` is `ReadonlyArray<T>`, which `isArrayType` answers
415
+ * `false` for and which reaches neither this helper nor that branch.
416
+ */
417
+ const indexedShapeOf = (type) => {
418
+ if (checker.isTupleType(type)) {
419
+ const reference = type;
420
+ return { kind: 'tuple', elements: tupleElementsOf(reference), readonly: reference.target.readonly };
421
+ }
422
+ if (!checker.isArrayType(type))
423
+ return null;
424
+ const element = checker.getTypeArguments(type)[0];
425
+ if (!element)
426
+ return { kind: 'unresolved', reason: 'array type without an element type argument' };
427
+ return { kind: 'array', element: typeOf(element), readonly: false, extension: [] };
428
+ };
429
+ /**
430
+ * Whether an interface's heritage reaches the standard `Array` or
431
+ * `ReadonlyArray`, through any chain of source interfaces.
432
+ */
433
+ const reachesStandardArray = (target, anchor, visited) => {
434
+ if (visited.has(target))
435
+ return null;
436
+ visited.add(target);
437
+ for (const base of checker.getBaseTypes(target)) {
438
+ if (isStandardInterfaceType(checker, anchor, 'Array', base))
439
+ return 'array';
440
+ if (isStandardInterfaceType(checker, anchor, 'ReadonlyArray', base))
441
+ return 'readonly-array';
442
+ // `ConcatArray<T>` is the third spelling of the same object, not a
443
+ // separate shape -- see `arrayHeritageShapeOf`'s own note on why it is
444
+ // recognized directly rather than through heritage.
445
+ if (isStandardInterfaceType(checker, anchor, 'ConcatArray', base))
446
+ return 'readonly-array';
447
+ const baseTarget = base.target ?? base;
448
+ if (!(baseTarget.objectFlags & ts.ObjectFlags.Interface))
449
+ continue;
450
+ const reached = reachesStandardArray(baseTarget, anchor, visited);
451
+ if (reached)
452
+ return reached;
453
+ }
454
+ return null;
455
+ };
456
+ /** Whether a property is one the standard `Array`/`ReadonlyArray` interfaces themselves declare. */
457
+ const isStandardArrayMember = (property) => (property.declarations ?? []).some((declaration) => {
458
+ const owner = declaration.parent;
459
+ return (ts.isInterfaceDeclaration(owner) &&
460
+ owner.getSourceFile().isDeclarationFile &&
461
+ (owner.name.text === 'Array' || owner.name.text === 'ReadonlyArray' || owner.name.text === 'ConcatArray'));
462
+ });
463
+ /**
464
+ * A BRAND on an array-extending interface -- `" __sortedArrayBrand": any`
465
+ * (TypeScript's `SortedReadonlyArray<T>`) -- names no storage: its type
466
+ * admits no value a program could write, and its name is spelled to be
467
+ * unwritable. The object deriver's `isVacuousBrand` makes the same call for
468
+ * intersections; here the member is simply not part of the extension.
469
+ */
470
+ const isArrayBrandMember = (property, location) => {
471
+ const name = property.getName();
472
+ if (!(name.startsWith(' ') || name.startsWith('__')))
473
+ return false;
474
+ const flags = checker.getTypeOfSymbolAtLocation(property, location).flags;
475
+ return (flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown | ts.TypeFlags.Never | ts.TypeFlags.UniqueESSymbol)) !== 0;
476
+ };
477
+ /**
478
+ * An interface whose heritage reaches the standard `Array`/`ReadonlyArray`
479
+ * -- TypeScript's own `NodeArray<T> extends ReadonlyArray<T>,
480
+ * ReadonlyTextRange` -- is an ARRAY with extra fields, not an object that
481
+ * happens to carry the array's members as storage. Enumerated as an object
482
+ * it interned `map<U>`, `filter<S>` and the rest as fields whose type
483
+ * parameters no copy ever binds (230 "type parameter ... reached
484
+ * representation without monomorphization" rows on the tsc self-compile,
485
+ * one shape), and the deriver laid out a record for a value every consumer
486
+ * indexes and iterates.
487
+ *
488
+ * The element is the INSTANTIATED number-index type, so `NodeArray<T>` read
489
+ * inside a generic copy still resolves `T` through that copy exactly as
490
+ * `T[]` does. The extension is the interface's own data members -- every
491
+ * property the array interfaces do not themselves declare, so a second base
492
+ * (`ReadonlyTextRange`'s `pos`/`end`) contributes too -- minus brand
493
+ * members, which state nothing storable. `readonly` stays `false` for the
494
+ * same reason `indexedShapeOf` keeps it so: `Array` and `ReadonlyArray`
495
+ * heritage must intern to ONE shape, since `MutableNodeArray<T>` and
496
+ * `NodeArray<T>` are the same object under two spellings.
497
+ */
498
+ const arrayHeritageShapeOf = (type, location) => {
499
+ if (!(type.flags & ts.TypeFlags.Object))
500
+ return null;
501
+ const object = type;
502
+ const target = object.objectFlags & ts.ObjectFlags.Reference ? type.target : object;
503
+ if (!(target.objectFlags & ts.ObjectFlags.Interface))
504
+ return null;
505
+ // `ConcatArray<T>` is the one standard array interface that reaches
506
+ // neither `Array` nor `ReadonlyArray` through heritage: `lib.es5.d.ts`
507
+ // declares it standalone, with `readonly length`, `readonly [n: number]:
508
+ // T`, `join` and `slice`, and `Array<T>`/`ReadonlyArray<T>`/every tuple
509
+ // satisfy it structurally. It is a SPELLING of the array object, not an
510
+ // object that happens to carry an array's members, and it is where every
511
+ // `Array.prototype.concat(...items: ConcatArray<T>[])` argument lands --
512
+ // so deriving it as a record made `a.concat(b)` refuse the rest pack it
513
+ // had just built (`conversion:array-object(E)->native-record-ref`), for
514
+ // every element type, in every program. hono's `RegExpRouter`
515
+ // (`Object.keys(a).concat(Object.keys(b))`) and its trie router
516
+ // (`tempNodes.concat(shifted)`) are the two that named it.
517
+ if (!reachesStandardArray(target, location, new Set()) &&
518
+ !isStandardInterfaceType(checker, location, 'ConcatArray', type))
519
+ return null;
520
+ const element = checker.getIndexTypeOfType(type, ts.IndexKind.Number);
521
+ if (!element)
522
+ return null;
523
+ const extension = [];
524
+ for (const property of creationOrderedProperties(checker, type, parameters)) {
525
+ if (isStandardArrayMember(property) || isArrayBrandMember(property, location))
526
+ continue;
527
+ const member = memberOf(property, location);
528
+ if (member)
529
+ extension.push(member);
530
+ }
531
+ return { kind: 'array', element: typeOf(element), readonly: false, extension };
532
+ };
533
+ const objectShapeOf = (type, location, members = 'all') => {
534
+ const properties = creationOrderedProperties(checker, type, parameters);
535
+ const kept = members === 'all' ? properties : properties.filter(keeperFor(properties, members));
536
+ const mapped = kept.flatMap((property) => {
537
+ const member = memberOf(property, location);
538
+ return member ? [member] : [];
539
+ });
540
+ const indexes = [...indexesOf(type)];
541
+ if (location && ts.isObjectLiteralExpression(location) && members === 'all') {
542
+ const runtimeMembers = mapped.filter((member) => {
543
+ if (member.key.kind !== 'symbol' || member.accessor !== null)
544
+ return false;
545
+ const keyDeclarationId = member.key.declaration;
546
+ const property = kept.find((candidate) => {
547
+ const keyDeclaration = symbolKeyDeclarationOf(checker, identities, candidate);
548
+ return keyDeclaration !== null && identities.declarationIdOf(keyDeclaration) === keyDeclarationId;
549
+ });
550
+ const declarations = property?.declarations;
551
+ return !!declarations?.length && declarations.every(ts.isPropertyAssignment) && !declarations[0].getSourceFile().isDeclarationFile;
552
+ });
553
+ if (runtimeMembers.length) {
554
+ const existing = indexes.findIndex((index) => index.key === 'symbol');
555
+ const prior = existing < 0 ? undefined : indexes[existing];
556
+ const values = [...new Set([...runtimeMembers.map((member) => member.type), ...(prior ? [prior.value] : [])])];
557
+ const value = values.length === 1 ? values[0] : table.intern({ kind: 'union', members: values });
558
+ const index = {
559
+ key: 'symbol',
560
+ value,
561
+ readonly: false,
562
+ runtimeMembers: runtimeMembers.flatMap((member) => (member.key.kind === 'symbol' ? [member.key.declaration] : [])),
563
+ finite: prior === undefined
564
+ };
565
+ if (existing < 0)
566
+ indexes.push(index);
567
+ else
568
+ indexes[existing] = index;
569
+ }
570
+ }
571
+ return {
572
+ kind: 'object',
573
+ members: mapped,
574
+ index: indexes,
575
+ membersDropped: kept.length !== properties.length
576
+ };
577
+ };
578
+ /**
579
+ * The structure a declared name stands for.
580
+ *
581
+ * A name without a body is a name the later layers cannot lay out, so the body
582
+ * is interned here while the nominal identity is still anchored -- a member
583
+ * that refers back to the declaration resolves to the anchor instead of
584
+ * re-entering translation.
585
+ */
586
+ /**
587
+ * The storage a class instance owns.
588
+ *
589
+ * Only `Property` members: a method and an accessor live on the prototype, so
590
+ * putting either in the instance's structure would claim per-instance storage
591
+ * the language does not allocate, and every instance would carry a copy of
592
+ * every method. A field that happens to hold a function (`onClick = () => {}`)
593
+ * *is* per-instance storage, and the symbol flags are what tell the two apart
594
+ * -- not the type of the value they hold.
595
+ */
596
+ const classInstanceBodyOf = (type, location) => {
597
+ // A class declared in a declaration file is enumerated like any other. Its
598
+ // *fields* are data, and a subclass this program does define inherits them
599
+ // -- refusing the layout would leave that subclass with no carrier at all.
600
+ // What the program genuinely cannot do with such a class is construct one or
601
+ // call one of its methods, and both of those refuse where they happen: the
602
+ // construction has no body to run, and a method key resolves to no callable.
603
+ const shape = objectShapeOf(type, location, 'data-only');
604
+ // `objectShapeOf` walks `type.getProperties()` -- the checker's OWN
605
+ // member table -- which is blind to a field installed only through a
606
+ // `const _this = this` alias (`source-class-data.ts`'s
607
+ // `constructorInstalledMemberWritesOf` says why the checker never learns
608
+ // one). Without this, such a field got no struct member at all, and every
609
+ // read/write of it fell back to the fully dynamic `gea_readOwnField`/
610
+ // `gea_writeOwnField` expando protocol -- the closure PROOF for a call
611
+ // reached through it could still certify (that fallback fixed the flow-
612
+ // index side, in `source-class-data.ts`), but the emitted storage stayed
613
+ // boxed. `flow` is only absent for a handful of callers that never had a
614
+ // constructor-function/class-alias question to ask in the first place
615
+ // (see `buildMapper`'s `flow?: ValueFlowIndex`); `ts.isClassLike` matches
616
+ // this function's one call site, gated the same way at `declaredAnchorOf`.
617
+ if (flow && ts.isClassLike(location) && shape.kind === 'object') {
618
+ const installed = constructorInstalledMemberDeclarationsOf(flow, location);
619
+ if (installed.size > 0) {
620
+ const existing = new Set(shape.members.flatMap((member) => (member.key.kind === 'string' ? [member.key.value] : [])));
621
+ const extra = [];
622
+ for (const [key, declarations] of installed) {
623
+ if (existing.has(key))
624
+ continue;
625
+ const values = [...new Set(declarations.map((declaration) => typeOf(checker.getTypeAtLocation(declaration.right))))];
626
+ extra.push({
627
+ key: { kind: 'string', value: key },
628
+ type: values.length === 1 ? values[0] : table.intern({ kind: 'union', members: values }),
629
+ optional: false,
630
+ readonly: false,
631
+ accessor: null
632
+ });
633
+ }
634
+ if (extra.length > 0)
635
+ return table.intern({ ...shape, members: [...shape.members, ...extra] });
636
+ }
637
+ }
638
+ return table.intern(shape);
639
+ };
640
+ const { declaredBodyOf } = createDeclaredBodyResolver({ table, typeOf, signatureOf, objectShapeOf, arrayHeritageShapeOf });
641
+ const declaredAnchorOf = (type) => {
642
+ // `type Img = { imageId: number; describe(): number }` -- a type alias to
643
+ // an anonymous object-literal type -- has its OWN symbol answer the
644
+ // anonymous `__type` symbol pointing at the `TypeLiteral` node, not the
645
+ // `TypeAliasDeclaration`, because that is genuinely what `type.getSymbol()`
646
+ // returns for an alias to an object literal type (verified against the
647
+ // checker directly). The `?? type.aliasSymbol` fallback below therefore
648
+ // never fires for this one specific shape, and `Img` never gets the
649
+ // `declared` nominal anchor an `interface Img {...}` gets for the
650
+ // identical body -- two spellings of the same kind of declaration ending
651
+ // up with two different identity treatments. Preferring `aliasSymbol`
652
+ // whenever the own symbol resolves to a `TypeLiteral` (rather than always
653
+ // preferring it, which would wrongly re-route `type X = SomeInterface`
654
+ // away from `SomeInterface`'s own, already-correct anchor) makes `Img`
655
+ // resolve through the alias exactly like `interface Img` does, without
656
+ // changing any other declared type's resolution.
657
+ //
658
+ // ⛔ A MAPPED type is deliberately NOT treated as anonymous here, and this
659
+ // was measured both ways. `Record<K, V>` is `type Record<K, T> = { [P in
660
+ // K]: T }`, so an instantiation's own symbol answers the anonymous
661
+ // `__type` of that `MappedTypeNode` rather than the `TypeAliasDeclaration`
662
+ // -- which means a type recursing THROUGH a mapped alias has no
663
+ // declaration to break the cycle on, and hono's `class Node { #children:
664
+ // Record<string, Node> }` (`router/reg-exp-router/node.ts`) refuses as `a
665
+ // self-referential type of this shape is not modelled`. Routing such a
666
+ // type through the ALIAS instead does fix that, and it costs
667
+ // `examples/weather` its whole certificate: with the alias as the anchor,
668
+ // a host-bound member reached through a mapped type demands
669
+ // `native-boundary:__type@1`, a protocol nothing registers. Net on hono
670
+ // once `router/reg-exp-router` stopped being reachable at all (see
671
+ // `reachability.ts`'s type-only import rule) it was WORSE by two
672
+ // obligations as well, so there is nothing left on the other side of the
673
+ // trade. A cycle through a mapped alias needs `selfReferentialShapeOf` to
674
+ // model that shape, not a second nominal anchor for it -- which is what it
675
+ // now does: its dictionary case closes `Record<string, Node>` on the
676
+ // anchor the retry already reserved, leaving this decision untouched.
677
+ const ownSymbol = type.getSymbol();
678
+ const ownDeclaration = ownSymbol ? identities.declarationOfSymbol(ownSymbol) : null;
679
+ const anonymous = ownDeclaration !== null && (ts.isTypeLiteralNode(ownDeclaration) || ts.isJSDocTypeLiteral(ownDeclaration));
680
+ const symbol = (anonymous ? type.aliasSymbol : null) ?? ownSymbol ?? type.aliasSymbol;
681
+ if (!symbol)
682
+ return null;
683
+ const declaration = identities.declarationOfSymbol(symbol);
684
+ if (!declaration)
685
+ return null;
686
+ // At the ROOT path, deliberately, and never at the copy this walk happens
687
+ // to be inside. `identities` is a per-copy VIEW (`identities.ts`'s
688
+ // `declarationIdOf: (declaration, override) => ... prefixFor(declaration,
689
+ // path)`), so asking it without an override mints `decl|f77|148` from a
690
+ // root walk and `decl|f77|148@0` from a copy's -- two nominal anchors for
691
+ // ONE declaration, and therefore two structural shapes, two `class-ref`
692
+ // carriers and two C++ struct names (`cppTypeOf` spells a class-ref as
693
+ // `cppClassName(representation.declaration)`).
694
+ //
695
+ // Which copy a walk was in is not part of a nominal type's identity. What
696
+ // IS part of it -- the instantiation's own type arguments -- is already in
697
+ // the anchor key below, folded through `layoutRelevantParameterIndices` so
698
+ // that two instantiations differing only in a phantom parameter share one
699
+ // physical layout. The copy path says nothing the arguments do not, and
700
+ // saying it twice is what split hono's `Context` and `Hono` into a
701
+ // root-cited half and a copy-cited half whose members only one of the two
702
+ // could ever find.
703
+ const id = identities.declarationIdOf(declaration, rootSpecialization);
704
+ if (ts.isClassLike(declaration)) {
705
+ // A class's constructor object and its instances are different values with
706
+ // different members; merging them loses `new` semantics entirely.
707
+ const isConstructorSide = type.getCallSignatures().length + type.getConstructSignatures().length > 0;
708
+ return { kind: isConstructorSide ? 'class-constructor' : 'class-instance', declaration: id, declarationNode: declaration };
709
+ }
710
+ // A JSDoc `@typedef {object} Node` is a declared name just as an
711
+ // `interface Node` is. The checker's own type for it has the synthetic
712
+ // JSDoc type-literal as its symbol and the typedef as `aliasSymbol`, so
713
+ // stopping here would re-enter the anonymous object through `Node[]` and
714
+ // lose the only finite native layout. The alias declaration is the stable
715
+ // checker identity that closes that cycle; this is declaration-kind
716
+ // parity, not a protocol for a particular JSDoc library.
717
+ if (ts.isInterfaceDeclaration(declaration) ||
718
+ ts.isTypeAliasDeclaration(declaration) ||
719
+ ts.isJSDocTypedefTag(declaration) ||
720
+ ts.isEnumDeclaration(declaration)) {
721
+ return { kind: 'declared', declaration: id, declarationNode: declaration };
722
+ }
723
+ // A pre-`class` JavaScript CONSTRUCTOR FUNCTION's instances are nominal,
724
+ // and named by the function: `function WebGLClipping( properties ) {
725
+ // this.uniform = uniform; ... }` gives TypeScript's own JS inference a
726
+ // construct signature whose return type it prints as `WebGLClipping`,
727
+ // symboled to the function declaration itself. Anchoring it here is what
728
+ // lets that type be SELF-REFERENTIAL, which every one of these is: the
729
+ // instance carries `this.setState = function ( material ) { ... }`, whose
730
+ // own receiver is the instance (`structural-receiver.ts`'s
731
+ // `jsConstructorReceiverOf`). Reached anonymously the walk collides with
732
+ // itself and `selfReferentialShapeOf` models no object shape with NAMED
733
+ // members (its dictionary case is index-only on purpose, because the
734
+ // retry cannot reach the location-aware member walk), so the whole
735
+ // instance -- every field, every method -- refuses as `a self-referential
736
+ // type of this shape is not modelled`; anchored, the member that refers
737
+ // back resolves to the anchor, exactly as a class instance's does.
738
+ //
739
+ // The INSTANCE side only. The function's own type has the same symbol, and
740
+ // it is not a declared name for a structure: it is the callable, whose
741
+ // carrier is `function-and-constructor`. The split is the one
742
+ // `ts.isClassLike` above makes for the identical reason -- a constructor
743
+ // object and its instances are different values with different members --
744
+ // told apart the same way, by whether the type carries a signature.
745
+ if (ts.isFunctionDeclaration(declaration) || ts.isFunctionExpression(declaration)) {
746
+ if (type.getCallSignatures().length + type.getConstructSignatures().length > 0)
747
+ return null;
748
+ return { kind: 'declared', declaration: id, declarationNode: declaration };
749
+ }
750
+ return null;
751
+ };
752
+ /**
753
+ * The body of a `declared`/`class-constructor`/`class-instance` anchor,
754
+ * once its type arguments are already in hand.
755
+ *
756
+ * Shared between the ordinary declared-anchor path (`translate`, below) and
757
+ * the self-referential retry (`typeOf`'s `selfReferential` branch): a class
758
+ * whose OWN type argument mentions the class again -- `Object3D<EventMap>`
759
+ * where `EventMap` describes an event carrying `Object3D<EventMap>` as its
760
+ * target, exactly what three.js's own `Object3DEventMap` does -- cannot
761
+ * compute this anchor's key up front, because the key needs the argument's
762
+ * structural id and deriving that id is what re-enters the class. That is a
763
+ * genuine cycle, not an undeclared shape: the retry mechanism already
764
+ * detects it and reserves an anchor before calling this, at which point
765
+ * `checker.getTypeArguments(...).map(typeOf)` re-entering the same class
766
+ * resolves through that anchor (`inProgress`) instead of recursing. Only
767
+ * the ordinary path's *key* depends on having the type arguments already
768
+ * -- the *body* this function builds does not care which path reserved its
769
+ * anchor.
770
+ */
771
+ /**
772
+ * The one layout every interface of a family shares -- `interface-families.ts`
773
+ * says why the layout follows the object rather than the view. Each member
774
+ * is enumerated through `objectShapeOf` exactly as a lone interface's body
775
+ * is, then the members merge by key: a field is required only where every
776
+ * member of the family declares it required (an object of the family may
777
+ * lack it otherwise, and `memberOf`'s own rule applies -- the absence has
778
+ * to be in the TYPE, since that is all a field's carrier derives from), and
779
+ * its type is the union of what the members declare, flattened, so that
780
+ * `Identifier` beside `Identifier | undefined` is one three-state union and
781
+ * not a union nesting a union, which `union.ts` would carry as two arms of
782
+ * one carrier.
783
+ *
784
+ * Reserved as an ANCHOR before any member is walked: a member's own field
785
+ * types name family-mates (`Node.parent: Node`, `SourceFile.statements:
786
+ * NodeArray<Statement>`), each a declared anchor whose body is this same
787
+ * layout, so the walk re-enters here with the reservation made and reads
788
+ * the id back instead of recursing. Abandoned on an unwind for the reason
789
+ * `typeOfWalk` abandons its own: the retry re-reserves under the same key.
790
+ */
791
+ const familyBodyOf = (declared) => {
792
+ if (declared.kind !== 'declared' || !ts.isInterfaceDeclaration(declared.declarationNode))
793
+ return null;
794
+ const family = families.familyOf(declared.declaration);
795
+ if (!family)
796
+ return null;
797
+ const { id, fresh } = table.anchor(`interface-family:${family.key}`);
798
+ if (!fresh)
799
+ return id;
800
+ let settled = false;
801
+ try {
802
+ table.complete(id, familyLayoutOf(family));
803
+ settled = true;
804
+ }
805
+ finally {
806
+ if (!settled)
807
+ table.abandon(id);
808
+ }
809
+ return id;
810
+ };
811
+ /**
812
+ * The one family member an intersection NARROWS, when that is all it does.
813
+ *
814
+ * tsc's type guards return `node is CallExpression & { expression:
815
+ * Identifier; arguments: [StringLiteralLike] }` and `node is
816
+ * BinaryExpression & { operatorToken: AssignmentOperatorToken }`
817
+ * (`isRequireCall`, `isAssignmentExpression`, ...): the checker narrows
818
+ * `node` to an intersection of a family member with an object literal
819
+ * type that restates some of the member's own fields more precisely. The
820
+ * value is the same object -- there is exactly one `Node` allocation, and
821
+ * the family exists so that every view of it is ONE layout -- but the
822
+ * intersection interned as its own shape below, whose `resolved` image is
823
+ * a fresh record with every field required, so every guarded read asked
824
+ * for `native-record-ref(family) -> record(...)`, a conversion that would
825
+ * copy an object the program still holds by identity (72 rows over
826
+ * `utilities.ts`, `checker.ts`, `utilitiesPublic.ts`).
827
+ *
828
+ * Admitted only where the intersection adds nothing to the object: every
829
+ * non-family member is an anonymous object literal type with no index,
830
+ * call or construct signature, and every property it names is a field the
831
+ * family already declares. A brand (`& { __x: unique symbol }`) or a new
832
+ * field is a different type and keeps the general path. Two family
833
+ * members of the same family are the same layout (`Expression &
834
+ * Declaration`); members of different families are not one object.
835
+ */
836
+ const familyFieldNames = new Map();
837
+ const familyMemberNarrowedBy = (type) => {
838
+ const member = narrowedFamilyMemberOf(type);
839
+ return member === null ? null : typeOf(member);
840
+ };
841
+ const narrowedFamilyMemberOf = (type) => {
842
+ let family = null;
843
+ let member = null;
844
+ const narrowings = [];
845
+ for (const part of type.types) {
846
+ const anchor = declaredAnchorOf(part);
847
+ const own = anchor?.kind === 'declared' && ts.isInterfaceDeclaration(anchor.declarationNode) ? families.familyOf(anchor.declaration) : null;
848
+ if (own) {
849
+ if (family !== null && own !== family)
850
+ return null;
851
+ family = own;
852
+ member ??= part;
853
+ continue;
854
+ }
855
+ if ((part.flags & ts.TypeFlags.Object) === 0 || (part.objectFlags & ts.ObjectFlags.Anonymous) === 0)
856
+ return null;
857
+ if ((part.getSymbol()?.declarations ?? []).some((declaration) => !ts.isTypeLiteralNode(declaration)))
858
+ return null;
859
+ narrowings.push(part);
860
+ }
861
+ if (family === null || member === null)
862
+ return null;
863
+ let names = familyFieldNames.get(family.key);
864
+ if (!names) {
865
+ const collected = new Set();
866
+ for (const declaration of family.members) {
867
+ const symbol = checker.getSymbolAtLocation(declaration.name);
868
+ if (!symbol)
869
+ continue;
870
+ for (const property of checker.getPropertiesOfType(checker.getDeclaredTypeOfSymbol(symbol)))
871
+ collected.add(property.getName());
872
+ }
873
+ names = collected;
874
+ familyFieldNames.set(family.key, names);
875
+ }
876
+ for (const part of narrowings) {
877
+ if (checker.getIndexInfosOfType(part).length > 0 || part.getCallSignatures().length > 0 || part.getConstructSignatures().length > 0)
878
+ return null;
879
+ if (!checker.getPropertiesOfType(part).every((property) => names.has(property.getName())))
880
+ return null;
881
+ }
882
+ return member;
883
+ };
884
+ const familyLayoutOf = (family) => {
885
+ // An open anchor is a family-mate's (or another recursive type's) body
886
+ // still being built; it names one member and nothing to flatten.
887
+ const flatten = (id) => {
888
+ if (table.isOpen(id))
889
+ return [id];
890
+ const shape = table.get(id).shape;
891
+ return shape.kind === 'union' ? shape.members.flatMap(flatten) : [id];
892
+ };
893
+ const merged = new Map();
894
+ for (const member of family.members) {
895
+ const symbol = checker.getSymbolAtLocation(member.name);
896
+ if (!symbol)
897
+ continue;
898
+ const shape = objectShapeOf(checker.getDeclaredTypeOfSymbol(symbol), member, 'all');
899
+ if (shape.kind !== 'object')
900
+ continue;
901
+ for (const field of shape.members) {
902
+ if (field.accessor !== null)
903
+ continue;
904
+ const keyText = JSON.stringify(field.key);
905
+ const slot = merged.get(keyText) ?? { key: field.key, types: [], declaredBy: 0, requiredBy: 0, readonlyBy: 0 };
906
+ if (!merged.has(keyText))
907
+ merged.set(keyText, slot);
908
+ for (const part of flatten(field.type))
909
+ if (!slot.types.includes(part))
910
+ slot.types.push(part);
911
+ slot.declaredBy += 1;
912
+ if (!field.optional)
913
+ slot.requiredBy += 1;
914
+ if (field.readonly)
915
+ slot.readonlyBy += 1;
916
+ }
917
+ }
918
+ const undefinedType = typeOf(checker.getUndefinedType());
919
+ const members = [...merged.values()].map((slot) => {
920
+ const optional = slot.requiredBy < family.members.length;
921
+ const types = optional && !slot.types.includes(undefinedType) ? [...slot.types, undefinedType] : slot.types;
922
+ const only = types.length === 1 ? types[0] : undefined;
923
+ return {
924
+ key: slot.key,
925
+ type: only ?? table.intern({ kind: 'union', members: types }),
926
+ optional,
927
+ readonly: slot.readonlyBy === slot.declaredBy,
928
+ accessor: null
929
+ };
930
+ });
931
+ return { kind: 'object', members, index: [], membersDropped: false };
932
+ };
933
+ const erasedTypeArgument = () => table.intern({ kind: 'primitive', primitive: 'any' });
934
+ /**
935
+ * The class copy this view is inside, or `null` when the view binds no copy
936
+ * of it.
937
+ *
938
+ * The LAST step naming the class wins, which is the precedence
939
+ * `createPathBinding` (structural-generics.ts) already gives the type
940
+ * parameters that step binds. A path can name one owner twice --
941
+ * `copyPathOf` appends the copy a site names onto the copy the site sits
942
+ * inside, so `new Box<R>(...)` written inside `Box<T>` is walked at
943
+ * `[Box#0, Box#1]` -- and taking the first there bound `T` from one copy
944
+ * while calling the other's constructor object a `Box<T>`.
945
+ */
946
+ const copyOfClassInPath = (owner) => {
947
+ for (let index = bindingPath.length - 1; index >= 0; index -= 1) {
948
+ const step = bindingPath[index];
949
+ if (!step || step.owner !== owner)
950
+ continue;
951
+ const copy = specializations.specializationsOf(owner)[step.ordinal];
952
+ return copy ? { ordinal: copy.ordinal, arguments: copy.arguments } : null;
953
+ }
954
+ return null;
955
+ };
956
+ /**
957
+ * The copy of the class this view is inside, with its fillings folded
958
+ * through the class's layout-relevant indices exactly as the instance
959
+ * anchor folds a written instantiation -- the arguments the copy's
960
+ * constructor object is read AT. `null` when the view is inside no copy
961
+ * of the class. Recorded against the copy's ordinal for the deriver
962
+ * (`classCopies`) once the anchor is reserved, by `recordClassCopy`.
963
+ */
964
+ const foldedCopyOf = (owner, layoutRelevant) => {
965
+ const copy = copyOfClassInPath(owner);
966
+ if (!copy)
967
+ return null;
968
+ return {
969
+ ordinal: copy.ordinal,
970
+ typeArguments: copy.arguments.map((argument, index) => layoutRelevant && !layoutRelevant.has(index) ? erasedTypeArgument() : typeOf(argument))
971
+ };
972
+ };
973
+ const recordClassCopy = (root, ordinal, typeArguments, constructor) => {
974
+ const known = classCopyKeys.get(root) ?? new Map();
975
+ if (!known.has(ordinal))
976
+ known.set(ordinal, { ordinal, typeArguments, constructor });
977
+ classCopyKeys.set(root, known);
978
+ };
979
+ const buildDeclaredShape = (type, declared, typeArguments) => {
980
+ const { kind, declaration } = declared;
981
+ if (kind === 'declared') {
982
+ return { kind, declaration, typeArguments, body: familyBodyOf(declared) ?? declaredBodyOf(type, declared.declarationNode) };
983
+ }
984
+ if (kind === 'class-constructor') {
985
+ // An overloaded constructor's IMPLEMENTATION declares the one frame the
986
+ // body runs with -- see `constructorImplementationSignatureOf`. Asked
987
+ // before the checker's own answer below, which is every overload and no
988
+ // single convention, exactly as `valueTypeAt` asks
989
+ // `implementationSignatureOf` before the symbol-level answer for a
990
+ // method's overload set.
991
+ const implementation = constructorImplementationSignatureOf(checker, declared.declarationNode);
992
+ const constructSignatures = implementation ? [implementation] : type.getConstructSignatures();
993
+ return {
994
+ kind,
995
+ declaration,
996
+ typeArguments,
997
+ // The constructor object's calling convention is what `new` invokes;
998
+ // a constructor value carrying no signature has no convention to
999
+ // select, and every construction fails closed.
1000
+ construct: constructSignatures.length > 0
1001
+ ? table.intern({ kind: 'signature', call: [], construct: constructSignatures.map((one) => signatureOf(one)) })
1002
+ : null
1003
+ };
1004
+ }
1005
+ // A class reached only as a field type has no constructor event to publish
1006
+ // its base's storage. Intern that checker-authenticated ancestry here so
1007
+ // the final carrier closure can resolve it without flattening inheritance.
1008
+ if (type.isClassOrInterface())
1009
+ for (const base of checker.getBaseTypes(type))
1010
+ typeOf(base);
1011
+ return { kind, declaration, typeArguments, body: classInstanceBodyOf(type, declared.declarationNode) };
1012
+ };
1013
+ // `keyof` reads its answer back out of the sealed table, so the table is the
1014
+ // only thing it needs from this closure -- which is why it lives on its own.
1015
+ const keyofOfShapeId = createKeyofResolver(table);
1016
+ function typeOf(type) {
1017
+ // Assignment-connected record views must agree before any layout is
1018
+ // interned, including the element reached through an array or tuple.
1019
+ const storage = storageTypeOf(type);
1020
+ if (storage !== type)
1021
+ return typeOf(storage);
1022
+ // A mapped type that changes only modifiers is its SOURCE, physically --
1023
+ // see `modifierOnlyMappedSourceOf`. Answered before the alias-recurrence
1024
+ // guard, because the point is that there is no recursion here at all:
1025
+ // `Mutable<T>` never was a second object for the walk to re-enter.
1026
+ const modifierOnly = modifierOnlyMappedSourceOf(type);
1027
+ if (modifierOnly)
1028
+ return typeOf(modifierOnly);
1029
+ return aliasRecurrence.within(type, () => typeOfWalk(type), foldToAncestor, (reason) => unresolved(reason));
1030
+ }
1031
+ /**
1032
+ * The id a recurring alias instantiation resolves to: its ancestor's, which
1033
+ * closes the cycle instead of unrolling it (`structural-alias-recurrence.ts`).
1034
+ * The cases are the three states the ancestor's own walk can be in; only the
1035
+ * last is new, and it reuses the retry a directly self-referential type takes.
1036
+ */
1037
+ function foldToAncestor(ancestor) {
1038
+ const done = completed.get(ancestor);
1039
+ if (done)
1040
+ return done;
1041
+ const pending = inProgress.get(ancestor);
1042
+ if (pending)
1043
+ return pending;
1044
+ if (walking.has(ancestor))
1045
+ throw selfReferentialSignal(ancestor);
1046
+ return unresolved(`a recurring type alias ${ancestor.aliasSymbol?.name ?? '(unnamed)'} resolved to an ancestor whose own walk had already unwound`);
1047
+ }
1048
+ function typeOfWalk(type) {
1049
+ const done = completed.get(type);
1050
+ if (done)
1051
+ return done;
1052
+ const shared = sharedCompleted.get(type);
1053
+ if (shared !== undefined)
1054
+ return remember(type, shared);
1055
+ const pending = inProgress.get(type);
1056
+ if (pending)
1057
+ return pending;
1058
+ // Re-entered while its own walk is still running, with no anchor to resolve
1059
+ // to: unwind to that walk's own frame, which retries under an anchor.
1060
+ if (walking.has(type))
1061
+ throw selfReferentialSignal(type);
1062
+ if (selfReferential.has(type)) {
1063
+ // `fresh` is the table's own answer to who owns this reservation. A walk
1064
+ // that did not create it must not complete it and must not abandon it:
1065
+ // the anchor is either finished already or being built by an outer frame,
1066
+ // and in both cases the id alone is the whole answer here.
1067
+ // The ordinal is local to this mapper view, while anchors live in the
1068
+ // compilation-wide table. Include both view paths so unrelated recursive
1069
+ // types cannot reuse another view's `self-referential:0`, and an open
1070
+ // type translated under different bindings keeps its own layout.
1071
+ // -- unless no binding can reach the type at all, in which case every
1072
+ // view closes the cycle at one anchor (`createViewIndependentRecurrence`).
1073
+ const sharedKey = viewIndependentKeyOf(type);
1074
+ const recurrenceKey = sharedKey ?? `${identities.copyKeyOf(path)}|${identities.copyKeyOf(bindingPath)}|${selfReferentialKeyOf(selfReferentialKeys, type)}`;
1075
+ const { id: anchor, fresh } = table.anchor(recurrenceKey);
1076
+ if (!fresh)
1077
+ return remember(type, anchor);
1078
+ inProgress.set(type, anchor);
1079
+ walking.add(type);
1080
+ let settled = false;
1081
+ let completedShape = { kind: 'unresolved', reason: 'a self-referential type of this shape is not modelled' };
1082
+ try {
1083
+ // A declared name (class instance, class constructor, interface, type
1084
+ // alias) whose OWN type argument mentions it again -- see
1085
+ // `buildDeclaredShape`'s docstring for the concrete three.js case --
1086
+ // is not an anonymous cycle `selfReferentialShapeOf` needs to know a
1087
+ // fourth shape for: it is one of the three shapes the ordinary
1088
+ // declared-anchor path already builds, just reached through the one
1089
+ // path that cannot compute its own anchor key up front. The anchor
1090
+ // for `type` is already reserved above, so recomputing its type
1091
+ // arguments here resolves any mention of `type` itself through
1092
+ // `inProgress` instead of recursing.
1093
+ const declared = declaredAnchorOf(type);
1094
+ // An Array or a tuple is shaped as one HERE too, ahead of the
1095
+ // declared-name path -- see `indexedShapeOf`'s own comment for what
1096
+ // reaching this frame first used to cost. The anchor is already
1097
+ // reserved, so the element's own walk resolves a mention of `type`
1098
+ // through `inProgress` exactly as `buildDeclaredShape`'s does.
1099
+ const shape = bagShapeOfType(typeOf, bags, type) ??
1100
+ indexedShapeOf(type) ??
1101
+ (declared
1102
+ ? buildDeclaredShape(type, declared, typeArgumentsOf(type).map(typeOf))
1103
+ : selfReferentialShapeOf(checker, type, typeOf, tupleElementsOf, indexesOf, (one) => selfReferentialCallableShapeOf(one, signatureOf)));
1104
+ completedShape = shape ?? completedShape;
1105
+ table.complete(anchor, completedShape);
1106
+ settled = true;
1107
+ }
1108
+ finally {
1109
+ walking.delete(type);
1110
+ inProgress.delete(type);
1111
+ if (!settled)
1112
+ table.abandon(anchor);
1113
+ }
1114
+ // A cycle another view already closed, entered here at a different
1115
+ // member, reaches through `sharedCompleted` a shape the table holds
1116
+ // under an earlier id. That shape cites nothing of this walk -- one
1117
+ // citing the fresh anchor could equal no earlier shape -- so the
1118
+ // earlier id is the answer and the anchor stays uncited: one cycle,
1119
+ // one set of ids, whichever member a view happened to enter at.
1120
+ const canonical = table.intern(completedShape);
1121
+ if (sharedKey !== null)
1122
+ sharedCompleted.set(type, canonical);
1123
+ return remember(type, canonical);
1124
+ }
1125
+ walking.add(type);
1126
+ // Only the OUTERMOST attempt journals: the frame the signal names is the
1127
+ // one whose retry redoes the work.
1128
+ const outermost = journal === null;
1129
+ const attempt = journal ?? [];
1130
+ journal = attempt;
1131
+ const mark = attempt.length;
1132
+ try {
1133
+ return translate(type);
1134
+ }
1135
+ catch (error) {
1136
+ if (!isSelfReferentialSignal(error) || error.selfReferentialType !== type)
1137
+ throw error;
1138
+ // Withdrawn before the retry: these name anchors that no longer exist.
1139
+ //
1140
+ // Deleting the `completed` memo is enough for anything this SAME walk
1141
+ // built by plain interning: a member id baked into its structural key,
1142
+ // so a shape that no longer resolves the same way mints a new id on its
1143
+ // own. It is not enough for a DECLARED type that finished its own build
1144
+ // successfully inside this failed attempt -- one that read a sibling
1145
+ // anchor's id while that sibling was still open (a legitimate
1146
+ // self-reference at the time, e.g. `MessageEvent.source` reading
1147
+ // `Window`'s in-progress anchor while `Window`'s own build was still
1148
+ // running). That declared type's OWN build never threw, so `translate`'s
1149
+ // finally never abandoned it; it is sitting there complete, citing an id
1150
+ // that is about to become an abandoned, unresolved stub. Its table KEY
1151
+ // has to be released too (`releaseKey`, a no-op for anything that is not
1152
+ // an anchor key), so the next `typeOf` call for it does not silently
1153
+ // reuse a shape built on a since-abandoned sibling and instead rebuilds
1154
+ // against whatever that sibling's retry actually resolves to.
1155
+ for (const remembered of attempt.slice(mark)) {
1156
+ const rememberedId = completed.get(remembered);
1157
+ completed.delete(remembered);
1158
+ if (rememberedId && table.citesAbandoned(rememberedId))
1159
+ table.releaseKey(rememberedId);
1160
+ }
1161
+ attempt.length = mark;
1162
+ selfReferential.add(type);
1163
+ }
1164
+ finally {
1165
+ walking.delete(type);
1166
+ if (outermost)
1167
+ journal = null;
1168
+ }
1169
+ // Retry inside the alias-recurrence frame that owns this walk. Calling
1170
+ // `typeOf` here would enter `aliasRecurrence.within` again before the
1171
+ // outer frame's `finally` has popped the same alias. The recurrence guard
1172
+ // would then find an ancestor whose failed walk has stopped walking but
1173
+ // whose retry has not reserved its anchor yet, and publish an unresolved
1174
+ // carrier instead of taking the self-referential branch above.
1175
+ //
1176
+ // The retry itself must bypass only that already-active outer guard. Every
1177
+ // nested type reached while rebuilding still enters through `typeOf`, so
1178
+ // equivalent back edges fold to the new `inProgress` anchor and a changed
1179
+ // alias instantiation continues to refuse fail-closed.
1180
+ return typeOfWalk(type);
1181
+ }
1182
+ /**
1183
+ * A type reference's OWN type arguments.
1184
+ *
1185
+ * `checker.getTypeArguments` answers with the reference's full argument list,
1186
+ * and for a target that declares a `this` type -- which every class and every
1187
+ * interface reached through one does -- that list carries one MORE entry than
1188
+ * the declaration has parameters: a trailing slot holding the reference's
1189
+ * `this` type, threaded through as an argument that no source ever writes.
1190
+ *
1191
+ * `super.has(name)` inside `class CaseInsensitiveMap<K extends string>
1192
+ * extends Map<K, string>` is the case that exposed it. The `Map` reference
1193
+ * answers THREE arguments -- `K`, `string`, `this` -- and
1194
+ * `representation/collections.ts`'s arity guard then refused, correctly, a
1195
+ * `map` that "needs exactly 2". The guard was right and the count was wrong.
1196
+ *
1197
+ * The declaration's own parameter list is the authority on how many arguments
1198
+ * a reference to it has, so the answer is cut to it. Cutting rather than
1199
+ * asserting: a target with no `typeParameters` at all (a tuple reached
1200
+ * through this path, an anonymous reference) is left exactly as the checker
1201
+ * answered.
1202
+ */
1203
+ const typeArgumentsOf = (type) => {
1204
+ const reference = type;
1205
+ const args = checker.getTypeArguments(reference) ?? [];
1206
+ const declared = reference.target?.typeParameters?.length;
1207
+ return declared !== undefined && args.length > declared ? args.slice(0, declared) : args;
1208
+ };
1209
+ /**
1210
+ * Whether an alias symbol IS one of the standard library's own type-level
1211
+ * operators, by name -- `null` in a program whose lib does not declare it.
1212
+ *
1213
+ * Resolved lazily and once per name, in the scope of the alias declaration
1214
+ * being asked about, exactly the way `host-protocols.ts`'s
1215
+ * `promiseDeclarationOf` resolves `Promise`: the question is "does this
1216
+ * alias mean the language's own operator", and `checker.resolveName` is the
1217
+ * public API that answers it without a use site. Resolving by name rather
1218
+ * than trusting the spelling is the whole point -- a program's own
1219
+ * `type Awaited<T> = ...` is a different operator with the same name.
1220
+ */
1221
+ const globalAliases = new Map();
1222
+ const isGlobalAlias = (name, symbol, at) => {
1223
+ if (!globalAliases.has(name))
1224
+ globalAliases.set(name, checker.resolveName(name, at, ts.SymbolFlags.TypeAlias, false) ?? null);
1225
+ const resolved = globalAliases.get(name) ?? null;
1226
+ return resolved !== null && resolved === symbol;
1227
+ };
1228
+ /**
1229
+ * The one type-level operator argument, if this type is one of the two the
1230
+ * checker can still evaluate, and its own single argument.
1231
+ */
1232
+ const operatorArgument = (type, name) => {
1233
+ const alias = type.aliasSymbol;
1234
+ const argument = type.aliasTypeArguments?.[0];
1235
+ if (!alias || !argument || type.aliasTypeArguments?.length !== 1)
1236
+ return null;
1237
+ const at = alias.declarations?.[0];
1238
+ return at && isGlobalAlias(name, alias, at) ? argument : null;
1239
+ };
1240
+ /**
1241
+ * This copy's filling for a type, closed as far as anything here can close it.
1242
+ *
1243
+ * Three ways, tried in order, and the third is what makes the operators
1244
+ * below compose. The image is the checker's own instantiation of a copy's
1245
+ * member type (`structural-instantiated-member.ts`); the path substitution
1246
+ * answers for a bare parameter a copy binds; and the recursion answers for a
1247
+ * parameter wrapped in one of the operators -- `NonNullable<TSchema>` closes
1248
+ * because `TSchema` does.
1249
+ */
1250
+ const closedForm = (type) => {
1251
+ const image = instantiatedMembers.through(type);
1252
+ if (image)
1253
+ return image;
1254
+ const substituted = substituteTypeParameter(type);
1255
+ if (substituted !== type)
1256
+ return substituted;
1257
+ return reducedOperator(type);
1258
+ };
1259
+ /**
1260
+ * A DEFERRED `Awaited<T>` or `NonNullable<T>`, re-asked of the checker with
1261
+ * this copy's own filling in place of the hole.
1262
+ *
1263
+ * `await fn()` inside `withRespawn<T>(fn: () => Promise<T>)` types as
1264
+ * `Awaited<T>`. The checker cannot reduce `T extends PromiseLike<infer U>`
1265
+ * while `T` is open, so it keeps the conditional unreduced -- and a
1266
+ * conditional type names no structure, so everything downstream of it
1267
+ * refused: the await's own result, the `const` it initializes, the `return`
1268
+ * that publishes it. mongodb's driver is generic almost everywhere and this
1269
+ * was its single largest root, 616 of its mandatory obligations.
1270
+ *
1271
+ * Monomorphization has already closed the hole this walk is inside, so the
1272
+ * reduction is not deferred any more -- only the checker's ability to spell
1273
+ * it as a type is. `getAwaitedType` and `getNonNullableType` are the
1274
+ * checker's OWN implementations of the two operators, so handing one the
1275
+ * closed argument asks precisely the question that was deferred, rather than
1276
+ * re-deriving an answer beside the language's. Nothing is reduced when the
1277
+ * argument is still open, and an answer that comes back conditional again is
1278
+ * discarded: both leave the shape exactly as it was.
1279
+ *
1280
+ * These are the ONLY two this layer reduces, and the reason is the same for
1281
+ * both: the checker exposes the operator. `resolvedTrueType`/
1282
+ * `resolvedFalseType` on a deferred `ts.ConditionalType` are lazily populated
1283
+ * and read `undefined` from outside the checker, so a general "pick the
1284
+ * branch the closed check type satisfies" rule has no branches to pick --
1285
+ * measured, not assumed. `T[number]` is refused here for the mirror-image
1286
+ * reason: `getIndexedAccessType` is not on the public checker at all.
1287
+ *
1288
+ * `NonNullable` is NOT gated on `TypeFlags.Conditional`, and that is not an
1289
+ * oversight: since TypeScript 4.8 it is spelled `T & {}`, so a deferred one
1290
+ * arrives as an INTERSECTION. mongodb's `abstract_cursor.ts` is the case --
1291
+ * `transformDocument(document: NonNullable<TSchema>): Promise<NonNullable<TSchema>>`,
1292
+ * awaited at four sites in six copies -- and gating on the flag is what left
1293
+ * it unreduced while the bare `Awaited<TSchema>` beside it reduced fine.
1294
+ */
1295
+ const reducedOperator = (type) => {
1296
+ const awaited = operatorArgument(type, 'Awaited');
1297
+ if (awaited) {
1298
+ const closed = closedForm(awaited);
1299
+ const reduced = closed ? checker.getAwaitedType(closed) : null;
1300
+ return reduced && (reduced.flags & ts.TypeFlags.Conditional) === 0 ? reduced : null;
1301
+ }
1302
+ const nullable = operatorArgument(type, 'NonNullable');
1303
+ if (nullable) {
1304
+ const closed = closedForm(nullable);
1305
+ const reduced = closed ? checker.getNonNullableType(closed) : null;
1306
+ return reduced && (reduced.flags & ts.TypeFlags.Conditional) === 0 ? reduced : null;
1307
+ }
1308
+ return null;
1309
+ };
1310
+ function translate(type) {
1311
+ // Asked BEFORE anything else, because it answers about the very type that
1312
+ // was handed in rather than about its parts: an open member type of a
1313
+ // monomorphized copy has an instantiated image, and every question below --
1314
+ // is it a conditional, a union, a record -- has a different answer for the
1315
+ // image than for the hole. See `structural-instantiated-member.ts`.
1316
+ const instantiated = instantiatedMembers.through(type);
1317
+ if (instantiated)
1318
+ return remember(type, typeOf(instantiated));
1319
+ // ⛔ BEFORE the conditional refusal below, not after it. A deferred
1320
+ // `Awaited<T>` IS a `ts.TypeFlags.Conditional` -- that is what the two
1321
+ // operators are spelled as -- so refusing every conditional first made
1322
+ // this line unreachable for the exact shape it exists to answer, and the
1323
+ // `getAwaitedType` reduction below it only ever ran for a `NonNullable`,
1324
+ // which since TypeScript 4.8 arrives as an INTERSECTION instead.
1325
+ //
1326
+ // `@hono/node-server`'s `readBodyWithFastPath<T>` is the case:
1327
+ // `Promise.resolve(fromBuffer(raw, request))` over a
1328
+ // `(buf, request) => T | Promise<T>` types as
1329
+ // `Promise<Awaited<T | Promise<T>>>`, and the copy that closed `T` got the
1330
+ // refusal rather than the reduction -- 54 of hono-hello's 225 roots, every
1331
+ // one of them a `promise(unresolved)` obligation off those two lines.
1332
+ //
1333
+ // Safe ahead of the refusal because this reads only `aliasSymbol` and
1334
+ // `aliasTypeArguments`, two plain fields on the type object, and calls the
1335
+ // checker only with an argument monomorphization has already CLOSED. What
1336
+ // the refusal is positioned to come before is declared-alias
1337
+ // NORMALIZATION further down, which asks a recursive conditional alias to
1338
+ // instantiate the very form it deferred -- hono's fluent environment
1339
+ // accumulator (`IfAnyThenEmptyObject<...>`, one alias deeper per route)
1340
+ // exhausted TypeScript's stack there. That alias is neither `Awaited` nor
1341
+ // `NonNullable`, so `operatorArgument` rejects it on the name and this
1342
+ // line returns before any checker call.
1343
+ const awaited = reducedOperator(type);
1344
+ if (awaited)
1345
+ return remember(type, typeOf(awaited));
1346
+ // A conditional that still exists after this copy's instantiated-member
1347
+ // image was asked for, and that neither operator above could reduce, is
1348
+ // unresolved.
1349
+ if (type.flags & ts.TypeFlags.Conditional)
1350
+ return remember(type, unresolved('an anonymous conditional type is still gated on a type parameter; monomorphization never filled it', 'erased-type-expression'));
1351
+ const primitive = primitiveFor(type);
1352
+ if (primitive)
1353
+ return remember(type, table.intern(primitive));
1354
+ const literal = literalFor(type);
1355
+ if (literal)
1356
+ return remember(type, table.intern(literal));
1357
+ const bag = bagShapeOfType(typeOf, bags, type);
1358
+ if (bag)
1359
+ return remember(type, table.intern(bag));
1360
+ // The global `Object` INTERFACE is a top type, and its layout is a
1361
+ // fiction.
1362
+ //
1363
+ // `Object` declares only what every value already has -- `toString`,
1364
+ // `valueOf`, `hasOwnProperty` -- and every non-nullish value in the
1365
+ // language is assignable to it, so it states nothing about what a
1366
+ // particular cell holds. `derived-expression-type.ts`'s
1367
+ // `annotationStatesNothing` has said exactly that for a long time, and
1368
+ // three's `@type {Object}` / `@return {Object}` tags reach this very
1369
+ // interface -- but only the write-discovery CENSUSES consulted it, so
1370
+ // this layer went on interning `Object` as a `declared` shape with a
1371
+ // real body, and `representation/derive.ts` went on turning that body
1372
+ // into a `native-record-ref` naming a struct of prototype methods. Two
1373
+ // authorities, one saying "states nothing" and the other emitting a
1374
+ // layout for it.
1375
+ //
1376
+ // Nothing can be stored in that struct. On the three.js app it was the target
1377
+ // of 11 of the 29 unmet conversion obligations whose pair simply has no
1378
+ // node -- `boolean`, an `HTMLElement` handle, an object literal and an
1379
+ // array of class instances all flowing into a cell typed `?Object` --
1380
+ // and no conversion could exist for any of them, because the target
1381
+ // layout was never real.
1382
+ //
1383
+ // `any` is the honest carrier, and it is the box: a genuinely dynamic
1384
+ // boundary, which is what `Object` is. The `ObjectConstructor` interface
1385
+ // -- the type of the global `Object` VALUE -- is excluded by
1386
+ // `isGlobalObjectInterface`'s own construct-signature test, so
1387
+ // `Object.keys` and friends keep their real callable shape.
1388
+ //
1389
+ // Anchored on the type's own declaration purely because `resolveName`
1390
+ // needs some node to resolve a GLOBAL from; which node it is cannot
1391
+ // change the answer, and a user interface declaring the same members
1392
+ // still fails the declaration-identity test.
1393
+ const objectAnchor = type.getSymbol()?.declarations?.[0];
1394
+ if (objectAnchor && isGlobalObjectInterface(checker, objectAnchor, type)) {
1395
+ return remember(type, table.intern({ kind: 'primitive', primitive: 'any' }));
1396
+ }
1397
+ // `IArguments` is the checker's name for the `arguments` object, and the
1398
+ // `arguments` object IS the phantom rest array this compiler mints for a
1399
+ // body that reads it (`producers/bindings.ts`'s `argumentsObjectValueAt`
1400
+ // binds the reference to that array). A function returning `arguments`
1401
+ // therefore returns that array, and typing the result by the interface's
1402
+ // declared layout (a record with `length` and `callee`) put a second
1403
+ // authority over one value: the body's return carrier said array-object,
1404
+ // the signature's result said native-record-ref, and the return
1405
+ // conversion between them cannot exist.
1406
+ if (objectAnchor && isStandardInterfaceType(checker, objectAnchor, 'IArguments', type)) {
1407
+ return remember(type, table.intern({ kind: 'array', element: table.intern({ kind: 'primitive', primitive: 'any' }), readonly: false, extension: [] }));
1408
+ }
1409
+ if (type.flags & ts.TypeFlags.UniqueESSymbol) {
1410
+ const symbol = type.getSymbol();
1411
+ const declaration = symbol ? identities.declarationOfSymbol(symbol) : null;
1412
+ return remember(type, declaration
1413
+ ? table.intern({ kind: 'unique-symbol', declaration: identities.declarationIdOf(declaration) })
1414
+ : unresolved('unique symbol without a declaration anchor'));
1415
+ }
1416
+ // `TypeParameter` extends `Type` with no extra members, so the predicate
1417
+ // `this is TypeParameter` narrows the *false* branch to `never` and hides
1418
+ // every later check. The flag carries the same fact without that collapse.
1419
+ if (type.flags & ts.TypeFlags.TypeParameter) {
1420
+ const symbol = type.getSymbol();
1421
+ const declaration = symbol ? identities.declarationOfSymbol(symbol) : null;
1422
+ // The polymorphic `this` type is a type parameter whose symbol is the
1423
+ // *class*, not a `TypeParameterDeclaration`. It is not a parameter a
1424
+ // caller instantiates: every value it can hold is an instance of that
1425
+ // class, so the class instance shape is its exact answer rather than an
1426
+ // erasure to a constraint. Treating it as an uninstantiated parameter is
1427
+ // what made every unannotated `this.field` read reach representation with
1428
+ // no carrier at all.
1429
+ //
1430
+ // JavaScript declares the same thing without the `class` keyword.
1431
+ // `function Renderer(gl) { this.setMode = setMode }`, called with `new`,
1432
+ // is a constructor function: the binder marks its symbol
1433
+ // `SymbolFlags.Class` alongside `Function`, `getDeclaredTypeOfSymbol`
1434
+ // answers with the inferred instance type exactly as it does for a
1435
+ // class -- and its declaration is a `FunctionDeclaration`, so
1436
+ // `isClassLike` alone said no. three.js's WebGL internals are written
1437
+ // this way throughout, and every `this.` inside one reached
1438
+ // representation as an uninstantiated parameter: 151 of the three.js app's root
1439
+ // diagnostics. The flag is checked rather than the syntax because the
1440
+ // syntax is the only thing that differs.
1441
+ if (symbol && declaration && (ts.isClassLike(declaration) || (symbol.flags & ts.SymbolFlags.Class) !== 0)) {
1442
+ // Routed through the class's own declared type rather than interned
1443
+ // here, so the anchor that makes recursive member walks terminate is the
1444
+ // one shared with every other mention of the class. Interning a second
1445
+ // shape under the same nominal key would race that anchor's completion.
1446
+ return remember(type, typeOf(checker.getDeclaredTypeOfSymbol(symbol)));
1447
+ }
1448
+ if (!declaration)
1449
+ return remember(type, unresolved('type parameter without a declaration anchor'));
1450
+ // What the copy this body belongs to binds the parameter to. This is the
1451
+ // monomorphization: `identity<T>` compiled inside copy 0 has `T` as
1452
+ // `number` and inside copy 1 as `string`, and both are exact rather than
1453
+ // an approximation, because each copy really is a separate function in
1454
+ // the language.
1455
+ //
1456
+ // The program-wide census answers the remaining case: a parameter bound
1457
+ // once everywhere, whose owner the census did not copy -- an ambient
1458
+ // declaration has no body to duplicate, so there is no copy for the path
1459
+ // to name and the unique binding is the whole answer.
1460
+ //
1461
+ // The substitution happens here, at the one place a type parameter is
1462
+ // turned into a shape, rather than in the deriver. A shape is what every
1463
+ // later stage keys on -- carriers, conventions, layouts -- so a parameter
1464
+ // substituted downstream would leave the graph citing one shape and the
1465
+ // representation another, which is the two-authorities defect this
1466
+ // architecture exists to avoid.
1467
+ const bound = boundByPath(declaration) ?? censusBindingOf(declaration);
1468
+ if (bound && bound !== type)
1469
+ return remember(type, typeOf(bound));
1470
+ // A parameter nothing bound, but that the author gave a DEFAULT, is not
1471
+ // an uninstantiated parameter: the language substitutes the default for
1472
+ // every reference that omits the argument, so `class App extends
1473
+ // Component` really is `Component<GeaElement>` and the checker has
1474
+ // already typed it that way. Reading it here keeps the shape and the
1475
+ // checker in agreement -- without it the un-monomorphized copy of the
1476
+ // base carried a naked parameter into its own field layout, which the
1477
+ // deriver correctly refused ("field \"el\" carries unresolved(type
1478
+ // parameter ... reached representation without monomorphization)") and
1479
+ // which cost `ttf-bench` its whole emission.
1480
+ //
1481
+ // After the two bindings above on purpose: a copy that really did
1482
+ // substitute something must keep what it substituted, and the default is
1483
+ // only the answer when nothing did.
1484
+ //
1485
+ // Measured cost, stated rather than hidden: three programs that import
1486
+ // `three` gain ~3,400 boxed carriers, because `lib.dom`'s `E = Element`
1487
+ // and `lib.es5`'s `TArrayBuffer = ArrayBuffer` resolve to types no host
1488
+ // table claims a carrier for. None of the three compiles either way, and
1489
+ // before this they were the same values counted as missing primitives
1490
+ // rather than as boxes -- neither state is native, and the cure for both
1491
+ // is a carrier for `Element`, not a naked type parameter. Excluding
1492
+ // defaults of `any` was tried and measured: it moved the number by 32.
1493
+ //
1494
+ // The default is asked of THIS parameter, not re-typed from its
1495
+ // declaration node. A method's default can name the enclosing
1496
+ // interface's parameter -- `Promise<T>.then<TResult1 = T, ...>` -- and
1497
+ // reading the node `= T` in the declaration's own scope hands back
1498
+ // `Promise`'s open `T` even when the receiver was `Promise<Response>`
1499
+ // and the checker had already instantiated the default to `Response`.
1500
+ // That open `T` reached representation through a promise method read as
1501
+ // a VALUE with no call to bind it -- `@hono/node-server`'s `isPromise`
1502
+ // (`typeof (res as Promise<Response>).then === 'function'`) -- and the
1503
+ // function-value carrier `(...)->promise(unresolved)` had no emitter
1504
+ // recipe. `getDefaultFromTypeParameter` returns the instantiated default
1505
+ // where one exists and the declaration's own where it does not, so the
1506
+ // measured cases above are unchanged.
1507
+ if (ts.isTypeParameterDeclaration(declaration) && declaration.default) {
1508
+ const instantiated = checker.getDefaultFromTypeParameter(type) ?? checker.getTypeFromTypeNode(declaration.default);
1509
+ return remember(type, typeOf(instantiated));
1510
+ }
1511
+ // A parameter a CALLABLE owns, reached where no copy binds it, is that
1512
+ // callable used as a VALUE: a generic arrow handed to `memoizeOne`, a
1513
+ // generic function passed where the parameter's type is itself generic
1514
+ // (`emitNodeList(emit, ...)` over `EmitFunction = <T extends Node>(node:
1515
+ // T, ...) => void`), or the result the checker propagated such an
1516
+ // argument's parameters into. One closure exists at runtime for all of
1517
+ // those, so its type parameters have exactly one filling, the
1518
+ // constraint -- the same one `specialization.ts`'s `constraintBindingsOf`
1519
+ // mints its copy over, and the one the checker itself lands on when a
1520
+ // call through the value cannot infer the parameter. A class, interface
1521
+ // or alias parameter is not answered this way: those are copied per
1522
+ // instantiation and never reached unbound by a body this compiles.
1523
+ if (ts.isTypeParameterDeclaration(declaration) && ts.isFunctionLike(declaration.parent)) {
1524
+ const constraint = checker.getBaseConstraintOfType(type) ?? checker.getUnknownType();
1525
+ if (constraint !== type)
1526
+ return remember(type, typeOf(constraint));
1527
+ }
1528
+ // A parameter an interface of a FAMILY owns (`Token<TKind extends
1529
+ // SyntaxKind>`), reached while the family's one layout is built from
1530
+ // the open declaration: the layout's field is the union over every
1531
+ // instantiation the program will ever make, and the constraint is that
1532
+ // union's upper bound -- `kind: SyntaxKind`, which is what every
1533
+ // `Token<SyntaxKind.X>` view reads it back through anyway. The census
1534
+ // admits only a constrained parameter, so `unknown` is never the answer.
1535
+ if (ts.isTypeParameterDeclaration(declaration) && ts.isInterfaceDeclaration(declaration.parent)) {
1536
+ const ownerSymbol = checker.getSymbolAtLocation(declaration.parent.name);
1537
+ const owner = ownerSymbol ? identities.declarationOfSymbol(ownerSymbol) : null;
1538
+ if (owner && families.familyOf(identities.declarationIdOf(owner, rootSpecialization))) {
1539
+ const constraint = checker.getBaseConstraintOfType(type) ?? checker.getUnknownType();
1540
+ if (constraint !== type)
1541
+ return remember(type, typeOf(constraint));
1542
+ }
1543
+ }
1544
+ return remember(type, table.intern({ kind: 'type-parameter', declaration: identities.declarationIdOf(declaration) }));
1545
+ }
1546
+ // `keyof T`. `isIndexType` is the public narrowing predicate for the flag,
1547
+ // matching the `isUnion`/`isTupleType` style already used below rather
1548
+ // than reading `.type` off the bare `Type` interface.
1549
+ if (type.isIndexType()) {
1550
+ const baseId = typeOf(type.type);
1551
+ let outcome;
1552
+ try {
1553
+ outcome = keyofOfShapeId(baseId);
1554
+ }
1555
+ catch {
1556
+ // The base is a nominal type whose own body is still being built --
1557
+ // `keyof` reaching back into a declaration it is itself a member of.
1558
+ // The sealed-table read a moment from completing cannot answer that
1559
+ // yet, and reading around it with a second pass would race the
1560
+ // anchor this same walk is in the middle of completing, so this
1561
+ // states the gap instead of throwing out of `typeOf` entirely.
1562
+ outcome = { kind: 'unmodelled', reason: `keyof of ${baseId}, whose declaration has not finished normalizing, is not modelled` };
1563
+ }
1564
+ return remember(type, outcome.kind === 'resolved' ? outcome.id : unresolved(outcome.reason));
1565
+ }
1566
+ // `T[K]`. The checker resolves every concrete indexed access before this
1567
+ // layer sees it, so one reaching here is the generic form -- and the
1568
+ // substitution this copy performs is what makes it concrete.
1569
+ // `structural-indexed-access.ts` states the rest.
1570
+ if ((type.flags & ts.TypeFlags.IndexedAccess) !== 0) {
1571
+ const access = type;
1572
+ const objectType = resolvedObjectType(access.objectType);
1573
+ const indexType = resolvedIndexType(access.indexType);
1574
+ // `any[K]` is `any` and `unknown[K]` is an error the checker already
1575
+ // reported -- neither is a member set to enumerate, and refusing it
1576
+ // reports a gap where the program declared one. hono's `Handler<E = any>`
1577
+ // binds `E` to `any` in one of `Context`'s copies, so `E['Bindings']`
1578
+ // there is the top type by the language's own rule, not a hole this
1579
+ // layer failed to fill. Answering with the object type itself adds no
1580
+ // dynamism: it IS the declared-any the program already carries.
1581
+ if ((objectType.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) !== 0)
1582
+ return remember(type, typeOf(objectType));
1583
+ const substituted = objectType === access.objectType && indexType === access.indexType ? null : indexedAccessMemberTypes(checker, objectType, indexType);
1584
+ // The bound of the type the PROGRAM WROTE is asked before the bound of
1585
+ // what this copy substituted into it, and the two disagree in hono's
1586
+ // favour of the first. `Context<E extends Env>`'s `env: E['Bindings']`
1587
+ // has `Env`'s own `Bindings?: Record<string, unknown>` as its bound
1588
+ // answer -- a dictionary that may be absent, which is what the
1589
+ // declaration says. The substituted intersection's bound is `{}`, which
1590
+ // declares no `Bindings` at all and so answers `undefined` -- and a
1591
+ // cell of `undefined` cannot hold that member's own `= {}` initializer.
1592
+ // Both are upper bounds; the tighter one is not always the truer one,
1593
+ // and the one the author stated outranks the one a copy produced.
1594
+ // A substitution that answers pure ABSENCE steps aside for the bound, and
1595
+ // hono's `env: E['Bindings'] = {}` is why. The copy that binds `E` to
1596
+ // `BlankEnv` (`{}`) really does have no `Bindings` member, so absence is
1597
+ // the language's own answer for a READ there -- but the field's STORAGE
1598
+ // was sized by the declaration, which TypeScript checked against `E`'s
1599
+ // constraint `Env`, where `Bindings?: Record<string, unknown>`. That is
1600
+ // how `= {}` on the same line is legal at all. A copy cannot shrink a
1601
+ // cell below what the declaration it copies admits, so the constraint's
1602
+ // answer outranks the copy's here, and absence survives only when no
1603
+ // bound has anything better to say.
1604
+ const statesOnlyAbsence = substituted !== null && substituted.every((member) => (member.flags & ts.TypeFlags.Undefined) !== 0);
1605
+ const members = (statesOnlyAbsence ? null : substituted) ??
1606
+ memberTypesThroughBound(access.objectType, indexType) ??
1607
+ memberTypesThroughBound(objectType, indexType) ??
1608
+ substituted;
1609
+ const only = members?.length === 1 ? members[0] : undefined;
1610
+ if (only)
1611
+ return remember(type, typeOf(only));
1612
+ if (members)
1613
+ return remember(type, table.intern({ kind: 'union', members: members.map(typeOf) }));
1614
+ return remember(type, unresolved('an indexed access whose object type is still a type parameter has no member set to resolve', 'erased-type-expression'));
1615
+ }
1616
+ if (type.isUnion()) {
1617
+ // A member whose bound type substitutes to `unknown`/`any` in this
1618
+ // copy absorbs the whole union -- `Component<RootElement = unknown>`'s
1619
+ // own `readonly el: RootElement | null` must collapse to bare
1620
+ // `unknown` for the exact same reason `unknown | null` written
1621
+ // directly, with no generic involved, is never a two-member union to
1622
+ // begin with: the checker's own union construction already performs
1623
+ // this simplification (`getUnionType` is not on the public
1624
+ // `ts.TypeChecker` surface, so it is replicated here rather than
1625
+ // called). Only the top type absorbs this way -- `never` is the
1626
+ // bottom type and a `T | never` union does not collapse the same
1627
+ // direction, so it is deliberately not handled here.
1628
+ const absorbing = type.types
1629
+ .map(substituteTypeParameter)
1630
+ .find((candidate) => candidate.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown));
1631
+ if (absorbing)
1632
+ return remember(type, typeOf(absorbing));
1633
+ // An arm naming a type the host says is ABSENT is not an arm this
1634
+ // program can ever take. `absentGlobals` already folds the VALUE
1635
+ // (`typeof HTMLImageElement !== 'undefined'` is `false` on a headless
1636
+ // ANGLE host, `absent-globals.ts`); this is the same fact asked of the
1637
+ // TYPE, so a union declared `HTMLImageElement | HTMLCanvasElement |
1638
+ // ImageData` collapses rather than demanding a carrier for a DOM class
1639
+ // that cannot exist here. Substituting per MEMBER rather than over the
1640
+ // whole union is what lets a mixed union keep the arms that are real.
1641
+ // `never[]` is what an EMPTY ARRAY LITERAL with no contextual type
1642
+ // checks as, and it is assignable to every array type -- so beside
1643
+ // another array-like arm it names no value the union does not already
1644
+ // hold, and no second carrier. `(path.match(/.../g) || [])` (hono's
1645
+ // pattern router) is the shape: `RegExpMatchArray | never[]`, which
1646
+ // carried as a tagged union of a match result and an EMPTY STRUCT, and
1647
+ // an `Array.prototype` method on that has no static receiver at all --
1648
+ // the read fell back to boxing the arm and asking a dynamic
1649
+ // `getProperty("map")` that nothing answers.
1650
+ //
1651
+ // Dropped only when the union keeps an arm that is itself indexable by
1652
+ // number, so a `never[]` standing alone (or beside non-array arms) is
1653
+ // untouched: this removes a REDUNDANT arm, it does not decide that an
1654
+ // empty array is some other type.
1655
+ const numericElementOf = (arm) => checker.getIndexTypeOfType(arm, ts.IndexKind.Number);
1656
+ // Contentless means EMPTY, not merely tuple-shaped: a tuple's numeric
1657
+ // index type is the union of its own elements, so a `[T, Params]` arm
1658
+ // answers a real element type and is a distinct shape this must not
1659
+ // touch (`Result<T>`'s two arms in hono's own router are a 1-tuple and a
1660
+ // 2-tuple). The two contentless spellings are `never[]` and the
1661
+ // zero-length tuple `[]`, which is what `x.match(re) || []` derives:
1662
+ // 13.2.4.2 gives an ArrayLiteral with no elements an Array of length 0,
1663
+ // and a value with no element cannot disagree with any element type, so
1664
+ // it is already a value of the arm beside it.
1665
+ const isEmptyArrayArm = (arm) => {
1666
+ // `isArrayType` answers only for `Array<T>` -- a tuple is an array-LIKE
1667
+ // whose target is its own synthetic type -- so the tuple is asked first.
1668
+ if (checker.isTupleType(arm)) {
1669
+ const shape = arm.target;
1670
+ return shape.fixedLength === 0 && shape.elementFlags.length === 0;
1671
+ }
1672
+ if (!checker.isArrayType(arm))
1673
+ return false;
1674
+ const element = checker.getTypeArguments(arm)[0];
1675
+ return element !== undefined && (element.flags & ts.TypeFlags.Never) !== 0;
1676
+ };
1677
+ const withoutEmptyArrays = type.types.filter((arm) => !isEmptyArrayArm(arm));
1678
+ const arms = withoutEmptyArrays.length === type.types.length ||
1679
+ withoutEmptyArrays.length === 0 ||
1680
+ !withoutEmptyArrays.some((arm) => numericElementOf(arm) !== undefined)
1681
+ ? type.types
1682
+ : withoutEmptyArrays;
1683
+ const sole = arms.length === 1 ? arms[0] : undefined;
1684
+ if (sole)
1685
+ return remember(type, typeOf(absent.substituteAbsentType(sole)));
1686
+ const present = arms.map((member) => absent.substituteAbsentType(member));
1687
+ // A union of pure INDEX-SIGNATURE objects is one table whose values are
1688
+ // the union. `Record<string, string> | Record<string, string[]>` (hono's
1689
+ // `_getQueryParam`, `utils/url.ts:255`) describes one object either way:
1690
+ // the arms differ in what an entry HOLDS, never in how entries are
1691
+ // stored, so the physical answer is a single `gea::Dictionary` over the
1692
+ // union of the value types. A tagged union of two dictionaries is the
1693
+ // wrong shape for it, and provably so: `results[name] = []` writes an
1694
+ // array through a carrier whose tag says the entries are strings, which
1695
+ // no per-arm dispatch can make correct -- there is one object and its
1696
+ // tag was fixed when `{}` was allocated.
1697
+ const table_ = joinedIndexUnionOf(checker, table, typeOf, present);
1698
+ return remember(type, table_ ?? table.intern({ kind: 'union', members: present.map(typeOf) }));
1699
+ }
1700
+ if (type.isIntersection()) {
1701
+ // The alias's own anchor, recorded beside the members rather than instead
1702
+ // of them: a branded alias (`type Rgb565 = number & { readonly
1703
+ // __geaRgb565: unique symbol }`) erases to its substantive member, and
1704
+ // the name is the only thing left that says which host type it is. This
1705
+ // still interns and derives as an intersection -- `derive.ts` reads the
1706
+ // anchor only where an installed host states a carrier for it.
1707
+ const anchor = declaredAnchorOf(type);
1708
+ const declaration = anchor?.kind === 'declared' ? anchor.declaration : null;
1709
+ // A type guard's `Member & { field: Narrower }` is the family object
1710
+ // itself -- see `familyMemberNarrowedBy`. Asked before the members are
1711
+ // interned: the narrowing's own object literal would otherwise be laid
1712
+ // out as a record nothing converts the family reference into. Asked
1713
+ // for a NAMED intersection too (`type LiteralImportTypeNode =
1714
+ // ImportTypeNode & { readonly argument: LiteralTypeNode & { ... } }`):
1715
+ // the alias names a view, and the anchor a branded alias keeps below
1716
+ // never applies -- a family member is never a brand's substantive half.
1717
+ const narrowedMember = familyMemberNarrowedBy(type);
1718
+ if (narrowedMember !== null)
1719
+ return remember(type, narrowedMember);
1720
+ const members = type.types.map(typeOf);
1721
+ const joined = declaration === null ? joinedCallableOf(table, type, members) : null;
1722
+ if (joined)
1723
+ return remember(type, joined);
1724
+ const distributed = declaration === null ? distributedIntersectionOf(members) : null;
1725
+ if (distributed !== null)
1726
+ return remember(type, distributed);
1727
+ // The checker's own reconciliation of the members, interned beside them.
1728
+ // See the `resolved` field's doc comment (`model/structural-types.ts`):
1729
+ // reading `A & B`'s members off the intersection TYPE is asking the one
1730
+ // authority that owns the reduction, instead of merging carriers pairwise
1731
+ // a layer later.
1732
+ // A deferred member means the checker has not reconciled this
1733
+ // intersection. Asking for its synthesized properties forces the
1734
+ // checker to instantiate the deferred conditional recursively and also
1735
+ // gives each equivalent unfolding a fresh resolved shape. Keep the
1736
+ // explicit members as the fail-closed answer until monomorphization has
1737
+ // supplied an instantiated image. This lets recursive generic APIs fold
1738
+ // on their physical member layout instead of expanding type-only fluent
1739
+ // history indefinitely.
1740
+ const resolved = carriesDeferredForm(type) ? null : table.intern(objectShapeOf(type, null, 'interface'));
1741
+ return remember(type, table.intern({ kind: 'intersection', members, declaration, resolved }));
1742
+ }
1743
+ const indexed = indexedShapeOf(type);
1744
+ if (indexed)
1745
+ return remember(type, table.intern(indexed));
1746
+ const declared = declaredAnchorOf(type);
1747
+ if (declared) {
1748
+ // Anchor before walking members. Every cycle in the type graph passes
1749
+ // through a declared name, so this is the one place that makes recursion
1750
+ // terminate: a member that refers back resolves to an id that already
1751
+ // exists instead of re-entering translation.
1752
+ // The key uses the arguments' canonical structural ids, not the checker's
1753
+ // type objects: the checker hands back a fresh object for each mention of
1754
+ // one instantiation, so object identity would mint a new anchor per member
1755
+ // and the member walk below would never converge.
1756
+ //
1757
+ // A class or interface's own type parameter that never reaches a stored
1758
+ // field -- `layoutRelevantParameterIndices`'s own question -- is folded
1759
+ // to one canonical placeholder instead of its real argument. Two
1760
+ // instantiations that disagree ONLY on such a parameter (hono's
1761
+ // `Hono<E,S,BasePath,CurrentPath>` across every distinct route
1762
+ // registration, `S` never stored) are the SAME physical layout, and
1763
+ // keying them apart mints one specialization per call site -- the
1764
+ // shape of the `#addRoute` producer stack overflow this exists to cut
1765
+ // off. `Context<E,...>`'s `env: E['Bindings']` keeps `E` unerased: an
1766
+ // unproven position is never folded, only one the field walk actually
1767
+ // proved irrelevant.
1768
+ const genericOwner = ts.isClassLike(declared.declarationNode) || ts.isInterfaceDeclaration(declared.declarationNode) ? declared.declarationNode : null;
1769
+ const layoutRelevant = genericOwner ? layoutRelevantParameterIndices(checker, genericOwner) : null;
1770
+ //
1771
+ // A class's CONSTRUCTOR type (`typeof Box`) carries no type arguments,
1772
+ // so the constructor side of a generic class was one anchor for every
1773
+ // instantiation -- one construct signature, one instance carrier and
1774
+ // one thunk, whichever copy completed it first, and `new Box<string>`
1775
+ // beside `new Box<number>` converted its argument to the other copy's
1776
+ // parameter. Inside a copy of the class, when the class's copies can
1777
+ // differ in layout at all (`copiesMayDifferInLayout`), the copy's own
1778
+ // fillings are the arguments the constructor object is being read AT
1779
+ // (`this.constructor`, `new Box(...)` in a method, and every
1780
+ // `new Box<string>(...)` site, which the census types in the copy it
1781
+ // reaches), folded exactly as the instance side folds its written
1782
+ // arguments; the deriver's `physicalClassDeclarationOf` then keys the
1783
+ // two sides of one instantiation to one physical class. Outside any
1784
+ // copy the arguments stay empty, which is the root's own constructor
1785
+ // object.
1786
+ const copy = declared.kind === 'class-constructor' &&
1787
+ ts.isClassLike(declared.declarationNode) &&
1788
+ specializations.copiesMayDifferInLayout(declared.declarationNode)
1789
+ ? foldedCopyOf(declared.declarationNode, layoutRelevant)
1790
+ : null;
1791
+ // A class whose copies must not split has ONE struct. Keying each
1792
+ // instantiation's anchor on its own written fillings gives that one
1793
+ // struct several shapes, and its field carriers then come from
1794
+ // whichever shape completed the anchor first -- for
1795
+ // `ReadableStream<any>` beside `ReadableStream<Uint8Array>` that was
1796
+ // the `any` one, so the struct stored `dynamic` and every read in the
1797
+ // concrete copy refused a narrowing no target installs. The census
1798
+ // names the most specific copy instead; keying every instantiation
1799
+ // there gives the collapse a single honest shape, and the wider
1800
+ // copies' reads widen out of it.
1801
+ const canonical = declared.kind === 'class-instance' && genericOwner && ts.isClassLike(genericOwner)
1802
+ ? specializations.canonicalLayoutFillings(genericOwner)
1803
+ : null;
1804
+ const typeArguments = declared.kind === 'class-constructor'
1805
+ ? (copy?.typeArguments ?? [])
1806
+ : typeArgumentsOf(type).map((argument, index) => {
1807
+ if (layoutRelevant && !layoutRelevant.has(index))
1808
+ return erasedTypeArgument();
1809
+ return typeOf(canonical?.[index] ?? argument);
1810
+ });
1811
+ // Reserved before the body is built, because building it walks members and
1812
+ // a member can reach this same anchor through a second checker type
1813
+ // object. `fresh` says which of the two this call is: the reserver
1814
+ // completes, everyone else just reads the id back.
1815
+ const { id: anchor, fresh } = table.anchor(`${declared.kind}:${declared.declaration}:${typeArguments.join(',')}`);
1816
+ if (copy)
1817
+ recordClassCopy(declared.declaration, copy.ordinal, copy.typeArguments, anchor);
1818
+ inProgress.set(type, anchor);
1819
+ remember(type, anchor);
1820
+ let settled = false;
1821
+ try {
1822
+ if (fresh)
1823
+ table.complete(anchor, buildDeclaredShape(type, declared, typeArguments));
1824
+ settled = true;
1825
+ }
1826
+ finally {
1827
+ inProgress.delete(type);
1828
+ // An unwound walk leaves nothing standing: not the memo, and -- when
1829
+ // this walk is the one that reserved it -- not the reservation either.
1830
+ if (!settled) {
1831
+ completed.delete(type);
1832
+ if (fresh)
1833
+ table.abandon(anchor);
1834
+ }
1835
+ }
1836
+ return anchor;
1837
+ }
1838
+ const callSignatures = type.getCallSignatures();
1839
+ const constructSignatures = type.getConstructSignatures();
1840
+ if (callSignatures.length > 0 || constructSignatures.length > 0) {
1841
+ // The type of an overloaded SOURCE function is every declared overload,
1842
+ // which is the checker's right answer for resolving a call and the
1843
+ // wrong one for the VALUE: the one function object that exists is the
1844
+ // implementation, and it declares exactly one signature.
1845
+ // `sharedAbiOf` (derive.ts) saw N conventions here and boxed every read
1846
+ // of `pad` -- and every unannotated `const padder = pad`, field and
1847
+ // parameter that shares the type object -- as
1848
+ // `dynamic(unjoinable-declared-overload-set)`, a typed function value
1849
+ // boxed. Inside a copy of a GENERIC implementation it was worse: the
1850
+ // overloads' own type parameters, which no copy ever binds, reached
1851
+ // representation as naked holes (TypeScript's `core.ts` `some`, `find`,
1852
+ // `every`, `filter`, `map`...). One answer at the one place the type
1853
+ // is interned, through this copy's own `signatureOf`, so the
1854
+ // implementation's `T` is substituted exactly as its body's would be.
1855
+ // `valueTypeAt` gives the DECLARATION the same answer.
1856
+ const implementation = sourceOverloadImplementationOf(callSignatures, constructSignatures);
1857
+ const generic = genericSourceFunctionOf(type, callSignatures, constructSignatures, implementation);
1858
+ return remember(type, table.intern({
1859
+ kind: 'signature',
1860
+ call: implementation ? [signatureOf(implementation)] : callSignatures.map((one) => signatureOf(one)),
1861
+ construct: constructSignatures.map((one) => signatureOf(one)),
1862
+ ...(generic ? { generic } : {})
1863
+ }));
1864
+ }
1865
+ if (type.flags & ts.TypeFlags.Object) {
1866
+ const symbol = type.getSymbol();
1867
+ const location = symbol ? identities.declarationOfSymbol(symbol) : null;
1868
+ if (location) {
1869
+ // An object literal with at least one method whose OWN body reads
1870
+ // `this` can have that method's member signature read `this` back to
1871
+ // the literal itself (`{ imageId: 1, describe() { return
1872
+ // this.imageId } }`) -- `implicitReceiverOf` above now answers such a
1873
+ // method's receiver with `layoutTypeAt(parent)`, which is THIS type
1874
+ // (or the type it shares identity with via the contextual-type
1875
+ // preference). Interning the body plainly, as the pure-data branch
1876
+ // below does, would walk `describe`'s own signature *while this exact
1877
+ // walk is still running* and recurse forever -- there is no anchor
1878
+ // yet for the receiver to resolve to. So a self-referencing object
1879
+ // literal is anchored EAGERLY, before its members are walked, exactly
1880
+ // as `declaredAnchorOf`'s interface/class/type-alias branch above
1881
+ // already anchors before descending -- the one difference being the
1882
+ // anchor here is keyed by the literal's own declaration
1883
+ // (`ObjectLiteralExpression`) rather than by a named
1884
+ // interface/class/alias, since a bare literal has no such name.
1885
+ //
1886
+ // Scoped to a method whose body ACTUALLY reads `this` (not merely
1887
+ // "has a method", and not an accessor -- an accessor's member type in
1888
+ // the shape is the property type, not its own signature, so it never
1889
+ // re-enters through `objectShapeOf`'s member walk the way a method
1890
+ // does, exactly as `implicitReceiverOf` above reasons). Anchoring
1891
+ // every callable-bearing literal regardless of `this` usage was tried
1892
+ // first and cost 25/116 corpus programs their certification --
1893
+ // ordinary event-handler-shaped literals (`{ onClick() { ... } }`,
1894
+ // never reading `this`) do not need this identity change and paid for
1895
+ // it anyway, by widening which literals reach `implicitReceiverOf`'s
1896
+ // interface-signature branch downstream (removed in edit 4 -- see
1897
+ // that edit's discussion, "Cause 3" in `risks.md`). A pure-data
1898
+ // object literal, and a callable-bearing one whose methods never read
1899
+ // `this`, both keep interning straight into `objectShapeOf`,
1900
+ // completely unchanged, below.
1901
+ //
1902
+ // A `function` expression held by a PROPERTY (`{ m: function () {
1903
+ // return this } }`) is the same method spelled the ES5 way, and
1904
+ // `structural-receiver.ts`'s `jsConstructorReceiverOf` grants it the
1905
+ // same receiver behind the same body gate -- so it needs the same
1906
+ // anchor, or the receiver's self-reference has no nominal carrier.
1907
+ const hasSelfReferencingMethod = type.getProperties().some((property) => {
1908
+ const declaration = identities.declarationOfSymbol(property);
1909
+ if (declaration === null)
1910
+ return false;
1911
+ if ((property.flags & ts.SymbolFlags.Method) !== 0) {
1912
+ return ts.isMethodDeclaration(declaration) && declaration.body !== undefined && bodyReadsThis(declaration.body);
1913
+ }
1914
+ return (ts.isPropertyAssignment(declaration) &&
1915
+ ts.isFunctionExpression(declaration.initializer) &&
1916
+ declaration.initializer.body !== undefined &&
1917
+ bodyReadsThis(declaration.initializer.body));
1918
+ });
1919
+ if (!hasSelfReferencingMethod) {
1920
+ return remember(type, table.intern(objectShapeOf(type, location)));
1921
+ }
1922
+ const declarationKey = `object-literal:${identities.declarationIdOf(location)}`;
1923
+ const { id: anchor, fresh } = table.anchor(declarationKey);
1924
+ inProgress.set(type, anchor);
1925
+ remember(type, anchor);
1926
+ let settled = false;
1927
+ try {
1928
+ if (fresh) {
1929
+ const body = table.intern(objectShapeOf(type, location));
1930
+ table.complete(anchor, { kind: 'object-anchor', declaration: identities.declarationIdOf(location), body });
1931
+ }
1932
+ settled = true;
1933
+ }
1934
+ finally {
1935
+ inProgress.delete(type);
1936
+ if (!settled) {
1937
+ completed.delete(type);
1938
+ if (fresh)
1939
+ table.abandon(anchor);
1940
+ }
1941
+ }
1942
+ return anchor;
1943
+ }
1944
+ // The object itself has no declaring symbol to anchor a `location` on --
1945
+ // `typeof globalThis` is the standing example, a synthetic checker type
1946
+ // whose OWN symbol has zero declarations (verified directly against the
1947
+ // checker: `type.getSymbol()` answers a real symbol named `globalThis`,
1948
+ // but `getDeclarations()` on it is empty). Its members are not
1949
+ // similarly synthetic: each is an ordinary ambient binding with a real
1950
+ // declaration of its own, and `memberOf` already prefers a member's own
1951
+ // declaration over the `location` it is passed (`declaration ?? location`
1952
+ // above), so any member here resolves correctly without ever consulting
1953
+ // `location`. Borrowing one member's declaration as the fallback only
1954
+ // matters for a member that itself has none, which is exactly the case
1955
+ // this branch could not previously tell apart from "every member is
1956
+ // fine, only the container lacks a name" -- and that harder case still
1957
+ // refuses below, unchanged.
1958
+ //
1959
+ // `data-only` mode is not just `declaredBodyOf`'s existing "we do not
1960
+ // implement ambient methods" reason (structural.ts's `declaredBodyOf`,
1961
+ // a few lines below): for a declarationless object it is also what
1962
+ // keeps this walk finite. `typeof globalThis`'s own `globalThis`
1963
+ // property mentions the type again (`declare var globalThis: typeof
1964
+ // globalThis`) and there is no anchor reserved here to break that
1965
+ // cycle on, unlike the `declared`/`class-instance` branch above. But
1966
+ // `globalThis` is checker-flagged `Module`, not `Property` -- like
1967
+ // every other ambient `var`/`function` binding at global scope
1968
+ // (`Array`, `console`, `eval`, ...), which are *not*
1969
+ // `SymbolFlags.Property` even though they read as ordinary data from
1970
+ // JS. `data-only` mode (`isDataMember`, below) filters exactly these
1971
+ // out, so the self-reference is never visited and never has a chance
1972
+ // to recurse.
1973
+ // A checker type flagged `Object`, with no declaring symbol AND no
1974
+ // structural facet at all -- no property, no index signature (call and
1975
+ // construct signatures were already excluded by the check above) -- is
1976
+ // not a shape this program wrote and this walk failed to normalize. It
1977
+ // is TypeScript's own internal answer to "some value, narrowed only to
1978
+ // exclude `null`/`undefined`": what `unknown` (or an unconstrained
1979
+ // generic, or the `{}` top type) becomes after a truthy check with no
1980
+ // `typeof`/`instanceof` narrowing to say anything more. `typeToString`
1981
+ // prints it `{}`, which reads exactly like an empty object literal, but
1982
+ // it is not one: a real `{}` literal anchors on its own
1983
+ // `ObjectLiteralExpression` and is caught by the `location` branch
1984
+ // above, as a genuinely, physically empty record. This one has no
1985
+ // declaration anywhere to anchor on because nothing in the program
1986
+ // wrote it -- the checker synthesized it purely to narrow the runtime
1987
+ // set of possible values without exposing a name for it. Laying it out
1988
+ // as an empty C++ record would claim a shape the runtime value might
1989
+ // not physically have at all (only `null`/`undefined` are excluded; it
1990
+ // could still be a `number`, a `string`, a function, anything), so the
1991
+ // honest carrier is the one plain `unknown` already gets: `dynamic`,
1992
+ // not a refusal.
1993
+ if (type.getProperties().length === 0 && checker.getIndexInfosOfType(type).length === 0) {
1994
+ return remember(type, table.intern({ kind: 'primitive', primitive: 'unknown' }));
1995
+ }
1996
+ // A member's own declaration is what `memberOf` asks at; the borrowed
1997
+ // sibling declaration below only ever answered for a member that has
1998
+ // NONE, and it is `null` when no member has one. That used to be a
1999
+ // refusal, on the reasoning that a location had to come from somewhere --
2000
+ // but the location was never the question. `getTypeOfSymbol` asks a
2001
+ // declarationless symbol for its type directly (`structural-parts.ts`'s
2002
+ // `typeOfSymbolAt`), which is available here and strictly more truthful
2003
+ // than borrowing an unrelated member's node. Every member with a
2004
+ // declaration still resolves at its own, so nothing that already worked
2005
+ // moves; what this unblocks is three.js, whose JSDoc-typed objects reach
2006
+ // here with no member declaration anywhere (three.js app violations 157 -> 21).
2007
+ const anchorLocation = type
2008
+ .getProperties()
2009
+ .map((property) => identities.declarationOfSymbol(property))
2010
+ .find((declaration) => declaration !== null) ?? null;
2011
+ return remember(type, table.intern(objectShapeOf(type, anchorLocation, 'data-only')));
2012
+ }
2013
+ // The `object` keyword type -- "any value that is not a primitive" -- is
2014
+ // its own flag (`NonPrimitive`), not `TypeFlags.Object`: it is a pure
2015
+ // keyword with no declaring symbol, so `type.getSymbol()` above is always
2016
+ // `undefined` for it and the branch that needs one never applies. It also
2017
+ // has no properties, no call/construct signature, and no index signature
2018
+ // of its own to enumerate (verified against the checker directly), so an
2019
+ // object shape with an empty member list and no index is not a guess --
2020
+ // it is exactly what `getProperties()`/`getIndexInfosOfType()` already
2021
+ // report for it. That is the same physical SHAPE `{}` gets -- no members,
2022
+ // no index -- but NOT the same physical CARRIER, and the difference
2023
+ // matters. `representation/derive.ts` turns an empty object shape into a
2024
+ // `record` with zero fields, and `record`'s conversion-from-dynamic has no
2025
+ // installed materializer anywhere in this codebase
2026
+ // (`conversion/build.ts`'s `emptyConversionRegistry.recordMaterializer: ()
2027
+ // => null`, never overridden by the C++ backend). That gap is universal
2028
+ // across every record shape today, so this choice costs nothing YET -- but
2029
+ // it is a latent trap, not a safe default. Record structs are nominal and
2030
+ // per-shape (`targets/cpp/records.ts`'s `cppRecordStructName(shapeId)`, one
2031
+ // distinct C++ struct per shape, no shared base), so the day anyone
2032
+ // installs a record materializer, a dynamic value narrowing to `record` of
2033
+ // this empty shape will either fabricate a fresh, identity-unrelated empty
2034
+ // struct -- breaking anything that depended on WHICH object it was, a
2035
+ // WeakMap key or an `===` -- or be reinterpreted as a struct type it never
2036
+ // was. Measured on the three.js app: 56 obligations of exactly this form, every one
2037
+ // a key argument to a bare `new WeakMap()` in three's renderer, where TS's
2038
+ // own `K extends object = object` default filled in for inference it had
2039
+ // nothing to work from. The cure is upstream -- infer the collection's type
2040
+ // arguments from its uses -- NOT a carrier general enough to swallow the
2041
+ // question, which would box the renderer's hot path and hide the gap.
2042
+ if (type.flags & ts.TypeFlags.NonPrimitive)
2043
+ return remember(type, table.intern({ kind: 'object', members: [], index: [], membersDropped: false }));
2044
+ // A SUBSTITUTION type is its base type, with a narrower constraint the
2045
+ // checker remembers for inference -- nothing more.
2046
+ //
2047
+ // TypeScript mints one inside the TRUE branch of a conditional, where it
2048
+ // knows `T extends X` held: the type of a value there is still `T`, but
2049
+ // every inference made from it may assume `X`. So the two are mutually
2050
+ // assignable and `getReducedType` erases the wrapper; the base is the
2051
+ // answer, and taking the CONSTRAINT instead would name an upper bound the
2052
+ // value need not have.
2053
+ //
2054
+ // Not any of the flags the tests above match, so without this a
2055
+ // substitution falls through to the bare-flags refusal below. Measured
2056
+ // ZERO on the mongodb probe and kept for the reason the reduction itself
2057
+ // states: a form the language erases must not be a refusal, and the one
2058
+ // line costs nothing.
2059
+ if (type.flags & ts.TypeFlags.Substitution)
2060
+ return remember(type, typeOf(type.baseType));
2061
+ // An ANONYMOUS deferred conditional -- `X extends Y ? A : B` written
2062
+ // inline, with no alias to name it.
2063
+ //
2064
+ // Named separately from the bare-flags refusal below because that refusal
2065
+ // reads as a gap in this switch and this is not one: it is the same wall
2066
+ // `structural-declared-body.ts` states for an ALIASED conditional, reached
2067
+ // by a type that has no alias symbol and so never becomes a `declared`
2068
+ // shape at all. There is nothing to reduce it with -- `resolvedTrueType`/
2069
+ // `resolvedFalseType` on a deferred conditional read `undefined` from
2070
+ // outside the checker, and `reducedOperator` above can only answer for the
2071
+ // two operators the checker exposes -- so the only routes out are the
2072
+ // instantiated image `translate` already consults first, or closing the
2073
+ // check type upstream. "checker type with flags 16777216" sent a reader
2074
+ // looking for a missing type FORM; the form is modelled, the reduction is
2075
+ // not.
2076
+ return remember(type, unresolved(`checker type with flags ${type.flags} is not modelled`));
2077
+ }
2078
+ const remember = (type, id) => {
2079
+ completed.set(type, id);
2080
+ journal?.push(type); // so an unwind can take it back -- see `typeOf`'s retry
2081
+ return id;
2082
+ };
2083
+ const layoutTypeAt = createLayoutTypeResolver(checker, parameters, absent);
2084
+ /**
2085
+ * The type at a node, with an absent host type collapsed -- and with that
2086
+ * collapse followed through a member read.
2087
+ *
2088
+ * `substituteAbsentType` answers about the type a node was declared with, so
2089
+ * it collapses the RECEIVER on its own: `canvas`, declared
2090
+ * `HTMLCanvasElement` by three.js's JSDoc, is `never` on a host with no DOM.
2091
+ * The member read is a different node, and the checker still answers it with
2092
+ * `HTMLCanvasElement.addEventListener`'s whole overload set -- so one
2093
+ * expression ends up carrying two incompatible facts: a receiver no value can
2094
+ * inhabit, and a member typed by the class that receiver cannot be. The
2095
+ * member is the half that has to give. Reading a property of a value that
2096
+ * cannot exist produces a value that cannot exist.
2097
+ *
2098
+ * This is not an optimization. `three-angle-metal`'s seven violations and
2099
+ * seven unresolved carriers were all this one shape -- `canvas.getContext`
2100
+ * (five overloads) and `canvas.addEventListener`/`removeEventListener` (two
2101
+ * each) -- refused as "no primitive joining N overload signatures into one
2102
+ * calling convention". That refusal was correct about the overloads and
2103
+ * wrong about the question: the overload set is a phantom. On this target
2104
+ * `canvas` is a native handle, and joining arms of a class that cannot exist
2105
+ * was never something the program asked for.
2106
+ *
2107
+ * It recurses through the receiver rather than reading `layoutTypeAt` there
2108
+ * directly, so a chain collapses from wherever the absent type actually is:
2109
+ * in `a.b.c` it is `a` that cannot exist, and `a.b` has to be `never` before
2110
+ * `a.b.c` can be.
2111
+ */
2112
+ const absentSubstitutedTypeAt = (node) => {
2113
+ const own = absent.substituteAbsentType(layoutTypeAt(node));
2114
+ if ((own.flags & ts.TypeFlags.Never) !== 0)
2115
+ return own;
2116
+ if (!ts.isPropertyAccessExpression(node) && !ts.isElementAccessExpression(node))
2117
+ return own;
2118
+ const receiver = absentSubstitutedTypeAt(node.expression);
2119
+ return (receiver.flags & ts.TypeFlags.Never) !== 0 ? receiver : own;
2120
+ };
2121
+ /**
2122
+ * A value declared `any`/`unknown` and narrowed only to the bare `object`
2123
+ * type is still a dynamic boundary. `typeof value === 'object'` proves that
2124
+ * property operations are permitted; it does not discover a field layout
2125
+ * or turn the value into a closed empty record. Keeping the declaration's
2126
+ * carrier here lets `key in value` and later dynamic reads consult the real
2127
+ * runtime object instead of asking a zero-field C++ struct to answer them.
2128
+ * A stronger narrowing (an interface, class, array, or other named shape)
2129
+ * has ordinary Object flags rather than NonPrimitive and remains untouched.
2130
+ */
2131
+ const dynamicObjectBoundaryAt = (node) => {
2132
+ if (!ts.isIdentifier(node))
2133
+ return null;
2134
+ if ((absentSubstitutedTypeAt(node).flags & ts.TypeFlags.NonPrimitive) === 0)
2135
+ return null;
2136
+ const symbol = checker.getSymbolAtLocation(node);
2137
+ const declaration = symbol?.valueDeclaration ?? symbol?.declarations?.[0];
2138
+ if (!symbol || !declaration)
2139
+ return null;
2140
+ const declared = checker.getTypeOfSymbolAtLocation(symbol, declaration);
2141
+ return (declared.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) !== 0 ? declared : null;
2142
+ };
2143
+ /**
2144
+ * A read the checker's control-flow analysis cannot place. An unannotated,
2145
+ * uninitialized `var t;` is auto-typed: the checker evolves the cell through
2146
+ * the assignments it can SEE, and a read that follows only the declaration
2147
+ * answers `undefined` -- the initial state -- even when a nested function
2148
+ * (`{ m: function () { t = this } }`, called before the read) has written the
2149
+ * cell in between, because the analysis never follows a call. The census read
2150
+ * every write through the flow index and bound the cell to what they store;
2151
+ * a bare-`undefined` read of such a cell tested nothing, so it is not a
2152
+ * narrowing the cell has to be converted for. The cell's own type is the
2153
+ * answer. A read the checker places from a write in the reader's OWN scope,
2154
+ * and a cell every write of which sits beside its reads, keep the checker's
2155
+ * view: there the `undefined` is the program's, not the analysis's.
2156
+ */
2157
+ const unplacedHoistedReadAt = (node) => {
2158
+ if (!flow || !ts.isIdentifier(node))
2159
+ return null;
2160
+ const own = absentSubstitutedTypeAt(node);
2161
+ if ((own.flags & ts.TypeFlags.Undefined) === 0 || own.isUnion())
2162
+ return null;
2163
+ const declaration = checker.getSymbolAtLocation(node)?.valueDeclaration;
2164
+ if (!declaration || !ts.isVariableDeclaration(declaration) || declaration.type || declaration.initializer)
2165
+ return null;
2166
+ if (node === declaration.name || !ts.isIdentifier(declaration.name))
2167
+ return null;
2168
+ const reader = ts.findAncestor(node, ts.isFunctionLike) ?? null;
2169
+ const writes = flow.writesToDeclaration(declaration).filter((write) => write.slot === 'whole');
2170
+ if (!writes.length || !writes.some((write) => (ts.findAncestor(write.site, ts.isFunctionLike) ?? null) !== reader))
2171
+ return null;
2172
+ const cell = parameters.typeAt(declaration);
2173
+ return cell && (cell.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown | ts.TypeFlags.Undefined)) === 0 ? cell : null;
2174
+ };
2175
+ /**
2176
+ * Whether this node is the one its parent site NAMES, rather than merely a
2177
+ * child of it.
2178
+ *
2179
+ * A call is recorded as one instantiation site, and everything under it --
2180
+ * the callee, but also every ARGUMENT -- has that call as its parent. Only
2181
+ * the callee is typed by the copy the call reaches; an argument is typed by
2182
+ * the scope it is written in, which is the ENCLOSING copy, and reading it
2183
+ * through the callee's copy loses whatever that enclosing copy binds. In
2184
+ * `outer<T>(op: T) { inner(op) }` compiled as `outer<Heavy>`, `op` read
2185
+ * through `inner`'s copy is a naked `T` again -- the exact hole
2186
+ * monomorphization removes, put back one node to the right of where it was
2187
+ * removed.
2188
+ *
2189
+ * A type reference (`Foo<Bar>`) is recorded on the reference node itself and
2190
+ * names no separate callee, so it answers `true` and behaves as before.
2191
+ */
2192
+ const namesItsSite = (node) => {
2193
+ const site = node.parent;
2194
+ if (ts.isCallOrNewExpression(site))
2195
+ return site.expression === node;
2196
+ if (ts.isTaggedTemplateExpression(site))
2197
+ return site.tag === node;
2198
+ if (ts.isJsxOpeningLikeElement(site))
2199
+ return site.tagName === node;
2200
+ return true;
2201
+ };
2202
+ /**
2203
+ * The type of the *value* a declaration introduces.
2204
+ *
2205
+ * `getTypeAtLocation` on a class declaration answers with the instance type,
2206
+ * because that is what the name means in a type position. The value the
2207
+ * declaration binds is the constructor object, which is the symbol's type --
2208
+ * a different type with different members, and asking the wrong one is how a
2209
+ * constructor ends up carried as one of its own instances.
2210
+ */
2211
+ const localUnionAt = createLocalUnionResolver(checker, table, parameters, flow, (node) => mapper.typeAt(node), (node) => (ts.isExpression(node) ? objectDescriptorReturnTypeAt(unwrapErasedExpression(node)) : null));
2212
+ const callResultAt = createStructuralCallResultResolver(checker, table, (node) => mapper.typeAt(node));
2213
+ const constructResultAt = createStructuralConstructResultResolver(table, (node) => mapper.typeAt(node));
2214
+ const impliedPatternArrayLiteralType = (node) => {
2215
+ // A tuple, or the empty literal the checker types `never[]` against a
2216
+ // rest pattern's `any[]` silhouette (`f([])` for `function f([...r])`).
2217
+ const own = checker.getNonNullableType(absentSubstitutedTypeAt(node));
2218
+ if (!checker.isTupleType(own) && !(node.elements.length === 0 && checker.isArrayType(own)))
2219
+ return null;
2220
+ const target = impliedPatternTargetOf(checker, node);
2221
+ if (!target)
2222
+ return null;
2223
+ if (node.elements.some((element) => ts.isSpreadElement(element)))
2224
+ return null;
2225
+ // A nested element's default (`[[x, y, z] = [4, 5, 6]]`) is stored in
2226
+ // THAT element's slot -- the census's own binding for it, which is the
2227
+ // outer array's element (a tuple record here) -- not in the root
2228
+ // parameter's: reading the root's slot typed this literal as an array OF
2229
+ // its own tuple and passed `4` into a three-field record.
2230
+ if (target.element) {
2231
+ const slot = parameters.typeAt(target.element);
2232
+ return slot && !isUnusableEvidence(slot) ? typeOf(slot) : null;
2233
+ }
2234
+ // The parameter's census slot (every tuple arm's positions, joined) is
2235
+ // the element this literal is stored as; the literal's own tuple shape
2236
+ // is not, or `f([1, 2]); f([])` would pass a `never[]` into a `number[]`.
2237
+ const bound = target.parameter ? parameters.typeAt(target.parameter) : null;
2238
+ const boundElement = target.parameter
2239
+ ? (impliedPatternArrayElementAt(checker, parameters, target.parameter) ??
2240
+ (bound ? checker.getIndexTypeOfType(checker.getNonNullableType(bound), ts.IndexKind.Number) : undefined))
2241
+ : undefined;
2242
+ // A hole (`[,]`) is a position holding nothing -- the array's element
2243
+ // read there is `undefined`, which the pattern's own absence already
2244
+ // covers -- so it states no element type of its own.
2245
+ const written = node.elements
2246
+ .filter((element) => !ts.isOmittedExpression(element))
2247
+ .map((element) => checker.getBaseTypeOfLiteralType(absentSubstitutedTypeAt(element)));
2248
+ const element = boundElement && !isUnusableEvidence(boundElement)
2249
+ ? boundElement
2250
+ : written.length === 0
2251
+ ? checker.getNeverType()
2252
+ : widestOf(checker, written);
2253
+ if (!element)
2254
+ return null;
2255
+ return table.intern({ kind: 'array', element: typeOf(element), readonly: false, extension: [] });
2256
+ };
2257
+ /**
2258
+ * A rest element of an array pattern over a plain array IS that array's
2259
+ * type -- the remaining elements, in an Array -- and the checker's own
2260
+ * answer is not: `var [x, ...rest] = [1, 2, 3]` types `rest` as the tuple
2261
+ * `[number, number]` because it typed the literal as a tuple, while the
2262
+ * value the pattern reads out of (`impliedPatternArrayLiteralType`) is an
2263
+ * ordinary array of unknown length. Answered for the element and for every
2264
+ * reference to it, since both are laid out from the same cell. A pattern
2265
+ * over a source that stays a tuple keeps the checker's tuple.
2266
+ *
2267
+ * Answers only for `rest` itself, never for a cell some OTHER assignment
2268
+ * also reaches. `rest = JSON.parse(...)` after `var [x, ...rest] = [1, 2,
2269
+ * 3]` is the identical defect `restAssignmentArrayShapeAt` (below) was
2270
+ * fixed for, one syntax over: this function is keyed by the symbol's
2271
+ * DECLARATION alone and, before this guard, never asked whether anything
2272
+ * else writes it, so a genuinely dynamic later value stored into `rest`
2273
+ * still read back as `array-object(scalar(number))` from the pattern
2274
+ * alone -- a fail-open `unboxDynamicArray<double>` that aborted the moment
2275
+ * the dynamic value held something else. See that function's own header
2276
+ * for the full trace; this is its DECLARATION-pattern twin.
2277
+ */
2278
+ const arrayPatternRestTypeAt = (node) => {
2279
+ const element = ts.isBindingElement(node)
2280
+ ? node
2281
+ : ts.isIdentifier(node)
2282
+ ? checker.getSymbolAtLocation(node)?.valueDeclaration
2283
+ : undefined;
2284
+ if (!element || !ts.isBindingElement(element) || !element.dotDotDotToken || !ts.isArrayBindingPattern(element.parent))
2285
+ return null;
2286
+ if (flow) {
2287
+ const symbol = ts.isIdentifier(element.name) ? checker.getSymbolAtLocation(element.name) : undefined;
2288
+ if (!symbol)
2289
+ return null;
2290
+ // The element's OWN binding is itself recorded as a write (`destructuring`,
2291
+ // `value: null` -- `recordBindingPattern`), so a real value here is always
2292
+ // a SEPARATE, later assignment this function has no way to fold in.
2293
+ const reassigned = flow.writesToSymbol(symbol).some((write) => write.slot === 'whole' && write.value !== null);
2294
+ if (reassigned)
2295
+ return null;
2296
+ }
2297
+ const source = mapper.typeAt(element.parent);
2298
+ return table.get(source).shape.kind === 'array' ? source : null;
2299
+ };
2300
+ /**
2301
+ * A REST target of an array-destructuring ASSIGNMENT (`var a, r; [a, ...r]
2302
+ * = [1, 2, 3]`), for a bare `r` with no annotation and no initializer.
2303
+ *
2304
+ * `arrayPatternRestTypeAt` above answers the DECLARATION-pattern twin of
2305
+ * this (`var [x, ...rest] = ...`), where the rest names a `ts.BindingElement`
2306
+ * this layer can walk straight to the pattern from. An assignment target
2307
+ * names no such element -- `r` is an ordinary bare `VariableDeclaration`,
2308
+ * written later through `[a, ...r] = arr`, and `local-bindings.ts`'s
2309
+ * `identifierWritesOf` (which types every OTHER bare-declaration write
2310
+ * through a recovered `ts.Expression`) explicitly refuses a rest target:
2311
+ * there is no single sub-expression that states "the remaining elements,"
2312
+ * and there is no public checker API to synthesize one --
2313
+ * `structural-array-element.ts`'s header documents the identical wall for
2314
+ * `never[]`.
2315
+ *
2316
+ * The source array's OWN resolved carrier already answers the question
2317
+ * this layer needs, without synthesizing anything: a rest capture over an
2318
+ * `array`-shaped source holds exactly that source's element, whatever the
2319
+ * capture's start position -- the identical fact `arrayPatternRestTypeAt`
2320
+ * trades on. So this asks every REST write of the symbol for its pattern's
2321
+ * source, resolves that source through this same mapper, and adopts its
2322
+ * shape outright when it is an `array` -- never a `tuple`, which states a
2323
+ * fixed arity the rest slice does not share, and never anything else,
2324
+ * which states a value no array carrier could hold.
2325
+ *
2326
+ * Several rest writes to the same cell must AGREE (the identical shape) or
2327
+ * this refuses outright -- a real disagreement is not this layer's to
2328
+ * resolve, and a wrong pick would be worse than the box the cell keeps
2329
+ * today. A write whose source cannot be resolved to an array shape states
2330
+ * nothing either way and is skipped rather than treated as a conflict.
2331
+ *
2332
+ * The premise this whole function trades on is "`r` is written ONLY
2333
+ * through rest capture" (the header's own words: "written LATER through
2334
+ * `[a, ...r] = arr]`"). It used to take that on faith -- the write loop
2335
+ * below `continue`d past any write that was not itself a recognised rest
2336
+ * capture, silently discarding it rather than checking whether the
2337
+ * premise actually held. A plain `r = JSON.parse(...)` reassignment after
2338
+ * `[a, ...r] = [1, 2, 3]` reached exactly that `continue`, so this
2339
+ * function answered "array of number" from the ONE write it understood
2340
+ * while a genuinely dynamic value flowed into the SAME cell from the one
2341
+ * it ignored -- the store then read that dynamic value back through
2342
+ * `unboxDynamicArray<double>`, which aborted at runtime the moment the
2343
+ * parsed JSON held strings. Certified clean, compiled clean, `gea:
2344
+ * SIGABRT`. Fixed by refusing outright the moment ANY write this
2345
+ * authority cannot itself vouch for as a rest capture exists, rather than
2346
+ * silently answering from the subset it does understand -- the same
2347
+ * "a write that states nothing is not a write that disagrees, but a write
2348
+ * this authority never SAW is not evidence of agreement either" correction
2349
+ * `local-bindings.ts`'s `branchArmsOf` made for `||`/`??`/`?:` writes.
2350
+ */
2351
+ const restAssignmentArrayShapeAt = (node) => {
2352
+ if (!flow)
2353
+ return null;
2354
+ const declaration = ts.isVariableDeclaration(node)
2355
+ ? node
2356
+ : ts.isIdentifier(node)
2357
+ ? checker.getSymbolAtLocation(node)?.valueDeclaration
2358
+ : undefined;
2359
+ if (!declaration ||
2360
+ !ts.isVariableDeclaration(declaration) ||
2361
+ declaration.type ||
2362
+ declaration.initializer ||
2363
+ !ts.isIdentifier(declaration.name))
2364
+ return null;
2365
+ const symbol = checker.getSymbolAtLocation(declaration.name);
2366
+ if (!symbol)
2367
+ return null;
2368
+ let agreed = null;
2369
+ let sawRestWrite = false;
2370
+ for (const write of flow.writesToSymbol(symbol)) {
2371
+ if (write.slot !== 'whole')
2372
+ continue;
2373
+ const target = write.edge === 'destructuring' && write.value === null && write.naming ? arrayAssignmentTargetOf(write.naming) : null;
2374
+ if (!target || !ts.isSpreadElement(target.keyNode)) {
2375
+ // Not a rest capture this authority recognises -- a bare/defaulted
2376
+ // destructuring element, a plain reassignment, a reused for-of head,
2377
+ // whatever it is, it is a write this loop cannot fold into `agreed`,
2378
+ // so the "written ONLY through rest capture" premise is false and
2379
+ // the honest answer is refusal, not an answer from a subset.
2380
+ return null;
2381
+ }
2382
+ sawRestWrite = true;
2383
+ const source = arrayAssignmentPatternSourceExpression(target.pattern);
2384
+ if (!source)
2385
+ continue;
2386
+ const sourceShape = mapper.typeAt(source);
2387
+ if (table.get(sourceShape).shape.kind !== 'array')
2388
+ continue;
2389
+ if (agreed !== null && agreed !== sourceShape)
2390
+ return null;
2391
+ agreed = sourceShape;
2392
+ }
2393
+ return sawRestWrite ? agreed : null;
2394
+ };
2395
+ /**
2396
+ * The copy a site's instantiation names, as a path this mapper can be asked
2397
+ * for: the copies enclosing the *site's* declaration, not this walk's whole
2398
+ * path. A generic named from inside an unrelated generic's body is not
2399
+ * nested in it, and carrying that outer step would compose `decl|X@0.0` --
2400
+ * an id the census, which walks that generic from its own scope, never
2401
+ * publishes.
2402
+ *
2403
+ * A SELF-instantiation (`Hono#clone()` naming `new Hono<...>` with its own
2404
+ * type parameters) resolves to the identical (declaration, ordinal) pair as
2405
+ * the enclosing path's own last step, since `prefixFor` is inclusive of
2406
+ * self-containment. Appending a second frame there composes `decl|Hono@0.0`
2407
+ * for a copy already named `decl|Hono@0` -- the spurious-nesting shape, one
2408
+ * step short -- so the enclosing path is reused unchanged when its last
2409
+ * step already IS this copy.
2410
+ */
2411
+ /**
2412
+ * The generic source function `type` is the OPEN type of, from this view.
2413
+ *
2414
+ * `typeof identity` where `function identity<T>(x: T): T` is a module-level
2415
+ * function with a body, read from a view that binds none of its type
2416
+ * parameters (the root, or a copy of something else). Inside `identity`'s
2417
+ * own copy the same `ts.Type` reads with `T` bound, and is the copy's own
2418
+ * closed callable, not a choice. Only a module- or namespace-level
2419
+ * declaration qualifies: a nested generic closes over its frame, and a
2420
+ * choice among closures would need the captured environment beside the
2421
+ * tag. See `StructuralShape`'s `generic` and `representation/model.ts`'s
2422
+ * `generic-function-set`.
2423
+ */
2424
+ const genericSourceFunctionOf = (type, callSignatures, constructSignatures, implementation) => {
2425
+ if (constructSignatures.length > 0 || callSignatures.length === 0)
2426
+ return null;
2427
+ const signatures = implementation ? [implementation] : callSignatures;
2428
+ // Open = this PATH binds none of it. Not `substituteTypeParameter`: that
2429
+ // also answers from the instantiation census's one-instantiation fallback,
2430
+ // which closes a root-view `T` whose only copy is the one a set call
2431
+ // minted -- reading the choice's own member as that copy's closed callable.
2432
+ const open = signatures.every((signature) => {
2433
+ const parameters = signature.getTypeParameters() ?? [];
2434
+ return (parameters.length > 0 &&
2435
+ parameters.some((parameter) => {
2436
+ const declared = parameter.getSymbol()?.declarations?.[0];
2437
+ return declared === undefined || boundByPath(declared) === null;
2438
+ }));
2439
+ });
2440
+ if (!open)
2441
+ return null;
2442
+ const declaration = implementation?.declaration ?? type.getSymbol()?.valueDeclaration;
2443
+ if (!declaration || !ts.isFunctionDeclaration(declaration) || declaration.body === undefined)
2444
+ return null;
2445
+ if (declaration.getSourceFile().isDeclarationFile)
2446
+ return null;
2447
+ if (!(ts.isSourceFile(declaration.parent) || ts.isModuleBlock(declaration.parent)))
2448
+ return null;
2449
+ if (declaration.asteriskToken !== undefined || (ts.getCombinedModifierFlags(declaration) & ts.ModifierFlags.Async) !== 0)
2450
+ return null;
2451
+ return identities.declarationIdOf(declaration, rootSpecialization);
2452
+ };
2453
+ const copyPathOf = (site) => {
2454
+ const enclosing = identities.prefixFor(site.declaration, path);
2455
+ const last = enclosing[enclosing.length - 1];
2456
+ const isSelfReference = last !== undefined && last.owner === site.declaration && last.ordinal === site.ordinal;
2457
+ return isSelfReference ? enclosing : [...enclosing, { owner: site.declaration, ordinal: site.ordinal }];
2458
+ };
2459
+ /**
2460
+ * The implementation signature behind a call-signature set that is one
2461
+ * overloaded SOURCE function or method -- two or more signatures, every one
2462
+ * declared by a body-less overload or the body of the same symbol, in a
2463
+ * source file -- or `null` for any other callable type. An ambient overload
2464
+ * set (`document.createElement`) has no body to be the value and keeps the
2465
+ * checker's answer.
2466
+ */
2467
+ const sourceOverloadImplementationOf = (callSignatures, constructSignatures) => {
2468
+ if (callSignatures.length < 2 || constructSignatures.length > 0)
2469
+ return null;
2470
+ let symbol;
2471
+ for (const signature of callSignatures) {
2472
+ const declaration = signature.getDeclaration();
2473
+ if (!declaration || !(ts.isFunctionDeclaration(declaration) || ts.isMethodDeclaration(declaration)))
2474
+ return null;
2475
+ if (declaration.getSourceFile().isDeclarationFile)
2476
+ return null;
2477
+ const name = ts.getNameOfDeclaration(declaration);
2478
+ const owner = name ? checker.getSymbolAtLocation(name) : undefined;
2479
+ if (!owner || (symbol !== undefined && owner !== symbol))
2480
+ return null;
2481
+ symbol = owner;
2482
+ }
2483
+ const first = callSignatures[0]?.getDeclaration();
2484
+ return first ? implementationSignatureOf(checker, first) : null;
2485
+ };
2486
+ /**
2487
+ * A member read off an EVOLVING array -- `var xs = []; xs.push('a')` -- whose
2488
+ * element the census proved (`inferredArrayElementAt`) but the checker still
2489
+ * carries as `any`/`never` at the read. The checker instantiates
2490
+ * `Array<T>.push` from the receiver EXPRESSION's type, so its signature says
2491
+ * `(...items: any[]) => number`, and every argument the call packs into that
2492
+ * rest slot is boxed on the way in and unboxed again by the native `push`
2493
+ * -- a `gea::Value` per pushed element for an array whose storage is
2494
+ * already `ArrayObject<std::string>`. Two authorities over one slot; the
2495
+ * census's element is the one the storage was chosen by, so it is the one
2496
+ * the member's own parameters carry too. Only the argument positions that
2497
+ * are the ELEMENT (`any`) or a rest of it (`any[]`) are rewritten -- the
2498
+ * shapes of `push`/`unshift`/`splice`/`indexOf`/`includes`/`fill` -- a
2499
+ * result or a nested callback stays the checker's, since nothing here is
2500
+ * asked about it and a wrong guess there is a silent miscompile.
2501
+ */
2502
+ const evolvingArrayMemberTypeAt = (node) => {
2503
+ if (!ts.isPropertyAccessExpression(node))
2504
+ return null;
2505
+ const element = inferredArrayElementAt(checker, collections, layoutTypeAt, node.expression);
2506
+ if (!element || (element.flags & (ts.TypeFlags.Any | ts.TypeFlags.Never)) !== 0)
2507
+ return null;
2508
+ // The checker's own member type, interned directly: asking `typeAt` of
2509
+ // this same node would re-enter here.
2510
+ const declared = typeOf(checker.getTypeAtLocation(node));
2511
+ const shape = table.get(declared).shape;
2512
+ if (shape.kind !== 'signature' || shape.call.length !== 1 || shape.construct.length !== 0)
2513
+ return null;
2514
+ // `any` for the evolving array the checker gave up on, `never` for the one
2515
+ // it is still tracking (`push` off a fresh `[]` is `(...items: never[])`).
2516
+ const unstated = new Set();
2517
+ for (const primitive of ['any', 'never']) {
2518
+ const id = table.intern({ kind: 'primitive', primitive });
2519
+ unstated.add(id);
2520
+ unstated.add(table.intern({ kind: 'array', element: id, readonly: false, extension: [] }));
2521
+ }
2522
+ const elementId = typeOf(element);
2523
+ const elementArray = table.intern({ kind: 'array', element: elementId, readonly: false, extension: [] });
2524
+ const substitute = (id) => {
2525
+ if (!unstated.has(id))
2526
+ return id;
2527
+ return table.get(id).shape.kind === 'array' ? elementArray : elementId;
2528
+ };
2529
+ const call = shape.call[0];
2530
+ if (!call || !call.parameters.some((parameter) => unstated.has(parameter.type)))
2531
+ return null;
2532
+ const parameters = call.parameters.map((parameter) => ({
2533
+ ...parameter,
2534
+ type: substitute(parameter.type),
2535
+ slot: substitute(parameter.slot)
2536
+ }));
2537
+ return table.intern({ kind: 'signature', call: [{ ...call, parameters }], construct: [] });
2538
+ };
2539
+ /**
2540
+ * The signature of a member read off a receiver the CENSUS typed and the
2541
+ * checker carries as `any` -- three's `LOD.addLevel` reading `levels`
2542
+ * through a descriptor-defined field -- when the member is an overload set
2543
+ * the census could not narrow to one convention: `memberTypeOf`'s
2544
+ * `singleConventionAt` needs the checker's resolved signature to pick, and a
2545
+ * call through an `any` receiver resolves to the fabricated no-parameter
2546
+ * signature instead. Picked here by the argument count, the checker's own
2547
+ * first overload-resolution step (`arityAdmittedSignature`), and interned as
2548
+ * the ONE selected signature over the census receiver's instantiation -- so
2549
+ * `levels.splice( l, 0, level )` names the rest-taking overload and the
2550
+ * lowering packs the item, where the joined overload set declared no rest
2551
+ * slot and the item reached `Array.prototype.splice`'s renderer bare.
2552
+ */
2553
+ const censusMemberSignatureAt = (node) => {
2554
+ if (!ts.isPropertyAccessExpression(node))
2555
+ return null;
2556
+ if ((absentSubstitutedTypeAt(node).flags & ts.TypeFlags.Any) === 0)
2557
+ return null;
2558
+ const call = node.parent;
2559
+ if (!call || !ts.isCallExpression(call) || call.expression !== node)
2560
+ return null;
2561
+ const receiver = parameters.typeAt(node.expression);
2562
+ if (!receiver || (receiver.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown | ts.TypeFlags.Never)) !== 0)
2563
+ return null;
2564
+ const property = checker.getPropertyOfType(checker.getNonNullableType(receiver), node.name.text);
2565
+ if (!property)
2566
+ return null;
2567
+ const member = checker.getTypeOfSymbolAtLocation(property, node);
2568
+ if (member.getCallSignatures().length < 2 || member.getConstructSignatures().length > 0)
2569
+ return null;
2570
+ const selected = arityAdmittedSignature(member, call);
2571
+ if (!selected || (selected.getTypeParameters()?.length ?? 0) > 0)
2572
+ return null;
2573
+ return table.intern({ kind: 'signature', call: [signatureOf(selected)], construct: [] });
2574
+ };
2575
+ /**
2576
+ * `Object.getOwnPropertyDescriptor(receiver, key)`'s result, minted from the
2577
+ * RECEIVER's own structural shape rather than the ambient `PropertyDescriptor`
2578
+ * interface's own declared `value?: any`.
2579
+ *
2580
+ * The library's own signature is `getOwnPropertyDescriptor(o: any, p:
2581
+ * PropertyKey): PropertyDescriptor | undefined` -- fixed and non-generic, so
2582
+ * every call resolves to the identical ambient shape no matter what `o` is.
2583
+ * That is the right answer for a receiver this compiler never gave a shape of
2584
+ * its own (`Math`, `Array.prototype`, a value the program declared `any`):
2585
+ * there is no narrower fact to publish, and `value: any` is honest. It is the
2586
+ * wrong answer for a record literal, an array, or an in-program function,
2587
+ * whose OWN declared members already answer "what is `receiver[key]`" -- and
2588
+ * publishing the ambient `any` there is exactly the "typed value lowered into
2589
+ * `gea_cpp_value`" defect this compiler exists to refuse:
2590
+ * `Object.getOwnPropertyDescriptor({ a: 1 }, "a").value` would box a `number`
2591
+ * the record's own layout already states, for no reason but the library
2592
+ * text's own `any`.
2593
+ *
2594
+ * Lives here, in `typeAt`'s own module, rather than beside
2595
+ * `producers/invocations.ts`'s other result overrides: this is asked of the
2596
+ * bare CallExpression node ITSELF (not just consulted from inside the
2597
+ * invocation producer's own result computation), because `context.types.typeAt`
2598
+ * is the ONE authority every OTHER consumer of this same node's type reads
2599
+ * from -- a property access's own receiver type
2600
+ * (`producers/properties.ts`), a local binding's declared type
2601
+ * (`local-bindings.ts`) -- and an override that only changed what the
2602
+ * invocation producer PUBLISHES for its own operation result left every one
2603
+ * of those asking `context.types.typeAt` on the very same node with the
2604
+ * old, ambient, boxed answer: the call's own SSA value came out fully
2605
+ * native while the record it got stored into, and the receiver of a plain
2606
+ * `d.value` off it, still boxed. `evolvingArrayMemberTypeAt` above is
2607
+ * exposed the same way for the identical reason.
2608
+ *
2609
+ * Gated to receivers this compiler already treats as having a REAL,
2610
+ * in-program shape: `membersDropped === false` for an object literal
2611
+ * (`membersDropped` is `true` for an ambient interface enumerated
2612
+ * `data-only`, `host/object-protocol.ts`'s own distinction between the two),
2613
+ * and a physical, non-ambient value declaration for a function. A host
2614
+ * intrinsic still falls through to the ambient signature below untouched --
2615
+ * its own static reflection, if any, is a separate, host-table-driven
2616
+ * mechanism this function has no business pre-empting.
2617
+ *
2618
+ * A literal key that names a member answers with that member's own type. A
2619
+ * runtime key, or a literal that names no member, answers with the union of
2620
+ * every member this receiver states (an array: its element and `length`; a
2621
+ * function: `name` and `length`), plus the record's dynamic-property
2622
+ * SIDECAR's own boxed arm for a key `Object.defineProperty` could have
2623
+ * added after the fact -- the one accepted, bounded exception this feature
2624
+ * carries, matching the sidecar's own storage
2625
+ * (`emit-dynamic-properties.ts`).
2626
+ */
2627
+ const objectDescriptorReturnTypeAt = (call) => {
2628
+ if (!ts.isCallExpression(call))
2629
+ return null;
2630
+ const node = call.expression;
2631
+ if (!ts.isPropertyAccessExpression(node) || node.name.text !== 'getOwnPropertyDescriptor')
2632
+ return null;
2633
+ if (!isIntrinsicDescriptorCall(call))
2634
+ return null;
2635
+ const target = call.arguments[0];
2636
+ const keyArgument = call.arguments[1];
2637
+ if (!target)
2638
+ return null;
2639
+ const literalKey = keyArgument
2640
+ ? ts.isStringLiteralLike(keyArgument)
2641
+ ? keyArgument.text
2642
+ : ts.isNumericLiteral(keyArgument)
2643
+ ? keyArgument.text
2644
+ : null
2645
+ : null;
2646
+ const intern = (built) => table.intern(built);
2647
+ const boolId = intern({ kind: 'primitive', primitive: 'boolean' });
2648
+ // The `value` this descriptor carries for one candidate receiver shape, or
2649
+ // `null` when this shape names no rendering this feature supports (a plain
2650
+ // `dynamic`/`unknown` receiver, an interface flattened to `membersDropped`).
2651
+ // Split out of the top level so a receiver typed as a UNION of shapes --
2652
+ // `describe(obj, key)` called once with a record and once with an array,
2653
+ // neither call site specializing the shared body -- can ask this same
2654
+ // question of each arm and union the answers, rather than refusing the
2655
+ // whole call the way an unhandled `shape.kind` correctly does.
2656
+ // `any | T` is `any`: an arm that already admits every value absorbs the
2657
+ // others, exactly as the checker reduces the same union. Interning the
2658
+ // unreduced pair instead published `tagged-union(dynamic | number)` for
2659
+ // `Array.prototype`'s `any` element, a carrier no installed conversion
2660
+ // reaches from the boxed read the array arm performs, and the whole call
2661
+ // was refused for a receiver whose honest answer was simply `any`.
2662
+ const anyId = intern({ kind: 'primitive', primitive: 'any' });
2663
+ const unionOf = (arms) => {
2664
+ const distinct = [...new Set(arms)];
2665
+ if (distinct.includes(anyId))
2666
+ return anyId;
2667
+ const first = distinct[0];
2668
+ return distinct.length === 1 && first !== undefined ? first : intern({ kind: 'union', members: distinct });
2669
+ };
2670
+ const valueIdOfShape = (shape) => {
2671
+ // A native class anchor carries its own member layout in the same body
2672
+ // as an ordinary declared record. Discarding that body here widens a
2673
+ // known field into ambient PropertyDescriptor.value:any before the
2674
+ // result is even lowered, forcing a needless box/unbox round trip.
2675
+ if ((shape.kind === 'declared' || shape.kind === 'class-instance') && shape.body !== null)
2676
+ return valueIdOfShape(table.get(shape.body).shape);
2677
+ if (shape.kind === 'object' && !shape.membersDropped) {
2678
+ if (literalKey !== null) {
2679
+ // A literal key that names no member this record's own structural
2680
+ // type declares is not proof the key is absent: `Object.defineProperty(o,
2681
+ // "b", ...)` adds "b" to the object's dynamic-property SIDECAR (see
2682
+ // `emit-dynamic-properties.ts`), which this type never sees, because
2683
+ // a record's structural shape only ever tracks its declared literal
2684
+ // fields. The sidecar stores its values boxed (`gea::Value` -- the
2685
+ // one accepted, bounded exception this feature carries, matching a
2686
+ // genuinely dynamic key with no static type to give it), so the
2687
+ // descriptor's `value` for a key the shape doesn't declare must stay
2688
+ // `dynamic` rather than borrowing an unrelated declared field's type.
2689
+ const match = shape.members.find((member) => member.key.kind === 'string' && member.key.value === literalKey);
2690
+ if (match)
2691
+ return match.type;
2692
+ const index = shape.index.find((candidate) => candidate.key === 'string' || (candidate.key === 'number' && literalKey !== '' && Number.isFinite(Number(literalKey))));
2693
+ return index?.value ?? intern({ kind: 'primitive', primitive: 'any' });
2694
+ }
2695
+ else if (shape.members.length > 0) {
2696
+ // A runtime (non-literal) key: `describe(obj, key)`'s `value` must
2697
+ // be able to hold whichever declared field `key` names at runtime,
2698
+ // so it is the union of the record's own field types -- the
2699
+ // emitter renders this as a switch over the record's known keys
2700
+ // (`finiteRecordUnionGetText`'s pattern), never a boxed carrier. A
2701
+ // runtime key can ALSO name a key the type declares nothing about,
2702
+ // so the value must also admit the sidecar's own boxed arm, exactly
2703
+ // as the literal-miss case above does, or a key the switch does not
2704
+ // recognize has nowhere sound to fall through to.
2705
+ const arms = [...new Set(shape.members.map((member) => member.type))];
2706
+ const keyType = keyArgument ? checker.getTypeAtLocation(keyArgument) : null;
2707
+ const index = shape.index.find((candidate) => keyType !== null &&
2708
+ ((candidate.key === 'string' && (keyType.flags & ts.TypeFlags.StringLike) !== 0) ||
2709
+ (candidate.key === 'number' && (keyType.flags & ts.TypeFlags.NumberLike) !== 0) ||
2710
+ (candidate.key === 'symbol' && (keyType.flags & ts.TypeFlags.ESSymbolLike) !== 0)));
2711
+ arms.push(index?.value ?? intern({ kind: 'primitive', primitive: 'any' }));
2712
+ // Through `unionOf`, like every sibling branch: an unreduced
2713
+ // `any | number` pair published `tagged-union(dynamic | number)`
2714
+ // for the `?.value` read, and the optional chain's `undefined`
2715
+ // arm has no conversion into that carrier, so a
2716
+ // `getOwnPropertyDescriptor(item, String(key))?.value` was refused
2717
+ // where its honest answer, as for `Array.prototype`'s element
2718
+ // above, is simply `any`.
2719
+ return unionOf(arms);
2720
+ }
2721
+ return null;
2722
+ }
2723
+ if (shape.kind === 'array') {
2724
+ const numberId = intern({ kind: 'primitive', primitive: 'number' });
2725
+ if (literalKey === 'length')
2726
+ return numberId;
2727
+ // An index's descriptor `value` is the STORED element, and an Array's
2728
+ // storage admits the language's `undefined` at a present index
2729
+ // independently of what its element type says: 12.9.6 gives a tagged
2730
+ // template's invalid escape an `undefined` cooked element inside an
2731
+ // array the checker still types `string`, and the runtime carries
2732
+ // exactly that as `ArrayObject`'s `undefineds` bit beside its element.
2733
+ // Answering with a bare `shape.element` gave the descriptor record no
2734
+ // carrier for that case, so the emitter proved the read unreachable
2735
+ // and `test/runtime/template-strings-array-identity.ts` aborted on
2736
+ // `gea::host::unreachableValue<std::string>()` -- with the emitter
2737
+ // side already correct (`indexDescriptor` in
2738
+ // `targets/cpp/host/emit-host-object.ts` handles the absent value) and
2739
+ // simply fed a false premise. Only the reflective read widens: a
2740
+ // TYPED read of the same index still publishes the element, because
2741
+ // the element type is what a typed read is entitled to.
2742
+ if (literalKey !== null && /^(0|[1-9]\d*)$/.test(literalKey))
2743
+ return unionOf([shape.element, intern({ kind: 'primitive', primitive: 'undefined' })]);
2744
+ // `extension` is the data an interface ADDS to the Array it extends --
2745
+ // `TemplateStringsArray`'s own `raw`, or `NodeArray<T>`'s `pos`/`end`.
2746
+ // A literal key naming one of those fields answers with that field's
2747
+ // OWN type: it is not an element (the element type is a red herring
2748
+ // for it) and not the generic "any other key" case either. Missing
2749
+ // this let `Object.getOwnPropertyDescriptor(templateStrings,
2750
+ // "raw").value` -- an array-object -- fall into the element/number
2751
+ // union below and mint `TaggedUnion<std::string, double>`, which then
2752
+ // refused every real read of `raw`'s array value at runtime.
2753
+ if (literalKey !== null) {
2754
+ const extensionMatch = shape.extension.find((member) => member.key.kind === 'string' && member.key.value === literalKey);
2755
+ if (extensionMatch)
2756
+ return extensionMatch.type;
2757
+ }
2758
+ else if (shape.extension.length > 0) {
2759
+ // A runtime key can equally name an extension field, so it must be
2760
+ // in the union the same way a record's runtime-key case unions its
2761
+ // declared members above.
2762
+ return unionOf([shape.element, numberId, ...shape.extension.map((member) => member.type)]);
2763
+ }
2764
+ return unionOf([shape.element, numberId]);
2765
+ }
2766
+ if (shape.kind === 'signature') {
2767
+ const name = ts.isPropertyAccessExpression(target) ? target.name : ts.isIdentifier(target) ? target : null;
2768
+ const symbol = name ? checker.getSymbolAtLocation(name) : undefined;
2769
+ const declaration = symbol ? identities.valueDeclarationOfSymbol(symbol) : null;
2770
+ // A host's own method (`Date.prototype.getTime`, `Array.from`) answers
2771
+ // the same two questions with the same two types: 10.2.10's `name`
2772
+ // and `length` are what a builtin function owns, and the emitter reads
2773
+ // both off the callable's facts. What stays refused is a callable
2774
+ // interface with declared members of its own, whose `name` could be
2775
+ // a data member the declaration states.
2776
+ // An OVERLOADED host method (`Array.from`, 4 signatures) stays on the
2777
+ // boxed path: its value has no single calling convention to carry,
2778
+ // so the typed descriptor arm could not receive it.
2779
+ const isRealFunction = declaration &&
2780
+ (ts.isFunctionDeclaration(declaration) ||
2781
+ ts.isFunctionExpression(declaration) ||
2782
+ ts.isArrowFunction(declaration) ||
2783
+ ((ts.isMethodSignature(declaration) || ts.isMethodDeclaration(declaration)) && shape.call.length === 1));
2784
+ if (!isRealFunction)
2785
+ return null;
2786
+ const stringId = intern({ kind: 'primitive', primitive: 'string' });
2787
+ const numberId = intern({ kind: 'primitive', primitive: 'number' });
2788
+ if (literalKey === 'name')
2789
+ return stringId;
2790
+ if (literalKey === 'length')
2791
+ return numberId;
2792
+ return intern({ kind: 'union', members: [stringId, numberId] });
2793
+ }
2794
+ if (shape.kind === 'union') {
2795
+ const arms = [];
2796
+ for (const member of shape.members) {
2797
+ const memberValueId = valueIdOfShape(table.get(member).shape);
2798
+ if (memberValueId === null)
2799
+ return null;
2800
+ if (!arms.includes(memberValueId))
2801
+ arms.push(memberValueId);
2802
+ }
2803
+ if (arms.length === 0)
2804
+ return null;
2805
+ return unionOf(arms);
2806
+ }
2807
+ return null;
2808
+ };
2809
+ const valueId = valueIdOfShape(table.get(mapper.typeAt(target)).shape);
2810
+ if (valueId === null)
2811
+ return null;
2812
+ const descriptor = intern({
2813
+ kind: 'object',
2814
+ members: [
2815
+ { key: { kind: 'string', value: 'value' }, type: valueId, optional: false, readonly: false, accessor: null },
2816
+ { key: { kind: 'string', value: 'writable' }, type: boolId, optional: false, readonly: false, accessor: null },
2817
+ { key: { kind: 'string', value: 'enumerable' }, type: boolId, optional: false, readonly: false, accessor: null },
2818
+ { key: { kind: 'string', value: 'configurable' }, type: boolId, optional: false, readonly: false, accessor: null }
2819
+ ],
2820
+ index: [],
2821
+ membersDropped: false
2822
+ });
2823
+ return intern({ kind: 'union', members: [descriptor, intern({ kind: 'primitive', primitive: 'undefined' })] });
2824
+ };
2825
+ // `X.prototype` on an ambient constructor. The checker types the slot as the
2826
+ // INSTANCE type, and following that answer makes `Date.prototype` a Date --
2827
+ // the same carrier as `new Date()`, which is exactly the object it is not:
2828
+ // reflection over it (`hasOwnProperty`, `getOwnPropertyDescriptor`, the
2829
+ // property helper's delete/restore) asks about the prototype's OWN
2830
+ // members. `bindHostObjectClosure` registers the slot's declaration as a
2831
+ // protocol of its own; this anchors a declared shape on that declaration,
2832
+ // carrying the instance's body so the member reads keep their signatures.
2833
+ const borrowedPrototypeMethodNames = new Set(['call', 'apply', 'bind']);
2834
+ // The ambient constructors whose `.prototype` methods, read as values, carry
2835
+ // an invoke that brand-checks a boxed receiver and dispatches to the
2836
+ // instance's own member (`hostPrototypeMethodValueText`, targets/cpp). A
2837
+ // constructor is added here only together with that dispatch: without it a
2838
+ // borrow through the prototype's method would compile to a callable that
2839
+ // throws for every receiver, which is a wrong answer where the instance
2840
+ // path at least refuses.
2841
+ const receiverDispatchingPrototypes = new Set(['Date']);
2842
+ /**
2843
+ * Prototype members whose `[[Call]]` is GENERIC over the receiver -- ECMA-262
2844
+ * 21.4.4.37 `Date.prototype.toJSON` runs ToPrimitive(this, number) and then
2845
+ * invokes `toISOString` on whatever it was given, never a brand check -- so
2846
+ * the boxed-receiver stub (`hostPrototypeMethodValueText`), whose invoke IS
2847
+ * a brand check, would render a borrow of it as a TypeError the language does
2848
+ * not throw. Such a borrow keeps the instance path's compile-time refusal
2849
+ * until the target states the generic form (ToPrimitive over a boxed value is
2850
+ * a runtime capability it does not carry yet); the VALUE read still renders,
2851
+ * so `name`/`length`/descriptor reflection over the member is untouched.
2852
+ */
2853
+ const receiverGenericPrototypeMembers = new Set(['toJSON']);
2854
+ const prototypeObjectTypeAt = (node) => {
2855
+ if (!ts.isPropertyAccessExpression(node) || node.name.text !== 'prototype')
2856
+ return null;
2857
+ const receiverType = checker.getTypeAtLocation(node.expression);
2858
+ if (receiverType.getConstructSignatures().length === 0)
2859
+ return null;
2860
+ const slot = checker.getPropertyOfType(receiverType, 'prototype');
2861
+ const declaration = slot?.valueDeclaration ?? slot?.declarations?.[0];
2862
+ if (!slot || !declaration || !declaration.getSourceFile().isDeclarationFile)
2863
+ return null;
2864
+ const instanceType = checker.getTypeOfSymbolAtLocation(slot, declaration);
2865
+ // `String.prototype.trim.call(s)` borrows the INSTANCE method: the read
2866
+ // off the prototype is the method the instance carrier already renders,
2867
+ // and the borrow lowers through it (`deferredFunctionCallCalleeOf`). A
2868
+ // prototype whose methods dispatch on a boxed receiver in the target
2869
+ // (`receiverDispatchingPrototypes`) has no use for that path: its own
2870
+ // method IS the borrow, brand check included, for a Date receiver and for
2871
+ // the this-value cases alike -- and the instance path never rendered the
2872
+ // `X.prototype` operand it needs (a handle into an instance cell).
2873
+ const member = node.parent;
2874
+ if (ts.isPropertyAccessExpression(member) && member.expression === node) {
2875
+ const borrow = member.parent;
2876
+ if (ts.isPropertyAccessExpression(borrow) && borrow.expression === member && borrowedPrototypeMethodNames.has(borrow.name.text)) {
2877
+ if (!receiverDispatchingPrototypes.has(instanceType.getSymbol()?.name ?? '') ||
2878
+ receiverGenericPrototypeMembers.has(member.name.text)) {
2879
+ return null;
2880
+ }
2881
+ }
2882
+ }
2883
+ const instance = table.get(typeOf(instanceType)).shape;
2884
+ // `Object.prototype`: the ONE ambient instance interface `typeOf`
2885
+ // deliberately collapses to `any` everywhere else
2886
+ // (`derived-expression-type.ts`'s `isGlobalObjectInterface` -- a
2887
+ // `: Object`-typed value states nothing, and that collapse is measured
2888
+ // and load-bearing, so it must keep firing for every OTHER read of this
2889
+ // exact `ts.Type`). This one occurrence names the SLOT itself, not an
2890
+ // ordinary Object-typed value: the declared shape it anchors is keyed by
2891
+ // the `prototype` slot's own declaration id, never by `instanceType`'s
2892
+ // shared identity, so it can safely carry a body the collapsed cache does
2893
+ // not. `Object`'s instance interface declares no DATA members at all --
2894
+ // `toString`/`valueOf`/`hasOwnProperty`/`isPrototypeOf`/
2895
+ // `propertyIsEnumerable`/`toLocaleString` are all methods -- so an empty
2896
+ // ambient body is the exact starting point `prototypeMethodBodyOf` needs
2897
+ // to inject them, the same way an ordinary ambient interned body is for
2898
+ // Date/RegExp/Boolean/String/Number.
2899
+ const dataBody = instance.kind === 'declared'
2900
+ ? instance.body
2901
+ : isGlobalObjectInterface(checker, declaration, instanceType)
2902
+ ? table.intern({ kind: 'object', members: [], index: [], membersDropped: true })
2903
+ : null;
2904
+ if (instance.kind !== 'declared' && dataBody === null)
2905
+ return null;
2906
+ const id = identities.declarationIdOf(declaration);
2907
+ const { id: anchor, fresh } = table.anchor(`declared:${id}:`);
2908
+ if (fresh)
2909
+ table.complete(anchor, {
2910
+ kind: 'declared',
2911
+ declaration: id,
2912
+ typeArguments: [],
2913
+ body: prototypeMethodBodyOf(dataBody, instanceType)
2914
+ });
2915
+ return anchor;
2916
+ };
2917
+ // The prototype object's body: the instance's data members, plus every
2918
+ // method the instance interface declares -- an ambient body is interned
2919
+ // DATA-ONLY (`membersDropped`), and the prototype is exactly the object
2920
+ // whose own members those methods are. A prototype method read as a VALUE
2921
+ // takes its receiver from whoever calls it -- `getTime.call(0)`,
2922
+ // `getTime.call(new Date())` -- and 21.4.4's `thisTimeValue(this value)`
2923
+ // decides at that moment whether it is a Date. An interface method's
2924
+ // signature carries no receiver (its `this` is the instance, implicitly,
2925
+ // never a physical slot), so the prototype's copy of each method states
2926
+ // one: `any`, the carrier that holds every value a caller may pass. The
2927
+ // emitted callable (`hostPrototypeMethodValueText`) performs the brand
2928
+ // check on it.
2929
+ const prototypeMethodBodyOf = (body, instanceType) => {
2930
+ if (body === null)
2931
+ return null;
2932
+ const shape = table.get(body).shape;
2933
+ if (shape.kind !== 'object')
2934
+ return body;
2935
+ const receiver = table.intern({ kind: 'primitive', primitive: 'any' });
2936
+ const methods = [];
2937
+ for (const symbol of checker.getPropertiesOfType(instanceType)) {
2938
+ const method = symbol.declarations?.find(ts.isMethodSignature);
2939
+ if (!method || shape.members.some((member) => member.key.kind === 'string' && member.key.value === symbol.getName()))
2940
+ continue;
2941
+ const type = table.get(typeOf(checker.getTypeOfSymbolAtLocation(symbol, method))).shape;
2942
+ if (type.kind !== 'signature' || type.call.length === 0)
2943
+ continue;
2944
+ // An overloaded method (`toLocaleDateString(): string` beside
2945
+ // `(locales?, options?): string`) is one function object with one
2946
+ // frame; the copy states its widest overload, which every narrower
2947
+ // call fits through its optionals.
2948
+ const widest = type.call.reduce((best, signature) => (signature.parameters.length > best.parameters.length ? signature : best));
2949
+ methods.push({
2950
+ key: { kind: 'string', value: symbol.getName() },
2951
+ type: table.intern({ ...type, call: [{ ...widest, thisParameter: receiver }] }),
2952
+ optional: false,
2953
+ readonly: false,
2954
+ accessor: null
2955
+ });
2956
+ }
2957
+ return table.intern({ ...shape, members: [...shape.members, ...methods], membersDropped: false });
2958
+ };
2959
+ // A method read off the prototype object (`Date.prototype.getTime`, or
2960
+ // `obj.getTime` where `obj` is the prototype through a parameter) is the
2961
+ // prototype's own copy of it -- the receiver-taking signature above -- not
2962
+ // the instance's, which is what the checker answers for the access.
2963
+ const prototypeObjectMemberTypeAt = (node) => {
2964
+ if (!ts.isPropertyAccessExpression(node))
2965
+ return null;
2966
+ const receiver = prototypeObjectTypeAt(node.expression) ?? prototypeObjectParameterTypeAt(node.expression);
2967
+ if (receiver === null)
2968
+ return null;
2969
+ const shape = table.get(receiver).shape;
2970
+ if (shape.kind !== 'declared' || shape.body === null)
2971
+ return null;
2972
+ const body = table.get(shape.body).shape;
2973
+ if (body.kind !== 'object')
2974
+ return null;
2975
+ const member = body.members.find((candidate) => candidate.key.kind === 'string' && candidate.key.value === node.name.text);
2976
+ return member?.type ?? null;
2977
+ };
2978
+ // A local initialized to the prototype object or one of its methods
2979
+ // (`var getTime = Date.prototype.getTime`) and never written again holds
2980
+ // exactly that value: the declaration and every read of it answer the
2981
+ // prototype's own type, ahead of the local census, whose ts.Type-space
2982
+ // answer is the instance's. Asked at the declaration AND at each reference
2983
+ // so the cell and its reads cannot disagree (the trap the note at the top
2984
+ // of `typeAt` describes).
2985
+ const prototypeObjectLocalTypeAt = (node) => {
2986
+ const declaration = ts.isVariableDeclaration(node)
2987
+ ? node
2988
+ : ts.isIdentifier(node) && !ts.isVariableDeclaration(node.parent)
2989
+ ? (checker.getSymbolAtLocation(node)?.valueDeclaration ?? null)
2990
+ : null;
2991
+ if (declaration === null || !ts.isVariableDeclaration(declaration) || !declaration.initializer || !ts.isIdentifier(declaration.name))
2992
+ return null;
2993
+ const initializer = declaration.initializer;
2994
+ if (!ts.isPropertyAccessExpression(initializer))
2995
+ return null;
2996
+ const writes = flow?.writesToDeclaration(declaration) ?? null;
2997
+ // Only a WHOLE-slot write re-binds the cell; `f[k] = v` on the held method
2998
+ // (propertyHelper's `isWritable` writing `length`) is a member write on
2999
+ // the function object the cell keeps holding.
3000
+ if (writes === null || writes.some((write) => write.slot === 'whole' && write.value !== initializer))
3001
+ return null;
3002
+ return prototypeObjectMemberTypeAt(initializer) ?? prototypeObjectTypeAt(initializer);
3003
+ };
3004
+ // A parameter every call site hands `X.prototype` to, and every read of it:
3005
+ // the census bound it to the checker's image of the argument (the instance
3006
+ // type), so it is re-asked here from the argument expressions themselves.
3007
+ // One disagreeing site returns the question to the census's answer.
3008
+ const prototypeObjectParameterTypeAt = (node, visiting = new Set()) => {
3009
+ const parameter = ts.isParameter(node)
3010
+ ? node
3011
+ : ts.isIdentifier(node) && !ts.isParameter(node.parent)
3012
+ ? (checker.getSymbolAtLocation(node)?.valueDeclaration ?? null)
3013
+ : null;
3014
+ if (parameter === null || !ts.isParameter(parameter) || visiting.has(parameter))
3015
+ return null;
3016
+ const passed = parameters.argumentsAt?.(parameter) ?? null;
3017
+ if (passed === null || passed.length === 0)
3018
+ return null;
3019
+ visiting.add(parameter);
3020
+ let agreed = null;
3021
+ for (const argument of passed) {
3022
+ // The handle travels through helper calls (`verifyProperty(obj, ...)`
3023
+ // forwards `obj` to `isWritable(obj, ...)`), so an argument that is
3024
+ // itself such a parameter is asked the same question.
3025
+ const own = prototypeObjectTypeAt(argument) ??
3026
+ prototypeObjectMemberTypeAt(argument) ??
3027
+ prototypeObjectLocalTypeAt(argument) ??
3028
+ prototypeObjectParameterTypeAt(argument, visiting);
3029
+ if (own === null || (agreed !== null && agreed !== own))
3030
+ return null;
3031
+ agreed = own;
3032
+ }
3033
+ return agreed;
3034
+ };
3035
+ // The SIGNATURE side of the `unstated-never-array` rule's parameter form.
3036
+ // A parameter the collection census refused as part of an array's alias
3037
+ // component carries the box the caller's own cell carries; without this the
3038
+ // body's binding reads that box while the ABI still declares the checker's
3039
+ // image of the parameter, and `projection/abi.ts` refuses the convention
3040
+ // with "parameter N is bound as X but the ABI declares Y".
3041
+ const refusedArrayParameterTypeAt = (parameter) => {
3042
+ if (!unstatedNeverArray(checker, collections, layoutTypeAt, parameter))
3043
+ return null;
3044
+ return table.intern({
3045
+ kind: 'array',
3046
+ element: table.intern({ kind: 'primitive', primitive: 'any' }),
3047
+ readonly: false,
3048
+ extension: []
3049
+ });
3050
+ };
3051
+ /** A callable type with the receiver its signatures state removed: what `Function.prototype.bind` produces. */
3052
+ const withoutReceiver = (id) => {
3053
+ const shape = table.get(id).shape;
3054
+ if (shape.kind === 'union')
3055
+ return table.intern({ ...shape, members: shape.members.map(withoutReceiver) });
3056
+ if (shape.kind !== 'signature' || shape.call.every((call) => call.thisParameter === null))
3057
+ return id;
3058
+ return table.intern({ ...shape, call: shape.call.map((call) => ({ ...call, thisParameter: null })) });
3059
+ };
3060
+ const boundCallResultAt = (node) => ts.isCallExpression(node) && builtinBindSignatureAt(node.expression) ? withoutReceiver(typeOf(checker.getTypeAtLocation(node))) : null;
3061
+ /**
3062
+ * `const readFile = host.readFile.bind(host)`: the cell, and every read of
3063
+ * it, holds what the bind produced. The checker types both with the
3064
+ * METHOD's own type (the same object `OmitThisParameter` hands back), so
3065
+ * the answer has to come from the initializer. A `let` keeps the checker's
3066
+ * type: a later write may store a method value the cell then has to bind.
3067
+ */
3068
+ const boundCellResultAt = (node) => {
3069
+ const declaration = ts.isVariableDeclaration(node)
3070
+ ? node
3071
+ : ts.isIdentifier(node)
3072
+ ? checker.getSymbolAtLocation(node)?.valueDeclaration
3073
+ : undefined;
3074
+ if (!declaration || !ts.isVariableDeclaration(declaration) || declaration.type !== undefined || !declaration.initializer)
3075
+ return null;
3076
+ if ((ts.getCombinedNodeFlags(declaration) & ts.NodeFlags.Const) === 0)
3077
+ return null;
3078
+ return boundCallResultAt(declaration.initializer);
3079
+ };
3080
+ /** The one `Function.prototype.bind` overload this call site resolved to, or `null` where the read is not that. */
3081
+ const builtinBindSignatureAt = (node) => {
3082
+ if (!ts.isPropertyAccessExpression(node) || node.name.text !== 'bind')
3083
+ return null;
3084
+ const call = node.parent;
3085
+ if (!ts.isCallExpression(call) || call.expression !== node)
3086
+ return null;
3087
+ // `host.realpath?.bind(host)`: an optional link's own type is the union
3088
+ // with the absence, which declares no call signature at all -- the
3089
+ // callable this binds is the payload.
3090
+ const receiver = checker.getNonNullableType(checker.getTypeAtLocation(node.expression));
3091
+ if (checker.getSignaturesOfType(receiver, ts.SignatureKind.Call).length === 0)
3092
+ return null;
3093
+ if (checker.getNonNullableType(checker.getTypeAtLocation(node)).getCallSignatures().length < 2)
3094
+ return null;
3095
+ const resolved = checker.getResolvedSignature(call);
3096
+ // Only the ambient declaration's own overloads: a program declaring its
3097
+ // own `bind` member keeps whatever its declaration states.
3098
+ return resolved?.declaration?.getSourceFile().isDeclarationFile ? resolved : null;
3099
+ };
3100
+ /** Whether `node` is a `for (const key in object)` head the loop declares, or a read of one. */
3101
+ const forInKeyAt = (node) => {
3102
+ // The declaration node itself is what `producers/bindings.ts` asks for the
3103
+ // cell's carrier; an identifier is every read of it.
3104
+ const declarations = ts.isVariableDeclaration(node)
3105
+ ? [node]
3106
+ : ts.isIdentifier(node)
3107
+ ? (checker.getSymbolAtLocation(node)?.declarations ?? [])
3108
+ : [];
3109
+ const declaration = declarations.length === 1 ? declarations[0] : undefined;
3110
+ if (!declaration || !ts.isVariableDeclaration(declaration) || !ts.isIdentifier(declaration.name))
3111
+ return false;
3112
+ const list = declaration.parent;
3113
+ if (!ts.isVariableDeclarationList(list))
3114
+ return false;
3115
+ const statement = list.parent;
3116
+ return ts.isForInStatement(statement) && statement.initializer === list;
3117
+ };
3118
+ /**
3119
+ * What a binding pattern's own INITIALIZER is worth to the pattern.
3120
+ *
3121
+ * Normally the initializer expression itself, which is what the pattern
3122
+ * destructures. An `as`/`satisfies`/`!`/`<T>x` wrapper is the exception, and
3123
+ * only when what it wraps is an ARRAY: those wrappers evaluate to nothing of
3124
+ * their own (`producers/erasure.ts`), so `citeExpressionResult` cites the
3125
+ * WRAPPED expression's result -- and the pattern that then reads that result
3126
+ * by index was being typed off the assertion instead. hono's
3127
+ * `defineWebSocketHelper` writes the shape exactly: `const [createEvents,
3128
+ * options] = args as [(c: Ctx) => Events, number?]` over a rest parameter,
3129
+ * whose value is one Array. `lower-destructuring.ts` refused the pair --
3130
+ * 'an array binding pattern's source resolved to "array-object(...)", but its
3131
+ * own iterator-record result selected "record(...)"' -- and it was right to:
3132
+ * the two really did describe different values.
3133
+ *
3134
+ * The assertion is not discarded, it is put where it belongs. A tuple
3135
+ * assertion over an array states the ARITY and the per-position types the
3136
+ * program is claiming, which the element reads still take from the pattern's
3137
+ * raw checker type (`producers/destructuring.ts`'s `elementTypeOf` asks
3138
+ * `isTupleType` of it); what it cannot state is a different CARRIER, because
3139
+ * `as` performs no conversion. Gated on the wrapped value actually being an
3140
+ * array so nothing else moves: an assertion over a `foo()` whose own type is
3141
+ * `unknown` keeps answering from the assertion, where it is the only thing
3142
+ * that states anything at all.
3143
+ */
3144
+ const patternSourceTypeAt = (initializer) => {
3145
+ const erased = unwrapErasedExpression(initializer);
3146
+ if (erased === initializer)
3147
+ return mapper.typeAt(initializer);
3148
+ const source = mapper.typeAt(erased);
3149
+ return table.get(source).shape.kind === 'array' ? source : mapper.typeAt(initializer);
3150
+ };
3151
+ /**
3152
+ * Every step of `typeAt`, in the order the chain asked them.
3153
+ *
3154
+ * the frontend's evidence-policy tables. This was thirty-nine `if (answer)
3155
+ * return answer` statements whose ORDER was the answer wherever two of them
3156
+ * could speak for one node -- and which of them could was not written down
3157
+ * anywhere, because an `if` states no domain. Stating each step as a rule
3158
+ * that names the FORMS it serves makes the domain a declaration: a rule that
3159
+ * cannot answer for a node is never asked, and two rules claiming one form
3160
+ * are a disagreement `GEA_STRUCTURAL_DISAGREEMENT` can name, rather than a
3161
+ * precedence nobody chose.
3162
+ *
3163
+ * Order is preserved exactly as the chain had it, so this port changes no
3164
+ * answer. `forms: null` means the step's own first test is not a node-kind
3165
+ * test, so its domain is still unknown and order still decides for it; each
3166
+ * one is a row this phase owes a form, and the count of them is the honest
3167
+ * measure of how far the port has got.
3168
+ */
3169
+ const mutableMethods = createMutableMethodResolver(checker, table, flow, signatureOf, (node) => mapper.typeAt(node), (node) => mapper.rawTypeAt(node));
3170
+ const structuralRules = [
3171
+ {
3172
+ name: 'mutable-method-storage',
3173
+ forms: [ts.SyntaxKind.PropertyAccessExpression, ts.SyntaxKind.ElementAccessExpression],
3174
+ resolve: mutableMethods.readTypeAt
3175
+ },
3176
+ {
3177
+ // A CommonJS wrapper's `module` is not the ambient `{ exports: any }`
3178
+ // silhouette when the source itself proves one exact top-level callable
3179
+ // export. Keep the record local to that source module and map the same
3180
+ // expression at `module.exports` and a resolved `require` so a binding
3181
+ // cannot store a function while its read asks for a dynamic record.
3182
+ name: 'module-exports-record',
3183
+ forms: [ts.SyntaxKind.Identifier],
3184
+ resolve: (node) => {
3185
+ const moduleExport = moduleRecords.moduleExportExpressionAt(node);
3186
+ if (moduleExport) {
3187
+ return table.intern({
3188
+ kind: 'object',
3189
+ members: [
3190
+ {
3191
+ key: { kind: 'string', value: 'exports' },
3192
+ type: mapper.typeAt(moduleExport),
3193
+ optional: false,
3194
+ readonly: false,
3195
+ accessor: null
3196
+ }
3197
+ ],
3198
+ index: [],
3199
+ membersDropped: false
3200
+ });
3201
+ }
3202
+ return null;
3203
+ }
3204
+ },
3205
+ {
3206
+ name: 'exported-expression',
3207
+ // The erasure wrappers are in the domain because `unwrapExpression` peels
3208
+ // them before testing for an `exports` access, so the node ASKED about can
3209
+ // be the wrapper rather than the access underneath it.
3210
+ forms: [
3211
+ ts.SyntaxKind.PropertyAccessExpression,
3212
+ ts.SyntaxKind.ElementAccessExpression,
3213
+ ts.SyntaxKind.ParenthesizedExpression,
3214
+ ts.SyntaxKind.AsExpression,
3215
+ ts.SyntaxKind.TypeAssertionExpression,
3216
+ ts.SyntaxKind.NonNullExpression,
3217
+ ts.SyntaxKind.SatisfiesExpression,
3218
+ ts.SyntaxKind.PartiallyEmittedExpression,
3219
+ ts.SyntaxKind.CallExpression
3220
+ ],
3221
+ resolve: (node) => {
3222
+ const exported = moduleRecords.exportExpressionAt(node) ?? moduleRecords.requiredExportExpressionAt(node);
3223
+ if (exported)
3224
+ return mapper.typeAt(exported);
3225
+ return null;
3226
+ }
3227
+ },
3228
+ {
3229
+ // `undefined as unknown as number` -- the shape every hand-written
3230
+ // iterator's `done: true` result has. An assertion is not a conversion:
3231
+ // the value that actually arrives is still the literal, and the asserted
3232
+ // type is only what consumers must accept. Publishing the asserted type
3233
+ // alone gave `{ value: undefined as unknown as number }` a `double` field,
3234
+ // and the emitter then had nowhere to put an `undefined` that faults --
3235
+ // `cppConstantLiteral` refuses a `double` for exactly that reason, so the
3236
+ // absence has to be in the carrier or the program has no honest emission.
3237
+ name: 'absence-assertion',
3238
+ forms: [ts.SyntaxKind.AsExpression, ts.SyntaxKind.TypeAssertionExpression],
3239
+ resolve: (node) => {
3240
+ if (ts.isAsExpression(node) || ts.isTypeAssertionExpression(node)) {
3241
+ const inner = unwrapErasedExpression(node.expression);
3242
+ const absent = inner.kind === ts.SyntaxKind.NullKeyword ? 'null' : ts.isIdentifier(inner) && inner.text === 'undefined' ? 'undefined' : null;
3243
+ if (absent !== null) {
3244
+ const asserted = typeOf(checker.getTypeAtLocation(node));
3245
+ return table.intern({ kind: 'union', members: [asserted, table.intern({ kind: 'primitive', primitive: absent })] });
3246
+ }
3247
+ }
3248
+ return null;
3249
+ }
3250
+ },
3251
+ {
3252
+ // A `for (const key in object)` head, and every read of it. The language
3253
+ // answers outright and without reference to the object: for-in enumerates
3254
+ // own enumerable STRING keys. TypeScript spells the binding
3255
+ // `Extract<keyof T, string>` so an index back into the same object narrows,
3256
+ // and inside a generic that spelling stays a conditional the checker
3257
+ // defers -- so the binding and every read in the loop body published an
3258
+ // unresolved carrier. tsc's `assign` and `copyProperties` are the measured
3259
+ // case; the census answers `string` for the bare-identifier and
3260
+ // destructured heads already, and a head the loop DECLARES had no rule.
3261
+ name: 'for-in-key-is-a-string',
3262
+ forms: [ts.SyntaxKind.VariableDeclaration, ts.SyntaxKind.Identifier],
3263
+ resolve: (node) => {
3264
+ if (forInKeyAt(node))
3265
+ return typeOf(checker.getStringType());
3266
+ return null;
3267
+ }
3268
+ },
3269
+ {
3270
+ // A binding, a read of it, or the choice expression itself, holding one of
3271
+ // several generic source functions: the union of the members' OPEN types,
3272
+ // never the checker's subtype-reduced declared type -- see
3273
+ // `generic-function-choice.ts`. Interned through this view's `typeOf`, so
3274
+ // a member whose type parameters THIS path binds (its own copy) reads as
3275
+ // that copy's closed callable, exactly as its bare name would.
3276
+ name: 'generic-function-choice',
3277
+ forms: [
3278
+ ts.SyntaxKind.ConditionalExpression,
3279
+ ts.SyntaxKind.BinaryExpression,
3280
+ ts.SyntaxKind.VariableDeclaration,
3281
+ ts.SyntaxKind.Identifier,
3282
+ ts.SyntaxKind.PropertyAccessExpression,
3283
+ ts.SyntaxKind.ParenthesizedExpression,
3284
+ ts.SyntaxKind.AsExpression,
3285
+ ts.SyntaxKind.NonNullExpression,
3286
+ ts.SyntaxKind.SatisfiesExpression,
3287
+ ts.SyntaxKind.TypeAssertionExpression
3288
+ ],
3289
+ resolve: (node) => {
3290
+ const choice = genericFunctionChoiceMembersOf(checker, node);
3291
+ if (choice) {
3292
+ return table.intern({
3293
+ kind: 'union',
3294
+ members: choice.map((member) => typeOf(checker.getTypeAtLocation(member.name ?? member)))
3295
+ });
3296
+ }
3297
+ return null;
3298
+ }
3299
+ },
3300
+ {
3301
+ // A generic source function handed to a slot that states ONE closed
3302
+ // signature: `match: typeof match<Router<T>, T> = match` (hono's
3303
+ // `RegExpRouter`), `const f: (x: number) => number = identity`.
3304
+ //
3305
+ // The checker's type for the name is the OPEN generic, which derives to
3306
+ // `generic-function-set` -- a choice tag, not a callable -- while the
3307
+ // slot derives to `function-value-dispatch`. No conversion exists
3308
+ // between the two and none can: a set index is not a frame. The two
3309
+ // authorities disagree and the slot is the one that is right, because it
3310
+ // states the instantiation and the name states none.
3311
+ //
3312
+ // Reading the contextual signature here is the SAME question
3313
+ // `specialization.ts`'s `fromValueUse` already asks at this same node to
3314
+ // mint the copy (its "contextual type is a closed signature" branch), so
3315
+ // the copy this type names exists by construction rather than by
3316
+ // coincidence. Only a contextual type with exactly one call signature
3317
+ // and no type parameters of its own qualifies: a generic contextual type
3318
+ // (`const nodeVisitor: NodeVisitor = visitNode`) is a set the value stays
3319
+ // open in, and an overload set states no single frame.
3320
+ name: 'generic-function-value-at-stated-instantiation',
3321
+ forms: [ts.SyntaxKind.Identifier],
3322
+ resolve: (node) => {
3323
+ if (!ts.isIdentifier(node) || !ts.isExpression(node))
3324
+ return null;
3325
+ const declaration = checker.getSymbolAtLocation(node)?.declarations?.[0];
3326
+ if (!declaration || !genericSourceFunctionDeclarationOf(declaration))
3327
+ return null;
3328
+ const contextual = checker.getContextualType(node);
3329
+ const signatures = contextual?.getCallSignatures() ?? [];
3330
+ const only = signatures.length === 1 ? signatures[0] : undefined;
3331
+ if (!contextual || !only || (only.getTypeParameters()?.length ?? 0) > 0)
3332
+ return null;
3333
+ if (contextual.getConstructSignatures().length > 0)
3334
+ return null;
3335
+ return typeOf(contextual);
3336
+ }
3337
+ },
3338
+ {
3339
+ // A binding pattern's type IS its source's: the pattern is the reference
3340
+ // half of `bind(reference, value)` and holds nothing of its own. The
3341
+ // checker types the pattern node from its own shape instead (a `[]`
3342
+ // initializer contextually typed by the pattern becomes the empty TUPLE
3343
+ // at the pattern while the literal itself is an array).
3344
+ name: 'binding-pattern-is-its-source',
3345
+ forms: [ts.SyntaxKind.ArrayBindingPattern, ts.SyntaxKind.ObjectBindingPattern],
3346
+ resolve: (node) => {
3347
+ // Re-tested rather than left to `forms`: a rule must answer correctly
3348
+ // for ANY node it is handed. `forms` is a claim the dispatcher can act
3349
+ // on and the audit can check, never the thing that makes a rule right
3350
+ // -- and this rule proved why. It was the first one ported, its kind
3351
+ // test was lifted into `forms` instead of kept, and it then answered
3352
+ // for call expressions, identifiers and string literals the moment
3353
+ // `GEA_STRUCTURAL_FORM_AUDIT` asked it outside its declared forms.
3354
+ if (!ts.isArrayBindingPattern(node) && !ts.isObjectBindingPattern(node))
3355
+ return null;
3356
+ const parent = node.parent;
3357
+ if (ts.isVariableDeclaration(parent) && parent.initializer)
3358
+ return patternSourceTypeAt(parent.initializer);
3359
+ if (ts.isParameter(parent) || ts.isBindingElement(parent))
3360
+ return mapper.typeAt(parent);
3361
+ return null;
3362
+ }
3363
+ },
3364
+ {
3365
+ // `Function.prototype.bind`, read as the callee of its own call. The
3366
+ // ambient declaration is FIVE overloads -- one per bound-argument arity --
3367
+ // and a value cannot be five conventions, so interning the read's own type
3368
+ // published `unresolved(no primitive joining 2 overload signatures into
3369
+ // one calling convention)` and killed every `host.readFile.bind(host)` in
3370
+ // the program (tsc's `program.ts`, `maybeBind`). TypeScript has already
3371
+ // chosen one overload at this site -- the argument count and the source's
3372
+ // own `this` type decide it -- so the read is that one signature, asked
3373
+ // for at the call the read is the callee of and nowhere else.
3374
+ //
3375
+ // `.call`/`.apply` need no such rule: each is declared once, and a borrow
3376
+ // through them is rewritten at the call anyway
3377
+ // (`ir/lower-invocation.ts`'s `deferredExplicitThisCalleeOf`).
3378
+ //
3379
+ // Asked EARLY: an optional link (`host.realpath?.bind`) is a union of the
3380
+ // overload set with the absence, and the local-union resolver above would
3381
+ // otherwise publish that union -- overload set included -- before this
3382
+ // rule was ever reached. The absence itself is kept, since the read really
3383
+ // can produce none.
3384
+ name: 'builtin-bind-signature',
3385
+ forms: [ts.SyntaxKind.PropertyAccessExpression],
3386
+ resolve: (node) => {
3387
+ const boundBuiltin = builtinBindSignatureAt(node);
3388
+ if (boundBuiltin) {
3389
+ // The overload's result is the bound callable, receiver-less -- the
3390
+ // same answer the call node gives below, so the invocation producer
3391
+ // sees one return type from both.
3392
+ const signature = signatureOf(boundBuiltin);
3393
+ const bound = table.intern({
3394
+ kind: 'signature',
3395
+ call: [{ ...signature, result: withoutReceiver(signature.result) }],
3396
+ construct: []
3397
+ });
3398
+ const own = checker.getTypeAtLocation(node);
3399
+ const absences = (own.isUnion() ? own.types : []).filter((member) => (member.flags & (ts.TypeFlags.Undefined | ts.TypeFlags.Null)) !== 0);
3400
+ return absences.length === 0 ? bound : table.intern({ kind: 'union', members: [bound, ...absences.map(typeOf)] });
3401
+ }
3402
+ return null;
3403
+ }
3404
+ },
3405
+ {
3406
+ // The bound function `host.readFile.bind(host)` PRODUCES: the checker
3407
+ // types it `OmitThisParameter<T>`, which for a method is `T` itself, and
3408
+ // `T`'s signature still names the method's implicit receiver
3409
+ // (`structural-receiver.ts`). The bound callable has none -- `bind` fixed
3410
+ // it -- so a value read out of this call must state a receiver-less
3411
+ // convention, or every slot it enters would be asked to bind the receiver
3412
+ // a second time. The absence of an optional link is kept as above.
3413
+ name: 'bound-call-result',
3414
+ forms: [ts.SyntaxKind.CallExpression, ts.SyntaxKind.VariableDeclaration, ts.SyntaxKind.Identifier],
3415
+ resolve: (node) => {
3416
+ const bound = boundCallResultAt(node) ?? boundCellResultAt(node);
3417
+ if (bound !== null)
3418
+ return bound;
3419
+ return null;
3420
+ }
3421
+ },
3422
+ {
3423
+ name: 'prototype-object-local',
3424
+ forms: [ts.SyntaxKind.VariableDeclaration, ts.SyntaxKind.Identifier],
3425
+ resolve: (node) => {
3426
+ const prototypeLocal = prototypeObjectLocalTypeAt(node);
3427
+ if (prototypeLocal)
3428
+ return prototypeLocal;
3429
+ return null;
3430
+ }
3431
+ },
3432
+ {
3433
+ name: 'array-pattern-rest',
3434
+ // The identifier arm resolves a SYMBOL to its declaration, so what that
3435
+ // declaration turns out to be does not widen the domain: the node asked
3436
+ // about is still only ever the element or a name for it.
3437
+ forms: [ts.SyntaxKind.BindingElement, ts.SyntaxKind.Identifier],
3438
+ resolve: (node) => {
3439
+ const restArray = arrayPatternRestTypeAt(node);
3440
+ if (restArray)
3441
+ return restArray;
3442
+ return null;
3443
+ }
3444
+ },
3445
+ {
3446
+ name: 'rest-assignment-array-shape',
3447
+ forms: [ts.SyntaxKind.VariableDeclaration, ts.SyntaxKind.Identifier],
3448
+ resolve: (node) => {
3449
+ const restAssignmentArray = restAssignmentArrayShapeAt(node);
3450
+ if (restAssignmentArray)
3451
+ return restAssignmentArray;
3452
+ return null;
3453
+ }
3454
+ },
3455
+ {
3456
+ name: 'local-union',
3457
+ forms: [ts.SyntaxKind.VariableDeclaration, ts.SyntaxKind.Identifier],
3458
+ resolve: (node) => {
3459
+ const localUnion = localUnionAt(node);
3460
+ if (localUnion)
3461
+ return localUnion;
3462
+ return null;
3463
+ }
3464
+ },
3465
+ {
3466
+ name: 'implicit-arguments-object',
3467
+ forms: [ts.SyntaxKind.Identifier],
3468
+ resolve: (node) => {
3469
+ if (!isArgumentsObjectIdentifier(node, checker))
3470
+ return null;
3471
+ const owner = enclosingArgumentsFunction(node);
3472
+ const signature = owner ? checker.getSignatureFromDeclaration(owner) : undefined;
3473
+ const slot = signature ? implicitArgumentsSlotOf(signature) : null;
3474
+ if (!signature || !slot)
3475
+ return null;
3476
+ // The ABI and arguments allocation already use this signature's sealed
3477
+ // phantom slot. Publish that same carrier at the expression, so indexed
3478
+ // reads do not recover their element from lib.d.ts's erased IArguments.
3479
+ const frame = table.get(mapper.resolvedSignatureTypeOf(signature, 'call')).shape;
3480
+ return frame.kind === 'signature' ? (frame.call[0]?.parameters[slot.ordinal]?.type ?? null) : null;
3481
+ }
3482
+ },
3483
+ {
3484
+ // `Array.isArray(x) ? x[0] : x` where nothing in `x` is assignable to
3485
+ // the predicate's `any[]`: TypeScript narrows `x` to `T & any[]` rather
3486
+ // than to `never`, and types the read `any`. That `any` is the failed
3487
+ // narrowing's artifact, not a boundary the program declared -- see
3488
+ // `arrayPredicateNarrowedTypeOf`. Asked BEFORE the array read below,
3489
+ // because the receiver is still that intersection and the carrier it
3490
+ // interns is not the one the read should be resolved through.
3491
+ name: 'array-predicate-narrowed-element',
3492
+ forms: [ts.SyntaxKind.ElementAccessExpression],
3493
+ resolve: (node) => {
3494
+ if (!ts.isElementAccessExpression(node))
3495
+ return null;
3496
+ const element = arrayPredicateNarrowedElementTypeOf(checker, node);
3497
+ return element === null ? null : typeOf(element);
3498
+ }
3499
+ },
3500
+ {
3501
+ name: 'structural-array-read',
3502
+ forms: [ts.SyntaxKind.ElementAccessExpression],
3503
+ resolve: (node) => {
3504
+ const censusedArrayElement = ts.isElementAccessExpression(node)
3505
+ ? inferredArrayElementAt(checker, collections, layoutTypeAt, node.expression)
3506
+ : null;
3507
+ // Read through the receiver's actual structural carrier whenever the
3508
+ // checker left the indexed result unstated. A parameter census was the
3509
+ // first place this mattered, but it is not the only place: an evolving
3510
+ // local `const values = []` is deliberately corrected below to
3511
+ // `array<any>` when no write census can prove a narrower element, while
3512
+ // `values[i]` can still be reported as `never` at an earlier flow point.
3513
+ // Taking the result from that stale checker view gives one cell two
3514
+ // answers -- an array that physically stores values and an indexed read
3515
+ // with no carrier. The receiver is a child of the access, so resolving it
3516
+ // here strictly descends the AST and cannot recurse back to this node.
3517
+ const arrayReadSource = ts.isElementAccessExpression(node)
3518
+ ? censusedArrayElement
3519
+ ? table.intern({ kind: 'array', element: typeOf(censusedArrayElement), readonly: false, extension: [] })
3520
+ : (localUnionAt(node.expression) ?? mapper.typeAt(node.expression))
3521
+ : null;
3522
+ const arrayRead = structuralArrayReadAt(checker, table, arrayReadSource, node);
3523
+ if (arrayRead)
3524
+ return arrayRead;
3525
+ return null;
3526
+ }
3527
+ },
3528
+ {
3529
+ // A recovered dynamic receiver makes the checker's downstream `never`
3530
+ // stale as well. This occurs one link after an evolving-array repair:
3531
+ // the checker typed `values[i]` as `never`, so it also typed
3532
+ // `values[i].field` as `never`; the mapper has since established that
3533
+ // the indexed value is `any`, whose property result is necessarily the
3534
+ // same dynamic boundary. Follow only that exact bottom-vs-any mismatch.
3535
+ // A genuinely `never` receiver and every statically shaped receiver keep
3536
+ // their own property type.
3537
+ name: 'never-property-of-any-receiver',
3538
+ forms: [ts.SyntaxKind.PropertyAccessExpression],
3539
+ resolve: (node) => {
3540
+ if (ts.isPropertyAccessExpression(node) && (absentSubstitutedTypeAt(node).flags & ts.TypeFlags.Never) !== 0) {
3541
+ const receiver = mapper.typeAt(node.expression);
3542
+ const receiverShape = table.get(receiver).shape;
3543
+ if (receiverShape.kind === 'primitive' && receiverShape.primitive === 'any')
3544
+ return receiver;
3545
+ }
3546
+ return null;
3547
+ }
3548
+ },
3549
+ {
3550
+ name: 'prototype-object',
3551
+ // The union of the three resolvers this rule ORs: two answer for a
3552
+ // property access, the third for a parameter or a name of one.
3553
+ forms: [ts.SyntaxKind.PropertyAccessExpression, ts.SyntaxKind.Parameter, ts.SyntaxKind.Identifier],
3554
+ resolve: (node) => {
3555
+ const prototypeObject = prototypeObjectTypeAt(node) ?? prototypeObjectParameterTypeAt(node) ?? prototypeObjectMemberTypeAt(node);
3556
+ if (prototypeObject)
3557
+ return prototypeObject;
3558
+ return null;
3559
+ }
3560
+ },
3561
+ {
3562
+ name: 'evolving-array-member',
3563
+ forms: [ts.SyntaxKind.PropertyAccessExpression],
3564
+ resolve: (node) => {
3565
+ const evolvingArrayMember = evolvingArrayMemberTypeAt(node);
3566
+ if (evolvingArrayMember)
3567
+ return evolvingArrayMember;
3568
+ return null;
3569
+ }
3570
+ },
3571
+ {
3572
+ name: 'census-member-signature',
3573
+ forms: [ts.SyntaxKind.PropertyAccessExpression],
3574
+ resolve: (node) => {
3575
+ const censusMemberSignature = censusMemberSignatureAt(node);
3576
+ if (censusMemberSignature)
3577
+ return censusMemberSignature;
3578
+ return null;
3579
+ }
3580
+ },
3581
+ {
3582
+ name: 'call-result',
3583
+ forms: [ts.SyntaxKind.CallExpression],
3584
+ resolve: (node) => {
3585
+ const callResult = callResultAt(node);
3586
+ if (callResult)
3587
+ return callResult;
3588
+ return null;
3589
+ }
3590
+ },
3591
+ {
3592
+ // The generator half of `physical-overload` below, asked at the CALL
3593
+ // rather than at a binding: the callee already publishes the one
3594
+ // convention its implementation has, and this is the same fact on the
3595
+ // result side. See `physicalGeneratorOverloadResultAt`.
3596
+ name: 'physical-generator-overload-result',
3597
+ forms: [ts.SyntaxKind.CallExpression],
3598
+ resolve: (node) => {
3599
+ const physicalResult = physicalGeneratorOverloadResultAt(checker, node);
3600
+ if (physicalResult)
3601
+ return typeOf(physicalResult);
3602
+ return null;
3603
+ }
3604
+ },
3605
+ {
3606
+ name: 'constructor-choice-result',
3607
+ forms: [ts.SyntaxKind.NewExpression],
3608
+ resolve: constructResultAt
3609
+ },
3610
+ {
3611
+ name: 'object-descriptor-return',
3612
+ forms: [ts.SyntaxKind.CallExpression],
3613
+ resolve: (node) => {
3614
+ const descriptorReturn = objectDescriptorReturnTypeAt(node);
3615
+ if (descriptorReturn)
3616
+ return descriptorReturn;
3617
+ return null;
3618
+ }
3619
+ },
3620
+ {
3621
+ // A parenthesized expression is its operand: the language attaches no
3622
+ // type of its own to the parentheses (`(cache = new Map())` inside a `||`
3623
+ // is the assignment, and the assignment's value is the allocation this
3624
+ // mapper laid out from its context). Asking the checker at the
3625
+ // parentheses instead hands back its own, pre-contextual reading of the
3626
+ // inside -- `Map<any, any>` -- and the merge that cites this node then
3627
+ // publishes a value nobody allocates.
3628
+ name: 'parenthesized-is-its-operand',
3629
+ forms: [ts.SyntaxKind.ParenthesizedExpression],
3630
+ resolve: (node) => (ts.isParenthesizedExpression(node) ? mapper.typeAt(node.expression) : null)
3631
+ },
3632
+ {
3633
+ // Likewise a plain assignment is the value it assigns (`AssignmentExpression
3634
+ // : LeftHandSideExpression = AssignmentExpression` completes with the RHS
3635
+ // value after PutValue) -- the rule `producers/computations.ts`'s
3636
+ // `finishComputation` already applies to the assignment OPERATION's own
3637
+ // result, asked here for the node so a merge citing `(cache = new Map())`
3638
+ // sees the same value the operation publishes.
3639
+ name: 'assignment-is-its-right-hand-side',
3640
+ forms: [ts.SyntaxKind.BinaryExpression],
3641
+ resolve: (node) => ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.EqualsToken ? mapper.typeAt(node.right) : null
3642
+ },
3643
+ {
3644
+ // A read off a type guard's narrowed family view publishes the FAMILY's
3645
+ // field, not the guard's restatement of it. `node.arguments` after
3646
+ // `isRequireCall(node)` is `NodeArray<Expression> & [StringLiteralLike]`
3647
+ // to the checker -- an intersection member's property is the
3648
+ // intersection of the members' properties -- and `NodeArray<Expression>`
3649
+ // in the one object the family lays out (`familyMemberNarrowedBy`). The
3650
+ // guard restated what the field holds; the storage the read loads from
3651
+ // is the family's, and the array-and-tuple intersection is a shape no
3652
+ // carrier spells (its overload sets never join).
3653
+ name: 'narrowed-family-property',
3654
+ forms: [ts.SyntaxKind.PropertyAccessExpression],
3655
+ resolve: (node) => {
3656
+ if (ts.isPropertyAccessExpression(node)) {
3657
+ const receiver = checker.getTypeAtLocation(node.expression);
3658
+ const narrowedMember = receiver.isIntersection() ? narrowedFamilyMemberOf(receiver) : null;
3659
+ const property = narrowedMember ? checker.getPropertyOfType(narrowedMember, node.name.text) : undefined;
3660
+ if (property)
3661
+ return typeOf(checker.getTypeOfSymbolAtLocation(property, node));
3662
+ }
3663
+ return null;
3664
+ }
3665
+ },
3666
+ {
3667
+ // Compiler-minted records can refine an ambient any/unknown member (for
3668
+ // example PropertyDescriptor.value). A concrete checker read is already
3669
+ // flow-sensitive: replacing it with the field's storage type would widen
3670
+ // `number | Wrapped` back after a typeof guard. Storage and a narrowed
3671
+ // read are different questions; preserve the checker's concrete answer.
3672
+ name: 'dynamic-property-of-shaped-receiver',
3673
+ forms: [ts.SyntaxKind.PropertyAccessExpression],
3674
+ resolve: (node) => {
3675
+ if (ts.isPropertyAccessExpression(node) &&
3676
+ (checker.getTypeAtLocation(node).flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) !== 0) {
3677
+ const receiverType = mapper.typeAt(node.expression);
3678
+ const receiverShape = table.get(receiverType).shape;
3679
+ const presentShapes = receiverShape.kind === 'union'
3680
+ ? receiverShape.members
3681
+ .map((member) => table.get(member).shape)
3682
+ .filter((shape) => !(shape.kind === 'primitive' && (shape.primitive === 'undefined' || shape.primitive === 'null')))
3683
+ : [receiverShape];
3684
+ // A nullable record has one present shape. A choice of records does
3685
+ // not: choosing its first object would discard the other arms' fields.
3686
+ const objectShape = presentShapes.length === 1 ? presentShapes[0] : null;
3687
+ if (objectShape?.kind === 'object' && !objectShape.membersDropped) {
3688
+ const field = objectShape.members.find((member) => member.key.kind === 'string' && member.key.value === node.name.text);
3689
+ if (field)
3690
+ return field.type;
3691
+ }
3692
+ }
3693
+ return null;
3694
+ }
3695
+ },
3696
+ {
3697
+ // A name in callee position whose call instantiates a generic is typed by
3698
+ // the copy that call reaches, not by the generic it was written against:
3699
+ // the identifier `identity` in `identity(1)` holds `(value: number) =>
3700
+ // number`, and holding the unbound `<T>(value: T) => T` there is the hole
3701
+ // monomorphization removes. The checker performed exactly this
3702
+ // substitution to type-check the call; this reads its answer back through
3703
+ // the copy's own view rather than redoing the inference.
3704
+ // A callee names its call's site; a generic function named as a VALUE
3705
+ // (`binarySearch(array, insert, identity, compare)`, `emitNodeList(emit,
3706
+ // ...)`) names its own -- `specialization.ts`'s `fromValueUse` keys the
3707
+ // copy that value is on the reference itself, and reading the name
3708
+ // through that copy's view is what closes its parameters: the checker's
3709
+ // instantiation where it made one, the constraints where it did not.
3710
+ // The value-use site is keyed on the REFERENCE, whatever its parent is:
3711
+ // an argument's parent is the call it is passed to, but a parameter
3712
+ // default's is the parameter (`nodeVisitor: NodeVisitor = visitNode`,
3713
+ // TypeScript's `visitEachChild`) and a property's is the assignment, and
3714
+ // none of those parents is a site of its own. So the parent is asked
3715
+ // only where it names the reference as its callee, and the reference
3716
+ // itself is asked whenever the parent answered nothing.
3717
+ name: 'specialization-copy',
3718
+ // The one rule 4.3 could not key, and the reason is a finding rather than
3719
+ // an omission: `namesItsSite` returns true by DEFAULT -- for every node
3720
+ // whose parent is not a call, new, tagged template or JSX opening element
3721
+ // -- so this rule asks about `node.parent` for arbitrary children of an
3722
+ // arrow function, a function expression, a type reference or an
3723
+ // `extends` clause. An arrow's concise body is any expression at all, so
3724
+ // the domain is not a closed set of forms; it is "almost everything",
3725
+ // which `forms: null` states honestly. Keying it means narrowing
3726
+ // `namesItsSite` to the positions that really name a site, which is a
3727
+ // change to what the rule ANSWERS and so not part of this port.
3728
+ forms: null,
3729
+ resolve: (node) => {
3730
+ const site = (namesItsSite(node) ? specializations.specializationAt(node.parent, substituteTypeParameter) : null) ??
3731
+ // A namespace-qualified name is the reference itself, exactly as an
3732
+ // identifier is -- `specialization.ts`'s `valueUseSubjectOf` keys the
3733
+ // value-use site on the whole `State.enter` access, because that is
3734
+ // what denotes the declaration (`namespace-paths.ts`). Asking for any
3735
+ // other property access costs nothing: only a node the census
3736
+ // recorded a site on answers, and a plain property read never is one.
3737
+ (ts.isIdentifier(node) || ts.isPropertyAccessExpression(node)
3738
+ ? specializations.specializationAt(node, substituteTypeParameter)
3739
+ : null);
3740
+ if (site) {
3741
+ const copy = mapperFor(copyPathOf(site));
3742
+ // The synthesized-union check of the non-specialized path below.
3743
+ const specializedUnionArms = parameters.unionArmsAt(node);
3744
+ if (specializedUnionArms)
3745
+ return table.intern({ kind: 'union', members: specializedUnionArms.map((arm) => copy.typeOf(arm)) });
3746
+ return copy.typeOf(absentSubstitutedTypeAt(node));
3747
+ }
3748
+ return null;
3749
+ }
3750
+ },
3751
+ {
3752
+ // The same absent-TYPE substitution the union arm above performs, at the
3753
+ // one other place a type enters from a source position: a binding whose
3754
+ // whole declared type is an absent host class, rather than one arm of a
3755
+ // union of them.
3756
+ name: 'array-literal-implied-pattern',
3757
+ forms: [ts.SyntaxKind.ArrayLiteralExpression],
3758
+ resolve: (node) => (ts.isArrayLiteralExpression(node) ? impliedPatternArrayLiteralType(node) : null)
3759
+ },
3760
+ {
3761
+ name: 'inferred-array-element',
3762
+ forms: [
3763
+ ts.SyntaxKind.ArrayLiteralExpression,
3764
+ ts.SyntaxKind.VariableDeclaration,
3765
+ ts.SyntaxKind.PropertyDeclaration,
3766
+ ts.SyntaxKind.Identifier,
3767
+ ts.SyntaxKind.PropertyAccessExpression
3768
+ ],
3769
+ resolve: (node) => {
3770
+ const inferredElement = inferredArrayElementAt(checker, collections, layoutTypeAt, node);
3771
+ if (inferredElement)
3772
+ return table.intern({ kind: 'array', element: typeOf(inferredElement), readonly: false, extension: [] });
3773
+ return null;
3774
+ }
3775
+ },
3776
+ {
3777
+ // See `unstatedNeverArray` for why `never` is the wrong answer for an
3778
+ // array whose element nothing states, and the box the right one.
3779
+ name: 'unstated-never-array',
3780
+ forms: [
3781
+ ts.SyntaxKind.ArrayLiteralExpression,
3782
+ ts.SyntaxKind.VariableDeclaration,
3783
+ ts.SyntaxKind.PropertyDeclaration,
3784
+ ts.SyntaxKind.Identifier,
3785
+ ts.SyntaxKind.PropertyAccessExpression,
3786
+ // A parameter is here for ONE case: it is an alias of an array whose
3787
+ // component the collection census refused, so it must carry the same
3788
+ // boxed element the caller's cell does. See `unstatedNeverArray`.
3789
+ ts.SyntaxKind.Parameter
3790
+ ],
3791
+ resolve: (node) => {
3792
+ if (unstatedNeverArray(checker, collections, layoutTypeAt, node)) {
3793
+ return table.intern({
3794
+ kind: 'array',
3795
+ element: table.intern({ kind: 'primitive', primitive: 'any' }),
3796
+ readonly: false,
3797
+ extension: []
3798
+ });
3799
+ }
3800
+ return null;
3801
+ }
3802
+ },
3803
+ {
3804
+ // The K/(V) a bare `new Map()`/`new Set()`/`new WeakMap()`/`new
3805
+ // WeakSet()` never states -- `collection-bindings.ts` has bound it since
3806
+ // its creation, and nothing downstream ever asked until now. See
3807
+ // `inferredCollectionTypeArgumentsAt`'s own header, in this file's
3808
+ // `structural-array-element.ts` sibling.
3809
+ //
3810
+ // Asked BEFORE the bag census, not after, because the two answer the
3811
+ // same node about the same storage and the collection census is the one
3812
+ // that looked at this cell's own uses. `WebGLRenderer.js`'s `let
3813
+ // programs = materialProperties.programs` is the shape: `programs` is a
3814
+ // slot of the `WebGLProperties` bag, so `bagShapeTypeAt` answers first
3815
+ // with the slot's own type -- `Map<any, any> | undefined`, the checker's
3816
+ // reading of the `new Map()` stored into it -- and the declaration kept
3817
+ // `optional(keyed-collection(map, dynamic, dynamic))` while every read
3818
+ // past the `if ( programs === undefined )` guard carried the census's
3819
+ // `keyed-collection(map, string, dynamic)`. Two authorities over one
3820
+ // cell, surfacing as an unsatisfiable `binding-read-conversion` per
3821
+ // read. Neither census is wrong about what it looked at; the collection
3822
+ // census simply looked at more (`programs.set( programCacheKey, ... )`
3823
+ // says what K is, the stored value's type does not), so it goes first.
3824
+ // It answers for a far narrower set of nodes than the bag census does --
3825
+ // only where a collection was actually bound for this exact owner,
3826
+ // allocation or read -- so this does not take work away from bags
3827
+ // generally, only where both describe one storage.
3828
+ name: 'inferred-collection-type-arguments',
3829
+ // Every one of these five is also a form `bag-shape` serves, which is what
3830
+ // makes the collection-before-bag order above load-bearing rather than
3831
+ // incidental: on exactly these kinds both rules can answer for one node.
3832
+ // The prose said so; the two form lists now make it checkable.
3833
+ forms: [
3834
+ ts.SyntaxKind.NewExpression,
3835
+ ts.SyntaxKind.VariableDeclaration,
3836
+ ts.SyntaxKind.PropertyDeclaration,
3837
+ ts.SyntaxKind.Identifier,
3838
+ ts.SyntaxKind.PropertyAccessExpression
3839
+ ],
3840
+ resolve: (node) => {
3841
+ const inferredCollection = inferredCollectionTypeArgumentsAt(collections, table, typeOf, bags, layoutTypeAt(node), node);
3842
+ if (inferredCollection)
3843
+ return inferredCollection;
3844
+ return null;
3845
+ }
3846
+ },
3847
+ {
3848
+ // The position's own statement, where the census had no writes to read
3849
+ // and the allocation itself states nothing -- and the syntax that carries
3850
+ // that allocation, unchanged, to the call the checker resolved off its
3851
+ // own dynamic reading. See `statedCollectionTypeAt`.
3852
+ name: 'stated-collection',
3853
+ forms: [
3854
+ ts.SyntaxKind.NewExpression,
3855
+ ts.SyntaxKind.ParenthesizedExpression,
3856
+ ts.SyntaxKind.BinaryExpression,
3857
+ ts.SyntaxKind.CallExpression
3858
+ ],
3859
+ resolve: (node) => {
3860
+ const statedCollection = statedCollectionTypeAt(checker, node);
3861
+ if (statedCollection)
3862
+ return typeOf(statedCollection);
3863
+ return null;
3864
+ }
3865
+ },
3866
+ {
3867
+ // The same statement for `new Array(n)`, whose ambient overload is
3868
+ // `any[]` for the identical reason a bare `new Map()` is `Map<any,
3869
+ // any>`. See `contextualArrayConstructTypeAt`. An assignment carries it
3870
+ // to the cell's merge through `assignment-is-its-right-hand-side`, so
3871
+ // only the allocation itself needs a form here.
3872
+ name: 'contextual-array-construct',
3873
+ forms: [ts.SyntaxKind.NewExpression],
3874
+ resolve: (node) => {
3875
+ const contextualArray = contextualArrayConstructTypeAt(checker, node);
3876
+ if (contextualArray)
3877
+ return typeOf(contextualArray);
3878
+ return null;
3879
+ }
3880
+ },
3881
+ {
3882
+ // The receiver's own type is not enough: `Map`/`WeakMap`'s `get` is a
3883
+ // prototype call, and a prototype call's result comes from the callee's
3884
+ // SIGNATURE -- which the checker instantiates from the receiver
3885
+ // EXPRESSION's type, not from what this compiler selected for it. See
3886
+ // `collectionMemberResultTypeAt` (`structural-array-element.ts`).
3887
+ name: 'collection-member-result',
3888
+ forms: [ts.SyntaxKind.CallExpression],
3889
+ resolve: (node) => {
3890
+ const collectionMember = collectionMemberResultTypeAt(collections, table, typeOf, bags, layoutTypeAt, node);
3891
+ if (collectionMember)
3892
+ return collectionMember;
3893
+ return null;
3894
+ }
3895
+ },
3896
+ {
3897
+ name: 'bag-shape',
3898
+ // A JS field written `this.field = {}` in a constructor makes the ASSIGNMENT
3899
+ // the field symbol's declaration as far as the checker is concerned, which
3900
+ // is why an `=` BinaryExpression is an owner form here and not only a
3901
+ // VariableDeclaration.
3902
+ forms: [
3903
+ ts.SyntaxKind.VariableDeclaration,
3904
+ ts.SyntaxKind.PropertyDeclaration,
3905
+ ts.SyntaxKind.Parameter,
3906
+ ts.SyntaxKind.BinaryExpression,
3907
+ ts.SyntaxKind.CallExpression,
3908
+ ts.SyntaxKind.NewExpression,
3909
+ ts.SyntaxKind.Identifier,
3910
+ ts.SyntaxKind.PropertyAccessExpression,
3911
+ ts.SyntaxKind.ElementAccessExpression,
3912
+ ts.SyntaxKind.ObjectLiteralExpression
3913
+ ],
3914
+ resolve: (node) => {
3915
+ const inferredBag = bagShapeTypeAt(table, typeOf, bags, node);
3916
+ if (inferredBag)
3917
+ return inferredBag;
3918
+ return null;
3919
+ }
3920
+ },
3921
+ {
3922
+ name: 'rest-parameter-array-element',
3923
+ forms: [ts.SyntaxKind.Parameter, ts.SyntaxKind.Identifier],
3924
+ resolve: (node) => {
3925
+ // Real call-site evidence (`parameter-bindings.ts`'s `restElementTypeAt`,
3926
+ // joined over every reachable caller's actual arguments) outranks the
3927
+ // checker's own contextual-tuple widening -- the same priority an
3928
+ // ordinary parameter's census answer already has over a bare checker
3929
+ // guess. `structural-parts.ts`'s `parameterOf` asks the identical
3930
+ // question the identical way, so the ABI and this body-side reference
3931
+ // to the same parameter cannot disagree about which one answered.
3932
+ // In `parameterOf`'s own order: census evidence, then a union of
3933
+ // tuples collapsed to one element, then the unannotated-tuple widening.
3934
+ const restElement = censusRestElementAt(checker, identities, parameters, node) ??
3935
+ restParameterUnionOfTuplesElementAt(checker, identities, node) ??
3936
+ restParameterArrayElementAt(checker, identities, node);
3937
+ if (restElement)
3938
+ return table.intern({ kind: 'array', element: typeOf(restElement), readonly: false, extension: [] });
3939
+ return null;
3940
+ }
3941
+ },
3942
+ {
3943
+ name: 'implied-pattern-array-element',
3944
+ // NOT ObjectBindingPattern, though `impliedPatternParameterOf` admits one:
3945
+ // the pattern it finds IS this node, and the caller then requires the
3946
+ // parameter's name to be an ARRAY pattern, so an object pattern can never
3947
+ // reach a non-null answer here.
3948
+ forms: [ts.SyntaxKind.Parameter, ts.SyntaxKind.ArrayBindingPattern],
3949
+ resolve: (node) => {
3950
+ const impliedElement = impliedPatternArrayElementAt(checker, parameters, node);
3951
+ if (impliedElement)
3952
+ return table.intern({ kind: 'array', element: typeOf(impliedElement), readonly: false, extension: [] });
3953
+ return null;
3954
+ }
3955
+ },
3956
+ {
3957
+ // A name bound to ONE function but annotated with an overloaded type.
3958
+ // `physicalOverloadTypeAt` states the rule; asked here, at the binding,
3959
+ // because the allocation already answers it from the initializer and the
3960
+ // two must not disagree about how many conventions one value has.
3961
+ name: 'physical-overload',
3962
+ forms: [
3963
+ ts.SyntaxKind.VariableDeclaration,
3964
+ ts.SyntaxKind.PropertyDeclaration,
3965
+ ts.SyntaxKind.PropertyAssignment,
3966
+ ts.SyntaxKind.ImportSpecifier,
3967
+ ts.SyntaxKind.ExportSpecifier,
3968
+ ts.SyntaxKind.ImportClause,
3969
+ ts.SyntaxKind.Identifier
3970
+ ],
3971
+ resolve: (node) => {
3972
+ const physical = physicalOverloadTypeAt(checker, node, parameters);
3973
+ if (physical)
3974
+ return typeOf(physical);
3975
+ return null;
3976
+ }
3977
+ },
3978
+ {
3979
+ // `new String(x) as T` -- the same shape one type-object over. See `physicalStringObjectTypeAt`.
3980
+ name: 'physical-string-object',
3981
+ forms: [
3982
+ ts.SyntaxKind.VariableDeclaration,
3983
+ ts.SyntaxKind.PropertyDeclaration,
3984
+ ts.SyntaxKind.PropertyAssignment,
3985
+ ts.SyntaxKind.Identifier
3986
+ ],
3987
+ resolve: (node) => {
3988
+ const stringObjectPhysical = physicalStringObjectTypeAt(checker, node, parameters);
3989
+ if (stringObjectPhysical)
3990
+ return typeOf(stringObjectPhysical);
3991
+ return null;
3992
+ }
3993
+ },
3994
+ {
3995
+ // The checker's constraint erasure over this copy's own binding. Guarded
3996
+ // on the substitution actually resolving: a generic whose copy binds
3997
+ // nothing has no better answer than the constraint, and answering with a
3998
+ // naked parameter there would trade a wide carrier for no carrier.
3999
+ name: 'constraint-erased-parameter',
4000
+ forms: [ts.SyntaxKind.Identifier],
4001
+ resolve: (node) => {
4002
+ const erased = constraintErasedParameterAt(checker, node);
4003
+ if (erased !== null && substituteTypeParameter(erased) !== erased)
4004
+ return typeOf(erased);
4005
+ return null;
4006
+ }
4007
+ },
4008
+ {
4009
+ // A disagreement the census resolved to a SYNTHESIZED union.
4010
+ // `unionArmsAt`'s own comment says why this is not a `ts.Type`
4011
+ // (`getUnionType` is not public); the structural union is built at
4012
+ // the one place `table.intern` and this copy's `typeOf` are both in
4013
+ // scope, where the plain `bound` fallback would have found nothing
4014
+ // and fallen through to `any`.
4015
+ name: 'parameter-union-arms',
4016
+ // The union of four composed censuses -- parameter, return, local, field --
4017
+ // each of which owns a different slice of this list.
4018
+ forms: [
4019
+ ts.SyntaxKind.Parameter,
4020
+ ts.SyntaxKind.Identifier,
4021
+ ts.SyntaxKind.VariableDeclaration,
4022
+ ts.SyntaxKind.PropertyDeclaration,
4023
+ ts.SyntaxKind.PropertyAccessExpression,
4024
+ ts.SyntaxKind.FunctionDeclaration,
4025
+ ts.SyntaxKind.FunctionExpression,
4026
+ ts.SyntaxKind.ArrowFunction,
4027
+ ts.SyntaxKind.MethodDeclaration,
4028
+ ts.SyntaxKind.GetAccessor,
4029
+ ts.SyntaxKind.CallExpression,
4030
+ ts.SyntaxKind.NewExpression
4031
+ ],
4032
+ resolve: (node) => {
4033
+ const unionArms = parameters.unionArmsAt(node);
4034
+ if (unionArms)
4035
+ return table.intern({ kind: 'union', members: unionArms.map((arm) => typeOf(arm)) });
4036
+ return null;
4037
+ }
4038
+ },
4039
+ {
4040
+ name: 'dynamic-object-boundary',
4041
+ forms: [ts.SyntaxKind.Identifier],
4042
+ resolve: (node) => {
4043
+ const dynamicObjectBoundary = dynamicObjectBoundaryAt(node);
4044
+ if (dynamicObjectBoundary)
4045
+ return typeOf(dynamicObjectBoundary);
4046
+ return null;
4047
+ }
4048
+ },
4049
+ {
4050
+ name: 'unplaced-hoisted-read',
4051
+ forms: [ts.SyntaxKind.Identifier],
4052
+ resolve: (node) => {
4053
+ const unplacedHoistedRead = unplacedHoistedReadAt(node);
4054
+ if (unplacedHoistedRead)
4055
+ return typeOf(unplacedHoistedRead);
4056
+ return null;
4057
+ }
4058
+ }
4059
+ ];
4060
+ const preparedRules = prepareStructuralRules(structuralRules);
4061
+ // Decided once per mapper, never per node: `typeAt` is asked for essentially
4062
+ // every node in the program, and reading an environment variable there would
4063
+ // make the instrument's own cost the thing it measures.
4064
+ const recordDisagreement = structuralDisagreementsEnabled()
4065
+ ? (disagreement) => {
4066
+ disagreements.push(disagreement);
4067
+ }
4068
+ : undefined;
4069
+ const typeAt = (node) => preparedRules.resolve(node, recordDisagreement) ?? typeOf(absentSubstitutedTypeAt(node));
4070
+ const rawTypeAt = (node) => {
4071
+ // A binding pattern is the reference half of binding its source and has no
4072
+ // independent value type. TypeScript does not support every direct
4073
+ // `getTypeAtLocation` query on these pattern nodes, so expose the same raw
4074
+ // source type that `typeAt` above interns.
4075
+ if (ts.isArrayBindingPattern(node) || ts.isObjectBindingPattern(node)) {
4076
+ const parent = node.parent;
4077
+ if (ts.isVariableDeclaration(parent) && parent.initializer)
4078
+ return rawTypeAt(parent.initializer);
4079
+ if (ts.isParameter(parent) || ts.isBindingElement(parent))
4080
+ return rawTypeAt(parent);
4081
+ }
4082
+ return absentSubstitutedTypeAt(node);
4083
+ };
4084
+ const mapper = {
4085
+ forSpecialization: mapperFor,
4086
+ substituteTypeParameter,
4087
+ typeOf,
4088
+ typeAt,
4089
+ mutableMethodStorageTypeAt: mutableMethods.storageTypeAt,
4090
+ mutableMethodReadTypeAt: mutableMethods.readTypeAt,
4091
+ boundCallResultAt,
4092
+ constructResultAt,
4093
+ evolvingArrayMemberTypeAt,
4094
+ objectDescriptorReturnTypeAt,
4095
+ instanceTypeAt: (node) => {
4096
+ if (!ts.isClassExpression(node))
4097
+ return typeAt(node);
4098
+ const construct = checker.getTypeAtLocation(node).getConstructSignatures()[0];
4099
+ return construct ? typeOf(construct.getReturnType()) : typeAt(node);
4100
+ },
4101
+ valueTypeAt: (node) => {
4102
+ const localUnion = localUnionAt(node);
4103
+ if (localUnion)
4104
+ return localUnion;
4105
+ const accessor = accessorSignatureOf(checker, node);
4106
+ if (accessor)
4107
+ return table.intern({ kind: 'signature', call: [signatureOf(accessor)], construct: [] });
4108
+ // An overload set's implementation declares the one signature that
4109
+ // physically exists -- see `implementationSignatureOf`. Asked before the
4110
+ // symbol-level answer below, which is every overload and no single
4111
+ // convention.
4112
+ const implementation = implementationSignatureOf(checker, node);
4113
+ if (implementation)
4114
+ return table.intern({ kind: 'signature', call: [signatureOf(implementation)], construct: [] });
4115
+ // A `?`-marked method WITH A BODY allocates its function object
4116
+ // unconditionally -- see `optionalMethodSignatureOf`. Asked before the
4117
+ // symbol-level answer below, which is `T | undefined` for an optional
4118
+ // member whether read through the symbol or the node, and states a
4119
+ // fact about READING the member, never about whether this declaration's
4120
+ // own allocation runs.
4121
+ const optionalMethod = optionalMethodSignatureOf(checker, node);
4122
+ if (optionalMethod)
4123
+ return table.intern({ kind: 'signature', call: [signatureOf(optionalMethod)], construct: [] });
4124
+ // A return census answers the RESULT of a callable declaration, never
4125
+ // the value allocated for the declaration itself. `layoutTypeAt` reads
4126
+ // that census for ordinary nodes, so asking it directly of an arrow or
4127
+ // function expression whose stated upper bound was refined returns the
4128
+ // concrete result type (an Array for `(): Iterable<T> => [...]`) and
4129
+ // would publish an Array allocation where the source allocates a
4130
+ // function. Rebuild the callable shape from its own signature here;
4131
+ // `signatureOf` consults the same composed census for the result slot,
4132
+ // preserving both facts without letting one replace the other.
4133
+ if ((ts.isArrowFunction(node) || ts.isFunctionExpression(node)) &&
4134
+ (parameters.typeAt(node) !== null || parameters.unionArmsAt(node) !== null)) {
4135
+ const signature = checker.getSignatureFromDeclaration(node);
4136
+ if (signature)
4137
+ return table.intern({ kind: 'signature', call: [signatureOf(signature)], construct: [] });
4138
+ }
4139
+ const declared = declaredValueTypeOf(checker, node);
4140
+ if (declared) {
4141
+ // A binding ANNOTATED with an overloaded type but INITIALIZED with one
4142
+ // function has exactly one physical convention -- the initializer's.
4143
+ // `structural-parts.ts`'s `memberOf` already asks this for a member;
4144
+ // a module-level `const` is the same fact spelled at file scope, and
4145
+ // hono's `export const parseBody: ParseBody = async (...)` is the
4146
+ // case that showed the two answers apart.
4147
+ return typeOf(physicalInitializerTypeOf(checker, node, declared, parameters) ?? declared);
4148
+ }
4149
+ const layout = layoutTypeAt(node);
4150
+ // A function LITERAL contextually typed by an overload set. Only a
4151
+ // `function` declaration merges into several conventions; an arrow or a
4152
+ // function expression is one function with one signature, whatever the
4153
+ // position expecting it declares -- so the literal's own signature is
4154
+ // the answer, exactly as `implementationSignatureOf` above answers the
4155
+ // merged-declaration spelling of the same fact.
4156
+ //
4157
+ // The overload set is not always written as one. `[].map` over a UNION
4158
+ // of two array types resolves to a callback parameter that is the
4159
+ // INTERSECTION of the two arms' callbacks -- contravariance -- and an
4160
+ // intersection of callables is exactly an overload set. hono's
4161
+ // `this.#matchResult[0].map(([[, route]]) => route)` (`request.ts:421`)
4162
+ // is that, and the arrow written there has one parameter list.
4163
+ //
4164
+ // Gated on the layout actually carrying more than one signature, so an
4165
+ // ordinary arrow keeps resolving through `layoutTypeAt` untouched.
4166
+ if (process.env.GEA_DEBUG_VALUETYPE &&
4167
+ (ts.isArrowFunction(node) || ts.isFunctionExpression(node)) &&
4168
+ node.getText().includes(process.env.GEA_DEBUG_VALUETYPE)) {
4169
+ console.error('[DEBUG valueTypeAt]', node.getText().slice(0, 80));
4170
+ console.error(' declared(before):', declared);
4171
+ console.error(' layout sig count:', layout.getCallSignatures().length);
4172
+ console.error(' layout typeToString:', checker.typeToString(layout));
4173
+ const own = checker.getSignatureFromDeclaration(node);
4174
+ console.error(' own signature exists:', !!own);
4175
+ if (own) {
4176
+ for (const p of own.getParameters()) {
4177
+ const t = checker.getTypeOfSymbolAtLocation(p, node);
4178
+ console.error(' param', p.getName(), checker.typeToString(t, undefined, ts.TypeFormatFlags.NoTruncation), 'isTuple:', checker.isTupleType(t));
4179
+ }
4180
+ }
4181
+ }
4182
+ // TRIED AND MEASURED DEAD (2026-09-03): widening this `> 1` gate to
4183
+ // also fire on an unannotated trailing rest -- hono's `newResponse:
4184
+ // NewResponse = (...args) => ...`, whose `layout` here is ONE
4185
+ // TypeScript-joined signature (`args_0: any, args_1?: any, args_2?:
4186
+ // unknown`), the checker's own collapse of a bare-rest literal against
4187
+ // several overloads, done before this function runs. Preferring `own`
4188
+ // there is a no-op: isolated A/B (snapshot, hono-hello + the three.js app)
4189
+ // byte-identical -- `own`'s contextual type for the rest
4190
+ // parameter is EQUALLY `any`/`unknown`-degraded by that same join, so
4191
+ // `own`/`layout` are two views of one already-lossy checker answer,
4192
+ // not two to disagree between. Also checked: the call-site census
4193
+ // (`StructuralPartsInput.parameters`) never binds a rest parameter's
4194
+ // declaration either (`bound` null for every `...args` in hono,
4195
+ // confirmed directly). The richer per-position record `abiBlockers`
4196
+ // reports seeing comes from neither path -- likely the `args as
4197
+ // Parameters<NewResponse>` cast at its one use site, narrowing a
4198
+ // DIFFERENT operand. Separate work; do not retry this selection point.
4199
+ if ((ts.isArrowFunction(node) || ts.isFunctionExpression(node)) && layout.getCallSignatures().length > 1) {
4200
+ const own = checker.getSignatureFromDeclaration(node);
4201
+ if (own)
4202
+ return table.intern({ kind: 'signature', call: [signatureOf(own)], construct: [] });
4203
+ }
4204
+ return typeOf(layout);
4205
+ },
4206
+ resolvedSignatureTypeOf: (signature, kind, resultOverride) => table.intern({
4207
+ kind: 'signature',
4208
+ call: kind === 'call' ? [signatureOf(signature, resultOverride)] : [],
4209
+ construct: kind === 'construct' ? [signatureOf(signature, resultOverride)] : []
4210
+ }),
4211
+ rawTypeAt,
4212
+ patternReadTypeAt: (element) => parameters.patternReadTypeAt?.(element) ?? null,
4213
+ structuralDisagreements: disagreements,
4214
+ structuralFormViolations: preparedRules.formViolations,
4215
+ classCopies: () => new Map([...classCopyKeys].map(([root, copies]) => [root, [...copies.values()].sort((a, b) => a.ordinal - b.ordinal)]))
4216
+ };
4217
+ return mapper;
4218
+ };