@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,3339 @@
1
+ import { isRealCallableDeclaration, isModuleExportedDeclaration, isTypePositionReference, runtimeParametersOf } from './flow/targets.js';
2
+ import { inProgramImportReferencesOf } from './flow/export-importers.js';
3
+ import ts from 'typescript';
4
+ import { implicitArgumentsSlotOf } from './implicit-arguments.js';
5
+ import { implicitArgumentsReadTypeAt, inferImplicitArgumentsTuple } from './implicit-arguments-tuple.js';
6
+ import { censusArgumentsObjects } from './arguments-objects.js';
7
+ import { censusRefusal } from './census-refusal.js';
8
+ import { classFamilyMemberReadTypeOf } from './flow/class-family-member-read.js';
9
+ import { omissionStatedTypeOf, statedParameterWithOmission } from './omitted-stated-parameter.js';
10
+ import { indexValueFlow } from './flow/value-flow.js';
11
+ import { closedArrayCalleeAuthorityOf, hasClosedMemberCallableUses } from './flow/callable-reach.js';
12
+ import { deferredIntrinsicProtocolLedgerOf } from './deferred-intrinsic-protocols.js';
13
+ import { callbackContractParameterType, callbackParameterContractsFor } from './callback-parameter-contracts.js';
14
+ import { declaredClosedTupleRestElementsOf, impliedPatternElementOfArms, impliedPatternPositionPresentEverywhere } from './parameter-slot.js';
15
+ import { iteratorYieldTypesOf } from './producers/iteration-yield.js';
16
+ import { annotationStatesNothing, exactEmptyObjectLiteralType, isNullishType, containsUnstatedPosition, derivedExpressionType, indexAliasEvidence, indexedTypeOf, explicitThisCallReturnType, overloadInvariantReturnTypeAt, indexNamedCallables, isStandardInterfaceType, isBindingOnlyReference, isCalleeOf, isTrackedCallable, isUnusableEvidence as statesNoStorage, carriesNoEvidence, disjointUnionMembersOf, disjointUnionTypeOf, joinOfWrites, jsDocTypeStatesNothing, literalMemberNameOf, narrowsOnlyUnstatedPositions, withoutUndefinedMember, memberTypeOf, objectAssignTargetType, nameOfCallable, synthesizedUnionArmsAt, widestOf, impliedPatternElementRootOf, impliedPatternParameterOf } from './derived-expression-type.js';
17
+ import { isUnreducedTypeForm } from './unreduced-type-form.js';
18
+ import { forEachReachableStatement } from './reachability.js';
19
+ /** A census that binds nothing, for callers that state no program. */
20
+ export const emptyParameterBindingCensus = {
21
+ typeAt: () => null,
22
+ statedTypeAt: () => null,
23
+ unionArmsAt: () => null,
24
+ boundCount: 0,
25
+ refusals: [],
26
+ refusalOf: () => null
27
+ };
28
+ const isAnyType = (type) => (type.flags & ts.TypeFlags.Any) !== 0;
29
+ /** A stable empty set, so alias attribution can return "nothing" without allocating one each time. */
30
+ const EMPTY_DECLARATIONS = new Set();
31
+ /**
32
+ * Whether a type is bare `Function` -- a type with NO calling convention at
33
+ * all. TypeScript's checker lets any callable be assigned to `Function` as an
34
+ * error-tolerance rule, but the type itself declares zero call signatures and
35
+ * zero construct signatures, so it says nothing about arity or return either.
36
+ * Signature count is the real question and is checked first; the symbol name
37
+ * is a second, narrower gate so a user type that happens to declare no
38
+ * signatures of its own (an empty interface, `Record<string, never>`) is not
39
+ * swept in beside it -- only the library's own `Function` is.
40
+ */
41
+ const isBareFunctionType = (type) => {
42
+ if (type.getCallSignatures().length > 0)
43
+ return false;
44
+ if (type.getConstructSignatures().length > 0)
45
+ return false;
46
+ return type.getSymbol()?.getName() === 'Function';
47
+ };
48
+ /**
49
+ * Whether a type says nothing about STORAGE, and so is not evidence.
50
+ *
51
+ * Four of the checker's answers are not carriers, and a census that admits
52
+ * them binds a parameter to a fact about something other than the value it
53
+ * holds:
54
+ *
55
+ * - `any` is the absence this module exists to fill, and propagating it is what
56
+ * it exists to stop.
57
+ * - `void` is a statement about a RESULT nobody may read. It and `undefined`
58
+ * are one runtime value and two facts, so a call passing the result of a void
59
+ * function binds `void` into a cell whose ABI correctly says `undefined` --
60
+ * measured, as an ABI disagreement in `PolyhedronGeometry`.
61
+ * - `never` is REACHABILITY, not storage. `const v = [];` before any write is
62
+ * `never[]`, so `v[ i ][ k + 1 ]` reads `never` -- and `pushVertex( v[ i ][ k
63
+ * + 1 ] )` is a call that plainly does happen. Binding its parameter to
64
+ * "no value ever arrives" describes the empty literal, not the argument.
65
+ * - bare `Function` is `isUnannotated`'s own exception admitted as a
66
+ * CANDIDATE, and it must stay non-evidence everywhere else in this module
67
+ * for the same reason: `Object3D.traverse( callback ) { callback( this );
68
+ * children[i].traverse( callback ); }` passes `callback` to a recursive
69
+ * call of `traverse` itself, and if the declared `Function` type were
70
+ * usable evidence, `known()` would read it straight off the checker at that
71
+ * self-reference (before this round's own binding exists) and hand it to
72
+ * `agreedArgumentType` as one of the call sites' passed types. Bare
73
+ * `Function` is assignable-to by nearly every real function type, so
74
+ * `widestOf` would then pick it as the "widest" answer over every genuine
75
+ * callback type the OTHER call sites pass -- collapsing a real function
76
+ * value back down to the one type that carries no calling convention,
77
+ * silently. Measured: admitting it produced exactly that, surfacing as a
78
+ * `native-record-ref` binding a `function-value-dispatch` ABI disagreed
79
+ * with. Excluding it here instead means a self-reference like this one is
80
+ * refused (`argument-states-no-storage`) rather than answered wrong, and
81
+ * the parameter binds only once every OTHER call site's real evidence
82
+ * agrees.
83
+ *
84
+ * Refused rather than rewritten: every type this module produces comes out of
85
+ * the checker, and substituting `undefined` for a `void` here would be the
86
+ * compiler stating a type instead of reading one. A parameter whose only
87
+ * evidence is one of these keeps the checker's own answer, which is the
88
+ * behaviour before this module existed.
89
+ */
90
+ const isUnusableEvidence = (type) => statesNoStorage(type) || isBareFunctionType(type) || isGenericCallableType(type);
91
+ /**
92
+ * Whether a type is a GENERIC callable -- `typeof emit` for `function emit<T
93
+ * extends Node>(node: T)`, passed uninstantiated to a parameter typed by a
94
+ * generic function type (`emitNodeList(emit, ...)` over `EmitFunction`).
95
+ *
96
+ * Not evidence for the same reason `Function` is not: the spelling says which
97
+ * function, not which frame. The frame the cell holds is the copy the
98
+ * specialization census mints for that very reference (`fromValueUse`), over
99
+ * the instantiation the PARAMETER's own type has in this program -- and the
100
+ * declared parameter type resolves to exactly that, while this argument type
101
+ * resolved in the callee's copy would read the function's own `T` with
102
+ * nothing binding it. Measured: `emitFn(child)` refused
103
+ * `function-value-dispatch((record(Node)) -> void) ->
104
+ * function-value-dispatch((native-record-ref(Stmt)) -> void)`, the cell
105
+ * typed from the argument and the read from the declaration.
106
+ */
107
+ const isGenericCallableType = (type) => [...type.getCallSignatures(), ...type.getConstructSignatures()].some((signature) => (signature.getTypeParameters()?.length ?? 0) > 0);
108
+ /**
109
+ * Whether this parameter is one the program never typed -- for the one
110
+ * question this census answers: what can a callable value here be called
111
+ * with.
112
+ *
113
+ * A type annotation, a JSDoc `@param`/`@type` tag, and a default initializer
114
+ * are all the program stating the type; only the total absence of all three
115
+ * (or a bare `Function` annotation, immediately below) leaves the checker
116
+ * with nothing to read. The `any` test comes last and is what makes this
117
+ * honest for a parameter TypeScript typed contextually -- a callback's
118
+ * parameter in `arr.map(x => x)` has no annotation and is not `any`, and
119
+ * rebinding it from a call site would overwrite a real inference.
120
+ *
121
+ * Bare `Function` -- `@param {Function} callback`, or `: Function` -- is the
122
+ * one exception to "an annotation settles it". Calling a `Function`-typed
123
+ * value is permitted only by the checker's own error tolerance; the type
124
+ * declares no call signature and no construct signature, so for THIS
125
+ * question -- what does a call here actually pass -- it is exactly as
126
+ * uninformative as no annotation at all. `Object3D.traverse`'s `callback`
127
+ * parameter is declared this way and the body calls `callback( this )`: one
128
+ * argument, where the annotation states none. A type that DOES declare a call
129
+ * signature -- `(x: T) => U`, a JSDoc `@callback` typedef -- is real evidence
130
+ * and keeps stopping the census exactly as before; only the signature-free
131
+ * case is let through.
132
+ *
133
+ * A real annotation that RESOLVES TO A NON-STATEMENT -- `options: {}`, `x:
134
+ * object`, `v: Object` -- is the second exception, and it is the JSDoc rule
135
+ * three lines of this function already apply, asked of the other spelling.
136
+ * `jsDocTypeStatesNothing` stopped a vague `@param {Object}` tag from
137
+ * outranking the census; a parameter written `: object` in TypeScript states
138
+ * exactly as little, and there is no reason the census should defer to one
139
+ * spelling of "nothing" and not the other. See `annotationStatesNothing`
140
+ * (`derived-expression-type.js`) for what is deliberately NOT in it --
141
+ * `unknown`, a named empty type, an explicit `: any`.
142
+ */
143
+ const isUnannotated = (checker, parameter) => {
144
+ if (parameter.dotDotDotToken)
145
+ return false;
146
+ if (!ts.isIdentifier(parameter.name)) {
147
+ // A DESTRUCTURING PATTERN as the parameter's name -- `function f([x, y])`,
148
+ // `function g({ a, b })` -- with no annotation. TypeScript synthesizes the
149
+ // parameter's type from the pattern's own SHAPE (`[any, any]`, `{ a: any;
150
+ // b: any }`): a statement about the syntax of the binding, not about any
151
+ // value a caller passes, and the `[any, any]` tuple is actively wrong for
152
+ // the language, which binds the pattern off ANY iterable of any length
153
+ // (`f([])` is legal and binds both names to `undefined`). So the site
154
+ // type is no evidence at all, exactly as a bare `any` parameter's is, and
155
+ // the census binds the slot from the call sites; the pattern's leaves then
156
+ // read out of THAT bound value (`resolve`'s `BindingElement` branch).
157
+ // A JSDoc tag or a real annotation on the pattern is a statement and
158
+ // keeps the parameter out, as it does for a named one.
159
+ return impliedPatternParameterOf(checker, parameter) !== null;
160
+ }
161
+ if (parameter.type) {
162
+ // Read at the TYPE NODE, never at the parameter. `checker.getTypeAtLocation`
163
+ // on an OPTIONAL parameter answers for the site -- `object | undefined`,
164
+ // `{} | undefined` -- and the trailing `isAnyType` test at the bottom of
165
+ // this function is written for a site type that really is bare `any`. That
166
+ // exact confusion is what silently re-excluded the empty-object JSDoc tags
167
+ // this rule's own sibling had just admitted (see the comment below), so
168
+ // this branch asks the annotation itself and RETURNS immediately either
169
+ // way rather than falling through to a test that answers a different
170
+ // question.
171
+ return annotationStatesNothing(checker, parameter.type, checker.getTypeFromTypeNode(parameter.type));
172
+ }
173
+ const jsDocParamTags = ts.getJSDocParameterTags(parameter);
174
+ const jsDocType = ts.getJSDocType(parameter) ?? jsDocParamTags[0]?.typeExpression?.type;
175
+ if (jsDocType || jsDocParamTags.length > 0) {
176
+ // HELD, not landed: candidacy itself is sound (see the doc above), but
177
+ // admitting it before `.call`/`.apply` attribution exists (see
178
+ // `unwrapExplicitThisCall`) measurably regressed `EventDispatcher.
179
+ // addEventListener`'s `listener` -- `callsByDeclaration` only ever saw
180
+ // the 2 direct-call sites in the whole corpus, both coincidentally
181
+ // zero-arg, so the join correctly found no disagreement among evidence
182
+ // that was itself an incomplete sample and bound `() => void`, while
183
+ // `dispatchEvent` really calls every listener with one argument via
184
+ // `array[i].call( this, event )`. Re-enable
185
+ // (`isBareFunctionType(checker.getTypeAtLocation(parameter))`) once that
186
+ // attribution gap is closed and re-measured.
187
+ //
188
+ // NARROWED, not repealed: the exclusion above still stands whenever the
189
+ // JSDoc type resolves to something the checker can actually read -- that
190
+ // is real evidence, exactly as informative as a TS annotation, and stays
191
+ // out of this census for the same reason a typed parameter always has.
192
+ // It is lifted for unusable JSDoc evidence or the same broad object bound
193
+ // `annotationStatesNothing` admits for a TypeScript parameter. This also
194
+ // covers the real lib Object interface, whose inherited methods state no
195
+ // configuration fields. Parameter refinement does not discard that tag on
196
+ // return cells. At that point the program has stated nothing this
197
+ // compiler can read, so refusing the parameter is refusing it for a fact
198
+ // that isn't there. Measured on the three.js corpus: 31/38 obligations (82%)
199
+ // and 20/24 distinct parameters (83%) in this bucket resolve to nothing
200
+ // and are exactly the unimported cross-module-name pattern documented on
201
+ // `jsDocTypeIsUninformative`; the remaining 17-18% resolve to a real type
202
+ // (`number | Vector3`, ...) and keep being excluded here, same as before
203
+ // this change.
204
+ if (!jsDocType ||
205
+ !(jsDocTypeStatesNothing(checker, jsDocType) || annotationStatesNothing(checker, jsDocType, checker.getTypeFromTypeNode(jsDocType))))
206
+ return false;
207
+ // Admit it HERE, rather than falling through to the `isAnyType(checker.
208
+ // getTypeAtLocation(parameter))` test below -- that test is written for
209
+ // the OTHER path into this function, the parameter with no annotation of
210
+ // any kind, where the checker's site type really is bare `any`. A tagged
211
+ // parameter's site type is not: it is the checker's answer for the TAG,
212
+ // and a `[name]`-bracketed (optional) tag makes that a real UNION with
213
+ // `undefined` for any resolved type except `any` itself -- TypeScript's
214
+ // own union normalization absorbs `any | undefined` back down to `any`,
215
+ // which is the ONLY reason the `any`/`unknown` half of `jsDocTypeStates
216
+ // Nothing` ever reached this point undetected before. `{} | undefined`
217
+ // does not absorb the same way, so an empty-object tag marked optional
218
+ // -- `InterleavedBuffer.clone( [data] )` via `@types/three`'s own `data:
219
+ // {}` -- hit the `isAnyType` test below, found a `Union`, and was
220
+ // silently re-excluded even though the line above had already judged the
221
+ // tag to state nothing. Measured: this was the entire reason widening
222
+ // `jsDocTypeStatesNothing` alone moved zero boxes on the three.js app.
223
+ return true;
224
+ }
225
+ // A DEFAULT VALUE is not a type. `constructor( parameters = {} )` states what
226
+ // the parameter holds when a caller omits it, and TypeScript widens that into
227
+ // `{}` -- a type with no members, which every real call site contradicts.
228
+ // `WebGLRenderer`'s whole configuration arrives through this parameter, so
229
+ // `{}` is the wall the entire renderer's typing stands behind.
230
+ //
231
+ // Binding it is sound only when the default is UNREACHABLE, and that is a
232
+ // condition this census already tests for its own reasons: every call site
233
+ // must pass an argument at this position (`call-passes-no-argument`) and the
234
+ // function must not escape to a caller it cannot see. A default that can
235
+ // still run is a second value the agreed type does not describe.
236
+ if (parameter.initializer)
237
+ return true;
238
+ return isAnyType(checker.getTypeAtLocation(parameter));
239
+ };
240
+ /**
241
+ * Whether a type still carries a piece of an UNSUBSTITUTED generic -- a bare
242
+ * type parameter, an indexed access whose object type is one (`E['Bindings']`),
243
+ * a conditional or a substitution.
244
+ *
245
+ * Such a type is not a carrier and never becomes one: the representation
246
+ * deriver has nothing to resolve `E['Bindings']` against and publishes
247
+ * `unresolved(...)`, which fails preflight as an unmet obligation rather than
248
+ * as a refusal anyone can read. hono's `Hono` is generic in `E` and every
249
+ * copy of it shares one parameter node, so a census answer taken from a call
250
+ * site INSIDE the generic carries `E` out with it -- 10 unmet obligations
251
+ * reading "an indexed access whose object type is still a type parameter has
252
+ * no member set to resolve", measured the first time this admission ran
253
+ * without the guard.
254
+ */
255
+ export const carriesUnsubstitutedGeneric = (checker, type, depth = 0) => {
256
+ if (depth > 8)
257
+ return false;
258
+ const open = ts.TypeFlags.TypeParameter | ts.TypeFlags.IndexedAccess | ts.TypeFlags.Conditional | ts.TypeFlags.Substitution;
259
+ if ((type.flags & open) !== 0)
260
+ return true;
261
+ if (type.isUnion() || type.isIntersection()) {
262
+ return type.types.some((part) => carriesUnsubstitutedGeneric(checker, part, depth + 1));
263
+ }
264
+ if ((type.flags & ts.TypeFlags.Object) === 0)
265
+ return false;
266
+ const reference = type;
267
+ if (reference.target === undefined)
268
+ return false;
269
+ return checker.getTypeArguments(reference).some((part) => carriesUnsubstitutedGeneric(checker, part, depth + 1));
270
+ };
271
+ /**
272
+ * A parameter the program DID type, whose statement is still only an UPPER
273
+ * BOUND -- one with an `any`/`unknown`/bare-`Function` position somewhere
274
+ * inside it. Returns that stated type, for `narrowsOnlyUnstatedPositions` to
275
+ * test the agreed argument type against; `null` for every parameter whose
276
+ * annotation constrains every position it mentions, which is nearly all of
277
+ * them and which this census must not touch.
278
+ *
279
+ * hono's `HonoRequest( ..., matchResult: Result<[unknown, RouterRoute]> )` and
280
+ * `compose( middleware: [[Function, unknown], unknown][] | [[Function]][] )`
281
+ * are the two measured cases: both state a full structure and leave exactly
282
+ * the handler slot unstated, and both are handed a fully concrete value by the
283
+ * program's only caller. See `narrowsOnlyUnstatedPositions` for why reading
284
+ * such an annotation as the last word forces an unrenderable aggregate rebuild.
285
+ *
286
+ * The same three structural exclusions `isUnannotated` applies hold here --
287
+ * a rest parameter, a destructured one, and a type that is itself no evidence.
288
+ */
289
+ const statedUpperBound = (checker, parameter) => {
290
+ if (parameter.dotDotDotToken)
291
+ return null;
292
+ if (!ts.isIdentifier(parameter.name))
293
+ return null;
294
+ if (!parameter.type)
295
+ return null;
296
+ const declared = checker.getTypeFromTypeNode(parameter.type);
297
+ // Already `isUnannotated`'s own business, and admitted there.
298
+ if (annotationStatesNothing(checker, parameter.type, declared))
299
+ return null;
300
+ if (isUnusableEvidence(declared))
301
+ return null;
302
+ if (!containsUnstatedPosition(checker, parameter.type, declared))
303
+ return null;
304
+ // A DEFAULTED or OPTIONAL parameter's statement is `T | undefined` to its
305
+ // callers, whatever its annotation spells: the absence is what the default
306
+ // exists to answer. Testing the agreed argument type against the bare `T`
307
+ // refuses every such parameter whose caller passes a possibly-absent value
308
+ // -- hono's `new HonoRequest( ..., this.#matchResult )` passing a `Result<
309
+ // [H, RouterRoute]> | undefined` into `matchResult: Result<[unknown,
310
+ // RouterRoute]> = [[]]` is the measured case, and it is ordinary
311
+ // TypeScript. `contributeDefaultedParameter` (`producers/bindings.ts`)
312
+ // already splits this answer back into the raw slot (with the absence) and
313
+ // the body's own binding (without it), so handing it the union is what
314
+ // makes both halves agree.
315
+ const absent = parameter.initializer !== undefined || parameter.questionToken !== undefined;
316
+ return absent ? checker.getNullableType(declared, ts.TypeFlags.Undefined) : declared;
317
+ };
318
+ /**
319
+ * A pure open object dictionary whose values the program explicitly leaves
320
+ * dynamic.
321
+ *
322
+ * BSON's `Document` is exactly `{ [key: string]: any }`. TypeScript permits a
323
+ * value with that annotation to be flow-narrowed to Array, Map or a named
324
+ * record by `Array.isArray`, `instanceof` and user predicates. Those narrowed
325
+ * values do not become dictionaries at runtime; the annotation is an upper
326
+ * bound on property reads, while the flow facts still state their physical
327
+ * identities. This predicate is deliberately limited to a memberless string
328
+ * index with an explicit `any` value so an ordinary typed record is never
329
+ * widened by the mechanism below.
330
+ */
331
+ const openDynamicObjectUpperBound = (checker, parameter) => {
332
+ if (!parameter.type || !ts.isIdentifier(parameter.name) || parameter.dotDotDotToken)
333
+ return null;
334
+ const declared = checker.getTypeFromTypeNode(parameter.type);
335
+ if (checker.getPropertiesOfType(declared).length !== 0)
336
+ return null;
337
+ const dynamicStringIndex = checker
338
+ .getIndexInfosOfType(declared)
339
+ .find((index) => (index.keyType.flags & ts.TypeFlags.String) !== 0 && (index.type.flags & ts.TypeFlags.Any) !== 0);
340
+ return dynamicStringIndex ? declared : null;
341
+ };
342
+ /**
343
+ * A flow narrowing that changes the value's physical container identity.
344
+ *
345
+ * An open `[string]: any` annotation admits both exotic containers and named
346
+ * structural records. Only the former need a distinct storage arm: Array and
347
+ * the keyed collections have layouts a dictionary cannot impersonate. A user
348
+ * predicate narrowing the same value to a record interface merely gives typed
349
+ * names to dictionary properties; treating that view as a second allocation
350
+ * kind loses negative narrowing when control leaves the predicate branch.
351
+ */
352
+ const isFlowContainerType = (checker, anchor, type) => checker.isArrayType(type) || ['Map', 'Set', 'WeakMap', 'WeakSet'].some((name) => isStandardInterfaceType(checker, anchor, name, type));
353
+ export const indexParameterBindingProgram = (checker, files, reachable, valueFlow = indexValueFlow(checker, files, reachable), argumentsObjects = censusArgumentsObjects(checker, files)) => {
354
+ // `GEA_INDEX_TIMING=1` prints what one build of this index costs. It is the
355
+ // only honest way to price the hoist on a shared machine: across two runs
356
+ // the load swings by a factor of two and `dist/` is rebuilt underneath
357
+ // them, but WITHIN one run the count of builds is the whole difference --
358
+ // five without the hoist, one with it.
359
+ const startedAt = process.env['GEA_INDEX_TIMING'] ? performance.now() : 0;
360
+ const candidates = [];
361
+ const restParameterCandidates = [];
362
+ const omissionSites = [];
363
+ const assigned = new Set();
364
+ // An update, logical assignment, destructuring assignment, or loop binding
365
+ // also replaces a parameter. Sharing the write inventory prevents the
366
+ // argument census from retaining an argument-only carrier after such a write.
367
+ const assignedEvidence = new Map();
368
+ for (const write of valueFlow.allWrites) {
369
+ if (write.slot !== 'whole' || !write.target.symbol)
370
+ continue;
371
+ const declaration = write.target.declaration;
372
+ if (declaration &&
373
+ ts.isParameter(declaration) &&
374
+ write.edge !== 'call-argument' &&
375
+ write.edge !== 'super-argument' &&
376
+ write.edge !== 'default-parameter') {
377
+ assigned.add(write.target.symbol);
378
+ // A compound assignment or update names no sub-expression holding the
379
+ // written value, so the flow layer records none. The checker can state
380
+ // its result at the whole expression; operand-sensitive cases may need
381
+ // the complete incoming frame before that result can be recovered. Every other write hands over its value expression, and
382
+ // a write that hands over neither leaves this parameter with a gap no
383
+ // join can close.
384
+ const evidence = write.edge === 'compound-assignment' &&
385
+ (ts.isBinaryExpression(write.site) || ts.isPostfixUnaryExpression(write.site) || ts.isPrefixUnaryExpression(write.site))
386
+ ? { expression: write.site, operatorTyped: true }
387
+ : write.value !== null
388
+ ? { expression: write.value, operatorTyped: false }
389
+ : null;
390
+ const seen = assignedEvidence.get(write.target.symbol);
391
+ if (seen === null)
392
+ continue;
393
+ if (evidence === null)
394
+ assignedEvidence.set(write.target.symbol, null);
395
+ else if (seen)
396
+ seen.push(evidence);
397
+ else
398
+ assignedEvidence.set(write.target.symbol, [evidence]);
399
+ }
400
+ }
401
+ const allCalls = valueFlow.calls.map((site) => site.call);
402
+ const checkerAttribution = new Map(valueFlow.calls.map((site) => [site.call, site.checkerDeclaration]));
403
+ const invocationOperands = new Map(valueFlow.calls.map((site) => [site.call, site.operands]));
404
+ for (const file of files) {
405
+ // The same boundary `flow/value-flow.ts` has always walked, and the fourth
406
+ // census to need it (`local-bindings.ts` and `collection-bindings.ts` were
407
+ // the other two corrected). `forEachReachableStatement` filters TOP-LEVEL
408
+ // statements only; a method inside a reachable class that whole-program DCE
409
+ // has pruned is still descended into by the bare `ts.forEachChild` below.
410
+ // Its parameters were therefore gathered as candidates, `agreedArgumentType`
411
+ // asked `calls` a question about a body that never runs, and the correct
412
+ // answer -- no call sites, no counted references -- was published as a
413
+ // refusal. The three.js app's `Quaternion.setFromUnitVectors`,
414
+ // `Vector3.project`/`unproject` and the whole pruned `BufferGeometry`
415
+ // helper set are refusals of exactly this kind: evidence that was never
416
+ // going to exist for code that is never emitted.
417
+ const visit = (node) => {
418
+ if (reachable.memberIsPruned(node))
419
+ return;
420
+ if (isTrackedCallable(node)) {
421
+ runtimeParametersOf(node).forEach((parameter, index) => {
422
+ // An UNANNOTATED rest parameter is a candidate for its OWN
423
+ // element-wise join (`restElementTypeAt`), never for the ordinary
424
+ // fixed-position sweep below -- `isUnannotated` returns `false` for
425
+ // every rest parameter precisely because a rest parameter's slot is
426
+ // not one argument's type. A real annotation (`...args: string[]`,
427
+ // even the widening `...args: any`) is the program stating a real
428
+ // element already, and is left to the checker exactly as before.
429
+ if (parameter.dotDotDotToken !== undefined && parameter.type === undefined) {
430
+ restParameterCandidates.push({ declaration: node, parameter, index });
431
+ }
432
+ if (isUnannotated(checker, parameter))
433
+ candidates.push({ declaration: node, parameter, index, stated: null, flowCarrierUpperBound: null });
434
+ else {
435
+ const stated = statedUpperBound(checker, parameter);
436
+ const flowCarrierUpperBound = openDynamicObjectUpperBound(checker, parameter);
437
+ if (stated || flowCarrierUpperBound)
438
+ candidates.push({
439
+ declaration: node,
440
+ parameter,
441
+ index,
442
+ stated: stated ?? flowCarrierUpperBound,
443
+ flowCarrierUpperBound
444
+ });
445
+ else {
446
+ // Not inferred -- but a caller may still leave it out.
447
+ const omissionStated = omissionStatedTypeOf(checker, parameter);
448
+ if (omissionStated)
449
+ omissionSites.push({ declaration: node, parameter, index, stated: omissionStated });
450
+ }
451
+ }
452
+ });
453
+ }
454
+ ts.forEachChild(node, visit);
455
+ };
456
+ forEachReachableStatement(reachable, file, visit);
457
+ }
458
+ /**
459
+ * VALUE-FLOW evidence for the two alias shapes `isBindingOnlyReference`
460
+ * treats as non-escapes: which functions are published under a member
461
+ * symbol, and which are bare-returned from a selector. Built once --
462
+ * see `AliasEvidence`'s own doc for why this does not need the round loop.
463
+ */
464
+ const aliasEvidence = indexAliasEvidence(checker, files, reachable, indexNamedCallables(checker, files, reachable));
465
+ // A reassignment makes a parameter's value differ from the argument's -- but
466
+ // not, on its own, its TYPE. `function f(r, a) { r *= a; }` called as
467
+ // `f(1, 2)` holds a number on entry and a number after the write, and
468
+ // refusing it outright bound neither: three's
469
+ // `setClear( r, g, b, a, premultipliedAlpha )` lost all five parameters
470
+ // because three of them are scaled in the body. An assignment is a WRITE to
471
+ // the parameter's cell, exactly as a `let`'s later assignment is a write to
472
+ // its cell, and `writeSetTypeOf` already answers that shape by joining every
473
+ // write. So the assigned values join the call-site arguments and face the
474
+ // same agreement test -- `x = 'text'` against `f(1)` still refuses, as a
475
+ // disagreement rather than as a category.
476
+ //
477
+ // What survives as a category is a reassignment whose written value this
478
+ // layer never produced (a destructuring or iteration binding it does not
479
+ // open). There the cell holds something unstated, and no join can close it.
480
+ // That test is a fact about the program, asked here once rather than once
481
+ // per round, and the refusal keeps naming the parameter.
482
+ const notReassigned = [];
483
+ const reassigned = [];
484
+ for (const candidate of candidates) {
485
+ const symbol = checker.getSymbolAtLocation(candidate.parameter.name);
486
+ if (symbol && assigned.has(symbol) && assignedEvidence.get(symbol) == null)
487
+ reassigned.push(candidate);
488
+ else
489
+ notReassigned.push(candidate);
490
+ }
491
+ /**
492
+ * Every method declaration that OVERRIDES a given base-class method, keyed
493
+ * by the base's own declaration.
494
+ *
495
+ * A call is written against the declaration the checker resolves it to,
496
+ * which for `this.interpolate_( i1, t0, t, t1 )` inside `Interpolant` is
497
+ * `Interpolant`'s own declaration -- never `LinearInterpolant`'s override,
498
+ * even though that override is what actually runs. The override therefore
499
+ * looks callerless (`no-call-site`) and its parameters stay `any`, which is
500
+ * how three's whole interpolant, loader and curve hierarchy stays dynamic:
501
+ * `interpolate_`, `load`, `getTangentAt` are each defined once with real
502
+ * callers on the base and re-declared with none on every subclass.
503
+ *
504
+ * Inheriting the base's calls is sound because it states LESS than the
505
+ * program does, not more: a virtual call may dispatch into ANY override, so
506
+ * every override's parameter storage must already accept what that call
507
+ * passes. Evidence is only ever ADDED -- the override's own direct calls are
508
+ * still collected, both sets feed the same `widestOf` join, and a genuine
509
+ * disagreement between them refuses with `call-sites-disagree` rather than
510
+ * picking a side. An override with more parameters than the base is passed
511
+ * fewer arguments than it declares, which `call-passes-no-argument` already
512
+ * refuses; that is a refusal replacing a refusal, never a binding.
513
+ *
514
+ * Built once, outside the fixpoint: class inheritance is a fact about the
515
+ * program's syntax, so unlike call attribution it cannot improve as
516
+ * bindings accumulate.
517
+ */
518
+ const overridesOfBaseMethod = (() => {
519
+ const overrides = new Map();
520
+ const record = (base, override) => {
521
+ const existing = overrides.get(base);
522
+ if (existing)
523
+ existing.push(override);
524
+ else
525
+ overrides.set(base, [override]);
526
+ };
527
+ const link = (method) => {
528
+ const owner = method.parent;
529
+ if (!ts.isClassDeclaration(owner) && !ts.isClassExpression(owner))
530
+ return;
531
+ if (!ts.isIdentifier(method.name))
532
+ return;
533
+ const name = method.name.text;
534
+ const seen = new Set();
535
+ // `getBaseTypes` READS `resolvedBaseTypes` and is defined only for a
536
+ // class-or-interface type. Handing it any other object type -- or the
537
+ // STATIC side of a class, which `getTypeAtLocation(classDeclaration)`
538
+ // returns -- throws rather than answering, so both are tested here.
539
+ const classOrInterface = (type) => type !== undefined &&
540
+ (type.flags & ts.TypeFlags.Object) !== 0 &&
541
+ (type.objectFlags & ts.ObjectFlags.ClassOrInterface) !== 0;
542
+ const climb = (type, depth) => {
543
+ if (depth > 8)
544
+ return;
545
+ for (const base of checker.getBaseTypes(type) ?? []) {
546
+ if (!base || seen.has(base))
547
+ continue;
548
+ seen.add(base);
549
+ for (const declaration of checker.getPropertyOfType(base, name)?.declarations ?? []) {
550
+ if (ts.isMethodDeclaration(declaration) && declaration !== method)
551
+ record(declaration, method);
552
+ }
553
+ if (classOrInterface(base))
554
+ climb(base, depth + 1);
555
+ }
556
+ };
557
+ const ownSymbol = owner.name ? checker.getSymbolAtLocation(owner.name) : checker.getTypeAtLocation(owner).getSymbol();
558
+ const ownType = ownSymbol ? checker.getDeclaredTypeOfSymbol(ownSymbol) : undefined;
559
+ if (classOrInterface(ownType))
560
+ climb(ownType, 0);
561
+ };
562
+ const walk = (node) => {
563
+ if (ts.isMethodDeclaration(node))
564
+ link(node);
565
+ ts.forEachChild(node, walk);
566
+ };
567
+ for (const file of files)
568
+ forEachReachableStatement(reachable, file, walk);
569
+ return overrides;
570
+ })();
571
+ /**
572
+ * `overridesOfBaseMethod` links a SUBCLASS method to the base it overrides
573
+ * through `extends`. This links the OTHER way one symbol gets more than one
574
+ * body: a class's own declared shape of a key alongside a `receiver.<name>
575
+ * = function ( ... ) { ... }` write that overrides it on ONE instance,
576
+ * never through inheritance. Three's `mesh.onBeforeRender = function (
577
+ * renderer, object ) { ... }` next to `Object3D`'s declared (empty)
578
+ * `onBeforeRender(){}` is exactly this: `object.onBeforeRender( this,
579
+ * object )` resolves, through the checker, to the STATED stub -- TypeScript
580
+ * has no flow model of "this one instance was later given its own property"
581
+ * -- so every call through an `Object3D`-typed receiver is attributed there
582
+ * and never to the override that actually runs and reads its parameters.
583
+ * `nameOfCallable` already draws the member name out of both shapes;
584
+ * grouping by the SYMBOL the checker resolves that name to (never by
585
+ * spelling) is what keeps this sound against an unrelated look-alike: an
586
+ * object literal's own `onBeforeRender(){}` gets its OWN anonymous-type
587
+ * property symbol, never `Object3D`'s, so it is never grouped with the
588
+ * class's declaration and never receives its calls.
589
+ *
590
+ * No separate "is this slot closed" gate is needed here: attributing a call
591
+ * between siblings only ever ADDS evidence, exactly as `overridesOfBaseMethod`
592
+ * argues above, and `escapeReason`'s own member-closure obligation --
593
+ * asked of the SAME symbol, over EVERY write to it -- already refuses
594
+ * whenever some other write into the slot cannot be named. This can only
595
+ * widen a join or trigger that existing refusal; it cannot narrow one.
596
+ */
597
+ const siblingMemberDeclarations = (() => {
598
+ const bySymbol = new Map();
599
+ const record = (declaration) => {
600
+ const name = nameOfCallable(declaration);
601
+ const symbol = name && checker.getSymbolAtLocation(name);
602
+ if (!symbol)
603
+ return;
604
+ const existing = bySymbol.get(symbol);
605
+ if (existing)
606
+ existing.push(declaration);
607
+ else
608
+ bySymbol.set(symbol, [declaration]);
609
+ };
610
+ const walk = (node) => {
611
+ if ((ts.isFunctionExpression(node) || ts.isArrowFunction(node) || ts.isMethodDeclaration(node)) &&
612
+ 'body' in node &&
613
+ node.body !== undefined)
614
+ record(node);
615
+ ts.forEachChild(node, walk);
616
+ };
617
+ for (const file of files)
618
+ forEachReachableStatement(reachable, file, walk);
619
+ const result = new Map();
620
+ for (const declarations of bySymbol.values()) {
621
+ if (declarations.length < 2)
622
+ continue;
623
+ for (const declaration of declarations)
624
+ result.set(declaration, declarations.filter((other) => other !== declaration));
625
+ }
626
+ return result;
627
+ })();
628
+ if (process.env['GEA_INDEX_TIMING']) {
629
+ process.stderr.write(`[INDEX] parameter-binding program index built in ${(performance.now() - startedAt).toFixed(0)}ms\n`);
630
+ }
631
+ return Object.freeze({
632
+ implicitArgumentsUses: argumentsObjects.usesByOwner,
633
+ valueFlow,
634
+ candidates,
635
+ restParameterCandidates,
636
+ notReassigned,
637
+ reassigned,
638
+ omissionSites,
639
+ assigned,
640
+ assignedEvidence,
641
+ allCalls,
642
+ checkerAttribution,
643
+ invocationOperands,
644
+ aliasEvidence,
645
+ overridesOfBaseMethod,
646
+ siblingMemberDeclarations
647
+ });
648
+ };
649
+ /**
650
+ * The declared tuple element a call's LAST argument, a spread of a closed-tuple
651
+ * rest parameter, supplies at argument position `index`, or `null` when the
652
+ * call has no such spread or `index` lies before it or past its arity. Only a
653
+ * final spread: a written argument after a spread would land at a position
654
+ * only the spread's runtime length knows.
655
+ */
656
+ const declaredTupleSpreadPositionAt = (checker, args, index) => {
657
+ const spreadAt = args.findIndex(ts.isSpreadElement);
658
+ if (spreadAt === -1 || spreadAt !== args.length - 1 || index < spreadAt)
659
+ return null;
660
+ const spread = args[spreadAt];
661
+ if (!spread || !ts.isSpreadElement(spread) || !ts.isIdentifier(spread.expression))
662
+ return null;
663
+ const declaration = checker.getSymbolAtLocation(spread.expression)?.valueDeclaration;
664
+ if (!declaration || !ts.isParameter(declaration))
665
+ return null;
666
+ return declaredClosedTupleRestElementsOf(checker, declaration)?.[index - spreadAt] ?? null;
667
+ };
668
+ export const censusParameterBindings = (checker, files, reachable,
669
+ /**
670
+ * A previously composed census this round may read from, the same way
671
+ * `withReturnBindings` and `withLocalBindings` already take one.
672
+ *
673
+ * `censusParameterBindings` used to be the one census with no upstream at
674
+ * all: `return-bindings.ts` and `local-bindings.ts` both compose OVER its
675
+ * output, but nothing ever composed back INTO it, so it answered every
676
+ * question -- including "what does this call site's argument hold" -- with
677
+ * only the checker's own evidence and its own internal fixpoint. That is
678
+ * why `texture`, `attribute` and `geometry` stayed `any` in the three.js app even
679
+ * after the other two censuses learned their receivers: those parameters'
680
+ * call sites pass expressions -- `state.buffers`, `const me = m.elements`
681
+ * one step removed -- whose types only exist once a LATER census has run,
682
+ * and by the time it runs this one has already finished.
683
+ *
684
+ * Feeding a prior round's composed census in here as `upstream` closes that
685
+ * gap for a second round: `known()` below consults it exactly where it
686
+ * already falls back from "the checker has no answer" to "keep looking",
687
+ * ahead of this census's own machinery reconstructing one from scratch.
688
+ * `emptyParameterBindingCensus` (round one, and every other caller) makes
689
+ * this identical to the unparameterized behaviour before -- `?? null` never
690
+ * changes an answer this module already had.
691
+ *
692
+ * ⛔ This is also the reason `binding-fixpoint.ts` carrying only
693
+ * `.parameters` across the round boundary (never `.facts.valueFlow`) does
694
+ * NOT stop a finished round's `ValueFlowIndex` from staying reachable.
695
+ * `known()` and `computeStatedTypeAt()` below close over BOTH `valueFlow`
696
+ * (this round's own) and `upstream` (this round's WHOLE argument, not a
697
+ * snapshot of it) so they can answer a node neither has seen yet. The
698
+ * object this function returns is exactly `upstream` for the NEXT round --
699
+ * so round N+1's `typeAt` closes over round N's `typeAt`, which closes over
700
+ * round N-1's, back to round one. `sourceValueSessionOf`
701
+ * (`flow/source-value-session.ts`) memoizes a ~1 GB dependency-solver
702
+ * session in a WeakMap keyed on the `ValueFlowIndex` object identity, so
703
+ * every round on this chain that was ever asked a call-target/receiver
704
+ * question keeps its whole session alive for as long as `settled.parameters`
705
+ * (`frontend.ts`) is reachable -- which is the rest of the compile. Measured
706
+ * on the three.js app: 4 rounds, 4 live `[SOLVER]` sessions at exit, not 1.
707
+ *
708
+ * Not cut here. Forcing `known()`/`computeStatedTypeAt()` to resolve eagerly
709
+ * instead of lazily falling through to `upstream` would answer a node
710
+ * before the round that can actually answer it has run -- the exact
711
+ * pending-read-as-decided collapse `SEMANTIC-AUTHORITY.md` §2(b) names.
712
+ * Truncating the chain (answering from this round's own evidence only,
713
+ * dropping `upstream` once this round stops being the fixpoint's active
714
+ * `previousCensus`) is answer-preserving only if no node reachable after
715
+ * that point was going to need a fact this round's own machinery never
716
+ * independently derived -- true for the RECORDED node set the convergence
717
+ * check in `binding-fixpoint.ts` verifies, unproven for the unbounded set of
718
+ * nodes `frontend.ts` and every downstream producer query afterward, and
719
+ * unverifiable here since the emitted-set gate is off-limits mid-measurement.
720
+ * A real fix has `typeAt`/`statedTypeAt`/`patternReadTypeAt` take the
721
+ * requesting round's own `ValueFlowIndex` as a call-time argument instead of
722
+ * a captured one, which is a migration of the shared `ParameterBindingCensus`
723
+ * surface (`return-bindings.ts`, `local-bindings.ts`, `field-bindings.ts`,
724
+ * `structural.ts`, every producer that calls `typeAt`), not a change
725
+ * confined to this file.
726
+ */
727
+ upstream = emptyParameterBindingCensus,
728
+ /**
729
+ * The program index every round shares. Defaulted so a caller that runs the
730
+ * census once needs no change; `frontend.ts`, which runs it up to eight
731
+ * times, builds it once and passes it.
732
+ */
733
+ index = indexParameterBindingProgram(checker, files, reachable),
734
+ /**
735
+ * The current round's value-flow facts. The reusable program index owns
736
+ * syntax discovery, not the evolving call attribution and collection edges.
737
+ * A one-shot census can use its index's flow; a composed census must receive
738
+ * the same round snapshot as the field, local, return and collection censuses.
739
+ */
740
+ valueFlow = index.valueFlow) => {
741
+ /** Every call this program makes, grouped by the declaration its signature resolved to. */
742
+ const callsByDeclaration = new Map();
743
+ const callTargets = new Map();
744
+ const resolvedCallDeclarations = new Map();
745
+ /**
746
+ * A `.call`/`.apply` wrapper whose receiver's checker type gave
747
+ * `unwrapExplicitThisCall` no call signature to unwrap statically (an
748
+ * untyped JS array element, `array[ i ].call( this, event )`), authenticated
749
+ * here instead by the SAME closed-array proof `aliasDeclarationsFor` already
750
+ * asks for TYPE attribution just below -- see its own comment. Feeds
751
+ * `indexValueFlow`'s `censusExplicitThisAt` on the NEXT round, so the
752
+ * operand frame this round proved sound becomes the one the whole flow
753
+ * index (argument-to-parameter binding included, not just target
754
+ * resolution) is built from, rather than staying a second reading nobody
755
+ * downstream of `site.operands` would ever see.
756
+ */
757
+ const pendingExplicitThisReadings = new Map();
758
+ /**
759
+ * Built once by `indexParameterBindingProgram` and shared by every round --
760
+ * see its doc. `callsByDeclaration` above is the one index that is NOT
761
+ * shared: `attributeCalls` rewrites it as bindings improve.
762
+ */
763
+ const { allCalls, checkerAttribution, invocationOperands, aliasEvidence, overridesOfBaseMethod, siblingMemberDeclarations, assignedEvidence } = index;
764
+ const protocolLedger = deferredIntrinsicProtocolLedgerOf(valueFlow);
765
+ const protocolRequirements = new Map();
766
+ const upstreamProtocolRequirements = protocolLedger?.requirements() ?? [];
767
+ /** What each bound parameter declaration now holds. */
768
+ const bindings = new Map();
769
+ /** Synthesized union arms for a disjointly-disagreeing parameter -- see `agreedArgumentType`. */
770
+ const unionArms = new Map();
771
+ // A synthesized parameter union is also a value read by sibling parameter
772
+ // inference. Publishing only unionArmsAt lets structural layout see it while
773
+ // a forwarding call sees no type at all. Materialize the same admitted arms
774
+ // through the shared checker union helper, without adding new alternatives.
775
+ const unionTypes = new Map();
776
+ const parameterTypeOf = (parameter) => {
777
+ const bound = bindings.get(parameter);
778
+ if (bound)
779
+ return bound;
780
+ const arms = unionArms.get(parameter);
781
+ if (!arms)
782
+ return null;
783
+ if (!unionTypes.has(parameter))
784
+ unionTypes.set(parameter, disjointUnionTypeOf(checker, arms));
785
+ return unionTypes.get(parameter) ?? null;
786
+ };
787
+ /** What each array-pattern element reads before its default -- see `patternReadTypeAt`. */
788
+ const patternReadTypes = new Map();
789
+ /** Physical object arms proven by flow narrowing of an open dynamic-object upper bound. */
790
+ const flowCarrierArms = new Map();
791
+ const flowCarrierBounds = new Map();
792
+ /**
793
+ * Whether every reference to this function's name is a call this census
794
+ * counted. A function nothing holds as a value has exactly the callers this
795
+ * enumeration found, which is what makes binding from them sound.
796
+ */
797
+ /**
798
+ * A returned record is a real callable flow edge, not an unknown escape,
799
+ * when its property declaration and complete value-flow inventory show only
800
+ * attributed calls. This is the same negative proof as the direct-name
801
+ * check below, applied one level farther out: accepting the object literal
802
+ * merely because it *looks* like a return would let an unobserved
803
+ * `record[key]()` call narrow an implicit-arguments frame from a partial
804
+ * sample.
805
+ */
806
+ /**
807
+ * Whether every value a cell can hold was ALLOCATED here -- following a
808
+ * write that merely FORWARDS another cell's value into it.
809
+ *
810
+ * A factory result reaches its reader by being PASSED. Three builds `state`
811
+ * once in `WebGLRenderer` and hands it to `WebGLTextures`, so the cell this
812
+ * proof actually examines is `WebGLTextures`'s own `state` parameter, whose
813
+ * only write is the argument edge naming `state` -- a bare identifier.
814
+ * Refusing that outright refused the ordinary way a record travels, which
815
+ * is the very case the caller's own comment describes, and it proved
816
+ * nothing: an identifier names a cell whose writes this same index holds,
817
+ * so the question is answerable one hop out rather than unanswerable. All
818
+ * ten of `WebGLState`'s `arguments` shims died here.
819
+ *
820
+ * A forward is followed only to a cell whose OWN writes satisfy the same
821
+ * test, so nothing is admitted that an allocation does not ultimately back.
822
+ * A cycle answers `true` because some other write in it must still be an
823
+ * allocation for the cell to hold anything at all; every other value kind
824
+ * stays the refusal it was.
825
+ */
826
+ const cellHoldsOnlyAllocations = (symbol, seen) => {
827
+ if (seen.has(symbol))
828
+ return true;
829
+ seen.add(symbol);
830
+ // A PARAMETER's write inventory is its argument edges, so it is complete
831
+ // only while every call site is counted -- the same obligation the
832
+ // factory itself is already held to a few lines above.
833
+ const declaration = symbol.valueDeclaration;
834
+ if (declaration && ts.isParameter(declaration)) {
835
+ const owner = ts.findAncestor(declaration, isTrackedCallable);
836
+ if (!owner || escapeReason(owner, true) !== null)
837
+ return false;
838
+ }
839
+ for (const write of valueFlow.writesToSymbol(symbol)) {
840
+ if (write.slot !== 'whole' || write.value === null)
841
+ continue;
842
+ const value = write.value;
843
+ if (ts.isCallExpression(value) || ts.isNewExpression(value) || ts.isObjectLiteralExpression(value))
844
+ continue;
845
+ if (ts.isIdentifier(value)) {
846
+ const forwarded = valueFlow.targetOf(value)?.symbol;
847
+ if (forwarded && cellHoldsOnlyAllocations(forwarded, seen))
848
+ continue;
849
+ }
850
+ return false;
851
+ }
852
+ return true;
853
+ };
854
+ /** Why the published-member proof gave up, for `GEA_ESCAPE_DEBUG`; always `false`, so it reads as the refusal it replaces. */
855
+ const escapeTrace = (member, reason) => {
856
+ if (process.env['GEA_ESCAPE_DEBUG'])
857
+ console.error(`[ESCAPE-PUBLISHED] ${member.name} ${reason}`);
858
+ return false;
859
+ };
860
+ const publishedMemberUsesAreCounted = (member, counted) => {
861
+ // Property symbols are late-bound by the checker: two lookups of the
862
+ // same inferred member commonly produce distinct Symbol objects. The
863
+ // declaration node is the stable identity shared by value-flow and the
864
+ // alias index, so use it for the completeness proof.
865
+ const declarations = member.declarations ?? [];
866
+ const accesses = declarations.flatMap((declaration) => valueFlow.referencesToDeclaration(declaration));
867
+ // An empty set is not a proof. It means this property's value-flow index
868
+ // could not connect the publication to a use, so retaining the dynamic
869
+ // checker frame is safer than inferring from no calls.
870
+ if (accesses.length === 0)
871
+ return escapeTrace(member, 'no-accesses');
872
+ const publication = declarations[0];
873
+ const factory = publication && ts.findAncestor(publication, isTrackedCallable);
874
+ const objectLiteral = publication?.parent;
875
+ const directReturn = objectLiteral &&
876
+ ts.isObjectLiteralExpression(objectLiteral) &&
877
+ ts.isReturnStatement(objectLiteral.parent) &&
878
+ objectLiteral.parent.expression === objectLiteral;
879
+ if (!directReturn)
880
+ return escapeTrace(member, 'not-a-direct-return');
881
+ // Every factory result is an ownership instance. If the factory has more
882
+ // than one call site, a result that never exposes this member can still
883
+ // escape through an unknown API. A single attributed call is the smallest
884
+ // closed publication set this proof can establish without inventing a
885
+ // result-to-receiver correspondence.
886
+ if (!factory)
887
+ return escapeTrace(member, 'no-factory');
888
+ if ((callsByDeclaration.get(factory)?.length ?? 0) !== 1)
889
+ return escapeTrace(member, `factory-call-sites=${callsByDeclaration.get(factory)?.length ?? 0}`);
890
+ const factoryEscape = escapeReason(factory, true);
891
+ if (factoryEscape !== null)
892
+ return escapeTrace(member, `factory-escapes:${factoryEscape}`);
893
+ const receivers = new Set();
894
+ for (const reference of accesses) {
895
+ if (ts.isElementAccessExpression(reference))
896
+ return false;
897
+ if (ts.isPropertyAccessExpression(reference)) {
898
+ if (!counted.has(reference))
899
+ return false;
900
+ // A receiver with no named cell (`factory().method()` or
901
+ // `{ api: factory() }.api.method()`) has no complete use inventory.
902
+ // Refuse it rather than treating the one visible call as the whole
903
+ // factory-result flow.
904
+ if (!ts.isIdentifier(reference.expression))
905
+ return escapeTrace(member, 'receiver-not-a-named-cell');
906
+ const receiver = valueFlow.targetOf(reference.expression);
907
+ if (receiver?.symbol)
908
+ receivers.add(receiver.symbol);
909
+ continue;
910
+ }
911
+ if (ts.isIdentifier(reference)) {
912
+ const parent = reference.parent;
913
+ if (ts.isPropertyAccessExpression(parent) && parent.name === reference && counted.has(parent))
914
+ continue;
915
+ if (ts.isPropertyAssignment(parent) && (parent.name === reference || parent.initializer === reference))
916
+ continue;
917
+ if (ts.isShorthandPropertyAssignment(parent) && parent.name === reference)
918
+ continue;
919
+ return escapeTrace(member, `identifier-use:${ts.SyntaxKind[parent.kind]}`);
920
+ }
921
+ return escapeTrace(member, `reference-kind:${ts.SyntaxKind[reference.kind]}`);
922
+ }
923
+ // A factory result can be safely kept as a record while its members are
924
+ // read, but passing the record itself through another cell/API is an
925
+ // escape the member census cannot enumerate. Check the shared reference
926
+ // inventory for every named receiver discovered above; a property read
927
+ // is a closed use, every other use is a leak (including object spread,
928
+ // assignment, and an unknown call argument).
929
+ if (receivers.size === 0)
930
+ return escapeTrace(member, 'no-named-receivers');
931
+ for (const receiver of receivers) {
932
+ if (!cellHoldsOnlyAllocations(receiver, new Set()))
933
+ return escapeTrace(member, 'receiver-holds-more-than-allocations');
934
+ const references = valueFlow.referencesToSymbol(receiver);
935
+ if (references.length === 0)
936
+ return escapeTrace(member, 'receiver-has-no-references');
937
+ for (const reference of references) {
938
+ if (!ts.isIdentifier(reference))
939
+ continue;
940
+ const type = checker.getTypeAtLocation(reference);
941
+ if ((type.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) !== 0)
942
+ return escapeTrace(member, `receiver-${receiver.name}-is-any`);
943
+ const parent = reference.parent;
944
+ if (ts.isVariableDeclaration(parent) && parent.name === reference)
945
+ continue;
946
+ if (ts.isBindingElement(parent) && parent.name === reference)
947
+ continue;
948
+ // A parameter's own name declares the cell; it is no more a use of the
949
+ // record than a variable declaration's name is. Omitting it refused
950
+ // every receiver that arrives as a parameter, which is every receiver
951
+ // a factory result is passed to.
952
+ if (ts.isParameter(parent) && parent.name === reference)
953
+ continue;
954
+ if (ts.isPropertyAccessExpression(parent) && parent.expression === reference)
955
+ continue;
956
+ return escapeTrace(member, `receiver-use:${ts.SyntaxKind[parent.kind]}`);
957
+ }
958
+ }
959
+ return true;
960
+ };
961
+ /** The member symbol published by an object-literal property value. */
962
+ const publishedMemberOf = (reference) => {
963
+ const parent = reference.parent;
964
+ if (ts.isPropertyAssignment(parent) && parent.initializer === reference) {
965
+ const name = parent.name;
966
+ if (!ts.isIdentifier(name) && !ts.isStringLiteralLike(name) && !ts.isNumericLiteral(name))
967
+ return null;
968
+ return checker.getTypeAtLocation(parent.parent).getProperty(name.text) ?? null;
969
+ }
970
+ if (ts.isShorthandPropertyAssignment(parent) && parent.name === reference) {
971
+ return checker.getTypeAtLocation(parent.parent).getProperty(parent.name.text) ?? null;
972
+ }
973
+ return null;
974
+ };
975
+ const isDirectReturnedPublication = (reference) => {
976
+ const parent = reference.parent;
977
+ if (!ts.isPropertyAssignment(parent) && !ts.isShorthandPropertyAssignment(parent))
978
+ return false;
979
+ const objectLiteral = parent.parent;
980
+ return (ts.isObjectLiteralExpression(objectLiteral) &&
981
+ ts.isReturnStatement(objectLiteral.parent) &&
982
+ objectLiteral.parent.expression === objectLiteral);
983
+ };
984
+ /** Match an inferred member through its stable declaration, not Symbol identity. */
985
+ const publishedDeclarationsFor = (member) => {
986
+ const direct = aliasEvidence.publishedUnderMember.get(member);
987
+ if (direct)
988
+ return direct;
989
+ const declarations = member.declarations ?? [];
990
+ if (declarations.length === 0)
991
+ return undefined;
992
+ let result;
993
+ for (const [candidate, values] of aliasEvidence.publishedUnderMember) {
994
+ if (!(candidate.declarations ?? []).some((declaration) => declarations.includes(declaration)))
995
+ continue;
996
+ if (!result)
997
+ result = new Set();
998
+ for (const value of values)
999
+ result.add(value);
1000
+ }
1001
+ return result;
1002
+ };
1003
+ const callbackContracts = new Map();
1004
+ const memberOpenUses = new Map();
1005
+ const contractsFor = (declaration) => {
1006
+ const cached = callbackContracts.get(declaration);
1007
+ if (cached !== undefined)
1008
+ return cached;
1009
+ const result = callbackParameterContractsFor(checker, valueFlow, declaration, new Set(callsByDeclaration.get(declaration) ?? []));
1010
+ callbackContracts.set(declaration, result);
1011
+ return result;
1012
+ };
1013
+ const escapeReason = (declaration, requireCountedReferences = false) => {
1014
+ memberOpenUses.delete(declaration);
1015
+ const name = nameOfCallable(declaration);
1016
+ if (!name)
1017
+ return `function-escapes:unnamed:${declaration.parent ? ts.SyntaxKind[declaration.parent.kind] : 'root'}`;
1018
+ const symbol = checker.getSymbolAtLocation(name);
1019
+ if (!symbol)
1020
+ return 'function-escapes:no-symbol';
1021
+ const calls = callsByDeclaration.get(declaration) ?? [];
1022
+ // The receiving formal publishes a complete callback input contract only
1023
+ // when every use of this function is accounted for by the shared flow.
1024
+ // This is parameter evidence, not the stricter single-publication proof
1025
+ // used by factory/receiver analyses elsewhere in this census.
1026
+ const memberClosed = (member) => hasClosedMemberCallableUses(checker, valueFlow, member, new Set(calls), memberClosureReceiverTypeAt, implicitArgumentsUsesAt, (reference, kind) => {
1027
+ const path = memberOpenUses.get(declaration) ?? [];
1028
+ if (!path.some((entry) => entry.reference === reference && entry.kind === kind))
1029
+ path.push({ reference, kind });
1030
+ memberOpenUses.set(declaration, path);
1031
+ });
1032
+ // A method is carried by every instance of its class family, and one that
1033
+ // never names `.m` still hands unknown code a way to call it: after
1034
+ // `globalThis.unknownConsumer( new A() )` that code can run `m` with any
1035
+ // argument, or replace it on the shared prototype. The member-name
1036
+ // inventory below sees only the mentions; the member proof also walks
1037
+ // every construction of the family -- the obligation a function-valued
1038
+ // slot already owes just below.
1039
+ // ⛔ UNSOUND MEASUREMENT ARM (`GEA_MEMBER_ESCAPE_FORCE=<member>[,<member>]|*`):
1040
+ // prices what the member-closure obligation alone is holding open, for one
1041
+ // named method or for all of them. Never set it for a build whose output is
1042
+ // kept -- it admits a method the program can replace, or call with
1043
+ // arguments no site here counted.
1044
+ const escapeForce = process.env['GEA_MEMBER_ESCAPE_FORCE'];
1045
+ const forced = escapeForce !== undefined && (escapeForce === '*' || escapeForce.split(',').includes(symbol.getName()));
1046
+ if (ts.isMethodDeclaration(declaration) && !forced && !memberClosed(symbol))
1047
+ return 'function-escapes:uncounted-member-reference';
1048
+ // An export is a mention no expression spells. Code outside the stated
1049
+ // module set can call it -- `inProgramImportReferencesOf` answers null
1050
+ // then -- and every in-program importer's mention must be a counted call,
1051
+ // exactly as the declaring module's own mentions are below.
1052
+ if (ts.isFunctionDeclaration(declaration) && isModuleExportedDeclaration(checker, declaration, symbol)) {
1053
+ const imported = inProgramImportReferencesOf(checker, valueFlow, declaration);
1054
+ if (imported === null)
1055
+ return 'function-escapes:exported';
1056
+ const callees = new Set(calls.map((call) => (ts.isCallExpression(call) || ts.isNewExpression(call) ? call.expression : call)));
1057
+ if (!imported.every((mention) => callees.has(mention)))
1058
+ return 'function-escapes:uncounted-import';
1059
+ }
1060
+ if (!requireCountedReferences && contractsFor(declaration) !== null)
1061
+ return null;
1062
+ const publication = declaration.parent;
1063
+ const inlineMemberPublication = (ts.isPropertyAssignment(publication) && publication.initializer === declaration) ||
1064
+ (ts.isBinaryExpression(publication) &&
1065
+ publication.right === declaration &&
1066
+ publication.operatorToken.kind === ts.SyntaxKind.EqualsToken &&
1067
+ (ts.isPropertyAccessExpression(publication.left) || ts.isElementAccessExpression(publication.left)));
1068
+ const publishedMember = ts.isPropertyAssignment(publication)
1069
+ ? checker.getSymbolAtLocation(publication.name)
1070
+ : ts.isBinaryExpression(publication) && ts.isPropertyAccessExpression(publication.left)
1071
+ ? checker.getSymbolAtLocation(publication.left.name)
1072
+ : ts.isBinaryExpression(publication) && ts.isElementAccessExpression(publication.left)
1073
+ ? checker.getSymbolAtLocation(publication.left)
1074
+ : undefined;
1075
+ if ((ts.isArrowFunction(declaration) || ts.isFunctionExpression(declaration)) && inlineMemberPublication && !publishedMember)
1076
+ return 'function-escapes:unresolved-published-member';
1077
+ if ((ts.isArrowFunction(declaration) || ts.isFunctionExpression(declaration)) &&
1078
+ inlineMemberPublication &&
1079
+ (!publishedMember || !memberClosed(publishedMember)))
1080
+ return 'function-escapes:uncounted-member-reference';
1081
+ const counted = new Set(calls.map((call) => (ts.isCallExpression(call) || ts.isNewExpression(call) ? call.expression : call)));
1082
+ // Ordinary inference keeps its member-name inventory. The strict path
1083
+ // needs full declaration-keyed expression references to prove publication
1084
+ // closure, including shorthand values and receiver aliases.
1085
+ const references = requireCountedReferences
1086
+ ? (symbol.declarations ?? []).flatMap((declaration) => valueFlow.referencesToDeclaration(declaration))
1087
+ : valueFlow.memberReferencesToSymbol(symbol);
1088
+ for (const reference of references) {
1089
+ if (counted.has(reference))
1090
+ continue;
1091
+ if (requireCountedReferences) {
1092
+ if (reference === name || isTypePositionReference(reference))
1093
+ continue;
1094
+ const access = reference.parent;
1095
+ // `export { f }`, `export { f as g } from`, `import { f }`: the binding,
1096
+ // not a use. It is closed when nothing outside the stated module set
1097
+ // can reach it and every importer mention it leads to is counted.
1098
+ if (ts.isExportSpecifier(access) || ts.isImportSpecifier(access) || ts.isImportClause(access) || ts.isNamespaceImport(access)) {
1099
+ const exposure = inProgramImportReferencesOf(checker, valueFlow, ts.isExportSpecifier(access) ? access : declaration);
1100
+ if (exposure !== null && exposure.every((mention) => counted.has(mention)))
1101
+ continue;
1102
+ return 'function-escapes:uncounted-import';
1103
+ }
1104
+ if ((ts.isCallExpression(access) || ts.isNewExpression(access)) && isCalleeOf(reference, access) && counted.has(access.expression))
1105
+ continue;
1106
+ if (ts.isPropertyAccessExpression(access) && access.name === reference && counted.has(access))
1107
+ continue;
1108
+ const publishedMember = publishedMemberOf(reference);
1109
+ const publicationOwner = publishedMember?.declarations?.[0] && ts.findAncestor(publishedMember.declarations[0], isTrackedCallable);
1110
+ if (publishedMember && publicationOwner === declaration && isDirectReturnedPublication(reference))
1111
+ continue;
1112
+ // The record's uses reach past one cell -- three's `WebGLState` is
1113
+ // handed to `WebGLTextures` and kept on `renderer.state` -- and the
1114
+ // shared member proof is the one that walks call arguments and
1115
+ // fields: every mention of the slot a counted call, every receiver of
1116
+ // the record closed.
1117
+ if (publishedMember &&
1118
+ publishedDeclarationsFor(publishedMember)?.has(declaration) === true &&
1119
+ (publishedMemberUsesAreCounted(publishedMember, counted) || memberClosed(publishedMember)))
1120
+ continue;
1121
+ // WHICH half of the published-member proof failed is the only thing a
1122
+ // reader needs here, and the refusal string cannot carry it: all four
1123
+ // ways to miss spell the same word. `WebGLState`'s ten `arguments`
1124
+ // shims are refused here and nothing said which.
1125
+ if (process.env['GEA_ESCAPE_DEBUG']) {
1126
+ const site = reference.getSourceFile();
1127
+ console.error(`[ESCAPE] ${nameOfCallable(declaration)?.getText() ?? '<anonymous>'} uncounted at ` +
1128
+ `${site.fileName.split('/').pop()}:${site.getLineAndCharacterOfPosition(reference.getStart()).line + 1} ` +
1129
+ `"${reference.parent?.getText().replace(/\s+/g, ' ').slice(0, 60) ?? ''}" ` +
1130
+ `published=${publishedMember ? publishedMember.name : 'none'} ` +
1131
+ `owns=${publishedMember ? String(publishedDeclarationsFor(publishedMember)?.has(declaration) === true) : '-'} ` +
1132
+ `usesCounted=${publishedMember ? String(publishedMemberUsesAreCounted(publishedMember, counted)) : '-'} ` +
1133
+ `memberClosed=${publishedMember ? String(memberClosed(publishedMember)) : '-'}`);
1134
+ }
1135
+ return 'function-escapes:uncounted-reference';
1136
+ }
1137
+ if ((ts.isIdentifier(reference) || ts.isPrivateIdentifier(reference)) && isBindingOnlyReference(reference))
1138
+ continue;
1139
+ if (isTypePositionReference(reference))
1140
+ continue;
1141
+ const parent = reference.parent;
1142
+ if (parent && (ts.isCallExpression(parent) || ts.isNewExpression(parent)) && isCalleeOf(reference, parent))
1143
+ continue;
1144
+ return `function-escapes:${parent ? ts.SyntaxKind[parent.kind] : 'root'}`;
1145
+ }
1146
+ return null;
1147
+ };
1148
+ /**
1149
+ * A resolver, in one of the two strengths this census needs.
1150
+ *
1151
+ * `lateAssignment` is the difference, and it is a soundness boundary rather
1152
+ * than a tuning knob. `let extensions;` filled later by `extensions = new
1153
+ * WebGLExtensions( _gl )` tells you exactly what the CALL passes -- the call
1154
+ * is downstream of the assignment -- so binding a parameter from it is right.
1155
+ * It does not tell you what the variable's own CELL holds, because that cell
1156
+ * begins empty. Publishing the assignment's type for the cell asks the
1157
+ * compiler to convert `null` into a `class-ref`, which is what preflight
1158
+ * reported the moment this was tried both ways: twelve new
1159
+ * `binding-read-conversion:null->...` obligations, one per late-filled
1160
+ * binding in three's renderer.
1161
+ *
1162
+ * So the strong resolver propagates and the weak one publishes. A variable
1163
+ * the weak resolver will not answer for stays exactly as it is today --
1164
+ * boxed -- and the unboxing happens at the call boundary, where the value
1165
+ * really has arrived.
1166
+ */
1167
+ /**
1168
+ * `this`, read at its own keyword inside an ordinary (non-static) class
1169
+ * method, checks as the POLYMORPHIC self type -- `typeToString` spells it
1170
+ * literally `this` -- because the checker is answering for every possible
1171
+ * subclass, not this one. That is the right answer for the METHOD's own
1172
+ * signature, but wrong the moment `this` is READ as a plain value and
1173
+ * handed somewhere else: `object.onBeforeRender( this, object )` passes
1174
+ * the calling `Renderer`, not an unspellable self-type, and a parameter
1175
+ * bound from it must carry the concrete class the same way any other
1176
+ * argument's checker type does.
1177
+ *
1178
+ * Mirrors `structural-receiver.ts`'s `implicitReceiverOf`, which resolves
1179
+ * the identical instance case to `checker.getDeclaredTypeOfSymbol` on the
1180
+ * owning class for the ABI's receiver frame; this is the same fact, read
1181
+ * for a value use rather than a calling convention. Deliberately narrow:
1182
+ * only the plain instance-method shape is resolved here, and everything
1183
+ * else -- static methods, object-literal methods, a `this` the checker
1184
+ * cannot place at all -- falls through to the checker's own answer
1185
+ * unchanged.
1186
+ */
1187
+ // Memoized because it is a pure function of the node and this census's own
1188
+ // checker, and `known` -- which asks it for every `this` it meets -- runs
1189
+ // thousands of times per sweep. Each miss walks the AST to the enclosing
1190
+ // non-arrow function, which for a `this` deep inside a method body is the
1191
+ // whole chain of enclosing nodes, re-walked per mention.
1192
+ const concreteThisTypes = new WeakMap();
1193
+ const concreteThisTypeOf = (keyword) => {
1194
+ const known = concreteThisTypes.get(keyword);
1195
+ if (known !== undefined)
1196
+ return known;
1197
+ if (concreteThisTypes.has(keyword))
1198
+ return null;
1199
+ const answer = concreteThisTypeUncached(keyword);
1200
+ concreteThisTypes.set(keyword, answer);
1201
+ return answer;
1202
+ };
1203
+ const concreteThisTypeUncached = (keyword) => {
1204
+ const frame = ts.findAncestor(keyword, (node) => ts.isFunctionLike(node) && !ts.isArrowFunction(node));
1205
+ if (frame === undefined || !ts.isFunctionLike(frame))
1206
+ return null;
1207
+ if ((ts.getCombinedModifierFlags(frame) & ts.ModifierFlags.Static) !== 0)
1208
+ return null;
1209
+ const holder = frame.parent;
1210
+ if (!ts.isClassDeclaration(holder) && !ts.isClassExpression(holder))
1211
+ return null;
1212
+ if (!holder.name)
1213
+ return null;
1214
+ const symbol = checker.getSymbolAtLocation(holder.name);
1215
+ return symbol ? checker.getDeclaredTypeOfSymbol(symbol) : null;
1216
+ };
1217
+ /** `GEA_KNOWN_DEBUG=<identifier>` reports, for every mention of that name,
1218
+ * what the checker answers, whether the vacuous-evidence guard fires, and
1219
+ * what the upstream round already knew -- which is the one place a fact that
1220
+ * exists in the settled census but not in a proof shows itself. Read once:
1221
+ * `known` runs thousands of times per sweep. */
1222
+ const watchedBinding = process.env['GEA_KNOWN_DEBUG'];
1223
+ const createResolver = (lateAssignment) => {
1224
+ // Memoized per round: a binding learned this round changes what a later
1225
+ // question answers, so a memo that outlived the round would answer with the
1226
+ // previous round's smaller view.
1227
+ let memo = new Map();
1228
+ const resolving = new Set();
1229
+ /**
1230
+ * The type this node holds, following a bound parameter through the
1231
+ * expressions computed from it.
1232
+ *
1233
+ * Every step delegates to the checker: a member is `getTypeOfPropertyOfType`,
1234
+ * a call is the return type of a signature the checker resolved. The walk
1235
+ * bottoms out ONLY at a bound parameter -- a node whose chain does not reach
1236
+ * one answers `null` and keeps the checker's own answer -- which is what
1237
+ * keeps a genuinely dynamic value dynamic.
1238
+ */
1239
+ const resolve = (node) => {
1240
+ const cached = memo.get(node);
1241
+ if (cached !== undefined)
1242
+ return cached;
1243
+ if (resolving.has(node))
1244
+ return null;
1245
+ resolving.add(node);
1246
+ const answer = compute(node);
1247
+ resolving.delete(node);
1248
+ memo.set(node, answer);
1249
+ return answer;
1250
+ };
1251
+ /**
1252
+ * The checker's answer when it is a real one, so a resolved chain stops as
1253
+ * soon as a type is known -- or, when the checker has nothing, the
1254
+ * upstream census's answer for this exact node. `upstream` is a settled
1255
+ * prior round (or `emptyParameterBindingCensus`, which always answers
1256
+ * `null` and changes nothing): consulting it here, ahead of this
1257
+ * resolver's own machinery, is what lets a second round see a fact only
1258
+ * `return-bindings.ts`/`local-bindings.ts` derived -- without this
1259
+ * resolver having to reconstruct that fact itself.
1260
+ */
1261
+ const known = (node) => {
1262
+ if (watchedBinding !== undefined && ts.isIdentifier(node) && node.text === watchedBinding) {
1263
+ const held = checker.getTypeAtLocation(node);
1264
+ const file = node.getSourceFile();
1265
+ process.stderr.write(`[KNOWN] ${file.fileName.split('/').pop()}#${file.getLineAndCharacterOfPosition(node.getStart()).line + 1} ` +
1266
+ `checker=${checker.typeToString(held).slice(0, 30)} unusable=${isUnusableEvidence(held)} ` +
1267
+ `vacuous=${annotationStatesNothing(checker, node, held)} upstream=${(() => {
1268
+ const answer = upstream.typeAt(node);
1269
+ return answer ? checker.typeToString(answer).slice(0, 40) : 'null';
1270
+ })()}\n`);
1271
+ }
1272
+ const argument = implicitArgumentsReadTypeAt(checker, node, (owner) => upstream.implicitArgumentsTupleAt?.(owner) ?? null);
1273
+ if (argument)
1274
+ return argument;
1275
+ const type = (node.kind === ts.SyntaxKind.ThisKeyword ? concreteThisTypeOf(node) : null) ??
1276
+ objectAssignTargetType(checker, node) ??
1277
+ checker.getTypeAtLocation(node);
1278
+ // `annotationStatesNothing` beside `isUnusableEvidence`, both halves of
1279
+ // the one shared rule: a vacuous type (`Object`, `{}`, bare `object`)
1280
+ // is not merely non-evidence -- handed to a `widestOf` join it
1281
+ // DOMINATES, because every type is assignable to it, so one vacuous
1282
+ // call site out-votes every real one. The layout resolver and the two
1283
+ // write-set censuses already ask both halves; this asking one was
1284
+ // drift. See `field-bindings.ts`'s `known` for the measured case.
1285
+ if (isUnusableEvidence(type) || annotationStatesNothing(checker, node, type))
1286
+ return upstream.typeAt(node);
1287
+ // A bound parameter's DECLARED type can be one TypeScript widened from a
1288
+ // default value -- `constructor( parameters = {} )` declares `{}`, a type
1289
+ // with no members, so every `parameters.canvas` reading through it finds
1290
+ // nothing. When the checker is reporting that declared type UNCHANGED at
1291
+ // this site, the census knows better and should answer.
1292
+ //
1293
+ // The equality test is what keeps flow narrowing intact: a site where the
1294
+ // checker narrowed the value reports a DIFFERENT type than the
1295
+ // declaration, and there the checker is right and this defers to it. A
1296
+ // census that always won would silently discard every narrowing in the
1297
+ // program.
1298
+ if (ts.isIdentifier(node)) {
1299
+ const declaration = declarationOf(node);
1300
+ if (declaration && ts.isParameter(declaration) && bindings.has(declaration)) {
1301
+ if (checker.getTypeAtLocation(declaration) === type)
1302
+ return null;
1303
+ }
1304
+ // A name bound by a parameter's implied pattern is typed by the
1305
+ // checker from the pattern's SHAPE (`any`, `any[]` for a rest
1306
+ // element), which is the silhouette `impliedPatternParameterOf`
1307
+ // exists to see through; the pattern's own read is the answer.
1308
+ if (declaration && ts.isBindingElement(declaration) && impliedPatternElementRootOf(checker, declaration) !== null)
1309
+ return null;
1310
+ }
1311
+ return type;
1312
+ };
1313
+ const declarationOf = (node) => {
1314
+ const symbol = checker.getSymbolAtLocation(node);
1315
+ const declarations = symbol?.declarations;
1316
+ return declarations && declarations.length === 1 ? (declarations[0] ?? null) : null;
1317
+ };
1318
+ /**
1319
+ * The type of one member of a resolved receiver.
1320
+ *
1321
+ * `getPropertyOfType` answers with the symbol and `getTypeOfSymbolAtLocation`
1322
+ * types it at the site that reads it, which is the pair the checker exposes
1323
+ * for exactly this question -- the same answer it computed to check the
1324
+ * access, read back rather than recomputed.
1325
+ */
1326
+ /**
1327
+ * The expression a literal member was written with -- `{ color: cb }`, or
1328
+ * shorthand `{ cb }` -- or `null` for any other declaration form.
1329
+ * `field-bindings.ts` states the same shape for the same reason.
1330
+ */
1331
+ const literalMemberInitializerOf = (member) => {
1332
+ const declaration = member?.valueDeclaration;
1333
+ if (!declaration)
1334
+ return null;
1335
+ if (ts.isPropertyAssignment(declaration))
1336
+ return declaration.initializer;
1337
+ if (ts.isShorthandPropertyAssignment(declaration))
1338
+ return declaration.name;
1339
+ return null;
1340
+ };
1341
+ const resolvingLiteralMembers = new Set();
1342
+ /**
1343
+ * A member read, answered by the checker -- and, where the checker has no
1344
+ * answer, by what the literal actually PUT there.
1345
+ *
1346
+ * The checker widens an object literal's member to `any` as soon as its
1347
+ * initializer is untyped, and in JavaScript a factory's product is exactly
1348
+ * that: `function ColorBuffer() { return { setClear: function (...) {} } }`
1349
+ * called with `new` has no construct signature, so `cb` is `any` to the
1350
+ * checker and so is `{ color: cb }.color`. This census has ALREADY resolved
1351
+ * `cb` to the literal it holds -- that is what it exists to do -- and
1352
+ * throwing that away at the property assignment is what made three's
1353
+ * `state.buffers.color.setClear(...)` unattributable, leaving every method
1354
+ * on all three WebGLState buffer literals with no call sites and all their
1355
+ * parameters dynamic.
1356
+ *
1357
+ * Asked only where the checker's own answer is unusable, so nothing that
1358
+ * already had a type changes; the recursion guard is for a literal whose
1359
+ * member initializer reads back through the same member.
1360
+ */
1361
+ const propertyTypeOf = (receiver, name, at) => {
1362
+ const answer = memberTypeOf(checker, receiver, name, at, valueFlow);
1363
+ if (answer !== null && !isUnusableEvidence(answer))
1364
+ return answer;
1365
+ // A member only some classes of the receiver's closed family declare:
1366
+ // three's `material.glslVersion` through a `Material`. See
1367
+ // `flow/class-family-member-read.ts`.
1368
+ const family = answer === null ? classFamilyMemberReadTypeOf(checker, valueFlow, receiver, name, upstream) : null;
1369
+ if (family !== null)
1370
+ return family;
1371
+ const written = literalMemberInitializerOf(checker.getPropertyOfType(checker.getApparentType(receiver), name));
1372
+ if (written === null || resolvingLiteralMembers.has(written))
1373
+ return answer;
1374
+ resolvingLiteralMembers.add(written);
1375
+ try {
1376
+ const resolved = known(written) ?? resolve(written);
1377
+ return resolved !== null && !isUnusableEvidence(resolved) ? resolved : answer;
1378
+ }
1379
+ finally {
1380
+ resolvingLiteralMembers.delete(written);
1381
+ }
1382
+ };
1383
+ /**
1384
+
1385
+ * What a function actually returns, when its declared return type is `any`.
1386
+
1387
+ *
1388
+
1389
+ * Only the `return` statements of THIS function: a nested function's returns
1390
+
1391
+ * belong to it, and walking into one would attribute its answer to the wrong
1392
+
1393
+ * frame. Agreement is required for the same reason it is required of a
1394
+
1395
+ * parameter's call sites -- two different types are two answers, and picking
1396
+
1397
+ * one is guessing. A bare `return;` among them is a refusal rather than an
1398
+
1399
+ * agreement: it means the function also returns `undefined`, which the
1400
+
1401
+ * agreed type does not describe.
1402
+
1403
+ */
1404
+ const resolvedReturnTypeOf = (declaration) => {
1405
+ const body = 'body' in declaration ? declaration.body : undefined;
1406
+ if (!body)
1407
+ return null;
1408
+ if (!ts.isBlock(body))
1409
+ return known(body) ?? resolve(body);
1410
+ const returnedTypes = [];
1411
+ let sawReturn = false;
1412
+ let refused = false;
1413
+ const walk = (node) => {
1414
+ if (refused)
1415
+ return;
1416
+ if (ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node) || ts.isArrowFunction(node) || ts.isMethodDeclaration(node))
1417
+ return;
1418
+ if (ts.isReturnStatement(node)) {
1419
+ sawReturn = true;
1420
+ if (!node.expression) {
1421
+ refused = true;
1422
+ return;
1423
+ }
1424
+ const returned = known(node.expression) ?? resolve(node.expression);
1425
+ if (!returned || isUnusableEvidence(returned))
1426
+ refused = true;
1427
+ else
1428
+ returnedTypes.push(returned);
1429
+ return;
1430
+ }
1431
+ ts.forEachChild(node, walk);
1432
+ };
1433
+ ts.forEachChild(body, walk);
1434
+ return refused || !sawReturn ? null : widestOf(checker, returnedTypes);
1435
+ };
1436
+ /**
1437
+ * What a `var`/`let`/`const` cell holds, read from EVERY write to it.
1438
+ *
1439
+ * Its initializer is one write; so is every later assignment. `let _gl =
1440
+ * context; ... _gl = getContext( contextName, contextAttributes );` in
1441
+ * `WebGLRenderer` writes twice, and reading only the initializer would
1442
+ * describe a value the program does not have -- the second write is how a
1443
+ * context that arrived as `null` gets created, and the cell has to hold
1444
+ * both. The writes settling on one carrier is the answer (`widestOf`);
1445
+ * anything else is refused.
1446
+ *
1447
+ * Both the declaration node and every identifier that reads the binding
1448
+ * route through here, because they are one cell and one carrier. Answering
1449
+ * the declaration from its initializer while answering references from the
1450
+ * whole write set is two authorities on one storage location, which is how
1451
+ * a cell gets a non-optional carrier and a `null` written into it.
1452
+ *
1453
+ * `let extensions, capabilities, state, info;` filled later inside
1454
+ * `initGLContext()` is the same rule with no initializer among the writes,
1455
+ * and it is the hop every chain into three's sub-modules passes through --
1456
+ * which is exactly why only the propagating resolver may use it. See
1457
+ * `createResolver`.
1458
+ */
1459
+ const writeSetTypeOf = (declaration) => {
1460
+ if (declaration.type)
1461
+ return null;
1462
+ if (!declaration.initializer && !lateAssignment)
1463
+ return null;
1464
+ const edges = valueFlow.writesToDeclaration(declaration).filter((write) => write.slot === 'whole');
1465
+ if (edges.some((write) => write.value === null))
1466
+ return null;
1467
+ const writes = edges.flatMap((write) => (write.value === null ? [] : [write.value]));
1468
+ if (writes.length === 0)
1469
+ return null;
1470
+ const writtenTypes = [];
1471
+ for (const write of writes) {
1472
+ const written = known(write) ?? resolve(write);
1473
+ if (!written || isUnusableEvidence(written))
1474
+ return null;
1475
+ writtenTypes.push(written);
1476
+ }
1477
+ return widestOf(checker, writtenTypes);
1478
+ };
1479
+ /**
1480
+ * The value a whole binding pattern reads out of: a parameter's own bound
1481
+ * slot, an outer element's resolved type for a nested pattern, or a
1482
+ * declaration's initializer. The pattern node itself resolves to this so
1483
+ * a producer asking `typeAt(pattern)` for the base of its steps gets the
1484
+ * census's answer rather than the checker's implied-shape type.
1485
+ */
1486
+ const patternHoldersOf = (pattern) => {
1487
+ const root = pattern.parent;
1488
+ if (ts.isParameter(root)) {
1489
+ // A disagreement the census settled as SYNTHESIZED arms has no single
1490
+ // `ts.Type` (`unionArms`), so the pattern reads out of every arm and
1491
+ // joins what it finds -- `f([1, 2])` next to `f([])` is that shape.
1492
+ const bound = bindings.get(root);
1493
+ return bound ? [bound] : (unionArms.get(root) ?? null);
1494
+ }
1495
+ const holder = ts.isBindingElement(root)
1496
+ ? (known(root) ?? resolve(root))
1497
+ : ts.isVariableDeclaration(root) && root.initializer
1498
+ ? (exactEmptyObjectLiteralType(checker, root.initializer) ?? known(root.initializer) ?? resolve(root.initializer))
1499
+ : null;
1500
+ return holder ? [holder] : null;
1501
+ };
1502
+ const patternHolderOf = (pattern) => {
1503
+ const holders = patternHoldersOf(pattern);
1504
+ return holders && holders.length === 1 ? (holders[0] ?? null) : null;
1505
+ };
1506
+ /**
1507
+ * An object pattern's NUMERIC key over a plain array -- `[...{ 0: v, 3: y,
1508
+ * length: z }] = [7, 8, 9]` -- reads the array's element WITH `undefined`:
1509
+ * position 3 of a three-element array is `undefined` to the language, and
1510
+ * a read typed bare aborted at runtime ("read of array hole or out-of-range
1511
+ * index"). A tuple holder states its positions, so a stated one answers
1512
+ * bare and an unstated one `undefined`; every other key (`length`) is an
1513
+ * ordinary member read. Published as the element's READ (`patternReadTypes`)
1514
+ * so the layout's outranking rule can lift the checker's bare binding.
1515
+ */
1516
+ const arrayIndexPatternReadOf = (holder, key, element) => {
1517
+ if (!/^(0|[1-9][0-9]*)$/.test(key))
1518
+ return null;
1519
+ const nonNull = checker.getNonNullableType(holder);
1520
+ let read = null;
1521
+ if (checker.isTupleType(nonNull)) {
1522
+ const stated = checker.getTypeArguments(nonNull)[Number(key)];
1523
+ read = stated === undefined ? checker.getUndefinedType() : checker.getBaseTypeOfLiteralType(stated);
1524
+ }
1525
+ else {
1526
+ const indexed = checker.getIndexTypeOfType(nonNull, ts.IndexKind.Number);
1527
+ if (!indexed || isUnusableEvidence(indexed) || checker.getIndexTypeOfType(nonNull, ts.IndexKind.String))
1528
+ return null;
1529
+ read = checker.getNullableType(indexed, ts.TypeFlags.Undefined);
1530
+ }
1531
+ patternReadTypes.set(element, read);
1532
+ if (!element.initializer)
1533
+ return read;
1534
+ const fallback = defaultWriteOf(element.initializer);
1535
+ return fallback ? (joinOfWrites(checker, [withoutUndefinedMember(checker, read), fallback]) ?? read) : read;
1536
+ };
1537
+ /**
1538
+ * A key the holder's closed object type declares no member for reads
1539
+ * `undefined` -- ECMA-262 `KeyedBindingInitialization` reads through
1540
+ * `GetV` and finds nothing, so `const { fn = function () {} } = {}` binds
1541
+ * the default. The checker binds the name `any` in a JavaScript file (an
1542
+ * error in TypeScript), which was enough to box the default's own
1543
+ * function type and every `.name`/call on it. Only a single object type
1544
+ * with no member of that name and no index signature of either kind
1545
+ * answers; a union, a primitive, or an open dictionary keeps the ordinary
1546
+ * member read. `getPropertyOfType` sees the apparent members too, so a
1547
+ * `{ toString }` pattern over `{}` still reads `Object.prototype`'s.
1548
+ */
1549
+ const absentKeyPatternReadOf = (holder, key, element) => {
1550
+ const nonNull = checker.getNonNullableType(holder);
1551
+ if (isUnusableEvidence(nonNull) || (nonNull.flags & ts.TypeFlags.Object) === 0)
1552
+ return null;
1553
+ if (checker.getPropertyOfType(nonNull, key) ||
1554
+ checker.getIndexTypeOfType(nonNull, ts.IndexKind.String) ||
1555
+ checker.getIndexTypeOfType(nonNull, ts.IndexKind.Number))
1556
+ return null;
1557
+ const read = checker.getUndefinedType();
1558
+ patternReadTypes.set(element, read);
1559
+ if (!element.initializer)
1560
+ return read;
1561
+ return defaultWriteOf(element.initializer) ?? read;
1562
+ };
1563
+ /**
1564
+ * One array-pattern element's own type, read out of `holder` the way the
1565
+ * language reads it (ECMA-262 IteratorBindingInitialization): a tuple
1566
+ * source answers by position; any other array answers its element type
1567
+ * WITH `undefined`, because the pattern may run past the array's length
1568
+ * and the language binds the name to `undefined` there rather than
1569
+ * faulting. A default resolves that absence to the default's own type
1570
+ * (`joinOfWrites`, the same nullish-is-absence join a defaulted object
1571
+ * element uses in `local-bindings.ts`). A rest element takes the holder's
1572
+ * remaining elements, which for a plain array is the same array type.
1573
+ */
1574
+ const arrayPatternElementTypeOf = (holders, element, pattern) => {
1575
+ const position = pattern.elements.indexOf(element);
1576
+ // A parameter's implied pattern reads out of the ARRAY the value is
1577
+ // stored as (`impliedPatternElementOfArms`, the same answer the slot
1578
+ // takes), not out of the tuple one call site happened to write: the
1579
+ // position holds the stored element or nothing, whatever the arms said.
1580
+ if (ts.isParameter(pattern.parent) && impliedPatternParameterOf(checker, pattern.parent) !== null && !element.dotDotDotToken) {
1581
+ const stored = impliedPatternElementOfArms(checker, holders, pattern);
1582
+ if (stored && !isUnusableEvidence(stored)) {
1583
+ const own = impliedPatternPositionPresentEverywhere(checker, holders, position)
1584
+ ? stored
1585
+ : checker.getNullableType(stored, ts.TypeFlags.Undefined);
1586
+ patternReadTypes.set(element, own);
1587
+ if (!element.initializer)
1588
+ return own;
1589
+ // The NAME holds the read with its absence replaced by the default
1590
+ // (`bodyBindingOf`'s rule for a parameter, one level down): the
1591
+ // read is `own`, published above for the pattern step to test,
1592
+ // and only a default that itself evaluates to `undefined` can put
1593
+ // the absence back. `[[,] = g()]` binding `Generator | undefined`
1594
+ // sent the nested pattern reading an optional cursor.
1595
+ const fallback = defaultWriteOf(element.initializer);
1596
+ return fallback ? (joinOfWrites(checker, [withoutUndefinedMember(checker, own), fallback]) ?? own) : own;
1597
+ }
1598
+ }
1599
+ const ownOf = (holder) => {
1600
+ const nonNull = checker.getNonNullableType(holder);
1601
+ if (checker.isTupleType(nonNull)) {
1602
+ if (element.dotDotDotToken)
1603
+ return null;
1604
+ const stated = checker.getTypeArguments(nonNull)[position];
1605
+ return stated === undefined ? checker.getUndefinedType() : checker.getBaseTypeOfLiteralType(stated);
1606
+ }
1607
+ const indexed = checker.getIndexTypeOfType(nonNull, ts.IndexKind.Number);
1608
+ if (!indexed) {
1609
+ // A non-array iterable holder (a generator, a Set, a Map) has no
1610
+ // numeric index; a position reads what the holder YIELDS, with
1611
+ // `undefined` for a cursor exhausted before it -- the checker binds
1612
+ // the name bare, and `var [a, b] = g()` over a one-yield generator
1613
+ // then read `0` for `b`. A rest element would need an array of the
1614
+ // yield, which no checker API mints, so it stays unanswered.
1615
+ if (element.dotDotDotToken)
1616
+ return null;
1617
+ const yielded = iteratorYieldTypesOf(checker, nonNull, pattern);
1618
+ const only = yielded?.length === 1 ? yielded[0] : undefined;
1619
+ return only && !isUnusableEvidence(only) ? checker.getNullableType(only, ts.TypeFlags.Undefined) : null;
1620
+ }
1621
+ if (isUnusableEvidence(indexed))
1622
+ return null;
1623
+ if (element.dotDotDotToken)
1624
+ return nonNull;
1625
+ return checker.getNullableType(indexed, ts.TypeFlags.Undefined);
1626
+ };
1627
+ const owns = holders.map(ownOf);
1628
+ if (owns.some((type) => type === null))
1629
+ return null;
1630
+ // Every arm's position, joined: a position one arm states and another
1631
+ // runs past is `T | undefined`, which is what `joinOfWrites` makes of
1632
+ // `[T, undefined]` -- the same nullish-is-absence join a default uses.
1633
+ const own = owns.length === 1 ? owns[0] : joinOfWrites(checker, owns);
1634
+ if (!own)
1635
+ return null;
1636
+ patternReadTypes.set(element, own);
1637
+ if (!element.initializer)
1638
+ return own;
1639
+ const fallback = defaultWriteOf(element.initializer);
1640
+ return fallback ? (joinOfWrites(checker, [own, fallback]) ?? own) : own;
1641
+ };
1642
+ /** What a default initializer WRITES: a `void` call's value is `undefined`, the language's own answer for it. */
1643
+ const defaultWriteOf = (initializer) => {
1644
+ if ((checker.getTypeAtLocation(initializer).flags & ts.TypeFlags.Void) !== 0)
1645
+ return checker.getUndefinedType();
1646
+ return known(initializer) ?? resolve(initializer);
1647
+ };
1648
+ const compute = (node) => {
1649
+ if (ts.isParenthesizedExpression(node) || ts.isAsExpression(node) || ts.isNonNullExpression(node)) {
1650
+ return known(node.expression) ?? resolve(node.expression);
1651
+ }
1652
+ if (ts.isIdentifier(node)) {
1653
+ const declaration = declarationOf(node);
1654
+ if (!declaration)
1655
+ return null;
1656
+ if (ts.isParameter(declaration))
1657
+ return parameterTypeOf(declaration);
1658
+ // A binding holds what is written into it, and EVERY write counts. Its
1659
+ // initializer is one; so is every later assignment -- `let _gl = context;
1660
+ // ... _gl = getContext( contextName, contextAttributes );` in
1661
+ // `WebGLRenderer` writes twice, and reading only the initializer would
1662
+ // describe a value the program does not have. All the writes agreeing is
1663
+ // one answer; anything else is refused rather than merged, because the
1664
+ // union that would describe two is not a type this can build without
1665
+ // inventing one, and the honest answer to "which of these two" is neither.
1666
+ //
1667
+ // `let extensions, capabilities, state, info;` filled later inside
1668
+ // `initGLContext()` is the same rule with no initializer among the
1669
+ // writes, and it is the hop every chain into three's sub-modules passes
1670
+ // through -- which is exactly why only the propagating resolver may use
1671
+ // it. See `createResolver`.
1672
+ // A reference to a destructured name is a read of the SAME storage the
1673
+ // pattern bound, so it answers with the pattern's own answer. Without
1674
+ // this hop the chain stops one step short of everything it was built
1675
+ // for: `const { canvas, context } = parameters` binds both names, and
1676
+ // then `canvas.getContext( ... )` -- an ordinary reference, three lines
1677
+ // down -- resolves to nothing. A later assignment to the name is the
1678
+ // same disqualification it is for a `let`: the binding then holds
1679
+ // something the pattern's member type does not describe.
1680
+ if (ts.isBindingElement(declaration)) {
1681
+ const symbol = checker.getSymbolAtLocation(declaration.name);
1682
+ // The pattern's own binding and its own default (`[w = c()]`) are
1683
+ // recorded at the element's site; the pattern's answer already
1684
+ // joins them. Only a write from somewhere ELSE disqualifies.
1685
+ if (symbol && valueFlow.writesToSymbol(symbol).some((write) => write.slot === 'whole' && write.site !== declaration))
1686
+ return null;
1687
+ return resolve(declaration);
1688
+ }
1689
+ if (ts.isVariableDeclaration(declaration))
1690
+ return writeSetTypeOf(declaration);
1691
+ return null;
1692
+ }
1693
+ if (ts.isObjectBindingPattern(node) || ts.isArrayBindingPattern(node))
1694
+ return patternHolderOf(node);
1695
+ if (ts.isBindingElement(node)) {
1696
+ // `const { canvas, context, antialias } = parameters` binds three names to
1697
+ // three members of one value. The member is the answer, and the value is
1698
+ // whatever this resolver can make of the pattern's own root.
1699
+ const pattern = node.parent;
1700
+ if (ts.isObjectBindingPattern(pattern)) {
1701
+ const holder = patternHolderOf(pattern);
1702
+ const key = node.propertyName ?? node.name;
1703
+ if (!holder || !(ts.isIdentifier(key) || ts.isStringLiteral(key) || ts.isNumericLiteral(key)))
1704
+ return null;
1705
+ const indexedRead = arrayIndexPatternReadOf(holder, key.text, node);
1706
+ if (indexedRead)
1707
+ return indexedRead;
1708
+ const absentRead = absentKeyPatternReadOf(holder, key.text, node);
1709
+ if (absentRead)
1710
+ return absentRead;
1711
+ return propertyTypeOf(holder, key.text, node);
1712
+ }
1713
+ const holders = patternHoldersOf(pattern);
1714
+ return holders ? arrayPatternElementTypeOf(holders, node, pattern) : null;
1715
+ }
1716
+ if (ts.isPropertyAccessExpression(node)) {
1717
+ const receiver = known(node.expression) ?? resolve(node.expression);
1718
+ if (!receiver)
1719
+ return null;
1720
+ return propertyTypeOf(receiver, node.name.text, node);
1721
+ }
1722
+ if (ts.isElementAccessExpression(node) && node.argumentExpression) {
1723
+ const receiver = known(node.expression) ?? resolve(node.expression);
1724
+ if (!receiver)
1725
+ return null;
1726
+ // A literal key is a named member spelled with brackets; any other key
1727
+ // is answered by the receiver's index signature, and by nothing else.
1728
+ const name = literalMemberNameOf(node);
1729
+ if (name !== null)
1730
+ return propertyTypeOf(receiver, name, node);
1731
+ const key = known(node.argumentExpression) ?? resolve(node.argumentExpression);
1732
+ return key ? indexedTypeOf(checker, receiver, key, node, valueFlow, upstream) : null;
1733
+ }
1734
+ if (ts.isCallExpression(node) || ts.isNewExpression(node)) {
1735
+ const invariant = overloadInvariantReturnTypeAt(checker, node, (operand) => known(operand) ?? resolve(operand));
1736
+ // An OPEN invariant is not one: every overload agreeing on the same
1737
+ // unreduced type EXPRESSION says nothing about the type. Falls through
1738
+ // rather than returning null, so the ordinary path below still gets its
1739
+ // turn -- and refuses the same form for the same reason.
1740
+ if (invariant && !isUnreducedTypeForm(invariant))
1741
+ return invariant;
1742
+ const callee = known(node.expression) ?? resolve(node.expression);
1743
+ if (!callee)
1744
+ return null;
1745
+ // A JavaScript factory called with `new` that returns an object is typed
1746
+ // by what it returns, which is why the call signature is consulted for a
1747
+ // `new` whose callee declares no construct signature -- `new
1748
+ // WebGLExtensions( _gl )` is `function WebGLExtensions( gl ) { ...;
1749
+ // return { has, init, get }; }`, and the record it returns is the whole
1750
+ // of what the expression holds.
1751
+ const constructed = ts.isNewExpression(node) ? callee.getConstructSignatures() : [];
1752
+ const signatures = constructed.length > 0 ? constructed : callee.getCallSignatures();
1753
+ if (signatures.length !== 1)
1754
+ return null;
1755
+ const signature = signatures[0];
1756
+ const operands = ts.isCallExpression(node) ? invocationOperands.get(node) : undefined;
1757
+ if (ts.isCallExpression(node) && !operands)
1758
+ return null;
1759
+ const returned = explicitThisCallReturnType(signature, operands?.explicitThis ? (known(operands.callee) ?? resolve(operands.callee)) : null);
1760
+ // `void` and `never` are refused here for the reason `isUnusableEvidence`
1761
+ // states, and `any` falls through to the return-expression walk below
1762
+ // rather than being refused -- the three answers are not one answer.
1763
+ if ((returned.flags & (ts.TypeFlags.Void | ts.TypeFlags.Never)) !== 0)
1764
+ return null;
1765
+ // A GENERIC signature's declared return is an OPEN FORM, and reading it
1766
+ // off the signature publishes the type expression rather than the type.
1767
+ // `Reflect.get(pattern, 'route')` is the case: one call signature,
1768
+ // `P extends keyof T ? T[P] : any`, and nothing on this walk binds `T`
1769
+ // or `P` -- so the census answered a conditional that no later stage
1770
+ // can reduce, `structural.ts` refused it as "an anonymous conditional
1771
+ // type is still gated on a type parameter", and a program whose call
1772
+ // the CHECKER had already reduced to `any` lost its certificate.
1773
+ //
1774
+ // Refused rather than instantiated: instantiating is what the checker
1775
+ // did at the call site, and its answer is the one `layoutTypeAt` falls
1776
+ // back to the moment this census declines. Doing it a second time here
1777
+ // would be a second authority on the same reduction.
1778
+ //
1779
+ // Asked of the ANSWER, not of the signature. The signature reached here
1780
+ // came off a census-derived callee type, and its `getTypeParameters()`
1781
+ // is empty even where its return type is still open -- so gating on the
1782
+ // signature being generic left this exact case through.
1783
+ if (isUnreducedTypeForm(returned))
1784
+ return null;
1785
+ // A stated return type that says NOTHING falls through with `any`, for
1786
+ // the same reason and by the same rule. `function makesBag(): object {
1787
+ // return { a: 1, b: 2 } }` answered `object` here, and because this
1788
+ // census's answer is the FIRST half of the composed view
1789
+ // (`composeReturnBindings`), that shadowed the return census's own,
1790
+ // already-derived record for the same call -- two authorities on one
1791
+ // invocation, which `model/selected-signature.ts` catches fail-closed
1792
+ // and pays for by withholding the call AND every binding it feeds.
1793
+ if (!isAnyType(returned))
1794
+ return returned;
1795
+ // The return type was not written down either. A function's `return`
1796
+ // expressions are the same kind of evidence a call's arguments are,
1797
+ // and asking them is the same question one frame down: `getContext`
1798
+ // returns `canvas.getContext( ... )`, and once `canvas` is known so is
1799
+ // this.
1800
+ const declared = signature.declaration;
1801
+ return declared && ts.isFunctionLike(declared) ? resolvedReturnTypeOf(declared) : null;
1802
+ }
1803
+ if (ts.isVariableDeclaration(node))
1804
+ return writeSetTypeOf(node);
1805
+ if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.EqualsToken) {
1806
+ return known(node.right) ?? resolve(node.right);
1807
+ }
1808
+ // Last, and through the SHARED resolver rather than a local reading of
1809
+ // these node kinds. `return-bindings.ts` asks the identical question of
1810
+ // the identical expressions, and two censuses answering it two ways is
1811
+ // the defect class this compiler keeps rediscovering -- so the rule lives
1812
+ // in one module and both callers hand it their own operand resolver.
1813
+ // Deliberately after the assignment arm above: a `BinaryExpression` whose
1814
+ // operator is `=` is a write, answered by its right-hand side, and only
1815
+ // the operators that COMPUTE a value reach here.
1816
+ if (ts.isConditionalExpression(node) || ts.isBinaryExpression(node) || ts.isTemplateExpression(node)) {
1817
+ return derivedExpressionType(checker, node, (operand) => known(operand) ?? resolve(operand));
1818
+ }
1819
+ return null;
1820
+ };
1821
+ return {
1822
+ resolve,
1823
+ known,
1824
+ reset: () => {
1825
+ memo = new Map();
1826
+ }
1827
+ };
1828
+ };
1829
+ const propagating = createResolver(true);
1830
+ // One pair of key functions per index: the member-closure memo keys on
1831
+ // their identity, and a closure minted per proof launch defeats it.
1832
+ const propagatingTypeAt = (expression) => propagating.known(expression) ?? propagating.resolve(expression);
1833
+ const implicitArgumentsUsesAt = (owner) => index.implicitArgumentsUses.get(owner);
1834
+ // `hasClosedMemberCallableUses`'s memo is keyed in part on THIS function's
1835
+ // identity, which is exactly right for a single whole-program authority --
1836
+ // but `bindingSweep` below re-derives `propagatingTypeAt`'s answers every
1837
+ // round from a GROWING `bindings` map behind the SAME stable reference, so
1838
+ // a member whose closure needs a later round's binding got refused once
1839
+ // and served that stale refusal forever after, with no further proof
1840
+ // activity to show for it. Reassigned once per round (not per proof
1841
+ // launch, which would defeat in-round reuse the comment above protects) so
1842
+ // each round's improved evidence gets its own cache generation.
1843
+ let memberClosureReceiverTypeAt = propagatingTypeAt;
1844
+ const publishing = createResolver(false);
1845
+ /**
1846
+ * Whether `call` is a recursive call: attributed to `declaration` (true of
1847
+ * every call in `callsByDeclaration.get(declaration)` by construction) AND
1848
+ * lexically inside `declaration`'s OWN body -- so this is `declaration`
1849
+ * calling itself, directly or through a different receiver of the same
1850
+ * method (`children[i].traverse( callback )` inside `Object3D.traverse`'s
1851
+ * own body is the same declaration, called again, from within itself).
1852
+ *
1853
+ * Direct self-reference only, deliberately: mutual recursion (`a` calling
1854
+ * `b` calling `a`) needs walking the call graph rather than one
1855
+ * containment check, and is worth the extra machinery only once this
1856
+ * narrower, measured, cheaply-checked case has proven the shape is worth
1857
+ * having at all.
1858
+ */
1859
+ const isRecursiveCallWithin = (call, declaration) => {
1860
+ const body = 'body' in declaration ? declaration.body : undefined;
1861
+ if (!body)
1862
+ return false;
1863
+ for (let current = call.parent; current; current = current.parent) {
1864
+ if (current === body)
1865
+ return true;
1866
+ }
1867
+ return false;
1868
+ };
1869
+ /** Whether `expression` (parens aside) is a bare reference to exactly `parameter`'s own declaration. */
1870
+ const referencesParameter = (expression, parameter) => {
1871
+ let current = expression;
1872
+ while (ts.isParenthesizedExpression(current))
1873
+ current = current.expression;
1874
+ if (!ts.isIdentifier(current))
1875
+ return false;
1876
+ const symbol = checker.getSymbolAtLocation(current);
1877
+ const declarations = symbol?.declarations;
1878
+ return declarations !== undefined && declarations.length === 1 && declarations[0] === parameter;
1879
+ };
1880
+ /**
1881
+ * Whether a recursive argument's type depends on `parameter`, through only
1882
+ * reference-preserving reads this census can replay after the parameter has
1883
+ * a provisional binding. Unlike a bare self-reference, a member/element
1884
+ * read is not automatically the same type as its receiver: it may name a
1885
+ * different field entirely. This predicate therefore only chooses what to
1886
+ * DEFER; `validateDeferredRecursiveArguments` below re-resolves the full
1887
+ * expression and proves its resulting type fits before publication.
1888
+ */
1889
+ const isDerivedFromParameter = (expression, parameter) => {
1890
+ const seen = new Set();
1891
+ const visit = (node) => {
1892
+ let current = node;
1893
+ while (ts.isParenthesizedExpression(current) ||
1894
+ ts.isAsExpression(current) ||
1895
+ ts.isTypeAssertionExpression(current) ||
1896
+ ts.isNonNullExpression(current) ||
1897
+ ts.isSatisfiesExpression(current))
1898
+ current = current.expression;
1899
+ if (seen.has(current))
1900
+ return false;
1901
+ seen.add(current);
1902
+ if (referencesParameter(current, parameter))
1903
+ return true;
1904
+ if (ts.isPropertyAccessExpression(current) || ts.isElementAccessExpression(current))
1905
+ return visit(current.expression);
1906
+ if (!ts.isIdentifier(current))
1907
+ return false;
1908
+ const declarations = checker.getSymbolAtLocation(current)?.declarations;
1909
+ if (!declarations || declarations.length !== 1)
1910
+ return false;
1911
+ const declaration = declarations[0];
1912
+ if (!declaration || (!ts.isVariableDeclaration(declaration) && !ts.isBindingElement(declaration)))
1913
+ return false;
1914
+ return valueFlow
1915
+ .writesToDeclaration(declaration)
1916
+ .some((write) => write.slot === 'whole' && write.value !== null && visit(write.value));
1917
+ };
1918
+ return visit(expression) && !referencesParameter(expression, parameter);
1919
+ };
1920
+ /**
1921
+ * One pass over every call attributed to `declaration`, resolving the
1922
+ * argument at `index`. `excludeBackEdges` chooses which of the two
1923
+ * readings `agreedArgumentType` (below) is asking for: skipping a back
1924
+ * edge -- see the module comment above `isRecursiveCallWithin` -- is the
1925
+ * sound, information-ADDING reading, and resolving it like any other
1926
+ * argument is the fallback for when a back edge is all the evidence
1927
+ * there is. `sawBackEdge` tells the caller whether skipping happened at
1928
+ * all, so it can tell "every call was a back edge" (this comes back with
1929
+ * an empty `passed` AND `sawBackEdge`) apart from "there were simply no
1930
+ * calls" (empty `passed`, no back edge) without re-walking `calls`.
1931
+ * `skipSilentSites` is the second such choice; see `EVIDENCE EXHAUSTED`.
1932
+ */
1933
+ const argumentsByParameter = new Map();
1934
+ /**
1935
+ * A silent site is one the census has no evidence for YET. A site whose
1936
+ * argument is a runtime-keyed read (`obj[name]`) or an ambient member the
1937
+ * library declares `any` (`desc.value` on lib's PropertyDescriptor) has no
1938
+ * evidence to come: the value is dynamic in every authority. Skipping it
1939
+ * and binding the parameter from the other sites would unbox the value at
1940
+ * this call -- test262's `isSameValue(desc.value, obj[name])` bound `b` to
1941
+ * `string` from `newValue` and aborted on the first numeric `length`.
1942
+ */
1943
+ const isSuppliedDynamic = (argument) => {
1944
+ let expression = argument;
1945
+ while (ts.isParenthesizedExpression(expression))
1946
+ expression = expression.expression;
1947
+ const type = checker.getTypeAtLocation(expression);
1948
+ if ((type.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) === 0)
1949
+ return false;
1950
+ if (ts.isElementAccessExpression(expression)) {
1951
+ return !ts.isStringLiteralLike(expression.argumentExpression) && !ts.isNumericLiteral(expression.argumentExpression);
1952
+ }
1953
+ if (ts.isPropertyAccessExpression(expression)) {
1954
+ const declaration = checker.getSymbolAtLocation(expression.name)?.valueDeclaration;
1955
+ return declaration !== undefined && declaration.getSourceFile().isDeclarationFile;
1956
+ }
1957
+ return false;
1958
+ };
1959
+ const collectPassedArguments = (calls, declaration, parameter, index, excludeBackEdges, skipSilentSites) => {
1960
+ const passed = [];
1961
+ const deferredRecursiveArguments = [];
1962
+ let sawBackEdge = false;
1963
+ let sawOmitted = false;
1964
+ let sawSilentSite = false;
1965
+ const record = (argument) => {
1966
+ const known = argumentsByParameter.get(parameter);
1967
+ if (known === undefined)
1968
+ argumentsByParameter.set(parameter, new Set([argument]));
1969
+ else
1970
+ known.add(argument);
1971
+ };
1972
+ for (const call of calls) {
1973
+ const effectiveArguments = invocationOperands.get(call).args;
1974
+ // `describe( ...args )` where `args` is a rest parameter DECLARED as a
1975
+ // closed tuple hands this position exactly the tuple's element there.
1976
+ // `producers/tuple-spread.ts` expands that spread into constant-index
1977
+ // reads typed by the same declaration; read the same fact here, or the
1978
+ // operands say `number` while this formal's storage is refused
1979
+ // `argument-unresolved` on the spread node and boxed -- which is how
1980
+ // `x * y` in a forwarding callee became a dynamic multiplication with
1981
+ // no C++ spelling (test/runtime/tuple-typed-rest-spread.runtime.js).
1982
+ // A position past the tuple's arity is a genuinely omitted argument,
1983
+ // and falls through to the omission rule below like any other.
1984
+ const forwarded = declaredTupleSpreadPositionAt(checker, effectiveArguments, index);
1985
+ if (forwarded !== null) {
1986
+ passed.push(forwarded.isLiteral() ? checker.getBaseTypeOfLiteralType(forwarded) : forwarded);
1987
+ continue;
1988
+ }
1989
+ const argument = effectiveArguments[index];
1990
+ // The checker also authenticates JSDoc's `[name]` as optional. Looking
1991
+ // only for a question token rejected legal JS constructor omissions and
1992
+ // discarded all their supplied configuration evidence. Absence is a
1993
+ // real incoming value, including when every caller omits the argument;
1994
+ // only a default replaces it before the body observes the binding.
1995
+ if (!argument && checker.isOptionalParameter(parameter)) {
1996
+ sawOmitted = true;
1997
+ if (parameter.initializer === undefined)
1998
+ passed.push(checker.getUndefinedType());
1999
+ continue;
2000
+ }
2001
+ if (!argument)
2002
+ return { refused: 'call-passes-no-argument' };
2003
+ // A BACK EDGE, not a second opinion. `projectObject( children[ i ],
2004
+ // camera, groupOrder, sortObjects )`, called from inside `projectObject`
2005
+ // itself, hands `groupOrder` its OWN value right back unchanged --
2006
+ // carrying no information about what the parameter holds until the
2007
+ // parameter is already bound. Joining it as if it were a disagreeing
2008
+ // call site is a category error: it is the recursion's own back edge.
2009
+ //
2010
+ // Excluding it is sound because it is VERIFIED, not assumed: the
2011
+ // structural test below (`referencesParameter`) is the same test that
2012
+ // finds it, and it proves the excluded argument literally IS
2013
+ // `parameter` -- so whatever `parameter` ends up bound to from the
2014
+ // OTHER call sites, this call site passes exactly that value BY
2015
+ // CONSTRUCTION. There is no type this argument could independently
2016
+ // hold that would disagree; a bare re-read of the same storage cannot
2017
+ // diverge from what that storage is bound to. That is a stronger
2018
+ // guarantee than re-resolving the argument after binding would give,
2019
+ // and it is available now, in the same round, without reopening the
2020
+ // fixpoint.
2021
+ const recursiveWithin = isRecursiveCallWithin(call, declaration);
2022
+ const isIdentityBackEdge = recursiveWithin && referencesParameter(argument, parameter);
2023
+ const isDerivedBackEdge = recursiveWithin && !isIdentityBackEdge && isDerivedFromParameter(argument, parameter);
2024
+ const isBackEdge = isIdentityBackEdge || isDerivedBackEdge;
2025
+ if (isBackEdge)
2026
+ sawBackEdge = true;
2027
+ if (isDerivedBackEdge)
2028
+ deferredRecursiveArguments.push(argument);
2029
+ if (excludeBackEdges && isBackEdge)
2030
+ continue;
2031
+ const resolved = propagating.known(argument) ?? propagating.resolve(argument);
2032
+ if (!resolved || isUnusableEvidence(resolved)) {
2033
+ // A default is not an annotation. If this read still has the checker's
2034
+ // dynamic type, it is a possible supplied value, not an omitted call.
2035
+ // Publish that actual type beside the initializer so falling back to
2036
+ // the checker's default-only parameter type cannot erase the input.
2037
+ const supplied = checker.getTypeAtLocation(argument);
2038
+ if (parameter.initializer && (supplied.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) !== 0) {
2039
+ passed.push(supplied);
2040
+ record(argument);
2041
+ continue;
2042
+ }
2043
+ if (skipSilentSites && !resolved && isSuppliedDynamic(argument)) {
2044
+ passed.push(supplied);
2045
+ record(argument);
2046
+ continue;
2047
+ }
2048
+ // An explicit unresolved argument is not an omitted argument. A
2049
+ // default describes only omission/undefined, so it cannot prove a
2050
+ // carrier for an unknown supplied value. Likewise void/never is a
2051
+ // real refusal, never evidence that the call did not happen.
2052
+ if (resolved || !skipSilentSites || parameter.initializer !== undefined) {
2053
+ return { refused: resolved ? 'argument-states-no-storage' : 'argument-unresolved' };
2054
+ }
2055
+ sawSilentSite = true;
2056
+ continue;
2057
+ }
2058
+ // `f(5)` does not mean the parameter holds only `5`. A literal argument's
2059
+ // type is a fact about the call, not about the storage it lands in, and a
2060
+ // second call site passing `6` would then read as a disagreement.
2061
+ passed.push(resolved.isLiteral() ? checker.getBaseTypeOfLiteralType(resolved) : resolved);
2062
+ record(argument);
2063
+ }
2064
+ return { passed, sawBackEdge, sawOmitted, sawSilentSite, deferredRecursiveArguments };
2065
+ };
2066
+ /** The type every call site passes at this position, or the reason there is no single one. */
2067
+ const agreedArgumentType = (declaration, parameter, parameterIndex, skipSilentSites) => {
2068
+ const calls = callsByDeclaration.get(declaration) ?? [];
2069
+ const contracts = contractsFor(declaration) ?? [];
2070
+ const contractTypes = [];
2071
+ for (const contract of contracts) {
2072
+ const type = callbackContractParameterType(checker, contract, parameterIndex);
2073
+ if (!type)
2074
+ return { refused: 'callback-contract-has-no-parameter' };
2075
+ contractTypes.push(type);
2076
+ }
2077
+ if (calls.length === 0 && contractTypes.length === 0)
2078
+ return { refused: 'no-call-site' };
2079
+ // A typed boundary must not turn a partially observed direct caller set
2080
+ // into a closed one. Unresolved direct inputs remain a refusal here.
2081
+ const allowSilentDirectSites = skipSilentSites && contracts.length === 0;
2082
+ const excluding = collectPassedArguments(calls, declaration, parameter, parameterIndex, true, allowSilentDirectSites);
2083
+ if ('refused' in excluding)
2084
+ return excluding;
2085
+ // A back edge is worth excluding only where doing so buys something:
2086
+ // real, independent evidence survives once it is set aside. Where the
2087
+ // back edge IS the only evidence -- `excluding.passed` comes back empty
2088
+ // -- there is nothing left to improve on, and refusing here would make
2089
+ // a parameter the OLD, pre-exclusion join could still answer WORSE than
2090
+ // before this exclusion existed: measured on the three.js app, paying the
2091
+ // exclusion unconditionally cost +6002 boxed carriers (+21%) for +14
2092
+ // resolved rows elsewhere, because most exclusions landed exactly here,
2093
+ // on parameters recursion-only in this program. Fall back to the
2094
+ // previous reading instead: join every call site, back edge included.
2095
+ // The same soundness argument above still covers it -- a bare re-read
2096
+ // of the parameter's own storage cannot disagree with whatever that
2097
+ // storage is bound to -- so including it here adds no unsound
2098
+ // information; it just declines to improve on the declaration the way
2099
+ // excluding it would have.
2100
+ const resolution = excluding.passed.length > 0 || !excluding.sawBackEdge
2101
+ ? excluding
2102
+ : collectPassedArguments(calls, declaration, parameter, parameterIndex, false, allowSilentDirectSites);
2103
+ if ('refused' in resolution)
2104
+ return resolution;
2105
+ // Reachable for a second reason once silent sites are dropped: every site
2106
+ // was silent -- no evidence at all, named for what actually happened.
2107
+ // Named apart from the per-site refusal above for the same reason: this is
2108
+ // "every site was silent", the relaxed phase's own exhaustion, not one
2109
+ // site handing over an unusable type.
2110
+ // A call site that leaves a defaulted parameter out is a WRITE of the
2111
+ // initializer: it runs at that call, so its type joins the cell's writes
2112
+ // exactly as a passed argument would. `static #m([x] = [1])` reached only
2113
+ // as `C.method()` is the all-silent shape (refusing it left the pattern
2114
+ // reading a dynamic array); `f([3])` beside `f()` is the mixed one, where
2115
+ // dropping `[1]` from the join had the pattern read a position the
2116
+ // default never states.
2117
+ const defaulted = (resolution.passed.length === 0 || resolution.sawOmitted) && parameter.initializer
2118
+ ? (propagating.known(parameter.initializer) ?? propagating.resolve(parameter.initializer))
2119
+ : null;
2120
+ // An evaluated `{}` default is the exact empty holder
2121
+ // (`exactEmptyObjectLiteralType`), not the vacuous annotation
2122
+ // `isUnusableEvidence` rightly drops: `function f({} = {})` reached only
2123
+ // as `f()` bound the parameter to `undefined` alone once its one real
2124
+ // write was filtered out. Taken only when no call site supplies a shape
2125
+ // of its own -- beside one, the join would let the empty literal (which
2126
+ // every object is assignable to) swallow the supplied shape, and the
2127
+ // pattern would read every key as absent.
2128
+ const emptyDefault = (resolution.passed.length === 0 || resolution.sawOmitted) &&
2129
+ parameter.initializer &&
2130
+ resolution.passed.every((type) => isNullishType(type))
2131
+ ? exactEmptyObjectLiteralType(checker, parameter.initializer)
2132
+ : null;
2133
+ const directPassed = emptyDefault !== null
2134
+ ? [...resolution.passed, emptyDefault]
2135
+ : defaulted && !isUnusableEvidence(defaulted)
2136
+ ? [...resolution.passed, defaulted]
2137
+ : resolution.passed;
2138
+ // Direct callers remain evidence even beside a typed higher-order slot.
2139
+ // In particular, an any input absorbs the typed contract rather than
2140
+ // letting the convenient boundary erase a real caller.
2141
+ // An assignment in the body writes this same cell, so its value joins the
2142
+ // incoming arguments before agreement is judged -- see the reassignment
2143
+ // note on `notReassigned`. An operator-typed write (`r *= a`) is read off
2144
+ // the assignment expression itself, where the operator states the result;
2145
+ // every other write is resolved like any other value expression.
2146
+ const parameterSymbol = ts.isIdentifier(parameter.name) ? checker.getSymbolAtLocation(parameter.name) : undefined;
2147
+ const writes = (parameterSymbol && assignedEvidence.get(parameterSymbol)) || [];
2148
+ const writtenTypes = writes.map((write) => write.operatorTyped
2149
+ ? checker.getTypeAtLocation(write.expression)
2150
+ : (propagating.known(write.expression) ?? propagating.resolve(write.expression)));
2151
+ // A complete numeric incoming frame can seed a numeric storage invariant.
2152
+ // Test EVERY write under that hypothesis before publishing it. In
2153
+ // particular, += is operand-sensitive: its checker answer stays any for an
2154
+ // unannotated self-read, although a numeric input and numeric RHS preserve
2155
+ // number. A string/opaque write, omitted unknown default or incomplete
2156
+ // caller must never borrow this seed to hide another possible value.
2157
+ const numeric = (type) => type !== null && type !== undefined && (type.flags & ts.TypeFlags.NumberLike) !== 0;
2158
+ const incoming = [...directPassed, ...contractTypes];
2159
+ const numericSeed = incoming.length > 0 &&
2160
+ incoming.every(numeric) &&
2161
+ !resolution.sawSilentSite &&
2162
+ !resolution.sawBackEdge &&
2163
+ (index.implicitArgumentsUses.get(declaration)?.length ?? 0) === 0 &&
2164
+ resolution.deferredRecursiveArguments.length === 0 &&
2165
+ (!resolution.sawOmitted || numeric(defaulted));
2166
+ let invariantTypes = null;
2167
+ if (numericSeed && writtenTypes.some((type) => !type || isUnusableEvidence(type))) {
2168
+ const tentative = writes.map((write, position) => {
2169
+ const expression = write.expression;
2170
+ if (!write.operatorTyped || !ts.isBinaryExpression(expression) || expression.operatorToken.kind !== ts.SyntaxKind.PlusEqualsToken)
2171
+ return writtenTypes[position];
2172
+ return derivedExpressionType(checker, expression, (operand) => ts.isIdentifier(operand) && checker.getSymbolAtLocation(operand) === parameterSymbol
2173
+ ? checker.getNumberType()
2174
+ : (propagating.known(operand) ?? propagating.resolve(operand)));
2175
+ });
2176
+ if (tentative.every(numeric))
2177
+ invariantTypes = tentative;
2178
+ }
2179
+ const assignedTypes = [];
2180
+ for (const written of invariantTypes ?? writtenTypes) {
2181
+ if (!written || isUnusableEvidence(written))
2182
+ return { refused: 'parameter-reassigned' };
2183
+ assignedTypes.push(written);
2184
+ }
2185
+ const passed = [...directPassed, ...contractTypes, ...assignedTypes];
2186
+ if (passed.length === 0)
2187
+ return { refused: skipSilentSites ? 'every-call-site-silent' : 'no-call-site' };
2188
+ // Omission is a real write, but cannot seed a concrete carrier while
2189
+ // supplied arguments remain unresolved. Otherwise the relaxed sweep
2190
+ // seals an optional forwarding method to Undefined before its callers
2191
+ // settle, then inserts failing unboxes for their actual objects.
2192
+ if (resolution.sawSilentSite && passed.every(isNullishType))
2193
+ return { refused: 'nullish-only-partial-evidence' };
2194
+ // A supplied dynamic value beside the default (`retain(); retain(JSON.
2195
+ // parse('{}'))`, `collectPassedArguments`'s own `supplied` arm) makes the
2196
+ // cell dynamic outright: `any` absorbs every other write, and asking
2197
+ // `joinOfWrites` to find a widest member among `[any, undefined]` only
2198
+ // refuses the site as a disagreement, erasing the input the arm kept.
2199
+ const dynamic = passed.find((type) => (type.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) !== 0);
2200
+ if (dynamic)
2201
+ return { type: dynamic, sawSilentSite: resolution.sawSilentSite, deferredRecursiveArguments: resolution.deferredRecursiveArguments };
2202
+ const joined = joinOfWrites(checker, passed); // same write-set join a cell's writes get
2203
+ if (joined)
2204
+ return { type: joined, sawSilentSite: resolution.sawSilentSite, deferredRecursiveArguments: resolution.deferredRecursiveArguments };
2205
+ // No single covering type -- is the disagreement itself sound? See `disjointUnionMembersOf`.
2206
+ const arms = disjointUnionMembersOf(checker, passed);
2207
+ return arms
2208
+ ? { unionArms: arms, sawSilentSite: resolution.sawSilentSite, deferredRecursiveArguments: resolution.deferredRecursiveArguments }
2209
+ : { refused: 'call-sites-disagree' };
2210
+ };
2211
+ // A fixpoint, because an argument can itself be an unannotated parameter one
2212
+ // frame up: `WebGLRenderer`'s own `context` is bound from the application
2213
+ // before `WebGLTextures`'s `_gl` can be bound from `WebGLRenderer`. Rounds
2214
+ // stop when a pass adds nothing, which terminates because a binding is only
2215
+ // ever added and there are finitely many parameters.
2216
+ /**
2217
+ * Attribute every call to the declaration it reaches, using this round's
2218
+ * bindings where the checker had no answer.
2219
+ *
2220
+ * `getResolvedSignature` gives up on `extensions.has( ... )` while
2221
+ * `extensions` is `any`, and never revisits it -- so the functions three's
2222
+ * factories return as members of a record have, from the checker's view, no
2223
+ * callers at all. They have exactly one each, and it becomes visible the
2224
+ * moment the record has a type. That is why attribution belongs INSIDE the
2225
+ * fixpoint: a round that binds `extensions` is what lets the next round see
2226
+ * who calls its members.
2227
+ */
2228
+ /** Records `call` as a site of `declaration`, once -- the same call can arrive from two different attribution passes below and must not double-count. */
2229
+ const pushCall = (declaration, call) => {
2230
+ if (isRealCallableDeclaration(declaration) &&
2231
+ !declaration.getSourceFile().isDeclarationFile &&
2232
+ 'body' in declaration &&
2233
+ declaration.body) {
2234
+ const targets = callTargets.get(call);
2235
+ if (!targets)
2236
+ callTargets.set(call, [declaration]);
2237
+ else if (!targets.includes(declaration))
2238
+ targets.push(declaration);
2239
+ }
2240
+ const existing = callsByDeclaration.get(declaration);
2241
+ if (existing) {
2242
+ if (!existing.includes(call))
2243
+ existing.push(call);
2244
+ }
2245
+ else
2246
+ callsByDeclaration.set(declaration, [call]);
2247
+ };
2248
+ /**
2249
+ * The selector declarations that could have produced the value now held by
2250
+ * `identifier`'s own storage -- `const setter = getSingularSetter(type);`
2251
+ * -- so that a later `setter( gl, v )` can be attributed to whatever that
2252
+ * selector returns, the same way `getSingularSetter(type)( gl, v )` (no
2253
+ * intervening variable) already is.
2254
+ *
2255
+ * Every WRITE to the identifier's binding is considered, same as
2256
+ * `writeSetTypeOf` considers every write to a cell: a write that is not
2257
+ * itself a call, or a call the checker did not attribute to a known
2258
+ * selector, simply contributes nothing here -- it is not a disagreement,
2259
+ * because this is gathering CALL-SITE evidence for whichever function
2260
+ * actually runs, not a claim about every value the variable could ever
2261
+ * hold. A write from an unrelated source and a write from a selector can
2262
+ * coexist on the same variable; the call site's arguments are the same
2263
+ * fixed expressions in the source regardless of which one is live, so
2264
+ * crediting the selector's returned functions with this call's evidence is
2265
+ * sound even when the other write cannot be explained.
2266
+ */
2267
+ const selectorsFeedingVariable = (identifier) => {
2268
+ const symbol = checker.getSymbolAtLocation(identifier);
2269
+ const declarations = symbol?.declarations;
2270
+ const declaration = declarations && declarations.length === 1 ? declarations[0] : undefined;
2271
+ if (!declaration || !ts.isVariableDeclaration(declaration))
2272
+ return EMPTY_DECLARATIONS;
2273
+ const writes = valueFlow
2274
+ .writesToDeclaration(declaration)
2275
+ .flatMap((write) => (write.slot === 'whole' && write.value !== null ? [write.value] : []));
2276
+ let result = null;
2277
+ for (const write of writes) {
2278
+ if (!ts.isCallExpression(write))
2279
+ continue;
2280
+ const selector = checkerAttribution.get(write);
2281
+ const returned = selector && aliasEvidence.returnedFrom.get(selector);
2282
+ if (!returned)
2283
+ continue;
2284
+ if (!result)
2285
+ result = new Set();
2286
+ for (const declaration of returned)
2287
+ result.add(declaration);
2288
+ }
2289
+ return result ?? EMPTY_DECLARATIONS;
2290
+ };
2291
+ /**
2292
+ * Every declaration this ALIAS pass attributes `call` to, beyond whatever
2293
+ * the checker or the propagating resolver already found -- see
2294
+ * `AliasEvidence`. Both shapes are real, symbol-anchored evidence, not a
2295
+ * guess: a member call matches only when the checker resolves the SAME
2296
+ * member symbol something was published under, and a selector-result call
2297
+ * matches only when the checker (not this census) already attributed the
2298
+ * inner call producing that result. A dynamic receiver or an unresolved
2299
+ * intermediate resolves to no symbol at all, so neither branch fires and
2300
+ * the ordinary refusal stands, exactly as it did before this pass existed.
2301
+ */
2302
+ // Built on first use rather than up front: `closedArrayCalleeAuthorityOf`
2303
+ // composes three collection/protocol queries, and the vast majority of
2304
+ // programs never reach the element-callee branch that needs it at all.
2305
+ let heldArrayCalleeAuthority = null;
2306
+ const arrayCalleeAuthority = () => (heldArrayCalleeAuthority ??= closedArrayCalleeAuthorityOf(checker, valueFlow, propagatingTypeAt, implicitArgumentsUsesAt));
2307
+ const aliasDeclarationsFor = (call) => {
2308
+ let result = null;
2309
+ const add = (declarations) => {
2310
+ if (!declarations || declarations.size === 0)
2311
+ return;
2312
+ if (!result)
2313
+ result = new Set();
2314
+ for (const declaration of declarations)
2315
+ result.add(declaration);
2316
+ };
2317
+ const heldOperands = invocationOperands.get(call);
2318
+ const heldCallee = heldOperands.callee;
2319
+ // Once a `.call`/`.apply` reading is settled -- statically, by
2320
+ // `unwrapExplicitThisCall`, or by THIS round's own closed-array proof
2321
+ // below -- it must stay settled every later round. `heldOperands` already
2322
+ // carries the readback of whichever `censusExplicitThisAt` answer built
2323
+ // THIS round's flow index, but `aliasDeclarationsFor` only recognizes the
2324
+ // pending (still-`.call`-wrapped) SHAPE further down, not an already-
2325
+ // resolved one (`heldCallee` is `array[ i ]` itself by then, no `.call`
2326
+ // property access left to match) -- so without this, round N proves the
2327
+ // reading, round N+1's index carries it, round N+1's OWN alias pass finds
2328
+ // no pending shape left to re-derive it from, publishes no
2329
+ // `explicitThisAt` answer for this call, and round N+2 reverts to
2330
+ // unresolved. Republishing the settled reading here breaks that
2331
+ // oscillation.
2332
+ if (heldOperands.explicitThis)
2333
+ pendingExplicitThisReadings.set(call, { callee: heldOperands.callee, receiver: heldOperands.receiver, args: heldOperands.args });
2334
+ if (ts.isPropertyAccessExpression(heldCallee) || ts.isElementAccessExpression(heldCallee)) {
2335
+ const key = ts.isPropertyAccessExpression(heldCallee) ? heldCallee.name.text : literalMemberNameOf(heldCallee);
2336
+ const receiver = propagating.known(heldCallee.expression) ?? propagating.resolve(heldCallee.expression);
2337
+ const memberSymbol = checker.getSymbolAtLocation(ts.isPropertyAccessExpression(heldCallee) ? heldCallee.name : heldCallee) ??
2338
+ (receiver && key !== null ? checker.getPropertyOfType(checker.getApparentType(receiver), key) : undefined);
2339
+ add(memberSymbol ? publishedDeclarationsFor(memberSymbol) : undefined);
2340
+ // `array[ i ].call( this, event )` -- a computed element read with no
2341
+ // literal key names no symbol at all, so the lookup above finds nothing
2342
+ // and the call is attributed to no declaration. That is exactly how
2343
+ // three's `EventDispatcher.dispatchEvent` invokes EVERY listener, which
2344
+ // is why each `on*Dispose( event )` body sees an untyped `event` and
2345
+ // every object recovered from `event.target` boxes.
2346
+ //
2347
+ // `arrayCalleeAuthority().arrayElementTargetsOf` is the identical
2348
+ // closed-array proof that `flow/callable-reach.ts`'s own `.call`/
2349
+ // `.apply` branch already trusts for ESCAPE closure (`callableArray-
2350
+ // TargetsOf`, with a record/dictionary-storage fallback via
2351
+ // `arrayStoredValuesOf` for a plain-object listener map like three's
2352
+ // `EventDispatcher._listeners[ type ]`); asked here for TYPE
2353
+ // ATTRIBUTION instead, so a listener's declaration receives this call
2354
+ // site as real parameter evidence the same way an override receives a
2355
+ // base's calls. It returns null unless the array's whole allocation
2356
+ // and use graph is closed, so it can only ever add complete evidence,
2357
+ // never a guess.
2358
+ //
2359
+ // Gated on the ordinary lookup having found nothing, so no attribution
2360
+ // that already worked can change.
2361
+ if (!memberSymbol && ts.isElementAccessExpression(heldCallee)) {
2362
+ const targets = arrayCalleeAuthority().arrayElementTargetsOf?.(heldCallee);
2363
+ if (targets)
2364
+ add(new Set(targets));
2365
+ }
2366
+ // The actual `array[ i ].call( this, event )` spelling: `heldCallee` is
2367
+ // the WRAPPER property access (`.call`/`.apply` itself), not the array
2368
+ // element, because `unwrapExplicitThisCall` left it unresolved -- its
2369
+ // static gate needs the element's checker type to already carry a call
2370
+ // signature, and an untyped push (`listeners[ type ].push( listener )`
2371
+ // onto a field with no declared element type) never does. The same
2372
+ // closed-array proof above still answers "is every value this array
2373
+ // ever held a real function" without needing that type, so ask it of
2374
+ // the WRAPPED element (`heldCallee.expression`) instead of `heldCallee`
2375
+ // itself, and commit to the explicit-this reading -- `thisArg` and the
2376
+ // real arguments, not the array-element receiver and both raw operands
2377
+ // -- only once it holds. `pendingExplicitThisReadings` feeds NEXT
2378
+ // round's `indexValueFlow` (`censusExplicitThisAt`), so `site.operands`
2379
+ // itself carries the corrected frame everywhere it is read (argument
2380
+ // census, host-mutation census, target resolution alike) rather than
2381
+ // this proof living only here.
2382
+ if (!memberSymbol &&
2383
+ ts.isPropertyAccessExpression(heldCallee) &&
2384
+ (key === 'call' || key === 'apply') &&
2385
+ ts.isElementAccessExpression(heldCallee.expression)) {
2386
+ const element = heldCallee.expression;
2387
+ const targets = arrayCalleeAuthority().arrayElementTargetsOf?.(element);
2388
+ if (targets) {
2389
+ add(new Set(targets));
2390
+ if (key === 'call') {
2391
+ pendingExplicitThisReadings.set(call, { callee: element, receiver: call.arguments[0] ?? null, args: call.arguments.slice(1) });
2392
+ }
2393
+ else if (call.arguments.length === 2) {
2394
+ const argumentsArray = call.arguments[1];
2395
+ if (argumentsArray &&
2396
+ ts.isArrayLiteralExpression(argumentsArray) &&
2397
+ argumentsArray.elements.every((e) => !ts.isSpreadElement(e)))
2398
+ pendingExplicitThisReadings.set(call, {
2399
+ callee: element,
2400
+ receiver: call.arguments[0] ?? null,
2401
+ args: argumentsArray.elements
2402
+ });
2403
+ }
2404
+ }
2405
+ }
2406
+ }
2407
+ const callee = call.expression;
2408
+ if (ts.isCallExpression(callee)) {
2409
+ const selector = checkerAttribution.get(callee);
2410
+ add(selector ? aliasEvidence.returnedFrom.get(selector) : undefined);
2411
+ }
2412
+ else if (ts.isIdentifier(callee)) {
2413
+ add(selectorsFeedingVariable(callee));
2414
+ }
2415
+ return result ?? EMPTY_DECLARATIONS;
2416
+ };
2417
+ const attributeCalls = () => {
2418
+ callbackContracts.clear();
2419
+ callsByDeclaration.clear();
2420
+ callTargets.clear();
2421
+ resolvedCallDeclarations.clear();
2422
+ for (const call of allCalls) {
2423
+ let declaration = checkerAttribution.get(call) ?? null;
2424
+ if (!declaration) {
2425
+ const calleeExpression = invocationOperands.get(call).callee;
2426
+ const callee = propagating.known(calleeExpression) ?? propagating.resolve(calleeExpression);
2427
+ if (callee) {
2428
+ // The same rule the return-type walk above states: a JavaScript
2429
+ // factory called with `new` declares no construct signature, and its
2430
+ // call signature is what says which function is being entered. Asked
2431
+ // the other way here -- not "what does it return" but "whose
2432
+ // parameters do these arguments land in" -- and answering it the
2433
+ // narrow way silently withheld every argument written at a `new`
2434
+ // against a plain function, so those parameters saw no evidence at
2435
+ // all and stayed unannotated.
2436
+ const constructed = ts.isNewExpression(call) ? callee.getConstructSignatures() : [];
2437
+ const signatures = constructed.length > 0 ? constructed : callee.getCallSignatures();
2438
+ if (signatures.length === 1)
2439
+ declaration = signatures[0]?.declaration ?? null;
2440
+ }
2441
+ }
2442
+ if (declaration) {
2443
+ pushCall(declaration, call);
2444
+ if (ts.isFunctionLike(declaration))
2445
+ resolvedCallDeclarations.set(call, declaration);
2446
+ }
2447
+ // ALIAS value flow: a call through a resolved member/selector-result
2448
+ // whose VALUE is a known function is a real call site of that
2449
+ // function too, in addition to (never instead of) whatever the block
2450
+ // above already attributed. Only `CallExpression`s are asked -- `new`
2451
+ // has no equivalent idiom in either shape.
2452
+ if (ts.isCallExpression(call)) {
2453
+ for (const aliased of aliasDeclarationsFor(call))
2454
+ pushCall(aliased, call);
2455
+ }
2456
+ }
2457
+ // Close the declaration relation with a worklist. A single pass depends on
2458
+ // whether a base/override or sibling happened to be declared first, and can
2459
+ // omit transitive implementations from both parameter and effect edges.
2460
+ const pending = [...callsByDeclaration].flatMap(([declaration, calls]) => calls.map((call) => ({ declaration, call })));
2461
+ for (let cursor = 0; cursor < pending.length; cursor++) {
2462
+ const { declaration, call } = pending[cursor];
2463
+ const destinations = [...(overridesOfBaseMethod.get(declaration) ?? []), ...(siblingMemberDeclarations.get(declaration) ?? [])];
2464
+ for (const destination of destinations) {
2465
+ if (callsByDeclaration.get(destination)?.includes(call))
2466
+ continue;
2467
+ pushCall(destination, call);
2468
+ pending.push({ declaration: destination, call });
2469
+ }
2470
+ }
2471
+ };
2472
+ /**
2473
+ * A parameter as a refusal's `owner`: the enclosing callable's name (or its
2474
+ * syntax kind, for one `nameOfCallable` cannot name) beside the parameter's
2475
+ * own name and source position -- the same identifying triple
2476
+ * `debugReport` below already prints, so a refusal and the debug line name
2477
+ * the same parameter the same way.
2478
+ */
2479
+ const describeParameter = (parameter) => {
2480
+ const callableName = nameOfCallable(parameter.parent)?.getText();
2481
+ const parameterName = ts.isIdentifier(parameter.name) ? parameter.name.text : parameter.name.getText();
2482
+ const file = parameter.getSourceFile();
2483
+ const line = file.getLineAndCharacterOfPosition(parameter.getStart()).line + 1;
2484
+ return `${callableName ?? `<${ts.SyntaxKind[parameter.parent.kind]}>`}(${parameterName}) @${file.fileName.split('/').pop()}:${line}`;
2485
+ };
2486
+ /**
2487
+ * The stable cause behind a reason string, for the refusal's `key`.
2488
+ *
2489
+ * Every reason this census writes is already a fixed kebab-case string with
2490
+ * one exception: `escapeReason` appends the escaping reference's syntax
2491
+ * kind (`function-escapes:CallExpression`, `function-escapes:unnamed:Root`,
2492
+ * ...), which varies per site by construction. Collapsing that family to
2493
+ * one root is the same split every other reason already gets for free --
2494
+ * the kind stays in `reason`, where the prose is allowed to vary.
2495
+ */
2496
+ const rootOf = (reason) => (reason.startsWith('function-escapes') ? 'function-escapes' : reason);
2497
+ const refusals = [];
2498
+ const refuse = (reason, owner, detail = reason) => {
2499
+ refusals.push(censusRefusal('parameter', rootOf(reason), detail, owner));
2500
+ };
2501
+ // The reassignment split is in the index: it asks the checker for a symbol
2502
+ // per candidate and the answer cannot change between rounds. Escape, by
2503
+ // contrast, IS re-tested every round -- it is stated against the calls
2504
+ // attributed so far, and those grow.
2505
+ const notReassigned = index.notReassigned;
2506
+ for (const candidate of index.reassigned)
2507
+ refuse('parameter-reassigned', describeParameter(candidate.parameter));
2508
+ /** The subset of `bindings` that came from a STATED annotation -- see `statedTypeAt`. */
2509
+ const statedBindings = new Map();
2510
+ let lastRefusal = new Map();
2511
+ /**
2512
+ * An optional parameter with no default binds `T | undefined` in its body, whatever
2513
+ * the call sites agree on: the declaration says a caller may omit it, and the
2514
+ * body can observe that omission. `structural-parts.ts`'s `parameterOf`
2515
+ * publishes the SLOT of the same parameter with `optional: true` off the
2516
+ * same checker optionality fact (including JSDoc), so a binding published without the absence made the
2517
+ * two frames disagree ("parameter 2 is bound as `string` but the ABI
2518
+ * declares `optional(string,undefined)`") and the whole body refused to
2519
+ * project. A DEFAULTED parameter is deliberately left alone: its body binding
2520
+ * is the type with the default already applied, and
2521
+ * `producers/bindings.ts`'s `contributeDefaultedParameter` is the one place
2522
+ * that splits the raw slot (with the absence) from that binding.
2523
+ */
2524
+ const withDeclaredAbsence = (parameter, type) => checker.isOptionalParameter(parameter) && parameter.initializer === undefined
2525
+ ? checker.getNullableType(type, ts.TypeFlags.Undefined)
2526
+ : type;
2527
+ /**
2528
+ * The synthesized-union counterpart of `withDeclaredAbsence`.
2529
+ *
2530
+ * `agreedArgumentType` returns `unionArms` when call sites contribute
2531
+ * structurally distinct carriers that have no single checker `ts.Type`.
2532
+ * That path used to bypass declared optionality, so `p?: T` bound only the
2533
+ * present synthesized arms in the body while `parameterOf` independently
2534
+ * widened the callable slot to `present | undefined`. ABI projection then
2535
+ * correctly refused the two physical frames. Preserve the same declared
2536
+ * absence at the one root where the synthesized arms enter the census.
2537
+ */
2538
+ const withDeclaredAbsenceArms = (parameter, arms) => {
2539
+ if (!checker.isOptionalParameter(parameter) || parameter.initializer !== undefined)
2540
+ return arms;
2541
+ const containsUndefined = (type) => (type.flags & ts.TypeFlags.Undefined) !== 0 || (type.isUnion() && type.types.some(containsUndefined));
2542
+ return arms.some(containsUndefined) ? arms : [...arms, checker.getUndefinedType()];
2543
+ };
2544
+ /**
2545
+ * Prove every derived recursive back edge against the type learned from
2546
+ * independent callers. The temporary binding is visible only to this
2547
+ * resolver invocation; it is removed before any other candidate can observe
2548
+ * it. A subtype is safe because the provisional parameter carrier already
2549
+ * admits every value of that subtype. Anything unresolved, dynamic, or wider
2550
+ * refuses the candidate instead of laundering a cycle into evidence.
2551
+ */
2552
+ const validateDeferredRecursiveArguments = (parameter, provisional, argumentsToValidate) => {
2553
+ if (argumentsToValidate.length === 0)
2554
+ return null;
2555
+ bindings.set(parameter, provisional);
2556
+ propagating.reset();
2557
+ try {
2558
+ for (const argument of argumentsToValidate) {
2559
+ const resolved = propagating.known(argument) ?? propagating.resolve(argument);
2560
+ if (!resolved)
2561
+ return 'recursive-derived-argument-unresolved';
2562
+ if (isUnusableEvidence(resolved))
2563
+ return 'recursive-derived-argument-states-no-storage';
2564
+ const passed = resolved.isLiteral() ? checker.getBaseTypeOfLiteralType(resolved) : resolved;
2565
+ if (!checker.isTypeAssignableTo(passed, provisional))
2566
+ return 'recursive-derived-argument-disagrees';
2567
+ }
2568
+ return null;
2569
+ }
2570
+ finally {
2571
+ bindings.delete(parameter);
2572
+ propagating.reset();
2573
+ }
2574
+ };
2575
+ /** One sweep over every still-unbound candidate, answering how many it bound. */
2576
+ const bindingSweep = (skipSilentSites) => {
2577
+ propagating.reset();
2578
+ attributeCalls();
2579
+ // `hasClosedMemberCallableUses` (`flow/callable-reach.ts`) memoizes its
2580
+ // answer keyed in part by this RECEIVER-TYPE FUNCTION's own identity --
2581
+ // sound for a whole-program compile, where the authority never changes
2582
+ // mid-walk, but `bindingSweep` calls it up to 48 times against a GROWING
2583
+ // `bindings` map behind the SAME `propagatingTypeAt` closure. A member
2584
+ // whose closure needs another parameter's binding (`event` here) to
2585
+ // settle first got asked, refused, and cached BEFORE that binding
2586
+ // existed -- and the cache, keyed on an identity that never changes,
2587
+ // never asked again. `stored-listener-member-closure.test.ts`'s `draw`
2588
+ // parameter is the measured case: refused round 1 (before `event`
2589
+ // settled), then silently served that same stale refusal every round
2590
+ // after, with no new proof activity at all. A fresh function identity
2591
+ // each round costs nothing this proof does not already recompute WITHIN
2592
+ // a round (the cache still hits repeat asks inside one sweep) and makes
2593
+ // the next round's improved `bindings` visible instead of shadowed.
2594
+ memberClosureReceiverTypeAt = (expression) => propagatingTypeAt(expression);
2595
+ lastRefusal = new Map();
2596
+ let added = 0;
2597
+ for (const candidate of notReassigned) {
2598
+ if (bindings.has(candidate.parameter) || unionArms.has(candidate.parameter))
2599
+ continue;
2600
+ const inferCandidate = () => {
2601
+ const escaped = escapeReason(candidate.declaration);
2602
+ if (escaped) {
2603
+ lastRefusal.set(candidate.parameter, escaped);
2604
+ return false;
2605
+ }
2606
+ // Narrowing a declared upper bound needs complete call-site evidence.
2607
+ // Partial inference may discover an unannotated cycle, but cannot prove
2608
+ // that a declared unknown/union excludes its unresolved incoming values.
2609
+ const answer = agreedArgumentType(candidate.declaration, candidate.parameter, candidate.index, skipSilentSites && candidate.stated === null);
2610
+ // A STATED candidate is held to its statement. The agreed type has to be
2611
+ // assignable to it (the floor -- a callable value the annotation forbids
2612
+ // is not what this parameter holds, whatever the call sites say) AND to
2613
+ // differ from it only where the annotation said nothing. A synthesized
2614
+ // disjoint union is refused outright: those arms are a member LIST this
2615
+ // census builds for `table.intern`, never a `ts.Type` the statement can
2616
+ // be tested against, so there is nothing to hold it to.
2617
+ if (candidate.stated) {
2618
+ if (!('type' in answer)) {
2619
+ lastRefusal.set(candidate.parameter, 'unionArms' in answer ? 'stated-parameter-synthesized-union' : answer.refused);
2620
+ return false;
2621
+ }
2622
+ if (carriesUnsubstitutedGeneric(checker, answer.type)) {
2623
+ lastRefusal.set(candidate.parameter, 'stated-parameter-open-generic');
2624
+ return false;
2625
+ }
2626
+ if (!checker.isTypeAssignableTo(answer.type, candidate.stated)) {
2627
+ lastRefusal.set(candidate.parameter, 'stated-parameter-argument-not-assignable');
2628
+ return false;
2629
+ }
2630
+ if (!narrowsOnlyUnstatedPositions(checker, candidate.parameter, candidate.stated, answer.type)) {
2631
+ lastRefusal.set(candidate.parameter, 'stated-parameter-narrows-a-stated-position');
2632
+ return false;
2633
+ }
2634
+ const narrowed = withDeclaredAbsence(candidate.parameter, answer.type);
2635
+ const recursiveRefusal = validateDeferredRecursiveArguments(candidate.parameter, narrowed, answer.deferredRecursiveArguments);
2636
+ if (recursiveRefusal) {
2637
+ lastRefusal.set(candidate.parameter, recursiveRefusal);
2638
+ return false;
2639
+ }
2640
+ bindings.set(candidate.parameter, narrowed);
2641
+ statedBindings.set(candidate.parameter, narrowed);
2642
+ return true;
2643
+ }
2644
+ if ('type' in answer) {
2645
+ const narrowed = withDeclaredAbsence(candidate.parameter, answer.type);
2646
+ const recursiveRefusal = validateDeferredRecursiveArguments(candidate.parameter, narrowed, answer.deferredRecursiveArguments);
2647
+ if (recursiveRefusal) {
2648
+ lastRefusal.set(candidate.parameter, recursiveRefusal);
2649
+ return false;
2650
+ }
2651
+ bindings.set(candidate.parameter, narrowed);
2652
+ }
2653
+ else if ('unionArms' in answer) {
2654
+ if (answer.deferredRecursiveArguments.length > 0) {
2655
+ lastRefusal.set(candidate.parameter, 'recursive-derived-argument-synthesized-union');
2656
+ return false;
2657
+ }
2658
+ unionArms.set(candidate.parameter, withDeclaredAbsenceArms(candidate.parameter, answer.unionArms));
2659
+ }
2660
+ else {
2661
+ lastRefusal.set(candidate.parameter, answer.refused);
2662
+ return false;
2663
+ }
2664
+ return true;
2665
+ };
2666
+ const captured = protocolLedger?.capture(inferCandidate) ?? { value: inferCandidate(), requirements: [] };
2667
+ if (captured.value) {
2668
+ protocolRequirements.set(candidate.parameter, captured.requirements);
2669
+ added += 1;
2670
+ }
2671
+ }
2672
+ return added;
2673
+ };
2674
+ // EVIDENCE EXHAUSTED.
2675
+ //
2676
+ // After strict inference stops adding bindings, unstated parameters may
2677
+ // join evidence from resolvable sites while skipping unresolved sites.
2678
+ // This relaxation cannot discard a resolved unusable type, narrow an
2679
+ // explicitly stated boundary, or let a default replace a supplied argument.
2680
+ // For defaulted parameters, an explicitly supplied any/unknown value remains
2681
+ // evidence with its actual checker type. Missing arguments still follow
2682
+ // the separate default/absence rules. All-silent evidence still refuses.
2683
+ //
2684
+ // The phases alternate, because a parameter bound from surviving evidence is
2685
+ // itself evidence: the strict fixpoint re-opens with the new bindings and
2686
+ // gets first refusal on all it can now type strictly. It stops when a relaxed
2687
+ // sweep adds nothing -- terminating because bindings are only ever added.
2688
+ for (let phase = 0; phase < 4; phase += 1) {
2689
+ for (let round = 0; round < 12; round += 1)
2690
+ if (bindingSweep(false) === 0)
2691
+ break;
2692
+ if (bindingSweep(true) === 0)
2693
+ break;
2694
+ }
2695
+ // Relaxed bindings seed cycles; they are not proof that a silent caller
2696
+ // cannot supply another shape. Seal the fixed point against EVERY incoming
2697
+ // argument, then withdraw dependent conclusions until the survivors are
2698
+ // closed. Without this check an unresolved forwarding parameter disappears
2699
+ // from its callee's evidence and an unrelated call dictates a wrong unbox.
2700
+ // Re-attribution and resolver caches must follow each withdrawal as well:
2701
+ // consumers inferred strictly can still depend on a provisional producer.
2702
+ //
2703
+ // ESCAPE is re-tested here too, not only inside `bindingSweep`, for a gap
2704
+ // measured on the three.js app's `WebGLCapabilities( gl, extensions, parameters,
2705
+ // utils )`: `gl` and `parameters` bind in an early sweep, while `extensions`
2706
+ // and `utils` each depend on a whole separate factory (`WebGLExtensions`,
2707
+ // `WebGLUtils`) resolving first and so are still unbound several sweeps
2708
+ // later. `escapeReason`'s export/import check (`isModuleExportedDeclaration`
2709
+ // + `inProgramImportReferencesOf`) is re-evaluated fresh every sweep and, by
2710
+ // the time `extensions`/`utils` finally have argument evidence, it has
2711
+ // started returning `function-escapes:exported` for `WebGLCapabilities`
2712
+ // itself -- confirmed against the real corpus (the app's actual refusal
2713
+ // list carries exactly this reason for both parameters). `bindingSweep`'s
2714
+ // per-candidate loop skips any parameter already in `bindings`, so
2715
+ // `gl`/`parameters` are never asked again and keep a binding taken before
2716
+ // the escape was visible -- while their siblings on the SAME declaration,
2717
+ // tested one sweep later, are correctly refused. Escape is a fact about the
2718
+ // DECLARATION, not about which of its parameters happened to resolve
2719
+ // first: if the function escapes, every one of its parameters is bound
2720
+ // from a caller set this census can no longer prove complete, `gl`/
2721
+ // `parameters` included, and a wrong type is worse than a boxed one (this
2722
+ // module's own charter, above). Withdrawing only the late arrivals leaves
2723
+ // the early ones silently unsound -- answered, never refused, and never
2724
+ // revisited.
2725
+ //
2726
+ // Only the export/import reasons are retested, not the full `escapeReason`
2727
+ // surface: the member-closure reasons (`function-escapes:
2728
+ // uncounted-member-reference`, `function-escapes:uncounted-reference`, and
2729
+ // the generic reference-walk fallback) read `propagating`/`calls` for
2730
+ // OTHER declarations reachable through the same receiver -- three's
2731
+ // `renderer` argument that Object3D's `add` walks through its own
2732
+ // `arguments` frame is exactly this shape, closed by `memberClosed`. Once
2733
+ // any sibling candidate in that same chain withdraws earlier in this same
2734
+ // pass, `propagating.reset()` (a few lines below) clears the cache
2735
+ // `memberClosed` reads, and re-asking the full escape question mid-pass
2736
+ // read a still-valid closure proof as open -- breaking
2737
+ // `arguments-frame-member-closure.test.ts`'s positive case and
2738
+ // `implicit-arguments-tuple.test.ts`'s "closed callers" case. The
2739
+ // export/import check has no such dependency: whether `WebGLCapabilities`
2740
+ // is reachable from outside the compiled program is a property of the
2741
+ // module graph, invariant to which of ITS OWN parameters is currently
2742
+ // bound. Re-running exactly that check, and no more, makes the one
2743
+ // measured gap retroactive without reopening the proof the loosening
2744
+ // above exists to protect.
2745
+ let withdrew;
2746
+ do {
2747
+ withdrew = false;
2748
+ propagating.reset();
2749
+ unionTypes.clear();
2750
+ patternReadTypes.clear();
2751
+ argumentsByParameter.clear();
2752
+ attributeCalls();
2753
+ for (const candidate of notReassigned) {
2754
+ const parameter = candidate.parameter;
2755
+ if (!bindings.has(parameter) && !unionArms.has(parameter))
2756
+ continue;
2757
+ const escaped = escapeReason(candidate.declaration);
2758
+ if (escaped === 'function-escapes:exported' || escaped === 'function-escapes:uncounted-import') {
2759
+ bindings.delete(parameter);
2760
+ unionArms.delete(parameter);
2761
+ protocolRequirements.delete(parameter);
2762
+ unionTypes.clear();
2763
+ statedBindings.delete(parameter);
2764
+ argumentsByParameter.delete(parameter);
2765
+ lastRefusal.set(parameter, escaped);
2766
+ propagating.reset();
2767
+ withdrew = true;
2768
+ continue;
2769
+ }
2770
+ const published = parameterTypeOf(parameter);
2771
+ const answer = agreedArgumentType(candidate.declaration, parameter, candidate.index, true);
2772
+ let reason = null;
2773
+ if ('refused' in answer)
2774
+ reason = answer.refused;
2775
+ else if (answer.sawSilentSite)
2776
+ reason = 'argument-unresolved';
2777
+ else {
2778
+ const incoming = 'type' in answer ? [answer.type] : answer.unionArms;
2779
+ const admits = (type) => published !== null &&
2780
+ ((type.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) === 0 ||
2781
+ (published.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) !== 0) &&
2782
+ checker.isTypeAssignableTo(type, published);
2783
+ if (!incoming.every(admits))
2784
+ reason = 'call-sites-disagree';
2785
+ else {
2786
+ for (const argument of answer.deferredRecursiveArguments) {
2787
+ const resolved = propagating.known(argument) ?? propagating.resolve(argument);
2788
+ if (!resolved || isUnusableEvidence(resolved) || !admits(resolved)) {
2789
+ reason = 'recursive-derived-argument-disagrees';
2790
+ break;
2791
+ }
2792
+ }
2793
+ }
2794
+ }
2795
+ if (reason === null)
2796
+ continue;
2797
+ bindings.delete(parameter);
2798
+ unionArms.delete(parameter);
2799
+ protocolRequirements.delete(parameter);
2800
+ unionTypes.clear();
2801
+ statedBindings.delete(parameter);
2802
+ argumentsByParameter.delete(parameter);
2803
+ lastRefusal.set(parameter, reason);
2804
+ propagating.reset();
2805
+ withdrew = true;
2806
+ }
2807
+ } while (withdrew);
2808
+ // A checker narrowing is evidence about the SAME parameter cell, not a
2809
+ // conversion request. Preserve every distinct concrete object kind the
2810
+ // checker exposes under a pure `[string]: any` upper bound, alongside the
2811
+ // dictionary arm used by unnarrowed reads. Preserve the complete finite
2812
+ // member set, as the ordinary synthesized-union path does.
2813
+ for (const candidate of notReassigned) {
2814
+ const upper = candidate.flowCarrierUpperBound;
2815
+ if (!upper || !ts.isIdentifier(candidate.parameter.name))
2816
+ continue;
2817
+ const symbol = checker.getSymbolAtLocation(candidate.parameter.name);
2818
+ const references = symbol ? valueFlow.memberReferencesToSymbol(symbol) : [];
2819
+ const narrowed = [];
2820
+ for (const reference of references) {
2821
+ const type = checker.getTypeAtLocation(reference);
2822
+ if ((type.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown | ts.TypeFlags.Never)) !== 0)
2823
+ continue;
2824
+ if (!isFlowContainerType(checker, reference, type))
2825
+ continue;
2826
+ if (!checker.isTypeAssignableTo(type, upper))
2827
+ continue;
2828
+ if (checker.isTypeAssignableTo(upper, type))
2829
+ continue;
2830
+ if (narrowed.some((seen) => checker.isTypeAssignableTo(type, seen) && checker.isTypeAssignableTo(seen, type)))
2831
+ continue;
2832
+ narrowed.push(type);
2833
+ }
2834
+ // A call that explicitly crosses this boundary from `any` contributes a
2835
+ // real dynamic arm. Plain runtime objects must remain the boxes they are;
2836
+ // rebuilding them as dictionaries would change identity and lose
2837
+ // prototype/accessor behavior. Concrete Document/Array/Map callers keep
2838
+ // their native arms beside it.
2839
+ let dynamicCallArm = null;
2840
+ for (const call of callsByDeclaration.get(candidate.declaration) ?? []) {
2841
+ const args = invocationOperands.get(call).args;
2842
+ const argument = args?.[candidate.index];
2843
+ if (!argument)
2844
+ continue;
2845
+ const passed = checker.getTypeAtLocation(argument);
2846
+ if ((passed.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) !== 0) {
2847
+ dynamicCallArm = passed;
2848
+ break;
2849
+ }
2850
+ }
2851
+ const arms = [upper, ...narrowed, ...(dynamicCallArm ? [dynamicCallArm] : [])];
2852
+ if (arms.length === 1)
2853
+ continue;
2854
+ // This late flow-container publication is a second synthesized-arm entry
2855
+ // point. It must preserve the same declared absence as the ordinary
2856
+ // `unionArms` path above; otherwise an optional open-document parameter
2857
+ // (BSON's `DBRef(..., fields?: Document)`) binds a required body union
2858
+ // while its callable slot remains optional.
2859
+ flowCarrierArms.set(candidate.parameter, withDeclaredAbsenceArms(candidate.parameter, arms));
2860
+ flowCarrierBounds.set(candidate.parameter, upper);
2861
+ // The union is the cell's placement. A same-annotation binding learned
2862
+ // from call sites would otherwise outrank it in `parameterOf`.
2863
+ bindings.delete(candidate.parameter);
2864
+ statedBindings.delete(candidate.parameter);
2865
+ lastRefusal.delete(candidate.parameter);
2866
+ }
2867
+ // A stated JS parameter the census does not infer can still be left out by
2868
+ // a caller: three's `colorBuffer.setClear( 0, 0, 0, 1 )` against the
2869
+ // overlay's `@param {boolean} premultipliedAlpha`. Its cell then holds the
2870
+ // statement plus `undefined` -- see `omitted-stated-parameter.ts`. Asked of
2871
+ // the settled attribution after every withdrawal, so no argument binding it
2872
+ // reads can still be taken back; the closure proof runs under the ledger
2873
+ // like any inference, and its obligations are kept with the binding.
2874
+ propagating.reset();
2875
+ // `GEA_STATED_OMISSION_OFF` keeps the arm without this rule runnable, the way `GEA_BAG_OFF` is.
2876
+ for (const site of process.env['GEA_STATED_OMISSION_OFF'] ? [] : index.omissionSites) {
2877
+ if (bindings.has(site.parameter) || unionArms.has(site.parameter))
2878
+ continue;
2879
+ const answer = statedParameterWithOmission(checker, site.stated, site.index, callsByDeclaration.get(site.declaration) ?? [], (call) => invocationOperands.get(call).args, (argument) => propagating.known(argument) ?? propagating.resolve(argument) ?? checker.getTypeAtLocation(argument));
2880
+ if (answer === null)
2881
+ continue;
2882
+ if ('refused' in answer) {
2883
+ lastRefusal.set(site.parameter, answer.refused);
2884
+ continue;
2885
+ }
2886
+ // Deliberately NOT gated on `escapeReason`. A caller the census cannot see
2887
+ // is held to the statement whether or not this binds -- that is what the
2888
+ // parameter's carrier is when it stays unbound -- so it can only add
2889
+ // statement values to the cell, never take away the `undefined` a caller
2890
+ // the census DOES see provably passes. Refusing an open caller set left
2891
+ // the bare statement standing, which is the one answer known to be wrong.
2892
+ const closure = () => ((contractsFor(site.declaration)?.length ?? 0) > 0 ? 'stated-omission-callback-contract' : null);
2893
+ const captured = protocolLedger?.capture(closure) ?? { value: closure(), requirements: [] };
2894
+ if (captured.value !== null) {
2895
+ lastRefusal.set(site.parameter, captured.value);
2896
+ continue;
2897
+ }
2898
+ bindings.set(site.parameter, answer.type);
2899
+ statedBindings.set(site.parameter, answer.type);
2900
+ protocolRequirements.set(site.parameter, captured.requirements);
2901
+ if (process.env['GEA_BINDING_DEBUG'])
2902
+ console.error(`[STATED-OMISSION] ${describeParameter(site.parameter)} :: ${checker.typeToString(answer.type)}`);
2903
+ }
2904
+ for (const [parameter, reason] of lastRefusal)
2905
+ refuse(reason, describeParameter(parameter));
2906
+ /**
2907
+ * A READ of a stated parameter answers the BODY's binding, not the slot's.
2908
+ *
2909
+ * The two differ by exactly the absence a DEFAULT exists to answer: the slot
2910
+ * carries `undefined` (`statedUpperBound` puts it there deliberately, so a
2911
+ * caller passing a possibly-absent value is not refused), and by the time
2912
+ * the body runs the initializer has replaced it, so the cell holds the
2913
+ * undefined-free type -- which is precisely what
2914
+ * `producers/bindings.ts`'s `contributeDefaultedParameter` builds as its
2915
+ * `bodyType`. Answering a read with the slot's union instead is a
2916
+ * cell-versus-read split: hono's `this.#matchResult = matchResult` had the
2917
+ * cell holding `Result<[H, RouterRoute]>` while the read of the very same
2918
+ * parameter published `Result<[H, RouterRoute]> | undefined`.
2919
+ *
2920
+ * An initializer that IS `undefined` replaces nothing and the body really
2921
+ * can observe one -- the same carve-out, for the same reason, that
2922
+ * `contributeDefaultedParameter` states at length. An OPTIONAL parameter
2923
+ * with no default keeps its absence too: nothing filled it in.
2924
+ */
2925
+ const bodyBindingOf = (declaration, narrowed) => {
2926
+ if (!declaration.initializer)
2927
+ return narrowed;
2928
+ if ((checker.getTypeAtLocation(declaration.initializer).flags & ts.TypeFlags.Undefined) !== 0)
2929
+ return narrowed;
2930
+ return withoutUndefinedMember(checker, narrowed);
2931
+ };
2932
+ // Publication reads a settled binding set, so its memo is built once, after
2933
+ // the fixpoint stops -- unlike the propagating one, which is thrown away
2934
+ // each round because the answers it caches are answers to a smaller view.
2935
+ publishing.reset();
2936
+ /** Answers for `statedTypeAt`, settled once the fixpoint above has stopped. */
2937
+ const statedTypes = new Map();
2938
+ const computeStatedTypeAt = (node) => {
2939
+ // A PRIOR ROUND's stated narrowings are forwarded, the same way `known`
2940
+ // above forwards `upstream.typeAt`: round two exists precisely so a
2941
+ // census that could not see round one's answers gets them, and a
2942
+ // narrowing this round did not make itself is still the settled fact
2943
+ // about that cell. Without this the FIELD census's narrowings (round
2944
+ // one, composed outside this census) were invisible to round two's
2945
+ // return census, which then typed a `return this.#field` from the
2946
+ // checker's un-narrowed annotation and split the two cells apart.
2947
+ //
2948
+ // This closure over `upstream` is the same chain the `upstream` parameter's
2949
+ // own doc above names: it is why the object this function returns keeps
2950
+ // every earlier round's `ValueFlowIndex` (and `source-value-session.ts`'s
2951
+ // ~1 GB solver session for it) reachable for the rest of the compile.
2952
+ const inherited = upstream.statedTypeAt(node);
2953
+ if (inherited)
2954
+ return inherited;
2955
+ if (ts.isParameter(node))
2956
+ return statedBindings.size === 0 ? null : (statedBindings.get(node) ?? null);
2957
+ if (!ts.isIdentifier(node))
2958
+ return null;
2959
+ // Both branches below need the identifier's parameter declaration and
2960
+ // nothing else, so the symbol is resolved ONCE. It used to be asked twice
2961
+ // -- and asked at all even when both maps were empty, which for a program
2962
+ // that states no narrowings is the entire cost for no possible answer.
2963
+ if (flowCarrierBounds.size === 0 && statedBindings.size === 0)
2964
+ return null;
2965
+ const declarations = checker.getSymbolAtLocation(node)?.declarations;
2966
+ if (!declarations)
2967
+ return null;
2968
+ const parameter = declarations.find(ts.isParameter);
2969
+ // A user predicate may give an open dynamic dictionary a named-record
2970
+ // VIEW so its property reads become typed. That does not replace the
2971
+ // object with a record allocation: the same dictionary enters and
2972
+ // leaves the guarded branch. Keep the cell's physical upper-bound
2973
+ // carrier at the identifier; destructuring/property producers still
2974
+ // use the checker's narrowed member types for each value they extract.
2975
+ const upper = parameter ? flowCarrierBounds.get(parameter) : undefined;
2976
+ if (upper) {
2977
+ const read = checker.getTypeAtLocation(node);
2978
+ const isProperNarrowing = checker.isTypeAssignableTo(read, upper) && !checker.isTypeAssignableTo(upper, read);
2979
+ if (isProperNarrowing && !isFlowContainerType(checker, node, read))
2980
+ return upper;
2981
+ }
2982
+ if (statedBindings.size === 0)
2983
+ return null;
2984
+ for (const declaration of declarations) {
2985
+ if (!ts.isParameter(declaration))
2986
+ continue;
2987
+ const narrowed = statedBindings.get(declaration);
2988
+ if (narrowed)
2989
+ return bodyBindingOf(declaration, narrowed);
2990
+ }
2991
+ return null;
2992
+ };
2993
+ // Implicit slots have an owning signature but no parameter declaration.
2994
+ // Reuse the settled call attribution and resolver; never start a second
2995
+ // call-site inventory or infer from only the successfully typed callers.
2996
+ const implicitTuples = new Map();
2997
+ /** Refused frames, for `debugReport` to print the open use behind each. */
2998
+ const implicitRefusals = new Map();
2999
+ // A `spread` edge names the spread's SOURCE, which it reads in bulk and never stores into.
3000
+ const writeNames = new Set(valueFlow.allWrites.flatMap((write) => (write.naming && write.edge !== 'spread' ? [write.naming] : [])));
3001
+ if (process.env['GEA_IMPLICIT_FRAME_DEBUG'])
3002
+ console.error(`[IMPLICIT-FRAME] owners in index: ${index.implicitArgumentsUses.size}`);
3003
+ for (const [owner, uses] of index.implicitArgumentsUses) {
3004
+ const infer = () => {
3005
+ const signature = checker.getSignatureFromDeclaration(owner);
3006
+ const slot = signature ? implicitArgumentsSlotOf(signature) : null;
3007
+ if (!slot)
3008
+ return { refused: 'implicit-arguments-no-frame' };
3009
+ const escape = escapeReason(owner, true);
3010
+ if (escape)
3011
+ return { refused: escape };
3012
+ if (owner.parameters.some((parameter) => parameter.initializer || parameter.dotDotDotToken))
3013
+ return { refused: 'implicit-arguments-non-simple-parameters' };
3014
+ if (owner.parameters.some((parameter) => {
3015
+ const symbol = checker.getSymbolAtLocation(parameter.name);
3016
+ return symbol !== undefined && index.assigned.has(symbol);
3017
+ }))
3018
+ return { refused: 'implicit-arguments-parameter-reassigned' };
3019
+ const usable = (type, node) => !!type && !isUnusableEvidence(type) && !annotationStatesNothing(checker, node, type);
3020
+ return inferImplicitArgumentsTuple({
3021
+ checker,
3022
+ owner,
3023
+ slot,
3024
+ uses,
3025
+ calls: callsByDeclaration.get(owner) ?? [],
3026
+ argumentsOf: (call) => invocationOperands.get(call).args,
3027
+ isWritten: (node) => writeNames.has(node),
3028
+ isRecursiveCall: (call) => isRecursiveCallWithin(call, owner),
3029
+ argumentTypeOf: (argument) => {
3030
+ const type = propagating.known(argument) ?? propagating.resolve(argument);
3031
+ return usable(type, argument) ? type : null;
3032
+ },
3033
+ statedElements: owner.parameters.flatMap((parameter) => {
3034
+ const type = checker.getTypeAtLocation(parameter);
3035
+ return usable(type, parameter) ? [type] : [];
3036
+ })
3037
+ });
3038
+ };
3039
+ const captured = protocolLedger?.capture(infer) ?? { value: infer(), requirements: [] };
3040
+ const answer = captured.value;
3041
+ if ('tuple' in answer) {
3042
+ implicitTuples.set(owner, answer.tuple);
3043
+ protocolRequirements.set(owner, captured.requirements);
3044
+ // A SETTLED frame can still be settled on a type nothing can carry, and
3045
+ // that outcome has no refusal to read: the census records only the
3046
+ // frames it turned down, so a frame that joined to a union no consumer
3047
+ // can lower looks identical to one that joined to a class. The three.js app's
3048
+ // largest nested-dynamic group -- 1382 carriers, every `.add( ... )` in
3049
+ // the program -- is one such frame, and nothing printed it.
3050
+ if (process.env['GEA_IMPLICIT_FRAME_DEBUG']) {
3051
+ const file = owner.getSourceFile();
3052
+ const line = file.getLineAndCharacterOfPosition(owner.getStart()).line + 1;
3053
+ const shape = answer.tuple.frame === 'array'
3054
+ ? `array element=${checker.typeToString(answer.tuple.element)}`
3055
+ : `tuple required=${answer.tuple.required} elements=[${answer.tuple.elements.map((element) => checker.typeToString(element)).join(', ')}]`;
3056
+ console.error(`[IMPLICIT-FRAME] ${nameOfCallable(owner)?.getText() ?? '<anonymous>'} @${file.fileName.split('/').pop()}:${line} ${shape}`);
3057
+ }
3058
+ }
3059
+ else {
3060
+ const file = owner.getSourceFile();
3061
+ const line = file.getLineAndCharacterOfPosition(owner.getStart()).line + 1;
3062
+ if (process.env['GEA_IMPLICIT_FRAME_DEBUG'])
3063
+ console.error(`[IMPLICIT-FRAME] REFUSED ${nameOfCallable(owner)?.getText() ?? '<anonymous>'} @${file.fileName.split('/').pop()}:${line} ${answer.refused}`);
3064
+ const evidence = answer.evidence;
3065
+ const evidenceFile = evidence?.getSourceFile();
3066
+ const detail = evidence && evidenceFile
3067
+ ? `${answer.refused}: ${evidenceFile.fileName}:${evidenceFile.getLineAndCharacterOfPosition(evidence.getStart()).line + 1} ${evidence.getText().slice(0, 160)}`
3068
+ : answer.refused;
3069
+ implicitRefusals.set(owner, answer.refused);
3070
+ refuse(answer.refused, `${nameOfCallable(owner)?.getText() ?? '<anonymous>'}(arguments) @${file.fileName.split('/').pop()}:${line}`, detail);
3071
+ }
3072
+ }
3073
+ /**
3074
+ * The element join `restElementTypeAt` publishes, per rest parameter.
3075
+ *
3076
+ * `ECMA-262 10.2.11` step 28 (`FunctionDeclarationInstantiation`) binds a
3077
+ * rest parameter to a fresh Array unconditionally, whatever arity each
3078
+ * caller uses -- so unlike an ordinary parameter there is no "position 0
3079
+ * disagrees with position 1" question to ask here: every argument at or
3080
+ * past the rest's own ordinal, at EVERY call, is one more member of the
3081
+ * SAME array, and this asks for the one type that join settles on.
3082
+ *
3083
+ * Built from `callsByDeclaration`/`propagating` exactly as the implicit-
3084
+ * arguments frame above is -- both read the settled call attribution this
3085
+ * census's own fixpoint already closed, and neither needs a fixpoint of
3086
+ * its own: a rest parameter's element can only be as good as the call
3087
+ * sites it is joined from, and nothing downstream of THIS census ever
3088
+ * feeds back into what a call site passes.
3089
+ *
3090
+ * Deliberately conservative, matching `collectPassedArguments`'s own
3091
+ * refusal philosophy: a spread argument anywhere in the tail, or any
3092
+ * argument this census cannot resolve to usable evidence, refuses the
3093
+ * WHOLE parameter rather than joining a partial view of what a caller
3094
+ * passes -- leaving the checker's own (dynamic) answer exactly as it was
3095
+ * before this existed.
3096
+ *
3097
+ * The call-site tail is not the only writer of this cell: three's
3098
+ * `utils.js` reassigns its own rest parameter outright --
3099
+ * `params = enhanceLogMessage( params )` inside `warn`/`error` -- and that
3100
+ * write replaces the SAME binding the tail above is joined into, not a
3101
+ * different question. `assignedEvidence` already carries it: the ordinary
3102
+ * sweep's own reassignment index (`indexParameterBindingProgram`, above)
3103
+ * walks `valueFlow.allWrites` by `ts.isParameter(declaration)` alone, never
3104
+ * filtering out a `dotDotDotToken` parameter, so a rest parameter's own
3105
+ * reassignment was captured from the start even though nothing read it
3106
+ * until now. `enhanceLogMessage` is declared `@returns {Array<any>}`, so
3107
+ * the honest join over BOTH sources is dynamic -- declining here, exactly
3108
+ * as the tail loop above declines on a spread or unusable argument, is
3109
+ * what keeps `warn`'s declaration and every one of its call sites agreeing
3110
+ * on the same (boxed) carrier instead of the census narrowing one end past
3111
+ * what the body's own write still produces.
3112
+ */
3113
+ const restElementTypes = new Map();
3114
+ for (const candidate of index.restParameterCandidates) {
3115
+ const calls = callsByDeclaration.get(candidate.declaration) ?? [];
3116
+ if (calls.length === 0)
3117
+ continue;
3118
+ const passed = [];
3119
+ let refused = false;
3120
+ for (const call of calls) {
3121
+ if (refused)
3122
+ break;
3123
+ const effectiveArguments = invocationOperands.get(call).args;
3124
+ for (const argument of (effectiveArguments ?? []).slice(candidate.index)) {
3125
+ if (ts.isSpreadElement(argument)) {
3126
+ refused = true;
3127
+ break;
3128
+ }
3129
+ const resolved = propagating.known(argument) ?? propagating.resolve(argument);
3130
+ if (!resolved || isUnusableEvidence(resolved)) {
3131
+ refused = true;
3132
+ break;
3133
+ }
3134
+ passed.push(resolved.isLiteral() ? checker.getBaseTypeOfLiteralType(resolved) : resolved);
3135
+ }
3136
+ }
3137
+ if (!refused) {
3138
+ const symbol = ts.isIdentifier(candidate.parameter.name) ? checker.getSymbolAtLocation(candidate.parameter.name) : undefined;
3139
+ const writes = symbol ? assignedEvidence.get(symbol) : undefined;
3140
+ if (writes === null)
3141
+ refused = true;
3142
+ else
3143
+ for (const write of writes ?? []) {
3144
+ if (refused)
3145
+ break;
3146
+ const written = write.operatorTyped
3147
+ ? checker.getTypeAtLocation(write.expression)
3148
+ : (propagating.known(write.expression) ?? propagating.resolve(write.expression));
3149
+ // The write replaces the WHOLE array, not one element -- read its
3150
+ // own element out through the numeric index signature (the same
3151
+ // primitive `indexedTypeOf` above uses for `array[i]`) before
3152
+ // joining it against the tail's per-element evidence, or a
3153
+ // reassignment to a plain `Array<any>` would join `string` against
3154
+ // the ARRAY type itself rather than against its `any` element.
3155
+ const element = written && checker.getIndexTypeOfType(checker.getNonNullableType(written), ts.IndexKind.Number);
3156
+ if (!element || carriesNoEvidence(element)) {
3157
+ refused = true;
3158
+ break;
3159
+ }
3160
+ passed.push(element.isLiteral() ? checker.getBaseTypeOfLiteralType(element) : element);
3161
+ }
3162
+ }
3163
+ if (refused || passed.length === 0)
3164
+ continue;
3165
+ const joined = joinOfWrites(checker, passed);
3166
+ if (joined)
3167
+ restElementTypes.set(candidate.parameter, joined);
3168
+ }
3169
+ /**
3170
+ * A rest parameter whose body forwards its ENTIRE array on, via a bare
3171
+ * `...name` spread naming its own binding as a call's ONLY argument, hands
3172
+ * that same array to whatever the call resolves to. `warnOnce( ...params )`
3173
+ * calling `warn( ...params )` in three's `utils.js` is exactly this: the
3174
+ * array `warnOnce` narrowed to `string` from its own callers' tail is the
3175
+ * IDENTICAL array `warn` receives, and `warn`'s own reassignment above
3176
+ * already forces it dynamic. A forwarder narrower than what its own target
3177
+ * settles on is not a smaller carrier for the same value, it is a SECOND,
3178
+ * disagreeing carrier for it -- exactly the shape `representation/verify.ts`
3179
+ * refuses to certify (`array-object(string) -> array-object(dynamic)`, no
3180
+ * conversion installed, and none may be: a mutable `ArrayObject` recast at a
3181
+ * call argument is a recorded aliasing miscompile, not a fallback here).
3182
+ *
3183
+ * Folded in as a SECOND pass, after every candidate's own call-site/
3184
+ * reassignment evidence has already settled, so which rest parameter
3185
+ * happens to be declared first in the file never changes the answer -- the
3186
+ * forward is asked once the map already holds every candidate's own-
3187
+ * evidence verdict, never a partial one.
3188
+ *
3189
+ * One-directional on purpose: the target's settled element folds into the
3190
+ * forwarder, never the reverse. `warn`'s own element is decided entirely by
3191
+ * `warn`'s OWN callers and its OWN body -- `warnOnce` forwarding into it is
3192
+ * not evidence about what `warn` does with the array, only about what
3193
+ * `warnOnce` must agree to.
3194
+ */
3195
+ const restCandidateByDeclaration = new Map(index.restParameterCandidates.map((candidate) => [candidate.declaration, candidate]));
3196
+ const isWithin = (node, ancestor) => {
3197
+ for (let current = node; current; current = current.parent)
3198
+ if (current === ancestor)
3199
+ return true;
3200
+ return false;
3201
+ };
3202
+ for (const candidate of index.restParameterCandidates) {
3203
+ const symbol = ts.isIdentifier(candidate.parameter.name) ? checker.getSymbolAtLocation(candidate.parameter.name) : undefined;
3204
+ if (!symbol)
3205
+ continue;
3206
+ for (const call of allCalls) {
3207
+ if (!isWithin(call, candidate.declaration))
3208
+ continue;
3209
+ const effectiveArguments = invocationOperands.get(call).args;
3210
+ if (!effectiveArguments || effectiveArguments.length !== 1)
3211
+ continue;
3212
+ const sole = effectiveArguments[0];
3213
+ if (!ts.isSpreadElement(sole) || !ts.isIdentifier(sole.expression) || checker.getSymbolAtLocation(sole.expression) !== symbol)
3214
+ continue;
3215
+ const resolvedTarget = resolvedCallDeclarations.get(call);
3216
+ const targetCandidate = resolvedTarget ? restCandidateByDeclaration.get(resolvedTarget) : undefined;
3217
+ if (!targetCandidate || targetCandidate.parameter === candidate.parameter)
3218
+ continue;
3219
+ const targetJoined = restElementTypes.get(targetCandidate.parameter);
3220
+ const ownJoined = restElementTypes.get(candidate.parameter);
3221
+ if (!targetJoined)
3222
+ restElementTypes.delete(candidate.parameter);
3223
+ else if (!ownJoined)
3224
+ restElementTypes.set(candidate.parameter, targetJoined);
3225
+ else {
3226
+ const combined = joinOfWrites(checker, [ownJoined, targetJoined]);
3227
+ if (combined)
3228
+ restElementTypes.set(candidate.parameter, combined);
3229
+ else
3230
+ restElementTypes.delete(candidate.parameter);
3231
+ }
3232
+ }
3233
+ }
3234
+ // Later composed censuses can retain earlier inferred facts. Their protocol
3235
+ // dependencies remain required while any dependent parameter facts survive.
3236
+ protocolLedger?.replace('parameter-bindings', [...upstreamProtocolRequirements, ...[...protocolRequirements.values()].flat()]);
3237
+ // `typeAt`, `patternReadTypeAt` and `statedTypeAt` below are the only fields
3238
+ // here that are not plain Map lookups -- see the `upstream` parameter's own
3239
+ // doc for why: they close over `publishing`/`computeStatedTypeAt`, which
3240
+ // close over this round's `valueFlow` and the whole `upstream` argument, so
3241
+ // THIS returned object is what keeps every earlier round's `ValueFlowIndex`
3242
+ // (and its `source-value-session.ts` solver session) reachable once it
3243
+ // becomes the next round's `upstream` -- and, for the settling round, for
3244
+ // the rest of the compile. `implicitArgumentsTupleAt`, `restElementTypeAt`,
3245
+ // `callDeclarationAt`, `callTargetsAt` and `argumentsAt` name neither and
3246
+ // are the ones a caller can hold onto for free.
3247
+ return {
3248
+ implicitArgumentsTupleAt: (owner) => implicitTuples.get(owner) ?? null,
3249
+ restElementTypeAt: (parameter) => restElementTypes.get(parameter) ?? null,
3250
+ callDeclarationAt: (call) => resolvedCallDeclarations.get(call) ?? null,
3251
+ explicitThisAt: (call) => pendingExplicitThisReadings.get(call) ?? null,
3252
+ callTargetsAt: (call) => callTargets.get(call) ?? null,
3253
+ typeAt: (node) => implicitArgumentsReadTypeAt(checker, node, (owner) => implicitTuples.get(owner) ?? null) ??
3254
+ (ts.isParameter(node) ? parameterTypeOf(node) : publishing.resolve(node)),
3255
+ argumentsAt: (parameter) => {
3256
+ const known = argumentsByParameter.get(parameter);
3257
+ return known === undefined || !bindings.has(parameter) ? null : [...known];
3258
+ },
3259
+ patternReadTypeAt: (element) => {
3260
+ publishing.resolve(element);
3261
+ return patternReadTypes.get(element) ?? null;
3262
+ },
3263
+ statedTypeAt: (node) => {
3264
+ // Memoized, and safe to memoize only HERE: this is the published view,
3265
+ // returned after the fixpoint has stopped, so `statedBindings` and
3266
+ // `flowCarrierBounds` no longer change and the answer for a node is
3267
+ // settled. The propagating view deliberately keeps no memo, because its
3268
+ // answers are answers to a smaller set of bindings.
3269
+ //
3270
+ // It earns the memo: this was 23% of a 58s three.js compile. Every
3271
+ // identifier in the program reaches it, and the body below asks the
3272
+ // checker for a symbol -- the single most expensive thing this compiler
3273
+ // can ask -- once per call.
3274
+ const remembered = statedTypes.get(node);
3275
+ if (remembered !== undefined)
3276
+ return remembered;
3277
+ const answer = computeStatedTypeAt(node);
3278
+ statedTypes.set(node, answer);
3279
+ return answer;
3280
+ },
3281
+ // A parameter and every UNNARROWED read of it are one storage cell. A
3282
+ // narrowed read keeps the checker's concrete arm so ordinary union loads
3283
+ // can select it from the placement rather than replacing the narrowing
3284
+ // with the full union again.
3285
+ unionArmsAt: (node) => {
3286
+ const declaration = ts.isParameter(node)
3287
+ ? node
3288
+ : ts.isIdentifier(node)
3289
+ ? checker.getSymbolAtLocation(node)?.declarations?.find(ts.isParameter)
3290
+ : undefined;
3291
+ if (declaration) {
3292
+ const arms = flowCarrierArms.get(declaration);
3293
+ const upper = flowCarrierBounds.get(declaration);
3294
+ if (arms && upper) {
3295
+ if (ts.isParameter(node))
3296
+ return arms;
3297
+ const read = checker.getTypeAtLocation(node);
3298
+ if (checker.isTypeAssignableTo(read, upper) && checker.isTypeAssignableTo(upper, read))
3299
+ return arms;
3300
+ // An optional parameter read still carries every physical object
3301
+ // arm; the checker's added nullish member only describes the
3302
+ // dynamic arm's possible absent state. Preserve the same placement
3303
+ // until control flow removes an actual container arm.
3304
+ const present = checker.getNonNullableType(read);
3305
+ if (checker.isTypeAssignableTo(present, upper) && checker.isTypeAssignableTo(upper, present))
3306
+ return arms;
3307
+ return null;
3308
+ }
3309
+ }
3310
+ return synthesizedUnionArmsAt(checker, node, unionArms);
3311
+ },
3312
+ boundCount: bindings.size + unionArms.size + flowCarrierArms.size + implicitTuples.size,
3313
+ refusals,
3314
+ refusalOf: (parameter) => lastRefusal.get(parameter) ?? null,
3315
+ debugReport: () => {
3316
+ const describeOpen = (entry) => {
3317
+ const reference = entry.reference;
3318
+ const file = reference.getSourceFile();
3319
+ const location = `${file.fileName.split('/').pop()}:${file.getLineAndCharacterOfPosition(reference.getStart()).line + 1}`;
3320
+ const parent = `${ts.SyntaxKind[reference.parent.kind]} ${reference.parent.getText().slice(0, 160)}`;
3321
+ return `${entry.kind} ${reference.getText().slice(0, 120)} in ${parent} @${location}`;
3322
+ };
3323
+ const row = (reason, subject, at, owner) => {
3324
+ const path = memberOpenUses.get(owner) ?? [];
3325
+ const open = path[0];
3326
+ const context = open ? `; ${describeOpen(open)}` : '';
3327
+ const continuation = path
3328
+ .slice(1)
3329
+ .map((entry) => ` via ${describeOpen(entry)}`)
3330
+ .join('\n');
3331
+ const file = at.getSourceFile();
3332
+ return ` ${reason} <- ${subject} @${file.fileName.split('/').pop()}:${file.getLineAndCharacterOfPosition(at.getStart()).line + 1}${context}${continuation ? `\n${continuation}` : ''}`;
3333
+ };
3334
+ const parameters = [...lastRefusal].map(([parameter, reason]) => row(reason, parameter.getText().slice(0, 80), parameter, parameter.parent));
3335
+ const frames = [...implicitRefusals].map(([owner, reason]) => row(reason, `${nameOfCallable(owner)?.getText() ?? '<anonymous>'}(arguments)`, owner, owner));
3336
+ return [...parameters, ...frames].join('\n') + '\n';
3337
+ }
3338
+ };
3339
+ };