@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,3463 @@
1
+ import ts from 'typescript';
2
+ import { logicalResultTypeOf } from './logical-result-type.js';
3
+ export { isOpenTypeForm } from './open-type-form.js';
4
+ import { forEachReachableStatement } from './reachability.js';
5
+ import { isClassSpelledSourceClass } from './flow/model.js';
6
+ import { ownedClassReceiverInventoryOf } from './flow/owned-class-receivers.js';
7
+ import { closedValueOriginAuthorityOf } from './flow/callable-reach.js';
8
+ import { seededOriginSolver } from './flow/seeded-origins.js';
9
+ import { deferredIntrinsicProtocolLedgerOf, intrinsicProtocolRequirementKind } from './deferred-intrinsic-protocols.js';
10
+ import { createPropertyKeyDomains, domainMayNameNumeric } from './property-key-domain.js';
11
+ import { unwrapErasedExpression } from './producers/erasure.js';
12
+ /**
13
+ * The type a COMPOSITE expression's own operator produces, read from its
14
+ * operands rather than invented.
15
+ *
16
+ * Extracted so `parameter-bindings.ts` and `return-bindings.ts` -- two
17
+ * censuses that both walk an expression the checker gave up on, resolving it
18
+ * from evidence the checker DOES have elsewhere -- answer a ternary's arms or
19
+ * a `+`'s operands the SAME way once, rather than each growing its own
20
+ * second, silently-drifting copy of the same three rules. That drift is this
21
+ * compiler's own named defect class (`CLAUDE.md`: "two authorities answering
22
+ * the same question differently"); this file exists so there is one.
23
+ *
24
+ * `parameter-bindings.ts`'s own `compute` does not yet call this -- this
25
+ * module does not own that file and cannot wire it in. The call this module
26
+ * was written to receive, added at the same point every other node kind is
27
+ * dispatched in that file's `compute`, is:
28
+ *
29
+ * if (ts.isConditionalExpression(node) || ts.isBinaryExpression(node) || ts.isTemplateExpression(node)) {
30
+ * return derivedExpressionType(checker, node, (operand) => known(operand) ?? resolve(operand))
31
+ * }
32
+ *
33
+ * placed anywhere before the function's final `return null`. `known`/
34
+ * `resolve` are that file's own existing closures (`createResolver`'s
35
+ * locals) -- passing them through as the `read` callback is what keeps this
36
+ * module free of any recursion or memoization of its own: every operand it
37
+ * asks about is resolved by the CALLER's own resolver, under the caller's
38
+ * own cycle guard and round-based memo, so wiring this in changes nothing
39
+ * about either file's termination or fixpoint behaviour. It only adds
40
+ * outcomes to `compute`'s dispatch that were previously `null`.
41
+ *
42
+ * ## What it refuses
43
+ *
44
+ * - A conditional (`a ? b : c`) whose arms disagree -- tested the identical
45
+ * way two call sites or two `return`s are tested elsewhere in these two
46
+ * censuses (`widestOf`): agreement is never spelling, and a union of this
47
+ * compiler's own making is a guess nobody wrote.
48
+ * - `+` over two operands where neither is provably `string`: ECMA-262
49
+ * 12.15.5 makes `+` do string concatenation the moment EITHER operand's
50
+ * runtime value is a string, and numeric addition otherwise -- so a `+`
51
+ * between an unresolved operand and anything is refused rather than
52
+ * assumed numeric. `hue2rgb`'s `p + ( q - p ) * 6 * t` is the shape this
53
+ * exists for: real arithmetic over real (parameter-derived) numbers, once
54
+ * every operand resolves, refused whole the moment one does not.
55
+ * - Every other arithmetic/bitwise operator (`-`, `*`, `/`, `%`, `**`, `&`,
56
+ * `|`, `^`, `<<`, `>>`, `>>>`) unless BOTH operands are provably in the
57
+ * number domain.
58
+ * - `&&`/`||`/`??` use `logicalResultTypeOf`, the shared partition of which
59
+ * left values the operator keeps and whether the right can contribute.
60
+ * A known class or absence combined with a boolean remains a native union;
61
+ * disagreement between those types does not erase both into checker `any`.
62
+ * Dynamic operands retain their uncertainty, and Number's falsy part keeps
63
+ * its Number type because it includes NaN as well as zero.
64
+ * - Comparison operators (`<`, `<=`, `>`, `>=`, `==`, `===`, `!=`, `!==`,
65
+ * `instanceof`, `in`) are not handled here at all: ECMA-262 fixes their
66
+ * result at `boolean` regardless of operand types, so the checker already
67
+ * answers them directly and this function is never reached for one --
68
+ * `read`/`known` at the BinaryExpression node itself already succeeded
69
+ * before either caller ever calls in here.
70
+ * - A template expression is always `string` (`ToString` is total), which
71
+ * the checker already reports without help for the identical reason; this
72
+ * module's own handling of it is a defensive fallback, never the primary
73
+ * path.
74
+ */
75
+ const numberDomain = (type) => (type.flags & ts.TypeFlags.NumberLike) !== 0;
76
+ const stringDomain = (type) => (type.flags & ts.TypeFlags.StringLike) !== 0;
77
+ /**
78
+ * Whether a type says nothing about STORAGE, and so is not evidence.
79
+ *
80
+ * The ONE copy. `parameter-bindings.ts` and `return-bindings.ts` each carried
81
+ * their own before this, with `parameter-bindings.ts`'s adding bare
82
+ * `Function` on top -- it still does, by composing with this rather than
83
+ * restating it, so the base three flags cannot drift between the three
84
+ * modules that ask this question. That module's own `isUnusableEvidence`
85
+ * carries the long-form reasoning for `any`, `void` and `never`.
86
+ *
87
+ * `annotationStatesNothing` is the fourth member and the reason this became
88
+ * shared: a value typed `object` or `{}` is not `any`, so every one of these
89
+ * copies read it as real evidence and published it -- and the parameter
90
+ * census's answer SHADOWS the return census's in the composed view
91
+ * (`composeReturnBindings`), so `function makesBag(): object { return { a: 1,
92
+ * b: 2 } }` had its call answered `object` by one census while the other had
93
+ * already derived the real record. Two authorities, one call, and
94
+ * `model/selected-signature.ts`'s fail-closed guard caught it as a withheld
95
+ * producer. A type that states nothing is not evidence here for exactly the
96
+ * reason `any` is not.
97
+ */
98
+ /**
99
+ * The destructuring TARGET an object or array literal is written against,
100
+ * when that target is a binding pattern whose type TypeScript merely IMPLIED
101
+ * from the pattern's shape: `const [a, b] = [1, 2]`, `[a, b] = [1, 2]`,
102
+ * `f([1, 2])` for `function f([x, y])`, `function g({ x } = { x: 1 })`. The
103
+ * checker contextually types such a literal from the pattern -- a tuple, or
104
+ * a record of `any` fields -- while the value is exactly what was written:
105
+ * nothing in the program stated a type, and the language binds the pattern
106
+ * off whatever arrives. `null` for a literal in any other position,
107
+ * including one whose target DECLARES its type, which stays what it states.
108
+ * The returned parameter is the census's cell for the value when the target
109
+ * is a parameter, so an empty literal can take its element from what the
110
+ * other call sites pass rather than from nothing. `element` names the nested
111
+ * binding element whose DEFAULT the literal is: that literal is stored in
112
+ * the element's own slot, never in the root parameter's.
113
+ */
114
+ export const impliedPatternTargetOf = (checker, node) => {
115
+ const parent = node.parent;
116
+ const shapeMatches = (name) => ts.isArrayLiteralExpression(node) ? ts.isArrayBindingPattern(name) : ts.isObjectBindingPattern(name);
117
+ const impliedPattern = (declaration) => shapeMatches(declaration.name) &&
118
+ declaration.type === undefined &&
119
+ (!ts.isParameter(declaration) || impliedPatternParameterOf(checker, declaration) !== null);
120
+ if (ts.isVariableDeclaration(parent) && parent.initializer === node && impliedPattern(parent))
121
+ return { parameter: null };
122
+ if (ts.isParameter(parent) && parent.initializer === node && impliedPattern(parent))
123
+ return { parameter: parent };
124
+ // A nested element's default (`[{ x } = { x: 44 }]`) is read by that
125
+ // element's own pattern, and is typed by the checker from the SAME
126
+ // silhouette the root pattern is: the root decides whether anything was
127
+ // stated.
128
+ if (ts.isBindingElement(parent) && parent.initializer === node && shapeMatches(parent.name)) {
129
+ let root = parent;
130
+ while (ts.isBindingElement(root) || ts.isArrayBindingPattern(root) || ts.isObjectBindingPattern(root))
131
+ root = root.parent;
132
+ if (ts.isParameter(root))
133
+ return impliedPatternParameterOf(checker, root) ? { parameter: root, element: parent } : null;
134
+ if (ts.isVariableDeclaration(root))
135
+ return root.type === undefined ? { parameter: null, element: parent } : null;
136
+ return null;
137
+ }
138
+ if (ts.isBinaryExpression(parent) && parent.operatorToken.kind === ts.SyntaxKind.EqualsToken && parent.right === node) {
139
+ const left = ts.isParenthesizedExpression(parent.left) ? parent.left.expression : parent.left;
140
+ const targetMatches = ts.isArrayLiteralExpression(node) ? ts.isArrayLiteralExpression(left) : ts.isObjectLiteralExpression(left);
141
+ return targetMatches ? { parameter: null } : null;
142
+ }
143
+ if ((ts.isCallExpression(parent) || ts.isNewExpression(parent)) && parent.arguments?.includes(node)) {
144
+ const position = parent.arguments.indexOf(node);
145
+ const signature = checker.getResolvedSignature(parent);
146
+ const symbol = signature?.getParameters()[position];
147
+ const declaration = symbol?.valueDeclaration;
148
+ if (!declaration || !ts.isParameter(declaration) || declaration.dotDotDotToken || !impliedPattern(declaration))
149
+ return null;
150
+ return { parameter: declaration };
151
+ }
152
+ return null;
153
+ };
154
+ /**
155
+ * The parameter whose DESTRUCTURING PATTERN `node` is or names, when the
156
+ * pattern's type is one TypeScript merely IMPLIED from the pattern's shape --
157
+ * `function f([x, y])`, `function g({ a, b })` -- with no annotation and no
158
+ * JSDoc tag. That implied type (`[any, any]`, `{ a: any; b: any }`) is a
159
+ * statement about the binding's SYNTAX, not about any value a caller passes:
160
+ * the language binds an array pattern off any iterable of any length, and an
161
+ * object pattern off any object. So for every question this compiler asks --
162
+ * does the parameter state a type (no: the census binds it from the call
163
+ * sites), is the pattern's own type real (no: it is its source's) -- the
164
+ * pattern is "unannotated", and this one predicate is what every site asks so
165
+ * the census, the layout resolver and the ABI projection agree by
166
+ * construction. `null` for a named parameter, an annotated pattern, or a
167
+ * pattern that is not a parameter's own name.
168
+ */
169
+ export const impliedPatternParameterOf = (checker, node) => {
170
+ const parameter = ts.isParameter(node)
171
+ ? node
172
+ : (ts.isArrayBindingPattern(node) || ts.isObjectBindingPattern(node)) && ts.isParameter(node.parent) && node.parent.name === node
173
+ ? node.parent
174
+ : null;
175
+ // A JSDoc function-type literal spells its parameters positionally --
176
+ // `@type {function(...number): void}` parses to a ParameterDeclaration whose
177
+ // `name` node is absent. Every predicate below reads `parameter.name`, so the
178
+ // absence has to be answered here rather than crashing the producer.
179
+ if (!parameter || !parameter.name || ts.isIdentifier(parameter.name) || parameter.type || parameter.dotDotDotToken)
180
+ return null;
181
+ if (ts.getJSDocParameterTags(parameter).length > 0 || ts.getJSDocType(parameter) !== undefined)
182
+ return null;
183
+ // A function literal can receive a real parameter type from its surrounding
184
+ // call or assignment even though the parameter has no annotation of its
185
+ // own. `pairs.map(([value, count]) => ...)` is the common case: Array#map's
186
+ // contextual signature states the tuple held by the callback parameter.
187
+ // That tuple is not the checker's pattern-shaped `[any, any]` placeholder
188
+ // and must keep its fixed positions. Otherwise the slot is flattened to an
189
+ // `Array<any>` while each binding element retains its contextual tuple
190
+ // field, leaving one value with two incompatible carriers.
191
+ const callable = parameter.parent;
192
+ if (ts.isArrowFunction(callable) || ts.isFunctionExpression(callable)) {
193
+ const contextual = checker.getContextualType(callable);
194
+ if (contextual) {
195
+ const position = callable.parameters.indexOf(parameter);
196
+ const signatures = checker.getNonNullableType(contextual).getCallSignatures();
197
+ if (signatures.length > 0 &&
198
+ signatures.every((signature) => {
199
+ const symbol = signature.getParameters()[position];
200
+ if (!symbol)
201
+ return false;
202
+ const type = checker.getTypeOfSymbolAtLocation(symbol, callable);
203
+ return (type.flags & ts.TypeFlags.Any) === 0;
204
+ }))
205
+ return null;
206
+ }
207
+ }
208
+ return parameter;
209
+ };
210
+ /**
211
+ * The implied-pattern parameter a binding element belongs to, or `null`. The
212
+ * checker types every name in `function f([w = c()])` from the pattern's own
213
+ * silhouette -- `void` here, because the default is the only evidence it has
214
+ * -- and that silhouette is the thing `impliedPatternParameterOf` exists to
215
+ * see through: a layout consult that trusts it skips the census that holds
216
+ * the callers' actual writes. An identifier declared by such an element is
217
+ * the same question asked at a read.
218
+ */
219
+ export const impliedPatternElementRootOf = (checker, node) => {
220
+ let current = node;
221
+ if (ts.isIdentifier(current)) {
222
+ const declarations = checker.getSymbolAtLocation(current)?.declarations;
223
+ current = declarations && declarations.length === 1 && declarations[0] && ts.isBindingElement(declarations[0]) ? declarations[0] : null;
224
+ }
225
+ if (!current || !ts.isBindingElement(current))
226
+ return null;
227
+ while (ts.isBindingElement(current) || ts.isArrayBindingPattern(current) || ts.isObjectBindingPattern(current))
228
+ current = current.parent;
229
+ return ts.isParameter(current) ? impliedPatternParameterOf(checker, current) : null;
230
+ };
231
+ export const isUnusableEvidence = (type) => (type.flags & (ts.TypeFlags.Any | ts.TypeFlags.Void | ts.TypeFlags.Never)) !== 0;
232
+ /**
233
+ * The single-signature call arity of a type, or `null` when it is not a
234
+ * callable with exactly one signature -- `widestOf`'s own guard against
235
+ * joining a CALLING CONVENTION by plain assignability, below.
236
+ */
237
+ const soleCallArity = (type) => {
238
+ const signatures = type.getCallSignatures();
239
+ return signatures.length === 1 ? (signatures[0]?.getParameters().length ?? null) : null;
240
+ };
241
+ /**
242
+ * The one type among these that every other fits into, or `null` when no
243
+ * single member holds them all.
244
+ *
245
+ * The ONE join every census in this compiler uses -- `parameter-bindings.ts`
246
+ * (call-site arguments, write-sets, return expressions), `return-bindings.ts`
247
+ * and `local-bindings.ts` (both by way of `derivedExpressionType`, below).
248
+ * Kept to one copy deliberately: two joins answering the same "do these
249
+ * agree" question two ways is the defect class this compiler keeps
250
+ * rediscovering (see this file's own header comment on `derivedExpressionType`).
251
+ *
252
+ * Two writes to one cell, two calls to one parameter, two `return`s from one
253
+ * function: each has to settle on a single carrier, and requiring the observed
254
+ * types to be IDENTICAL refuses a case the program answers itself. In three's
255
+ * renderer `let _gl = context;` is followed by
256
+ * `if ( _gl === null ) _gl = getContext( ... );` -- the writes are
257
+ * `NativeWebGL2RenderingContext` and `NativeWebGL2RenderingContext | null`, and
258
+ * the null check on the very next line says which one the cell is.
259
+ *
260
+ * Nothing is invented here. The answer is always one of the types the program
261
+ * itself produced, admitted only because the checker says every other observed
262
+ * type is assignable to it -- so the storage provably holds all of them. Two
263
+ * unrelated types stay refused, because there the honest answer is neither, and
264
+ * a union of this compiler's own making would be a source-shaped guess at a
265
+ * carrier rather than a reading of one.
266
+ *
267
+ * A CALLING CONVENTION is the one case plain assignability gets wrong. A
268
+ * function declaring FEWER parameters is assignable wherever one declaring
269
+ * more is expected -- TypeScript lets a callee ignore an argument it never
270
+ * named -- so joining `(event) => void` and `() => void` by assignability
271
+ * alone picks `() => void`: the least informative signature, with the
272
+ * parameter every real call site actually passes silently dropped.
273
+ * `EventDispatcher.addEventListener`'s `listener` parameter, bound once bare
274
+ * `Function` stopped being usable evidence (`parameter-bindings.ts`'s
275
+ * `isUnusableEvidence`), is exactly this: joined by assignability it
276
+ * collapsed to `() => void` while `dispatchEvent` calls every listener with
277
+ * one argument, and that reached the emitter as a real ABI mismatch. Requiring
278
+ * the SAME arity when either side is a single-signature callable is the
279
+ * narrow fix -- compatible same-arity callables still agree exactly as
280
+ * `isTypeAssignableTo` already decided; only arity itself stops being
281
+ * something a join can widen away.
282
+ */
283
+ /**
284
+ * Whether a JSDoc type node states nothing this compiler can read -- it
285
+ * resolves to `any`, `unknown`, or the checker's internal error type (which
286
+ * carries the `Any` flag).
287
+ *
288
+ * `checker.getTypeFromTypeNode` degrades to this when the node NAMES something
289
+ * the checker cannot bind at that site, and three.js's source does it
290
+ * constantly: `Box3.js` JSDoc-references `Sphere`/`Object3D`/`Triangle`/
291
+ * `Line3`/`Plane`/`Matrix3`/`Matrix4`/`Raycaster`/`Sprite` while its only
292
+ * import is `Vector3`, and every one of those resolves to `any` here.
293
+ *
294
+ * The distinction this draws is the whole point: a tag the checker CAN read is
295
+ * the program stating a type, and stops a census exactly as a TS annotation
296
+ * does. A tag that resolves to nothing is the program stating a type this
297
+ * compiler failed to resolve -- refusing the declaration for it is refusing it
298
+ * for a fact that is not there. `parameter-bindings.ts` has drawn this
299
+ * distinction since the call-site census landed; `return-bindings.ts` and
300
+ * `local-bindings.ts` did not, and bailed on the mere PRESENCE of a tag, which
301
+ * is why 48 of the app's three.js returns stayed `any` while the identical
302
+ * shape on a parameter was rescued. One predicate, three censuses.
303
+ */
304
+ /**
305
+ * The type one member of `receiver` produces, or `null` when nothing usable
306
+ * comes back.
307
+ *
308
+ * ONE copy, shared by all three censuses. `parameter-bindings.ts`,
309
+ * `local-bindings.ts` and `field-bindings.ts` each carried a private,
310
+ * byte-identical version of this -- three authorities on one question, which
311
+ * is the defect class this compiler keeps rediscovering. The bug below lived
312
+ * in all three at once precisely because fixing it in one would not have been
313
+ * visible in the others.
314
+ *
315
+ * ## The receiver's own null is not part of the question
316
+ *
317
+ * `getPropertyOfType` on a UNION answers only with properties every member
318
+ * has, and `null` has none -- so `_gl.R32F`, where `_gl` is
319
+ * `NativeWebGL2RenderingContext | null`, came back with no property at all and
320
+ * the whole chain below it refused. That is not the program being unreadable;
321
+ * it is the question being asked of the wrong type. A member read either runs
322
+ * with a non-null receiver or does not run, so what the read PRODUCES is the
323
+ * member of the non-null receiver -- exactly what TypeScript itself answers
324
+ * once flow narrowing has done its work, and `structural-layout-type.ts`
325
+ * already asks it this way.
326
+ *
327
+ * Stripping the null cannot make an answer worse: where the receiver has no
328
+ * null, `getNonNullableType` is the identity, and where it does, the
329
+ * alternative was `null` -- the boxed carrier -- rather than some other type.
330
+ *
331
+ * Measured on the three.js app: 52 boxed identifier reads hang off `WebGLTextures.js`'s
332
+ * `internalFormat` cell alone, whose every write is a `_gl.<CONSTANT>` read.
333
+ */
334
+ /**
335
+ * `resolved` when it names ONE calling convention, the convention this call
336
+ * site actually selected when it does not, and `null` when neither.
337
+ *
338
+ * A member can land on a method declaring more than one signature, and there is
339
+ * no primitive joining two overloads into one: substituting the overloaded type
340
+ * trades a `dynamic` carrier for an `unresolved` one -- lattice BOTTOM -- which
341
+ * trips `representation/verify.ts`'s `unresolved-reaches-materialization`
342
+ * guard. That guard is right; the defect is asking the question of the wrong
343
+ * node.
344
+ *
345
+ * A member read that IS a call's callee does not need its overloads joined: the
346
+ * program picked one, with its arguments, and TypeScript resolves exactly that
347
+ * with `getResolvedSignature`. Reading the type back off the selected
348
+ * signature's own declaration yields a single-signature function type -- the
349
+ * real convention this call uses. `string.split( '\n' )` in `WebGLProgram.js`
350
+ * is the whole of it: two `String.prototype.split` overloads, one call.
351
+ *
352
+ * NOT the refuted overload-selector. That one lived inside
353
+ * `resolvedCalleeSignatureType`, where the receiver had collapsed to `never` --
354
+ * so the overload set was a phantom and joining its arms answered a question
355
+ * the program never asked. Here the receiver is a real type a census bound, the
356
+ * overloads are real, and the SELECTION is TypeScript's own rather than one
357
+ * reimplemented here.
358
+ *
359
+ * An overloaded member NOT in callee position keeps its box: nothing at that
360
+ * site says which signature the value stands for, and guessing would give it a
361
+ * convention the program never chose.
362
+ */
363
+ /**
364
+ * The type an ELEMENT read produces, when the key is not a name.
365
+ *
366
+ * `lights[ i ]`, `state.probe[ j ]`, `array[ i ]` -- the census resolvers
367
+ * handled only a STRING-LITERAL key, which is a named member spelled with
368
+ * brackets. Every other key was refused, and on the three.js app that is 470 boxed
369
+ * identifier reads at the root of the chain plus everything downstream of
370
+ * them: `const light = lights[ i ]` is the single largest one.
371
+ *
372
+ * A key not known until runtime is answered by the receiver's INDEX signature,
373
+ * which is the only thing that CAN answer it -- and an array's element type is
374
+ * exactly its numeric index signature, so `Light[]` indexed by a `number`
375
+ * yields `Light` with no array special-case. Which signature to ask is decided
376
+ * by the key's own type, resolved by the caller's own operand resolver so each
377
+ * census keeps its own view of what a key expression holds.
378
+ *
379
+ * A receiver with no index signature for that key comes back `null` and stays
380
+ * boxed: the read is then something this cannot describe, and an array whose
381
+ * element type TypeScript inferred as `any` is `any` again by the
382
+ * `isUnusableEvidence` test below rather than an improvement -- except where
383
+ * the caller hands over the program's value-flow index and that index proves
384
+ * a NUMBER key can name nothing any instance of the receiver's class family
385
+ * will ever hold (`absentNumericIndexTypeOf`): the read is then `undefined`.
386
+ */
387
+ export const indexedTypeOf = (checker, receiver, key, at, flow, census = null) => {
388
+ const numeric = (key.flags & (ts.TypeFlags.Number | ts.TypeFlags.NumberLiteral)) !== 0;
389
+ const nonNullReceiver = checker.getNonNullableType(receiver);
390
+ // Numeric property keys also address a string index signature. Prefer an
391
+ // explicit numeric signature when present; its narrower value contract
392
+ // must survive alongside the string signature's broader one.
393
+ const indexed = numeric
394
+ ? (checker.getIndexTypeOfType(nonNullReceiver, ts.IndexKind.Number) ?? checker.getIndexTypeOfType(nonNullReceiver, ts.IndexKind.String))
395
+ : checker.getIndexTypeOfType(nonNullReceiver, ts.IndexKind.String);
396
+ if (indexed)
397
+ return isUnusableEvidence(indexed) ? null : indexed;
398
+ return (closedObjectLiteralIndexTypeOf(checker, nonNullReceiver, at) ??
399
+ (flow ? absentNumericIndexTypeOf(checker, flow, nonNullReceiver, key, census) : null));
400
+ };
401
+ /**
402
+ * A closed object LITERAL declares no index signature, but every string (or
403
+ * number) key reading it either lands on one of its own properties or misses
404
+ * -- exactly the fact an index signature states. `const shaderIDs = { a: '1',
405
+ * b: '2' }; shaderIDs[ material.type ]` is not a different question from
406
+ * `Record<string, string>[ k ]`; TypeScript answers it `any` only because
407
+ * nobody wrote the signature down, and the checker's own `getIndexTypeOfType`
408
+ * has nothing to hand back. Synthesizing `(join of the literal's own property
409
+ * types) | undefined` from the literal's OWN declaration is citing the object,
410
+ * not guessing at it -- the same standing `joinOfWrites` already gives a
411
+ * cell's disagreeing writes, applied to a different evidence set.
412
+ *
413
+ * Fires only when EVERY declaration of the receiver's own symbol is an object
414
+ * LITERAL expression: a class instance or a declared interface can grow
415
+ * properties (or hold others already) this reading never sees, so those stay
416
+ * refused. A missing key answers `undefined` -- the language's own reading of
417
+ * an absent property, the same precedent `structural-indexed-access.ts`
418
+ * already relies on for `T[K]` -- so the synthesized type always carries it,
419
+ * matching how the source itself is written: every real call site of this
420
+ * shape (`shaderIDs[ material.type ]` chained into `if ( shaderID )`, a
421
+ * dispatch-table `handlers[ event ]?.()`) already treats the read as
422
+ * possibly-absent.
423
+ */
424
+ const closedObjectLiteralIndexTypeOf = (checker, receiver, at) => {
425
+ const declarations = receiver.getSymbol()?.declarations;
426
+ if (!declarations || declarations.length === 0 || !declarations.every(ts.isObjectLiteralExpression))
427
+ return null;
428
+ const properties = checker.getPropertiesOfType(receiver);
429
+ if (properties.length === 0)
430
+ return null;
431
+ const valueTypes = [];
432
+ for (const property of properties) {
433
+ const type = checker.getTypeOfSymbolAtLocation(property, at);
434
+ if (isUnusableEvidence(type))
435
+ return null;
436
+ valueTypes.push(type);
437
+ }
438
+ const joined = joinOfWrites(checker, valueTypes);
439
+ return joined ? checker.getNullableType(joined, ts.TypeFlags.Undefined) : null;
440
+ };
441
+ /** The source class an INSTANCE type is an instance of -- never `typeof C`, and never a library class whose instances the host shapes. */
442
+ const sourceClassOfInstance = (type) => {
443
+ if ((type.flags & ts.TypeFlags.Object) === 0)
444
+ return null;
445
+ const target = (type.objectFlags & ts.ObjectFlags.Reference) !== 0 ? type.target : type;
446
+ if (!target.isClassOrInterface() || (target.objectFlags & ts.ObjectFlags.Class) === 0)
447
+ return null;
448
+ const declaration = target.getSymbol()?.valueDeclaration;
449
+ if (!declaration || (!ts.isClassDeclaration(declaration) && !ts.isClassExpression(declaration)))
450
+ return null;
451
+ return declaration.getSourceFile().isDeclarationFile ? null : declaration;
452
+ };
453
+ /** `ToPropertyKey` of a Number is its `ToString`: exactly the names a number key can spell. */
454
+ const isCanonicalNumericName = (name) => String(Number(name)) === name;
455
+ const KEYED_WRITE_EDGES = new Set([
456
+ 'index-assignment',
457
+ 'compound-assignment',
458
+ 'logical-assignment',
459
+ 'destructuring',
460
+ 'destructuring-default',
461
+ 'iteration-binding'
462
+ ]);
463
+ /** `Object.<method>` / `Reflect.<method>` calls that add own properties or replace a prototype. */
464
+ const OBJECT_PROPERTY_MUTATORS = ['assign', 'defineProperty', 'defineProperties', 'setPrototypeOf'];
465
+ const REFLECT_PROPERTY_MUTATORS = ['set', 'defineProperty', 'setPrototypeOf'];
466
+ const INSTANCE_PRIMITIVE_FLAGS = ts.TypeFlags.StringLike |
467
+ ts.TypeFlags.NumberLike |
468
+ ts.TypeFlags.BigIntLike |
469
+ ts.TypeFlags.BooleanLike |
470
+ ts.TypeFlags.EnumLike |
471
+ ts.TypeFlags.ESSymbolLike |
472
+ ts.TypeFlags.Void |
473
+ ts.TypeFlags.Undefined |
474
+ ts.TypeFlags.Null |
475
+ ts.TypeFlags.Never;
476
+ const EQUALITY_OPERATORS = new Set([
477
+ ts.SyntaxKind.EqualsEqualsEqualsToken,
478
+ ts.SyntaxKind.ExclamationEqualsEqualsToken,
479
+ ts.SyntaxKind.EqualsEqualsToken,
480
+ ts.SyntaxKind.ExclamationEqualsToken
481
+ ]);
482
+ const unwrapValueExpression = (expression) => {
483
+ let value = expression;
484
+ while (ts.isParenthesizedExpression(value) ||
485
+ ts.isAsExpression(value) ||
486
+ ts.isTypeAssertionExpression(value) ||
487
+ ts.isSatisfiesExpression(value) ||
488
+ ts.isNonNullExpression(value))
489
+ value = value.expression;
490
+ return value;
491
+ };
492
+ /** The outermost parenthesis or assertion wrapping `node`: where its value is actually USED. */
493
+ const outermostValueWrapperOf = (node) => {
494
+ let use = node;
495
+ while (ts.isParenthesizedExpression(use.parent) ||
496
+ ts.isAsExpression(use.parent) ||
497
+ ts.isTypeAssertionExpression(use.parent) ||
498
+ ts.isSatisfiesExpression(use.parent) ||
499
+ ts.isNonNullExpression(use.parent))
500
+ use = use.parent;
501
+ return use;
502
+ };
503
+ const NO_SETTLED_CENSUS = {};
504
+ // Keyed by the census too: a proof that consulted a settled census may pass
505
+ // where the checker-only proof refused, and the two must never share a slot.
506
+ const numericAbsenceProofs = new WeakMap();
507
+ const activeNumericAbsenceProofs = new WeakMap();
508
+ const numericAbsenceKeyDomains = new WeakMap();
509
+ const numericAbsenceDebug = process.env['GEA_INDEXED_ABSENCE_DEBUG'];
510
+ /**
511
+ * ⛔ UNSOUND MEASUREMENT ARM. `GEA_INDEXED_ABSENCE_FORCE=<class>|*` drops the
512
+ * KEYED-WRITE clause of the proof below and nothing else, so the carriers that
513
+ * clause alone is holding open can be counted before any work is spent making
514
+ * it discharge honestly. It admits a numeric-named property this program may
515
+ * really create; never set it for a build whose output is kept.
516
+ */
517
+ const numericAbsenceForce = process.env['GEA_INDEXED_ABSENCE_FORCE'];
518
+ /** `GEA_NUMERIC_ABSENCE=0` refuses the numeric-absence proof; see its use for why. */
519
+ const numericAbsenceEnabled = process.env['GEA_NUMERIC_ABSENCE'];
520
+ /**
521
+ * `undefined`, when a NUMBER key can name no property that any instance of the
522
+ * receiver's class family will ever hold; `null` when that is not proved.
523
+ *
524
+ * three's `WebGLUtils.convert( p )` ends `return ( gl[ p ] !== undefined ) ?
525
+ * gl[ p ] : null;`, `gl` a `NativeWebGL2RenderingContext` and `p` a numeric
526
+ * format constant. The context declares no member a number can name, so the
527
+ * read is `undefined` on every call -- but the checker reads it `any`, the
528
+ * return census refused `convert` whole (`return-index-signature-absent`), and
529
+ * everything downstream of it (`getInternalFormat` and the texture upload
530
+ * paths) carried a dynamic value.
531
+ *
532
+ * JavaScript reads an absent property as `undefined`, and a number key spells
533
+ * only canonical numeric strings. So the read is absent on every instance when:
534
+ *
535
+ * - every value the receiver can hold is an instance of an ENUMERATED set of
536
+ * source classes (`ownedClassReceiverInventoryOf`), none declaring an index
537
+ * signature, a member whose name is a canonical numeric string anywhere on
538
+ * its prototype chain, or a computed member whose key could spell one -- and
539
+ * none with a library base, whose instances the host shapes;
540
+ * - no write can create such a property on a family member: no named write of
541
+ * a numeric name (`o[ 3 ] = v` is one), no computed write whose key domain
542
+ * (`property-key-domain.ts`) may spell one, no `__proto__` write, and no
543
+ * reflective definition or prototype replacement -- each unless its receiver
544
+ * provably cannot hold a family member. That is
545
+ * `flow/class-family-member-read.ts`'s closure rule, restated for a NAME SET
546
+ * (it answers one identifier-shaped name and refuses numeric ones up front);
547
+ * - `Object.prototype`, the one intrinsic every such chain ends in, is never
548
+ * handed anywhere that could give it a numeric property: every mention of it
549
+ * is a member read off it or an identity comparison, every `getPrototypeOf`
550
+ * result is used the same way, and no reflective mutator is referenced other
551
+ * than as a direct callee this scan reads. `global-host-mutations.ts` states
552
+ * the general form of this taint, but it reads the settled structural mapper
553
+ * and so cannot be consulted from inside the binding fixpoint that asks this.
554
+ *
555
+ * A string key refuses outright: it can spell a declared member's own name.
556
+ * `GEA_INDEXED_ABSENCE_DEBUG=<class>|*` prints the first failing proof.
557
+ */
558
+ const absentNumericIndexTypeOf = (checker, flow, receiver, key, census) => {
559
+ const keys = key.isUnion() ? key.types : [key];
560
+ if (!keys.every((part) => (part.flags & ts.TypeFlags.NumberLike) !== 0))
561
+ return null;
562
+ const arms = receiver.isUnion() ? receiver.types : [receiver];
563
+ const censusKey = census ?? NO_SETTLED_CENSUS;
564
+ for (const arm of arms) {
565
+ const root = sourceClassOfInstance(arm);
566
+ if (!root)
567
+ return null;
568
+ let proofsByCensus = numericAbsenceProofs.get(flow);
569
+ if (!proofsByCensus)
570
+ numericAbsenceProofs.set(flow, (proofsByCensus = new WeakMap()));
571
+ let proofs = proofsByCensus.get(censusKey);
572
+ if (!proofs)
573
+ proofsByCensus.set(censusKey, (proofs = new Map()));
574
+ const ledger = deferredIntrinsicProtocolLedgerOf(flow);
575
+ let proved = proofs.get(root);
576
+ if (proved === undefined) {
577
+ let activeByCensus = activeNumericAbsenceProofs.get(flow);
578
+ if (!activeByCensus)
579
+ activeNumericAbsenceProofs.set(flow, (activeByCensus = new WeakMap()));
580
+ let active = activeByCensus.get(censusKey);
581
+ if (!active)
582
+ activeByCensus.set(censusKey, (active = new Set()));
583
+ if (active.has(root))
584
+ return null;
585
+ active.add(root);
586
+ try {
587
+ const compute = () => {
588
+ // The numeric twin of `class-family-member-read.ts`'s
589
+ // `GEA_FAMILY_MEMBER_ABSENT_KEYS`, and it exists for the same reason.
590
+ // The obligation below is DEFERRED: `requirePrototypeKeys` admits it
591
+ // on the spot (it only records into the active capture) and the
592
+ // sealed host census judges it much later. Under the `*` wildcard it
593
+ // cannot be judged true, and the result is a certification
594
+ // diagnostic that costs the WHOLE program its certificate -- a sound
595
+ // outcome, but a worse one than the boxed read this proof replaced,
596
+ // since refusing here simply leaves the read as it was. `0` refuses
597
+ // the proof outright and keeps the program compiling; the default is
598
+ // unchanged. Remove this switch when the census stops taking the
599
+ // wildcard, exactly as that sibling switch says.
600
+ // ... and the installed hosts state the same refusal for every build
601
+ // that loads them: `PluginCapabilities.refusesObjectPrototypeAbsenceProofs`.
602
+ if (numericAbsenceEnabled === '0' || ledger?.refusesObjectPrototypeAbsenceProofs === true)
603
+ return false;
604
+ // Numeric absence also depends on the complete numeric key domain of
605
+ // Object.prototype. Record that dependency in the same deferred
606
+ // ledger as the class-family proof; otherwise an opaque call may
607
+ // mutate a numeric prototype key after this provisional result.
608
+ if (ledger?.requirePrototypeKeys('Object', { numeric: true }, root) !== true)
609
+ return false;
610
+ return numericNamesAbsentFrom(checker, flow, root, census);
611
+ };
612
+ proved = ledger ? ledger.capture(compute) : { value: compute(), requirements: [] };
613
+ proofs.set(root, proved);
614
+ }
615
+ finally {
616
+ active.delete(root);
617
+ }
618
+ }
619
+ if (!proved.value || (proved.requirements.length > 0 && ledger?.include(proved.requirements) !== true))
620
+ return null;
621
+ }
622
+ return checker.getUndefinedType();
623
+ };
624
+ /**
625
+ * Whether a numeric element read is proven to miss every owned class-family
626
+ * instance. This is deliberately separate from `indexedTypeOf`: an
627
+ * `undefined` result can also come from an ordinary index signature or a
628
+ * checker-derived type, neither of which licenses bypassing the runtime
629
+ * property lookup.
630
+ */
631
+ export const numericIndexAbsenceProven = (checker, flow, receiver, key, census = null) => deferredIntrinsicProtocolLedgerOf(flow) !== null && absentNumericIndexTypeOf(checker, flow, receiver, key, census) !== null;
632
+ const numericNamesAbsentFrom = (checker, flow, root, census) => {
633
+ // `GEA_INDEXED_ABSENCE_DEBUG` used to report only the FIRST failing clause,
634
+ // because every refusal below was `return refuse(...)`: the function ended
635
+ // there, so a class refused by two keyed writes only ever showed one, and
636
+ // finding the second took a re-run with the first fixed. While watched,
637
+ // `refuse` still prints and records every site it is called at, but the loop
638
+ // and mutator-scan sites stop RETURNING on the first one and keep walking --
639
+ // the boolean this function hands back is unchanged either way, since a
640
+ // proof that refuses once is exactly as refused as one that refuses five
641
+ // times; only the reporting is exhaustive now.
642
+ const enumerating = numericAbsenceDebug !== undefined && (numericAbsenceDebug === '*' || numericAbsenceDebug === root.name?.text);
643
+ const clauseCounts = new Map();
644
+ let refused = 0;
645
+ const refuse = (reason, at) => {
646
+ if (numericAbsenceDebug !== undefined && (numericAbsenceDebug === '*' || numericAbsenceDebug === root.name?.text)) {
647
+ const file = at?.getSourceFile();
648
+ const where = at && file
649
+ ? `${file.fileName.split('/').pop()}:${file.getLineAndCharacterOfPosition(at.getStart()).line + 1} ${at.getText().slice(0, 80)}`
650
+ : '';
651
+ process.stderr.write(`[INDEXED-ABSENCE] ${root.name?.text ?? '(anonymous)'} ${reason} ${where}\n`);
652
+ }
653
+ refused += 1;
654
+ clauseCounts.set(reason, (clauseCounts.get(reason) ?? 0) + 1);
655
+ return false;
656
+ };
657
+ // Every path that ends this proof funnels through here, so the summary line
658
+ // is emitted exactly once per call, whether the proof stopped at the first
659
+ // refusal (not enumerating) or walked every site (enumerating).
660
+ const summarize = () => {
661
+ if (enumerating && refused > 0)
662
+ process.stderr.write(`[INDEXED-ABSENCE-SUMMARY] ${root.name?.text ?? '(anonymous)'} refused=${refused} clauses=${[...clauseCounts]
663
+ .map(([clause, count]) => `${clause}:${count}`)
664
+ .join(',')}\n`);
665
+ return false;
666
+ };
667
+ const inventory = ownedClassReceiverInventoryOf(checker, flow, new Set([root]));
668
+ if (!inventory) {
669
+ refuse('family-not-closed');
670
+ return summarize();
671
+ }
672
+ let domains = numericAbsenceKeyDomains.get(flow);
673
+ // Every write the index holds is already reachable: the flow walk prunes
674
+ // unreachable members before it records anything.
675
+ if (!domains)
676
+ numericAbsenceKeyDomains.set(flow, (domains = createPropertyKeyDomains(checker, flow, () => true)));
677
+ const keys = domains;
678
+ // The family, each member's source ancestry, and what each declares.
679
+ const family = new Map();
680
+ const ancestorsOf = new Map();
681
+ const chain = new Set();
682
+ // Each member of the inventory is an independent question -- a bad member B
683
+ // says nothing about member A -- so while enumerating, a refused member is
684
+ // skipped (it contributes nothing to `family`/`ancestorsOf`/`chain`, which
685
+ // is safe: every later reader of those maps already tolerates an absent
686
+ // entry) rather than ending the whole proof before the rest are checked.
687
+ for (const member of inventory.classes) {
688
+ const symbol = member.name ? checker.getSymbolAtLocation(member.name) : checker.getTypeAtLocation(member).getSymbol();
689
+ const instance = symbol && checker.getDeclaredTypeOfSymbol(symbol);
690
+ if (!instance?.isClassOrInterface()) {
691
+ refuse('family-member-untyped', member);
692
+ if (!enumerating)
693
+ return summarize();
694
+ continue;
695
+ }
696
+ if (checker.getIndexInfosOfType(instance).length > 0) {
697
+ refuse('index-signature', member);
698
+ if (!enumerating)
699
+ return summarize();
700
+ continue;
701
+ }
702
+ const numeric = checker.getPropertiesOfType(instance).find((property) => isCanonicalNumericName(property.name));
703
+ if (numeric) {
704
+ refuse('numeric-member', numeric.valueDeclaration ?? member);
705
+ if (!enumerating)
706
+ return summarize();
707
+ continue;
708
+ }
709
+ const ancestors = new Set();
710
+ let libraryBase = null;
711
+ const visit = (type) => {
712
+ for (const base of checker.getBaseTypes(type)) {
713
+ const declaration = sourceClassOfInstance(base);
714
+ if (!declaration) {
715
+ libraryBase ??= member;
716
+ return;
717
+ }
718
+ if (ancestors.has(declaration))
719
+ continue;
720
+ ancestors.add(declaration);
721
+ const target = (base.objectFlags & ts.ObjectFlags.Reference) !== 0 ? base.target : base;
722
+ if (target.isClassOrInterface())
723
+ visit(target);
724
+ }
725
+ };
726
+ visit(instance);
727
+ if (libraryBase) {
728
+ refuse('library-base', libraryBase);
729
+ if (!enumerating)
730
+ return summarize();
731
+ continue;
732
+ }
733
+ family.set(member, instance);
734
+ ancestorsOf.set(member, ancestors);
735
+ chain.add(member);
736
+ for (const ancestor of ancestors)
737
+ chain.add(ancestor);
738
+ }
739
+ for (const owner of chain) {
740
+ // The question is whether any member of the chain is spelled with a
741
+ // COMPUTED name that may be numeric. A constructor function's equivalent is
742
+ // `this[ expr ] = v` in its body, which this walk does not read -- so it
743
+ // cannot say there is none.
744
+ if (!isClassSpelledSourceClass(owner)) {
745
+ refuse('constructor-function-computed-members', owner);
746
+ if (!enumerating)
747
+ return summarize();
748
+ continue;
749
+ }
750
+ for (const element of owner.members) {
751
+ const name = element.name;
752
+ if (!name || !ts.isComputedPropertyName(name))
753
+ continue;
754
+ if ((ts.getCombinedModifierFlags(element) & ts.ModifierFlags.Static) !== 0)
755
+ continue;
756
+ if (domainMayNameNumeric(keys.of(name.expression))) {
757
+ refuse('computed-member', element);
758
+ if (!enumerating)
759
+ return summarize();
760
+ }
761
+ }
762
+ }
763
+ // "May hold a family member", from the receiver's static type and its
764
+ // allocation -- the same two questions `class-family-member-read.ts` asks.
765
+ const holdsFamily = (declaration) => family.has(declaration) || [...ancestorsOf.values()].some((ancestors) => ancestors.has(declaration));
766
+ // The checker's type, or -- only where the checker says nothing -- the
767
+ // settled census's. Three stores through receivers the checker types `any`
768
+ // (`currentRenderState.state.transmissionRenderTarget[ camera.id ] = new
769
+ // WebGLRenderTarget(...)`, `programs[ programCacheKey ] = program`); the
770
+ // census types the first `Record<string, WebGLRenderTarget | undefined>`,
771
+ // a carrier no class instance can be stored into, so the write cannot land
772
+ // on a family member. Those two writes alone held `WebGLUtils.convert`'s
773
+ // result -- and 409 results downstream of it -- dynamic on the three.js app.
774
+ const typeOf = (expression) => {
775
+ const own = checker.getTypeAtLocation(expression);
776
+ if (!census || (own.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) === 0)
777
+ return own;
778
+ const settled = census.typeAt(expression);
779
+ return settled && (settled.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) === 0 ? settled : own;
780
+ };
781
+ const typeMayHold = (type, depth = 0) => {
782
+ if (depth > 8 || (type.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) !== 0)
783
+ return true;
784
+ if (type.isUnionOrIntersection())
785
+ return type.types.some((part) => typeMayHold(part, depth + 1));
786
+ if ((type.flags & ts.TypeFlags.TypeParameter) !== 0) {
787
+ const constraint = checker.getBaseConstraintOfType(type);
788
+ return constraint === undefined || constraint === type || typeMayHold(constraint, depth + 1);
789
+ }
790
+ if ((type.flags & INSTANCE_PRIMITIVE_FLAGS) !== 0)
791
+ return false;
792
+ if ((type.flags & (ts.TypeFlags.Object | ts.TypeFlags.NonPrimitive)) === 0)
793
+ return true;
794
+ const declaration = sourceClassOfInstance(type);
795
+ if (declaration)
796
+ return holdsFamily(declaration);
797
+ return [...family.values()].some((instance) => checker.isTypeAssignableTo(instance, type));
798
+ };
799
+ // The shared source-slot proof accounts for replacements and receiver
800
+ // escapes; a descriptor inventory or a field annotation does not. Retain
801
+ // that proof context across this query's parameter and field continuations.
802
+ let origins;
803
+ const sourcesOf = (anchor) => (origins ??= closedValueOriginAuthorityOf(checker, flow, anchor));
804
+ const through = (values) => ({
805
+ admitted: true,
806
+ seed: false,
807
+ dependencies: values.map(unwrapValueExpression)
808
+ });
809
+ const excluded = (yes) => ({ admitted: yes, seed: yes, dependencies: [] });
810
+ // A recursive alias must be grounded in an actual disjoint allocation.
811
+ // Revisiting an active expression is not itself evidence of disjointness.
812
+ const nonFamilyOrigin = seededOriginSolver((value) => {
813
+ if (ts.isObjectLiteralExpression(value) ||
814
+ ts.isArrayLiteralExpression(value) ||
815
+ ts.isFunctionExpression(value) ||
816
+ ts.isArrowFunction(value) ||
817
+ ts.isRegularExpressionLiteral(value))
818
+ return excluded(true);
819
+ if (ts.isConditionalExpression(value))
820
+ return through([value.whenTrue, value.whenFalse]);
821
+ if (ts.isBinaryExpression(value) &&
822
+ [ts.SyntaxKind.BarBarToken, ts.SyntaxKind.AmpersandAmpersandToken, ts.SyntaxKind.QuestionQuestionToken].includes(value.operatorToken.kind))
823
+ return through([value.left, value.right]);
824
+ if (ts.isNewExpression(value)) {
825
+ const constructed = checker.getTypeAtLocation(value);
826
+ const declaration = sourceClassOfInstance(constructed);
827
+ if (declaration) {
828
+ const allocations = sourcesOf(value).classAllocationsOf(value);
829
+ return excluded(allocations !== null && [...allocations.classes].every((owner) => !holdsFamily(owner)));
830
+ }
831
+ const callee = checker.getSymbolAtLocation(value.expression)?.valueDeclaration;
832
+ return excluded(callee !== undefined && callee.getSourceFile().isDeclarationFile && !typeMayHold(constructed));
833
+ }
834
+ if (ts.isPropertyAccessExpression(value) || ts.isElementAccessExpression(value)) {
835
+ const stored = sourcesOf(value).fieldValuesOf(value);
836
+ return stored !== null && stored.length > 0 ? through(stored) : excluded(false);
837
+ }
838
+ if (!ts.isIdentifier(value))
839
+ return excluded(!typeMayHold(typeOf(value)));
840
+ const declaration = flow.targetOf(value)?.declaration;
841
+ if (declaration && ts.isParameter(declaration)) {
842
+ const incoming = sourcesOf(value).parameterValuesOf(declaration);
843
+ return incoming !== null && incoming.length > 0 ? through(incoming) : excluded(false);
844
+ }
845
+ if (!declaration || !ts.isVariableDeclaration(declaration))
846
+ return excluded(false);
847
+ const values = sourcesOf(value).bindingValuesOf(declaration);
848
+ return values !== null && values.length > 0 ? through(values) : excluded(false);
849
+ });
850
+ const excludesFamily = (expression) => nonFamilyOrigin(unwrapValueExpression(expression)) === 'allocated';
851
+ const mayHold = (expression) => !expression || (typeMayHold(typeOf(expression)) && !excludesFamily(expression));
852
+ const keyMayNameNumeric = (expression) => expression === undefined || ts.isSpreadElement(expression) || domainMayNameNumeric(keys.of(expression));
853
+ /** Whether an `Object.assign` source or `defineProperties` map can carry a numeric key: only a spread-free literal says it cannot. */
854
+ const literalMayNameNumeric = (expression) => {
855
+ const literal = expression && unwrapValueExpression(expression);
856
+ if (!literal || !ts.isObjectLiteralExpression(literal))
857
+ return true;
858
+ return literal.properties.some((property) => {
859
+ if (ts.isSpreadAssignment(property))
860
+ return true;
861
+ const key = property.name;
862
+ if (!key)
863
+ return true;
864
+ if (ts.isComputedPropertyName(key))
865
+ return domainMayNameNumeric(keys.of(key.expression));
866
+ if (ts.isIdentifier(key) || ts.isStringLiteralLike(key) || ts.isNumericLiteral(key))
867
+ return isCanonicalNumericName(key.text);
868
+ return true;
869
+ });
870
+ };
871
+ // Named, keyed and prototype writes.
872
+ for (const write of flow.allWrites) {
873
+ if (write.slot === 'member' && write.member !== null) {
874
+ // A delete never creates a property; a literal's own member is not an
875
+ // expando on an object that already existed; a binding pattern's member
876
+ // edge is a READ of its source.
877
+ if (write.edge === 'delete')
878
+ continue;
879
+ if (ts.isPropertyAssignment(write.site) || ts.isShorthandPropertyAssignment(write.site))
880
+ continue;
881
+ if ((write.edge === 'destructuring' || write.edge === 'destructuring-default') && ts.isBindingElement(write.site))
882
+ continue;
883
+ if (write.member === '__proto__' && mayHold(write.naming)) {
884
+ refuse('prototype-write', write.site);
885
+ if (!enumerating)
886
+ return summarize();
887
+ }
888
+ if (isCanonicalNumericName(write.member) && mayHold(write.naming)) {
889
+ refuse('numeric-member-write', write.site);
890
+ if (!enumerating)
891
+ return summarize();
892
+ }
893
+ continue;
894
+ }
895
+ if (write.slot !== 'element' || !KEYED_WRITE_EDGES.has(write.edge))
896
+ continue;
897
+ const receiver = write.naming;
898
+ const access = receiver?.parent;
899
+ if (!receiver || !access || !ts.isElementAccessExpression(access) || access.expression !== receiver) {
900
+ if (mayHold(receiver)) {
901
+ refuse('keyed-write-unattributed', write.site);
902
+ if (!enumerating)
903
+ return summarize();
904
+ }
905
+ continue;
906
+ }
907
+ // This is the shape the debug arm was built for: the three.js app's `programs[
908
+ // programCacheKey ] = program` and `state.transmissionRenderTarget[
909
+ // camera.id ] = ...` are TWO independent keyed writes onto the same class
910
+ // family, and the old first-refusal-ends-the-proof behavior meant a run
911
+ // could only ever report one of them.
912
+ if (domainMayNameNumeric(keys.of(access.argumentExpression)) && mayHold(receiver)) {
913
+ if (numericAbsenceForce === undefined || (numericAbsenceForce !== '*' && numericAbsenceForce !== root.name?.text)) {
914
+ refuse('keyed-write', write.site);
915
+ if (!enumerating)
916
+ return summarize();
917
+ continue;
918
+ }
919
+ refuse('keyed-write(FORCED-PAST)', write.site);
920
+ }
921
+ }
922
+ // Reflective definitions and prototype replacement, at every direct call.
923
+ for (const { call } of flow.calls) {
924
+ if (!ts.isCallExpression(call))
925
+ continue;
926
+ const callee = unwrapValueExpression(call.expression);
927
+ if (!ts.isPropertyAccessExpression(callee))
928
+ continue;
929
+ const method = callee.name.text;
930
+ const owner = callee.expression;
931
+ const onObject = OBJECT_PROPERTY_MUTATORS.includes(method) && isGlobalObjectConstructor(checker, owner, checker.getTypeAtLocation(owner));
932
+ const onReflect = !onObject && REFLECT_PROPERTY_MUTATORS.includes(method) && isStandardGlobalValue(checker, owner, 'Reflect');
933
+ if (!onObject && !onReflect)
934
+ continue;
935
+ const args = call.arguments;
936
+ // A spread hides which argument is the target and which the key, so the
937
+ // rest of this call's own checks below (which index into `args`
938
+ // positionally) cannot run meaningfully -- skip straight to the next call
939
+ // even while enumerating.
940
+ if (args.some(ts.isSpreadElement)) {
941
+ refuse('reflective-spread-arguments', call);
942
+ if (!enumerating)
943
+ return summarize();
944
+ continue;
945
+ }
946
+ const target = args[0];
947
+ if (method === 'setPrototypeOf') {
948
+ if (mayHold(target)) {
949
+ refuse('prototype-replaced', call);
950
+ if (!enumerating)
951
+ return summarize();
952
+ }
953
+ continue;
954
+ }
955
+ if (method === 'assign') {
956
+ if (mayHold(target) && args.slice(1).some(literalMayNameNumeric)) {
957
+ refuse('object-assign', call);
958
+ if (!enumerating)
959
+ return summarize();
960
+ }
961
+ continue;
962
+ }
963
+ if (method === 'defineProperties') {
964
+ if (mayHold(target) && literalMayNameNumeric(args[1])) {
965
+ refuse('define-properties', call);
966
+ if (!enumerating)
967
+ return summarize();
968
+ }
969
+ continue;
970
+ }
971
+ // `defineProperty` (either owner) and `Reflect.set`, whose optional fourth
972
+ // argument is the receiver a data property is created on.
973
+ const receivers = method === 'set' && args[3] ? [target, args[3]] : [target];
974
+ if (receivers.some(mayHold) && keyMayNameNumeric(args[1])) {
975
+ refuse(`reflective-${method}`, call);
976
+ if (!enumerating)
977
+ return summarize();
978
+ }
979
+ }
980
+ // The intrinsics themselves, resolved from the standard library -- a program
981
+ // that shadows `Object` or `Reflect` at the root's own scope proves nothing.
982
+ const intrinsic = (name) => {
983
+ const symbol = checker.resolveName(name, root, ts.SymbolFlags.Value, false);
984
+ const declaration = symbol?.valueDeclaration ?? symbol?.declarations?.[0];
985
+ return symbol && declaration?.getSourceFile().isDeclarationFile ? checker.getTypeOfSymbolAtLocation(symbol, root) : null;
986
+ };
987
+ const objectConstructor = intrinsic('Object');
988
+ const reflect = intrinsic('Reflect');
989
+ const objectPrototype = objectConstructor?.getProperty('prototype');
990
+ if (!objectConstructor || !reflect || !objectPrototype) {
991
+ refuse('intrinsics-unresolved');
992
+ return summarize();
993
+ }
994
+ const isDirectCallee = (reference) => {
995
+ const access = reference.parent;
996
+ return (ts.isPropertyAccessExpression(access) &&
997
+ access.name === reference &&
998
+ ts.isCallExpression(outermostValueWrapperOf(access).parent) &&
999
+ unwrapValueExpression(outermostValueWrapperOf(access).parent.expression) === access);
1000
+ };
1001
+ // `const define = Object.defineProperty; define( o, 0, d )` calls a mutator
1002
+ // the scan above never sees as one.
1003
+ const mutators = [
1004
+ ...OBJECT_PROPERTY_MUTATORS.map((method) => objectConstructor.getProperty(method)),
1005
+ ...REFLECT_PROPERTY_MUTATORS.map((method) => reflect.getProperty(method))
1006
+ ];
1007
+ for (const symbol of mutators) {
1008
+ if (!symbol)
1009
+ continue;
1010
+ for (const reference of flow.memberReferencesToSymbol(symbol)) {
1011
+ if (!isDirectCallee(reference)) {
1012
+ refuse('reflective-mutator-escapes', reference);
1013
+ if (!enumerating)
1014
+ return summarize();
1015
+ }
1016
+ }
1017
+ }
1018
+ /** A value that may be `Object.prototype` is only ever read from or compared. */
1019
+ const onlyReadOrCompared = (value) => {
1020
+ const use = outermostValueWrapperOf(value);
1021
+ const parent = use.parent;
1022
+ return ((ts.isPropertyAccessExpression(parent) && parent.expression === use) ||
1023
+ (ts.isBinaryExpression(parent) && EQUALITY_OPERATORS.has(parent.operatorToken.kind)));
1024
+ };
1025
+ for (const reference of flow.memberReferencesToSymbol(objectPrototype)) {
1026
+ const access = reference.parent;
1027
+ if (!ts.isPropertyAccessExpression(access) || access.name !== reference || !onlyReadOrCompared(access)) {
1028
+ refuse('object-prototype-escapes', reference);
1029
+ if (!enumerating)
1030
+ return summarize();
1031
+ }
1032
+ }
1033
+ for (const symbol of [objectConstructor.getProperty('getPrototypeOf'), reflect.getProperty('getPrototypeOf')]) {
1034
+ if (!symbol)
1035
+ continue;
1036
+ for (const reference of flow.memberReferencesToSymbol(symbol)) {
1037
+ if (!isDirectCallee(reference) || !onlyReadOrCompared(outermostValueWrapperOf(reference.parent).parent)) {
1038
+ refuse('prototype-read-escapes', reference);
1039
+ if (!enumerating)
1040
+ return summarize();
1041
+ }
1042
+ }
1043
+ }
1044
+ if (refused > 0)
1045
+ return summarize();
1046
+ return true;
1047
+ };
1048
+ const closedLiteralAbsenceProofs = new WeakMap();
1049
+ const closedLiteralAbsenceDebug = process.env['GEA_CLOSED_LITERAL_ABSENCE_DEBUG'];
1050
+ /** Same question `typeMayHold` (above, in `numericNamesAbsentFrom`) asks for a class family, restated for ONE structural record: object literals have no subclasses, so "may hold" is plain assignability. */
1051
+ const literalMayHoldType = (checker, candidate, record, depth = 0) => {
1052
+ if (depth > 8 || (candidate.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) !== 0)
1053
+ return true;
1054
+ if (candidate.isUnionOrIntersection())
1055
+ return candidate.types.some((part) => literalMayHoldType(checker, part, record, depth + 1));
1056
+ if ((candidate.flags & ts.TypeFlags.TypeParameter) !== 0) {
1057
+ const constraint = checker.getBaseConstraintOfType(candidate);
1058
+ return constraint === undefined || constraint === candidate || literalMayHoldType(checker, constraint, record, depth + 1);
1059
+ }
1060
+ if ((candidate.flags & INSTANCE_PRIMITIVE_FLAGS) !== 0)
1061
+ return false;
1062
+ if ((candidate.flags & (ts.TypeFlags.Object | ts.TypeFlags.NonPrimitive)) === 0)
1063
+ return true;
1064
+ // Is ONE OF OUR OWN instances assignable to the write's receiver -- could the
1065
+ // receiver, per its own declared shape, actually be holding this record?
1066
+ return checker.isTypeAssignableTo(record, candidate);
1067
+ };
1068
+ /**
1069
+ * Whether NO write anywhere in the program can put `name` on `record` --
1070
+ * `numericNamesAbsentFrom`'s write inventory (named/keyed writes, `Object`/
1071
+ * `Reflect` mutators, prototype escapes), restated for one closed object
1072
+ * LITERAL instead of an owned class family. There is no inheritance chain to
1073
+ * close and no constructor-function computed-member case to refuse, because a
1074
+ * literal has neither; there is still every other way a program can hand a
1075
+ * plain object a new key.
1076
+ */
1077
+ const closedLiteralMemberAbsent = (checker, flow, record, name, at) => {
1078
+ const refuse = (reason, site) => {
1079
+ if (closedLiteralAbsenceDebug !== undefined) {
1080
+ const file = site?.getSourceFile();
1081
+ const where = site && file
1082
+ ? ` ${file.fileName.split('/').pop()}:${file.getLineAndCharacterOfPosition(site.getStart()).line + 1} ${site.getText().slice(0, 80)}`
1083
+ : '';
1084
+ process.stderr.write(`[CLOSED-LITERAL-ABSENCE] ${name} ${reason}${where}\n`);
1085
+ }
1086
+ return false;
1087
+ };
1088
+ // Only a class instance or a declared interface can grow members this
1089
+ // reading never sees; a literal's own declaration(s) are the whole story.
1090
+ const declarations = record.getSymbol()?.declarations;
1091
+ if (!declarations || declarations.length === 0 || !declarations.every(ts.isObjectLiteralExpression))
1092
+ return refuse('not-a-closed-literal');
1093
+ // An index signature already answers every named key through `indexedTypeOf`;
1094
+ // reaching here at all means none was stated, but a defensive check keeps
1095
+ // this proof correct even if that changes upstream.
1096
+ if (checker.getIndexInfosOfType(record).length > 0)
1097
+ return refuse('index-signature');
1098
+ const domains = createPropertyKeyDomains(checker, flow, () => true);
1099
+ const typeOf = (expression) => checker.getTypeAtLocation(expression);
1100
+ const mayHold = (expression) => !!expression && literalMayHoldType(checker, typeOf(expression), record);
1101
+ const keyMayName = (expression) => expression === undefined || ts.isSpreadElement(expression) || domains.mayName(domains.of(expression), name);
1102
+ /** Whether an `Object.assign` source or `defineProperties` map can carry `name`: only a spread-free literal says it cannot. */
1103
+ const literalMayName = (expression) => {
1104
+ const literal = expression && unwrapValueExpression(expression);
1105
+ if (!literal || !ts.isObjectLiteralExpression(literal))
1106
+ return true;
1107
+ return literal.properties.some((property) => {
1108
+ if (ts.isSpreadAssignment(property))
1109
+ return true;
1110
+ const key = property.name;
1111
+ if (!key)
1112
+ return true;
1113
+ if (ts.isComputedPropertyName(key))
1114
+ return domains.mayName(domains.of(key.expression), name);
1115
+ if (ts.isIdentifier(key) || ts.isStringLiteralLike(key) || ts.isNumericLiteral(key))
1116
+ return key.text === name;
1117
+ return true;
1118
+ });
1119
+ };
1120
+ // Named, keyed and prototype writes.
1121
+ for (const write of flow.allWrites) {
1122
+ if (write.slot === 'member' && write.member !== null) {
1123
+ // A delete never creates a property; a literal's own member is not an
1124
+ // expando on an object that already existed; a binding pattern's member
1125
+ // edge is a READ of its source.
1126
+ if (write.edge === 'delete')
1127
+ continue;
1128
+ if (ts.isPropertyAssignment(write.site) || ts.isShorthandPropertyAssignment(write.site))
1129
+ continue;
1130
+ if ((write.edge === 'destructuring' || write.edge === 'destructuring-default') && ts.isBindingElement(write.site))
1131
+ continue;
1132
+ if (write.member === '__proto__' && mayHold(write.naming))
1133
+ return refuse('prototype-write', write.site);
1134
+ if (write.member === name && mayHold(write.naming))
1135
+ return refuse('named-write', write.site);
1136
+ continue;
1137
+ }
1138
+ if (write.slot !== 'element' || !KEYED_WRITE_EDGES.has(write.edge))
1139
+ continue;
1140
+ const target = write.naming;
1141
+ const access = target?.parent;
1142
+ if (!target || !access || !ts.isElementAccessExpression(access) || access.expression !== target) {
1143
+ if (mayHold(target))
1144
+ return refuse('keyed-write-unattributed', write.site);
1145
+ continue;
1146
+ }
1147
+ if (keyMayName(access.argumentExpression) && mayHold(target))
1148
+ return refuse('keyed-write', write.site);
1149
+ }
1150
+ // Reflective definitions and prototype replacement, at every direct call.
1151
+ for (const { call } of flow.calls) {
1152
+ if (!ts.isCallExpression(call))
1153
+ continue;
1154
+ const callee = unwrapValueExpression(call.expression);
1155
+ if (!ts.isPropertyAccessExpression(callee))
1156
+ continue;
1157
+ const method = callee.name.text;
1158
+ const owner = callee.expression;
1159
+ const onObject = OBJECT_PROPERTY_MUTATORS.includes(method) && isGlobalObjectConstructor(checker, owner, checker.getTypeAtLocation(owner));
1160
+ const onReflect = !onObject && REFLECT_PROPERTY_MUTATORS.includes(method) && isStandardGlobalValue(checker, owner, 'Reflect');
1161
+ if (!onObject && !onReflect)
1162
+ continue;
1163
+ const args = call.arguments;
1164
+ // A spread hides which argument is the target and which the key.
1165
+ if (args.some(ts.isSpreadElement))
1166
+ return refuse('reflective-spread-arguments', call);
1167
+ const target = args[0];
1168
+ if (method === 'setPrototypeOf') {
1169
+ if (mayHold(target))
1170
+ return refuse('prototype-replaced', call);
1171
+ continue;
1172
+ }
1173
+ if (method === 'assign') {
1174
+ if (mayHold(target) && args.slice(1).some(literalMayName))
1175
+ return refuse('object-assign', call);
1176
+ continue;
1177
+ }
1178
+ if (method === 'defineProperties') {
1179
+ if (mayHold(target) && literalMayName(args[1]))
1180
+ return refuse('define-properties', call);
1181
+ continue;
1182
+ }
1183
+ // `defineProperty` (either owner) and `Reflect.set`, whose optional fourth
1184
+ // argument is the receiver a data property is created on.
1185
+ const receivers = method === 'set' && args[3] ? [target, args[3]] : [target];
1186
+ if (receivers.some(mayHold) && keyMayName(args[1]))
1187
+ return refuse(`reflective-${method}`, call);
1188
+ }
1189
+ // The intrinsics themselves, resolved from the standard library -- a program
1190
+ // that shadows `Object` or `Reflect` at the root's own scope proves nothing.
1191
+ const intrinsic = (symbolName) => {
1192
+ const symbol = checker.resolveName(symbolName, at, ts.SymbolFlags.Value, false);
1193
+ const declaration = symbol?.valueDeclaration ?? symbol?.declarations?.[0];
1194
+ return symbol && declaration?.getSourceFile().isDeclarationFile ? checker.getTypeOfSymbolAtLocation(symbol, at) : null;
1195
+ };
1196
+ const objectConstructor = intrinsic('Object');
1197
+ const reflect = intrinsic('Reflect');
1198
+ const objectPrototype = objectConstructor?.getProperty('prototype');
1199
+ if (!objectConstructor || !reflect || !objectPrototype)
1200
+ return refuse('intrinsics-unresolved');
1201
+ const isDirectCallee = (reference) => {
1202
+ const access = reference.parent;
1203
+ return (ts.isPropertyAccessExpression(access) &&
1204
+ access.name === reference &&
1205
+ ts.isCallExpression(outermostValueWrapperOf(access).parent) &&
1206
+ unwrapValueExpression(outermostValueWrapperOf(access).parent.expression) === access);
1207
+ };
1208
+ // `const define = Object.defineProperty; define( o, 0, d )` calls a mutator
1209
+ // the scan above never sees as one.
1210
+ const mutators = [
1211
+ ...OBJECT_PROPERTY_MUTATORS.map((method) => objectConstructor.getProperty(method)),
1212
+ ...REFLECT_PROPERTY_MUTATORS.map((method) => reflect.getProperty(method))
1213
+ ];
1214
+ for (const symbol of mutators) {
1215
+ if (!symbol)
1216
+ continue;
1217
+ for (const reference of flow.memberReferencesToSymbol(symbol)) {
1218
+ if (!isDirectCallee(reference))
1219
+ return refuse('reflective-mutator-escapes', reference);
1220
+ }
1221
+ }
1222
+ /** A value that may be `Object.prototype` is only ever read from or compared. */
1223
+ const onlyReadOrCompared = (value) => {
1224
+ const use = outermostValueWrapperOf(value);
1225
+ const parent = use.parent;
1226
+ return ((ts.isPropertyAccessExpression(parent) && parent.expression === use) ||
1227
+ (ts.isBinaryExpression(parent) && EQUALITY_OPERATORS.has(parent.operatorToken.kind)));
1228
+ };
1229
+ for (const reference of flow.memberReferencesToSymbol(objectPrototype)) {
1230
+ const access = reference.parent;
1231
+ if (!ts.isPropertyAccessExpression(access) || access.name !== reference || !onlyReadOrCompared(access))
1232
+ return refuse('object-prototype-escapes', reference);
1233
+ }
1234
+ for (const symbol of [objectConstructor.getProperty('getPrototypeOf'), reflect.getProperty('getPrototypeOf')]) {
1235
+ if (!symbol)
1236
+ continue;
1237
+ for (const reference of flow.memberReferencesToSymbol(symbol)) {
1238
+ if (!isDirectCallee(reference) || !onlyReadOrCompared(outermostValueWrapperOf(reference.parent).parent))
1239
+ return refuse('prototype-read-escapes', reference);
1240
+ }
1241
+ }
1242
+ return true;
1243
+ };
1244
+ const CLOSED_LITERAL_ABSENCE_LEDGER_SCOPE = 'closed-literal-member-absence';
1245
+ const publishedClosedLiteralAbsenceRequirements = new WeakMap();
1246
+ /**
1247
+ * Keep a surviving answer's intrinsic obligations -- `flow/class-family-member-read.ts`'s
1248
+ * own `publish` restated for this proof. `ledger.include` only reaches an
1249
+ * active `capture` frame, which a binding census's `propertyTypeOf` does not
1250
+ * open around this ask (unlike the producer-context hook, which does); without
1251
+ * a `capture`-independent path the obligation this proof raises would just be
1252
+ * dropped the first time a census asks outside one, and the answer it is
1253
+ * attached to would be unsound. `ledger.replace` writes straight into the
1254
+ * ledger's persistent scope map, so it works regardless.
1255
+ */
1256
+ const publishClosedLiteralAbsenceRequirements = (ledger, requirements) => {
1257
+ if (requirements.length === 0)
1258
+ return;
1259
+ ledger.include(requirements);
1260
+ let held = publishedClosedLiteralAbsenceRequirements.get(ledger);
1261
+ if (!held)
1262
+ publishedClosedLiteralAbsenceRequirements.set(ledger, (held = { all: [], seen: new Map() }));
1263
+ let added = false;
1264
+ for (const requirement of requirements) {
1265
+ let kinds = held.seen.get(requirement.location);
1266
+ if (!kinds)
1267
+ held.seen.set(requirement.location, (kinds = new Set()));
1268
+ const kind = `${requirement.intrinsic}.${intrinsicProtocolRequirementKind(requirement) ?? ''}`;
1269
+ if (kinds.has(kind))
1270
+ continue;
1271
+ kinds.add(kind);
1272
+ held.all.push(requirement);
1273
+ added = true;
1274
+ }
1275
+ if (added)
1276
+ ledger.replace(CLOSED_LITERAL_ABSENCE_LEDGER_SCOPE, held.all);
1277
+ };
1278
+ /**
1279
+ * `undefined`, when a NAMED key is proven absent from a CLOSED object-literal
1280
+ * record and nothing in the program can add it -- the same fact
1281
+ * `flow/class-family-member-read.ts` states for an absent CLASS key, restated
1282
+ * for a record with no class behind it at all.
1283
+ *
1284
+ * three's `getProgramCacheKey( parameters )` pushes
1285
+ * `parameters.morphAttributeCount` into the program's cache-key array.
1286
+ * `parameters` is the 135-field literal `getParameters` returns, and
1287
+ * `morphAttributeCount` is not one of its fields -- not written anywhere in
1288
+ * the file, not anywhere in three's whole source (measured: the only mention
1289
+ * is this one read). JavaScript reads an absent own property as `undefined`,
1290
+ * falling through to `Object.prototype.morphAttributeCount`, which nothing
1291
+ * defines -- so the push is `undefined` on every call, while the checker's own
1292
+ * answer for the read (an unknown member of an object type with no index
1293
+ * signature) is `any`.
1294
+ *
1295
+ * `closedObjectLiteralIndexTypeOf` already states this fact for an
1296
+ * unresolved KEY read on a closed literal, from the literal's own declared
1297
+ * properties alone. A NAMED read commits to one key (`morphAttributeCount`)
1298
+ * up front, so unlike an index read it can be wrong about a SPECIFIC name if
1299
+ * the literal is handed to code that adds exactly that key through an alias
1300
+ * this read never sees syntactically -- which is why this proof also has to
1301
+ * survive every write in the program (`closedLiteralMemberAbsent`) rather
1302
+ * than stop at the literal's own declaration.
1303
+ *
1304
+ * The Object obligation is the one `flow/class-family-member-read.ts`
1305
+ * publishes for the same reason: the answer depends on `Object.prototype`
1306
+ * staying intact for this one key, recorded on the deferred ledger
1307
+ * (`requirePrototypeKeys('Object', { names: [name] }, at)`) and discharged
1308
+ * against the final host-mutation census, never assumed here.
1309
+ */
1310
+ const absentClosedObjectLiteralMemberTypeOf = (checker, flow, receiver, name, at) => {
1311
+ const ledger = deferredIntrinsicProtocolLedgerOf(flow);
1312
+ if (!ledger) {
1313
+ if (closedLiteralAbsenceDebug !== undefined)
1314
+ process.stderr.write(`[CLOSED-LITERAL-ABSENCE] ${name} no-ledger\n`);
1315
+ return null;
1316
+ }
1317
+ const arms = receiver.isUnion() ? receiver.types : [receiver];
1318
+ for (const arm of arms) {
1319
+ if (checker.getPropertyOfType(arm, name)) {
1320
+ if (closedLiteralAbsenceDebug !== undefined)
1321
+ process.stderr.write(`[CLOSED-LITERAL-ABSENCE] ${name} property-found-on-arm ${checker.typeToString(arm)}\n`);
1322
+ return null;
1323
+ }
1324
+ let proofsByType = closedLiteralAbsenceProofs.get(flow);
1325
+ if (!proofsByType)
1326
+ closedLiteralAbsenceProofs.set(flow, (proofsByType = new WeakMap()));
1327
+ let proofs = proofsByType.get(arm);
1328
+ if (!proofs)
1329
+ proofsByType.set(arm, (proofs = new Map()));
1330
+ let proved = proofs.get(name);
1331
+ if (!proved) {
1332
+ proved = ledger.capture(() => {
1333
+ // The prototype obligation is recorded HERE, not inside the write
1334
+ // scan: the scan can refuse for reasons that have nothing to do with
1335
+ // `Object.prototype` (a keyed write it cannot rule out), and a
1336
+ // refused proof must not still publish an obligation nobody needs.
1337
+ if (ledger.requirePrototypeKeys('Object', { names: [name] }, at) !== true) {
1338
+ if (closedLiteralAbsenceDebug !== undefined)
1339
+ process.stderr.write(`[CLOSED-LITERAL-ABSENCE] ${name} require-prototype-keys-failed\n`);
1340
+ return false;
1341
+ }
1342
+ return closedLiteralMemberAbsent(checker, flow, arm, name, at);
1343
+ });
1344
+ proofs.set(name, proved);
1345
+ }
1346
+ if (!proved.value) {
1347
+ if (closedLiteralAbsenceDebug !== undefined)
1348
+ process.stderr.write(`[CLOSED-LITERAL-ABSENCE] ${name} proof-rejected\n`);
1349
+ return null;
1350
+ }
1351
+ // `ledger.include` only reaches an active `capture` frame; a caller that
1352
+ // asks this OUTSIDE one (every binding census's `propertyTypeOf`, unlike
1353
+ // the producer-context hook which wraps its own ask) would silently lose
1354
+ // the obligation right here. Publish it into a persistent scope instead --
1355
+ // the same `capture`-independent path `flow/class-family-member-read.ts`'s
1356
+ // own `publish` uses for the identical class-family obligation -- so the
1357
+ // requirement survives to the final sealed-census discharge regardless of
1358
+ // which caller asked first.
1359
+ publishClosedLiteralAbsenceRequirements(ledger, proved.requirements);
1360
+ }
1361
+ return checker.getUndefinedType();
1362
+ };
1363
+ /**
1364
+ * Whether a NAMED property read is proven to miss every instance of a closed
1365
+ * object-literal record -- `numericIndexAbsenceProven`'s counterpart for a
1366
+ * named key instead of a numeric one. Deliberately separate from
1367
+ * `memberTypeOf`: an `undefined` answer there can also come from an ordinary
1368
+ * declared member or an array index signature, neither of which licenses a
1369
+ * PRODUCER skipping the runtime property lookup and constant-folding the read
1370
+ * -- only THIS proof does, which is why `producers/properties.ts` asks it
1371
+ * directly rather than re-deriving "was it the absence arm" from
1372
+ * `memberTypeOf`'s result.
1373
+ */
1374
+ export const closedLiteralMemberAbsenceProven = (checker, flow, receiver, name, at) => deferredIntrinsicProtocolLedgerOf(flow) !== null && absentClosedObjectLiteralMemberTypeOf(checker, flow, receiver, name, at) !== null;
1375
+ /**
1376
+ * The literal member NAME an element access spells, or `null` when its key is
1377
+ * not a literal. `x[ 'name' ]` and `x[ 0 ]` are named reads written with
1378
+ * brackets and resolve exactly as `x.name` does.
1379
+ */
1380
+ export const literalMemberNameOf = (node) => {
1381
+ const argument = node.argumentExpression;
1382
+ if (!argument)
1383
+ return null;
1384
+ if (ts.isStringLiteralLike(argument))
1385
+ return argument.text;
1386
+ if (ts.isNumericLiteral(argument))
1387
+ return argument.text;
1388
+ return null;
1389
+ };
1390
+ /**
1391
+ * The one overload of `resolved` whose declared parameter count admits this
1392
+ * call's argument count, or `null` when none or several do.
1393
+ *
1394
+ * Asked only when the checker resolved the call to a signature with NO
1395
+ * declaration -- its fabricated any-call, which is what a call through an
1396
+ * `any` receiver gets. The RECEIVER here is census-typed (`memberTypeOf` was
1397
+ * handed it), so the member's overload set is real and only the checker's own
1398
+ * choice among its members is missing. Counting arguments is the checker's own
1399
+ * first step (`chooseOverload` discards every candidate the count rules out
1400
+ * before comparing one type), so it is the step that can be repeated without
1401
+ * the receiver the checker refused to type; a tie keeps the set whole. Three's
1402
+ * `LOD.addLevel` is the measured case: `levels` is a descriptor-defined field
1403
+ * the checker declares nothing for, and `levels.splice( l, 0, level )` chose
1404
+ * the two-parameter overload by joining, so the item reached the emitter
1405
+ * unpacked -- `Array.prototype.splice`'s renderer refused it by name.
1406
+ */
1407
+ export const arityAdmittedSignature = (resolved, call) => {
1408
+ if (call.arguments.some((argument) => ts.isSpreadElement(argument)))
1409
+ return null;
1410
+ const count = call.arguments.length;
1411
+ const admitted = resolved.getCallSignatures().filter((signature) => {
1412
+ const declaration = signature.getDeclaration();
1413
+ if (!declaration)
1414
+ return false;
1415
+ const parameters = declaration.parameters;
1416
+ const last = parameters[parameters.length - 1];
1417
+ const rest = last?.dotDotDotToken !== undefined;
1418
+ const required = parameters.filter((parameter) => !parameter.questionToken && !parameter.initializer && !parameter.dotDotDotToken).length;
1419
+ return count >= required && (rest || count <= parameters.length);
1420
+ });
1421
+ const only = admitted[0];
1422
+ return admitted.length === 1 && only ? only : null;
1423
+ };
1424
+ const arityAdmittedDeclaration = (resolved, call) => arityAdmittedSignature(resolved, call)?.getDeclaration() ?? null;
1425
+ export const singleConventionAt = (checker, resolved, node) => {
1426
+ const overloaded = resolved.getCallSignatures().length > 1 || resolved.getConstructSignatures().length > 1;
1427
+ if (!overloaded)
1428
+ return resolved;
1429
+ const call = node.parent;
1430
+ if (!call || !ts.isCallExpression(call) || call.expression !== node)
1431
+ return null;
1432
+ const declaration = checker.getResolvedSignature(call)?.declaration ?? arityAdmittedDeclaration(resolved, call);
1433
+ if (!declaration)
1434
+ return null;
1435
+ const single = checker.getTypeAtLocation(declaration);
1436
+ if ((single.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) !== 0)
1437
+ return null;
1438
+ return single.getCallSignatures().length === 1 ? single : null;
1439
+ };
1440
+ /** The result of an authenticated `.call`/`.apply`, read from its already-resolved underlying callable. */
1441
+ export const explicitThisCallReturnType = (fallback, underlying) => {
1442
+ if (!underlying)
1443
+ return fallback.getReturnType();
1444
+ const signatures = underlying.getCallSignatures();
1445
+ const signature = signatures[0];
1446
+ if (signatures.length !== 1 || !signature || signature.typeParameters?.length)
1447
+ return fallback.getReturnType();
1448
+ return signature.getReturnType();
1449
+ };
1450
+ /**
1451
+ * An overload-independent result is knowable even when its physical call
1452
+ * convention is not. Read every declared return through the same recovered
1453
+ * receiver type; no overload is selected and no callable carrier is changed.
1454
+ * Generic signatures remain the checker's instantiation question.
1455
+ */
1456
+ export const overloadInvariantReturnTypeAt = (checker, call, read) => {
1457
+ const expression = call.expression;
1458
+ let callee;
1459
+ if (ts.isPropertyAccessExpression(expression) || ts.isElementAccessExpression(expression)) {
1460
+ const receiver = read(expression.expression);
1461
+ const name = ts.isPropertyAccessExpression(expression) ? expression.name.text : literalMemberNameOf(expression);
1462
+ if (!receiver || name === null)
1463
+ return null;
1464
+ // memberTypeOf also asks for a single convention. This query only asks
1465
+ // what all conventions return, so retain the complete member type.
1466
+ const member = checker.getPropertyOfType(checker.getNonNullableType(receiver), name);
1467
+ callee = member ? checker.getTypeOfSymbolAtLocation(member, expression) : null;
1468
+ }
1469
+ else {
1470
+ callee = read(expression);
1471
+ }
1472
+ if (!callee)
1473
+ return null;
1474
+ const signatures = ts.isNewExpression(call) ? callee.getConstructSignatures() : callee.getCallSignatures();
1475
+ if (signatures.length < 2 || signatures.some((signature) => signature.typeParameters?.length))
1476
+ return null;
1477
+ const returned = signatures[0]?.getReturnType();
1478
+ if (!returned || isUnusableEvidence(returned))
1479
+ return null;
1480
+ return signatures.every((signature) => signature.getReturnType() === returned) ? returned : null;
1481
+ };
1482
+ /** Whether `node` (through any parentheses) is the expression a call or `new` invokes. */
1483
+ const calleePosition = (node) => {
1484
+ let current = node;
1485
+ while (current.parent && ts.isParenthesizedExpression(current.parent))
1486
+ current = current.parent;
1487
+ const parent = current.parent;
1488
+ return parent !== undefined && (ts.isCallExpression(parent) || ts.isNewExpression(parent)) && parent.expression === current;
1489
+ };
1490
+ export const memberTypeOf = (checker, receiver, name, at, flow) => {
1491
+ const nonNullReceiver = checker.getNonNullableType(receiver);
1492
+ const property = checker.getPropertyOfType(nonNullReceiver, name);
1493
+ if (!property) {
1494
+ // Array index signatures also govern literal keys. An array has no own
1495
+ // declared "0" member, unlike a tuple; treating that absence as silence
1496
+ // loses an element already recovered from the receiver's storage.
1497
+ if (checker.isArrayLikeType(nonNullReceiver) && String(Number(name)) === name) {
1498
+ const element = checker.getIndexTypeOfType(nonNullReceiver, ts.IndexKind.Number);
1499
+ return element && !isUnusableEvidence(element) ? checker.getNullableType(element, ts.TypeFlags.Undefined) : null;
1500
+ }
1501
+ // JavaScript reads an absent own property as `undefined`. When the
1502
+ // receiver is proven a CLOSED object-literal record that nothing in the
1503
+ // program can add `name` to, that really is the read's value -- see
1504
+ // `absentClosedObjectLiteralMemberTypeOf`'s own header for why this is
1505
+ // answered here (the one shared authority every binding census's
1506
+ // `propertyTypeOf` already routes through) rather than once per census.
1507
+ //
1508
+ // Never for a CALLEE. `undefined` is the read's value; calling it is a
1509
+ // guaranteed TypeError, and a callee slot typed `undefined` is not a
1510
+ // refusal, it is a program the lowering has to invent a meaning for.
1511
+ // `test/runtime/borrowed-array-method-unmatched-receiver.runtime.js`
1512
+ // is the measured case: `borrowed-builtin-call-bind-source-transform.ts`
1513
+ // rewrites `Array.prototype.join.call( o, ',' )` into `o.join( ',' )`, a
1514
+ // read the ORIGINAL program never performs, on a literal that proves
1515
+ // `join` absent. Answered as absent, the site was refused only by the
1516
+ // host-mutation census happening to read the same call as a possible
1517
+ // `Object.prototype.join` mutator -- a circular refusal that names the
1518
+ // wrong thing. Left unanswered, the callee falls through to the record
1519
+ // member get, which refuses by name (`"Array.prototype.join" has no
1520
+ // rendering off a "record(...)"`), exactly as before absence existed.
1521
+ return flow && !calleePosition(at) ? absentClosedObjectLiteralMemberTypeOf(checker, flow, nonNullReceiver, name, at) : null;
1522
+ }
1523
+ const type = checker.getTypeOfSymbolAtLocation(property, at);
1524
+ if (isUnusableEvidence(type))
1525
+ return null;
1526
+ return singleConventionAt(checker, type, at);
1527
+ };
1528
+ /**
1529
+ * Whether a JSDoc tag resolved to nothing AT ALL -- `any` or `unknown`.
1530
+ *
1531
+ * Not the whole question a cell has; see `jsDocTypeStatesNothing`, which is
1532
+ * what every cell should ask. This is only the arm that is specific to a TAG:
1533
+ * a tag naming a type this module cannot import degrades to `any`. A tag
1534
+ * that SPELLS `unknown` (`{unknown}`, `{?}`) is not that degradation -- it is
1535
+ * the author's own statement, exactly as a real `unknown` annotation is
1536
+ * (`annotationStatesNothing`), and is answered `false` below so the two
1537
+ * spellings of one statement get one census answer.
1538
+ */
1539
+ export const jsDocTypeIsUninformative = (checker, typeNode) => {
1540
+ // A SPELLED `{unknown}` (or its JSDoc form `{?}`) is the author writing
1541
+ // the statement a TS `: unknown` annotation makes, and stays one: a name
1542
+ // that fails to resolve degrades to `any`, never to `unknown`, so this
1543
+ // spelling cannot be the degradation this exists to admit. Measured the
1544
+ // other way on test262's own harness compiled as JavaScript: `@param
1545
+ // {unknown} actual` on `assert.sameValue` was admitted, the call sites
1546
+ // bound the slot `number`, and the body -- laid out from the checker's
1547
+ // `unknown` -- declared the same parameter dynamic, so the ABI and the
1548
+ // frame disagreed and every case using the shim refused. `{any}`/`{*}`
1549
+ // stay admitted: three.js writes `{any}` 31 times on parameters the three.js app
1550
+ // measures as call-site-bindable, and that tag IS indistinguishable in
1551
+ // resolved type from a degraded name.
1552
+ if (typeNode.kind === ts.SyntaxKind.UnknownKeyword || typeNode.kind === ts.SyntaxKind.JSDocUnknownType)
1553
+ return false;
1554
+ const resolved = checker.getTypeFromTypeNode(typeNode);
1555
+ return (resolved.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) !== 0;
1556
+ };
1557
+ /**
1558
+ * Whether a JSDoc tag states nothing about storage -- the ONE test every cell
1559
+ * asks of a tag, tag-specific degradation plus the identical vacuity rule a
1560
+ * real annotation gets.
1561
+ *
1562
+ * Four cells asked this and each asked it differently:
1563
+ * `parameter-bindings.ts` had a private copy that added `isEmptyObjectType`,
1564
+ * while `return-bindings.ts`, `field-bindings.ts` and `local-bindings.ts`
1565
+ * asked `jsDocTypeIsUninformative` alone -- so a `@param {{}}` tag was
1566
+ * non-evidence at one cell and a stated type at the other three. Ordinary
1567
+ * drift, of the shape this compiler keeps finding.
1568
+ *
1569
+ * The measured hole all four shared is `{Object}`. Three separate comments in
1570
+ * this file asserted that TypeScript's JSDoc parser maps a capitalized
1571
+ * `{Object}` tag to `any`, so `jsDocTypeIsUninformative` would catch it and
1572
+ * `isGlobalObjectInterface` was documented as "not reachable from JSDoc".
1573
+ * That is false, measured on three's `UniformsUtils.js`:
1574
+ *
1575
+ * &#64;return {Object} The cloned uniforms.
1576
+ * export function cloneUniforms( src ) { const dst = {}; ... return dst }
1577
+ *
1578
+ * `getReturnTypeOfSignature` answers the REAL `lib.es5.d.ts` `Object`
1579
+ * interface -- 7 properties, `TypeFlags.Object`, not `any` and not empty. So
1580
+ * it passed every vacuity test, became the return cell's stated answer, and
1581
+ * the honest `dictionary` the body builds had to convert to a named record
1582
+ * with zero members (every one of `Object`'s members is an ambient method
1583
+ * `structural.ts` drops). No backend can render that pair, and the whole
1584
+ * uniforms chain downstream of it -- `parameters.uniforms`,
1585
+ * `materialProperties.uniforms`, and the 338 boxed carriers of
1586
+ * `WebGLMaterials.js`'s `refreshUniforms*( uniforms, material )` -- was
1587
+ * dynamic because of one tag.
1588
+ *
1589
+ * Recording that premise as false is the finding; making the tag path REFUSE
1590
+ * an `{Object}` is not the cure, and the inline comment below carries the
1591
+ * measurement that rules it out.
1592
+ */
1593
+ export const jsDocTypeStatesNothing = (checker, typeNode) =>
1594
+ // The parameter census's own private copy of this test, made shared: three
1595
+ // cells asked only `jsDocTypeIsUninformative`, one asked that OR
1596
+ // `isEmptyObjectType`, and a tag is one question, so they answer with one
1597
+ // authority now.
1598
+ //
1599
+ // Deliberately NOT `annotationStatesNothing`: that also refuses a tag
1600
+ // resolving to the global `Object` interface. Adding that arm was measured on
1601
+ // the three.js app and is a DEAD LEVER -- boxedTop stayed at exactly 9431, boxed rose
1602
+ // 15899 -> 15906, and `withheld` went 8 -> 39, taking 134 operations with it
1603
+ // (the 31 new ones sit on `mergeUniforms`/`cloneUniforms` results cited by
1604
+ // object literals: ShaderLib 20, WebGLBackground 8, plus ShaderMaterial,
1605
+ // Object3D and WebGLEnvironments). The carrier does not change because refusing
1606
+ // the tag only makes the census decline, after which the CHECKER hands the
1607
+ // very same named-empty `Object` record to the signature -- so the two
1608
+ // authorities on one call's result stop agreeing while the boxing stays put.
1609
+ // Do not retry it here. `@return {Object}` DOES reach a cell and resolve to
1610
+ // the real 7-member `lib.es5` interface (three comments in this file once
1611
+ // claimed the JSDoc parser maps it to `any` -- it does not, they are
1612
+ // corrected), but the fix has to change what that interface DERIVES to, not
1613
+ // whether a census reads it.
1614
+ jsDocTypeIsUninformative(checker, typeNode) || isEmptyObjectType(checker.getTypeFromTypeNode(typeNode));
1615
+ /**
1616
+ * Whether a resolved type is a structural object type with ZERO evidence in
1617
+ * it: no properties, no call signature, no construct signature, no index
1618
+ * signature.
1619
+ *
1620
+ * Lived in `parameter-bindings.ts` until `return-bindings.ts` needed the same
1621
+ * question; moved here -- the module both already share for
1622
+ * `jsDocTypeIsUninformative` and `widestOf` -- rather than copied, so the two
1623
+ * cannot drift.
1624
+ *
1625
+ * `jsDocTypeIsUninformative` above catches a tag that resolves to
1626
+ * `any`/`unknown` -- an unimported cross-module name, or the JSDoc-special
1627
+ * `Object`/`object`. It does NOT catch this: three writes `@param {Object}
1628
+ * data` for `InterleavedBuffer.clone( data )`, and
1629
+ * `declaration-overlay-transform.ts`'s `replaceVagueParamTags` correctly
1630
+ * prefers the SHIPPED declaration's answer over that vague tag -- but the
1631
+ * shipped declaration (`@types/three`) states `clone(data: {}): ...`, and
1632
+ * `{}` is itself a type with nothing IN it. The overlay's replacement is a
1633
+ * real improvement in the general case (`Material.fromJSON`'s `json` gets a
1634
+ * real `MaterialJSON`); here it swaps one uninformative spelling for another,
1635
+ * and without this check the resolved `{}` reads as "the program stated a
1636
+ * real type" and stays excluded from the call-site census forever, even
1637
+ * though it states precisely as much as `any` does about what the parameter
1638
+ * holds.
1639
+ *
1640
+ * The same non-evidence `parameter-bindings.ts`'s `isBareFunctionType`
1641
+ * already is for a type with zero CALLING convention, generalized to zero
1642
+ * MEMBER convention.
1643
+ */
1644
+ export const isEmptyObjectType = (type) => {
1645
+ // The bare `object` KEYWORD (lowercase, `TypeFlags.NonPrimitive`) is a
1646
+ // structural type distinct from `ts.TypeFlags.Object` -- it is TypeScript's
1647
+ // own "some non-primitive value, shape unstated" wildcard, so it declares
1648
+ // no properties/signatures by construction and states nothing about
1649
+ // storage for the identical reason an empty `{}` type literal does. Caught
1650
+ // here rather than folded into `jsDocTypeIsUninformative`: lowercase
1651
+ // `object` resolves to this REAL, non-`any`/`unknown` type (and so, it
1652
+ // turns out, does capitalized `Object` -- see `isGlobalObjectInterface`,
1653
+ // which handles that one) -- `WebGLProgram`'s own
1654
+ // `@param {object} parameters` (matching what `@types/three` itself
1655
+ // declares: `constructor(..., parameters: object)`) reads as "the program
1656
+ // stated a real type" without this check, even though `object` carries
1657
+ // exactly as little information as `any` does for what can be read off it.
1658
+ if ((type.flags & ts.TypeFlags.NonPrimitive) !== 0)
1659
+ return true;
1660
+ if ((type.flags & ts.TypeFlags.Object) === 0)
1661
+ return false;
1662
+ if (type.getProperties().length > 0)
1663
+ return false;
1664
+ if (type.getCallSignatures().length > 0)
1665
+ return false;
1666
+ if (type.getConstructSignatures().length > 0)
1667
+ return false;
1668
+ return !type.getStringIndexType() && !type.getNumberIndexType();
1669
+ };
1670
+ /**
1671
+ * Whether a type has no NAME of its own -- the `object` keyword, or an
1672
+ * anonymous `{}` type literal, as opposed to a declared interface that
1673
+ * happens to have no members.
1674
+ *
1675
+ * This distinction does not arise on the JSDoc path and is what makes
1676
+ * `annotationStatesNothing` below narrower than `isEmptyObjectType`. Measured
1677
+ * over the three.js app's whole program: 168 of the 197 parameter annotations that
1678
+ * `isEmptyObjectType` alone calls empty are NAMED, and they are `lib.dom`'s
1679
+ * opaque handle interfaces -- `interface WebGLProgram {}`, `WebGLBuffer`,
1680
+ * `WebGLShader`, `PeriodicWave`, `FragmentDirective`. Those are declared
1681
+ * empty on purpose: emptiness IS the statement, a nominal handle nobody may
1682
+ * read a member off. Re-deriving one of them from its call sites would
1683
+ * replace a nominal identity the host owns with whatever this compiler's own
1684
+ * join happened to pick, so a named type keeps outranking the census here
1685
+ * even when it is structurally empty.
1686
+ */
1687
+ const isAnonymousType = (type) => {
1688
+ if ((type.flags & ts.TypeFlags.NonPrimitive) !== 0)
1689
+ return true;
1690
+ const name = type.getSymbol()?.getName();
1691
+ return name === undefined || name === '__type' || name === '__object';
1692
+ };
1693
+ /**
1694
+ * The checker's own answer for a standard-library INTERFACE name, resolved at
1695
+ * `anchor` and memoized per checker -- so a name a large program's walk asks
1696
+ * about at every write site (`Object`, `Map`, ...) is resolved once rather
1697
+ * than once per site.
1698
+ *
1699
+ * `checker.resolveName` is the public API for exactly "what does this name
1700
+ * mean here", independent of any use site -- the mechanism `host-protocols.ts`
1701
+ * already uses to name `Promise`/`Date`/`String`/the four keyed collections.
1702
+ * This shares that same first step. Where it deliberately does NOT follow
1703
+ * `host-protocols.ts` is the second: those functions take
1704
+ * `identities.symbolDeclarationId(...)` and key a `Map<DeclarationId, ...>`
1705
+ * with it, because they publish an answer for OTHER layers to read back
1706
+ * across specialization copies. Every caller here asks a one-off "is this
1707
+ * type THAT ambient interface" and keys nothing -- and an ambient library
1708
+ * interface has exactly one `ts.Symbol` per checker for every INSTANTIATION
1709
+ * of that same generic declaration (`Map<string, number>`'s own `getSymbol()`
1710
+ * answers the same object bare `Map` does), so comparing that symbol
1711
+ * directly states the identical fact `symbolDeclarationId` equality would
1712
+ * for that question, without needing an `IdentityTable` this layer does not
1713
+ * otherwise hold.
1714
+ *
1715
+ * What raw symbol equality does NOT state, and `symbolDeclarationId`
1716
+ * equality would not either: whether some OTHER type derives from the
1717
+ * standard interface rather than being it directly. `class Registry extends
1718
+ * Map<string, number> {}` has its own `Registry` symbol, distinct from
1719
+ * `Map`'s; `<T extends Map<string, number>>` has its own per-declaration
1720
+ * type-parameter symbol. `isStandardInterfaceType(checker, anchor, 'Map',
1721
+ * receiverType)` answers `false` for both, correctly by its own question
1722
+ * ("IS this type the standard interface") but not by the question a
1723
+ * receiver-identity check usually means to ask ("is this a Map"). A caller
1724
+ * that means the second question -- `flow/value-flow.ts`'s
1725
+ * `matchesStandardInterfaceTransitively` is the one that does -- must take
1726
+ * `checker.getApparentType` (to resolve a type parameter to its constraint)
1727
+ * and walk `checker.getBaseTypes` transitively (to resolve a subclass to
1728
+ * what it extends) itself; this function is one ingredient of that
1729
+ * question, not the whole answer to it.
1730
+ */
1731
+ const standardInterfaceSymbolCache = new WeakMap();
1732
+ const standardInterfaceSymbol = (checker, anchor, name) => {
1733
+ let cache = standardInterfaceSymbolCache.get(checker);
1734
+ if (!cache) {
1735
+ cache = new Map();
1736
+ standardInterfaceSymbolCache.set(checker, cache);
1737
+ }
1738
+ const cached = cache.get(name);
1739
+ if (cached !== undefined)
1740
+ return cached;
1741
+ const resolved = checker.resolveName(name, anchor, ts.SymbolFlags.Interface, false) ?? null;
1742
+ cache.set(name, resolved);
1743
+ return resolved;
1744
+ };
1745
+ /**
1746
+ * Whether `type` IS the standard library's `name` interface -- by declaration
1747
+ * identity, never by the symbol's own spelling. See `standardInterfaceSymbol`.
1748
+ */
1749
+ export const isStandardInterfaceType = (checker, anchor, name, type) => {
1750
+ const symbol = type.getSymbol();
1751
+ return symbol !== undefined && symbol === standardInterfaceSymbol(checker, anchor, name);
1752
+ };
1753
+ /**
1754
+ * Whether a type is the global `Object` INTERFACE -- `x: Object`, spelled as a
1755
+ * real TypeScript annotation.
1756
+ *
1757
+ * The exact argument `parameter-bindings.ts`'s `isBareFunctionType` makes for
1758
+ * bare `Function`, one level up: `Object` declares only what every value
1759
+ * already has (`toString`, `valueOf`, `hasOwnProperty`), every non-null value
1760
+ * is assignable to it, and it therefore states nothing about what this
1761
+ * particular value holds. Resolved by DECLARATION IDENTITY (`isStandardInterfaceType`),
1762
+ * so a user interface that merely declares those members -- and would once
1763
+ * have matched on the bare spelling `'Object'` -- is not swept in beside it;
1764
+ * only the library's own `Object` is.
1765
+ *
1766
+ * Reachable from JSDoc TOO, contrary to what this comment said for a long
1767
+ * time. A capitalized `{Object}` tag does NOT degrade to `any`: measured on
1768
+ * three's `@return {Object}`, the checker answers this very interface. See
1769
+ * `jsDocTypeStatesNothing`, which is what makes the tag path ask.
1770
+ *
1771
+ * `normalize/structural.ts` interns exactly THIS interface as `any`, and the
1772
+ * two obvious companions to it are measured DEAD LEVERS, recorded here so the
1773
+ * next session does not re-derive them:
1774
+ *
1775
+ * - an anonymous `{}` (empty, no signatures, no index, excluding fresh object
1776
+ * literals, which share the identical type and are real values whose shape
1777
+ * the object-bag and collection censuses discover): the three.js app's unmet
1778
+ * obligations went 33 UP to 34 and `boxed` 17190 -> 17568. `{}` is the
1779
+ * checker's answer for a great many things that are not "unstated" at all --
1780
+ * an intersection reduced to nothing, a mapped type over no keys, a bag
1781
+ * before its census runs -- and boxing all of them costs more pairings than
1782
+ * it closes.
1783
+ * - the lowercase `object` KEYWORD (`TypeFlags.NonPrimitive`), which really is
1784
+ * one unambiguous spelling and really does state nothing: exactly NEUTRAL on
1785
+ * unmet obligations (33 -> 33) at `boxed` +103. A cost with no return.
1786
+ *
1787
+ * Both remain correct as statements about what those types SAY. Neither is
1788
+ * worth what it costs as a carrier decision.
1789
+ */
1790
+ export const isGlobalObjectInterface = (checker, anchor, type) => {
1791
+ if ((type.flags & ts.TypeFlags.Object) === 0)
1792
+ return false;
1793
+ if (type.getCallSignatures().length > 0 || type.getConstructSignatures().length > 0)
1794
+ return false;
1795
+ return isStandardInterfaceType(checker, anchor, 'Object', type);
1796
+ };
1797
+ /**
1798
+ * Whether `type` is the standard library's `ObjectConstructor` interface --
1799
+ * the type the global `Object` VALUE has, as opposed to `isGlobalObjectInterface`'s
1800
+ * `Object` INSTANCE interface immediately above.
1801
+ *
1802
+ * Exported so the two call sites that ask "is this call really `Object.assign`
1803
+ * on the real global" (`flow/value-flow.ts`'s `isGlobalObjectAssign`,
1804
+ * `object-bag-bindings.ts`'s `isGlobalObjectAssignCall`) ask one shared
1805
+ * question instead of two byte-for-byte-identical copies of it, each
1806
+ * comparing `checker.getTypeAtLocation(callee.expression).getSymbol()?.getName()`
1807
+ * against the literal string `'ObjectConstructor'`.
1808
+ */
1809
+ export const isGlobalObjectConstructor = (checker, anchor, type) => isStandardInterfaceType(checker, anchor, 'ObjectConstructor', type);
1810
+ /** The standard global Function constructor value, by ambient declaration identity. */
1811
+ export const isGlobalFunctionConstructor = (checker, anchor, type) => isStandardInterfaceType(checker, anchor, 'FunctionConstructor', type);
1812
+ /** The standard global Array constructor value, by ambient declaration identity. */
1813
+ export const isGlobalArrayConstructor = (checker, anchor, type) => isStandardInterfaceType(checker, anchor, 'ArrayConstructor', type);
1814
+ /** A standard global namespace value, resolved by symbol identity rather than spelling. */
1815
+ export const isStandardGlobalValue = (checker, expression, name) => {
1816
+ let actual = checker.getSymbolAtLocation(expression);
1817
+ if (actual && (actual.flags & ts.SymbolFlags.Alias) !== 0)
1818
+ actual = checker.getAliasedSymbol(actual);
1819
+ let expected = checker.resolveName(name, expression, ts.SymbolFlags.Value | ts.SymbolFlags.Namespace, false);
1820
+ if (expected && (expected.flags & ts.SymbolFlags.Alias) !== 0)
1821
+ expected = checker.getAliasedSymbol(expected);
1822
+ return actual !== undefined && expected !== undefined && actual === expected;
1823
+ };
1824
+ /**
1825
+ * The target type of an authenticated `Object.assign` call with at least one source.
1826
+ *
1827
+ * The ambient signature's `T & U` result describes which properties source
1828
+ * code may read after the copy. The runtime value is still `T`: ECMA-262
1829
+ * mutates and returns the first argument. Every binding census has to read
1830
+ * that identity the same way, or one census publishes the intersection while
1831
+ * the invocation producer publishes the target and creates a conversion
1832
+ * between two carriers for one object. The extra keys live in the native
1833
+ * target's dynamic-property sidecar; changing the value's carrier is neither
1834
+ * necessary nor correct.
1835
+ *
1836
+ * A primitive target is excluded because Object.assign first boxes it, and
1837
+ * this backend does not implement wrapper-object carriers.
1838
+ */
1839
+ export const objectAssignTargetType = (checker, node) => {
1840
+ if (!isAuthenticatedObjectAssign(checker, node))
1841
+ return null;
1842
+ const target = node.arguments[0];
1843
+ if (!target)
1844
+ return null;
1845
+ const fresh = ts.isObjectLiteralExpression(target) ? objectAssignFreshTargetType(checker, target) : null;
1846
+ if (fresh !== null)
1847
+ return fresh;
1848
+ const type = checker.getTypeAtLocation(target);
1849
+ return (type.flags & ts.TypeFlags.Object) !== 0 ? type : null;
1850
+ };
1851
+ /** `Object.assign(...)` on the real global with at least one source, resolved by declaration identity. */
1852
+ const isAuthenticatedObjectAssign = (checker, node) => {
1853
+ if (!ts.isCallExpression(node) || node.arguments.length < 2)
1854
+ return false;
1855
+ const callee = node.expression;
1856
+ if (!ts.isPropertyAccessExpression(callee) || callee.name.text !== 'assign')
1857
+ return false;
1858
+ return isGlobalObjectConstructor(checker, callee.expression, checker.getTypeAtLocation(callee.expression));
1859
+ };
1860
+ /**
1861
+ * The object `Object.assign( {}, ...sources )` builds, when `literal` is that
1862
+ * bare `{}`.
1863
+ *
1864
+ * `objectAssignTargetType`'s identity argument holds for a target that exists
1865
+ * before the call: the value returned IS that object, so its carrier is that
1866
+ * object's own, extra keys in the sidecar. A bare empty literal written in the
1867
+ * target position has no carrier of its own to keep. It is allocated for this
1868
+ * call, observed nowhere else, and the one statement anywhere of what it holds
1869
+ * afterwards is the call's own `T & U` -- which the checker has already
1870
+ * reduced, dropping the empty member (`{} & Record<string, number[]>` reports
1871
+ * as `Record<string, number[]>`). Publishing the literal's own `{}` in its
1872
+ * place put an empty record on one side of the copy and a dictionary on the
1873
+ * other: three's `Object.assign( {}, source.defines )` then refused for want of
1874
+ * a record<-dictionary arm, and no such arm can exist, since an empty struct
1875
+ * has nowhere to put a key.
1876
+ *
1877
+ * Read by BOTH the call's result (`objectAssignTargetType`) and the literal's
1878
+ * own layout (`structural-layout-type.ts`), so the target and the value it
1879
+ * becomes are one carrier by construction. A literal with properties keeps its
1880
+ * own shape -- it states one -- and so does a literal under an assertion.
1881
+ */
1882
+ export const objectAssignFreshTargetType = (checker, literal) => {
1883
+ if (literal.properties.length !== 0)
1884
+ return null;
1885
+ const call = literal.parent;
1886
+ if (!isAuthenticatedObjectAssign(checker, call) || call.arguments[0] !== literal)
1887
+ return null;
1888
+ const type = checker.getTypeAtLocation(call);
1889
+ return (type.flags & ts.TypeFlags.Object) !== 0 ? type : null;
1890
+ };
1891
+ /**
1892
+ * Whether a REAL TypeScript type ANNOTATION states nothing -- the same
1893
+ * non-statement `jsDocTypeStatesNothing` already recognises in a JSDoc tag,
1894
+ * asked of a type the program wrote out in TypeScript.
1895
+ *
1896
+ * `getExtension( name: string ): object | null`, `f( options: {} )`, `g( x:
1897
+ * Object )`: each is exactly as informative about storage as the JSDoc
1898
+ * `@param {Object}` tag that commit `f6c90e4b4` stopped trusting, and for the
1899
+ * same reason -- a stated type that resolves to something which says nothing
1900
+ * is WORSE than no type at all, because it becomes the answer and outranks a
1901
+ * census that could have derived a real one.
1902
+ *
1903
+ * Deliberately NOT widened past that:
1904
+ *
1905
+ * - `unknown` is a statement. An author who writes `unknown` is saying "do not
1906
+ * assume", and that must keep outranking anything this compiler infers.
1907
+ * - a NAMED empty type is a statement -- see `isAnonymousType`.
1908
+ * - a non-empty interface is a statement, however loose.
1909
+ * - `any` written out as a real annotation is left exactly where it is. It is
1910
+ * a separate lever with a separate blast radius, and this module's
1911
+ * `resolvedReturnTypeOf` already documents honouring `: any` at face value.
1912
+ *
1913
+ * A union is seen through only when its non-absent half is itself a
1914
+ * non-statement: `object | null` states as little as `object` does, since
1915
+ * `null` is not a shape. Any other union member is real evidence and stops
1916
+ * this.
1917
+ *
1918
+ * `checker`/`anchor` exist only for `isGlobalObjectInterface`'s declaration-identity
1919
+ * resolution (`isStandardInterfaceType`) -- `anchor` is any node reachable
1920
+ * from the site this type came from; a REAL `Object` is a single ambient
1921
+ * global, so which node names it does not change the answer.
1922
+ */
1923
+ /**
1924
+ * The one test for "this PART of a type says nothing about storage" -- bare
1925
+ * `{}` (anonymous and empty) or the global `Object` interface.
1926
+ *
1927
+ * Shared so `annotationStatesNothing` (is the WHOLE thing a non-statement?)
1928
+ * and `withoutVacuousMembers` (which PARTS of it are) cannot drift apart:
1929
+ * they are the same question asked of a type and of its members, and a join
1930
+ * that trusts one while the other disagrees is exactly the bug both exist to
1931
+ * prevent.
1932
+ */
1933
+ const statesNothingPart = (checker, anchor, part) => (isEmptyObjectType(part) && isAnonymousType(part)) || (anchor !== null && isGlobalObjectInterface(checker, anchor, part));
1934
+ /**
1935
+ * `statesNothingPart` asked THROUGH a constraint, for a part that is not
1936
+ * itself a type at all but a stand-in for one.
1937
+ *
1938
+ * `E['Bindings']`, where hono declares `type Bindings = object` and
1939
+ * `E extends Env`, is a deferred indexed access: not an object type, so
1940
+ * neither arm of `statesNothingPart` sees it, and yet the checker relates
1941
+ * every object type to it exactly as it does to `object` -- through that
1942
+ * constraint. It carries as little as `object` does (this compiler derives it
1943
+ * to `dynamic`), and a join that treats it as a real statement lets it cover
1944
+ * observations it says nothing about, which is the whole defect the veto
1945
+ * exists to stop.
1946
+ *
1947
+ * Kept OUT of `annotationStatesNothing`, deliberately: that function decides
1948
+ * whether a stated type is evidence at all, and a constraint-following
1949
+ * version of it would demote every `T extends object` annotation in every
1950
+ * census at once. This one is read only by `withoutVacuousMembers`, whose
1951
+ * single caller uses it to RE-ASK a coverage question it has already been
1952
+ * given an answer to -- so a wrong answer here can only refuse a join, never
1953
+ * narrow a slot.
1954
+ *
1955
+ * A constraint that is a union is vacuous only when its every non-absent
1956
+ * member is -- the same shape, and the same reason, as the union arm of
1957
+ * `annotationStatesNothing` itself.
1958
+ */
1959
+ const statesNothingThroughConstraint = (checker, anchor, part) => {
1960
+ if (statesNothingPart(checker, anchor, part))
1961
+ return true;
1962
+ const constraint = checker.getBaseConstraintOfType(part);
1963
+ if (constraint === undefined || constraint === part)
1964
+ return false;
1965
+ const absent = ts.TypeFlags.Null | ts.TypeFlags.Undefined;
1966
+ let sawStatement = false;
1967
+ for (const member of constraint.isUnion() ? constraint.types : [constraint]) {
1968
+ if ((member.flags & absent) !== 0)
1969
+ continue;
1970
+ if (!statesNothingPart(checker, anchor, member))
1971
+ return false;
1972
+ sawStatement = true;
1973
+ }
1974
+ return sawStatement;
1975
+ };
1976
+ /**
1977
+ * `type` with every vacuous member dropped, or `null` when nothing is left.
1978
+ *
1979
+ * `annotationStatesNothing` answers "is this type ENTIRELY a non-statement",
1980
+ * which is the right question for evidence: a type that says nothing must not
1981
+ * become the answer. It is the wrong question for a JOIN with a vacuous
1982
+ * member ALONGSIDE a real one -- `{} | E['Bindings'] | undefined`, the first
1983
+ * element of the tuple TypeScript gives hono's `fetch(request, ...rest)`.
1984
+ * That type is not entirely vacuous (the indexed access is a statement), yet
1985
+ * the `{}` inside it still makes EVERY object type assignable to the whole,
1986
+ * so a `widestOf` join hands it back as "the" type and the other elements --
1987
+ * `ExecutionContext` -- vanish without a trace.
1988
+ *
1989
+ * The caller's use is a re-test, never an answer: strip the vacuous parts and
1990
+ * ask whether the coverage survives. If it does, the join was real; if it
1991
+ * does not, the coverage was `{}`'s alone and the join has to state the union
1992
+ * instead. Nothing published to representation is ever the stripped type --
1993
+ * that would be the opposite error, narrowing a slot below what the program
1994
+ * annotated.
1995
+ */
1996
+ export const withoutVacuousMembers = (checker, anchor, type) => {
1997
+ const parts = type.isUnion() ? type.types : [type];
1998
+ // `isGlobalObjectInterface` resolves the NAME `Object` somewhere in the
1999
+ // program to compare declaration identity, and any node in it answers that
2000
+ // the same way (a real `Object` is a single ambient global). A caller with
2001
+ // no node in hand -- `widestOf`, which is handed types alone -- gets one
2002
+ // from the type itself rather than losing that arm of the test.
2003
+ const at = anchor ?? parts.flatMap((part) => part.getSymbol()?.getDeclarations() ?? [])[0] ?? null;
2004
+ const kept = parts.filter((part) => !statesNothingThroughConstraint(checker, at, part));
2005
+ if (kept.length === parts.length)
2006
+ return type;
2007
+ if (kept.length === 0)
2008
+ return null;
2009
+ if (kept.length === 1)
2010
+ return kept[0];
2011
+ const constructing = checker;
2012
+ return typeof constructing.getUnionType === 'function' ? constructing.getUnionType(kept) : null;
2013
+ };
2014
+ export const annotationStatesNothing = (checker, anchor, type) => {
2015
+ const bare = (part) => statesNothingPart(checker, anchor, part);
2016
+ if (bare(type))
2017
+ return true;
2018
+ if (!type.isUnion())
2019
+ return false;
2020
+ const absent = ts.TypeFlags.Null | ts.TypeFlags.Undefined;
2021
+ let sawNonStatement = false;
2022
+ for (const part of type.types) {
2023
+ if ((part.flags & absent) !== 0)
2024
+ continue;
2025
+ if (!bare(part))
2026
+ return false;
2027
+ sawNonStatement = true;
2028
+ }
2029
+ return sawNonStatement;
2030
+ };
2031
+ /**
2032
+ * The exact type of an EMPTY object literal the program wrote as a value --
2033
+ * `{}` in `const { fn = function () {} } = {}` -- or `null` for any other node.
2034
+ *
2035
+ * `annotationStatesNothing` above is right to treat the vacuous type `{}` as
2036
+ * a non-statement when it arrives as an ANNOTATION or as a join member: every
2037
+ * type is assignable to it, so it dominates. The same type on a literal the
2038
+ * program EVALUATES is the opposite: a fresh object with exactly zero members,
2039
+ * the most precise statement there is, and the one a destructuring pattern
2040
+ * reads out of. Filtering it out there left every pattern over `{}` with no
2041
+ * holder at all, so each leaf fell back to the checker's own `any` (the JS
2042
+ * checker's answer for a key the literal lacks) and boxed the default it was
2043
+ * meant to bind. A literal with spreads or properties is not this case: the
2044
+ * ordinary literal type is already non-vacuous and needs no exception.
2045
+ */
2046
+ export const exactEmptyObjectLiteralType = (checker, node) => ts.isObjectLiteralExpression(node) && node.properties.length === 0 ? checker.getTypeAtLocation(node) : null;
2047
+ /**
2048
+ * A position the DECLARATION states nothing about.
2049
+ *
2050
+ * `annotationStatesNothing` above answers this for a WHOLE annotation -- `x:
2051
+ * {}`, `x: object`. This is the same question asked of one position INSIDE
2052
+ * one: `any` and `unknown` are the checker's two spellings of "no statement
2053
+ * about this value", and bare `Function` is the third (see
2054
+ * `parameter-bindings.ts`'s `isBareFunctionType` -- zero call signatures,
2055
+ * zero construct signatures, so no arity and no result either).
2056
+ */
2057
+ const positionStatesNothing = (checker, anchor, declared) => {
2058
+ if ((declared.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) !== 0)
2059
+ return true;
2060
+ if (annotationStatesNothing(checker, anchor, declared))
2061
+ return true;
2062
+ if (declared.getCallSignatures().length > 0 || declared.getConstructSignatures().length > 0)
2063
+ return false;
2064
+ return declared.getSymbol()?.getName() === 'Function';
2065
+ };
2066
+ /**
2067
+ * Whether a stated type has an unstated position ANYWHERE inside it, and so
2068
+ * could be an upper bound rather than the last word.
2069
+ *
2070
+ * A pre-filter, not a judgement: `narrowsOnlyUnstatedPositions` below decides
2071
+ * whether a particular value may narrow a particular statement. This only
2072
+ * keeps a census from carrying every annotated declaration in the program as
2073
+ * a candidate when almost none of them state nothing anywhere.
2074
+ */
2075
+ export const containsUnstatedPosition = (checker, anchor, declared, depth = 0) => {
2076
+ if (depth > 8)
2077
+ return false;
2078
+ if (positionStatesNothing(checker, anchor, declared))
2079
+ return true;
2080
+ // `Iterable<T>` states the values iteration yields and deliberately does
2081
+ // not state what physical object implements the protocol. A concrete Array,
2082
+ // Set, generator or user iterator returned through that annotation must keep
2083
+ // its own carrier; flattening the interface into a record invents an object
2084
+ // layout for a protocol view. Treat the implementation position as unstated
2085
+ // while `narrowsOnlyUnstatedPositions` below still requires the concrete
2086
+ // type to satisfy this exact standard-library declaration, including `T`.
2087
+ if (isStandardInterfaceType(checker, anchor, 'Iterable', declared))
2088
+ return true;
2089
+ if (declared.isUnion() || declared.isIntersection()) {
2090
+ return declared.types.some((part) => containsUnstatedPosition(checker, anchor, part, depth + 1));
2091
+ }
2092
+ if ((declared.flags & ts.TypeFlags.Object) === 0)
2093
+ return false;
2094
+ const reference = declared;
2095
+ if (reference.target === undefined)
2096
+ return false;
2097
+ return checker.getTypeArguments(reference).some((part) => containsUnstatedPosition(checker, anchor, part, depth + 1));
2098
+ };
2099
+ /**
2100
+ * WHETHER A STATED TYPE AND THE TYPE THAT ACTUALLY FLOWS INTO IT DIFFER ONLY
2101
+ * WHERE THE STATEMENT SAID NOTHING.
2102
+ *
2103
+ * `annotationStatesNothing` is all-or-nothing about one annotation, which is
2104
+ * the right question for a parameter written `: {}` and the wrong one for
2105
+ * hono's `matchResult: Result<[unknown, RouterRoute]>`. That annotation states
2106
+ * plenty -- a two-armed union of tuples of arrays of tuples -- and states
2107
+ * NOTHING at exactly one leaf, the `unknown` where the handler goes. The
2108
+ * program's only writer hands it `Result<[H, RouterRoute]>`, identical
2109
+ * everywhere the annotation spoke and concrete at the one place it did not.
2110
+ *
2111
+ * Reading the annotation as the last word there is what forces a value that is
2112
+ * already exactly right to be rebuilt into a boxed copy of itself -- through
2113
+ * two arrays and three records, which is not a conversion any backend can
2114
+ * render soundly (an array rebuild is a COPY, and a copy is not the array the
2115
+ * caller passed). Reading it as an upper bound instead, satisfied at every
2116
+ * position it constrains, is what lets the value stay itself.
2117
+ *
2118
+ * This is deliberately NOT "the actual type is assignable to the declared
2119
+ * one". Assignability admits a narrowing at a position the program DID state
2120
+ * -- `x: string | number` fed only strings -- and honoring the statement is
2121
+ * this compiler's rule everywhere else. `checker.isTypeAssignableTo` is still
2122
+ * required (the caller asks it), but it is the floor, not the test.
2123
+ */
2124
+ export const narrowsOnlyUnstatedPositions = (checker, anchor, declared, actual, depth = 0) => {
2125
+ if (declared === actual)
2126
+ return true;
2127
+ if (depth > 8)
2128
+ return false;
2129
+ // A statement of nothing accepts anything CONCRETE. `any` on the actual side
2130
+ // is the absence these censuses exist to fill, never an answer to propagate.
2131
+ if (positionStatesNothing(checker, anchor, declared))
2132
+ return (actual.flags & ts.TypeFlags.Any) === 0;
2133
+ // The implementation half of the `Iterable<T>` upper bound described in
2134
+ // `containsUnstatedPosition`: assignability is the checker's proof that the
2135
+ // actual object implements this precise protocol and yields the declared
2136
+ // element. The concrete carrier is therefore strictly more informative at
2137
+ // the one position the annotation leaves open.
2138
+ if (isStandardInterfaceType(checker, anchor, 'Iterable', declared)) {
2139
+ return (actual.flags & ts.TypeFlags.Any) === 0 && checker.isTypeAssignableTo(actual, declared);
2140
+ }
2141
+ // Two spellings of one type -- an alias and its expansion, `Params` and
2142
+ // `Record<string, string>` -- state the identical thing at every position.
2143
+ if (checker.isTypeAssignableTo(actual, declared) && checker.isTypeAssignableTo(declared, actual))
2144
+ return true;
2145
+ const declaredReference = declared;
2146
+ const actualReference = actual;
2147
+ if ((declared.flags & ts.TypeFlags.Object) !== 0 &&
2148
+ (actual.flags & ts.TypeFlags.Object) !== 0 &&
2149
+ declaredReference.target !== undefined &&
2150
+ declaredReference.target === actualReference.target) {
2151
+ const left = checker.getTypeArguments(declaredReference);
2152
+ const right = checker.getTypeArguments(actualReference);
2153
+ if (left.length === 0 || left.length !== right.length)
2154
+ return false;
2155
+ return left.every((part, index) => {
2156
+ const other = right[index];
2157
+ return other !== undefined && narrowsOnlyUnstatedPositions(checker, anchor, part, other, depth + 1);
2158
+ });
2159
+ }
2160
+ // A union member that states its whole carrier is not an open position.
2161
+ // Preserve every such member before allowing call-site evidence to refine
2162
+ // the members that do contain `any`/`unknown`. Otherwise one open arm makes
2163
+ // the whole union look open: `string | ArrayBuffer | ReadableStream<unknown>`
2164
+ // observed at an incomplete indirect call as only `ReadableStream` dropped
2165
+ // the two fully stated body arms, and generated Response construction then
2166
+ // read a string as the stream arm. Hono's `Result<[unknown, Route]>` remains
2167
+ // refinable because each member's differing position is itself unstated.
2168
+ if (declared.isUnion()) {
2169
+ const actualMembers = actual.isUnion() ? actual.types : [actual];
2170
+ for (const member of declared.types) {
2171
+ if (containsUnstatedPosition(checker, anchor, member, depth + 1))
2172
+ continue;
2173
+ const preserved = actualMembers.some((candidate) => checker.isTypeAssignableTo(candidate, member) && checker.isTypeAssignableTo(member, candidate));
2174
+ if (!preserved)
2175
+ return false;
2176
+ }
2177
+ }
2178
+ // A union is matched member-to-member, and NOT as a bijection: `A | B` both
2179
+ // narrowing the same declared member is still a narrowing only at unstated
2180
+ // positions, which is the whole claim. What is refused is an actual member
2181
+ // no declared member covers -- that one is a widening the statement forbids.
2182
+ if (declared.isUnion() && actual.isUnion()) {
2183
+ return actual.types.every((member) => declared.types.some((candidate) => narrowsOnlyUnstatedPositions(checker, anchor, candidate, member, depth + 1)));
2184
+ }
2185
+ if (declared.isUnion()) {
2186
+ return declared.types.some((candidate) => narrowsOnlyUnstatedPositions(checker, anchor, candidate, actual, depth + 1));
2187
+ }
2188
+ return false;
2189
+ };
2190
+ /**
2191
+ * `T | undefined` -> `T`, and ONLY the `undefined` member: a `null` member is
2192
+ * a different absence value and stays.
2193
+ *
2194
+ * Needed where a cell's contents and a READ of that cell disagree about an
2195
+ * absence the language already resolved -- a DEFAULTED parameter, whose slot
2196
+ * carries `undefined` (that is what the default exists to answer) and whose
2197
+ * body binding cannot: `producers/bindings.ts`'s `contributeDefaultedParameter`
2198
+ * strips it there from the compiler's own type table, and this is the same
2199
+ * strip asked of a `ts.Type`, for the censuses that answer a body read.
2200
+ *
2201
+ * `getNonNullableType` is the wrong instrument -- it strips `null` too, and
2202
+ * `p: T | null = null` is ordinary TypeScript whose body really does observe
2203
+ * the `null`.
2204
+ */
2205
+ export const withoutUndefinedMember = (checker, type) => {
2206
+ if (!type.isUnion())
2207
+ return type;
2208
+ const kept = type.types.filter((member) => (member.flags & ts.TypeFlags.Undefined) === 0);
2209
+ if (kept.length === type.types.length || kept.length === 0)
2210
+ return type;
2211
+ const sole = kept.length === 1 ? kept[0] : undefined;
2212
+ if (sole)
2213
+ return sole;
2214
+ const constructing = checker;
2215
+ return typeof constructing.getUnionType === 'function' ? constructing.getUnionType(kept) : type;
2216
+ };
2217
+ /** The class a constructor-object type (`typeof C`) belongs to, or `null` for any other type. */
2218
+ const classOfConstructorType = (type) => type.symbol !== undefined && (type.symbol.flags & ts.SymbolFlags.Class) !== 0 && type.getConstructSignatures().length > 0
2219
+ ? type.symbol
2220
+ : null;
2221
+ /** Whether `a` and `b` are the constructor objects of two different classes -- nominally distinct, whatever their shapes. */
2222
+ export const isDistinctClassConstructorPair = (a, b) => {
2223
+ const first = classOfConstructorType(a);
2224
+ const second = classOfConstructorType(b);
2225
+ return first !== null && second !== null && first !== second;
2226
+ };
2227
+ /** Shape subtyping cannot discard the identity of a class constructor selected at runtime. */
2228
+ export const nominalConstructorChoiceTypeAt = (checker, node, read) => {
2229
+ if (ts.isParenthesizedExpression(node))
2230
+ return nominalConstructorChoiceTypeAt(checker, node.expression, read);
2231
+ if (!ts.isConditionalExpression(node))
2232
+ return null;
2233
+ const arms = [read(node.whenTrue), read(node.whenFalse)].flatMap((type) => (type.isUnion() ? type.types : [type]));
2234
+ if (arms.some((arm) => classOfConstructorType(arm) === null))
2235
+ return null;
2236
+ return disjointUnionTypeOf(checker, arms);
2237
+ };
2238
+ export const widestOf = (checker, types) => {
2239
+ const agree = (other, candidate) => {
2240
+ const candidateArity = soleCallArity(candidate);
2241
+ const otherArity = soleCallArity(other);
2242
+ if (candidateArity !== null && otherArity !== null && candidateArity !== otherArity)
2243
+ return false;
2244
+ // Two DIFFERENT classes' constructor objects never agree, however alike
2245
+ // their shapes: `class {}` beside `class X {}` is structurally assignable
2246
+ // both ways to the checker, but this compiler's `constructor-family`
2247
+ // carrier is nominal (one class per carrier), and a join that picked one
2248
+ // as "the" type made the other's default convert into it --
2249
+ // `[cls = class {}, xCls = class X {}]` read `xCls.name` as `"cls"`.
2250
+ if (isDistinctClassConstructorPair(other, candidate))
2251
+ return false;
2252
+ if (!checker.isTypeAssignableTo(other, candidate))
2253
+ return false;
2254
+ // Assignability is not carriage, the same reason the nominal veto above
2255
+ // exists. A union with a VACUOUS member alongside real ones -- hono's
2256
+ // `Env?: E['Bindings'] | {}` -- absorbs every object type there is, so a
2257
+ // candidate carrying one "covers" observations it says nothing about:
2258
+ // `widestOf([E['Bindings'] | {} | undefined, ExecutionContext |
2259
+ // undefined])` answered the first, and the array built from it
2260
+ // (`parameter-slot.ts`'s rest element, reached through `joinOfWrites`'s
2261
+ // call-site tail join) named no `ExecutionContext` at all -- so
2262
+ // `app.request(path, init, Env, executionCtx)` forwarding a real one had
2263
+ // no conversion into it.
2264
+ //
2265
+ // Re-asked with the candidate's vacuous members removed: coverage that
2266
+ // survives was real and stands, coverage that does not was `{}`'s alone
2267
+ // and this is a disagreement, which every caller already handles (a union
2268
+ // of the observations, or the checker's own answer left standing).
2269
+ //
2270
+ // Only for a candidate that is a UNION with BOTH vacuous and non-vacuous
2271
+ // members. A wholly vacuous candidate is deliberately left exactly as it
2272
+ // was: `{}` is also the type of an EMPTY OBJECT LITERAL the program
2273
+ // evaluated, where it is the most precise statement there is rather than
2274
+ // a non-statement (see `exactEmptyObjectLiteralType`), and the censuses
2275
+ // that must not admit a vacuous ANNOTATION already filter it before they
2276
+ // ever get here (`field-bindings.ts`'s `known`).
2277
+ if (!candidate.isUnion())
2278
+ return true;
2279
+ const stated = withoutVacuousMembers(checker, null, candidate);
2280
+ if (stated === null || stated === candidate)
2281
+ return true;
2282
+ return checker.isTypeAssignableTo(other, stated);
2283
+ };
2284
+ for (const candidate of types) {
2285
+ if (types.every((other) => other === candidate || agree(other, candidate)))
2286
+ return candidate;
2287
+ }
2288
+ return null;
2289
+ };
2290
+ /**
2291
+ * Whether `type` states one value of a wider primitive. `isLiteral()` covers
2292
+ * string/number/bigint literals but, per the checker's own design, never a
2293
+ * boolean literal -- `true`/`false` are distinct intrinsic types, not
2294
+ * `LiteralType`s -- even though `getBaseTypeOfLiteralType` still widens them
2295
+ * to `boolean` correctly when asked. Shared so both call sites below agree.
2296
+ */
2297
+ const hasLiteralForm = (type) => type.isLiteral() || (type.flags & ts.TypeFlags.BooleanLiteral) !== 0;
2298
+ /** `type`, widened off its literal form when it has one -- `"a" + "b"` is `string`, not the literal `"ab"` nobody wrote. */
2299
+ const widenLiteral = (checker, type) => hasLiteralForm(type) ? checker.getBaseTypeOfLiteralType(type) : type;
2300
+ const ARITHMETIC_ONLY_OPERATORS = new Set([
2301
+ ts.SyntaxKind.MinusToken,
2302
+ ts.SyntaxKind.AsteriskToken,
2303
+ ts.SyntaxKind.SlashToken,
2304
+ ts.SyntaxKind.PercentToken,
2305
+ ts.SyntaxKind.AsteriskAsteriskToken,
2306
+ ts.SyntaxKind.AmpersandToken,
2307
+ ts.SyntaxKind.BarToken,
2308
+ ts.SyntaxKind.CaretToken,
2309
+ ts.SyntaxKind.LessThanLessThanToken,
2310
+ ts.SyntaxKind.GreaterThanGreaterThanToken,
2311
+ ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken
2312
+ ]);
2313
+ const LOGICAL_OPERATORS = new Set([
2314
+ ts.SyntaxKind.AmpersandAmpersandToken,
2315
+ ts.SyntaxKind.BarBarToken,
2316
+ ts.SyntaxKind.QuestionQuestionToken
2317
+ ]);
2318
+ const binaryExpressionType = (checker, node, read) => {
2319
+ const op = node.operatorToken.kind;
2320
+ if (op === ts.SyntaxKind.PlusToken || op === ts.SyntaxKind.PlusEqualsToken) {
2321
+ const left = read(node.left);
2322
+ const right = read(node.right);
2323
+ if (!left || !right)
2324
+ return null;
2325
+ // ECMA-262 12.15.5: EITHER operand being a string makes the whole
2326
+ // expression string concatenation.
2327
+ if (stringDomain(left))
2328
+ return widenLiteral(checker, left);
2329
+ if (stringDomain(right))
2330
+ return widenLiteral(checker, right);
2331
+ if (numberDomain(left) && numberDomain(right))
2332
+ return widenLiteral(checker, left);
2333
+ return null;
2334
+ }
2335
+ if (ARITHMETIC_ONLY_OPERATORS.has(op)) {
2336
+ const left = read(node.left);
2337
+ const right = read(node.right);
2338
+ if (!left || !right || !numberDomain(left) || !numberDomain(right))
2339
+ return null;
2340
+ return widenLiteral(checker, left);
2341
+ }
2342
+ if (LOGICAL_OPERATORS.has(op)) {
2343
+ const left = read(node.left);
2344
+ const right = read(node.right);
2345
+ if (!left || !right)
2346
+ return null;
2347
+ const operator = op === ts.SyntaxKind.AmpersandAmpersandToken ? '&&' : op === ts.SyntaxKind.BarBarToken ? '||' : '??';
2348
+ return logicalResultTypeOf(checker, operator, left, right);
2349
+ }
2350
+ return null;
2351
+ };
2352
+ /**
2353
+ * Whether two expressions are the SAME pure read of the same storage, with no
2354
+ * evaluation hidden in either of them.
2355
+ *
2356
+ * Two shapes qualify, and deliberately no others. Property reads can invoke
2357
+ * accessors and arbitrary computed keys can call user code, so this is much
2358
+ * smaller than syntactic equality:
2359
+ *
2360
+ * - two IDENTIFIERS resolving to one symbol. A bare identifier read has no
2361
+ * receiver, no key and no user code behind it at all -- it is strictly
2362
+ * purer than the element access below, not a relaxation of it. Comparing
2363
+ * SYMBOLS rather than source spelling keeps shadowed bindings distinct.
2364
+ * - two element accesses reading one slot of one checker-proven Array
2365
+ * through an identifier-bound receiver and an identifier/literal index --
2366
+ * exactly the carrier this compiler lowers through
2367
+ * `ArrayObject::elementAt`.
2368
+ *
2369
+ * Used only across the authenticated, pure `Array.isArray` call immediately
2370
+ * below. There is therefore no operation between the two reads that can
2371
+ * mutate the storage -- which is why a `let` binding is admitted alongside a
2372
+ * `const` one: nothing can run between a conditional's condition and the arm
2373
+ * it selects.
2374
+ */
2375
+ const sameStablePureRead = (checker, left, right) => {
2376
+ while (ts.isParenthesizedExpression(left) || ts.isNonNullExpression(left))
2377
+ left = left.expression;
2378
+ while (ts.isParenthesizedExpression(right) || ts.isNonNullExpression(right))
2379
+ right = right.expression;
2380
+ if (ts.isIdentifier(left) && ts.isIdentifier(right)) {
2381
+ const symbol = checker.getSymbolAtLocation(left);
2382
+ return symbol !== undefined && symbol === checker.getSymbolAtLocation(right);
2383
+ }
2384
+ if (!ts.isElementAccessExpression(left) || !ts.isElementAccessExpression(right))
2385
+ return false;
2386
+ if (!ts.isIdentifier(left.expression) || !ts.isIdentifier(right.expression))
2387
+ return false;
2388
+ const leftReceiver = checker.getSymbolAtLocation(left.expression);
2389
+ const rightReceiver = checker.getSymbolAtLocation(right.expression);
2390
+ if (!leftReceiver || leftReceiver !== rightReceiver)
2391
+ return false;
2392
+ const receiverType = checker.getNonNullableType(checker.getTypeAtLocation(left.expression));
2393
+ if (!checker.isArrayType(receiverType))
2394
+ return false;
2395
+ const leftKey = left.argumentExpression;
2396
+ const rightKey = right.argumentExpression;
2397
+ if (!leftKey || !rightKey)
2398
+ return false;
2399
+ if (ts.isIdentifier(leftKey) && ts.isIdentifier(rightKey)) {
2400
+ const leftSymbol = checker.getSymbolAtLocation(leftKey);
2401
+ return leftSymbol !== undefined && leftSymbol === checker.getSymbolAtLocation(rightKey);
2402
+ }
2403
+ if (ts.isNumericLiteral(leftKey) && ts.isNumericLiteral(rightKey))
2404
+ return leftKey.text === rightKey.text;
2405
+ if (ts.isStringLiteralLike(leftKey) && ts.isStringLiteralLike(rightKey))
2406
+ return leftKey.text === rightKey.text;
2407
+ return false;
2408
+ };
2409
+ /**
2410
+ * The array carrier selected by the normalizing idiom
2411
+ *
2412
+ * Array.isArray(values[i]) ? values[i] : [values[i]]
2413
+ * Array.isArray(data) ? data : [data]
2414
+ *
2415
+ * or `null` when the expression does not prove that one carrier.
2416
+ *
2417
+ * A binding census can know more about `values[i]` than TypeScript's checker
2418
+ * does. Three's `UniformsGroup.copy` is the measured case: the census has
2419
+ * `Uniform | Uniform[]`, while the JSDoc-backed array literal still has
2420
+ * `Uniform[]`. The generic conditional join sees `Uniform | Uniform[]` and
2421
+ * republishes that union, losing the fact the condition just established;
2422
+ * the subsequent numeric read then correctly refuses a union whose scalar arm
2423
+ * is not indexable.
2424
+ *
2425
+ * The rule is tied to the real global `Array.isArray`, to a repeated stable
2426
+ * PURE READ -- a bare identifier, or one slot of one proven native Array --
2427
+ * and to a one-element alternate containing that same read. The IDENTIFIER
2428
+ * form is what a one-or-many parameter is normally written over -- hono's
2429
+ * `node-server` websocket bridge is `const datas = Array.isArray(data) ?
2430
+ * data : [data]` over `data: WebSocketData` -- and without it the join
2431
+ * republished the whole union, so the `for (const data of datas)` that
2432
+ * follows read an element off a carrier whose scalar arms are not indexable
2433
+ * at all. Every array arm already discovered for the slot must fit the
2434
+ * alternate's array type. Thus the answer is the carrier both reachable arms
2435
+ * share; this does not turn a general predicate or a mutable/accessor read
2436
+ * into a narrowing.
2437
+ */
2438
+ export const normalizedArrayConditionalType = (checker, node, read) => {
2439
+ const condition = node.condition;
2440
+ if (!ts.isCallExpression(condition) || condition.arguments.length !== 1)
2441
+ return null;
2442
+ const callee = condition.expression;
2443
+ if (!ts.isPropertyAccessExpression(callee) || callee.name.text !== 'isArray')
2444
+ return null;
2445
+ const receiverType = checker.getTypeAtLocation(callee.expression);
2446
+ if (!isStandardInterfaceType(checker, callee.expression, 'ArrayConstructor', receiverType))
2447
+ return null;
2448
+ const tested = condition.arguments[0];
2449
+ if (!tested || !sameStablePureRead(checker, tested, node.whenTrue))
2450
+ return null;
2451
+ if (!ts.isArrayLiteralExpression(node.whenFalse) || node.whenFalse.elements.length !== 1)
2452
+ return null;
2453
+ const singleton = node.whenFalse.elements[0];
2454
+ if (!singleton || ts.isSpreadElement(singleton) || !sameStablePureRead(checker, tested, singleton))
2455
+ return null;
2456
+ const alternate = read(node.whenFalse);
2457
+ const source = read(tested);
2458
+ if (!alternate || !source || !checker.isArrayType(alternate))
2459
+ return null;
2460
+ const sourceMembers = source.isUnion() ? source.types : [source];
2461
+ // A `readonly T[]` member is NOT admitted here, although `readonly` has no
2462
+ // physical reading in this compiler (`structural.ts` publishes every array
2463
+ // as `readonly: false`) and node-server's
2464
+ // `WebSocketData = string | ArrayBuffer | Uint8Array | readonly Uint8Array[]`
2465
+ // is refused for exactly that spelling. Admitting it was measured: the
2466
+ // arm's element is NARROWER than the alternate's (`Uint8Array` against the
2467
+ // whole union), so the answer widens an array's element -- and the binding
2468
+ // conversion this function feeds then selected an arm that produced an
2469
+ // EMPTY array at runtime instead of refusing. A plain
2470
+ // `array-object(record) -> array-object(tagged-union)` is refused outright
2471
+ // (`conversion:array-object(...)->array-object(...)`: no runtime conversion
2472
+ // installed), which is the correct fail-closed answer; reaching the same
2473
+ // widening through this idiom's arm selection turned that refusal into a
2474
+ // wrong answer, so the arm selection is what has to be fixed before the
2475
+ // spelling can be admitted.
2476
+ const arrayMembers = sourceMembers.filter((member) => checker.isArrayType(checker.getNonNullableType(member)));
2477
+ if (!arrayMembers.every((member) => checker.isTypeAssignableTo(member, alternate)))
2478
+ return null;
2479
+ // With no array arm the authenticated predicate is statically false only
2480
+ // for a concrete class instance. An interface/object/type parameter can
2481
+ // still describe an Array value structurally, and `any`/`unknown` state no
2482
+ // carrier at all, so none of those license the same conclusion.
2483
+ if (arrayMembers.length === 0) {
2484
+ const symbol = checker.getNonNullableType(source).getSymbol();
2485
+ if (!symbol || (symbol.flags & ts.SymbolFlags.Class) === 0)
2486
+ return null;
2487
+ }
2488
+ return alternate;
2489
+ };
2490
+ /**
2491
+ * The type an `arg is any[]` predicate REALLY establishes, when the checker
2492
+ * answered with the intersection it falls back to.
2493
+ *
2494
+ * `Array.isArray`'s `lib.es5.d.ts` signature is `isArray(arg: any): arg is
2495
+ * any[]`, and TypeScript narrows a union by a predicate by KEEPING the
2496
+ * constituents assignable to the predicate's type. Where none is, it does not
2497
+ * answer `never` -- it answers the INTERSECTION `T & any[]`, distributed over
2498
+ * `T`'s arms, and every read through it is typed `any`:
2499
+ *
2500
+ * Array.isArray(value) ? value[0] : value // value: string
2501
+ * Array.isArray(pattern) ? pattern[0] : p // readonly [...] | '*'
2502
+ *
2503
+ * (`@hono/node-server`'s `createUpgradeRequest` and hono's trie router; a
2504
+ * `readonly` tuple is not assignable to the mutable `any[]` either, so the
2505
+ * fallback fires for a type that IS an array.) That `any` is an artifact of a
2506
+ * failed narrowing, not a boundary the program declared: the value is a
2507
+ * `std::string` or a fixed tuple and the read has a stated answer either way.
2508
+ * Carried as `dynamic` it reached the backend as a result with no absence
2509
+ * materialization, and boxing the read to make it compile is the shortcut this
2510
+ * compiler does not take.
2511
+ *
2512
+ * `any[]` states no carrier at all (`isUnusableEvidence`), so intersecting
2513
+ * with it adds nothing physical; what it adds is the assertion that the value
2514
+ * is an array HERE. So the answer is the array/tuple constituents of the rest
2515
+ * -- and with none of those the predicate is statically false for a value that
2516
+ * has a carrier, the arm is dead, and the honest type is the one the value
2517
+ * already had. Only a SINGLE surviving subject is answered: two array arms
2518
+ * would need a join this is not the place to take.
2519
+ */
2520
+ export const arrayPredicateNarrowedTypeOf = (checker, type) => {
2521
+ const isPredicateArray = (part) => checker.isArrayType(part) && isUnusableEvidence(checker.getTypeArguments(part)[0] ?? part);
2522
+ const subjects = [];
2523
+ for (const member of type.isUnion() ? type.types : [type]) {
2524
+ if (!member.isIntersection())
2525
+ return null;
2526
+ const rest = member.types.filter((part) => !isPredicateArray(part));
2527
+ const subject = rest.length === 1 ? rest[0] : undefined;
2528
+ if (subject === undefined || rest.length === member.types.length)
2529
+ return null;
2530
+ subjects.push(subject);
2531
+ }
2532
+ const arrays = subjects.filter((subject) => checker.isArrayType(subject) || checker.isTupleType(subject));
2533
+ if (arrays.length === 1)
2534
+ return arrays[0] ?? null;
2535
+ return arrays.length === 0 && subjects.length === 1 ? (subjects[0] ?? null) : null;
2536
+ };
2537
+ /**
2538
+ * The element an `x[k]` read produces when the checker typed it `any` only
2539
+ * because `x` is standing in an `arg is any[]` narrowing's intersection.
2540
+ *
2541
+ * The key is answered off the narrowed subject exactly as any other read is:
2542
+ * a literal key names a member (a tuple's `[0]` is its first element type,
2543
+ * not the join of all of them), and anything else takes the receiver's own
2544
+ * index signature -- `String`'s is `readonly [index: number]: string`, which
2545
+ * is the carrier `stringIndexText`'s `charAt` already renders.
2546
+ */
2547
+ export const arrayPredicateNarrowedElementTypeOf = (checker, node) => {
2548
+ if (!isUnusableEvidence(checker.getTypeAtLocation(node)))
2549
+ return null;
2550
+ const narrowed = arrayPredicateNarrowedTypeOf(checker, checker.getTypeAtLocation(node.expression));
2551
+ if (narrowed === null)
2552
+ return null;
2553
+ const name = literalMemberNameOf(node);
2554
+ const property = name === null ? undefined : checker.getPropertyOfType(narrowed, name);
2555
+ if (property) {
2556
+ const member = checker.getTypeOfSymbolAtLocation(property, node);
2557
+ return isUnusableEvidence(member) ? null : member;
2558
+ }
2559
+ const key = node.argumentExpression;
2560
+ return key ? indexedTypeOf(checker, narrowed, checker.getTypeAtLocation(key), node) : null;
2561
+ };
2562
+ /**
2563
+ * The outcome of `x === undefined`, `x !== null`, `x == null` (either side
2564
+ * literal) when `read` types `x` as nothing but the nullish value(s) it is
2565
+ * compared with or against -- `null` when the operands do not decide it.
2566
+ *
2567
+ * `( gl[ p ] !== undefined ) ? gl[ p ] : null` (three's `WebGLUtils.convert`)
2568
+ * is the shape: once the element read is proved `undefined`, the arms are
2569
+ * `undefined` and `null`, which `joinOfWrites` rightly refuses to join -- but
2570
+ * the untaken arm contributes no value, so the conditional is its other arm.
2571
+ * The literal side is recognised by syntax and the standard `undefined`
2572
+ * binding's identity, never read, so a census's read of it cannot attribute a
2573
+ * refusal of its own.
2574
+ */
2575
+ const decidedNullishEqualityOf = (checker, condition, read) => {
2576
+ let test = condition;
2577
+ while (ts.isParenthesizedExpression(test))
2578
+ test = test.expression;
2579
+ if (!ts.isBinaryExpression(test))
2580
+ return null;
2581
+ const operator = test.operatorToken.kind;
2582
+ const strict = operator === ts.SyntaxKind.EqualsEqualsEqualsToken || operator === ts.SyntaxKind.ExclamationEqualsEqualsToken;
2583
+ const loose = operator === ts.SyntaxKind.EqualsEqualsToken || operator === ts.SyntaxKind.ExclamationEqualsToken;
2584
+ if (!strict && !loose)
2585
+ return null;
2586
+ const literalNullish = (side) => {
2587
+ let value = side;
2588
+ while (ts.isParenthesizedExpression(value))
2589
+ value = value.expression;
2590
+ if (value.kind === ts.SyntaxKind.NullKeyword)
2591
+ return ts.TypeFlags.Null;
2592
+ if (ts.isVoidExpression(value))
2593
+ return ts.TypeFlags.Undefined;
2594
+ return ts.isIdentifier(value) && value.text === 'undefined' && isStandardGlobalValue(checker, value, 'undefined')
2595
+ ? ts.TypeFlags.Undefined
2596
+ : null;
2597
+ };
2598
+ const left = literalNullish(test.left);
2599
+ const right = literalNullish(test.right);
2600
+ const literal = left ?? right;
2601
+ if (literal === null || (left !== null && right !== null))
2602
+ return null;
2603
+ const operand = read(left === null ? test.left : test.right);
2604
+ if (!operand)
2605
+ return null;
2606
+ const flags = operand.flags & NULLISH_FLAGS;
2607
+ if (flags === 0 || (operand.flags & ~NULLISH_FLAGS) !== 0)
2608
+ return null;
2609
+ // `==` treats `null` and `undefined` as equal; `===` only a match of each.
2610
+ const equal = loose ? true : flags === literal ? true : (flags & literal) === 0 ? false : null;
2611
+ if (equal === null)
2612
+ return null;
2613
+ const negated = operator === ts.SyntaxKind.ExclamationEqualsEqualsToken || operator === ts.SyntaxKind.ExclamationEqualsToken;
2614
+ return negated ? !equal : equal;
2615
+ };
2616
+ /**
2617
+ * `node`'s own type, derived from its immediate operands via `read`.
2618
+ *
2619
+ * Handles exactly the composite shapes described in this file's header
2620
+ * comment, and nothing else: this is a LEAF function, not a walker -- it
2621
+ * asks `read` for each operand's type and combines the answers by the
2622
+ * operator's own fixed rule, doing no traversal of its own beyond that one
2623
+ * level. Every caller supplies its own `read` (its `known ?? resolve`), so
2624
+ * this function's own recursion depth is always exactly one.
2625
+ */
2626
+ export const derivedExpressionType = (checker, node, read) => {
2627
+ if (ts.isConditionalExpression(node)) {
2628
+ const whenTrue = read(node.whenTrue);
2629
+ const whenFalse = read(node.whenFalse);
2630
+ // A ternary's two arms are a two-element WRITE SET to one storage
2631
+ // location -- the value the expression evaluates to. `cond ? x : null`
2632
+ // is exactly the "sometimes empty, otherwise T" shape `joinOfWrites`
2633
+ // exists for (see its own header comment), and `cond ? 5126 : 5131`
2634
+ // is exactly the same literal-form-agreement shape. `widestOf` alone
2635
+ // answers FIRST and unchanged; only a pair it already refused reaches
2636
+ // `joinOfWrites`'s nullish-partition and literal-widening retries. Kept
2637
+ // to the ONE join this compiler owns rather than a second copy of its
2638
+ // reasoning.
2639
+ const joined = whenTrue && whenFalse ? joinOfWrites(checker, [whenTrue, whenFalse]) : null;
2640
+ if (joined)
2641
+ return joined;
2642
+ // Only a pair the join refused asks the condition: a census that attributes
2643
+ // a refusal to every unresolved operand must not see one more read here
2644
+ // than it did before on any conditional it already answered.
2645
+ const decided = decidedNullishEqualityOf(checker, node.condition, read);
2646
+ return decided === null ? null : decided ? whenTrue : whenFalse;
2647
+ }
2648
+ if (ts.isBinaryExpression(node))
2649
+ return binaryExpressionType(checker, node, read);
2650
+ if (ts.isTemplateExpression(node)) {
2651
+ // Defensive only -- see header comment. `ToString` is total, so the
2652
+ // checker already reports `string` here without this module's help in
2653
+ // every case observed; this exists so a genuine surprise refuses
2654
+ // instead of throwing.
2655
+ const own = checker.getTypeAtLocation(node);
2656
+ return isUnusableEvidence(own) ? null : own;
2657
+ }
2658
+ return null;
2659
+ };
2660
+ /** `null`/`undefined` and nothing else: a write stating the storage is EMPTY rather than naming a type for it. */
2661
+ const NULLISH_FLAGS = ts.TypeFlags.Null | ts.TypeFlags.Undefined;
2662
+ export const isNullishType = (type) => (type.flags & NULLISH_FLAGS) !== 0 && (type.flags & ~NULLISH_FLAGS) === 0;
2663
+ /** `type` off its literal form, the same rule `widenLiteral` above states. */
2664
+ const widenLiteralForm = (checker, type) => hasLiteralForm(type) ? checker.getBaseTypeOfLiteralType(type) : type;
2665
+ /**
2666
+ * The join of a WRITE SET -- every value the program stores into one storage
2667
+ * location -- once the two things `widestOf` reads as a disagreement but
2668
+ * which are not one have been accounted for; or `null` when the writes
2669
+ * genuinely do not agree.
2670
+ *
2671
+ * `widestOf` answers FIRST and unchanged, so every location bound today binds
2672
+ * to exactly the same type; only a set it has already refused reaches the
2673
+ * rest of this.
2674
+ *
2675
+ * ## A nullish write states ABSENCE, not a rival type
2676
+ *
2677
+ * `widestOf` asks whether one OBSERVED type covers every other, and under
2678
+ * `strictNullChecks` no object type covers `null`. So the single commonest
2679
+ * shape a write-set census exists for -- `let currentProgram = null;` filled
2680
+ * in later with a real value and set back to `null` on teardown, or
2681
+ * `this.view = null` in a constructor and a real object in a setter --
2682
+ * refuses, attributed `writes-disagree`: the join read the location's own
2683
+ * emptiness as a type competing for the slot. It is not one. Storage that is
2684
+ * sometimes empty and otherwise holds `T` is exactly `T | null` -- the
2685
+ * `optional(T, null)` carrier this compiler already has, not a union of its
2686
+ * own making. Every constituent is still a type the program itself wrote.
2687
+ *
2688
+ * `getNullableType` is the checker's own constructor for that union, the
2689
+ * same one `return-bindings.ts` uses for a `Map.get` result and
2690
+ * `parameter-slot.ts` for a defaulted parameter, and it flattens -- so a
2691
+ * write already typed `T | null` re-joins to `T | null` rather than nesting.
2692
+ *
2693
+ * The observed nullish FLAGS are carried through rather than fixed: writes
2694
+ * holding `null` yield `T | null`, `undefined` yields `T | undefined`, both
2695
+ * yield both. Answering `null` where the program only ever wrote `undefined`
2696
+ * (or the reverse) would be inventing an inhabitant no census here may
2697
+ * invent. And a set that is ENTIRELY nullish is left to `widestOf`, which
2698
+ * already answers it on its own.
2699
+ *
2700
+ * ## A literal FORM is not a disagreement either
2701
+ *
2702
+ * The other shape is storage whose every write is a different LITERAL of one
2703
+ * primitive: `let type;` in three's `WebGLAttributes.js` is written `5126`,
2704
+ * `5131`, `5123`, `5122`, `5125`, `5124`, `5120`, `5121` -- eight writes,
2705
+ * eight literal types, none covering another, refused. The storage question
2706
+ * has an answer nobody has to invent: `number`. It is TypeScript's own
2707
+ * answer too -- a `let` initialized with `5126` is widened to `number` by
2708
+ * the language's mutable-binding rule, and the literal type survives here
2709
+ * only because these censuses read the RIGHT-HAND SIDE expression rather
2710
+ * than the declaration. `widenLiteral` above states the same rule for the
2711
+ * same reason (`"a" + "b"` is `string`, not the literal `"ab"` nobody
2712
+ * wrote). Tried only after the unwidened join has refused, so storage whose
2713
+ * writes DO agree on a literal keeps it.
2714
+ *
2715
+ * ## Why this is shared rather than copied
2716
+ *
2717
+ * `local-bindings.ts` (a `let`/`var` cell) and `field-bindings.ts` (a class
2718
+ * field) ask the identical question of two different declaration kinds, and
2719
+ * a field written `null` in the constructor and filled in later is the same
2720
+ * shape as the cell this landed for. Two copies of a join rule is the
2721
+ * "two authorities" defect this compiler keeps paying for -- the same
2722
+ * reasoning that made `annotationStatesNothing` shared. One rule, one file,
2723
+ * asked by both.
2724
+ */
2725
+ export const joinOfWrites = (checker, types) => {
2726
+ const direct = widestOf(checker, types);
2727
+ if (direct)
2728
+ return direct;
2729
+ let observed = 0;
2730
+ const present = [];
2731
+ for (const type of types) {
2732
+ if (isNullishType(type))
2733
+ observed |= type.flags & NULLISH_FLAGS;
2734
+ else
2735
+ present.push(type);
2736
+ }
2737
+ if (present.length === 0)
2738
+ return null;
2739
+ const joined = (observed === 0 ? null : widestOf(checker, present)) ??
2740
+ widestOf(checker, present.map((part) => widenLiteralForm(checker, part)));
2741
+ if (!joined)
2742
+ return null;
2743
+ return observed === 0 ? joined : checker.getNullableType(joined, observed);
2744
+ };
2745
+ /**
2746
+ * A member with no evidence at all -- vetoes the whole set (see
2747
+ * `disjointArmsOf`). Deliberately wider than `isUnusableEvidence` above:
2748
+ * `unknown` is a genuine dynamic boundary here too, not merely a case that
2749
+ * other join rules leave alone.
2750
+ *
2751
+ * Exported for `parameter-bindings.ts`'s `restElementTypeAt`: a rest
2752
+ * parameter's own binding can be REASSIGNED in the body (`params =
2753
+ * enhanceLogMessage(params)`), and that write is evidence about the SAME
2754
+ * cell the call-site tail is joined into -- an `Array<any>`-returning
2755
+ * reassignment is exactly the "genuine dynamic boundary" this test already
2756
+ * names, not a second question needing its own copy of the flag set.
2757
+ */
2758
+ export const carriesNoEvidence = (type) => (type.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown | ts.TypeFlags.Void | ts.TypeFlags.Never)) !== 0;
2759
+ /**
2760
+ * The DISTINCT, pairwise-disjoint members of `types` -- every one a real
2761
+ * type, none of them subsuming another -- or `null` when the set cannot
2762
+ * safely become one union.
2763
+ *
2764
+ * `joinOfWrites` above answers "is there ONE type every write agrees on".
2765
+ * This is the question that only gets asked once that has already failed:
2766
+ * is the DISAGREEMENT ITSELF the answer? `A | B | C`, where `A`, `B`, `C` are
2767
+ * exactly the types the program's own write sites used, is not a guess when
2768
+ * every one of them is real and none of them overlaps another -- it is
2769
+ * precisely what the program does. This compiler's `tagged-union`
2770
+ * representation (`representation/model.ts`) exists for it.
2771
+ *
2772
+ * Two members overlap when either is assignable to the other -- the SAME
2773
+ * `checker.isTypeAssignableTo` `widestOf`'s own `agree` reads a single
2774
+ * covering candidate from above, applied PAIRWISE instead of one-to-all.
2775
+ * Assignable in one direction only is a subsumption (a literal `5` inside
2776
+ * `number`, or one record type's fields a strict subset of another's) --
2777
+ * accepting it would let a value that is honestly a `B` also match arm `A`,
2778
+ * which is a mis-selection, not a conservative one, so the WHOLE set
2779
+ * refuses rather than dropping the overlapping member. Assignable both ways
2780
+ * is the same member spelled twice (two structurally-identical types, or
2781
+ * two references to one declaration) and collapses to one arm silently,
2782
+ * the same reduction `representation/union.ts`'s own `canonicalMembersOf`
2783
+ * performs one layer down. Neither direction is exactly ECMAScript's own
2784
+ * "no runtime value can satisfy both", which is the fact a tagged union's
2785
+ * arms need to be told apart at all -- see that file's own module comment.
2786
+ *
2787
+ * A member that states no evidence at all (`any`/`unknown`/`void`/`never`)
2788
+ * vetoes the whole set outright: unioning a real type with "nothing was
2789
+ * declared" would launder the missing statement as if it were one more arm,
2790
+ * and `void`/`never` are refusals about the STORAGE, not values competing
2791
+ * for the slot.
2792
+ *
2793
+ * Cardinality is not missing evidence. Preserve every admitted member of a
2794
+ * finite write set; representation planning owns its storage and dispatch
2795
+ * costs. An earlier four-arm cutoff erased complete five-way inputs and
2796
+ * made downstream forwarding indistinguishable from an unknown caller.
2797
+ */
2798
+ export const disjointArmsOf = (checker, types) => {
2799
+ const arms = [];
2800
+ for (const type of types) {
2801
+ if (carriesNoEvidence(type))
2802
+ return null;
2803
+ let duplicate = false;
2804
+ for (const existing of arms) {
2805
+ // Two different classes' constructor objects are disjoint by identity,
2806
+ // whatever the checker says of their shapes -- `widestOf`'s rule.
2807
+ if (isDistinctClassConstructorPair(type, existing))
2808
+ continue;
2809
+ const forward = checker.isTypeAssignableTo(type, existing);
2810
+ const backward = checker.isTypeAssignableTo(existing, type);
2811
+ if (forward && backward) {
2812
+ duplicate = true;
2813
+ break;
2814
+ }
2815
+ if (forward || backward)
2816
+ return null; // one member subsumes the other: not disjoint
2817
+ }
2818
+ if (!duplicate)
2819
+ arms.push(type);
2820
+ }
2821
+ return arms.length >= 2 ? arms : null;
2822
+ };
2823
+ /**
2824
+ * The full member list for a SYNTHESIZED union carrier, once `joinOfWrites`
2825
+ * has already refused -- every present (non-nullish) write partitioned the
2826
+ * identical way `joinOfWrites` partitions them, checked for disjointness via
2827
+ * `disjointArmsOf`, with the observed absence values (`null`/`undefined`)
2828
+ * carried through UNCHANGED as members rather than folded into a flag here.
2829
+ *
2830
+ * That last point is deliberate, not an oversight: this function answers a
2831
+ * STRUCTURAL question ("what are this union's members"), not a `ts.Type`
2832
+ * one -- `ts.TypeChecker.getUnionType` is not on the public surface (see
2833
+ * `absent-globals.ts` and `producers/bindings.ts`'s own comments on the same
2834
+ * wall), so unlike `joinOfWrites` this cannot hand back one `ts.Type` a
2835
+ * caller re-derives structurally. It hands back the member LIST instead, for
2836
+ * a caller that is about to `table.intern({ kind: 'union', members:
2837
+ * list.map(typeOf) })` directly -- and `representation/union.ts`'s own
2838
+ * `deriveUnion` already partitions absent members from present ones and
2839
+ * wraps the result in `optional` exactly as `joinOfWrites` would have, so
2840
+ * passing the nullish members through as ordinary list entries here, rather
2841
+ * than pre-collapsing them, is asking that ONE authority to do it once
2842
+ * instead of a second copy of the same partition living here too.
2843
+ */
2844
+ export const disjointUnionMembersOf = (checker, types) => {
2845
+ const present = [];
2846
+ const nullish = [];
2847
+ const atomsOf = (type) => (type.isUnion() ? type.types.flatMap(atomsOf) : [type]);
2848
+ for (const type of types)
2849
+ for (const atom of atomsOf(type)) {
2850
+ const widened = widenLiteralForm(checker, atom);
2851
+ if (isNullishType(widened)) {
2852
+ if (!nullish.some((seen) => seen.flags === widened.flags))
2853
+ nullish.push(widened);
2854
+ }
2855
+ else
2856
+ present.push(widened);
2857
+ }
2858
+ const arms = disjointArmsOf(checker, present);
2859
+ return arms ? [...arms, ...nullish] : null;
2860
+ };
2861
+ /**
2862
+ * `disjointUnionMembersOf`, answered as ONE `ts.Type` -- for a census whose
2863
+ * contract is a `ts.Type` and whose every consumer reads one.
2864
+ *
2865
+ * `collection-bindings.ts`'s array-element census is that census: every
2866
+ * sibling write-set census (a `let` cell, a class field, a parameter, a
2867
+ * return) already answers a disagreeing write set as a disjoint tagged union
2868
+ * through its own `unionArmsAt` channel, while the array census asked
2869
+ * `joinOfWrites` alone and REFUSED the same disagreement
2870
+ * (`array:elements-disagree`). `var xs = []; xs.push(1); xs.push('a')` is the
2871
+ * shape: the array's storage fell to the box, and every `push` boxed its
2872
+ * argument on the way in, for a program that declared nothing dynamic.
2873
+ *
2874
+ * Two things make the `ts.Type` form the right one here rather than a fourth
2875
+ * arms channel. The census's array answers travel through `arrayElementAt`/
2876
+ * `arrayElementForRead`/`arrayElementForOwner` into three other censuses that
2877
+ * read a `ts.Type` (`local-bindings.ts`, `return-bindings.ts`,
2878
+ * `field-bindings.ts`), so a list would leave every one of them answering the
2879
+ * checker's `any` for a union the storage already carries. And the checker's
2880
+ * OWN evolving-array machinery settles the SAME array to the SAME union at
2881
+ * every reference it can finalize (`xs.join(...)` after the pushes is `(string
2882
+ * | number)[]` there): TypeScript widens each pushed value off its literal form
2883
+ * (`addEvolvingArrayElementType`, `getBaseTypeOfLiteralType`) and unions the
2884
+ * results. Building the union through the checker from the identically
2885
+ * widened members yields the IDENTICAL `ts.Type` object (verified: `built ===
2886
+ * settled` for `[number, string, boolean]`), so the storage the census types,
2887
+ * the reads the checker settled, and the `push` slots
2888
+ * (`structural.ts`'s `evolvingArrayMemberTypeAt`) intern to one structural
2889
+ * type with no conversion between them. An arms list interned separately
2890
+ * could not promise that.
2891
+ *
2892
+ * Widening is therefore part of the rule, not a convenience: unwidened, `1`
2893
+ * and `"a"` are two disjoint LITERAL arms, and a storage of `1 | "a"` would be
2894
+ * a second authority beside the checker's `string | number` at every settled
2895
+ * read. `disjointUnionMembersOf`'s own soundness test (no member subsumes
2896
+ * another) is applied unchanged to the
2897
+ * widened members, so a set the cell census would refuse is refused here too.
2898
+ *
2899
+ * Built through the checker's internal `getUnionType`, the same guarded reach
2900
+ * `withoutUndefinedMember` above and `field-bindings.ts`'s `withNullish` make;
2901
+ * a checker without it answers `null`, which is the refusal the caller already
2902
+ * handles.
2903
+ */
2904
+ export const disjointUnionTypeOf = (checker, types) => {
2905
+ const members = disjointUnionMembersOf(checker, types.map((type) => widenLiteralForm(checker, type)));
2906
+ if (!members)
2907
+ return null;
2908
+ const constructing = checker;
2909
+ return typeof constructing.getUnionType === 'function' ? constructing.getUnionType(members) : null;
2910
+ };
2911
+ // -----------------------------------------------------------------------
2912
+ // CALLABLE VALUE FLOW -- moved here from a would-be sibling module because
2913
+ // `normalize/` sits at the architecture gate's directory-file cap. This
2914
+ // section answers `parameter-bindings.ts`'s one question about a reference
2915
+ // to a named function -- "what value does it stand for" -- plus the two
2916
+ // symbol-anchored ALIAS evidence indexes (`indexNamedCallables`,
2917
+ // `indexAliasEvidence`) that let a call through a resolved member or a
2918
+ // selector's result count as a real call site of the function it names.
2919
+ // -----------------------------------------------------------------------
2920
+ /**
2921
+ * The parts of `parameter-bindings.ts` that answer one question --
2922
+ * "what value does this reference of a named function's identifier stand
2923
+ * for" -- without touching that module's own fixpoint state. Moved here so
2924
+ * `parameter-bindings.ts` has room, under the architecture gate, for the
2925
+ * value-flow evidence this module also builds: `indexNamedCallables` and
2926
+ * `indexAliasEvidence`, below.
2927
+ */
2928
+ /** Whether this declaration is one of the five function-like shapes the parameter-binding census tracks. */
2929
+ export const isTrackedCallable = (node) => ts.isFunctionDeclaration(node) ||
2930
+ ts.isFunctionExpression(node) ||
2931
+ ts.isMethodDeclaration(node) ||
2932
+ ts.isArrowFunction(node) ||
2933
+ ts.isConstructorDeclaration(node);
2934
+ /**
2935
+ * The real callee and the arguments that actually reach it, once an explicit-
2936
+ * `this` wrapper -- `.call( thisArg, ...args )` or `.apply( thisArg, [ ...
2937
+ * args ] )` -- is unwrapped, or `null` when this call is neither.
2938
+ *
2939
+ * `EventDispatcher.dispatchEvent` calls every registered listener as
2940
+ * `array[ i ].call( this, event )`: a call to `array[ i ]`, with ONE argument,
2941
+ * not a call to `Function.prototype.call` with two. Left wrapped, `checker.
2942
+ * getResolvedSignature` resolves `.call`'s own (unrelated) ambient signature
2943
+ * successfully -- it is not `any`, so it never fell through to the fallback
2944
+ * that would have resolved the real callee -- and the call vanished from
2945
+ * every candidate's evidence without a trace: not refused, simply never
2946
+ * counted. `collect` skips recording checker attribution for these and
2947
+ * `attributeCalls`/`agreedArgumentType` read this map instead of the raw
2948
+ * node, so the SAME machinery that already resolves an ordinary call site's
2949
+ * callee and arguments does the resolving here too, just against `callee`
2950
+ * and `args` rather than `call.expression` and `call.arguments`.
2951
+ *
2952
+ * `.apply` is unwrapped only when its argument list is a literal array with
2953
+ * no spread (`.apply( this, [ a, b ] )`) -- anything else (a spread, a
2954
+ * variable holding the array) stays wrapped rather than guessed at, exactly
2955
+ * the same "refuse rather than invent" rule this module uses everywhere
2956
+ * else.
2957
+ *
2958
+ * The RECEIVER -- `call.expression.expression`, `array[ i ]` above -- must
2959
+ * itself be a FUNCTION VALUE before any of this fires. `.call`/`.apply` are
2960
+ * ordinary member names, and a program is free to declare its own object with
2961
+ * a `.call( ... )` or `.apply( ... )` method (a Command/Strategy pattern, a
2962
+ * Callable-shaped API): unwrapping THAT receiver would silently replace its
2963
+ * real callee and arguments with wrong ones, from a name match with no
2964
+ * relationship to `Function.prototype.call`/`.apply` at all. The receiver's
2965
+ * own static type having at least one CALL SIGNATURE is what makes it
2966
+ * actually a function value -- the same fact `parameter-bindings.ts`'s
2967
+ * `isUnannotated` reads off a `Function`-typed parameter, asked here of the
2968
+ * `.call`/`.apply` receiver instead.
2969
+ */
2970
+ export const unwrapExplicitThisCall = (checker, call) => {
2971
+ if (!ts.isPropertyAccessExpression(call.expression))
2972
+ return null;
2973
+ const name = call.expression.name.text;
2974
+ if (name !== 'call' && name !== 'apply')
2975
+ return null;
2976
+ const member = checker.getSymbolAtLocation(call.expression.name);
2977
+ if (!member?.declarations?.length || !member.declarations.every((declaration) => declaration.getSourceFile().hasNoDefaultLib))
2978
+ return null;
2979
+ const receiver = call.expression.expression;
2980
+ if (checker.getSignaturesOfType(checker.getTypeAtLocation(receiver), ts.SignatureKind.Call).length === 0)
2981
+ return null;
2982
+ if (name === 'call')
2983
+ return { callee: receiver, receiver: call.arguments[0] ?? null, args: call.arguments.slice(1) };
2984
+ if (call.arguments.length === 2) {
2985
+ const argumentsArray = call.arguments[1];
2986
+ if (argumentsArray &&
2987
+ ts.isArrayLiteralExpression(argumentsArray) &&
2988
+ argumentsArray.elements.every((element) => !ts.isSpreadElement(element))) {
2989
+ return { callee: receiver, receiver: call.arguments[0] ?? null, args: argumentsArray.elements };
2990
+ }
2991
+ }
2992
+ return null;
2993
+ };
2994
+ const staticInvocationKeyOf = (expression) => {
2995
+ if (ts.isPropertyAccessExpression(expression))
2996
+ return expression.name.text;
2997
+ if (!ts.isElementAccessExpression(expression) || !expression.argumentExpression)
2998
+ return null;
2999
+ const argument = unwrapErasedExpression(expression.argumentExpression);
3000
+ if (ts.isStringLiteralLike(argument) || ts.isNoSubstitutionTemplateLiteral(argument))
3001
+ return argument.text;
3002
+ if (ts.isNumericLiteral(argument)) {
3003
+ const key = String(Number(argument.text));
3004
+ return key === argument.text ? key : null;
3005
+ }
3006
+ return null;
3007
+ };
3008
+ const isWithin = (node, root) => {
3009
+ for (let current = node; current; current = current.parent)
3010
+ if (current === root)
3011
+ return true;
3012
+ return false;
3013
+ };
3014
+ const staticHomeObjectOf = (member) => (ts.getCombinedModifierFlags(member) & ts.ModifierFlags.Static) !== 0;
3015
+ const isInsideCallableExecution = (expression, callable) => isWithin(expression, callable.body) || callable.parameters.some((parameter) => isWithin(expression, parameter));
3016
+ const lexicalSuperHomeOf = (expression) => {
3017
+ for (let current = expression.parent; current; current = current.parent) {
3018
+ if (ts.isArrowFunction(current))
3019
+ continue;
3020
+ if (ts.isMethodDeclaration(current) || ts.isGetAccessorDeclaration(current) || ts.isSetAccessorDeclaration(current)) {
3021
+ const owner = current.parent;
3022
+ if ((ts.isClassDeclaration(owner) || ts.isClassExpression(owner)) && isInsideCallableExecution(expression, current))
3023
+ return { home: owner, static: staticHomeObjectOf(current) };
3024
+ if (ts.isObjectLiteralExpression(owner) && isInsideCallableExecution(expression, current))
3025
+ return { home: owner, static: false };
3026
+ // Computed names are evaluated in the enclosing context, not with this
3027
+ // member's home object. Keep walking so an enclosing method can own it.
3028
+ continue;
3029
+ }
3030
+ if (ts.isConstructorDeclaration(current)) {
3031
+ const owner = current.parent;
3032
+ return ts.isClassDeclaration(owner) || ts.isClassExpression(owner) ? { home: owner, static: false } : { home: null, static: false };
3033
+ }
3034
+ if (ts.isPropertyDeclaration(current)) {
3035
+ const owner = current.parent;
3036
+ if ((ts.isClassDeclaration(owner) || ts.isClassExpression(owner)) && isWithin(expression, current.initializer))
3037
+ return { home: owner, static: staticHomeObjectOf(current) };
3038
+ continue;
3039
+ }
3040
+ if (ts.isClassStaticBlockDeclaration(current)) {
3041
+ const owner = current.parent;
3042
+ return ts.isClassDeclaration(owner) || ts.isClassExpression(owner) ? { home: owner, static: true } : { home: null, static: false };
3043
+ }
3044
+ if (ts.isFunctionLike(current))
3045
+ return { home: null, static: false };
3046
+ }
3047
+ return { home: null, static: false };
3048
+ };
3049
+ const superConstructorHomeOf = (call) => {
3050
+ for (let current = call.parent; current; current = current.parent) {
3051
+ if (ts.isArrowFunction(current))
3052
+ continue;
3053
+ if (ts.isConstructorDeclaration(current)) {
3054
+ const home = current.parent;
3055
+ return isWithin(call, current.body) && (ts.isClassDeclaration(home) || ts.isClassExpression(home)) ? home : null;
3056
+ }
3057
+ if (ts.isFunctionLike(current))
3058
+ return null;
3059
+ }
3060
+ return null;
3061
+ };
3062
+ /** The actual operand frame of a source call, with authenticated `.call`/`.apply` wrappers erased.
3063
+ *
3064
+ * `pendingExplicitThisAt` is the round-over-round counterpart of
3065
+ * `unwrapExplicitThisCall`'s own static gate: that gate needs the receiver's
3066
+ * CHECKER type to already carry a call signature, which an untyped JS array
3067
+ * element never does -- `EventDispatcher.dispatchEvent`'s `array[ i ].call(
3068
+ * this, event )` types `array[ i ]` as `any` even with a `@param {Function}`
3069
+ * JSDoc tag on the pushing `addEventListener`, because the field the array
3070
+ * lives on (`this._listeners`) itself carries no type. Unwrapping THAT
3071
+ * receiver unconditionally would be unsound (a program's own `.call`-shaped
3072
+ * Command/Strategy object would be silently misread as `Function.prototype.
3073
+ * call`), so the census this resolver comes from proves the array's whole
3074
+ * write history is CLOSED to real function values first (`callableArrayTargetsOf`
3075
+ * in `parameter-bindings.ts`, the identical flow proof `callable-reach.ts`'s
3076
+ * own target resolution trusts) and supplies a reading only once that holds --
3077
+ * never guessed, and absent (round one, and every caller with no census yet)
3078
+ * this stays byte-identical to the always-unresolved answer it replaced. */
3079
+ export const invocationOperandsOf = (checker, call, pendingExplicitThisAt) => {
3080
+ const explicitThis = ts.isCallExpression(call) ? (unwrapExplicitThisCall(checker, call) ?? pendingExplicitThisAt?.(call) ?? null) : null;
3081
+ const callee = unwrapErasedExpression(explicitThis?.callee ?? call.expression);
3082
+ const kind = ts.isNewExpression(call)
3083
+ ? 'construct'
3084
+ : callee.kind === ts.SyntaxKind.SuperKeyword
3085
+ ? 'super'
3086
+ : 'call';
3087
+ const receiver = explicitThis
3088
+ ? explicitThis.receiver
3089
+ : kind === 'call' && (ts.isPropertyAccessExpression(callee) || ts.isElementAccessExpression(callee))
3090
+ ? callee.expression
3091
+ : null;
3092
+ let dispatch = { kind: 'direct' };
3093
+ if (kind === 'super') {
3094
+ dispatch = { kind: 'super-constructor', home: superConstructorHomeOf(call) };
3095
+ }
3096
+ else if ((ts.isPropertyAccessExpression(callee) || ts.isElementAccessExpression(callee)) &&
3097
+ callee.expression.kind === ts.SyntaxKind.SuperKeyword) {
3098
+ dispatch = { kind: 'lexical-super', ...lexicalSuperHomeOf(callee), key: staticInvocationKeyOf(callee) };
3099
+ }
3100
+ else if (ts.isPropertyAccessExpression(callee) || ts.isElementAccessExpression(callee)) {
3101
+ dispatch = { kind: 'member', lookup: callee.expression, key: staticInvocationKeyOf(callee) };
3102
+ }
3103
+ return {
3104
+ kind,
3105
+ dispatch,
3106
+ explicitThis: explicitThis !== null,
3107
+ callee,
3108
+ receiver,
3109
+ args: explicitThis?.args ?? call.arguments ?? []
3110
+ };
3111
+ };
3112
+ /** Whether an identifier stands in the callee position of this call. */
3113
+ export const isCalleeOf = (node, call) => (ts.isCallExpression(call) || ts.isNewExpression(call)) && call.expression === node;
3114
+ /**
3115
+ * The symbol that names this function's value, or `null` when nothing does.
3116
+ *
3117
+ * A function is enumerable exactly when the program refers to it by a name,
3118
+ * because a name is what a reference can be counted against. Three forms of
3119
+ * name exist and all three are ordinary: a declaration's own (`function f(){}`),
3120
+ * the variable a function expression initializes (`const f = function(){}`),
3121
+ * and the member a method declares (`{ f() {} }`, `class { f() {} }`). A
3122
+ * function expression written directly as an argument has no name at all, and
3123
+ * refusing it is right: its only caller is the function it was passed to, which
3124
+ * is precisely the caller this census cannot enumerate.
3125
+ */
3126
+ export const nameOfCallable = (declaration) => {
3127
+ if (ts.isFunctionDeclaration(declaration) || ts.isFunctionExpression(declaration)) {
3128
+ if (declaration.name)
3129
+ return declaration.name;
3130
+ }
3131
+ // A private name is a name: `static #m(x) {}` is reached through `this.#m`
3132
+ // and nothing else, and the checker resolves that reference to the same
3133
+ // symbol an identifier's would. Left out, every private method was
3134
+ // `unnamed`, and every one of its parameters dynamic.
3135
+ if (ts.isMethodDeclaration(declaration) && (ts.isIdentifier(declaration.name) || ts.isPrivateIdentifier(declaration.name))) {
3136
+ return declaration.name;
3137
+ }
3138
+ // A constructor is named by its class: `new WebGLRenderer( ... )` reaches it
3139
+ // through that name and no other.
3140
+ if (ts.isConstructorDeclaration(declaration)) {
3141
+ const owner = declaration.parent;
3142
+ if (ts.isClassDeclaration(owner) && owner.name)
3143
+ return owner.name;
3144
+ }
3145
+ const parent = declaration.parent;
3146
+ if (parent && ts.isVariableDeclaration(parent) && parent.initializer === declaration && ts.isIdentifier(parent.name)) {
3147
+ return parent.name;
3148
+ }
3149
+ if (parent && ts.isPropertyAssignment(parent) && parent.initializer === declaration && ts.isIdentifier(parent.name)) {
3150
+ return parent.name;
3151
+ }
3152
+ // `this.render = function ( scene, camera ) { ... }` and `_this.shadowMap =
3153
+ // shadowMap` are how `WebGLRenderer` declares half its surface. TypeScript's
3154
+ // JavaScript inference does not read that idiom as a declaration, but the
3155
+ // member being assigned is still a NAME -- the same kind of name a method
3156
+ // declaration is -- and a name is all this needs to count references against.
3157
+ if (parent && ts.isBinaryExpression(parent) && parent.operatorToken.kind === ts.SyntaxKind.EqualsToken && parent.right === declaration) {
3158
+ if (ts.isPropertyAccessExpression(parent.left) && ts.isIdentifier(parent.left.name))
3159
+ return parent.left.name;
3160
+ if (ts.isIdentifier(parent.left))
3161
+ return parent.left;
3162
+ }
3163
+ return null;
3164
+ };
3165
+ /**
3166
+ * Whether a reference to a function's name is one that keeps it enumerable.
3167
+ *
3168
+ * An import or export specifier re-binds the name in another module's scope
3169
+ * without letting anything hold the function as a value, and a declaration's
3170
+ * own name is not a reference to it. A shorthand property in a returned object
3171
+ * (`return { has, init, get }`) is the idiom three's factories are built on:
3172
+ * the function is reachable only as a member of that record, so every call to
3173
+ * it is a member call this census resolves once the record has a type -- which
3174
+ * is what the fixpoint is for.
3175
+ *
3176
+ * Two more shapes are binding-only for the identical reason, one level of
3177
+ * indirection removed -- see `indexAliasEvidence` for the evidence that makes
3178
+ * each of them SOUND rather than merely silent:
3179
+ *
3180
+ * - a bare `return f;`: the SELECTOR-RETURN idiom (`getSingularSetter(type)`
3181
+ * returning one of several named setters from a switch). The function is
3182
+ * reachable only by calling whatever the selector returns, and
3183
+ * `indexAliasEvidence.returnedFrom` records exactly which functions a given
3184
+ * selector declaration can return, so a call through its result becomes
3185
+ * real evidence for every one of them.
3186
+ * - `<propertyAccess> = f`: the MEMBER-PUBLICATION idiom (`this.setValue =
3187
+ * setValueV3f`), the same idea `nameOfCallable` already handles for a
3188
+ * function declared directly in that position, extended to a function
3189
+ * merely REFERENCED there. `indexAliasEvidence.publishedUnderMember` keys
3190
+ * on the checker's own symbol for the member, never its spelling, so a
3191
+ * later call through an unrelated member that happens to share a name
3192
+ * never matches.
3193
+ *
3194
+ * A fourth shape needs no alias evidence at all, because it carries no value
3195
+ * flow to begin with: a class named in a HERITAGE CLAUSE (`class Sub extends
3196
+ * Base`, `class Sub implements Base`). `ExpressionWithTypeArguments` is the
3197
+ * node TypeScript uses for exactly these two positions and nowhere else, so
3198
+ * a reference whose direct parent is one names the class being extended or
3199
+ * implemented -- it does not hand the class's constructor to anything. The
3200
+ * two ways a heritage mention could matter for a constructor's own
3201
+ * enumerability are both already real `NewExpression`/`CallExpression` nodes
3202
+ * this census's own `attributeCalls` visits and attributes through
3203
+ * `checker.getResolvedSignature`, independent of the heritage reference
3204
+ * itself: a `super(...)` call in a declared derived constructor resolves
3205
+ * straight to the base constructor's declaration, and `new Derived(...)`
3206
+ * where `Derived` declares no constructor of its own resolves to that same
3207
+ * base declaration too (TypeScript gives the derived class the base's own
3208
+ * construct signature when it has none -- measured directly against this
3209
+ * compiler's own checker: `new Derived(...)`'s resolved signature IS the
3210
+ * base constructor node, and a declared `super(...)` resolves to it too).
3211
+ * Counting the heritage mention as a further escape does not add evidence
3212
+ * the walk lacks -- it double-refuses a constructor whose real callers are
3213
+ * already enumerated elsewhere.
3214
+ *
3215
+ * Everything else -- an argument, a bare variable initializer, a return of
3216
+ * the bare name wrapped in a way that isn't a plain `ReturnStatement` -- hands
3217
+ * the function to a caller this census cannot see, and stays an escape.
3218
+ */
3219
+ export const isBindingOnlyReference = (node) => {
3220
+ const parent = node.parent;
3221
+ if (!parent)
3222
+ return false;
3223
+ if (ts.isImportSpecifier(parent) || ts.isExportSpecifier(parent) || ts.isImportClause(parent))
3224
+ return true;
3225
+ if (ts.isShorthandPropertyAssignment(parent) || ts.isPropertyAssignment(parent))
3226
+ return true;
3227
+ if (ts.isVariableDeclaration(parent) && parent.name === node)
3228
+ return true;
3229
+ if (ts.isMethodDeclaration(parent) && parent.name === node)
3230
+ return true;
3231
+ if (ts.isPropertyAccessExpression(parent) && parent.name === node)
3232
+ return true;
3233
+ if (ts.isReturnStatement(parent) && parent.expression === node)
3234
+ return true;
3235
+ if (ts.isExpressionWithTypeArguments(parent) && parent.expression === node)
3236
+ return true;
3237
+ if (ts.isBinaryExpression(parent) &&
3238
+ parent.operatorToken.kind === ts.SyntaxKind.EqualsToken &&
3239
+ parent.right === node &&
3240
+ ts.isPropertyAccessExpression(parent.left)) {
3241
+ return true;
3242
+ }
3243
+ return ts.isFunctionDeclaration(parent) || ts.isFunctionExpression(parent) || ts.isClassDeclaration(parent) ? parent.name === node : false;
3244
+ };
3245
+ /**
3246
+ * Every tracked callable declaration in the program, keyed by the symbol
3247
+ * `nameOfCallable` resolves for it -- built once, over EVERY declaration
3248
+ * (not only the census's own unannotated-parameter candidates), because a
3249
+ * selector can return, or a constructor can publish, a callable whose own
3250
+ * parameters are fully typed and irrelevant to this census except as the
3251
+ * far end of an alias chain leading to one that is not.
3252
+ */
3253
+ export const indexNamedCallables = (checker, files, reachable) => {
3254
+ const bySymbol = new Map();
3255
+ const visit = (node) => {
3256
+ if (isTrackedCallable(node)) {
3257
+ const name = nameOfCallable(node);
3258
+ const symbol = name && checker.getSymbolAtLocation(name);
3259
+ if (symbol && !bySymbol.has(symbol))
3260
+ bySymbol.set(symbol, node);
3261
+ }
3262
+ ts.forEachChild(node, visit);
3263
+ };
3264
+ for (const file of files)
3265
+ forEachReachableStatement(reachable, file, visit);
3266
+ return bySymbol;
3267
+ };
3268
+ export const emptyAliasEvidence = { publishedUnderMember: new Map(), returnedFrom: new Map() };
3269
+ const EMPTY_CALLABLES = new Set();
3270
+ export const indexAliasEvidence = (checker, files, reachable, namedCallables) => {
3271
+ const publishedUnderMember = new Map();
3272
+ const returnedFrom = new Map();
3273
+ const record = (map, key, values) => {
3274
+ if (values.size === 0)
3275
+ return;
3276
+ const existing = map.get(key);
3277
+ if (existing)
3278
+ for (const value of values)
3279
+ existing.add(value);
3280
+ else
3281
+ map.set(key, new Set(values));
3282
+ };
3283
+ /** The function a bare identifier names, via the checker's own symbol -- never its spelling. */
3284
+ const namedCallableOf = (expression) => {
3285
+ if (!ts.isIdentifier(expression))
3286
+ return null;
3287
+ const symbol = checker.getSymbolAtLocation(expression);
3288
+ const direct = symbol ? namedCallables.get(symbol) : undefined;
3289
+ if (direct)
3290
+ return direct;
3291
+ // A shorthand property has a property symbol at its name, while the
3292
+ // callable value is the local symbol behind that property. Ask the
3293
+ // checker for that value symbol so `{ method }` records the same callable
3294
+ // publication as `{ method: method }`.
3295
+ const parent = expression.parent;
3296
+ if (ts.isShorthandPropertyAssignment(parent)) {
3297
+ const valueSymbol = checker.getShorthandAssignmentValueSymbol(parent);
3298
+ return valueSymbol ? (namedCallables.get(valueSymbol) ?? null) : null;
3299
+ }
3300
+ return null;
3301
+ };
3302
+ /**
3303
+ * Every function `expression` could evaluate to: a written callable,
3304
+ * a bare name, or a call straight
3305
+ * through a known selector -- `getSingularSetter( type )`, resolved by
3306
+ * the CHECKER's own attribution, never this module's. `this.setValue =
3307
+ * getSingularSetter( activeInfo.type )` is the real idiom this exists
3308
+ * for: the member is published not with a single named function but with
3309
+ * whichever one the selector call itself picks, and the two shapes
3310
+ * compose -- a member publication whose right side is a selector call
3311
+ * publishes the WHOLE returned set under that member, one pass after
3312
+ * `returnedFrom` has settled it for the selector.
3313
+ */
3314
+ const callablesOf = (expression) => {
3315
+ // A callable written directly into a member is its exact allocation
3316
+ // declaration, just as a named callable assigned there is. Omitting
3317
+ // these values loses every later member-call argument from their
3318
+ // parameter census despite knowing the member's publication identity.
3319
+ if (ts.isFunctionExpression(expression) || ts.isArrowFunction(expression))
3320
+ return new Set([expression]);
3321
+ const named = namedCallableOf(expression);
3322
+ if (named)
3323
+ return new Set([named]);
3324
+ if (ts.isCallExpression(expression)) {
3325
+ const selector = checker.getResolvedSignature(expression)?.declaration;
3326
+ const returned = selector && returnedFrom.get(selector);
3327
+ if (returned)
3328
+ return returned;
3329
+ }
3330
+ return EMPTY_CALLABLES;
3331
+ };
3332
+ // Pass 1: every selector's returned set, so pass 2 can already consult it
3333
+ // for a member published from a selector CALL rather than a bare name.
3334
+ const visitReturns = (node) => {
3335
+ if (ts.isReturnStatement(node) && node.expression) {
3336
+ const callable = namedCallableOf(node.expression);
3337
+ // A `return` belongs to its nearest enclosing function-like ancestor by
3338
+ // construction -- syntax cannot let it skip over a nested one -- so
3339
+ // this is exactly the declaration the reference above is binding-only
3340
+ // FOR, no separate containment walk needed.
3341
+ const enclosing = ts.findAncestor(node, isTrackedCallable);
3342
+ if (callable && enclosing)
3343
+ record(returnedFrom, enclosing, new Set([callable]));
3344
+ }
3345
+ ts.forEachChild(node, visitReturns);
3346
+ };
3347
+ for (const file of files)
3348
+ forEachReachableStatement(reachable, file, visitReturns);
3349
+ // Pass 2: every member publication, now free to resolve a selector call
3350
+ // on the right side through the completed `returnedFrom`. Object
3351
+ // literals need the same treatment as `receiver.member = callable`:
3352
+ // factories such as WebGLState return a record whose properties are the
3353
+ // local forwarding functions. The property symbol is the checker-owned
3354
+ // identity that later member calls expose, so recording it here keeps the
3355
+ // alias path generic and does not depend on the property's spelling.
3356
+ const visitPublications = (node) => {
3357
+ if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.EqualsToken && ts.isPropertyAccessExpression(node.left)) {
3358
+ const callables = callablesOf(node.right);
3359
+ if (callables.size > 0) {
3360
+ const memberSymbol = checker.getSymbolAtLocation(node.left.name);
3361
+ if (memberSymbol)
3362
+ record(publishedUnderMember, memberSymbol, callables);
3363
+ }
3364
+ }
3365
+ if (ts.isPropertyAssignment(node)) {
3366
+ const name = node.name;
3367
+ if (ts.isIdentifier(name) || ts.isStringLiteralLike(name) || ts.isNumericLiteral(name)) {
3368
+ const callables = callablesOf(node.initializer);
3369
+ // The symbol at an object-literal key is the declaration-local
3370
+ // property symbol. Reads use the property symbol from the inferred
3371
+ // object type, so use that same stable identity for both sides.
3372
+ const memberSymbol = checker.getTypeAtLocation(node.parent).getProperty(name.text);
3373
+ if (memberSymbol && callables.size > 0)
3374
+ record(publishedUnderMember, memberSymbol, callables);
3375
+ }
3376
+ }
3377
+ else if (ts.isShorthandPropertyAssignment(node)) {
3378
+ const callables = callablesOf(node.name);
3379
+ // The shorthand value and the inferred object property have distinct
3380
+ // symbol objects. Ask the object literal's apparent type for the
3381
+ // PROPERTY symbol that later member calls resolve to.
3382
+ const memberSymbol = checker.getTypeAtLocation(node.parent).getProperty(node.name.text);
3383
+ if (memberSymbol && callables.size > 0)
3384
+ record(publishedUnderMember, memberSymbol, callables);
3385
+ }
3386
+ ts.forEachChild(node, visitPublications);
3387
+ };
3388
+ for (const file of files)
3389
+ forEachReachableStatement(reachable, file, visitPublications);
3390
+ return { publishedUnderMember, returnedFrom };
3391
+ };
3392
+ /**
3393
+ * The type a node holds according to every authority in the program, checker
3394
+ * included.
3395
+ *
3396
+ * The binding census answers `null` for "nothing here improves on the
3397
+ * checker's answer", which is the safe default for the census but a trap for
3398
+ * its readers: it makes consulting the census OPTIONAL. A consumer that simply
3399
+ * calls `checker.getTypeAtLocation` gets a plausible type, no error, and no
3400
+ * indication that a better answer already existed one call away. That is not a
3401
+ * hypothetical -- it is the single most common defect this compiler has had.
3402
+ * `signatureOf` asked the census for a signature's parameters and not its
3403
+ * result; `memberOf` had the census threaded into its own module and never
3404
+ * called it; the array-element consumer asked only about `never` and not
3405
+ * `any`. Each was a few lines, each cost hundreds of boxed carriers, and each
3406
+ * looked locally correct.
3407
+ *
3408
+ * So the rule is: a consumer asks THIS, not the checker. The checker is an
3409
+ * input to the census, not an alternative to it, and the fallback belongs in
3410
+ * one place rather than being rewritten -- or forgotten -- at every call site.
3411
+ *
3412
+ * A site that genuinely wants the checker's own answer wants a different
3413
+ * question than this one ("what did the program STATE here", for a stated
3414
+ * annotation, versus "what does this hold"), and should say so in its own
3415
+ * words at the call rather than reaching past this by habit.
3416
+ */
3417
+ export const censusedTypeAt = (checker, census, node) => census.typeAt(node) ?? checker.getTypeAtLocation(node);
3418
+ /**
3419
+ * The synthesized-union arms a write-set census resolved for a cell, answered
3420
+ * at the DECLARATION and at every READ of it alike.
3421
+ *
3422
+ * A cell whose writes disagree DISJOINTLY resolves to a union rather than a
3423
+ * refusal (see `disjointUnionMembersOf`), and that answer has to travel as an
3424
+ * arm LIST because `ts.TypeChecker.getUnionType` is not public -- so it cannot
3425
+ * ride in a census's `typeAt`, and each census publishes it through a second
3426
+ * channel, `unionArmsAt`, for `structural.ts` to intern.
3427
+ *
3428
+ * Every one of those channels was written as `ts.isParameter(node) ? arms.get(
3429
+ * node) : null` (and the variable/field equivalents), which answers for the
3430
+ * declaration NODE and for nothing else. That is the two-authorities defect
3431
+ * this compiler keeps rediscovering, in its quietest possible form: the
3432
+ * declaration got the union, and every ordinary reference to the cell -- an
3433
+ * identifier one line down -- fell through to the checker's own `any` and
3434
+ * boxed. Nothing reported a disagreement, because the second authority
3435
+ * answered `null`, and `null` is exactly how a census says "the checker's
3436
+ * answer stands".
3437
+ *
3438
+ * Measured on the three.js app: **176 top-level `dynamic` carriers sat on identifiers
3439
+ * reading a parameter the census had already resolved** -- 104 + 57 + 15,
3440
+ * the three synthesized-union parameters in the renderer's object walks, to
3441
+ * the unit. Answering here instead swapped exactly 171 `dynamic` carriers for
3442
+ * 171 `tagged-union` ones (a carrier kind the same program already selected
3443
+ * 2040 times), with `ops` unchanged and 92 FEWER unmet obligations.
3444
+ *
3445
+ * No flow narrowing is discarded by answering at a read, which is the one
3446
+ * thing that could make this unsound and the reason a census's `typeAt` needs
3447
+ * an equality guard for its ordinary bindings: a synthesized union arises only
3448
+ * where the declaration's own checker type is `any`, and `any` carries no
3449
+ * narrowing for a reference to report differently.
3450
+ *
3451
+ * `declarations.length === 1` is the same soleness test every resolver in this
3452
+ * module applies -- a name with two declarations is two cells, and answering
3453
+ * for either would be picking one.
3454
+ */
3455
+ export const synthesizedUnionArmsAt = (checker, node, arms, owns = ts.isParameter) => {
3456
+ if (owns(node))
3457
+ return arms.get(node) ?? null;
3458
+ if (!ts.isIdentifier(node))
3459
+ return null;
3460
+ const declarations = checker.getSymbolAtLocation(node)?.declarations;
3461
+ const declaration = declarations && declarations.length === 1 ? declarations[0] : undefined;
3462
+ return declaration && owns(declaration) ? (arms.get(declaration) ?? null) : null;
3463
+ };