@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,2154 @@
1
+ import { receivableArguments } from '../../ir/call-entry.js';
2
+ import { stableBorrowEntryAccepts } from './borrowed-call-entry.js';
3
+ import { callableMemberSlot } from '../../ir/callable-member-candidates.js';
4
+ import { transferOf } from '../../ir/transfer.js';
5
+ import { boxedValueText } from './emit-dynamic-properties.js';
6
+ import { functionConstructorArgumentKindOf } from '../../representation/function-constructor.js';
7
+ import { nativeSumWidenable } from './emit-sum-widening.js';
8
+ import { abiKey, representationKey } from '../../representation/model.js';
9
+ import { alignedValueText, bindsReceiver, callableObjectAbi, movedValueText, unboxedLoadText } from './emit-narrowing.js';
10
+ import { memberAccessOperator, reactiveRevisionText } from './emit-carrier-members.js';
11
+ import { structuralRecordViewText } from './emit-record-view.js';
12
+ import { emitDateConstruct, isDateCarrier } from './prototype/emit-prototype-date.js';
13
+ import { unwrapPresentValue, bindingReference, cppConstructedThunkName, cppConstructThunkName, cppEnvironmentStructName, cppReceiverName, cppThunkName, createCppEmitBlockedError, declareCell, defineValue, defineValueAlias, isCppEmitBlockedError, isIntegerStorageValue, operandText, paddedArguments, captureFieldText } from './emit-context.js';
14
+ import { classMemberOf, classStaticMemberOf, cppFieldInitializerStatements, lazyArrowFieldPlanOf } from './class-layout.js';
15
+ import { declaredRecordFieldOf } from './records.js';
16
+ import { hostArityCallLines, hostResultText } from './host/emit-host-arity.js';
17
+ import { hostMemberOf } from './host/host-members.js';
18
+ import { hostCallText, nativeHandleInvocationText } from './host/emit-host-invoke.js';
19
+ import { nativeReflectCallText } from './host/emit-host-reflect.js';
20
+ import { jsonStringifyFillLines } from './emit-json.js';
21
+ import { withheldCellOf } from './deferral-safety.js';
22
+ import { prototypeMethodCallText } from './prototype/emit-prototype-invoke.js';
23
+ import { mutatingArrayMembers } from './prototype/emit-prototype-array.js';
24
+ import { regexpRoleOf, regExpConstructionFromObject } from './prototype/emit-prototype-regexp.js';
25
+ import { cppConstructPatternEntry, cppRegExpNativeTypes } from './regexp-types.js';
26
+ import { cppErrorNativeType } from './error-types.js';
27
+ import { isNativeErrorBaseRefusal, nativeErrorBaseInitializeStatements } from './native-error-base.js';
28
+ import { emitArrayBufferConstruct, emitSharedArrayBufferConstruct, emitTextCodecConstruct, emitDataViewConstruct, emitTypedArrayBufferConstruct, typedArrayTargetSpelling } from './emit-buffers.js';
29
+ import { armAt, armIs } from './emit-union-properties.js';
30
+ import { cppAbiType, cppBodyName, cppBoxedType, cppCallableDeclarationTagName, cppClassName, cppConstructName, cppInitializeName, cppRecordFieldName, cppRefcountedReceiver, cppTypeOf, cppUndefinedValue } from './types.js';
31
+ /** `Function.prototype.bind` preserves the native call ABI and captures only evaluated prefix values. */
32
+ export const emitBindCallable = (ctx, lines, operation) => {
33
+ if (operation.result.representation.kind !== 'function-value-dispatch') {
34
+ throw createCppEmitBlockedError('call-abi:bind-callable', 'a bound Function result is not carried as an evaluated function-value dispatch');
35
+ }
36
+ if (operation.detached) {
37
+ // See `BindCallableOperation.detached`: the language calls a detached
38
+ // method with no receiver, so a body that reads `this` would be answered
39
+ // where the program would have thrown.
40
+ if (operation.sourceFunctionId !== null && ctx.captures.readsReceiver(operation.sourceFunctionId)) {
41
+ throw createCppEmitBlockedError('call-abi:bind-callable', `passes method ${operation.sourceFunctionId} on as a value, and its body reads \`this\`: the language calls a detached method ` +
42
+ 'with no receiver, so binding the object it was read from would answer where the program would have thrown');
43
+ }
44
+ if (operation.receiver === null)
45
+ throw createCppEmitBlockedError('call-abi:bind-callable', 'a detached method bind names no receiver to bind');
46
+ const bound = alignedText(ctx, operation.sourceAbi.receiver ?? undefined, operation.receiver, 'detached method receiver');
47
+ const type = cppTypeOf(operation.result.representation);
48
+ lines.push(`${defineValue(ctx, operation.result)} = ${type}::bindReceiver(${operandText(ctx, operation.source)}, ${bound});`);
49
+ return;
50
+ }
51
+ const receiver = operation.receiver
52
+ ? [alignedText(ctx, operation.sourceAbi.receiver ?? undefined, operation.receiver, 'Function.prototype.bind receiver')]
53
+ : [];
54
+ const bound = operation.bound.map((value, index) => alignedText(ctx, operation.sourceAbi.parameters[index]?.value, value, 'Function.prototype.bind argument'));
55
+ // A dynamic-fallback callable is boxed only for its mutable Function-object
56
+ // properties. Its declaration-owned ABI survives on the operation, so
57
+ // recover that callable through the authenticated Function adapter before
58
+ // capturing the prefix; passing a Value to bindCallable would erase both
59
+ // the call frame and the target's own-property identity.
60
+ let source = operandText(ctx, operation.source);
61
+ if (operation.source.representation.kind === 'dynamic') {
62
+ if (operation.sourceFunctionId === null) {
63
+ throw createCppEmitBlockedError('call-abi:bind-callable', 'a dynamic Function source carries no checker-authenticated declaration identity');
64
+ }
65
+ const authenticated = ctx.abiOfCallable(operation.sourceFunctionId);
66
+ if (authenticated === null || abiKey(authenticated) !== abiKey(operation.sourceAbi)) {
67
+ throw createCppEmitBlockedError('call-abi:bind-callable', `dynamic Function source ${operation.sourceFunctionId} does not publish the exact ABI carried by its bind operation`);
68
+ }
69
+ source = unboxedLoadText({ kind: 'function', functionId: operation.sourceFunctionId, abi: authenticated }, source);
70
+ }
71
+ if (source === null) {
72
+ throw createCppEmitBlockedError('call-abi:bind-callable', 'a dynamic Function source has no authenticated native ABI adapter');
73
+ }
74
+ const prefix = [...receiver, ...bound];
75
+ lines.push(`${defineValue(ctx, operation.result)} = gea::bindCallable<${cppAbiType(operation.result.representation.abi)}, ${operation.bound.length}>(${[
76
+ source,
77
+ ...prefix
78
+ ].join(', ')});`);
79
+ };
80
+ /**
81
+ * Rendering the callable family: calling, constructing, super-initializing, and
82
+ * allocating the two carriers that make a function or a class a first-class
83
+ * value.
84
+ *
85
+ * They belong together because they are four views of one convention. A call
86
+ * and a construction both go through a carrier's own pointer; an allocation is
87
+ * what fills that carrier in; and `super(...)` is the one member that is
88
+ * neither -- initialization against a receiver that already exists -- which is
89
+ * exactly why it is easiest to get wrong when it sits among unrelated code.
90
+ */
91
+ /**
92
+ * A host object written where one of its own base types is declared.
93
+ *
94
+ * The same rule as the class case below, for a hierarchy this compiler did not
95
+ * lay out: an `NSStackView` IS an `NSView`, the generated bridge gives the
96
+ * wrapper structs that same inheritance, and the upcast is the language's own
97
+ * derived-to-base rule with no text of its own. What this cannot be is
98
+ * inferred -- two opaque handles are unrelated to the checker whatever the
99
+ * host's class hierarchy says -- so it is read from what the host stated
100
+ * (`PluginCapabilities.nativeBases`), off the carrier, which is where that
101
+ * statement now travels (`Representation`'s `native-handle` arm).
102
+ *
103
+ * Read from the carrier rather than from this emitter's own host tables so
104
+ * that the conversion census -- which is pure carrier-to-carrier and has no
105
+ * emit context to consult -- answers this pair the same way the printer does.
106
+ * While the fact reached only here, the census minted a `never` node for every
107
+ * host upcast and the certificate refused programs this function was perfectly
108
+ * able to render.
109
+ *
110
+ * A handle with no stated carrier is compared by nothing: a host that named no
111
+ * C++ type for a protocol has said nothing about that protocol's place in a
112
+ * hierarchy either, and treating the protocol name as a carrier would compare
113
+ * two different key spaces. `bases` is empty for such a handle, so the
114
+ * membership test below already says so.
115
+ */
116
+ const hostHandleDerivesFrom = (source, target) => target.native !== null && source.bases.includes(target.native);
117
+ /**
118
+ * An instance of a class written where one of its base classes is declared.
119
+ *
120
+ * `records.ts` emits a derived class as `struct D : B`, so `shared_ptr<D>`
121
+ * converts to `shared_ptr<B>` by the language's own derived-to-base rule and
122
+ * the value needs no text of its own. `convertedValueText` cannot answer this:
123
+ * two `class-ref`s differ in a `DeclarationId`, and which classes extend which
124
+ * is a projection fact, not something a carrier carries.
125
+ *
126
+ * The chain is walked rather than the immediate base checked, because
127
+ * `class C extends B extends A` really does make a `C` an `A`. Both sides must
128
+ * agree on ownership: the conversion is on the pointer, and a by-value `B`
129
+ * built from a `D` would slice off exactly the fields that made it a `D`.
130
+ */
131
+ const derivesFrom = (ctx, source, target) => {
132
+ if (source.kind === 'native-handle' && target.kind === 'native-handle')
133
+ return hostHandleDerivesFrom(source, target);
134
+ if (source.kind !== 'class-ref' || target.kind !== 'class-ref')
135
+ return false;
136
+ if (source.ownership !== target.ownership || source.ownership !== 'shared-refcount')
137
+ return false;
138
+ const seen = new Set();
139
+ let current = ctx.classes.get(source.declaration)?.base ?? null;
140
+ while (current !== null && !seen.has(current)) {
141
+ if (current === target.declaration)
142
+ return true;
143
+ seen.add(current);
144
+ current = ctx.classes.get(current)?.base ?? null;
145
+ }
146
+ return false;
147
+ };
148
+ /**
149
+ * A class instance written where a structurally-compatible DECLARED SHAPE is
150
+ * the slot -- the interface view TypeScript's own assignability already
151
+ * granted, materialized.
152
+ *
153
+ * hono's `createResponseInstance(_res.body, _res)` (context.ts) hands a
154
+ * `Response` INSTANCE to a parameter declared `ResponseInit`. The checker
155
+ * accepts it structurally: `ResponseInit`'s three optional members --
156
+ * `status`, `statusText`, `headers` -- are all present on the class. C++ has
157
+ * no such rule. `gea::Ref<gea_class_...>` and `gea::Ref<gea_record_...>` are
158
+ * unrelated types, `derivesFrom` above answers only the nominal hierarchy the
159
+ * program actually wrote, and `convertedValueText` has no way to reach a
160
+ * class's members: a `class-ref` carries a declaration and a shape id, never a
161
+ * field list. This is the one place both layouts are in hand.
162
+ *
163
+ * The rebuild is `recastedRecordText`'s (emit-narrowing.ts), one carrier kind
164
+ * further out: read each of the TARGET's fields off the source and construct
165
+ * the target's struct. Both field lists come from `recordFieldsOfShape`, the
166
+ * same authority `records.ts` builds every struct body from, so the members
167
+ * read here are exactly the members that exist.
168
+ *
169
+ * What this is NOT is an alias. The result is a fresh record holding a
170
+ * snapshot of the instance's fields, so a callee that ASSIGNS one of them
171
+ * writes to the copy and the instance never sees it -- the same limit the
172
+ * record-to-record recast already carries, one carrier kind wider. That makes
173
+ * this sound for a slot the declaration shapes as a read-only bag (an options
174
+ * record, which is what every such interface in practice is) and wrong for one
175
+ * declared to be written through. A field whose own carrier is refcounted --
176
+ * `Response.headers`, a `Headers` instance -- still aliases, because the copy
177
+ * copies the reference.
178
+ *
179
+ * Fail-closed on everything it cannot account for: a target with accessors or
180
+ * a dynamic-property sidecar has members this aggregate cannot fill, a
181
+ * host-named struct is the engine's own type with a layout this compiler did
182
+ * not choose, and a target field with no source member of its own is a real
183
+ * hole -- unless the field is optional, which is the declaration's own word
184
+ * that absence is a value it accepts.
185
+ */
186
+ /** The lambda's own names, kept out of every body-local namespace a view can be spliced into. */
187
+ /**
188
+ * One argument in the carrier the frame it is being written into declares.
189
+ *
190
+ * An argument arrives in the carrier of the expression that produced it, which
191
+ * is not always the slot's: `setSupportedOrientations('landscape')` hands a
192
+ * `std::string` to a parameter declared `OrientationLock | OrientationLock[]`,
193
+ * a real `gea::TaggedUnion`. Writing it through unconverted is a frame
194
+ * mismatch, and C++ rejects it -- correctly -- at the call.
195
+ *
196
+ * This is deliberately in the emitter and not in the lowering. Only three of
197
+ * this file's renderings build a frame at all: a host member and a
198
+ * String/Array.prototype method are both spelled through a text template that
199
+ * never sees the declared convention (`emit-host-invoke.ts`,
200
+ * `emit-prototype-invoke.ts`), so an argument reaching one of those must stay
201
+ * exactly as its own carrier spells it -- `substring`'s optional `end` is a C++
202
+ * OVERLOAD there, not a `gea::Optional<double>` parameter. Which rendering a
203
+ * call gets is decided here, once, a few lines above; a lowering that decided
204
+ * it a second time would be a second authority over the same question.
205
+ *
206
+ * A slot the convention does not declare is left alone: ECMAScript lets a call
207
+ * pass more arguments than a signature names, and an argument past the last
208
+ * slot has no declared carrier to be reconciled against. So is the rest slot,
209
+ * which `ir/lower-operands.ts`'s `packRestArguments` has already built in
210
+ * exactly the carrier the convention states.
211
+ */
212
+ export const alignedText = (ctx, slot, argument, what = 'call') => {
213
+ const text = operandText(ctx, argument);
214
+ if (!slot)
215
+ return text;
216
+ if (derivesFrom(ctx, argument.representation, slot))
217
+ return text;
218
+ // Native sum widening owns its source. Preserve a proven dying input's
219
+ // value category through that conversion, rather than copying before the
220
+ // outer argument move gets a chance to see the different carrier.
221
+ const sourceText = nativeSumWidenable(argument.representation, slot) ? movedValueText(ctx, argument, argument.representation, text) : text;
222
+ const converted = alignedValueText(ctx, `emit-callable.ts:503:${what}`, argument.representation, slot, sourceText);
223
+ if (converted !== null)
224
+ return converted;
225
+ // Last, and only here: the structural interface view above needs both
226
+ // layouts, which is a fact of this emitter's context rather than of the two
227
+ // carriers, so `convertedValueText` cannot be asked it. Tried after that
228
+ // function has refused so a pair with a real conversion never reaches a
229
+ // rebuild it does not need.
230
+ const view = structuralRecordViewText(ctx, argument.representation, slot, text);
231
+ if (view !== null)
232
+ return view;
233
+ // A storage-free argument in a slot that declares a real carrier is not a
234
+ // missing conversion: `undefined`/`void` is also `never`'s carrier
235
+ // (`representation/primitives.ts`), so this call sits on a branch flow
236
+ // analysis proved unreachable and there is nothing to convert. Rendered as
237
+ // the throw rather than refused -- mongodb's `execute_operation.ts:198`
238
+ // narrows a generic by `instanceof` to a class its own monomorphized copy
239
+ // cannot be, 28 copies over, and every one of them blocked emission for code
240
+ // that cannot run.
241
+ if (argument.representation.kind === 'undefined' || argument.representation.kind === 'void') {
242
+ return `gea::host::unreachableValue<${cppTypeOf(slot)}>()`;
243
+ }
244
+ const bound = receiverBoundCallableText(ctx, argument, slot, text);
245
+ if (bound !== null)
246
+ return bound;
247
+ throw createCppEmitBlockedError(`conversion:${representationKey(argument.representation)}->${representationKey(slot)}`, `passes a ${representationKey(argument.representation)} argument into a parameter slot carrying ` +
248
+ `${representationKey(slot)}, and no installed load performs that conversion`);
249
+ };
250
+ /**
251
+ * A method read as a value, handed on into a slot that declares no receiver
252
+ * -- tsc's `formatGeneratedName(..., IdentifierNameMap.toKey)`, or
253
+ * `apply(fmt.upper, s)`.
254
+ *
255
+ * `classMethodValueText` materializes a method value in the method's own
256
+ * physical convention, receiver first, and leaves the receiver to be filled
257
+ * by the call (`emitCall`'s `directCallReceivers`), which is right for the
258
+ * one call a property read feeds directly and wrong for a value that
259
+ * escapes: the slot it lands in states the language's own view of the
260
+ * value, `(name: string) => string`, and nothing at THAT site knows which
261
+ * object the read went through. The read does: `propertyReadOrigins` keeps
262
+ * every property read by its result, so the receiver is recovered here from
263
+ * the read itself and packed in with the value (`gea_runtime.h`'s
264
+ * `CallableObject::bindReceiver`).
265
+ *
266
+ * ECMAScript calls a detached method with `this` undefined. Packing the
267
+ * receiver in is the same call exactly when the body never reads it, and
268
+ * that is checked -- directly, and through every closure the body allocates
269
+ * (`captures.ts`'s `readsReceiver`) -- before anything is rendered; a body
270
+ * that does read `this` is refused by name, since the language would have
271
+ * thrown (or, in sloppy code, read the global) where this would have handed
272
+ * it the object. Measured on tsc's `transformers/utilities.ts`: every method
273
+ * passed as a value there is receiver-free.
274
+ *
275
+ * `null` for a pair this is not about, or a read this cannot see: the caller
276
+ * refuses in its own words, exactly as before.
277
+ */
278
+ /**
279
+ * The body a `receiver.key` read names, for a class instance or for the class
280
+ * object itself -- the same two member sets `emit-class-properties.ts`
281
+ * materializes a method value out of, asked through the same two functions so
282
+ * a value this binds a receiver into is the one that read published.
283
+ */
284
+ const methodBodyRead = (ctx, receiver, key) => {
285
+ const isStatic = receiver.kind === 'constructor-family';
286
+ const declarations = receiver.kind === 'class-ref' ? [receiver.declaration] : isStatic ? receiver.members : [];
287
+ for (const declaration of declarations) {
288
+ const site = isStatic ? classStaticMemberOf(ctx.classes, declaration, key) : classMemberOf(ctx.classes, declaration, key);
289
+ if (site?.kind === 'method' && site.method.callable)
290
+ return site.method.callable;
291
+ }
292
+ return null;
293
+ };
294
+ export const receiverBoundCallableText = (ctx, operand, target, text) => {
295
+ const source = operand.representation;
296
+ if (!bindsReceiver(source, target))
297
+ return null;
298
+ const origin = ctx.propertyReadOrigins.get(operand.value);
299
+ if (origin === undefined)
300
+ return null;
301
+ const abi = callableObjectAbi(source);
302
+ if (abi === null || abi.receiver === null)
303
+ return null;
304
+ const key = ctx.staticKeyTexts.get(origin.key.value);
305
+ const method = key === undefined ? null : methodBodyRead(ctx, origin.receiver.representation, key);
306
+ if (method === null)
307
+ return null;
308
+ if (ctx.captures.readsReceiver(method)) {
309
+ throw createCppEmitBlockedError('call-abi:bind-callable', `passes method "${key}" on as a value, and its body reads \`this\`: the language calls a detached method with no receiver, ` +
310
+ 'so binding the object it was read from would answer where the program would have thrown');
311
+ }
312
+ const receiver = alignedValueText(ctx, 'emit-callable.ts:593', origin.receiver.representation, abi.receiver, operandText(ctx, origin.receiver));
313
+ if (receiver === null)
314
+ return null;
315
+ return `${cppTypeOf(target)}::bindReceiver(${text}, ${receiver})`;
316
+ };
317
+ const argumentText = (ctx, abi, position, argument, what = 'call') => {
318
+ const slot = abi.restFrom !== null && position >= abi.restFrom ? undefined : abi.parameters[position]?.value;
319
+ const text = alignedText(ctx, slot, argument, what);
320
+ // A dying refcounted argument MOVES (`buildDyingArgumentIndex`, captures.ts):
321
+ // the cell it reads is never looked at again, so the increment on the way in
322
+ // and the release on the way out are both pure cost. Only a carrier that
323
+ // OWNS a count can move -- and only into a slot carrying exactly what the
324
+ // argument already holds, since any conversion (`derivesFrom`'s upcast
325
+ // included: `Ref` has no converting MOVE constructor) has already produced a
326
+ // temporary of its own, and moving that is no cheaper than leaving it.
327
+ return movedValueText(ctx, argument, slot ?? null, text);
328
+ };
329
+ /**
330
+ * The receiver occupies the frame's first formal, and reconciles against the
331
+ * slot the convention declares for it exactly as any other argument does.
332
+ *
333
+ * One extra obligation, and only for a refcounted receiver a body takes BY
334
+ * REFERENCE (`cppRefcountedReceiver`, translation-unit.ts): the argument must
335
+ * be something that survives the call. A local, a formal and a temporary all
336
+ * do -- a `const&` parameter extends a temporary's lifetime past the call that
337
+ * made it -- but a WITHHELD cell read renders as the cell's own storage, and a
338
+ * callee that assigns that cell drops the last count and destroys the object
339
+ * its own receiver names. So a withheld read is given its temporary back: the
340
+ * same copy passing by value would have made, in the one shape where the
341
+ * reference has nothing behind it.
342
+ */
343
+ export const receiverArgumentText = (ctx, abi, receiver) => {
344
+ const slot = abi.receiver ?? receiver.representation;
345
+ // A receiver the callee never names, whose construction was therefore deleted
346
+ // (`ir/instantiation.ts`). The frame still declares the formal, so something
347
+ // has to be passed -- and the one thing that is certainly safe is a
348
+ // default-constructed value of the slot's own type, since no body reads it.
349
+ // Spelling the deleted value's name instead would name a variable that was
350
+ // never declared.
351
+ if (ctx.deadValues.has(receiver.value))
352
+ return `${cppTypeOf(slot)}{}`;
353
+ const text = alignedText(ctx, abi.receiver ?? undefined, receiver, 'receiver');
354
+ // `withheldCellOf` rather than a private pair of lookups: this is one of the
355
+ // three sites where an emitter observes a withheld read somewhere the
356
+ // deferral census never placed it, and they share that question even though
357
+ // the cure here -- give the read its temporary back -- is this site's alone.
358
+ // See `deferral-safety.ts`.
359
+ const withheldCellRead = withheldCellOf(ctx, receiver.value) !== null;
360
+ return withheldCellRead && cppRefcountedReceiver(slot) ? `${cppTypeOf(slot)}{${text}}` : text;
361
+ };
362
+ /**
363
+ * A call through the callable carrier's own invoke pointer.
364
+ *
365
+ * This is the generic path, and it is the only one emitted: `open` is a
366
+ * complete answer, and the plan already narrowed the *convention* to one exact
367
+ * ABI, so an indirect call here costs one pointer load and loses no proof. A
368
+ * direct call to a known symbol is a devirtualization to attach later, on top
369
+ * of this, not instead of it.
370
+ */
371
+ const emitNullishInvocation = (ctx, lines, operation) => {
372
+ const kind = operation.callee.representation.kind;
373
+ if (kind !== 'undefined' && kind !== 'null' && kind !== 'void')
374
+ return false;
375
+ // Argument expressions have already evaluated in the IR. There is no call
376
+ // frame or parameter conversion for a value with no [[Call]]/[[Construct]].
377
+ const result = operation.result;
378
+ const target = result && result.representation.kind !== 'void' ? cppTypeOf(result.representation) : 'void';
379
+ const call = `gea::host::throwNullishInvocation<${target}>("${kind === 'null' ? 'null' : 'undefined'}", "${operation.kind === 'construct' ? 'constructor' : 'function'}")`;
380
+ lines.push(result && target !== 'void' ? `${defineValue(ctx, result)} = ${call};` : `${call};`);
381
+ if (result?.representation.kind === 'void')
382
+ defineValueAlias(ctx, result, '(void)0');
383
+ return true;
384
+ };
385
+ const emitUnionMethodCall = (ctx, lines, operation) => {
386
+ const read = ctx.unionMethodReads.get(operation.callee.value);
387
+ if (read === undefined)
388
+ return false;
389
+ const arms = read.arms;
390
+ if (arms.length === 0)
391
+ throw createCppEmitBlockedError('call-abi:tagged-union-method', 'a deferred tagged-union method read has no class arms');
392
+ ctx.unionMethodReadsUsed.add(operation.callee.value);
393
+ // The union's own spelling, taken HERE rather than at the read: the arm
394
+ // paths the claim recorded are indices into the carrier, and `armAt`/`armIs`
395
+ // turn them into text against a receiver that has a name by now.
396
+ const receiverText = operandText(ctx, read.receiver);
397
+ const branches = arms.map((arm, index) => {
398
+ const tests = [];
399
+ let armText = receiverText;
400
+ for (const step of arm.path) {
401
+ tests.push(armIs(armText, step));
402
+ armText = armAt(armText, step);
403
+ }
404
+ const armTest = tests.length === 0 ? 'true' : tests.join(' && ');
405
+ const abi = ctx.abiOfCallable(arm.callable);
406
+ if (abi === null || abi.receiver === null) {
407
+ throw createCppEmitBlockedError('call-abi:tagged-union-method', 'a deferred tagged-union method body has no receiver-bearing convention');
408
+ }
409
+ const receiver = alignedValueText(ctx, 'emit-callable.ts:705', arm.receiverRepresentation, abi.receiver, armText);
410
+ if (receiver === null) {
411
+ throw createCppEmitBlockedError(`conversion:${representationKey(arm.receiverRepresentation)}->${representationKey(abi.receiver)}`, `a deferred tagged-union method receiver cannot convert from ${representationKey(arm.receiverRepresentation)} to ${representationKey(abi.receiver)}`);
412
+ }
413
+ const supplied = receivableArguments(abi, operation.arguments).map((argument, position) => argumentText(ctx, abi, position, argument));
414
+ const invocation = `${cppBodyName(arm.callable)}(${paddedArguments(abi, [receiver, ...supplied], 'union method call').join(', ')})`;
415
+ let body;
416
+ if (operation.result === null || operation.result.representation.kind === 'void') {
417
+ body = `${invocation}; return;`;
418
+ }
419
+ else if (abi.result.kind === 'void') {
420
+ const converted = alignedValueText(ctx, 'emit-callable.ts:718', { kind: 'undefined' }, operation.result.representation, cppUndefinedValue);
421
+ if (converted === null) {
422
+ throw createCppEmitBlockedError(`conversion:undefined->${representationKey(operation.result.representation)}`, 'a void tagged-union method result has no installed conversion to its published result');
423
+ }
424
+ body = `${invocation}; return ${converted};`;
425
+ }
426
+ else {
427
+ const converted = alignedValueText(ctx, 'emit-callable.ts:724', abi.result, operation.result.representation, invocation);
428
+ if (converted === null) {
429
+ throw createCppEmitBlockedError(`conversion:${representationKey(abi.result)}->${representationKey(operation.result.representation)}`, `a tagged-union method result cannot convert from ${representationKey(abi.result)} to ${representationKey(operation.result.representation)}`);
430
+ }
431
+ body = `return ${converted};`;
432
+ }
433
+ return index === arms.length - 1 ? body : `if (${armTest}) { ${body} }`;
434
+ });
435
+ const resultType = operation.result === null || operation.result.representation.kind === 'void' ? 'void' : cppTypeOf(operation.result.representation);
436
+ const invocation = `[&]() -> ${resultType} { ${branches.join(' ')} }()`;
437
+ if (operation.result === null)
438
+ lines.push(`${invocation};`);
439
+ else if (operation.result.representation.kind === 'void') {
440
+ lines.push(`${invocation};`);
441
+ defineValueAlias(ctx, operation.result, '(void)0');
442
+ }
443
+ else
444
+ lines.push(`${defineValue(ctx, operation.result)} = ${invocation};`);
445
+ return true;
446
+ };
447
+ /**
448
+ * A DIRECT call on a lazy arrow class field (`class-layout.ts`'s
449
+ * `censusLazyArrowFields`/`LazyArrowFieldPlan`): `c.json(...)` invokes the
450
+ * arrow's own body directly, with the receiver as its own leading argument,
451
+ * while the field's storage is still the zero-initialized `CallableObject`
452
+ * (`invoke == nullptr`) -- exactly the read this field's whole design exists
453
+ * to avoid materializing.
454
+ *
455
+ * A REASSIGNED field (`c.json = other; c.json(...)`) must still call
456
+ * `other`, so this cannot simply always call the body: the field's guard is
457
+ * read at the call site, same as `class-layout.ts`'s `lazyMaterializedFieldText`,
458
+ * and the branch not taken is exactly the ordinary `.call()` this whole
459
+ * feature otherwise renders. Both arms share ONE evaluation of the receiver
460
+ * and ONE evaluation of each argument -- the branches are mutually exclusive
461
+ * at runtime (an `if`/`else` inside one IIFE, the same shape
462
+ * `emitUnionMethodCall`'s arms already rely on above), so duplicating an
463
+ * argument's TEXT across them never duplicates its evaluation.
464
+ *
465
+ * Keyed off `ctx.propertyReadOrigins`, exactly as the existing
466
+ * "callable member candidate" lookup just above is (`memberRead`/`memberKey`)
467
+ * -- both ask "where did this call's callee value come from", just of two
468
+ * different answers (a method slot there, a class field here). Fails closed
469
+ * to `false` -- today's materializing text -- for anything this cannot prove:
470
+ * a receiver that is not statically a class (or subclass) instance, a key
471
+ * this compile never gave lazy-field storage, an unresolved body ABI, or a
472
+ * callee reached through `unwrapPresentValue` (`c.json?.()`) rather than the
473
+ * read itself, none of which this fusion has been asked to handle.
474
+ */
475
+ const emitLazyArrowFieldCall = (ctx, lines, operation) => {
476
+ const memberRead = ctx.propertyReadOrigins.get(operation.callee.value);
477
+ if (memberRead === undefined)
478
+ return false;
479
+ const receiverRepresentation = memberRead.receiver.representation;
480
+ if (receiverRepresentation.kind !== 'class-ref')
481
+ return false;
482
+ const fieldName = ctx.staticKeyTexts.get(memberRead.key.value);
483
+ if (fieldName === undefined)
484
+ return false;
485
+ // `classMemberOf` walks the receiver's OWN class up through its bases, so a
486
+ // subclass instance resolves to the same declaring owner a base instance
487
+ // would -- the identical walk `emit-properties.ts`'s `emitGet` already
488
+ // trusts for this same field, and the reason an inherited qualifying field
489
+ // is published under the DECLARING class rather than every receiver that
490
+ // might read it (`class-layout.ts`'s own comment on `lazyArrowFieldPlanOf`).
491
+ const site = classMemberOf(ctx.classes, receiverRepresentation.declaration, fieldName);
492
+ if (site === null || site.kind !== 'field')
493
+ return false;
494
+ const plan = lazyArrowFieldPlanOf(ctx.classes, site.owner, fieldName);
495
+ if (plan === null)
496
+ return false;
497
+ // The callee's own representation is the field's STORED CallableObject
498
+ // convention -- what `.call()` below already invokes through, unchanged.
499
+ const callee = operation.callee.representation;
500
+ if (callee.kind !== 'function' && callee.kind !== 'function-value-dispatch' && callee.kind !== 'function-family')
501
+ return false;
502
+ // A `function`-kind read names a SPECIFIC function identity, which is not
503
+ // always the census's own arrow: a generic field instantiates a fresh,
504
+ // per-call-site copy of its body (hono's `LightRequest#cached` --
505
+ // `test/runtime/pending-promise-payload-narrowed-at-call.ts` -- reads back
506
+ // `promise(string)` at one call and `promise(scalar(number))` at another,
507
+ // from the SAME field), and a flow fact narrowing the field to a specific
508
+ // reassigned value is the same shape. Either way, `plan.body`'s own ABI has
509
+ // no reason to agree with THIS read's, so direct-call fusion only fires when
510
+ // the read confirms it is looking at the very arrow the census found --
511
+ // anything else keeps today's materializing text, which is always correct.
512
+ if (callee.kind === 'function' && callee.functionId !== plan.body)
513
+ return false;
514
+ // The stored branch calls whatever the FIELD physically holds, so its result
515
+ // is the field's own declared result, not this read's: a generic field
516
+ // (`cached = <K extends keyof R>(key: K): Promise<R[K]> => ...`) is stored
517
+ // as ONE `CallableObject` whose result is the union of every payload, while
518
+ // the read at `this.cached('text')` is instantiated to `promise(string)`.
519
+ // Taking the read's ABI here declared the `.call()` result already narrowed
520
+ // and emitted `return field.call("text")` into a `Promise<std::string>`
521
+ // lambda -- a C++ type error, not a refusal
522
+ // (`test/runtime/pending-promise-payload-narrowed-at-call.ts`). The
523
+ // conversion below then adapts the stored result to the read's, or refuses
524
+ // and declines the fusion.
525
+ const storedField = ctx.classes.get(site.owner)?.fields.find((field) => field.key === fieldName)?.representation ?? null;
526
+ const storedAbi = storedField !== null && (storedField.kind === 'function' || storedField.kind === 'function-family' || storedField.kind === 'function-value-dispatch')
527
+ ? storedField.abi
528
+ : callee.abi;
529
+ const bodyAbi = ctx.abiOfCallable(plan.body);
530
+ if (bodyAbi === null)
531
+ return false;
532
+ // Every check above is exactly what `class-layout.ts`'s `lazyCalleeReadsOf`
533
+ // proves BEFORE admitting a GET to `ctx.lazyCalleeReads` -- so a callee this
534
+ // set names is guaranteed to have reached this point, and `emit-properties.ts`'s
535
+ // `emitGet` has already rendered it as a RAW, unmaterialized copy rather than
536
+ // through `lazyMaterializedFieldText`'s guard-and-store text. That copy's own
537
+ // name -- not a fresh read of the field -- is this call's one evaluation of
538
+ // the callee reference, taken (by `emitGet`, at ITS point in program order)
539
+ // BEFORE any of this call's own arguments could reassign the field: exactly
540
+ // the ECMA-262 order `c.json(c.json = other)` needs and the field-time guard
541
+ // read below, on its own, does not give.
542
+ const snapshot = ctx.lazyCalleeReads.has(operation.callee.value) ? operandText(ctx, operation.callee) : null;
543
+ // A GENERIC field whose `function-value-dispatch` read carries a per-call
544
+ // instantiated result (`test/runtime/pending-promise-payload-narrowed-at-call.ts`'s
545
+ // `cached`: `promise(string)` at one call site, `promise(scalar(number))`
546
+ // at another, from the identical field) has no `functionId` for the guard
547
+ // above to catch -- the census's canonical `plan.body` names the GENERIC
548
+ // declaration, whose own result need not agree with THIS call's. Rather
549
+ // than special-case every shape that can disagree, this tries the direct
550
+ // branch's conversions and DECLINES the fusion (falls back to today's
551
+ // always-correct materializing text) the moment one refuses, the same
552
+ // "prove it before committing" fail-closed answer `receiver whose
553
+ // representation is not the declaring class/subclass` above already gives.
554
+ // `isCppEmitBlockedError` is this file's own distinguishing test for exactly
555
+ // that kind of refusal; anything else escapes as the genuine defect it is.
556
+ try {
557
+ const receiverText = operandText(ctx, memberRead.receiver);
558
+ const fieldMember = cppRecordFieldName(fieldName);
559
+ const accessor = memberAccessOperator(receiverRepresentation.ownership);
560
+ // An arrow's OWN abi never states a receiver (13.2.4: no `this` binding of
561
+ // its own) -- `plan.bodyReceiverRepresentation` is the ONE place that
562
+ // captured receiver is recorded, so a body with neither is genuinely
563
+ // receiver-free (`censusLazyArrowFields`'s `{kind: 'none'}` admission).
564
+ const bodyReceiver = bodyAbi.receiver ?? plan.bodyReceiverRepresentation;
565
+ // `physicalFrame` states whether the receiver occupies the frame's first
566
+ // formal for `paddedArguments`'/`receivableArguments`' own arithmetic --
567
+ // the identical adjustment the ordinary direct-callee path makes for a
568
+ // method value whose semantic ABI declares no receiver of its own (this
569
+ // file's own `physicalFrame`, further below, and `EmitContext.
570
+ // directCallReceivers`'s doc).
571
+ const physicalFrame = { ...bodyAbi, receiver: bodyReceiver };
572
+ const result = operation.result;
573
+ const voidResult = result === null || result.representation.kind === 'void';
574
+ const resultType = voidResult ? 'void' : cppTypeOf(result.representation);
575
+ // The receiver is bound ONCE, by `gea_lazy_receiver` below -- passed here
576
+ // as that plain local name, not re-derived through `receiverArgumentText`,
577
+ // exactly as `class-layout.ts`'s `lazyMaterializedFieldText` already
578
+ // passes it to `initializer` unconverted: a subclass instance's `Ref`
579
+ // converts to the declaring class's `Ref` implicitly, the same conversion
580
+ // struct member access on that same local already relies on for
581
+ // `fieldMember` below.
582
+ const directArgs = [
583
+ ...(bodyReceiver !== null ? ['gea_lazy_receiver'] : []),
584
+ ...receivableArguments(physicalFrame, operation.arguments).map((argument, position) => argumentText(ctx, physicalFrame, position, argument))
585
+ ];
586
+ const directPadded = paddedArguments(physicalFrame, directArgs, 'lazy field direct call');
587
+ const directInvocation = `${cppBodyName(plan.body)}(${[...(plan.bodyHasEnvironment ? ['nullptr'] : []), ...directPadded].join(', ')})`;
588
+ const storedArgs = receivableArguments(storedAbi, operation.arguments).map((argument, position) => argumentText(ctx, storedAbi, position, argument));
589
+ const storedPadded = paddedArguments(storedAbi, storedArgs, 'lazy field stored call');
590
+ // `snapshot` names the copy `emitGet` already rendered, read once at the
591
+ // callee's own evaluation point; the field-time `auto&` alias is the copy's
592
+ // stand-in ONLY where no snapshot exists.
593
+ const storedInvocation = `${snapshot ?? 'gea_lazy_field'}.call(${storedPadded.join(', ')})`;
594
+ const branchText = (abi, invocation) => {
595
+ if (voidResult)
596
+ return `${invocation}; return;`;
597
+ if (abi.result.kind === 'void') {
598
+ const converted = alignedValueText(ctx, 'emit-callable.ts:lazy-field-call', { kind: 'undefined' }, result.representation, cppUndefinedValue);
599
+ if (converted === null) {
600
+ throw createCppEmitBlockedError(`conversion:undefined->${representationKey(result.representation)}`, 'a void lazy arrow field call result has no installed conversion to its published result');
601
+ }
602
+ return `${invocation}; return ${converted};`;
603
+ }
604
+ const converted = alignedValueText(ctx, 'emit-callable.ts:lazy-field-call', abi.result, result.representation, invocation);
605
+ if (converted === null) {
606
+ throw createCppEmitBlockedError(`conversion:${representationKey(abi.result)}->${representationKey(result.representation)}`, `a lazy arrow field call result cannot convert from ${representationKey(abi.result)} to ${representationKey(result.representation)}`);
607
+ }
608
+ return `return ${converted};`;
609
+ };
610
+ // Both branches' text is built -- including the RESULT conversion, the one
611
+ // most likely to refuse for a generic field -- before anything is pushed
612
+ // to `lines`, so a refusal caught below has emitted nothing for this
613
+ // function to undo.
614
+ const storedBranch = branchText(storedAbi, storedInvocation);
615
+ // The direct branch may refuse where the stored one does not: a generic
616
+ // field's body is emitted ONCE, for one instantiation's result
617
+ // (`Promise<std::string>` for `cached`), so a call instantiated to another
618
+ // payload (`this.cached('count')`) has no conversion from the body's result
619
+ // while the stored callable -- whose result is the union of every payload
620
+ // -- converts through its arm. That call is not lost: the field is
621
+ // materialized first (the same initializer `lazyMaterializedFieldText`
622
+ // calls) and the stored branch alone is taken, which is exactly the
623
+ // pre-fusion text with the result conversion the ordinary `.call()` path
624
+ // below cannot add (it declares the result in the READ's type and would
625
+ // hand clang a `Promise<union>` for a `Promise<double>`).
626
+ const directBranch = (() => {
627
+ try {
628
+ return branchText(bodyAbi, directInvocation);
629
+ }
630
+ catch (error) {
631
+ if (!isCppEmitBlockedError(error))
632
+ throw error;
633
+ return null;
634
+ }
635
+ })();
636
+ // A snapshot needs no `auto& gea_lazy_field` alias into the field at all --
637
+ // that alias is precisely the re-read the snapshot exists to avoid, since
638
+ // an argument between the original read and this call may have reassigned
639
+ // the field to something the snapshot never saw.
640
+ const fieldText = `gea_lazy_receiver${accessor}${fieldMember}`;
641
+ const materialize = snapshot !== null
642
+ ? `if (${snapshot}.invoke == nullptr) { ${snapshot} = ${cppBodyName(plan.initializer)}(gea_lazy_receiver); ` +
643
+ `if (${fieldText}.invoke == nullptr) { ${fieldText} = ${snapshot}; } } `
644
+ : `auto& gea_lazy_field = ${fieldText}; if (gea_lazy_field.invoke == nullptr) { gea_lazy_field = ${cppBodyName(plan.initializer)}(gea_lazy_receiver); } `;
645
+ const invocation = directBranch === null
646
+ ? `[&]() -> ${resultType} { const auto& gea_lazy_receiver = ${receiverText}; ${materialize}${storedBranch} }()`
647
+ : snapshot !== null
648
+ ? `[&]() -> ${resultType} { const auto& gea_lazy_receiver = ${receiverText}; ` +
649
+ `if (${snapshot}.invoke == nullptr) { ${directBranch} } else { ${storedBranch} } }()`
650
+ : `[&]() -> ${resultType} { const auto& gea_lazy_receiver = ${receiverText}; auto& gea_lazy_field = ${fieldText}; ` +
651
+ `if (gea_lazy_field.invoke == nullptr) { ${directBranch} } else { ${storedBranch} } }()`;
652
+ if (result === null)
653
+ lines.push(`${invocation};`);
654
+ else if (result.representation.kind === 'void') {
655
+ lines.push(`${invocation};`);
656
+ defineValueAlias(ctx, result, '(void)0');
657
+ }
658
+ else
659
+ lines.push(`${defineValue(ctx, result)} = ${invocation};`);
660
+ return true;
661
+ }
662
+ catch (error) {
663
+ if (!isCppEmitBlockedError(error))
664
+ throw error;
665
+ // The ordinary `.call()` path declares its result in the READ's type. That
666
+ // is only the stored callable's own result when the two agree physically;
667
+ // a stored branch that refused to convert between them has just proved
668
+ // they do not, and declining would emit C++ clang rejects (or, with a
669
+ // reinterpreting carrier, silently misreads). Refuse by name instead.
670
+ if (representationKey(storedAbi.result) !== representationKey(callee.abi.result))
671
+ throw error;
672
+ if (snapshot === null)
673
+ return false;
674
+ // A snapshot the census admitted must NEVER reach the ordinary `.call()`
675
+ // path below unmaterialized: `emitGet` rendered it as the field's RAW
676
+ // storage, with no guarantee `invoke` is non-null. This is the one refusal
677
+ // `lazyCalleeReadsOf` could not predict structurally (a generic field's
678
+ // per-call-site result, `test/runtime/pending-promise-payload-narrowed-at-call.ts`'s
679
+ // `cached`) -- so, rather than decline to a `.call()` this copy cannot
680
+ // safely make, materialize the copy itself (the SAME initializer thunk
681
+ // `class-layout.ts`'s `lazyMaterializedFieldText` calls) and publish it
682
+ // into the field ONLY if the field is still unmaterialized -- an argument
683
+ // between the read and this call may already have written a real value
684
+ // there, which this must not clobber. Never re-reads the field into the
685
+ // local: that would pick up exactly the reassignment the snapshot exists
686
+ // to see past. The ordinary call path below then reads `snapshot` back
687
+ // through `operandText`, now guaranteed materialized either way.
688
+ const receiverText = operandText(ctx, memberRead.receiver);
689
+ const accessor = memberAccessOperator(receiverRepresentation.ownership);
690
+ const fieldText = `${receiverText}${accessor}${cppRecordFieldName(fieldName)}`;
691
+ lines.push(`if (${snapshot}.invoke == nullptr) { ${snapshot} = ${cppBodyName(plan.initializer)}(${receiverText}); ` +
692
+ `if (${fieldText}.invoke == nullptr) { ${fieldText} = ${snapshot}; } }`);
693
+ return false;
694
+ }
695
+ };
696
+ const functionConstructorArgumentTexts = (ctx, arguments_, internalMethod) => arguments_.map((argument) => {
697
+ if (functionConstructorArgumentKindOf(argument.representation) === null) {
698
+ throw createCppEmitBlockedError(`call-abi:function-constructor:${internalMethod}`, 'Function construction requires string or dynamic source arguments');
699
+ }
700
+ return `gea::Eval::functionArgument(${operandText(ctx, argument)})`;
701
+ });
702
+ export const emitCall = (ctx, lines, operation) => {
703
+ if (ctx.numericCalls.get(operation) === 'imul') {
704
+ const args = operation.arguments.map((argument) => {
705
+ const text = operandText(ctx, argument);
706
+ // A proven integer can still live in a double global/captured cell.
707
+ // Convert through the exact signed carrier before taking its low bits:
708
+ // casting a negative double directly to uint32_t is undefined in C++.
709
+ return isIntegerStorageValue(ctx, argument.value)
710
+ ? `static_cast<std::uint32_t>(static_cast<long long>(${text}))`
711
+ : `gea::toUint32(${text})`;
712
+ });
713
+ const expression = `gea::integerImul(${args.join(', ')})`;
714
+ if (operation.result && !ctx.unreadValues.has(operation.result.id))
715
+ lines.push(`${defineValue(ctx, operation.result)} = ${expression};`);
716
+ else
717
+ lines.push(`${expression};`);
718
+ return;
719
+ }
720
+ if (operation.result !== null && ctx.unreadValues.has(operation.result.id)) {
721
+ emitCall(ctx, lines, { ...operation, result: null });
722
+ return;
723
+ }
724
+ if (emitNullishInvocation(ctx, lines, operation))
725
+ return;
726
+ if (operation.callee.representation.kind === 'native-handle' && operation.callee.representation.protocol === 'FunctionConstructor') {
727
+ if (!ctx.deriver.dynamicFallback)
728
+ throw createCppEmitBlockedError('call-abi:function-constructor', 'Function construction requires --dynamic-fallback');
729
+ const args = functionConstructorArgumentTexts(ctx, operation.arguments, 'call');
730
+ const expression = `gea::Eval::constructFunction({${args.join(', ')}})`;
731
+ if (operation.result)
732
+ lines.push(`${defineValue(ctx, operation.result)} = ${expression};`);
733
+ else
734
+ lines.push(`${expression};`);
735
+ return;
736
+ }
737
+ const functionSourceText = ctx.functionSourceReads.get(operation.callee.value);
738
+ if (functionSourceText) {
739
+ const text = functionSourceText;
740
+ if (operation.result?.representation.kind === 'void') {
741
+ lines.push(`${text};`);
742
+ defineValueAlias(ctx, operation.result, '(void)0');
743
+ }
744
+ else if (operation.result) {
745
+ const converted = alignedValueText(ctx, 'emit-callable.ts:794', { kind: 'string' }, operation.result.representation, text);
746
+ if (converted === null)
747
+ throw createCppEmitBlockedError(`conversion:string->${representationKey(operation.result.representation)}`, 'Function.toString result has no string conversion');
748
+ lines.push(`${defineValue(ctx, operation.result)} = ${converted};`);
749
+ }
750
+ return;
751
+ }
752
+ // Before every dispatch path below, because this one renders STATEMENTS
753
+ // rather than an expression a single assignment consumes: `JSON.stringify`
754
+ // serialized straight into the cell that receives it. See
755
+ // `emit-json.ts`'s `jsonStringifyFillLines`.
756
+ const jsonFill = jsonStringifyFillLines(ctx, operation);
757
+ if (jsonFill !== null) {
758
+ lines.push(...jsonFill);
759
+ return;
760
+ }
761
+ // Both host paths -- a host method reached through a receiver, and a host
762
+ // handle used as the callee itself -- render a qualified C++ expression
763
+ // rather than a call through a callable carrier (see `emit-host-invoke.ts`).
764
+ const hostCall = hostCallText(ctx, operation);
765
+ if (hostCall !== null) {
766
+ // A member the host states is REALLY `void` -- `OscillatorNode.connect`'s
767
+ // ambient declaration says `AudioDestinationNode` for the Web Audio
768
+ // chaining convention, `gea::host::OscillatorNode::connect` is `void` --
769
+ // is rendered as a bare statement regardless of `operation.result`: the
770
+ // checker's ABI minted a result carrier from the declared type, and
771
+ // assigning that carrier from a void C++ expression is what "no viable
772
+ // overloaded '='" was, at the one place upstream that knows the real
773
+ // signature (`HostSpellings.voidResults`, host-members.ts). Discarding
774
+ // here is sound exactly when the discarded value is never read: if some
775
+ // later operation still names `operation.result.id` as an operand, that
776
+ // read throws `nameOfValue`'s own "read before it is defined" error
777
+ // rather than silently compiling a wrong value -- fail closed, not fail
778
+ // quiet.
779
+ const read = ctx.hostMemberReads.get(operation.callee.value);
780
+ const forcedVoid = read !== undefined && ctx.hosts.voidResults.has(`${read.protocol}.${read.member}`);
781
+ if (!operation.result) {
782
+ lines.push(`${hostCall};`);
783
+ return;
784
+ }
785
+ if (operation.result.representation.kind === 'void') {
786
+ lines.push(`${hostCall};`);
787
+ defineValueAlias(ctx, operation.result, '(void)0');
788
+ return;
789
+ }
790
+ if (forcedVoid) {
791
+ lines.push(`${hostCall};`);
792
+ return;
793
+ }
794
+ // As with a host data member: what the host's C++ returns and what the
795
+ // program holds are not always one carrier -- see `hostResultText`.
796
+ const hostMember = read === undefined ? undefined : hostMemberOf(ctx.hosts.members, read.protocol, read.member);
797
+ const dynamicHostResult = hostMember?.kind === 'method' && hostMember.result === 'dynamic';
798
+ const spelling = dynamicHostResult ? { kind: 'path', text: hostCall, result: 'dynamic' } : undefined;
799
+ lines.push(`${defineValue(ctx, operation.result)} = ${hostResultText(operation.result.representation, hostCall, spelling)};`);
800
+ return;
801
+ }
802
+ // A String/Array.prototype method read defers the same way a host member's
803
+ // does (see `emit-prototype-invoke.ts`'s header) -- checked here, before the
804
+ // generic callable-carrier dispatch below, for the identical reason: this
805
+ // callee was never materialized as a real `CallableObject`.
806
+ const prototypeCall = prototypeMethodCallText(ctx, operation);
807
+ if (prototypeCall !== null) {
808
+ const expression = typeof prototypeCall === 'string' ? prototypeCall : prototypeCall.expression;
809
+ const resultStorage = typeof prototypeCall === 'string' ? undefined : prototypeCall.resultStorage;
810
+ if (!operation.result)
811
+ lines.push(`${expression};`);
812
+ else if (operation.result.representation.kind === 'void') {
813
+ lines.push(`${expression};`);
814
+ defineValueAlias(ctx, operation.result, '(void)0');
815
+ }
816
+ else
817
+ lines.push(`${defineValue(ctx, operation.result, resultStorage)} = ${expression};`);
818
+ // A call that CHANGED a reactive array's contents ticks its revision cell,
819
+ // so a list rendered from it rebuilds. `push`/`splice`/`sort` mutate;
820
+ // `slice`/`concat`/`map` build a new array and owe nothing.
821
+ const mutated = ctx.reactiveOrigins.get(operation.callee.value);
822
+ const member = ctx.prototypeMethodReads.get(operation.callee.value)?.member;
823
+ if (mutated !== undefined && member !== undefined && mutatingArrayMembers.has(member))
824
+ lines.push(`${reactiveRevisionText(ctx, mutated)}.notify();`);
825
+ return;
826
+ }
827
+ if (emitUnionMethodCall(ctx, lines, operation))
828
+ return;
829
+ if (emitLazyArrowFieldCall(ctx, lines, operation))
830
+ return;
831
+ // `f?.(x)` proves its callee present and then calls it, so the operand's
832
+ // declared type is the callable while the value flowing in is still the
833
+ // `Optional<callable>` the plan gave the read -- the same carrier gap a
834
+ // present receiver has, answered by the same helper. It is unwrapped here
835
+ // rather than at the top of this function so a host or prototype call, which
836
+ // returns above without ever loading a callable, does not emit a dereference
837
+ // nothing reads.
838
+ const calleeOperand = unwrapPresentValue(ctx, lines, operation.callee);
839
+ const callee = calleeOperand.representation;
840
+ // A CHOICE of generic functions: the callee is the index of the member the
841
+ // cell holds, and `operation.family` names the copy each member runs at
842
+ // this call. Every arm is a direct call by name, padded to its own
843
+ // convention -- the arguments were packed against none
844
+ // (`ir/lower-invocation.ts`), exactly as a callable union's arms are.
845
+ if (callee.kind === 'generic-function-set') {
846
+ if (!operation.family)
847
+ throw createCppEmitBlockedError('call-abi:generic-function-set', 'a call through a generic function set names no instantiated family');
848
+ if (operation.receiver !== null)
849
+ throw createCppEmitBlockedError('call-abi:generic-function-set', 'a generic function set call carries a receiver its members declare none of');
850
+ const family = operation.family;
851
+ const voidResult = operation.result?.representation.kind === 'void';
852
+ const branches = callee.members.map((member, index) => {
853
+ const target = family.find((entry) => entry.member === member);
854
+ if (!target)
855
+ throw createCppEmitBlockedError('call-abi:generic-function-set', `generic function set member ${member} has no instantiated copy at this call`);
856
+ const abi = ctx.abiOfCallable(target.functionId);
857
+ if (!abi || abi.receiver !== null || abi.restFrom !== null) {
858
+ throw createCppEmitBlockedError('call-abi:generic-function-set', `generic function set member ${member} needs a fixed, receiver-free calling convention`);
859
+ }
860
+ const args = receivableArguments(abi, operation.arguments).map((argument, position) => argumentText(ctx, abi, position, argument));
861
+ const invocation = `${cppBodyName(target.functionId)}(${paddedArguments(abi, args, 'generic set call').join(', ')})`;
862
+ let body = `${invocation}; return;`;
863
+ if (operation.result && !voidResult) {
864
+ const source = abi.result.kind === 'void' ? { kind: 'undefined' } : abi.result;
865
+ const text = abi.result.kind === 'void' ? cppUndefinedValue : invocation;
866
+ const converted = alignedValueText(ctx, 'emit-callable.ts:909', source, operation.result.representation, text);
867
+ if (converted === null) {
868
+ throw createCppEmitBlockedError(`conversion:${representationKey(abi.result)}->${representationKey(operation.result.representation)}`, `generic function set member ${member} returns ${representationKey(abi.result)}, which cannot fill ${representationKey(operation.result.representation)}`);
869
+ }
870
+ body = `${abi.result.kind === 'void' ? `${invocation}; ` : ''}return ${converted};`;
871
+ }
872
+ return `case ${index}: { ${body} }`;
873
+ });
874
+ const resultType = !operation.result || voidResult ? 'void' : cppTypeOf(operation.result.representation);
875
+ const invocation = `[&]() -> ${resultType} { switch (${operandText(ctx, calleeOperand)}) { ${branches.join(' ')} ` +
876
+ `default: gea::detail::refuseTaggedUnionArmMismatch("a generic function set tag naming no member"); } }()`;
877
+ if (!operation.result)
878
+ lines.push(`${invocation};`);
879
+ else if (voidResult) {
880
+ lines.push(`${invocation};`);
881
+ defineValueAlias(ctx, operation.result, '(void)0');
882
+ }
883
+ else
884
+ lines.push(`${defineValue(ctx, operation.result)} = ${invocation};`);
885
+ return;
886
+ }
887
+ // A sum of native callables keeps each frame intact. Dispatching on its
888
+ // tag invokes that frame directly; boxing the sum would erase information
889
+ // already present in every arm. Rest/receiver frames need their own packing
890
+ // and are deliberately refused until that per-arm operation is installed.
891
+ if (callee.kind === 'tagged-union') {
892
+ if (operation.receiver !== null || callee.arms.length === 0) {
893
+ throw createCppEmitBlockedError('call-abi:tagged-union-call', 'a native callable union needs nonempty, receiver-free alternatives');
894
+ }
895
+ const voidResult = operation.result?.representation.kind === 'void';
896
+ const branches = callee.arms.map((arm, index) => {
897
+ const selected = `gea_union_callee.get<${index}>()`;
898
+ // A bare `Function` arm genuinely has no static frame. Keep that arm's
899
+ // dynamic invocation local to the union branch while fixed native arms
900
+ // retain their direct convention. Hono's middleware selection is the
901
+ // representative shape: `Function | Next`, narrowed present before the
902
+ // call. Boxing the whole sum would erase Next's known ABI; refusing the
903
+ // dynamic arm would reject a call the runtime already knows how to make.
904
+ if (arm.value.kind === 'dynamic') {
905
+ const boxed = operation.arguments.map((argument) => alignedText(ctx, arm.value, argument, 'boxed-arm'));
906
+ const invocation = `${selected}.callAsFunction({${boxed.join(', ')}})`;
907
+ let body = `${invocation}; return;`;
908
+ if (operation.result && !voidResult) {
909
+ const held = operation.result.representation;
910
+ const converted = held.kind === 'dynamic' ? invocation : alignedValueText(ctx, 'emit-callable.ts:954', arm.value, held, invocation);
911
+ if (converted === null) {
912
+ throw createCppEmitBlockedError(`conversion:${representationKey(arm.value)}->${representationKey(held)}`, `a dynamic callable-union arm's result is read as ${representationKey(held)}, and no installed load performs that conversion`);
913
+ }
914
+ body = `return ${converted};`;
915
+ }
916
+ return index === callee.arms.length - 1 ? body : `if (gea_union_callee.is<${index}>()) { ${body} }`;
917
+ }
918
+ const abi = callableObjectAbi(arm.value);
919
+ if (!abi || abi.receiver !== null || abi.restFrom !== null) {
920
+ throw createCppEmitBlockedError('call-abi:tagged-union-call', 'a native callable union arm needs a fixed, receiver-free calling convention');
921
+ }
922
+ const args = receivableArguments(abi, operation.arguments).map((argument, position) => argumentText(ctx, abi, position, argument));
923
+ const invocation = `${selected}.call(${paddedArguments(abi, args, 'union call').join(', ')})`;
924
+ let body = `${invocation}; return;`;
925
+ if (operation.result && !voidResult) {
926
+ const source = abi.result.kind === 'void' ? { kind: 'undefined' } : abi.result;
927
+ const text = abi.result.kind === 'void' ? cppUndefinedValue : invocation;
928
+ const converted = alignedValueText(ctx, 'emit-callable.ts:975', source, operation.result.representation, text);
929
+ if (converted === null)
930
+ throw createCppEmitBlockedError(`conversion:${representationKey(source)}->${representationKey(operation.result.representation)}`, 'a native callable union result has no installed conversion');
931
+ body = `${abi.result.kind === 'void' ? `${invocation}; ` : ''}return ${converted};`;
932
+ }
933
+ return index === callee.arms.length - 1 ? body : `if (gea_union_callee.is<${index}>()) { ${body} }`;
934
+ });
935
+ const resultType = !operation.result || voidResult ? 'void' : cppTypeOf(operation.result.representation);
936
+ const invocation = `[&]() -> ${resultType} { const auto& gea_union_callee = ${operandText(ctx, calleeOperand)}; ${branches.join(' ')} }()`;
937
+ if (!operation.result)
938
+ lines.push(`${invocation};`);
939
+ else if (voidResult) {
940
+ lines.push(`${invocation};`);
941
+ defineValueAlias(ctx, operation.result, '(void)0');
942
+ }
943
+ else
944
+ lines.push(`${defineValue(ctx, operation.result)} = ${invocation};`);
945
+ return;
946
+ }
947
+ // A callee the program never gave a type: `const fn: any = handlers[i];
948
+ // fn(event)`. There is no convention to build a frame against, so the
949
+ // arguments cross as boxes and the callable's own declared parameters are
950
+ // recovered by the thunk `gea::Value::box` recorded
951
+ // (`gea::Value::callAsFunction`, gea_runtime.h). Rendered before the
952
+ // callable-carrier dispatch below for the same reason the host paths are:
953
+ // this callee was never materialised as a `CallableObject` the emitter can
954
+ // see the ABI of.
955
+ if (callee.kind === 'dynamic') {
956
+ // The dynamic call adapter transports this separately from positional
957
+ // arguments; the actual callable decides whether its ABI consumes it.
958
+ const boxed = operation.arguments.map((argument) => alignedText(ctx, callee, argument, 'boxed-callee'));
959
+ const receiver = operation.receiver ? boxedValueText(ctx, operation.receiver, 'dynamic call receiver') : 'gea::Value()';
960
+ const text = `${operandText(ctx, calleeOperand)}.callWithReceiver(${receiver}, {${boxed.join(', ')}})`;
961
+ if (!operation.result) {
962
+ lines.push(`${text};`);
963
+ return;
964
+ }
965
+ if (operation.result.representation.kind === 'void') {
966
+ lines.push(`${text};`);
967
+ defineValueAlias(ctx, operation.result, '(void)0');
968
+ return;
969
+ }
970
+ // The call answers a box; what the program holds may be narrower -- `const
971
+ // ok: boolean = fn()` is the checker's answer to a call whose callee is
972
+ // `any`, and the box has to be read back into it.
973
+ const held = operation.result.representation;
974
+ const converted = held.kind === 'dynamic' ? text : alignedValueText(ctx, 'emit-callable.ts:1017', callee, held, text);
975
+ if (converted === null) {
976
+ throw createCppEmitBlockedError(`conversion:${representationKey(callee)}->${representationKey(held)}`, `a dynamic call's result is read as ${representationKey(held)}, and no installed load performs that conversion`);
977
+ }
978
+ lines.push(`${defineValue(ctx, operation.result)} = ${converted};`);
979
+ return;
980
+ }
981
+ if (callee.kind !== 'function' &&
982
+ callee.kind !== 'function-value-dispatch' &&
983
+ callee.kind !== 'function-family' &&
984
+ callee.kind !== 'function-and-constructor') {
985
+ throw createCppEmitBlockedError(`call-abi:no-invoke-path:${callee.kind}`, `a callee carried as "${callee.kind}" has no invoke path; this emitter calls only through a callable carrier`);
986
+ }
987
+ // The convention a *call* site selects, which for a value that is also a
988
+ // constructor is its `[[Call]]` half and never its `[[Construct]]` one.
989
+ const abi = callee.kind === 'function-and-constructor' ? callee.call : callee.abi;
990
+ // A directly-bound class method records the receiver at the property read.
991
+ // Usually IR carries that same receiver on the call. A materialized method
992
+ // value can instead publish the receiver-bearing physical convention while
993
+ // the semantic call still has the receiver-less method-value convention;
994
+ // in that case the authenticated property-read receiver fills the ABI slot.
995
+ // Keep this tied to the exact callee value and direct body: a detached
996
+ // function value has no receiver to recover, and must still refuse below.
997
+ const direct = calleeOperand.value === operation.callee.value ? ctx.directCallees.get(operation.callee.value) : undefined;
998
+ // A direct call's C++ target IS the concrete body, whose declared parameter
999
+ // carriers can be narrower than the semantic ABI at the read that reached
1000
+ // it -- the same erasure the RESULT conversion below already reconciles
1001
+ // through `ctx.directCalleeAbis` (see the comment at its use, further down).
1002
+ // Argument conversion has to go through that identical physical ABI: a
1003
+ // generic method's one C++ body declares a concrete carrier (e.g.
1004
+ // `Optional<Ref<TypedArray<uint8_t>>>` for a `ReadableStream<Uint8Array>`
1005
+ // method) while the semantic read that named it can still carry the wider
1006
+ // erased carrier (`gea::Value`) of the unspecialized declaration. Building
1007
+ // arguments from the semantic `abi` in that case hands the physical body a
1008
+ // `gea::Value` for a slot it never declared, with no conversion rendered.
1009
+ //
1010
+ // WHETHER A RECEIVER TRAVELS is the one thing that stays on the semantic
1011
+ // `abi`, because that is a fact about the CALL -- a method's convention
1012
+ // states a receiver its receiver-less view does not, and reading that off the
1013
+ // physical ABI dropped the receiver of an interface-typed call whose direct
1014
+ // callee was a class method, sliding the first real argument into the
1015
+ // receiver's place (`test/runtime/direct-interface-method-receiver.ts`).
1016
+ //
1017
+ // ARITY AND THE RECEIVER'S CARRIER do NOT. They used to, and that was only
1018
+ // ever true while every body a direct bind could name repeated its
1019
+ // declaration's parameter list. An OVERRIDE need not: method parameters are
1020
+ // bivariant, so `ServerResponse.write(chunk: string | Uint8Array)` overrides
1021
+ // `Writable.write(chunk: unknown, encoding?: unknown, callback?: unknown)`,
1022
+ // and a call reaching that body through `(outgoing as Writable).write(value)`
1023
+ // built the base's three-argument list -- padded with `undefined`, with the
1024
+ // argument boxed into the base's `unknown` slot -- around the override's
1025
+ // one-parameter body, and passed it a `Ref<Writable>` for a
1026
+ // `const Ref<ServerResponse>&`. `@hono/node-server`'s `listener.ts` writes
1027
+ // exactly that (`test/runtime/virtual-call-through-a-base-whose-override-narrows-unknown.ts`).
1028
+ // The surplus arguments are not lost: 10.2.1 binds only the parameters the
1029
+ // body declares and discards the rest, which is what dropping them here
1030
+ // spells.
1031
+ const directAbi = direct === undefined ? abi : (ctx.directCalleeAbis.get(operation.callee.value) ?? abi);
1032
+ // The frame the PHYSICAL call fills: the body's parameter list, under the
1033
+ // call's own answer to whether a receiver occupies the first formal.
1034
+ const physicalFrame = directAbi === abi ? abi : { ...directAbi, receiver: abi.receiver === null ? null : (directAbi.receiver ?? abi.receiver) };
1035
+ const boundReceiverOperand = operation.receiver === null ? ctx.directCallReceivers.get(operation.callee.value) : undefined;
1036
+ const declaredReceiverOperand = operation.receiver ?? (abi.receiver !== null ? (boundReceiverOperand ?? null) : null);
1037
+ // The receiver is the first physical argument when the convention declares
1038
+ // one, and it must be present exactly when it does: a call that passes a
1039
+ // receiver to a convention with none, or omits one where the convention
1040
+ // expects it, is a frame mismatch and not something to paper over. A direct
1041
+ // class method's recorded receiver above is part of that convention, not a
1042
+ // manufactured value.
1043
+ if ((abi.receiver === null) !== (declaredReceiverOperand === null)) {
1044
+ const propertyOrigin = ctx.propertyReadOrigins.get(operation.callee.value);
1045
+ const originText = propertyOrigin === undefined
1046
+ ? 'no property-read origin'
1047
+ : `property-read origin ${representationKey(propertyOrigin.receiver.representation)}.${ctx.staticKeyTexts.get(propertyOrigin.key.value) ?? '<computed>'}`;
1048
+ throw createCppEmitBlockedError('call-abi:receiver-mismatch', declaredReceiverOperand
1049
+ ? 'passes a receiver to a callee whose convention declares none'
1050
+ : `omits the receiver its callee's convention declares (callee ${operation.callee.value} is ${representationKey(callee)}; ${originText}; ` +
1051
+ `${boundReceiverOperand === undefined ? 'no recorded method receiver' : 'recorded method receiver present'})`);
1052
+ }
1053
+ // A host's own free function is called as a function, not through a
1054
+ // callable carrier: the read that reached it rendered nothing and recorded
1055
+ // the host's spelling instead (`emit-bindings.ts`), because there is no
1056
+ // object of that name to load. Asked for as an operand it refuses, which is
1057
+ // why the callee text is only taken on the carrier path.
1058
+ const hostFunction = ctx.hostFunctionReads.get(operation.callee.value);
1059
+ // A host's parameter that the program may omit is declared with a C++
1060
+ // default, which is filled in at the call site and not by passing an
1061
+ // absence. So a host call with a trailing run of optional arguments is
1062
+ // emitted once per arity rather than handed a `gea::Optional` the host's
1063
+ // `double` cannot accept -- see `emit-host-arity.ts`.
1064
+ if (hostFunction !== undefined) {
1065
+ // A host that answers in a `gea::Value` hands the crossing back a carrier
1066
+ // to REBUILD, and a `native-record-ref` names its layout by shape instead
1067
+ // of carrying it (`representation/model.ts`) -- so the materializer, which
1068
+ // reads fields off the representation it is given, saw no fields and fell
1069
+ // back to asking the box to already hold that exact struct. It never does:
1070
+ // `Reflect.getOwnPropertyDescriptor` returns an object the RUNTIME built.
1071
+ // The two are physically one C++ type (`obligations-graph.ts` says so
1072
+ // where it skips the conversion entirely), so this resolves the shape
1073
+ // through the deriver at the one boundary that needs the fields, rather
1074
+ // than threading a deriver through every unbox in the backend.
1075
+ const resolvedRecordRefs = (representation) => {
1076
+ if (representation.kind === 'optional') {
1077
+ const payload = resolvedRecordRefs(representation.payload);
1078
+ return payload === representation.payload ? representation : { ...representation, payload };
1079
+ }
1080
+ if (representation.kind !== 'native-record-ref' || representation.native !== null)
1081
+ return representation;
1082
+ const derived = ctx.deriver.layoutOf(representation.shapeId);
1083
+ return derived.kind === 'record' ? derived : representation;
1084
+ };
1085
+ const reflection = nativeReflectCallText(ctx, operation, hostFunction.kind === 'path' ? hostFunction.text : hostFunction.emit);
1086
+ if (reflection !== null) {
1087
+ lines.push(operation.result ? `${defineValue(ctx, operation.result)} = ${reflection};` : `${reflection};`);
1088
+ return;
1089
+ }
1090
+ // Host overloads consume the actual native value. Do not mint a larger
1091
+ // union just to dispatch it immediately: that instantiates unreachable
1092
+ // host overloads, and an optional wrapper can disagree with the actual
1093
+ // arity. Retain real conversions (e.g. callback ABI adaptation); only a
1094
+ // widening into an identical payload is unnecessary at this boundary.
1095
+ const slotOf = (position, fallback) => (abi.restFrom !== null && position >= abi.restFrom ? undefined : abi.parameters[position]?.value) ?? fallback;
1096
+ const passed = [
1097
+ ...(operation.receiver
1098
+ ? [{ text: receiverArgumentText(ctx, abi, operation.receiver), representation: abi.receiver ?? operation.receiver.representation }]
1099
+ : []),
1100
+ ...receivableArguments(abi, operation.arguments).map((argument, position) => {
1101
+ if (hostFunction.arguments === 'dynamic')
1102
+ return {
1103
+ text: boxedValueText(ctx, argument, 'dynamic host argument'),
1104
+ representation: { kind: 'dynamic', reason: 'declared-any-never-narrowed' }
1105
+ };
1106
+ const slot = slotOf(position, argument.representation);
1107
+ const preserve = hostPayloadIdentity(argument.representation, slot);
1108
+ return {
1109
+ text: preserve ? operandText(ctx, argument) : argumentText(ctx, abi, position, argument),
1110
+ representation: preserve ? argument.representation : slot
1111
+ };
1112
+ })
1113
+ ];
1114
+ const optionals = trailingOptionalCount(passed);
1115
+ const voidResult = operation.result?.representation.kind === 'void';
1116
+ lines.push(...hostArityCallLines({
1117
+ spelling: hostFunction.kind === 'path' && ctx.hosts.nativeArrayFunctions?.has(hostFunction.text)
1118
+ ? { ...hostFunction, arrayArguments: 'native' }
1119
+ : hostFunction.kind === 'path' && ctx.hosts.arraySnapshotFunctions?.has(hostFunction.text)
1120
+ ? { ...hostFunction, arrayArguments: 'snapshot' }
1121
+ : hostFunction,
1122
+ fixed: passed.slice(0, passed.length - optionals),
1123
+ optionals: passed.slice(passed.length - optionals),
1124
+ result: operation.result && !voidResult
1125
+ ? {
1126
+ name: defineValue(ctx, operation.result),
1127
+ representation: hostFunction.result === 'dynamic' ? resolvedRecordRefs(operation.result.representation) : operation.result.representation
1128
+ }
1129
+ : null
1130
+ }));
1131
+ if (operation.result && voidResult)
1132
+ defineValueAlias(ctx, operation.result, '(void)0');
1133
+ return;
1134
+ }
1135
+ const args = [
1136
+ ...(declaredReceiverOperand ? [receiverArgumentText(ctx, physicalFrame, declaredReceiverOperand)] : []),
1137
+ ...receivableArguments(physicalFrame, operation.arguments).map((argument, position) => argumentText(ctx, directAbi, position, argument))
1138
+ ];
1139
+ // A callee whose environment is `nullptr` is called by name. The carrier is
1140
+ // still built wherever the program stores one -- this only decides how THIS
1141
+ // call reaches the body, and an unread `CallableObject` the C++ compiler then
1142
+ // drops costs nothing. Guarded on the operand being the callee itself: `f?.()`
1143
+ // unwraps an `Optional` first, and what was proved present is a different
1144
+ // value from the one the record was keyed by.
1145
+ // A method the program overrides is reached through the OBJECT, not by name:
1146
+ // `virtual-methods.ts` put a dispatch member on the family's root struct, and
1147
+ // the receiver -- always the first padded argument, since a method's
1148
+ // convention states one -- selects the implementation. Binding the body the
1149
+ // member lookup found instead would run the base's for every instance of a
1150
+ // subclass, which compiles and links and is silently wrong.
1151
+ const dispatched = calleeOperand.value === operation.callee.value ? ctx.virtualCallees.get(operation.callee.value) : undefined;
1152
+ if (dispatched !== undefined)
1153
+ ctx.virtualCalleesUsed.add(operation.callee.value);
1154
+ // The receiver a direct bind needs and this call's own convention does not
1155
+ // declare -- see `EmitContext.directCallReceivers`. Prepended to the
1156
+ // PHYSICAL argument list only, so the convention, the plan and every arity
1157
+ // check above stay exactly as they are: this is the one place the emitted
1158
+ // frame and the declared one legitimately differ, because the body being
1159
+ // named is a method and the value being called is its receiver-less view.
1160
+ const boundReceiver = abi.receiver === null && boundReceiverOperand !== undefined ? operandText(ctx, boundReceiverOperand) : undefined;
1161
+ const padded = [...(boundReceiver === undefined ? [] : [boundReceiver]), ...paddedArguments(physicalFrame, args, 'call')];
1162
+ // The callable value is typed at the access site, but the C++ virtual member
1163
+ // is declared with the family root's reconciled ABI. Convert the receiver
1164
+ // and arguments into that ABI before invoking the member; using `args`
1165
+ // directly is only valid when every override repeats the root signature.
1166
+ const virtualArgs = dispatched === undefined
1167
+ ? []
1168
+ : [
1169
+ ...(operation.receiver ? [receiverArgumentText(ctx, dispatched.abi, operation.receiver)] : []),
1170
+ ...receivableArguments(dispatched.abi, operation.arguments).map((argument, position) => argumentText(ctx, dispatched.abi, position, argument))
1171
+ ];
1172
+ const virtualPadded = dispatched === undefined ? [] : paddedArguments(dispatched.abi, virtualArgs, 'virtual call');
1173
+ const memberRead = ctx.propertyReadOrigins.get(operation.callee.value);
1174
+ const memberKey = memberRead === undefined ? undefined : ctx.staticKeyTexts.get(memberRead.key.value);
1175
+ const candidate = memberRead === undefined || memberKey === undefined || calleeOperand.value !== operation.callee.value
1176
+ ? undefined
1177
+ : ctx.callableMemberCandidates.get(callableMemberSlot(memberRead.receiver.representation, memberKey));
1178
+ const stableCandidate = ctx.stableBorrowEntries.get(direct ?? (candidate === undefined ? '' : cppBodyName(candidate)));
1179
+ const potentiallyMovingArguments = new Set(operation.arguments
1180
+ .filter((argument) => transferOf(ctx.dyingArguments, ctx.ownedValues, ctx.ownedDyingValues, argument.value) === 'move')
1181
+ .map((argument) => argument.value));
1182
+ const stableEntry = stableCandidate !== undefined &&
1183
+ stableBorrowEntryAccepts(stableCandidate, operation.arguments, ctx.stableBorrowActuals, potentiallyMovingArguments)
1184
+ ? stableCandidate
1185
+ : undefined;
1186
+ const callMember = candidate === undefined
1187
+ ? 'call'
1188
+ : stableEntry !== undefined
1189
+ ? `callKnownBorrowed<&${cppThunkName(candidate)}, &${stableEntry.name}>`
1190
+ : ctx.borrowableMemberBodies.has(candidate)
1191
+ ? `callKnownBorrowed<&${cppThunkName(candidate)}, &${cppBodyName(candidate)}>`
1192
+ : `callKnown<&${cppThunkName(candidate)}>`;
1193
+ const invocation = dispatched !== undefined
1194
+ ? `${virtualPadded[0]}->${dispatched.member}(${virtualPadded.slice(1).join(', ')})`
1195
+ : direct !== undefined
1196
+ ? `${stableEntry?.name ?? direct}(${padded.join(', ')})`
1197
+ : `${operandText(ctx, calleeOperand)}.${callMember}(${padded.join(', ')})`;
1198
+ if (!operation.result) {
1199
+ lines.push(`${invocation};`);
1200
+ return;
1201
+ }
1202
+ // A call whose expression is explicitly converted to `void` still runs the
1203
+ // callee, but there is no C++ result object to declare. Publish a real void
1204
+ // expression for the SSA result so a following discard can name it without
1205
+ // fabricating storage.
1206
+ if (operation.result.representation.kind === 'void') {
1207
+ lines.push(`${invocation};`);
1208
+ defineValueAlias(ctx, operation.result, '(void)0');
1209
+ return;
1210
+ }
1211
+ const name = defineValue(ctx, operation.result);
1212
+ // A convention whose result is `void` returns nothing at all in C++, so its
1213
+ // call is a statement and never the right-hand side of an assignment. The
1214
+ // language still gives the *expression* a value -- `undefined` -- and an
1215
+ // optional call is where that value becomes real: `d?.toggle()` has to merge
1216
+ // the call's answer with the absent branch's, so the result is materialized
1217
+ // even though a bare `d.toggle()` would discard it. Written as the literal it
1218
+ // is, rather than assigned from a void call, which is exactly the "no viable
1219
+ // overloaded '='" the host path's own `forcedVoid` above already avoids.
1220
+ if (abi.result.kind === 'void') {
1221
+ // Fail closed on any other carrier: a `void` convention can only ever have
1222
+ // produced `undefined`, so a plan that asked for something else is a
1223
+ // disagreement to fix rather than a value to invent here.
1224
+ if (operation.result.representation.kind !== 'undefined') {
1225
+ throw createCppEmitBlockedError(`conversion:void->${representationKey(operation.result.representation)}`, `a callee whose convention returns void was asked for a "${operation.result.representation.kind}" result`);
1226
+ }
1227
+ lines.push(`${invocation};`);
1228
+ lines.push(`${name} = ${cppUndefinedValue};`);
1229
+ return;
1230
+ }
1231
+ // The CONVENTION states what the call produces; the plan states what the
1232
+ // cell holds, and the two are not always the same carrier. A callable read
1233
+ // out of a union arm carries the arm's own convention -- hono's handler
1234
+ // slot declares `gea::Value(Context, Next)` because that arm's return type
1235
+ // is unstated -- while the call's published result is the type the checker
1236
+ // gave the call expression, `Response | Promise<Response>`. Assigning the
1237
+ // convention's result straight into the cell is the "no viable overloaded
1238
+ // '='" clang reports, and there is no defensible identity to claim between
1239
+ // the two: the box has to be read back out.
1240
+ //
1241
+ // Reconciled through the one conversion authority rather than a local
1242
+ // widening, and refused by name when it has no answer, so a disagreement
1243
+ // between the two is a defect to fix rather than a cast invented here.
1244
+ // A virtual call is physically declared with the family root's ABI, even
1245
+ // when the callable value and the call expression retain a covariant
1246
+ // descendant result. Reconcile from the carrier the invocation actually
1247
+ // returns; using the semantic callable ABI here makes that conversion look
1248
+ // like identity and emits `Ref<Derived> = Ref<Base>` at the assignment.
1249
+ // `convertedValueText` performs the checked class narrowing using the
1250
+ // target's ancestry, while non-virtual calls keep their ordinary ABI.
1251
+ const physicalResult = dispatched?.abi.result ?? ctx.directCalleeAbis.get(operation.callee.value)?.result ?? abi.result;
1252
+ const produced = alignedValueText(ctx, 'emit-callable.ts:1285', physicalResult, operation.result.representation, callResultName);
1253
+ if (produced === null) {
1254
+ throw createCppEmitBlockedError(`conversion:${representationKey(physicalResult)}->${representationKey(operation.result.representation)}`, `a callee whose convention returns "${physicalResult.kind}" cannot fill a "${operation.result.representation.kind}" result`);
1255
+ }
1256
+ // Identity needs no local at all. When a real conversion was rendered it
1257
+ // may read its source more than once (the unbox-into-a-union chain tests
1258
+ // the tag before loading the payload), so the call is evaluated ONCE into a
1259
+ // local and the conversion reads that -- an IIFE rather than two statements
1260
+ // because a declaration between two of this body's `goto` labels would let
1261
+ // a jump bypass its initialization.
1262
+ if (produced === callResultName) {
1263
+ lines.push(`${name} = ${invocation};`);
1264
+ return;
1265
+ }
1266
+ const target = cppTypeOf(operation.result.representation);
1267
+ lines.push(`${name} = ([&]() -> ${target} { auto ${callResultName} = ${invocation}; return ${produced}; }());`);
1268
+ };
1269
+ /** The local a call's own result is read into when its carrier has to be reconciled with the cell's. */
1270
+ const callResultName = 'gea_call_result';
1271
+ /** How many of a call's arguments trail it as optionals -- the run at the end, and only the run at the end. */
1272
+ const hostPayloadIdentity = (source, target) => {
1273
+ if (representationKey(source) === representationKey(target))
1274
+ return true;
1275
+ if (target.kind === 'optional')
1276
+ return hostPayloadIdentity(source, target.payload);
1277
+ if (target.kind === 'tagged-union')
1278
+ return target.arms.some((arm) => hostPayloadIdentity(source, arm.value));
1279
+ return false;
1280
+ };
1281
+ const trailingOptionalCount = (args) => {
1282
+ let count = 0;
1283
+ for (let index = args.length - 1; index >= 0; index -= 1) {
1284
+ if (args[index]?.representation.kind !== 'optional')
1285
+ break;
1286
+ count += 1;
1287
+ }
1288
+ return count;
1289
+ };
1290
+ /**
1291
+ * `super(...)`: the base's initialization against the object under
1292
+ * construction, then this class's own field initializers.
1293
+ *
1294
+ * Both halves are the language's, in the language's order. `super()` runs the
1295
+ * base chain -- its field initializers and its constructor body -- against the
1296
+ * receiver the derived construction already allocated, which is why it calls
1297
+ * the base's *initialize* half rather than its construct: constructing would
1298
+ * allocate a second object of the base's own type and throw the derived one
1299
+ * away. Immediately after it returns, and before the next statement of this
1300
+ * constructor, the derived class's own field initializers run; that is why they
1301
+ * are here and not in `constructDefinitionsOf`, which cannot see where in the
1302
+ * body they belong.
1303
+ *
1304
+ * Which class this is, is read from the projection rather than from the frame:
1305
+ * the body's own receiver carrier names the class the *receiver* has, which for
1306
+ * a derived constructor is the derived class either way, but only
1307
+ * `ClassLayout.constructor` states that this body is that class's constructor
1308
+ * at all -- a `super()` reached from a nested arrow is a different frame and is
1309
+ * refused here rather than silently initializing the enclosing class.
1310
+ */
1311
+ export const emitSuperInitialize = (ctx, lines, operation) => {
1312
+ const owning = [...ctx.classes.values()].find((layout) => layout.constructor === ctx.owner);
1313
+ if (!owning) {
1314
+ throw createCppEmitBlockedError('call-abi:super-initialize', `runs in ${ctx.owner}, which no class publishes as its constructor body, so there is no base to initialize`);
1315
+ }
1316
+ if (owning.base === null && owning.nativeBase === null) {
1317
+ throw createCppEmitBlockedError('call-abi:super-initialize', `class ${owning.declaration} states no base class to initialize`);
1318
+ }
1319
+ if (ctx.abi?.receiver?.kind !== 'class-ref') {
1320
+ throw createCppEmitBlockedError('call-abi:super-initialize', `the constructor of class ${owning.declaration} declares no class receiver to initialize the base against`);
1321
+ }
1322
+ if (owning.nativeBase !== null) {
1323
+ if (owning.nativeBase.instance.native !== cppErrorNativeType) {
1324
+ throw createCppEmitBlockedError('call-abi:super-initialize', `native base ${owning.nativeBase.protocol} uses "${owning.nativeBase.instance.native ?? 'no native layout'}"; only the intrinsic Error layout has an existing-receiver initializer`);
1325
+ }
1326
+ const baseStatements = nativeErrorBaseInitializeStatements(ctx.deriver, cppReceiverName, operation.arguments.slice(0, 2).map((argument) => ({ representation: argument.representation, text: operandText(ctx, argument) })));
1327
+ if (isNativeErrorBaseRefusal(baseStatements)) {
1328
+ throw baseStatements.refusal === 'conversion'
1329
+ ? createCppEmitBlockedError(`conversion:${baseStatements.conversion}`, baseStatements.reason)
1330
+ : createCppEmitBlockedError('call-abi:super-initialize', baseStatements.reason);
1331
+ }
1332
+ for (const statement of baseStatements)
1333
+ lines.push(statement);
1334
+ const fieldInitializers = cppFieldInitializerStatements(ctx, owning.declaration, owning.fields, cppReceiverName, (field) => owning.instance === null ? null : declaredRecordFieldOf(ctx.deriver, owning.instance, field.key, ctx.classes));
1335
+ if (typeof fieldInitializers === 'string')
1336
+ throw createCppEmitBlockedError('conversion:class-property-initializer', fieldInitializers);
1337
+ for (const statement of fieldInitializers)
1338
+ lines.push(statement);
1339
+ return;
1340
+ }
1341
+ const baseDeclaration = owning.base;
1342
+ if (baseDeclaration === null) {
1343
+ throw createCppEmitBlockedError('call-abi:super-initialize', `class ${owning.declaration} has neither a native nor a program class base`);
1344
+ }
1345
+ // A `super()` that omits a trailing argument the base gives a default is the
1346
+ // same omission as any other call's, and is padded the same way -- against
1347
+ // the BASE's construct convention, which is the one `constructDefinitionsOf`
1348
+ // spells the initializer's formals from. Joining the arguments raw instead
1349
+ // emitted `gea_initialize_Base(this)` against a two-parameter initializer:
1350
+ // `class IncomingMessage extends EventEmitter` calls `super()` while
1351
+ // `EventEmitter(options: EventEmitterOptions = {})` declares one parameter,
1352
+ // and the C++ compiler is where that landed rather than here.
1353
+ const baseConstruct = ctx.classes.get(baseDeclaration)?.construct ?? null;
1354
+ if (baseConstruct === null) {
1355
+ throw createCppEmitBlockedError('call-abi:super-initialize', `base class ${baseDeclaration} published no construct convention, so \`super(...)\` has no frame to fill`);
1356
+ }
1357
+ const received = receivableArguments(baseConstruct, operation.arguments);
1358
+ const args = paddedArguments(baseConstruct, received.map((argument, position) => argumentText(ctx, baseConstruct, position, argument, 'super-initialize')), 'super-initialize');
1359
+ lines.push(`${cppInitializeName(baseDeclaration)}(${[cppReceiverName, ...args].join(', ')});`);
1360
+ const fieldInitializers = cppFieldInitializerStatements(ctx, owning.declaration, owning.fields, cppReceiverName, (field) => owning.instance === null ? null : declaredRecordFieldOf(ctx.deriver, owning.instance, field.key, ctx.classes));
1361
+ if (typeof fieldInitializers === 'string')
1362
+ throw createCppEmitBlockedError('conversion:class-property-initializer', fieldInitializers);
1363
+ for (const statement of fieldInitializers)
1364
+ lines.push(statement);
1365
+ };
1366
+ /**
1367
+ * Declares a capture's box before the environment that captures it is built
1368
+ * when no earlier binding write allocated that box.
1369
+ *
1370
+ * Most boxed slots already exist because the owning frame's first
1371
+ * `binding-write` allocates them before a closure is created. Two ordinary
1372
+ * language shapes do not: a closure can precede the first write to a
1373
+ * declaration (`let cached; const get = () => cached; cached = value`), and a
1374
+ * closure can hold ITSELF (`CaptureSlot.boxed` set because
1375
+ * `closureInitialized.get(declaration) === owner`, `captures.ts`):
1376
+ * `const loop = (ts) => { ...; requestAnimationFrame(loop) }` allocates the
1377
+ * closure before the initializing write. In both cases the environment needs
1378
+ * a handle to the cell immediately. So this declares an empty box exactly
1379
+ * once, ahead of the environment build, and marks it declared; a later
1380
+ * initializing write that follows (`emitBindingWrite`) then sees it already
1381
+ * declared and only fills it in, exactly as any later reassignment would.
1382
+ */
1383
+ /**
1384
+ * The packed environment one capturing body is entered with, built in the
1385
+ * frame that supplies its captures.
1386
+ *
1387
+ * `gea::packEnvironment` (gea_runtime.h) decides where the captured state
1388
+ * physically goes, and the body's own `unpackEnvironment` reads that same
1389
+ * decision from the same predicate, so the two cannot disagree. Where it
1390
+ * fits, the state IS the pointer the carrier holds and nothing is allocated;
1391
+ * where it does not, the struct is a `gea::Ref` block every holder counts on
1392
+ * -- which is why there is no "who deletes it" question here: the last holder
1393
+ * does.
1394
+ *
1395
+ * Two callers, and they are the two ways a body can be reached with state it
1396
+ * did not declare: a `CallableObject` carries it for an allocated closure,
1397
+ * and a record member carries it for a capturing ACCESSOR
1398
+ * (`emit-allocation.ts`), which has no carrier of its own.
1399
+ */
1400
+ export const packedEnvironmentText = (ctx, lines, functionId, admission) => {
1401
+ if (admission.kind !== 'ok')
1402
+ throw new Error(`packedEnvironmentText called for ${functionId} with no admitted environment`);
1403
+ for (const slot of admission.layout.slots)
1404
+ ensureBoxedSlotDeclared(ctx, lines, slot);
1405
+ const fields = [
1406
+ ...admission.layout.slots.map((slot) => slot.boxed
1407
+ ? bindingReference(ctx, slot.declaration, `a capture of ${functionId}`).name
1408
+ : captureFieldText(ctx, slot.declaration, slot.representation, bindingReference(ctx, slot.declaration, `a capture of ${functionId}`).name)),
1409
+ ...(admission.layout.receiver !== null ? [cppReceiverName] : [])
1410
+ ];
1411
+ return `gea::packEnvironment(${cppEnvironmentStructName(functionId)}{${fields.join(', ')}})`;
1412
+ };
1413
+ const ensureBoxedSlotDeclared = (ctx, lines, slot) => {
1414
+ if (!slot.boxed)
1415
+ return;
1416
+ const placement = ctx.placements.get(slot.declaration);
1417
+ if (placement?.storage.kind !== 'local' || placement.storage.owner !== ctx.owner)
1418
+ return;
1419
+ if (ctx.declaredBindings.has(slot.declaration))
1420
+ return;
1421
+ const cell = bindingReference(ctx, slot.declaration, 'a self-referencing capture');
1422
+ declareCell(ctx, cell.name, cppBoxedType(slot.representation));
1423
+ lines.push(`${cell.name} = gea::makeRef<${cppTypeOf(slot.representation)}>();`);
1424
+ ctx.declaredBindings.add(slot.declaration);
1425
+ };
1426
+ /** A statically numeric scalar, including storage-narrowed Number carriers. */
1427
+ const isNumberScalarCarrier = (representation) => representation.kind === 'scalar' &&
1428
+ (representation.domain === 'number' ||
1429
+ representation.domain === 'int32' ||
1430
+ representation.domain === 'uint32' ||
1431
+ representation.domain === 'float64');
1432
+ /** An ordinary numeric Array whose elements `TypedArray.fromValues` can apply ToNumber to without a dynamic boundary. */
1433
+ const isNumericArrayCarrier = (representation) => representation.kind === 'array-object' && representation.ownership === 'shared-refcount' && isNumberScalarCarrier(representation.element);
1434
+ /** A typed-array source with the reference ownership needed to preserve and read its view identity. */
1435
+ const isSharedTypedArrayCarrier = (representation) => representation.kind === 'typed-array' && representation.ownership === 'shared-refcount';
1436
+ /**
1437
+ * `CallableObject{invoke, environment}` for one function-object allocation.
1438
+ *
1439
+ * `operation.captures` is never consulted: nothing publishes it, so it is not
1440
+ * a source of truth for what this closure reads from an enclosing frame.
1441
+ * `targets/cpp/captures.ts`'s whole-program `CaptureIndex` is. Each captured
1442
+ * cell is read through `bindingReference` in *this* (allocating) context,
1443
+ * which owns every declaration the closure captures by construction, so the
1444
+ * ordinary branch of `bindingReference` names it correctly with no special
1445
+ * casing. A captured receiver reads `cppReceiverName` the same way: this
1446
+ * body's own `gea_this` formal exists whenever it has a receiver at all,
1447
+ * whether real or itself captured (`emit-context.ts`'s `effectiveAbiOf`).
1448
+ *
1449
+ * A boxed slot's field copy needs no special casing here either, despite
1450
+ * carrying a `std::shared_ptr` rather than the declaration's own value type:
1451
+ * `bindingReference` already names the box's OWN storage for a boxed
1452
+ * declaration (never its dereferenced pointee -- that is
1453
+ * `emit-bindings.ts`'s `cellValueText`, used only where a value, not a
1454
+ * handle, is wanted), so copying `.name` verbatim into the new environment
1455
+ * struct copies the pointer, which is exactly the aliasing this closure's
1456
+ * capture is supposed to establish.
1457
+ */
1458
+ export const emitAllocateCallable = (ctx, lines, operation) => {
1459
+ const admission = ctx.captures.of(operation.functionId);
1460
+ if (admission.kind === 'refused') {
1461
+ throw createCppEmitBlockedError('capture:refused', `allocates a closure whose environment cannot be built: ${admission.reason}`);
1462
+ }
1463
+ const name = defineValue(ctx, operation.result);
1464
+ const carrier = operation.result.representation;
1465
+ // An OPTIONAL class method (`bodyString?(): string`) allocates through this
1466
+ // exact same operation -- the checker widened the MEMBER's type to admit
1467
+ // absence (a structural-compatibility escape hatch, `structural-parts.ts`'s
1468
+ // `memberOf`), never the allocation itself: `admission.kind === 'refused'`
1469
+ // just above is the only "cannot build a callable" outcome this operation
1470
+ // has, and it throws rather than leaving the result unassigned. So the
1471
+ // payload built below is unconditionally present; only the C++ TYPE gains a
1472
+ // `gea::Optional<...>` wrapper. `gea::Optional<T>`'s own constructors
1473
+ // (gea_runtime.h) take exactly one `T`, not `CallableObject`'s pointer pair,
1474
+ // so the payload has to be built at its own (unwrapped) type first and
1475
+ // handed to `Optional` as that single value -- `payloadCarrier`/`wrap` below
1476
+ // do exactly that, and reduce to the un-wrapped case unchanged when there is
1477
+ // no `optional` to begin with.
1478
+ const payloadCarrier = carrier.kind === 'optional' ? carrier.payload : carrier;
1479
+ const wrap = (payloadText) => (carrier.kind === 'optional' ? `${cppTypeOf(carrier)}{${payloadText}}` : payloadText);
1480
+ // Which body this callable runs, kept so a consumer that must RE-RUN it --
1481
+ // a reactive JSX slot -- can ask what that body reads. See `thunkValues`.
1482
+ //
1483
+ // A THUNK only: no arguments and no receiver. `emit-jsx.ts`'s
1484
+ // `reactiveThunkPlan` re-runs what it finds here as `thunk.call()`, and that
1485
+ // is the one call it can write -- it has the callee's value and nothing
1486
+ // else, no frame to rebuild and no receiver to pass. A component's render
1487
+ // member is allocated through this same operation (`plugins/gea/lower.ts`
1488
+ // binds it, then calls it with the instance and a props record), and
1489
+ // recording it would offer a re-run that cannot be spelled; it would also
1490
+ // read that body's `this.x` dependencies and subscribe them through the
1491
+ // CALLING frame's receiver, which is a different object. Both are silent
1492
+ // until the slot is one the emitter binds, which is why the filter belongs
1493
+ // here rather than at the one call site that noticed.
1494
+ // A two-entry function object holds THREE fields, not two: an invoke pointer,
1495
+ // a construct pointer and the environment (`gea::CallableConstructorObject`,
1496
+ // gea_runtime.h). The construct pointer is a second thunk over the same body,
1497
+ // rendered by `translation-unit.ts`'s `constructThunkOf` -- ECMA-262 10.2.2's
1498
+ // "create the object, then enter the body with it", which no `[[Call]]`
1499
+ // pointer can serve because it neither allocates nor returns the instance.
1500
+ // Brace-initializing this carrier with two values is what used to leave every
1501
+ // pre-`class` constructor function in three.js's renderer unclaimed.
1502
+ const pointers = payloadCarrier.kind === 'function-and-constructor'
1503
+ ? `&${cppThunkName(operation.functionId)}, &${cppConstructedThunkName(operation.functionId)}`
1504
+ : `&${cppThunkName(operation.functionId)}`;
1505
+ // Tagged by the SOURCE DECLARATION, not by this copy's thunk. Two
1506
+ // instantiations of one generic function are two thunks and one JavaScript
1507
+ // function object; the runtime's own `CallableDeclarationTag` comment says
1508
+ // "one program-wide address per emitted source declaration", and passing the
1509
+ // thunk made it one per copy. `translation-unit.ts` defines the tag object.
1510
+ //
1511
+ // And only when the identity can be SEEN. `identifyCallable` forces the
1512
+ // `FunctionObjectIdentity` allocation (and its property table) that the
1513
+ // runtime otherwise mints lazily; `ir/callable-identity-demand.ts` says
1514
+ // whether anything in the program ever asks this convention's callables for
1515
+ // their identity. When nothing does, the allocation stays the bare
1516
+ // thunk/environment pair and a closure in a hot loop costs its environment
1517
+ // and nothing else. A callable that is also a constructor keeps its identity
1518
+ // regardless: its `prototype` lives on that owner and `new F()` reads it.
1519
+ const identified = (payloadText) => payloadCarrier.kind === 'function-and-constructor' ||
1520
+ payloadCarrier.kind === 'dynamic' ||
1521
+ ctx.callableIdentityDemand.observes(payloadCarrier)
1522
+ ? `gea::identifyCallable<&${cppCallableDeclarationTagName(operation.functionId)}>(${payloadText})`
1523
+ : payloadText;
1524
+ // A function whose OWN structural type the `--dynamic-fallback` prototype
1525
+ // census marked (`prototypeMutatedConstructorTypes`, dynamic-fallback.ts)
1526
+ // publishes `dynamic` here in place of a native callable carrier -- because
1527
+ // `F.prototype = ...`/`F.prototype.n = ...` needs a real, mutable property
1528
+ // table (ECMA-262 10.2.5 MakeConstructor) that no native callable carrier
1529
+ // has. The box's OWN call ABI is gone once boxed, so it is recovered from
1530
+ // `ctx.abiOfCallable` (the same recovery `emit-union-properties.ts` already
1531
+ // relies on for the identical problem) and used to pick the matching
1532
+ // `Value::box`/`boxMethod`/`boxCallable` overload. `new F()` never uses the
1533
+ // native construct-thunk pointer for this carrier (`translation-unit.ts`'s
1534
+ // `constructThunkOf` refuses to build one for a `dynamic` instance type
1535
+ // anyway) -- `emitConstruct`'s own `dynamic` branch calls `Value::construct`
1536
+ // instead, which re-enters through the ordinary `[[Call]]` thunk -- so only
1537
+ // ONE pointer is ever needed here, never the constructor-family pair.
1538
+ if (payloadCarrier.kind === 'dynamic') {
1539
+ const abi = ctx.abiOfCallable(operation.functionId);
1540
+ if (!abi) {
1541
+ throw createCppEmitBlockedError('call-abi:dynamic', 'a callable boxed as "dynamic" under --dynamic-fallback needs its own call ABI, and this function publishes none');
1542
+ }
1543
+ const callableType = `gea::CallableObject<${cppAbiType(abi)}>`;
1544
+ const boxText = (payloadText) => {
1545
+ const callable = identified(payloadText);
1546
+ if (abi.receiver !== null)
1547
+ return `gea::Value::boxMethod<${abi.restFrom === null ? -1 : abi.restFrom + 1}>(${callable})`;
1548
+ if (abi.restFrom === null)
1549
+ return `gea::Value::box(gea::Value::Tag::Function, ${callable})`;
1550
+ return `gea::Value::boxCallable<${abi.restFrom}>(${callable})`;
1551
+ };
1552
+ if (admission.kind === 'none') {
1553
+ lines.push(`${name} = gea::host::installOrdinaryConstructorPrototype(${boxText(`${callableType}{&${cppThunkName(operation.functionId)}, nullptr}`)});`);
1554
+ return;
1555
+ }
1556
+ const dynamicEnvironment = packedEnvironmentText(ctx, lines, operation.functionId, admission);
1557
+ lines.push(`${name} = gea::host::installOrdinaryConstructorPrototype(${boxText(`${callableType}{&${cppThunkName(operation.functionId)}, ${dynamicEnvironment}}`)});`);
1558
+ return;
1559
+ }
1560
+ if (admission.kind === 'none') {
1561
+ // Same reasoning as a module-level function cell: a callable with no
1562
+ // environment is reached by name, and the carrier stays for whoever stores
1563
+ // one. The name itself is registered up front by `emitBody`'s walk of
1564
+ // `CallOperation.target` (`ir/call-dispatch.ts`), not by this allocation.
1565
+ lines.push(`${name} = ${wrap(identified(`${cppTypeOf(payloadCarrier)}{${pointers}, nullptr}`))};`);
1566
+ return;
1567
+ }
1568
+ const environment = packedEnvironmentText(ctx, lines, operation.functionId, admission);
1569
+ lines.push(`${name} = ${wrap(identified(`${cppTypeOf(payloadCarrier)}{${pointers}, ${environment}}`))};`);
1570
+ };
1571
+ /**
1572
+ * `new Uint8Array(...)`'s checker overload set (ECMA-262 23.2.5.1) has no
1573
+ * single physical frame: a `length: number` overload zero-fills, an
1574
+ * `ArrayLike<number>` overload copies-and-converts each element, and a
1575
+ * `buffer, byteOffset?, length?` overload aliases existing storage -- three
1576
+ * different parameter-0 shapes, not three spellings of one convention. That is
1577
+ * why `callee.construct` is `null` here, unconditionally, for every
1578
+ * typed-array constructor: `representation/host-abi.ts`'s `widestSubsumingAbi`
1579
+ * correctly refuses to join an unrelated shape into "the" ABI.
1580
+ *
1581
+ * This does not re-run overload resolution to work around that: it reads the
1582
+ * argument's own, already-resolved physical representation, which is the
1583
+ * checker's resolved-signature decision made visible through the plan
1584
+ * (`representation/plan.ts`) rather than re-derived from syntax. A `scalar
1585
+ * (number)` argument can only be the `length: number` overload's parameter --
1586
+ * no other construct signature has a bare-number parameter 0 -- and an
1587
+ * `array-object` argument can only be the `ArrayLike<number>` overload's.
1588
+ * Optional numeric lengths preserve absence until this intrinsic applies
1589
+ * ToIndex: both undefined and null allocate an empty array. Native buffer
1590
+ * views and numeric array copies use their own branches below; unsupported
1591
+ * carrier families are refused rather than treated as a numeric length.
1592
+ */
1593
+ const emitTypedArrayConstruct = (ctx, lines, operation, result) => {
1594
+ if (result.ownership !== 'shared-refcount') {
1595
+ throw createCppEmitBlockedError(`physical-cpp-type:${representationKey(result)}`, `a typed array allocation carries ownership "${result.ownership}", but this emitter only spells std::make_shared for "shared-refcount"`);
1596
+ }
1597
+ const target = typedArrayTargetSpelling(result);
1598
+ // ECMA-262 23.2.5.1's THIRD overload, `(buffer, byteOffset?, length?)`,
1599
+ // which ALIASES the block rather than copying it. Recognized by the
1600
+ // argument's own already-resolved carrier, exactly as the two forms below
1601
+ // are, and rendered in `emit-buffers.ts` with the rest of the block-shaped
1602
+ // family. Checked before the arity guard below because it is the one
1603
+ // overload that takes more than one argument.
1604
+ const first = operation.arguments[0];
1605
+ if (first?.representation.kind === 'array-buffer' || first?.representation.kind === 'shared-array-buffer') {
1606
+ emitTypedArrayBufferConstruct(ctx, lines, operation, target);
1607
+ return;
1608
+ }
1609
+ const name = defineValue(ctx, operation.result);
1610
+ // The zero-argument form IS "no first operand", so reading the operand first
1611
+ // and branching on its absence states the arity check once, in the terms the
1612
+ // rest of this function already uses, instead of asserting a length and then
1613
+ // indexing on the strength of that assertion.
1614
+ const argument = operation.arguments[0];
1615
+ if (!argument) {
1616
+ lines.push(`${name} = gea::makeRef<${target}>();`);
1617
+ return;
1618
+ }
1619
+ if (operation.arguments.length > 1) {
1620
+ throw createCppEmitBlockedError('call-abi:construct:typed-array', `constructs a typed array from ${operation.arguments.length} arguments; only the zero-, length-, and array-like-argument ` +
1621
+ 'forms of ECMA-262 23.2.5.1 are implemented (see emitTypedArrayConstruct)');
1622
+ }
1623
+ const carrier = argument.representation;
1624
+ if (isNumberScalarCarrier(carrier) ||
1625
+ (carrier.kind === 'optional' && isNumberScalarCarrier(carrier.payload)) ||
1626
+ carrier.kind === 'undefined' ||
1627
+ carrier.kind === 'null') {
1628
+ const source = operandText(ctx, argument);
1629
+ const length = carrier.kind === 'optional'
1630
+ ? `(${source}.has_value() ? *${source} : 0.0)`
1631
+ : carrier.kind === 'undefined' || carrier.kind === 'null'
1632
+ ? '0.0'
1633
+ : source;
1634
+ // Normalize the numeric argument before the runtime's integer/range guard.
1635
+ // ToIndex truncates fractions and maps NaN/absence to zero.
1636
+ lines.push(`${name} = gea::makeRef<${target}>(gea::detail::typedArrayLengthIndex(gea::detail::toIntegerOrInfinity(${length})));`);
1637
+ return;
1638
+ }
1639
+ // A BOXED argument. The overload this dispatch reads off a carrier is read
1640
+ // off the BOX'S TAG instead, and the tag can pick exactly one: `Tag::Number`
1641
+ // is the `length` overload. `unboxedLoadText` renders that as the
1642
+ // tag-and-payload-checked read, so a box holding anything else aborts by
1643
+ // name at the construction rather than being reinterpreted as a length --
1644
+ // the same discipline every other boxed read in this backend keeps, and the
1645
+ // reason `preflight/invocation-arguments.ts` can state `scalar(number)` as
1646
+ // this argument's target without over-claiming.
1647
+ //
1648
+ // three's `new Int32Array( n )` (`WebGLUniforms.allocTexUnits`) and
1649
+ // `new Float32Array( flatSize )` (`WebGLClipping.projectPlanes`) are both a
1650
+ // length through a JS parameter the source never typed.
1651
+ if (carrier.kind === 'dynamic') {
1652
+ const length = unboxedLoadText({ kind: 'scalar', domain: 'number' }, operandText(ctx, argument));
1653
+ if (length !== null) {
1654
+ lines.push(`${name} = gea::makeRef<${target}>(gea::detail::typedArrayLengthIndex(gea::detail::toIntegerOrInfinity(${length})));`);
1655
+ return;
1656
+ }
1657
+ }
1658
+ if (isNumericArrayCarrier(carrier)) {
1659
+ lines.push(`${name} = gea::makeRef<${target}>(${target}::fromValues(${operandText(ctx, argument)}));`);
1660
+ return;
1661
+ }
1662
+ // ECMA-262 23.2.5.1's copy-from-another-typed-array overload
1663
+ // (`InitializeTypedArrayFromTypedArray`): a fresh block the same LENGTH as
1664
+ // the source, each element converted through the target's own write rule --
1665
+ // which is what makes `new Uint8ClampedArray(new Float32Array([1.5]))`
1666
+ // clamp-and-round rather than truncate. `setFrom` performs exactly that
1667
+ // conversion, so the copy is `fromLength` plus one `set` at offset zero.
1668
+ if (isSharedTypedArrayCarrier(carrier)) {
1669
+ const source = operandText(ctx, argument);
1670
+ lines.push(`${name} = gea::makeRef<${target}>(static_cast<std::size_t>(${source}->length()));`);
1671
+ lines.push(`${name}->setFrom(*${source}, 0.0);`);
1672
+ return;
1673
+ }
1674
+ // A parameter declared `number[] | TypedArray` retains both overloads as a
1675
+ // native sum. Each alternative is still one of the two copying forms above;
1676
+ // dispatching on the sum's existing tag preserves that decision without
1677
+ // boxing the source or collapsing typed-array element domains.
1678
+ if (carrier.kind === 'tagged-union' &&
1679
+ carrier.arms.length > 0 &&
1680
+ carrier.arms.every((arm) => isNumericArrayCarrier(arm.value) || isSharedTypedArrayCarrier(arm.value))) {
1681
+ const branches = carrier.arms.map((arm, index) => {
1682
+ const selected = `gea_typed_source.get<${index}>()`;
1683
+ const body = isNumericArrayCarrier(arm.value)
1684
+ ? `return gea::makeRef<${target}>(${target}::fromValues(${selected}));`
1685
+ : `{ const auto& gea_typed_input = ${selected}; auto gea_typed_result = gea::makeRef<${target}>(gea_typed_input->size()); gea_typed_result->setFrom(*gea_typed_input, 0.0); return gea_typed_result; }`;
1686
+ return index === carrier.arms.length - 1 ? body : `if (gea_typed_source.is<${index}>()) { ${body} }`;
1687
+ });
1688
+ lines.push(`${name} = ([&]() -> ${cppTypeOf(result)} { const auto& gea_typed_source = ${operandText(ctx, argument)}; ${branches.join(' ')} }());`);
1689
+ return;
1690
+ }
1691
+ throw createCppEmitBlockedError('call-abi:construct:typed-array', `constructs a typed array from a "${carrier.kind}" argument; supported carriers are numeric lengths (including absence), ` +
1692
+ 'native buffer views, numeric arrays, typed arrays, and native unions of the two array-copy forms');
1693
+ };
1694
+ /**
1695
+ * `new Array(...)` -- the one native constructor whose result is an ordinary
1696
+ * `array-object` rather than a handle to the host's own object.
1697
+ *
1698
+ * It is here, beside `emitTypedArrayConstruct`, and for the same structural
1699
+ * reason: `ArrayConstructor`'s checker overload set is `new (arrayLength:
1700
+ * number)` and `new <T>(...items: T[])`, two genuinely different parameter-0
1701
+ * shapes with no single physical frame to join, so `derive.ts` leaves
1702
+ * `.construct` null and the recipe has to read the construct operation's own,
1703
+ * already-resolved argument representation instead.
1704
+ *
1705
+ * The length form is exactly `ArrayObject::setLength`, which is ECMA-262
1706
+ * 10.4.2.1's own rule -- `resize` grows with value-initialized `Slot`s, and a
1707
+ * `Slot` value-initializes `present` to false, i.e. a HOLE. `new Array(64)` is
1708
+ * a length-64 array of holes in the specification and a length-64 array of
1709
+ * holes here; nothing is materialized into `undefined` behind the program's
1710
+ * back, and a read of one still aborts by name in `elementAt` rather than
1711
+ * handing back a zero.
1712
+ *
1713
+ * The `...items` form is refused: each item owes a conversion to the array's
1714
+ * element carrier, which is lowering's to state (it is what an array literal
1715
+ * already gets), not something to improvise from the argument list here. So is
1716
+ * a single non-numeric argument -- `new Array("a")` is a one-element array,
1717
+ * `new Array(3)` is three holes, and picking between them is the argument's
1718
+ * type talking, so an argument whose carrier is neither is a refusal rather
1719
+ * than a guess.
1720
+ */
1721
+ const emitArrayConstruct = (ctx, lines, operation, result) => {
1722
+ if (result.ownership !== 'shared-refcount') {
1723
+ throw createCppEmitBlockedError(`physical-cpp-type:${representationKey(result)}`, `an Array allocation carries ownership "${result.ownership}", but this emitter only spells std::make_shared for "shared-refcount"`);
1724
+ }
1725
+ const target = `gea::ArrayObject<${cppTypeOf(result.element)}>`;
1726
+ const name = defineValue(ctx, operation.result);
1727
+ const argument = operation.arguments[0];
1728
+ if (!argument) {
1729
+ lines.push(`${name} = gea::makeRef<${target}>();`);
1730
+ return;
1731
+ }
1732
+ if (operation.arguments.length > 1) {
1733
+ throw createCppEmitBlockedError('call-abi:construct:array', `constructs an Array from ${operation.arguments.length} arguments; only the zero- and length-argument forms of ` +
1734
+ 'ECMA-262 23.1.1.1 are implemented, because the element form owes each item a conversion to the array element ' +
1735
+ 'carrier that only lowering states (see emitArrayConstruct)');
1736
+ }
1737
+ const carrier = argument.representation;
1738
+ if (carrier.kind !== 'scalar' || carrier.domain !== 'number') {
1739
+ throw createCppEmitBlockedError('call-abi:construct:array', `constructs an Array from a "${carrier.kind}" argument; ECMA-262 23.1.1.1 reads a single argument as a LENGTH only ` +
1740
+ 'when it is a number and as a sole ELEMENT otherwise, and the element form is not implemented');
1741
+ }
1742
+ lines.push(`${name} = gea::makeRef<${target}>();`);
1743
+ lines.push(`${name}->setLength(${operandText(ctx, argument)});`);
1744
+ };
1745
+ /**
1746
+ * `new Map()` / `new Set()` / `new WeakMap()` / `new WeakSet()`, and
1747
+ * `new Set(array)`.
1748
+ *
1749
+ * The third member of the `emitTypedArrayConstruct`/`emitArrayConstruct`
1750
+ * family above, here for exactly the same structural reason: these four
1751
+ * constructors' checker overload sets have no single physical frame. `new
1752
+ * Map()`, `new Map(entries: readonly (readonly [K, V])[] | null)` and `new
1753
+ * Map(iterable: Iterable<readonly [K, V]>)` are three different parameter-0
1754
+ * shapes, so `representation/host-abi.ts`'s `widestSubsumingAbi` correctly
1755
+ * refuses to join them and `derive.ts` leaves `.construct` null. This reads
1756
+ * the construction's own already-resolved result carrier and argument
1757
+ * representation instead.
1758
+ *
1759
+ * Only the zero-argument form, plus `new Set(T[])`, is rendered. Every other
1760
+ * seeding form refuses by name:
1761
+ *
1762
+ * - a Map/WeakMap seeded from entries needs each element to be a `[K, V]`
1763
+ * PAIR, and this compiler carries a tuple as an ordinary record of "0"/"1"
1764
+ * fields (`derive.ts`'s `deriveTuple`). Reading two struct members back out
1765
+ * as a key and a value is a real lowering, not a spelling, and guessing at
1766
+ * it would be the kind of improvisation `emitArrayConstruct` already
1767
+ * declines for `new Array(...items)`;
1768
+ * - a Set seeded from any iterable that is not an Array needs the dynamic
1769
+ * `@@iterator` protocol this backend does not lower at all
1770
+ * (`emit-iterator.ts`);
1771
+ * - `new WeakSet(array)` is refused with the others rather than folded in with
1772
+ * `new Set(array)`: it is genuinely rare, and admitting it would mean
1773
+ * claiming the weak-key precondition holds for every element of an array
1774
+ * whose own element carrier this function would have to re-check.
1775
+ */
1776
+ /**
1777
+ * The four ambient constructor PROTOCOL NAMES this renderer is written for --
1778
+ * named here, once, rather than being re-typed as a fifth copy by anything
1779
+ * that needs to know which protocols `emitKeyedCollectionConstruct` answers
1780
+ * for. The dispatch above is structural (`result.kind === 'keyed-collection'`),
1781
+ * never by this name, so this table is not read by the renderer itself: it is
1782
+ * the renderer's own restatement of the four names its comment already
1783
+ * documents, exported for `host/native-protocols.ts` to derive a
1784
+ * native-boundary claim from, since no host-member-table row names any of
1785
+ * them the way most other protocols are named.
1786
+ */
1787
+ export const cppKeyedCollectionConstructorProtocols = [
1788
+ 'MapConstructor',
1789
+ 'SetConstructor',
1790
+ 'WeakMapConstructor',
1791
+ 'WeakSetConstructor'
1792
+ ];
1793
+ const emitKeyedCollectionConstruct = (ctx, lines, operation, result) => {
1794
+ if (result.ownership !== 'shared-refcount') {
1795
+ throw createCppEmitBlockedError(`physical-cpp-type:${representationKey(result)}`, `a ${result.family} allocation carries ownership "${result.ownership}", but this emitter only spells std::make_shared for "shared-refcount"`);
1796
+ }
1797
+ // The pointee, not the carrier: `cppTypeOf` would wrap it in the
1798
+ // `shared_ptr` this line is itself constructing.
1799
+ const target = cppTypeOf({ ...result, ownership: 'owned' });
1800
+ const name = defineValue(ctx, operation.result);
1801
+ const argument = operation.arguments[0];
1802
+ if (!argument) {
1803
+ lines.push(`${name} = gea::makeRef<${target}>();`);
1804
+ return;
1805
+ }
1806
+ if (operation.arguments.length > 1) {
1807
+ throw createCppEmitBlockedError('call-abi:construct:keyed-collection', `constructs a ${result.family} from ${operation.arguments.length} arguments; ECMA-262 gives these constructors one ` +
1808
+ 'optional iterable parameter and nothing else');
1809
+ }
1810
+ const carrier = argument.representation;
1811
+ if (result.family === 'set' && carrier.kind === 'array-object' && representationKey(carrier.element) === representationKey(result.key)) {
1812
+ return void lines.push(`${name} = gea::setFromArray<${cppTypeOf(result.key)}>(${operandText(ctx, argument)});`);
1813
+ }
1814
+ // A STRING is the second iterable this backend proves statically, and it is
1815
+ // not a special case of the Array one: ECMA-262 22.1.5.1 iterates a string
1816
+ // by CODE POINT, so `new Set('ab')` holds two one-character strings and
1817
+ // `new Set('\u{1F600}')` holds one two-unit string, never two halves of a
1818
+ // surrogate pair. The runtime walks it with the same `forEachCodePoint`
1819
+ // `[...str]` uses, so the seeded Set and the spread can never disagree.
1820
+ // Only a `set<string>` -- a `Set<T>` for any other T seeded from a string is
1821
+ // not a program this checker admits, and inventing an element conversion
1822
+ // here would be a conversion nothing proved.
1823
+ if (result.family === 'set' && carrier.kind === 'string' && result.key.kind === 'string') {
1824
+ return void lines.push(`${name} = gea::setFromString(${operandText(ctx, argument)});`);
1825
+ }
1826
+ throw createCppEmitBlockedError('call-abi:construct:keyed-collection', `constructs a ${result.family}<${representationKey(result.key)}> from a "${representationKey(carrier)}" argument; only the zero-argument form is implemented for every ` +
1827
+ "family, plus `new Set(T[])` where the array's element carrier is exactly the set's own -- a Map seeded from " +
1828
+ 'entries needs a [K, V] pair lowering (a tuple is carried here as a record of "0"/"1" fields), and any other ' +
1829
+ 'iterable needs the dynamic @@iterator protocol this backend does not lower');
1830
+ };
1831
+ /**
1832
+ * `new RegExp(pattern)`, `new RegExp(pattern, flags)` and the two
1833
+ * pattern-copying forms (ECMA-262 22.2.4.1).
1834
+ *
1835
+ * The fourth case of the same `native-handle` exception `emitTypedArrayConstruct`,
1836
+ * `emitArrayConstruct` and `emitKeyedCollectionConstruct` are, for the same
1837
+ * reason: `RegExpConstructor`'s overload set has three different parameter-0
1838
+ * shapes (`string | RegExp`, `string`, `string | RegExp` again with a second
1839
+ * parameter), so `derive.ts` correctly leaves `.construct` null and there is
1840
+ * no joined convention to invoke through. The construction renders off its own
1841
+ * ARGUMENT carriers instead, which is exactly what the specification switches
1842
+ * on: 22.2.4.1 step 3 asks whether the pattern is already a RegExp before it
1843
+ * asks anything else.
1844
+ *
1845
+ * `constructPatternOrThrow` (v1: the validation half of `regex.cpp`'s
1846
+ * construction path) is the entry point rather than `gea::makeRef<Pattern>`
1847
+ * so that 22.2.3.2 `RegExpInitialize`'s flag and source validation runs and an
1848
+ * unknown or repeated flag throws where the language says it throws.
1849
+ */
1850
+ const emitRegExpConstruct = (ctx, lines, operation) => {
1851
+ const args = operation.arguments;
1852
+ if (args.length > 2) {
1853
+ throw createCppEmitBlockedError('call-abi:construct:regexp', `constructs a RegExp from ${args.length} argument(s); ECMA-262 22.2.4.1 takes a pattern and an optional flags string`);
1854
+ }
1855
+ if (args.length === 0) {
1856
+ lines.push(`${defineValue(ctx, operation.result)} = ${cppConstructPatternEntry}(std::string());`);
1857
+ return;
1858
+ }
1859
+ const spellingOf = (argument, position) => {
1860
+ const carrier = argument.representation;
1861
+ if (carrier.kind === 'dynamic')
1862
+ return operandText(ctx, argument);
1863
+ if (carrier.kind === 'string')
1864
+ return operandText(ctx, argument);
1865
+ if (position === 0 && regexpRoleOf(carrier) === 'pattern')
1866
+ return operandText(ctx, argument);
1867
+ throw createCppEmitBlockedError(`conversion:${representationKey(carrier)}->string`, `"new RegExp" argument ${position} carries "${representationKey(carrier)}"; this backend spells it for a string` +
1868
+ (position === 0 ? ` or an existing ${cppRegExpNativeTypes.pattern}` : '') +
1869
+ ', and ECMA-262 22.2.4.1 ToStrings anything else -- ToString of an arbitrary value is what this backend has no box for');
1870
+ };
1871
+ const patternArgument = args[0];
1872
+ if (!patternArgument)
1873
+ throw createCppEmitBlockedError('call-abi:construct:regexp', 'a RegExp construction with an argument has no pattern operand');
1874
+ const flag = args[1];
1875
+ // Steps 5-7 over an ordinary OBJECT pattern. Step 5 is already `false` here
1876
+ // -- a value carrying `[[RegExpMatcher]]` is the `Pattern` carrier
1877
+ // `spellingOf` hands straight through -- so what remains is `patternIsRegExp`
1878
+ // choosing between the object's own `source`/`flags` and a ToString of it.
1879
+ const fromObject = regExpConstructionFromObject(ctx, patternArgument, flag ?? null);
1880
+ if (fromObject !== null) {
1881
+ lines.push(`${defineValue(ctx, operation.result)} = ${fromObject};`);
1882
+ return;
1883
+ }
1884
+ const pattern = spellingOf(patternArgument, 0);
1885
+ const rendered = flag ? spellingOf(flag, 1) : null;
1886
+ const name = defineValue(ctx, operation.result);
1887
+ if (rendered === null) {
1888
+ lines.push(`${name} = ${cppConstructPatternEntry}(${pattern});`);
1889
+ return;
1890
+ }
1891
+ lines.push(`${name} = ${cppConstructPatternEntry}(${pattern}, ${rendered});`);
1892
+ };
1893
+ /** Reconcile one [[Construct]] branch's declared result with the carrier selected for the `new` expression. */
1894
+ const constructResultText = (ctx, source, target, text) => {
1895
+ if (derivesFrom(ctx, source, target))
1896
+ return text;
1897
+ return alignedValueText(ctx, 'emit-callable.ts:2038', source, target, text);
1898
+ };
1899
+ /** Evaluate a construction exactly once before applying any result conversion that may inspect its source more than once. */
1900
+ const convertedConstructInvocationText = (ctx, source, target, invocation) => {
1901
+ const converted = constructResultText(ctx, source, target, callResultName);
1902
+ if (converted === null)
1903
+ return null;
1904
+ if (converted === callResultName)
1905
+ return invocation;
1906
+ return `[&]() -> ${cppTypeOf(target)} { auto ${callResultName} = ${invocation}; return ${converted}; }()`;
1907
+ };
1908
+ /** The actual [[Construct]] convention held by one non-sum carrier. */
1909
+ const constructConventionOf = (representation) => {
1910
+ if (representation.kind === 'function-and-constructor')
1911
+ return representation.construct;
1912
+ if (representation.kind === 'constructor-family' || representation.kind === 'constructor-value-dispatch')
1913
+ return representation.abi;
1914
+ return null;
1915
+ };
1916
+ /**
1917
+ * `new (condition ? A : B)(...)` where every live alternative is a real
1918
+ * constructor carrier. The sum keeps each alternative's frame intact, so the
1919
+ * discriminant selects both the construct pointer and the result conversion.
1920
+ */
1921
+ const emitTaggedUnionConstruct = (ctx, lines, operation) => {
1922
+ const callee = operation.callee.representation;
1923
+ if (callee.kind !== 'tagged-union')
1924
+ return false;
1925
+ if (callee.arms.length === 0)
1926
+ throw createCppEmitBlockedError('call-abi:tagged-union-construct', 'a constructor union has no live alternatives');
1927
+ const branches = callee.arms.map((arm, index) => {
1928
+ const abi = constructConventionOf(arm.value);
1929
+ if (abi === null || abi.receiver !== null || abi.restFrom !== null) {
1930
+ throw createCppEmitBlockedError('call-abi:tagged-union-construct', `constructor-union arm ${index} carries "${representationKey(arm.value)}", not a fixed receiver-free [[Construct]] convention`);
1931
+ }
1932
+ const args = receivableArguments(abi, operation.arguments).map((argument, position) => argumentText(ctx, abi, position, argument, 'union construct'));
1933
+ const selected = `gea_union_constructor.get<${index}>()`;
1934
+ const invocation = `${selected}.construct(${paddedArguments(abi, args, 'union construct').join(', ')})`;
1935
+ const converted = convertedConstructInvocationText(ctx, abi.result, operation.result.representation, invocation);
1936
+ if (converted === null) {
1937
+ throw createCppEmitBlockedError(`conversion:${representationKey(abi.result)}->${representationKey(operation.result.representation)}`, `constructor-union arm ${index} returns "${representationKey(abi.result)}", which cannot fill "${representationKey(operation.result.representation)}"`);
1938
+ }
1939
+ const body = `return ${converted};`;
1940
+ return index === callee.arms.length - 1 ? body : `if (gea_union_constructor.is<${index}>()) { ${body} }`;
1941
+ });
1942
+ const target = cppTypeOf(operation.result.representation);
1943
+ const invocation = `[&]() -> ${target} { const auto& gea_union_constructor = ${operandText(ctx, operation.callee)}; ${branches.join(' ')} }()`;
1944
+ lines.push(`${defineValue(ctx, operation.result)} = ${invocation};`);
1945
+ return true;
1946
+ };
1947
+ /** Invoke the call entry already selected by the IR's constructor-entry census. */
1948
+ const emitExplicitObjectReturnConstruct = (ctx, lines, operation) => {
1949
+ const entry = operation.entry;
1950
+ if (entry?.kind !== 'explicit-object-return')
1951
+ return false;
1952
+ const abi = entry.abi;
1953
+ const args = receivableArguments(abi, operation.arguments).map((argument, position) => argumentText(ctx, abi, position, argument, 'construct'));
1954
+ const invocation = `${operandText(ctx, operation.callee)}.call(${paddedArguments(abi, args, 'construct').join(', ')})`;
1955
+ const converted = convertedConstructInvocationText(ctx, abi.result, operation.result.representation, invocation);
1956
+ if (converted === null) {
1957
+ throw createCppEmitBlockedError(`conversion:${representationKey(abi.result)}->${representationKey(operation.result.representation)}`, `an ordinary function's explicit object result "${representationKey(abi.result)}" cannot fill "${representationKey(operation.result.representation)}"`);
1958
+ }
1959
+ lines.push(`${defineValue(ctx, operation.result)} = ${converted};`);
1960
+ return true;
1961
+ };
1962
+ /**
1963
+ * `new C(...)`: the construction goes through the constructor carrier's own
1964
+ * construct pointer, exactly as a call goes through a callable's invoke
1965
+ * pointer. `newTarget` is not consulted -- a derived construction needs the
1966
+ * new-target to reach the field initializers of the class that was actually
1967
+ * newed, and nothing here transports it -- so a construction whose new-target
1968
+ * is not its own callee is refused rather than silently treated as ordinary.
1969
+ */
1970
+ export const emitConstruct = (ctx, lines, operation) => {
1971
+ const callee = operation.callee.representation;
1972
+ if (operation.newTarget.value !== operation.callee.value) {
1973
+ throw createCppEmitBlockedError('call-abi:construct', 'a construction whose new-target differs from its callee needs new-target transport, which is not installed');
1974
+ }
1975
+ if (emitNullishInvocation(ctx, lines, operation))
1976
+ return;
1977
+ if (emitTaggedUnionConstruct(ctx, lines, operation))
1978
+ return;
1979
+ if (emitExplicitObjectReturnConstruct(ctx, lines, operation))
1980
+ return;
1981
+ // `new TextEncoder()` / `new TextDecoder(...)`, dispatched on the RESULT and
1982
+ // therefore ahead of every callee-shaped branch below: their class objects
1983
+ // are declared in `lib.dom.d.ts` as anonymous type literals, so the callee
1984
+ // never derives a `native-handle` the way `Uint8Array`'s named
1985
+ // `Uint8ArrayConstructor` does -- it derives a constructor carrier over a
1986
+ // structural body, and `projection/bindings.ts` gives the NAME `host-class`
1987
+ // storage so no cell is emitted for it. See `emitTextCodecConstruct`.
1988
+ if (emitTextCodecConstruct(ctx, lines, operation))
1989
+ return;
1990
+ if (callee.kind === 'native-handle') {
1991
+ // `Uint8Array`/`Int32Array`/... are `native-handle`s whose checker
1992
+ // overload set genuinely has no single physical frame (see
1993
+ // `emitTypedArrayConstruct`'s own comment), so `callee.construct` is
1994
+ // correctly `null` for them -- this has to come before the general
1995
+ // `!callee.construct` refusal below, which is right for every OTHER
1996
+ // native-handle constructor (one unjoinable overload set there really
1997
+ // does mean "no convention"), just not this one.
1998
+ const result = operation.result.representation;
1999
+ if (result.kind === 'typed-array') {
2000
+ emitTypedArrayConstruct(ctx, lines, operation, result);
2001
+ return;
2002
+ }
2003
+ // `ArrayBuffer` and `DataView` -- the same exception for the same
2004
+ // unjoinable-overload-set reason, rendered in `emit-buffers.ts` with the
2005
+ // rest of the binary family.
2006
+ if (result.kind === 'array-buffer') {
2007
+ emitArrayBufferConstruct(ctx, lines, operation, result);
2008
+ return;
2009
+ }
2010
+ if (result.kind === 'shared-array-buffer') {
2011
+ emitSharedArrayBufferConstruct(ctx, lines, operation, result);
2012
+ return;
2013
+ }
2014
+ if (result.kind === 'data-view') {
2015
+ emitDataViewConstruct(ctx, lines, operation, result);
2016
+ return;
2017
+ }
2018
+ // `Array` is the same shape of exception, and for the same reason -- see
2019
+ // `emitArrayConstruct`. Its result is an ordinary array-object, not a
2020
+ // handle to the host's own object, which is what distinguishes it here.
2021
+ if (callee.protocol === 'FunctionConstructor') {
2022
+ if (!ctx.deriver.dynamicFallback || result.kind !== 'dynamic')
2023
+ throw createCppEmitBlockedError('call-abi:function-constructor', 'Function requires --dynamic-fallback and a dynamic callable result');
2024
+ const args = functionConstructorArgumentTexts(ctx, operation.arguments, 'construct');
2025
+ lines.push(`${defineValue(ctx, operation.result)} = gea::Eval::constructFunction({${args.join(', ')}});`);
2026
+ return;
2027
+ }
2028
+ if (callee.protocol === 'ProxyConstructor') {
2029
+ if (!ctx.deriver.dynamicFallback || result.kind !== 'dynamic')
2030
+ throw createCppEmitBlockedError('call-abi:proxy-construct', 'Proxy requires --dynamic-fallback and a dynamic result carrier');
2031
+ if (operation.arguments.length !== 2)
2032
+ throw createCppEmitBlockedError('call-abi:proxy-construct', 'Proxy requires target and handler');
2033
+ const args = operation.arguments.map((argument) => boxedValueText(ctx, argument, 'Proxy construction'));
2034
+ lines.push(`${defineValue(ctx, operation.result)} = gea::Value::proxy(${args.join(', ')});`);
2035
+ return;
2036
+ }
2037
+ if (result.kind === 'array-object' && callee.protocol === 'ArrayConstructor') {
2038
+ emitArrayConstruct(ctx, lines, operation, result);
2039
+ return;
2040
+ }
2041
+ // `Map`/`Set`/`WeakMap`/`WeakSet` -- the third case of the same exception,
2042
+ // for the same unjoinable-overload-set reason. See
2043
+ // `emitKeyedCollectionConstruct`.
2044
+ if (result.kind === 'keyed-collection') {
2045
+ emitKeyedCollectionConstruct(ctx, lines, operation, result);
2046
+ return;
2047
+ }
2048
+ // `Date` -- the fourth case, and the same unjoinable overload set again:
2049
+ // `new Date()`, `new Date(value)` and `new Date(year, monthIndex, ...)`
2050
+ // are three different parameter-0 shapes. See `emitDateConstruct`
2051
+ // (emit-prototype-date.ts), which owns every Date spelling this backend has.
2052
+ if (isDateCarrier(result) && result.kind === 'native-record-ref') {
2053
+ emitDateConstruct(ctx, lines, operation, result);
2054
+ return;
2055
+ }
2056
+ // `RegExp` -- the fourth case of the same exception, for the same
2057
+ // unjoinable-overload-set reason. See `emitRegExpConstruct`.
2058
+ if (regexpRoleOf(result) === 'pattern') {
2059
+ emitRegExpConstruct(ctx, lines, operation);
2060
+ return;
2061
+ }
2062
+ if (!callee.construct) {
2063
+ throw createCppEmitBlockedError(`host-invocation:${callee.native ?? callee.protocol}`, `a "${callee.protocol}" host handle carries no [[Construct]] convention this program's checker derived for it`);
2064
+ }
2065
+ const invocation = nativeHandleInvocationText(ctx, callee, callee.construct, operation.arguments, 'construct', result);
2066
+ const name = defineValue(ctx, operation.result);
2067
+ lines.push(`${name} = ${invocation};`);
2068
+ return;
2069
+ }
2070
+ // A plain JS constructor function whose `.prototype` the program itself
2071
+ // mutates (`prototypeMutatedConstructorTypes`, dynamic-fallback.ts) is boxed
2072
+ // to `dynamic`, and `translation-unit.ts`'s `constructThunkOf` refuses to
2073
+ // build a native construct thunk for it (its instance carrier is `dynamic`,
2074
+ // not `record`/`record-with-index`/`native-record-ref`) -- so `new F()`
2075
+ // cannot go through the constructor-family path below at all. `Value::construct`
2076
+ // (gea_runtime.h) is the ECMA-262 10.2.2 OrdinaryCreateFromConstructor
2077
+ // equivalent instead: it makes a fresh object whose [[Prototype]] is
2078
+ // whatever `F.prototype` CURRENTLY holds, re-enters through the ordinary
2079
+ // `[[Call]]` thunk with that object as `this`, and returns the object
2080
+ // unless the body itself returned one.
2081
+ if (callee.kind === 'dynamic') {
2082
+ const args = operation.arguments.map((argument) => boxedValueText(ctx, argument, 'dynamic construction argument'));
2083
+ const name = defineValue(ctx, operation.result);
2084
+ lines.push(`${name} = ${operandText(ctx, operation.callee)}.construct({${args.join(', ')}});`);
2085
+ return;
2086
+ }
2087
+ if (callee.kind !== 'constructor-family' && callee.kind !== 'constructor-value-dispatch' && callee.kind !== 'function-and-constructor') {
2088
+ throw createCppEmitBlockedError(`call-abi:no-construct-path:${callee.kind}`, `a callee carried as "${callee.kind}" has no construct path; this emitter constructs only through a constructor carrier`);
2089
+ }
2090
+ // The construct convention, which is the callee's own and not its call one:
2091
+ // `function-and-constructor` states both, and padding a construction against
2092
+ // the call frame would count the wrong parameters.
2093
+ const abi = callee.kind === 'function-and-constructor' ? callee.construct : callee.abi;
2094
+ // Reconciled against the declared parameter slot exactly as `emitCall`'s
2095
+ // generic path reconciles a call's arguments (`argumentText`, above) --
2096
+ // this used raw `operandText` before, which left a dynamic-sourced
2097
+ // argument (e.g. a caught `error` passed to `new SomeClass(error)`) never
2098
+ // converted at all, an unconditional over-claim the moment anything
2099
+ // upstream started asking whether that conversion was even installed. See
2100
+ // `preflight/invocation-arguments.ts`'s `conversion-role:invocation:construct:argument`.
2101
+ const args = receivableArguments(abi, operation.arguments).map((argument, position) => argumentText(ctx, abi, position, argument, 'construct'));
2102
+ // Devirtualized only where the program constructs REPEATEDLY, which is the
2103
+ // distinction an earlier attempt at this lacked: naming the construct
2104
+ // function lets clang inline the whole construction -- `gea::makeRef`, its
2105
+ // pool refill, its `try`/`catch` -- into whatever body constructs, and that
2106
+ // is worth 46.1ms to 41.9ms in `binary_trees`, which constructs a million
2107
+ // times inside a recursive body, and 38.1ms to 49.0ms the wrong way in
2108
+ // `method_calls`, which constructs once before a hot loop whose own callee
2109
+ // then stops being inlined. `buildRepeatedConstructorIndex` answers which,
2110
+ // and its doc carries the rest of the measurements -- including `noinline`
2111
+ // on the construct function, the obvious way to have the direct call without
2112
+ // the inlining, which is worse than either (41.9ms to 44.5ms).
2113
+ const cell = ctx.bindingReadDeclarations.get(operation.callee.value);
2114
+ const repeated = cell === undefined ? undefined : ctx.repeatedConstructors.get(cell);
2115
+ const invocation = repeated === undefined
2116
+ ? `${operandText(ctx, operation.callee)}.construct(${paddedArguments(abi, args, 'construct').join(', ')})`
2117
+ : `${cppConstructName(repeated)}(${[
2118
+ `static_cast<gea::NativeClassMethodState*>(${operandText(ctx, operation.callee)}.environment)`,
2119
+ ...paddedArguments(abi, args, 'construct')
2120
+ ].join(', ')})`;
2121
+ const name = defineValue(ctx, operation.result);
2122
+ lines.push(`${name} = ${invocation};`);
2123
+ };
2124
+ /**
2125
+ * Class evaluation allocates a native prototype owner, even when its methods
2126
+ * capture nothing. Constructor copies share it, while another evaluation of
2127
+ * the same declaration gets a new owner. The evaluated superclass supplies
2128
+ * the parent owner; looking it up by declaration would conflate factories.
2129
+ *
2130
+ * This state carries method identities only. Constructor body/field capture
2131
+ * transport remains subject to the existing fail-closed admission below.
2132
+ */
2133
+ export const emitAllocateConstructor = (ctx, lines, operation) => {
2134
+ if (operation.captures.length > 0) {
2135
+ throw createCppEmitBlockedError('capture:class-constructor', `carries ${operation.captures.length} capture(s); a class's methods and field initializers are called directly by ` +
2136
+ "translation-unit.ts's constructDefinitionsOf, with no environment parameter to receive one, so no capture can be transported here");
2137
+ }
2138
+ const name = defineValue(ctx, operation.result);
2139
+ const heritageOperand = operation.heritage;
2140
+ const heritage = heritageOperand?.representation;
2141
+ // A family of several classes is a base's constructor slot that the program
2142
+ // also stores subclasses into; the struct extends the family's declared
2143
+ // class alone, so the evaluated value is checked to be exactly that class.
2144
+ const exactBase = heritage?.kind === 'constructor-family' && heritage.members.length > 1 && heritage.abi.result.kind === 'class-ref'
2145
+ ? heritage.abi.result.declaration
2146
+ : null;
2147
+ const parent = heritage?.kind !== 'constructor-family' || !heritageOperand
2148
+ ? ''
2149
+ : exactBase !== null
2150
+ ? `gea::exactNativeClassHeritage<${cppClassName(exactBase)}>(${operandText(ctx, heritageOperand)}.environment)`
2151
+ : `gea::nativeClassMethodStateFromEnvironment(${operandText(ctx, heritageOperand)}.environment)`;
2152
+ const environment = `gea::allocateNativeClassMethodEnvironment<${cppClassName(operation.declaration)}>(${parent})`;
2153
+ lines.push(`${name} = ${cppTypeOf(operation.result.representation)}{&${cppConstructThunkName(operation.declaration)}, ${environment}};`);
2154
+ };