@scriptc/compiler 0.3.5 → 0.4.0

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 (1243) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +960 -82
  2. package/ambient/scriptc.d.ts +134 -0
  3. package/dist/backend/cycle-analysis.d.ts +1 -1
  4. package/dist/backend/cycle-analysis.js +1 -0
  5. package/dist/backend/cycle-analysis.js.map +1 -1
  6. package/dist/backend/cycle-analysis.test.js +13 -1
  7. package/dist/backend/cycle-analysis.test.js.map +1 -1
  8. package/dist/backend/cycle-mutability.js +16 -5
  9. package/dist/backend/cycle-mutability.js.map +1 -1
  10. package/dist/backend/executable-features.js +13 -0
  11. package/dist/backend/executable-features.js.map +1 -1
  12. package/dist/backend/immutability.test.js +1 -1
  13. package/dist/backend/library-pack.js +6 -0
  14. package/dist/backend/library-pack.js.map +1 -1
  15. package/dist/backend/llvm/alloc.d.ts +41 -4
  16. package/dist/backend/llvm/alloc.js +138 -7
  17. package/dist/backend/llvm/alloc.js.map +1 -1
  18. package/dist/backend/llvm/alloc.test.js +30 -1
  19. package/dist/backend/llvm/alloc.test.js.map +1 -1
  20. package/dist/backend/llvm/appended-array-literals.test.js +1 -1
  21. package/dist/backend/llvm/array-search.test.js +1 -1
  22. package/dist/backend/llvm/blocks.d.ts +8 -0
  23. package/dist/backend/llvm/blocks.js +43 -1
  24. package/dist/backend/llvm/blocks.js.map +1 -1
  25. package/dist/backend/llvm/blocks.test.js +22 -1
  26. package/dist/backend/llvm/blocks.test.js.map +1 -1
  27. package/dist/backend/llvm/byte-numbers.js +15 -5
  28. package/dist/backend/llvm/byte-numbers.js.map +1 -1
  29. package/dist/backend/llvm/bytes-alias.d.ts +14 -0
  30. package/dist/backend/llvm/bytes-alias.js +20 -0
  31. package/dist/backend/llvm/bytes-alias.js.map +1 -0
  32. package/dist/backend/llvm/bytes-loop-versions.d.ts +86 -0
  33. package/dist/backend/llvm/bytes-loop-versions.js +506 -0
  34. package/dist/backend/llvm/bytes-loop-versions.js.map +1 -0
  35. package/dist/backend/llvm/bytes-loop-versions.test.d.ts +1 -0
  36. package/dist/backend/llvm/bytes-loop-versions.test.js +244 -0
  37. package/dist/backend/llvm/bytes-loop-versions.test.js.map +1 -0
  38. package/dist/backend/llvm/call-lifetimes.js +50 -1
  39. package/dist/backend/llvm/call-lifetimes.js.map +1 -1
  40. package/dist/backend/llvm/call-lifetimes.test.js +34 -0
  41. package/dist/backend/llvm/call-lifetimes.test.js.map +1 -1
  42. package/dist/backend/llvm/checked-narrows.test.js +1 -1
  43. package/dist/backend/llvm/checked-value-lifetimes.js +4 -1
  44. package/dist/backend/llvm/checked-value-lifetimes.js.map +1 -1
  45. package/dist/backend/llvm/classes.d.ts +11 -0
  46. package/dist/backend/llvm/classes.js +71 -14
  47. package/dist/backend/llvm/classes.js.map +1 -1
  48. package/dist/backend/llvm/classes.test.js +58 -8
  49. package/dist/backend/llvm/classes.test.js.map +1 -1
  50. package/dist/backend/llvm/common.js +1 -0
  51. package/dist/backend/llvm/common.js.map +1 -1
  52. package/dist/backend/llvm/constant-callbacks.d.ts +5 -1
  53. package/dist/backend/llvm/constant-callbacks.js +55 -12
  54. package/dist/backend/llvm/constant-callbacks.js.map +1 -1
  55. package/dist/backend/llvm/constant-callbacks.test.js +88 -1
  56. package/dist/backend/llvm/constant-callbacks.test.js.map +1 -1
  57. package/dist/backend/llvm/counted-loops.d.ts +4 -0
  58. package/dist/backend/llvm/counted-loops.js +37 -0
  59. package/dist/backend/llvm/counted-loops.js.map +1 -1
  60. package/dist/backend/llvm/dense-array-access.d.ts +12 -3
  61. package/dist/backend/llvm/dense-array-access.js +72 -14
  62. package/dist/backend/llvm/dense-array-access.js.map +1 -1
  63. package/dist/backend/llvm/dense-array-access.test.js +59 -3
  64. package/dist/backend/llvm/dense-array-access.test.js.map +1 -1
  65. package/dist/backend/llvm/dense-array-loops.d.ts +51 -0
  66. package/dist/backend/llvm/dense-array-loops.js +162 -0
  67. package/dist/backend/llvm/dense-array-loops.js.map +1 -0
  68. package/dist/backend/llvm/dense-array-loops.test.d.ts +1 -0
  69. package/dist/backend/llvm/dense-array-loops.test.js +128 -0
  70. package/dist/backend/llvm/dense-array-loops.test.js.map +1 -0
  71. package/dist/backend/llvm/dyn-handle-tags.test.d.ts +1 -0
  72. package/dist/backend/llvm/dyn-handle-tags.test.js +38 -0
  73. package/dist/backend/llvm/dyn-handle-tags.test.js.map +1 -0
  74. package/dist/backend/llvm/dyn.d.ts +28 -4
  75. package/dist/backend/llvm/dyn.js +324 -179
  76. package/dist/backend/llvm/dyn.js.map +1 -1
  77. package/dist/backend/llvm/emit-function.d.ts +64 -0
  78. package/dist/backend/llvm/emit-function.js +1190 -0
  79. package/dist/backend/llvm/emit-function.js.map +1 -0
  80. package/dist/backend/llvm/emit-module.d.ts +24 -0
  81. package/dist/backend/llvm/emit-module.js +1535 -0
  82. package/dist/backend/llvm/emit-module.js.map +1 -0
  83. package/dist/backend/llvm/emit-statements.d.ts +58 -0
  84. package/dist/backend/llvm/emit-statements.js +1964 -0
  85. package/dist/backend/llvm/emit-statements.js.map +1 -0
  86. package/dist/backend/llvm/emitter.d.ts +576 -268
  87. package/dist/backend/llvm/emitter.js +801 -4447
  88. package/dist/backend/llvm/emitter.js.map +1 -1
  89. package/dist/backend/llvm/emitter.test.js +57 -3
  90. package/dist/backend/llvm/emitter.test.js.map +1 -1
  91. package/dist/backend/llvm/expr-async.js +73 -46
  92. package/dist/backend/llvm/expr-async.js.map +1 -1
  93. package/dist/backend/llvm/expr-async.test.js +1 -1
  94. package/dist/backend/llvm/expr-bytes.d.ts +2 -0
  95. package/dist/backend/llvm/expr-bytes.js +76 -29
  96. package/dist/backend/llvm/expr-bytes.js.map +1 -1
  97. package/dist/backend/llvm/expr-callbacks.d.ts +6 -2
  98. package/dist/backend/llvm/expr-callbacks.js +48 -11
  99. package/dist/backend/llvm/expr-callbacks.js.map +1 -1
  100. package/dist/backend/llvm/expr-calls.d.ts +1 -1
  101. package/dist/backend/llvm/expr-calls.js +71 -53
  102. package/dist/backend/llvm/expr-calls.js.map +1 -1
  103. package/dist/backend/llvm/expr-calls.test.js +1 -1
  104. package/dist/backend/llvm/expr-containers.js +39 -15
  105. package/dist/backend/llvm/expr-containers.js.map +1 -1
  106. package/dist/backend/llvm/expr-control.js +16 -16
  107. package/dist/backend/llvm/expr-control.js.map +1 -1
  108. package/dist/backend/llvm/expr-dispatch.js +1 -0
  109. package/dist/backend/llvm/expr-dispatch.js.map +1 -1
  110. package/dist/backend/llvm/expr-dynamic.d.ts +3 -0
  111. package/dist/backend/llvm/expr-dynamic.js +92 -63
  112. package/dist/backend/llvm/expr-dynamic.js.map +1 -1
  113. package/dist/backend/llvm/expr-primitives.d.ts +1 -1
  114. package/dist/backend/llvm/expr-primitives.js +132 -25
  115. package/dist/backend/llvm/expr-primitives.js.map +1 -1
  116. package/dist/backend/llvm/expr-primitives.test.js +2 -2
  117. package/dist/backend/llvm/expr-records.d.ts +1 -1
  118. package/dist/backend/llvm/expr-records.js +32 -11
  119. package/dist/backend/llvm/expr-records.js.map +1 -1
  120. package/dist/backend/llvm/expr-stream-bridges.js +54 -12
  121. package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
  122. package/dist/backend/llvm/expr-stream-bridges.test.js +2 -2
  123. package/dist/backend/llvm/expr-stream-callbacks.js +22 -1
  124. package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
  125. package/dist/backend/llvm/int32-abi.test.js +2 -2
  126. package/dist/backend/llvm/integer-clones.test.js +3 -3
  127. package/dist/backend/llvm/integer-remainder.d.ts +34 -13
  128. package/dist/backend/llvm/integer-remainder.js +156 -22
  129. package/dist/backend/llvm/integer-remainder.js.map +1 -1
  130. package/dist/backend/llvm/intern-tables.test.js +1 -1
  131. package/dist/backend/llvm/jsval-encoding.d.ts +21 -0
  132. package/dist/backend/llvm/jsval-encoding.js +20 -0
  133. package/dist/backend/llvm/jsval-encoding.js.map +1 -0
  134. package/dist/backend/llvm/jsval.d.ts +12 -0
  135. package/dist/backend/llvm/jsval.js +488 -0
  136. package/dist/backend/llvm/jsval.js.map +1 -0
  137. package/dist/backend/llvm/lazy-captures.d.ts +12 -2
  138. package/dist/backend/llvm/lazy-captures.js +39 -17
  139. package/dist/backend/llvm/lazy-captures.js.map +1 -1
  140. package/dist/backend/llvm/lib-abi.js +1 -1
  141. package/dist/backend/llvm/lib-abi.js.map +1 -1
  142. package/dist/backend/llvm/lib-connect.js +1 -1
  143. package/dist/backend/llvm/lib-connect.js.map +1 -1
  144. package/dist/backend/llvm/lib-datagram.js +14 -8
  145. package/dist/backend/llvm/lib-datagram.js.map +1 -1
  146. package/dist/backend/llvm/lib-dispatch.js +217 -24
  147. package/dist/backend/llvm/lib-dispatch.js.map +1 -1
  148. package/dist/backend/llvm/lib-filesystem.js +102 -13
  149. package/dist/backend/llvm/lib-filesystem.js.map +1 -1
  150. package/dist/backend/llvm/lib-http2.js +3 -3
  151. package/dist/backend/llvm/lib-http2.js.map +1 -1
  152. package/dist/backend/llvm/lib-lookup.js +2 -2
  153. package/dist/backend/llvm/lib-lookup.js.map +1 -1
  154. package/dist/backend/llvm/lib-network.js +77 -25
  155. package/dist/backend/llvm/lib-network.js.map +1 -1
  156. package/dist/backend/llvm/lib-process.js +100 -50
  157. package/dist/backend/llvm/lib-process.js.map +1 -1
  158. package/dist/backend/llvm/lib-shared.d.ts +12 -0
  159. package/dist/backend/llvm/lib-shared.js +229 -5
  160. package/dist/backend/llvm/lib-shared.js.map +1 -1
  161. package/dist/backend/llvm/lib-stream.js +46 -16
  162. package/dist/backend/llvm/lib-stream.js.map +1 -1
  163. package/dist/backend/llvm/lib-test.js +57 -8
  164. package/dist/backend/llvm/lib-test.js.map +1 -1
  165. package/dist/backend/llvm/lib-tls.js +4 -9
  166. package/dist/backend/llvm/lib-tls.js.map +1 -1
  167. package/dist/backend/llvm/local-array-reads.js +2 -2
  168. package/dist/backend/llvm/local-array-reads.test.js +1 -1
  169. package/dist/backend/llvm/local-extents.d.ts +19 -0
  170. package/dist/backend/llvm/local-extents.js +169 -0
  171. package/dist/backend/llvm/local-extents.js.map +1 -0
  172. package/dist/backend/llvm/local-extents.test.d.ts +1 -0
  173. package/dist/backend/llvm/local-extents.test.js +92 -0
  174. package/dist/backend/llvm/local-extents.test.js.map +1 -0
  175. package/dist/backend/llvm/local-union-storage.js +7 -7
  176. package/dist/backend/llvm/local-union-storage.js.map +1 -1
  177. package/dist/backend/llvm/local-union-storage.test.js +2 -2
  178. package/dist/backend/llvm/map-entry-fusion.test.js +1 -1
  179. package/dist/backend/llvm/map-number-lookup.js +2 -2
  180. package/dist/backend/llvm/map-number-lookup.test.js +2 -2
  181. package/dist/backend/llvm/map-read-lifetimes.test.js +2 -2
  182. package/dist/backend/llvm/narrow-guards.d.ts +38 -0
  183. package/dist/backend/llvm/narrow-guards.js +151 -0
  184. package/dist/backend/llvm/narrow-guards.js.map +1 -0
  185. package/dist/backend/llvm/nullable-unions.d.ts +70 -9
  186. package/dist/backend/llvm/nullable-unions.js +105 -6
  187. package/dist/backend/llvm/nullable-unions.js.map +1 -1
  188. package/dist/backend/llvm/nullable-unions.test.d.ts +1 -0
  189. package/dist/backend/llvm/nullable-unions.test.js +65 -0
  190. package/dist/backend/llvm/nullable-unions.test.js.map +1 -0
  191. package/dist/backend/llvm/publish.d.ts +4 -0
  192. package/dist/backend/llvm/publish.js +14 -2
  193. package/dist/backend/llvm/publish.js.map +1 -1
  194. package/dist/backend/llvm/publish.test.js +1 -1
  195. package/dist/backend/llvm/receivers.d.ts +31 -0
  196. package/dist/backend/llvm/receivers.js +395 -0
  197. package/dist/backend/llvm/receivers.js.map +1 -0
  198. package/dist/backend/llvm/record-results.d.ts +13 -2
  199. package/dist/backend/llvm/record-results.js +66 -6
  200. package/dist/backend/llvm/record-results.js.map +1 -1
  201. package/dist/backend/llvm/reference-effects.js +9 -0
  202. package/dist/backend/llvm/reference-effects.js.map +1 -1
  203. package/dist/backend/llvm/reference-writes.d.ts +4 -0
  204. package/dist/backend/llvm/reference-writes.js +143 -6
  205. package/dist/backend/llvm/reference-writes.js.map +1 -1
  206. package/dist/backend/llvm/reference-writes.test.d.ts +1 -0
  207. package/dist/backend/llvm/reference-writes.test.js +88 -0
  208. package/dist/backend/llvm/reference-writes.test.js.map +1 -0
  209. package/dist/backend/llvm/regex-matchers.d.ts +8 -0
  210. package/dist/backend/llvm/regex-matchers.js +33 -0
  211. package/dist/backend/llvm/regex-matchers.js.map +1 -1
  212. package/dist/backend/llvm/regex-matchers.test.js +23 -1
  213. package/dist/backend/llvm/regex-matchers.test.js.map +1 -1
  214. package/dist/backend/llvm/regions.d.ts +1 -1
  215. package/dist/backend/llvm/regions.js +9 -6
  216. package/dist/backend/llvm/regions.js.map +1 -1
  217. package/dist/backend/llvm/regions.test.js +1 -1
  218. package/dist/backend/llvm/shapes.d.ts +69 -43
  219. package/dist/backend/llvm/shapes.js +285 -21
  220. package/dist/backend/llvm/shapes.js.map +1 -1
  221. package/dist/backend/llvm/shapes.test.js +37 -3
  222. package/dist/backend/llvm/shapes.test.js.map +1 -1
  223. package/dist/backend/llvm/speculative-integers.d.ts +74 -0
  224. package/dist/backend/llvm/speculative-integers.js +571 -0
  225. package/dist/backend/llvm/speculative-integers.js.map +1 -0
  226. package/dist/backend/llvm/speculative-integers.test.d.ts +1 -0
  227. package/dist/backend/llvm/speculative-integers.test.js +148 -0
  228. package/dist/backend/llvm/speculative-integers.test.js.map +1 -0
  229. package/dist/backend/llvm/split-loops.js +2 -2
  230. package/dist/backend/llvm/split-loops.js.map +1 -1
  231. package/dist/backend/llvm/stack-objects.d.ts +26 -6
  232. package/dist/backend/llvm/stack-objects.js +133 -10
  233. package/dist/backend/llvm/stack-objects.js.map +1 -1
  234. package/dist/backend/llvm/stack-objects.test.js +55 -1
  235. package/dist/backend/llvm/stack-objects.test.js.map +1 -1
  236. package/dist/backend/llvm/stack-unions.test.js +1 -1
  237. package/dist/backend/llvm/string-construction.test.js +1 -1
  238. package/dist/backend/llvm/string-lifetimes.test.js +15 -14
  239. package/dist/backend/llvm/string-lifetimes.test.js.map +1 -1
  240. package/dist/backend/llvm/string-slices.d.ts +25 -0
  241. package/dist/backend/llvm/string-slices.js +207 -1
  242. package/dist/backend/llvm/string-slices.js.map +1 -1
  243. package/dist/backend/llvm/string-slices.test.js +139 -2
  244. package/dist/backend/llvm/string-slices.test.js.map +1 -1
  245. package/dist/backend/llvm/switch-dispatch.test.js +2 -2
  246. package/dist/backend/llvm/thread-slots.d.ts +5 -0
  247. package/dist/backend/llvm/thread-slots.js +142 -0
  248. package/dist/backend/llvm/thread-slots.js.map +1 -0
  249. package/dist/backend/llvm/thread-slots.test.d.ts +1 -0
  250. package/dist/backend/llvm/thread-slots.test.js +110 -0
  251. package/dist/backend/llvm/thread-slots.test.js.map +1 -0
  252. package/dist/backend/llvm/union-repr.d.ts +7 -7
  253. package/dist/backend/llvm/union-repr.js +18 -2
  254. package/dist/backend/llvm/union-repr.js.map +1 -1
  255. package/dist/backend/llvm/union-retype.test.js +17 -3
  256. package/dist/backend/llvm/union-retype.test.js.map +1 -1
  257. package/dist/backend/llvm/walkers.d.ts +2 -2
  258. package/dist/backend/llvm/walkers.js +51 -26
  259. package/dist/backend/llvm/walkers.js.map +1 -1
  260. package/dist/backend/llvm/wasm-modules.d.ts +16 -0
  261. package/dist/backend/llvm/wasm-modules.js +66 -0
  262. package/dist/backend/llvm/wasm-modules.js.map +1 -0
  263. package/dist/backend/llvm/wrapping-sums.d.ts +7 -0
  264. package/dist/backend/llvm/wrapping-sums.js +11 -3
  265. package/dist/backend/llvm/wrapping-sums.js.map +1 -1
  266. package/dist/backend/mangle.d.ts +7 -0
  267. package/dist/backend/mangle.js +11 -0
  268. package/dist/backend/mangle.js.map +1 -1
  269. package/dist/backend/may-throw.d.ts +3 -0
  270. package/dist/backend/may-throw.js +6 -2
  271. package/dist/backend/may-throw.js.map +1 -1
  272. package/dist/backend/may-throw.test.js +1 -1
  273. package/dist/backend/native/contracts.d.ts +37 -0
  274. package/dist/backend/native/executable.js +192 -134
  275. package/dist/backend/native/executable.js.map +1 -1
  276. package/dist/backend/native/library.js +1 -0
  277. package/dist/backend/native/library.js.map +1 -1
  278. package/dist/backend/native/runtime-inputs.d.ts +1 -1
  279. package/dist/backend/native/runtime-inputs.js +2 -0
  280. package/dist/backend/native/runtime-inputs.js.map +1 -1
  281. package/dist/backend/native-link-info-core.d.ts +30 -0
  282. package/dist/backend/native-link-info-core.js.map +1 -1
  283. package/dist/backend/publication.test.js +1 -1
  284. package/dist/backend/runtime-pack-core.d.ts +9 -1
  285. package/dist/backend/runtime-pack-core.js +10 -1
  286. package/dist/backend/runtime-pack-core.js.map +1 -1
  287. package/dist/backend/runtime-pack-native.js +1 -1
  288. package/dist/backend/runtime-pack-native.js.map +1 -1
  289. package/dist/backend/runtime-pack-native.test.d.ts +1 -0
  290. package/dist/backend/runtime-pack-native.test.js +31 -0
  291. package/dist/backend/runtime-pack-native.test.js.map +1 -0
  292. package/dist/backend/runtime-pack-targets.test.js +5 -0
  293. package/dist/backend/runtime-pack-targets.test.js.map +1 -1
  294. package/dist/backend/runtime-pack.d.ts +7 -3
  295. package/dist/backend/runtime-pack.js +12 -6
  296. package/dist/backend/runtime-pack.js.map +1 -1
  297. package/dist/backend/runtime-pack.test.js +20 -6
  298. package/dist/backend/runtime-pack.test.js.map +1 -1
  299. package/dist/backend/stack-observations.d.ts +22 -0
  300. package/dist/backend/stack-observations.js +382 -0
  301. package/dist/backend/stack-observations.js.map +1 -0
  302. package/dist/backend/stack-observations.test.d.ts +1 -0
  303. package/dist/backend/stack-observations.test.js +233 -0
  304. package/dist/backend/stack-observations.test.js.map +1 -0
  305. package/dist/backend/target-diagnostics.js +8 -0
  306. package/dist/backend/target-diagnostics.js.map +1 -1
  307. package/dist/backend/target-diagnostics.test.js +1 -1
  308. package/dist/backend/warm-cache.js +5 -0
  309. package/dist/backend/warm-cache.js.map +1 -1
  310. package/dist/backend/young-nursery.d.ts +7 -0
  311. package/dist/backend/young-nursery.js +10 -0
  312. package/dist/backend/young-nursery.js.map +1 -0
  313. package/dist/cli/command.js +44 -4
  314. package/dist/cli/command.js.map +1 -1
  315. package/dist/cli/usage.d.ts +11 -1
  316. package/dist/cli/usage.js +20 -1
  317. package/dist/cli/usage.js.map +1 -1
  318. package/dist/compat/fetch-profile.js +10 -1
  319. package/dist/compat/fetch-profile.js.map +1 -1
  320. package/dist/compile-types.d.ts +13 -0
  321. package/dist/contracts/check.js +25 -6
  322. package/dist/contracts/check.js.map +1 -1
  323. package/dist/contracts/int32-elements.d.ts +115 -0
  324. package/dist/contracts/int32-elements.js +1179 -0
  325. package/dist/contracts/int32-elements.js.map +1 -0
  326. package/dist/coverage/report.d.ts +16 -0
  327. package/dist/coverage/report.js +182 -1
  328. package/dist/coverage/report.js.map +1 -1
  329. package/dist/coverage/surface-manifest.js +19 -6
  330. package/dist/coverage/surface-manifest.js.map +1 -1
  331. package/dist/coverage/verdict-cache.d.ts +2 -0
  332. package/dist/coverage/verdict-cache.js +12 -0
  333. package/dist/coverage/verdict-cache.js.map +1 -1
  334. package/dist/coverage/verdict-cache.test.js +2 -1
  335. package/dist/coverage/verdict-cache.test.js.map +1 -1
  336. package/dist/diagnostics/diagnostic.d.ts +11 -7
  337. package/dist/diagnostics/diagnostic.js +35 -23
  338. package/dist/diagnostics/diagnostic.js.map +1 -1
  339. package/dist/diagnostics/envelope.d.ts +39 -2
  340. package/dist/diagnostics/envelope.js.map +1 -1
  341. package/dist/diagnostics/render.d.ts +7 -0
  342. package/dist/diagnostics/render.js +50 -13
  343. package/dist/diagnostics/render.js.map +1 -1
  344. package/dist/diagnostics/render.test.d.ts +1 -0
  345. package/dist/diagnostics/render.test.js +49 -0
  346. package/dist/diagnostics/render.test.js.map +1 -0
  347. package/dist/executable/executable-cache.d.ts +17 -0
  348. package/dist/executable/executable-cache.js +13 -1
  349. package/dist/executable/executable-cache.js.map +1 -1
  350. package/dist/executable/executable-cache.test.js +7 -1
  351. package/dist/executable/executable-cache.test.js.map +1 -1
  352. package/dist/executable/prepare.js +2 -1
  353. package/dist/executable/prepare.js.map +1 -1
  354. package/dist/frontend/analysis.js +6 -1
  355. package/dist/frontend/analysis.js.map +1 -1
  356. package/dist/frontend/builtin-modules.d.ts +16 -2
  357. package/dist/frontend/builtin-modules.js +40 -7
  358. package/dist/frontend/builtin-modules.js.map +1 -1
  359. package/dist/frontend/cjs-syntax.js +52 -51
  360. package/dist/frontend/cjs-syntax.js.map +1 -1
  361. package/dist/frontend/contract-types.d.ts +3 -0
  362. package/dist/frontend/contract-types.js +36 -7
  363. package/dist/frontend/contract-types.js.map +1 -1
  364. package/dist/frontend/experimental-import.d.ts +5 -1
  365. package/dist/frontend/experimental-import.js +26 -7
  366. package/dist/frontend/experimental-import.js.map +1 -1
  367. package/dist/frontend/fork-target.js +20 -22
  368. package/dist/frontend/fork-target.js.map +1 -1
  369. package/dist/frontend/fork-target.test.js +2 -1
  370. package/dist/frontend/fork-target.test.js.map +1 -1
  371. package/dist/frontend/function-completion.js +6 -6
  372. package/dist/frontend/function-completion.js.map +1 -1
  373. package/dist/frontend/helper-tokens.js +15 -3
  374. package/dist/frontend/helper-tokens.js.map +1 -1
  375. package/dist/frontend/helper-tokens.test.js +7 -1
  376. package/dist/frontend/helper-tokens.test.js.map +1 -1
  377. package/dist/frontend/inferred-js-diagnostics.js +14 -17
  378. package/dist/frontend/inferred-js-diagnostics.js.map +1 -1
  379. package/dist/frontend/input-tracker.d.ts +3 -0
  380. package/dist/frontend/input-tracker.js +32 -3
  381. package/dist/frontend/input-tracker.js.map +1 -1
  382. package/dist/frontend/lib-contract.js +36 -32
  383. package/dist/frontend/lib-contract.js.map +1 -1
  384. package/dist/frontend/lib-exports.js +3 -3
  385. package/dist/frontend/lib-exports.js.map +1 -1
  386. package/dist/frontend/lowering/array-values.d.ts +8 -3
  387. package/dist/frontend/lowering/array-values.js +60 -11
  388. package/dist/frontend/lowering/array-values.js.map +1 -1
  389. package/dist/frontend/lowering/assert-instances.js +4 -4
  390. package/dist/frontend/lowering/assert-instances.js.map +1 -1
  391. package/dist/frontend/lowering/assertion-identity.d.ts +12 -0
  392. package/dist/frontend/lowering/assertion-identity.js +70 -0
  393. package/dist/frontend/lowering/assertion-identity.js.map +1 -0
  394. package/dist/frontend/lowering/assertion-members.d.ts +28 -0
  395. package/dist/frontend/lowering/assertion-members.js +185 -0
  396. package/dist/frontend/lowering/assertion-members.js.map +1 -0
  397. package/dist/frontend/lowering/binding-analysis.js +27 -20
  398. package/dist/frontend/lowering/binding-analysis.js.map +1 -1
  399. package/dist/frontend/lowering/builtin-calls.js +72 -4
  400. package/dist/frontend/lowering/builtin-calls.js.map +1 -1
  401. package/dist/frontend/lowering/builtin-function-fences.d.ts +14 -0
  402. package/dist/frontend/lowering/builtin-function-fences.js +42 -0
  403. package/dist/frontend/lowering/builtin-function-fences.js.map +1 -0
  404. package/dist/frontend/lowering/builtins/arguments.js +1 -1
  405. package/dist/frontend/lowering/builtins/arguments.js.map +1 -1
  406. package/dist/frontend/lowering/builtins/async-context.js +53 -52
  407. package/dist/frontend/lowering/builtins/async-context.js.map +1 -1
  408. package/dist/frontend/lowering/builtins/atomics.js +6 -6
  409. package/dist/frontend/lowering/builtins/atomics.js.map +1 -1
  410. package/dist/frontend/lowering/builtins/blob.js +8 -6
  411. package/dist/frontend/lowering/builtins/blob.js.map +1 -1
  412. package/dist/frontend/lowering/builtins/builtin-class-dyn.d.ts +23 -0
  413. package/dist/frontend/lowering/builtins/builtin-class-dyn.js +156 -0
  414. package/dist/frontend/lowering/builtins/builtin-class-dyn.js.map +1 -0
  415. package/dist/frontend/lowering/builtins/callable-aliases.js +45 -6
  416. package/dist/frontend/lowering/builtins/callable-aliases.js.map +1 -1
  417. package/dist/frontend/lowering/builtins/child-process-async.js +7 -7
  418. package/dist/frontend/lowering/builtins/child-process-async.js.map +1 -1
  419. package/dist/frontend/lowering/builtins/child-process-methods.d.ts +6 -4
  420. package/dist/frontend/lowering/builtins/child-process-methods.js +310 -57
  421. package/dist/frontend/lowering/builtins/child-process-methods.js.map +1 -1
  422. package/dist/frontend/lowering/builtins/child-process-sync.js +16 -10
  423. package/dist/frontend/lowering/builtins/child-process-sync.js.map +1 -1
  424. package/dist/frontend/lowering/builtins/child-process.d.ts +6 -4
  425. package/dist/frontend/lowering/builtins/child-process.js +85 -61
  426. package/dist/frontend/lowering/builtins/child-process.js.map +1 -1
  427. package/dist/frontend/lowering/builtins/class-values.d.ts +60 -0
  428. package/dist/frontend/lowering/builtins/class-values.js +226 -0
  429. package/dist/frontend/lowering/builtins/class-values.js.map +1 -0
  430. package/dist/frontend/lowering/builtins/compression.d.ts +18 -0
  431. package/dist/frontend/lowering/builtins/compression.js +230 -52
  432. package/dist/frontend/lowering/builtins/compression.js.map +1 -1
  433. package/dist/frontend/lowering/builtins/constants.d.ts +9 -1
  434. package/dist/frontend/lowering/builtins/constants.js +28 -7
  435. package/dist/frontend/lowering/builtins/constants.js.map +1 -1
  436. package/dist/frontend/lowering/builtins/crypto.d.ts +19 -0
  437. package/dist/frontend/lowering/builtins/crypto.js +223 -38
  438. package/dist/frontend/lowering/builtins/crypto.js.map +1 -1
  439. package/dist/frontend/lowering/builtins/dates.d.ts +7 -1
  440. package/dist/frontend/lowering/builtins/dates.js +92 -16
  441. package/dist/frontend/lowering/builtins/dates.js.map +1 -1
  442. package/dist/frontend/lowering/builtins/disposable-stack.d.ts +18 -0
  443. package/dist/frontend/lowering/builtins/disposable-stack.js +137 -0
  444. package/dist/frontend/lowering/builtins/disposable-stack.js.map +1 -0
  445. package/dist/frontend/lowering/builtins/environment.js +3 -3
  446. package/dist/frontend/lowering/builtins/environment.js.map +1 -1
  447. package/dist/frontend/lowering/builtins/errors.d.ts +14 -10
  448. package/dist/frontend/lowering/builtins/errors.js +174 -6
  449. package/dist/frontend/lowering/builtins/errors.js.map +1 -1
  450. package/dist/frontend/lowering/builtins/filesystem-calls.d.ts +4 -0
  451. package/dist/frontend/lowering/builtins/filesystem-calls.js +136 -113
  452. package/dist/frontend/lowering/builtins/filesystem-calls.js.map +1 -1
  453. package/dist/frontend/lowering/builtins/filesystem.d.ts +8 -0
  454. package/dist/frontend/lowering/builtins/filesystem.js +213 -76
  455. package/dist/frontend/lowering/builtins/filesystem.js.map +1 -1
  456. package/dist/frontend/lowering/builtins/fs-glob.js +3 -3
  457. package/dist/frontend/lowering/builtins/fs-glob.js.map +1 -1
  458. package/dist/frontend/lowering/builtins/fs-streams.js +10 -11
  459. package/dist/frontend/lowering/builtins/fs-streams.js.map +1 -1
  460. package/dist/frontend/lowering/builtins/hash-stream.d.ts +12 -0
  461. package/dist/frontend/lowering/builtins/hash-stream.js +80 -0
  462. package/dist/frontend/lowering/builtins/hash-stream.js.map +1 -0
  463. package/dist/frontend/lowering/builtins/ipc.js +45 -8
  464. package/dist/frontend/lowering/builtins/ipc.js.map +1 -1
  465. package/dist/frontend/lowering/builtins/json.js +232 -24
  466. package/dist/frontend/lowering/builtins/json.js.map +1 -1
  467. package/dist/frontend/lowering/builtins/key-object.js +4 -4
  468. package/dist/frontend/lowering/builtins/key-object.js.map +1 -1
  469. package/dist/frontend/lowering/builtins/module-bindings.d.ts +8 -0
  470. package/dist/frontend/lowering/builtins/module-bindings.js +71 -22
  471. package/dist/frontend/lowering/builtins/module-bindings.js.map +1 -1
  472. package/dist/frontend/lowering/builtins/module-calls.js +67 -46
  473. package/dist/frontend/lowering/builtins/module-calls.js.map +1 -1
  474. package/dist/frontend/lowering/builtins/module-resolution.d.ts +4 -3
  475. package/dist/frontend/lowering/builtins/module-resolution.js +24 -23
  476. package/dist/frontend/lowering/builtins/module-resolution.js.map +1 -1
  477. package/dist/frontend/lowering/builtins/navigator.d.ts +13 -0
  478. package/dist/frontend/lowering/builtins/navigator.js +40 -0
  479. package/dist/frontend/lowering/builtins/navigator.js.map +1 -0
  480. package/dist/frontend/lowering/builtins/net-address.d.ts +19 -0
  481. package/dist/frontend/lowering/builtins/net-address.js +156 -0
  482. package/dist/frontend/lowering/builtins/net-address.js.map +1 -0
  483. package/dist/frontend/lowering/builtins/numbers.js +25 -9
  484. package/dist/frontend/lowering/builtins/numbers.js.map +1 -1
  485. package/dist/frontend/lowering/builtins/operating-system.d.ts +4 -0
  486. package/dist/frontend/lowering/builtins/operating-system.js +25 -12
  487. package/dist/frontend/lowering/builtins/operating-system.js.map +1 -1
  488. package/dist/frontend/lowering/builtins/performance.d.ts +12 -0
  489. package/dist/frontend/lowering/builtins/performance.js +259 -8
  490. package/dist/frontend/lowering/builtins/performance.js.map +1 -1
  491. package/dist/frontend/lowering/builtins/process.d.ts +32 -1
  492. package/dist/frontend/lowering/builtins/process.js +468 -99
  493. package/dist/frontend/lowering/builtins/process.js.map +1 -1
  494. package/dist/frontend/lowering/builtins/promises.d.ts +5 -1
  495. package/dist/frontend/lowering/builtins/promises.js +326 -43
  496. package/dist/frontend/lowering/builtins/promises.js.map +1 -1
  497. package/dist/frontend/lowering/builtins/promisify-callback.d.ts +37 -0
  498. package/dist/frontend/lowering/builtins/promisify-callback.js +320 -0
  499. package/dist/frontend/lowering/builtins/promisify-callback.js.map +1 -0
  500. package/dist/frontend/lowering/builtins/properties.js +37 -1
  501. package/dist/frontend/lowering/builtins/properties.js.map +1 -1
  502. package/dist/frontend/lowering/builtins/querystring.js +14 -14
  503. package/dist/frontend/lowering/builtins/querystring.js.map +1 -1
  504. package/dist/frontend/lowering/builtins/readline.d.ts +55 -13
  505. package/dist/frontend/lowering/builtins/readline.js +931 -69
  506. package/dist/frontend/lowering/builtins/readline.js.map +1 -1
  507. package/dist/frontend/lowering/builtins/receiver-types.js +3 -5
  508. package/dist/frontend/lowering/builtins/receiver-types.js.map +1 -1
  509. package/dist/frontend/lowering/builtins/reflection.js +16 -14
  510. package/dist/frontend/lowering/builtins/reflection.js.map +1 -1
  511. package/dist/frontend/lowering/builtins/runtime-constructor.d.ts +26 -0
  512. package/dist/frontend/lowering/builtins/runtime-constructor.js +165 -0
  513. package/dist/frontend/lowering/builtins/runtime-constructor.js.map +1 -0
  514. package/dist/frontend/lowering/builtins/strings.js +101 -12
  515. package/dist/frontend/lowering/builtins/strings.js.map +1 -1
  516. package/dist/frontend/lowering/builtins/text-codecs.js +41 -38
  517. package/dist/frontend/lowering/builtins/text-codecs.js.map +1 -1
  518. package/dist/frontend/lowering/builtins/timers.js +75 -30
  519. package/dist/frontend/lowering/builtins/timers.js.map +1 -1
  520. package/dist/frontend/lowering/builtins/url.d.ts +3 -0
  521. package/dist/frontend/lowering/builtins/url.js +120 -17
  522. package/dist/frontend/lowering/builtins/url.js.map +1 -1
  523. package/dist/frontend/lowering/builtins/util-types.js +20 -4
  524. package/dist/frontend/lowering/builtins/util-types.js.map +1 -1
  525. package/dist/frontend/lowering/builtins/v8.d.ts +11 -0
  526. package/dist/frontend/lowering/builtins/v8.js +105 -0
  527. package/dist/frontend/lowering/builtins/v8.js.map +1 -0
  528. package/dist/frontend/lowering/builtins/webassembly.d.ts +33 -0
  529. package/dist/frontend/lowering/builtins/webassembly.js +388 -0
  530. package/dist/frontend/lowering/builtins/webassembly.js.map +1 -0
  531. package/dist/frontend/lowering/builtins/webcrypto.d.ts +20 -0
  532. package/dist/frontend/lowering/builtins/webcrypto.js +112 -0
  533. package/dist/frontend/lowering/builtins/webcrypto.js.map +1 -0
  534. package/dist/frontend/lowering/builtins/workers.d.ts +16 -0
  535. package/dist/frontend/lowering/builtins/workers.js +246 -3
  536. package/dist/frontend/lowering/builtins/workers.js.map +1 -1
  537. package/dist/frontend/lowering/call-arguments.js +69 -14
  538. package/dist/frontend/lowering/call-arguments.js.map +1 -1
  539. package/dist/frontend/lowering/call-signatures.d.ts +19 -1
  540. package/dist/frontend/lowering/call-signatures.js +254 -47
  541. package/dist/frontend/lowering/call-signatures.js.map +1 -1
  542. package/dist/frontend/lowering/checked-promise-all.d.ts +3 -0
  543. package/dist/frontend/lowering/checked-promise-all.js +1 -1
  544. package/dist/frontend/lowering/checked-promise-all.js.map +1 -1
  545. package/dist/frontend/lowering/cjs-exports-object.d.ts +53 -0
  546. package/dist/frontend/lowering/cjs-exports-object.js +528 -0
  547. package/dist/frontend/lowering/cjs-exports-object.js.map +1 -0
  548. package/dist/frontend/lowering/cjs-inline-require.d.ts +86 -0
  549. package/dist/frontend/lowering/cjs-inline-require.js +314 -0
  550. package/dist/frontend/lowering/cjs-inline-require.js.map +1 -0
  551. package/dist/frontend/lowering/cjs-tsc-interop.d.ts +28 -0
  552. package/dist/frontend/lowering/cjs-tsc-interop.js +208 -0
  553. package/dist/frontend/lowering/cjs-tsc-interop.js.map +1 -0
  554. package/dist/frontend/lowering/class-attributes.d.ts +19 -0
  555. package/dist/frontend/lowering/class-attributes.js +378 -0
  556. package/dist/frontend/lowering/class-attributes.js.map +1 -0
  557. package/dist/frontend/lowering/class-callbacks.d.ts +3 -1
  558. package/dist/frontend/lowering/class-callbacks.js +21 -10
  559. package/dist/frontend/lowering/class-callbacks.js.map +1 -1
  560. package/dist/frontend/lowering/class-construction.js +49 -4
  561. package/dist/frontend/lowering/class-construction.js.map +1 -1
  562. package/dist/frontend/lowering/class-descriptors.d.ts +2 -0
  563. package/dist/frontend/lowering/class-descriptors.js +8 -8
  564. package/dist/frontend/lowering/class-descriptors.js.map +1 -1
  565. package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +64 -0
  566. package/dist/frontend/lowering/class-dynamic-dispatch.js +1115 -89
  567. package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
  568. package/dist/frontend/lowering/class-instance-constructor.js +1 -1
  569. package/dist/frontend/lowering/class-instance-constructor.js.map +1 -1
  570. package/dist/frontend/lowering/class-iterables.d.ts +11 -0
  571. package/dist/frontend/lowering/class-iterables.js +31 -0
  572. package/dist/frontend/lowering/class-iterables.js.map +1 -0
  573. package/dist/frontend/lowering/class-method-mutations.js +73 -35
  574. package/dist/frontend/lowering/class-method-mutations.js.map +1 -1
  575. package/dist/frontend/lowering/class-method-values.js +56 -10
  576. package/dist/frontend/lowering/class-method-values.js.map +1 -1
  577. package/dist/frontend/lowering/class-protocol-dispatch.js +24 -22
  578. package/dist/frontend/lowering/class-protocol-dispatch.js.map +1 -1
  579. package/dist/frontend/lowering/class-protocols.d.ts +55 -0
  580. package/dist/frontend/lowering/class-protocols.js +738 -22
  581. package/dist/frontend/lowering/class-protocols.js.map +1 -1
  582. package/dist/frontend/lowering/class-prototypes.d.ts +6 -0
  583. package/dist/frontend/lowering/class-prototypes.js +80 -18
  584. package/dist/frontend/lowering/class-prototypes.js.map +1 -1
  585. package/dist/frontend/lowering/class-runtime-statics.js +1 -1
  586. package/dist/frontend/lowering/class-runtime-statics.js.map +1 -1
  587. package/dist/frontend/lowering/class-static-data.js +2 -2
  588. package/dist/frontend/lowering/class-static-data.js.map +1 -1
  589. package/dist/frontend/lowering/class-to-primitive.d.ts +25 -0
  590. package/dist/frontend/lowering/class-to-primitive.js +261 -0
  591. package/dist/frontend/lowering/class-to-primitive.js.map +1 -0
  592. package/dist/frontend/lowering/class-unions.d.ts +25 -0
  593. package/dist/frontend/lowering/class-unions.js +102 -1
  594. package/dist/frontend/lowering/class-unions.js.map +1 -1
  595. package/dist/frontend/lowering/code-generation.d.ts +14 -0
  596. package/dist/frontend/lowering/code-generation.js +127 -0
  597. package/dist/frontend/lowering/code-generation.js.map +1 -0
  598. package/dist/frontend/lowering/coercions/function-adapters.d.ts +16 -2
  599. package/dist/frontend/lowering/coercions/function-adapters.js +145 -3
  600. package/dist/frontend/lowering/coercions/function-adapters.js.map +1 -1
  601. package/dist/frontend/lowering/coercions/structural-plans.js +25 -3
  602. package/dist/frontend/lowering/coercions/structural-plans.js.map +1 -1
  603. package/dist/frontend/lowering/coercions/structural.js +35 -3
  604. package/dist/frontend/lowering/coercions/structural.js.map +1 -1
  605. package/dist/frontend/lowering/coercions/unions.d.ts +15 -0
  606. package/dist/frontend/lowering/coercions/unions.js +57 -1
  607. package/dist/frontend/lowering/coercions/unions.js.map +1 -1
  608. package/dist/frontend/lowering/collection-ingestion.js +2 -2
  609. package/dist/frontend/lowering/collection-ingestion.js.map +1 -1
  610. package/dist/frontend/lowering/collection-narrowing.js +2 -4
  611. package/dist/frontend/lowering/collection-narrowing.js.map +1 -1
  612. package/dist/frontend/lowering/construction-escapes.js +8 -8
  613. package/dist/frontend/lowering/construction-escapes.js.map +1 -1
  614. package/dist/frontend/lowering/construction-escapes.test.js +4 -4
  615. package/dist/frontend/lowering/construction-escapes.test.js.map +1 -1
  616. package/dist/frontend/lowering/constructor-returns.d.ts +61 -0
  617. package/dist/frontend/lowering/constructor-returns.js +477 -0
  618. package/dist/frontend/lowering/constructor-returns.js.map +1 -0
  619. package/dist/frontend/lowering/containers/array-callback-call.js +1 -1
  620. package/dist/frontend/lowering/containers/array-callback-call.js.map +1 -1
  621. package/dist/frontend/lowering/containers/array-callbacks.d.ts +9 -0
  622. package/dist/frontend/lowering/containers/array-callbacks.js +266 -100
  623. package/dist/frontend/lowering/containers/array-callbacks.js.map +1 -1
  624. package/dist/frontend/lowering/containers/array-concat.js +1 -1
  625. package/dist/frontend/lowering/containers/array-concat.js.map +1 -1
  626. package/dist/frontend/lowering/containers/array-construction.d.ts +0 -1
  627. package/dist/frontend/lowering/containers/array-construction.js +51 -13
  628. package/dist/frontend/lowering/containers/array-construction.js.map +1 -1
  629. package/dist/frontend/lowering/containers/array-from-async.d.ts +19 -0
  630. package/dist/frontend/lowering/containers/array-from-async.js +427 -0
  631. package/dist/frontend/lowering/containers/array-from-async.js.map +1 -0
  632. package/dist/frontend/lowering/containers/array-methods.js +89 -77
  633. package/dist/frontend/lowering/containers/array-methods.js.map +1 -1
  634. package/dist/frontend/lowering/containers/array-pipelines.js +1 -0
  635. package/dist/frontend/lowering/containers/array-pipelines.js.map +1 -1
  636. package/dist/frontend/lowering/containers/bytes.js +161 -101
  637. package/dist/frontend/lowering/containers/bytes.js.map +1 -1
  638. package/dist/frontend/lowering/containers/callback-arguments.d.ts +9 -1
  639. package/dist/frontend/lowering/containers/callback-arguments.js +55 -5
  640. package/dist/frontend/lowering/containers/callback-arguments.js.map +1 -1
  641. package/dist/frontend/lowering/containers/collection-grouping.d.ts +7 -8
  642. package/dist/frontend/lowering/containers/collection-grouping.js +219 -27
  643. package/dist/frontend/lowering/containers/collection-grouping.js.map +1 -1
  644. package/dist/frontend/lowering/containers/collection-methods.js +81 -48
  645. package/dist/frontend/lowering/containers/collection-methods.js.map +1 -1
  646. package/dist/frontend/lowering/containers/dynamic-receivers.js +1 -1
  647. package/dist/frontend/lowering/containers/dynamic-receivers.js.map +1 -1
  648. package/dist/frontend/lowering/containers/exec-result-uses.js +2 -2
  649. package/dist/frontend/lowering/containers/exec-result-uses.js.map +1 -1
  650. package/dist/frontend/lowering/containers/for-of.d.ts +6 -0
  651. package/dist/frontend/lowering/containers/for-of.js +19 -19
  652. package/dist/frontend/lowering/containers/for-of.js.map +1 -1
  653. package/dist/frontend/lowering/containers/indexed-objects.js +142 -57
  654. package/dist/frontend/lowering/containers/indexed-objects.js.map +1 -1
  655. package/dist/frontend/lowering/containers/iterator-helpers.d.ts +53 -4
  656. package/dist/frontend/lowering/containers/iterator-helpers.js +1581 -462
  657. package/dist/frontend/lowering/containers/iterator-helpers.js.map +1 -1
  658. package/dist/frontend/lowering/containers/match-row-uses.d.ts +17 -0
  659. package/dist/frontend/lowering/containers/match-row-uses.js +264 -0
  660. package/dist/frontend/lowering/containers/match-row-uses.js.map +1 -0
  661. package/dist/frontend/lowering/containers/string-and-regexp.d.ts +14 -0
  662. package/dist/frontend/lowering/containers/string-and-regexp.js +419 -30
  663. package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
  664. package/dist/frontend/lowering/containers/string-replacement.js +1 -1
  665. package/dist/frontend/lowering/containers/string-replacement.js.map +1 -1
  666. package/dist/frontend/lowering/cycle-initialization.d.ts +4 -0
  667. package/dist/frontend/lowering/cycle-initialization.js +39 -0
  668. package/dist/frontend/lowering/cycle-initialization.js.map +1 -1
  669. package/dist/frontend/lowering/deferred-module-initializers.js +47 -43
  670. package/dist/frontend/lowering/deferred-module-initializers.js.map +1 -1
  671. package/dist/frontend/lowering/devirtualize.d.ts +1 -1
  672. package/dist/frontend/lowering/devirtualize.js +27 -7
  673. package/dist/frontend/lowering/devirtualize.js.map +1 -1
  674. package/dist/frontend/lowering/divergences.d.ts +0 -5
  675. package/dist/frontend/lowering/divergences.js +238 -128
  676. package/dist/frontend/lowering/divergences.js.map +1 -1
  677. package/dist/frontend/lowering/dyn-streams.d.ts +25 -0
  678. package/dist/frontend/lowering/dyn-streams.js +257 -0
  679. package/dist/frontend/lowering/dyn-streams.js.map +1 -0
  680. package/dist/frontend/lowering/error-methods.js +4 -1
  681. package/dist/frontend/lowering/error-methods.js.map +1 -1
  682. package/dist/frontend/lowering/error-name-order.d.ts +19 -0
  683. package/dist/frontend/lowering/error-name-order.js +93 -0
  684. package/dist/frontend/lowering/error-name-order.js.map +1 -0
  685. package/dist/frontend/lowering/expressions/array-literals.d.ts +21 -0
  686. package/dist/frontend/lowering/expressions/array-literals.js +703 -0
  687. package/dist/frontend/lowering/expressions/array-literals.js.map +1 -0
  688. package/dist/frontend/lowering/expressions/binary.d.ts +35 -0
  689. package/dist/frontend/lowering/expressions/binary.js +2483 -0
  690. package/dist/frontend/lowering/expressions/binary.js.map +1 -0
  691. package/dist/frontend/lowering/expressions/element-access.d.ts +31 -0
  692. package/dist/frontend/lowering/expressions/element-access.js +1797 -0
  693. package/dist/frontend/lowering/expressions/element-access.js.map +1 -0
  694. package/dist/frontend/lowering/expressions/evaluation-safety.js +4 -3
  695. package/dist/frontend/lowering/expressions/evaluation-safety.js.map +1 -1
  696. package/dist/frontend/lowering/expressions/hosted-narrowing.d.ts +38 -0
  697. package/dist/frontend/lowering/expressions/hosted-narrowing.js +160 -0
  698. package/dist/frontend/lowering/expressions/hosted-narrowing.js.map +1 -0
  699. package/dist/frontend/lowering/expressions/identifiers.d.ts +4 -0
  700. package/dist/frontend/lowering/expressions/identifiers.js +830 -0
  701. package/dist/frontend/lowering/expressions/identifiers.js.map +1 -0
  702. package/dist/frontend/lowering/expressions/keyed-field-targets.d.ts +40 -0
  703. package/dist/frontend/lowering/expressions/keyed-field-targets.js +226 -0
  704. package/dist/frontend/lowering/expressions/keyed-field-targets.js.map +1 -0
  705. package/dist/frontend/lowering/expressions/narrowing.d.ts +37 -0
  706. package/dist/frontend/lowering/expressions/narrowing.js +1322 -0
  707. package/dist/frontend/lowering/expressions/narrowing.js.map +1 -0
  708. package/dist/frontend/lowering/expressions/native-proxy.js +4 -4
  709. package/dist/frontend/lowering/expressions/native-proxy.js.map +1 -1
  710. package/dist/frontend/lowering/expressions/nullish-assignment.js +45 -0
  711. package/dist/frontend/lowering/expressions/nullish-assignment.js.map +1 -1
  712. package/dist/frontend/lowering/expressions/object-literals.d.ts +10 -0
  713. package/dist/frontend/lowering/expressions/object-literals.js +253 -85
  714. package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
  715. package/dist/frontend/lowering/expressions/optional-chains.d.ts +2 -1
  716. package/dist/frontend/lowering/expressions/optional-chains.js +91 -14
  717. package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
  718. package/dist/frontend/lowering/expressions/property-access.d.ts +110 -0
  719. package/dist/frontend/lowering/expressions/property-access.js +3544 -0
  720. package/dist/frontend/lowering/expressions/property-access.js.map +1 -0
  721. package/dist/frontend/lowering/expressions/relational.d.ts +28 -0
  722. package/dist/frontend/lowering/expressions/relational.js +1679 -0
  723. package/dist/frontend/lowering/expressions/relational.js.map +1 -0
  724. package/dist/frontend/lowering/expressions/typeof.d.ts +22 -0
  725. package/dist/frontend/lowering/expressions/typeof.js +538 -0
  726. package/dist/frontend/lowering/expressions/typeof.js.map +1 -0
  727. package/dist/frontend/lowering/expressions/union-fields.js +1 -1
  728. package/dist/frontend/lowering/expressions/union-fields.js.map +1 -1
  729. package/dist/frontend/lowering/expressions/updates.d.ts +21 -0
  730. package/dist/frontend/lowering/expressions/updates.js +780 -0
  731. package/dist/frontend/lowering/expressions/updates.js.map +1 -0
  732. package/dist/frontend/lowering/function-context.d.ts +10 -0
  733. package/dist/frontend/lowering/function-context.js +11 -1
  734. package/dist/frontend/lowering/function-context.js.map +1 -1
  735. package/dist/frontend/lowering/function-returns.js +52 -28
  736. package/dist/frontend/lowering/function-returns.js.map +1 -1
  737. package/dist/frontend/lowering/general-streams.d.ts +25 -0
  738. package/dist/frontend/lowering/general-streams.js +108 -0
  739. package/dist/frontend/lowering/general-streams.js.map +1 -0
  740. package/dist/frontend/lowering/generator-dynamic-dispatch.d.ts +7 -0
  741. package/dist/frontend/lowering/generator-dynamic-dispatch.js +172 -69
  742. package/dist/frontend/lowering/generator-dynamic-dispatch.js.map +1 -1
  743. package/dist/frontend/lowering/generic-functions.d.ts +39 -0
  744. package/dist/frontend/lowering/generic-functions.js +393 -75
  745. package/dist/frontend/lowering/generic-functions.js.map +1 -1
  746. package/dist/frontend/lowering/import-meta.js +2 -2
  747. package/dist/frontend/lowering/import-meta.js.map +1 -1
  748. package/dist/frontend/lowering/intern-tables.js +10 -9
  749. package/dist/frontend/lowering/intern-tables.js.map +1 -1
  750. package/dist/frontend/lowering/iterator-adapters.d.ts +19 -0
  751. package/dist/frontend/lowering/iterator-adapters.js +331 -3
  752. package/dist/frontend/lowering/iterator-adapters.js.map +1 -1
  753. package/dist/frontend/lowering/js-class-fields.d.ts +28 -0
  754. package/dist/frontend/lowering/js-class-fields.js +170 -0
  755. package/dist/frontend/lowering/js-class-fields.js.map +1 -0
  756. package/dist/frontend/lowering/js-dynamic-objects.d.ts +15 -0
  757. package/dist/frontend/lowering/js-dynamic-objects.js +299 -0
  758. package/dist/frontend/lowering/js-dynamic-objects.js.map +1 -0
  759. package/dist/frontend/lowering/js-dynamic-objects.test.d.ts +1 -0
  760. package/dist/frontend/lowering/js-dynamic-objects.test.js +35 -0
  761. package/dist/frontend/lowering/js-dynamic-objects.test.js.map +1 -0
  762. package/dist/frontend/lowering/json-require.d.ts +22 -0
  763. package/dist/frontend/lowering/json-require.js +131 -0
  764. package/dist/frontend/lowering/json-require.js.map +1 -0
  765. package/dist/frontend/lowering/key-order-witness.d.ts +44 -0
  766. package/dist/frontend/lowering/key-order-witness.js +641 -0
  767. package/dist/frontend/lowering/key-order-witness.js.map +1 -0
  768. package/dist/frontend/lowering/key-order-witness.test.d.ts +1 -0
  769. package/dist/frontend/lowering/key-order-witness.test.js +239 -0
  770. package/dist/frontend/lowering/key-order-witness.test.js.map +1 -0
  771. package/dist/frontend/lowering/lifetime-regions.js +7 -7
  772. package/dist/frontend/lowering/lifetime-regions.js.map +1 -1
  773. package/dist/frontend/lowering/lower-assert.js +61 -60
  774. package/dist/frontend/lowering/lower-assert.js.map +1 -1
  775. package/dist/frontend/lowering/lower-async-iteration.d.ts +10 -1
  776. package/dist/frontend/lowering/lower-async-iteration.js +34 -6
  777. package/dist/frontend/lowering/lower-async-iteration.js.map +1 -1
  778. package/dist/frontend/lowering/lower-builtin-values.d.ts +5 -0
  779. package/dist/frontend/lowering/lower-builtin-values.js +32 -3
  780. package/dist/frontend/lowering/lower-builtin-values.js.map +1 -1
  781. package/dist/frontend/lowering/lower-calls.js +1298 -452
  782. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  783. package/dist/frontend/lowering/lower-classes.d.ts +50 -3
  784. package/dist/frontend/lowering/lower-classes.js +1499 -456
  785. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  786. package/dist/frontend/lowering/lower-comptime.d.ts +4 -2
  787. package/dist/frontend/lowering/lower-comptime.js +111 -13
  788. package/dist/frontend/lowering/lower-comptime.js.map +1 -1
  789. package/dist/frontend/lowering/lower-console.js +13 -11
  790. package/dist/frontend/lowering/lower-console.js.map +1 -1
  791. package/dist/frontend/lowering/lower-dgram.d.ts +10 -0
  792. package/dist/frontend/lowering/lower-dgram.js +179 -8
  793. package/dist/frontend/lowering/lower-dgram.js.map +1 -1
  794. package/dist/frontend/lowering/lower-enums.js +113 -14
  795. package/dist/frontend/lowering/lower-enums.js.map +1 -1
  796. package/dist/frontend/lowering/lower-event-emitter.d.ts +16 -7
  797. package/dist/frontend/lowering/lower-event-emitter.js +268 -71
  798. package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
  799. package/dist/frontend/lowering/lower-event-target.js +2 -2
  800. package/dist/frontend/lowering/lower-event-target.js.map +1 -1
  801. package/dist/frontend/lowering/lower-expando.js +17 -13
  802. package/dist/frontend/lowering/lower-expando.js.map +1 -1
  803. package/dist/frontend/lowering/lower-exprs.d.ts +188 -186
  804. package/dist/frontend/lowering/lower-exprs.js +1493 -12407
  805. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  806. package/dist/frontend/lowering/lower-functions.js +68 -22
  807. package/dist/frontend/lowering/lower-functions.js.map +1 -1
  808. package/dist/frontend/lowering/lower-generators.d.ts +6 -0
  809. package/dist/frontend/lowering/lower-generators.js +29 -16
  810. package/dist/frontend/lowering/lower-generators.js.map +1 -1
  811. package/dist/frontend/lowering/lower-global-value.js +5 -1
  812. package/dist/frontend/lowering/lower-global-value.js.map +1 -1
  813. package/dist/frontend/lowering/lower-inspect.js +354 -99
  814. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  815. package/dist/frontend/lowering/lower-mixins.js +23 -20
  816. package/dist/frontend/lowering/lower-mixins.js.map +1 -1
  817. package/dist/frontend/lowering/lower-mock.d.ts +19 -2
  818. package/dist/frontend/lowering/lower-mock.js +557 -74
  819. package/dist/frontend/lowering/lower-mock.js.map +1 -1
  820. package/dist/frontend/lowering/lower-modules.js +268 -61
  821. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  822. package/dist/frontend/lowering/lower-namespaces.d.ts +6 -0
  823. package/dist/frontend/lowering/lower-namespaces.js +45 -33
  824. package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
  825. package/dist/frontend/lowering/lower-node-module.d.ts +16 -0
  826. package/dist/frontend/lowering/lower-node-module.js +147 -14
  827. package/dist/frontend/lowering/lower-node-module.js.map +1 -1
  828. package/dist/frontend/lowering/lower-server.d.ts +6 -6
  829. package/dist/frontend/lowering/lower-server.js +638 -105
  830. package/dist/frontend/lowering/lower-server.js.map +1 -1
  831. package/dist/frontend/lowering/lower-stdlib.d.ts +4 -0
  832. package/dist/frontend/lowering/lower-stdlib.js +151 -109
  833. package/dist/frontend/lowering/lower-stdlib.js.map +1 -1
  834. package/dist/frontend/lowering/lower-stmts.d.ts +28 -2
  835. package/dist/frontend/lowering/lower-stmts.js +1589 -398
  836. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  837. package/dist/frontend/lowering/lower-stream.d.ts +4 -3
  838. package/dist/frontend/lowering/lower-stream.js +714 -75
  839. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  840. package/dist/frontend/lowering/lower-test.d.ts +3 -0
  841. package/dist/frontend/lowering/lower-test.js +574 -100
  842. package/dist/frontend/lowering/lower-test.js.map +1 -1
  843. package/dist/frontend/lowering/lower-timers.js +80 -32
  844. package/dist/frontend/lowering/lower-timers.js.map +1 -1
  845. package/dist/frontend/lowering/lower-url.js +1 -1
  846. package/dist/frontend/lowering/lower-url.js.map +1 -1
  847. package/dist/frontend/lowering/lowerer.d.ts +409 -26
  848. package/dist/frontend/lowering/lowerer.js +1918 -305
  849. package/dist/frontend/lowering/lowerer.js.map +1 -1
  850. package/dist/frontend/lowering/lowerer.test.js +10 -4
  851. package/dist/frontend/lowering/lowerer.test.js.map +1 -1
  852. package/dist/frontend/lowering/maybe-promise.d.ts +46 -0
  853. package/dist/frontend/lowering/maybe-promise.js +249 -0
  854. package/dist/frontend/lowering/maybe-promise.js.map +1 -0
  855. package/dist/frontend/lowering/module-member-this.d.ts +3 -0
  856. package/dist/frontend/lowering/module-member-this.js +262 -0
  857. package/dist/frontend/lowering/module-member-this.js.map +1 -0
  858. package/dist/frontend/lowering/module-namespace-elements.js +1 -1
  859. package/dist/frontend/lowering/module-namespace-elements.js.map +1 -1
  860. package/dist/frontend/lowering/nan-coded-reads.d.ts +3 -0
  861. package/dist/frontend/lowering/nan-coded-reads.js +45 -32
  862. package/dist/frontend/lowering/nan-coded-reads.js.map +1 -1
  863. package/dist/frontend/lowering/narrowing-stability.d.ts +18 -3
  864. package/dist/frontend/lowering/narrowing-stability.js +104 -32
  865. package/dist/frontend/lowering/narrowing-stability.js.map +1 -1
  866. package/dist/frontend/lowering/native-ffi.js +11 -11
  867. package/dist/frontend/lowering/native-ffi.js.map +1 -1
  868. package/dist/frontend/lowering/null-prototype.d.ts +13 -0
  869. package/dist/frontend/lowering/null-prototype.js +33 -0
  870. package/dist/frontend/lowering/null-prototype.js.map +1 -0
  871. package/dist/frontend/lowering/object-factory-new.js +6 -8
  872. package/dist/frontend/lowering/object-factory-new.js.map +1 -1
  873. package/dist/frontend/lowering/private-brands.d.ts +46 -0
  874. package/dist/frontend/lowering/private-brands.js +265 -0
  875. package/dist/frontend/lowering/private-brands.js.map +1 -0
  876. package/dist/frontend/lowering/promise-executor-adapter.d.ts +11 -0
  877. package/dist/frontend/lowering/promise-executor-adapter.js +87 -0
  878. package/dist/frontend/lowering/promise-executor-adapter.js.map +1 -0
  879. package/dist/frontend/lowering/require-initialization.d.ts +32 -0
  880. package/dist/frontend/lowering/require-initialization.js +246 -0
  881. package/dist/frontend/lowering/require-initialization.js.map +1 -0
  882. package/dist/frontend/lowering/runtime-optional-bounds.js +7 -7
  883. package/dist/frontend/lowering/runtime-optional-bounds.js.map +1 -1
  884. package/dist/frontend/lowering/runtime-optional-elements.js +12 -12
  885. package/dist/frontend/lowering/runtime-optional-elements.js.map +1 -1
  886. package/dist/frontend/lowering/runtime-optional-guards.js +10 -10
  887. package/dist/frontend/lowering/runtime-optional-guards.js.map +1 -1
  888. package/dist/frontend/lowering/runtime-optional-guards.test.js +1 -1
  889. package/dist/frontend/lowering/runtime-optional-guards.test.js.map +1 -1
  890. package/dist/frontend/lowering/runtime-optional-ownership.js +10 -9
  891. package/dist/frontend/lowering/runtime-optional-ownership.js.map +1 -1
  892. package/dist/frontend/lowering/runtime-optional-provenance.js +2 -2
  893. package/dist/frontend/lowering/runtime-optional-provenance.js.map +1 -1
  894. package/dist/frontend/lowering/runtime-optional-records.d.ts +35 -0
  895. package/dist/frontend/lowering/runtime-optional-records.js +205 -32
  896. package/dist/frontend/lowering/runtime-optional-records.js.map +1 -1
  897. package/dist/frontend/lowering/runtime-optional-records.test.js +19 -1
  898. package/dist/frontend/lowering/runtime-optional-records.test.js.map +1 -1
  899. package/dist/frontend/lowering/sanitize-class-types.test.js +2 -2
  900. package/dist/frontend/lowering/split-consumers.js +4 -4
  901. package/dist/frontend/lowering/split-consumers.js.map +1 -1
  902. package/dist/frontend/lowering/static-function-names.d.ts +28 -0
  903. package/dist/frontend/lowering/static-function-names.js +212 -0
  904. package/dist/frontend/lowering/static-function-names.js.map +1 -0
  905. package/dist/frontend/lowering/static-this.js +6 -6
  906. package/dist/frontend/lowering/static-this.js.map +1 -1
  907. package/dist/frontend/lowering/strict-mode.d.ts +5 -0
  908. package/dist/frontend/lowering/strict-mode.js +31 -0
  909. package/dist/frontend/lowering/strict-mode.js.map +1 -0
  910. package/dist/frontend/lowering/string-index-bounds.js +10 -10
  911. package/dist/frontend/lowering/string-index-bounds.js.map +1 -1
  912. package/dist/frontend/lowering/string-index.d.ts +12 -0
  913. package/dist/frontend/lowering/string-index.js +72 -1
  914. package/dist/frontend/lowering/string-index.js.map +1 -1
  915. package/dist/frontend/lowering/surfaces.d.ts +15 -6
  916. package/dist/frontend/lowering/surfaces.js +278 -45
  917. package/dist/frontend/lowering/surfaces.js.map +1 -1
  918. package/dist/frontend/lowering/symbol-fields.d.ts +7 -0
  919. package/dist/frontend/lowering/symbol-fields.js +204 -36
  920. package/dist/frontend/lowering/symbol-fields.js.map +1 -1
  921. package/dist/frontend/lowering/symbol-methods.d.ts +2 -1
  922. package/dist/frontend/lowering/symbol-methods.js +24 -6
  923. package/dist/frontend/lowering/symbol-methods.js.map +1 -1
  924. package/dist/frontend/lowering/thread-slots.d.ts +13 -0
  925. package/dist/frontend/lowering/thread-slots.js +208 -0
  926. package/dist/frontend/lowering/thread-slots.js.map +1 -0
  927. package/dist/frontend/lowering/typed-arguments.d.ts +74 -0
  928. package/dist/frontend/lowering/typed-arguments.js +472 -0
  929. package/dist/frontend/lowering/typed-arguments.js.map +1 -0
  930. package/dist/frontend/lowering/union-retag.d.ts +8 -0
  931. package/dist/frontend/lowering/union-retag.js +27 -0
  932. package/dist/frontend/lowering/union-retag.js.map +1 -1
  933. package/dist/frontend/lowering/union-retag.test.js +24 -1
  934. package/dist/frontend/lowering/union-retag.test.js.map +1 -1
  935. package/dist/frontend/lowering/var-hoisting.js +6 -6
  936. package/dist/frontend/lowering/var-hoisting.js.map +1 -1
  937. package/dist/frontend/lowering/width-lift.d.ts +4 -0
  938. package/dist/frontend/mock-shapes.d.ts +5 -0
  939. package/dist/frontend/mock-shapes.js +39 -7
  940. package/dist/frontend/mock-shapes.js.map +1 -1
  941. package/dist/frontend/module-source-candidates.js +1 -1
  942. package/dist/frontend/module-source-candidates.js.map +1 -1
  943. package/dist/frontend/module-source-candidates.test.js +2 -1
  944. package/dist/frontend/module-source-candidates.test.js.map +1 -1
  945. package/dist/frontend/module-syntax.js +8 -8
  946. package/dist/frontend/module-syntax.js.map +1 -1
  947. package/dist/frontend/npm-static-bundled-chunks.d.ts +51 -0
  948. package/dist/frontend/npm-static-bundled-chunks.js +810 -0
  949. package/dist/frontend/npm-static-bundled-chunks.js.map +1 -0
  950. package/dist/frontend/npm-static-bundled-chunks.test.d.ts +1 -0
  951. package/dist/frontend/npm-static-bundled-chunks.test.js +287 -0
  952. package/dist/frontend/npm-static-bundled-chunks.test.js.map +1 -0
  953. package/dist/frontend/npm-static-bundled-cjs.js +24 -23
  954. package/dist/frontend/npm-static-bundled-cjs.js.map +1 -1
  955. package/dist/frontend/npm-static-bundled-esm.d.ts +9 -0
  956. package/dist/frontend/npm-static-bundled-esm.js +768 -0
  957. package/dist/frontend/npm-static-bundled-esm.js.map +1 -0
  958. package/dist/frontend/npm-static-bundled-esm.test.d.ts +1 -0
  959. package/dist/frontend/npm-static-bundled-esm.test.js +207 -0
  960. package/dist/frontend/npm-static-bundled-esm.test.js.map +1 -0
  961. package/dist/frontend/npm-static-cjs-exports-alias.d.ts +2 -0
  962. package/dist/frontend/npm-static-cjs-exports-alias.js +186 -0
  963. package/dist/frontend/npm-static-cjs-exports-alias.js.map +1 -0
  964. package/dist/frontend/npm-static-cjs-exports-alias.test.d.ts +1 -0
  965. package/dist/frontend/npm-static-cjs-exports-alias.test.js +73 -0
  966. package/dist/frontend/npm-static-cjs-exports-alias.test.js.map +1 -0
  967. package/dist/frontend/npm-static-cjs-exports-var.d.ts +2 -0
  968. package/dist/frontend/npm-static-cjs-exports-var.js +236 -0
  969. package/dist/frontend/npm-static-cjs-exports-var.js.map +1 -0
  970. package/dist/frontend/npm-static-declaration-syntax.js +102 -101
  971. package/dist/frontend/npm-static-declaration-syntax.js.map +1 -1
  972. package/dist/frontend/npm-static-prune.js +36 -24
  973. package/dist/frontend/npm-static-prune.js.map +1 -1
  974. package/dist/frontend/npm-static-rewrite-host.d.ts +4 -1
  975. package/dist/frontend/npm-static-rewrite-host.js +14 -3
  976. package/dist/frontend/npm-static-rewrite-host.js.map +1 -1
  977. package/dist/frontend/npm-static-rewrite-syntax.d.ts +19 -0
  978. package/dist/frontend/npm-static-rewrite-syntax.js +274 -101
  979. package/dist/frontend/npm-static-rewrite-syntax.js.map +1 -1
  980. package/dist/frontend/npm-static-subtyping.js +7 -9
  981. package/dist/frontend/npm-static-subtyping.js.map +1 -1
  982. package/dist/frontend/npm-static.d.ts +17 -1
  983. package/dist/frontend/npm-static.js +167 -16
  984. package/dist/frontend/npm-static.js.map +1 -1
  985. package/dist/frontend/npm-static.test.js +22 -1
  986. package/dist/frontend/npm-static.test.js.map +1 -1
  987. package/dist/frontend/pipeline.js +164 -26
  988. package/dist/frontend/pipeline.js.map +1 -1
  989. package/dist/frontend/pipeline.test.js +22 -1
  990. package/dist/frontend/pipeline.test.js.map +1 -1
  991. package/dist/frontend/program-analysis.d.ts +6 -1
  992. package/dist/frontend/program-analysis.js +7 -0
  993. package/dist/frontend/program-analysis.js.map +1 -1
  994. package/dist/frontend/program.d.ts +92 -2
  995. package/dist/frontend/program.js +1557 -254
  996. package/dist/frontend/program.js.map +1 -1
  997. package/dist/frontend/program.test.js +76 -6
  998. package/dist/frontend/program.test.js.map +1 -1
  999. package/dist/frontend/resolve.js +36 -2
  1000. package/dist/frontend/resolve.js.map +1 -1
  1001. package/dist/frontend/resolve.test.js +49 -0
  1002. package/dist/frontend/resolve.test.js.map +1 -1
  1003. package/dist/frontend/services.d.ts +20 -1
  1004. package/dist/frontend/services.js +40 -3
  1005. package/dist/frontend/services.js.map +1 -1
  1006. package/dist/frontend/services.test.js +2 -1
  1007. package/dist/frontend/services.test.js.map +1 -1
  1008. package/dist/frontend/threads-import.js +1 -1
  1009. package/dist/frontend/threads-import.js.map +1 -1
  1010. package/dist/frontend/tier-analysis.d.ts +71 -0
  1011. package/dist/frontend/tier-analysis.js +522 -0
  1012. package/dist/frontend/tier-analysis.js.map +1 -0
  1013. package/dist/frontend/ts7/api-conformance.d.ts +234 -0
  1014. package/dist/frontend/ts7/api-conformance.js +7 -0
  1015. package/dist/frontend/ts7/api-conformance.js.map +1 -0
  1016. package/dist/frontend/ts7/ast-guards.generated.js +2 -1
  1017. package/dist/frontend/ts7/ast-guards.generated.js.map +1 -1
  1018. package/dist/frontend/ts7/ast-node.d.ts +47 -25
  1019. package/dist/frontend/ts7/ast-node.js +64 -18
  1020. package/dist/frontend/ts7/ast-node.js.map +1 -1
  1021. package/dist/frontend/ts7/ast-node.test.js +36 -12
  1022. package/dist/frontend/ts7/ast-node.test.js.map +1 -1
  1023. package/dist/frontend/ts7/ast-types.d.ts +10 -3
  1024. package/dist/frontend/ts7/ast-types.generated.d.ts +39 -39
  1025. package/dist/frontend/ts7/ast.d.ts +1 -0
  1026. package/dist/frontend/ts7/ast.js +3 -2
  1027. package/dist/frontend/ts7/ast.js.map +1 -1
  1028. package/dist/frontend/ts7/checker-backend.d.ts +23 -0
  1029. package/dist/frontend/ts7/checker-backend.js +88 -0
  1030. package/dist/frontend/ts7/checker-backend.js.map +1 -0
  1031. package/dist/frontend/ts7/checker-backend.test.d.ts +1 -0
  1032. package/dist/frontend/ts7/checker-backend.test.js +63 -0
  1033. package/dist/frontend/ts7/checker-backend.test.js.map +1 -0
  1034. package/dist/frontend/ts7/checker-cache.d.ts +0 -3
  1035. package/dist/frontend/ts7/checker-cache.js +0 -6
  1036. package/dist/frontend/ts7/checker-cache.js.map +1 -1
  1037. package/dist/frontend/ts7/checker.d.ts +18 -11
  1038. package/dist/frontend/ts7/checker.js +42 -55
  1039. package/dist/frontend/ts7/checker.js.map +1 -1
  1040. package/dist/frontend/ts7/checker.test.js +10 -7
  1041. package/dist/frontend/ts7/checker.test.js.map +1 -1
  1042. package/dist/frontend/ts7/diagnostic.d.ts +19 -0
  1043. package/dist/frontend/ts7/diagnostic.js +22 -0
  1044. package/dist/frontend/ts7/diagnostic.js.map +1 -0
  1045. package/dist/frontend/ts7/node-functions.d.ts +8 -0
  1046. package/dist/frontend/ts7/node-functions.js +18 -0
  1047. package/dist/frontend/ts7/node-functions.js.map +1 -0
  1048. package/dist/frontend/ts7/program-host.d.ts +5 -1
  1049. package/dist/frontend/ts7/program-host.js +12 -0
  1050. package/dist/frontend/ts7/program-host.js.map +1 -1
  1051. package/dist/frontend/ts7/rpc-api.d.ts +5 -1
  1052. package/dist/frontend/ts7/rpc-api.js +8 -1
  1053. package/dist/frontend/ts7/rpc-api.js.map +1 -1
  1054. package/dist/frontend/ts7/semantic-checker.d.ts +13 -6
  1055. package/dist/frontend/ts7/semantic-checker.js +26 -8
  1056. package/dist/frontend/ts7/semantic-checker.js.map +1 -1
  1057. package/dist/frontend/ts7/semantic-checker.test.js +12 -9
  1058. package/dist/frontend/ts7/semantic-checker.test.js.map +1 -1
  1059. package/dist/frontend/ts7/semantic-model.d.ts +54 -24
  1060. package/dist/frontend/ts7/semantic-model.js +88 -16
  1061. package/dist/frontend/ts7/semantic-model.js.map +1 -1
  1062. package/dist/frontend/ts7/semantic-model.test.js +4 -4
  1063. package/dist/frontend/ts7/semantic-model.test.js.map +1 -1
  1064. package/dist/frontend/ts7/semantic-types.d.ts +7 -3
  1065. package/dist/frontend/ts7/semantic-types.js +1 -1
  1066. package/dist/frontend/ts7/semantic-types.js.map +1 -1
  1067. package/dist/frontend/ts7/session.d.ts +11 -11
  1068. package/dist/frontend/ts7/session.js +8 -5
  1069. package/dist/frontend/ts7/session.js.map +1 -1
  1070. package/dist/frontend/ts7/session.test.js +9 -5
  1071. package/dist/frontend/ts7/session.test.js.map +1 -1
  1072. package/dist/frontend/ts7/source-parser.d.ts +6 -2
  1073. package/dist/frontend/ts7/source-parser.js +24 -3
  1074. package/dist/frontend/ts7/source-parser.js.map +1 -1
  1075. package/dist/frontend/ts7/source-parser.test.js +38 -17
  1076. package/dist/frontend/ts7/source-parser.test.js.map +1 -1
  1077. package/dist/frontend/type-mapper.d.ts +122 -2
  1078. package/dist/frontend/type-mapper.js +2612 -695
  1079. package/dist/frontend/type-mapper.js.map +1 -1
  1080. package/dist/frontend/type-only-imports.d.ts +28 -0
  1081. package/dist/frontend/type-only-imports.js +122 -0
  1082. package/dist/frontend/type-only-imports.js.map +1 -0
  1083. package/dist/frontend/worker-target.js +8 -8
  1084. package/dist/frontend/worker-target.js.map +1 -1
  1085. package/dist/index.d.ts +3 -1
  1086. package/dist/index.js +47 -10
  1087. package/dist/index.js.map +1 -1
  1088. package/dist/ir/analysis.js +4 -2
  1089. package/dist/ir/analysis.js.map +1 -1
  1090. package/dist/ir/api.d.ts +1 -1
  1091. package/dist/ir/api.js +1 -1
  1092. package/dist/ir/api.js.map +1 -1
  1093. package/dist/ir/array-length-stability.d.ts +30 -0
  1094. package/dist/ir/array-length-stability.js +236 -0
  1095. package/dist/ir/array-length-stability.js.map +1 -0
  1096. package/dist/ir/array-length-stability.test.d.ts +1 -0
  1097. package/dist/ir/array-length-stability.test.js +113 -0
  1098. package/dist/ir/array-length-stability.test.js.map +1 -0
  1099. package/dist/ir/build.d.ts +2 -2
  1100. package/dist/ir/build.js +1 -1
  1101. package/dist/ir/build.js.map +1 -1
  1102. package/dist/ir/builtin-effects.js +139 -0
  1103. package/dist/ir/builtin-effects.js.map +1 -1
  1104. package/dist/ir/builtin-signatures.d.ts +1 -1
  1105. package/dist/ir/builtin-signatures.js +655 -25
  1106. package/dist/ir/builtin-signatures.js.map +1 -1
  1107. package/dist/ir/byte-numbers.js +3 -0
  1108. package/dist/ir/byte-numbers.js.map +1 -1
  1109. package/dist/ir/callback-specialization.d.ts +37 -0
  1110. package/dist/ir/callback-specialization.js +459 -0
  1111. package/dist/ir/callback-specialization.js.map +1 -0
  1112. package/dist/ir/callback-specialization.test.d.ts +1 -0
  1113. package/dist/ir/callback-specialization.test.js +208 -0
  1114. package/dist/ir/callback-specialization.test.js.map +1 -0
  1115. package/dist/ir/capture-values.d.ts +0 -1
  1116. package/dist/ir/capture-values.js +51 -40
  1117. package/dist/ir/capture-values.js.map +1 -1
  1118. package/dist/ir/constant-globals.test.js +1 -1
  1119. package/dist/ir/constant-tables.test.js +1 -1
  1120. package/dist/ir/field-values.test.js +1 -1
  1121. package/dist/ir/final-fields.test.js +1 -1
  1122. package/dist/ir/function-references.test.js +10 -1
  1123. package/dist/ir/function-references.test.js.map +1 -1
  1124. package/dist/ir/init-only-globals.test.js +1 -1
  1125. package/dist/ir/initializer-bindings.test.js +1 -1
  1126. package/dist/ir/int32-slots.d.ts +14 -0
  1127. package/dist/ir/int32-slots.js +119 -14
  1128. package/dist/ir/int32-slots.js.map +1 -1
  1129. package/dist/ir/int32-slots.test.js +29 -1
  1130. package/dist/ir/int32-slots.test.js.map +1 -1
  1131. package/dist/ir/integer-loop-facts.d.ts +16 -6
  1132. package/dist/ir/integer-loop-facts.js +143 -38
  1133. package/dist/ir/integer-loop-facts.js.map +1 -1
  1134. package/dist/ir/integer-loops.d.ts +1 -1
  1135. package/dist/ir/integer-loops.js +39 -9
  1136. package/dist/ir/integer-loops.js.map +1 -1
  1137. package/dist/ir/integer-loops.test.js +104 -0
  1138. package/dist/ir/integer-loops.test.js.map +1 -1
  1139. package/dist/ir/integer-ranges.d.ts +3 -0
  1140. package/dist/ir/integer-ranges.js +4 -6
  1141. package/dist/ir/integer-ranges.js.map +1 -1
  1142. package/dist/ir/integer-ranges.test.js +142 -1
  1143. package/dist/ir/integer-ranges.test.js.map +1 -1
  1144. package/dist/ir/intrinsic-signatures.js +6 -0
  1145. package/dist/ir/intrinsic-signatures.js.map +1 -1
  1146. package/dist/ir/ir.d.ts +234 -58
  1147. package/dist/ir/ir.js +123 -12
  1148. package/dist/ir/ir.js.map +1 -1
  1149. package/dist/ir/ir.test.js +10 -0
  1150. package/dist/ir/ir.test.js.map +1 -1
  1151. package/dist/ir/jsval.d.ts +8 -0
  1152. package/dist/ir/jsval.js +365 -0
  1153. package/dist/ir/jsval.js.map +1 -0
  1154. package/dist/ir/jsval.test.d.ts +1 -0
  1155. package/dist/ir/jsval.test.js +239 -0
  1156. package/dist/ir/jsval.test.js.map +1 -0
  1157. package/dist/ir/runtime-features.d.ts +150 -33
  1158. package/dist/ir/runtime-features.js +672 -339
  1159. package/dist/ir/runtime-features.js.map +1 -1
  1160. package/dist/ir/runtime-features.test.js +62 -0
  1161. package/dist/ir/runtime-features.test.js.map +1 -1
  1162. package/dist/ir/scalar-records.test.js +1 -1
  1163. package/dist/ir/self-captures.d.ts +33 -0
  1164. package/dist/ir/self-captures.js +245 -0
  1165. package/dist/ir/self-captures.js.map +1 -0
  1166. package/dist/ir/self-captures.test.d.ts +1 -0
  1167. package/dist/ir/self-captures.test.js +135 -0
  1168. package/dist/ir/self-captures.test.js.map +1 -0
  1169. package/dist/ir/serialize.d.ts +1 -1
  1170. package/dist/ir/serialize.js +7 -4
  1171. package/dist/ir/serialize.js.map +1 -1
  1172. package/dist/ir/tiers.d.ts +26 -0
  1173. package/dist/ir/tiers.js +101 -0
  1174. package/dist/ir/tiers.js.map +1 -0
  1175. package/dist/ir/tiers.test.d.ts +1 -0
  1176. package/dist/ir/tiers.test.js +140 -0
  1177. package/dist/ir/tiers.test.js.map +1 -0
  1178. package/dist/ir/traverse.js +107 -94
  1179. package/dist/ir/traverse.js.map +1 -1
  1180. package/dist/ir/traverse.test.js +33 -30
  1181. package/dist/ir/traverse.test.js.map +1 -1
  1182. package/dist/ir/unshare.js +65 -3
  1183. package/dist/ir/unshare.js.map +1 -1
  1184. package/dist/ir/unshare.test.js +1 -1
  1185. package/dist/ir/validate.js +220 -71
  1186. package/dist/ir/validate.js.map +1 -1
  1187. package/dist/ir/validate.test.js +64 -9
  1188. package/dist/ir/validate.test.js.map +1 -1
  1189. package/dist/library/fence-eval.test.js +1 -1
  1190. package/dist/library/int-infer.test.js +4 -4
  1191. package/dist/library/ir-policy.js +18 -0
  1192. package/dist/library/ir-policy.js.map +1 -1
  1193. package/dist/library/library-cache.d.ts +1 -0
  1194. package/dist/library/library-cache.js.map +1 -1
  1195. package/dist/library/library-cache.test.js +5 -5
  1196. package/dist/library/library-profile.d.ts +4 -4
  1197. package/dist/library/library-profile.js +35 -7
  1198. package/dist/library/library-profile.js.map +1 -1
  1199. package/dist/library/prepare.js +13 -1
  1200. package/dist/library/prepare.js.map +1 -1
  1201. package/dist/native/cli.js +5 -0
  1202. package/dist/native/cli.js.map +1 -1
  1203. package/dist/native/compiler.js +2 -2
  1204. package/dist/native/compiler.js.map +1 -1
  1205. package/dist/native/compiler.test.js +2 -2
  1206. package/dist/native/prepare.js +7 -0
  1207. package/dist/native/prepare.js.map +1 -1
  1208. package/dist/native/sanitizer.test.js +12 -0
  1209. package/dist/native/sanitizer.test.js.map +1 -1
  1210. package/dist/native/toolchain.d.ts +2 -0
  1211. package/dist/native/toolchain.js +10 -1
  1212. package/dist/native/toolchain.js.map +1 -1
  1213. package/dist/native/toolchain.test.js +39 -1
  1214. package/dist/native/toolchain.test.js.map +1 -1
  1215. package/dist/startup-cache.d.ts +1 -0
  1216. package/dist/startup-cache.js +1 -0
  1217. package/dist/startup-cache.js.map +1 -1
  1218. package/dist/wasm/base64.d.ts +5 -0
  1219. package/dist/wasm/base64.js +62 -0
  1220. package/dist/wasm/base64.js.map +1 -0
  1221. package/dist/wasm/binary.d.ts +36 -0
  1222. package/dist/wasm/binary.js +1976 -0
  1223. package/dist/wasm/binary.js.map +1 -0
  1224. package/dist/wasm/binary.test.d.ts +1 -0
  1225. package/dist/wasm/binary.test.js +190 -0
  1226. package/dist/wasm/binary.test.js.map +1 -0
  1227. package/dist/wasm/discover.d.ts +38 -0
  1228. package/dist/wasm/discover.js +377 -0
  1229. package/dist/wasm/discover.js.map +1 -0
  1230. package/dist/wasm/discover.test.d.ts +1 -0
  1231. package/dist/wasm/discover.test.js +24 -0
  1232. package/dist/wasm/discover.test.js.map +1 -0
  1233. package/dist/wasm/module.d.ts +151 -0
  1234. package/dist/wasm/module.js +575 -0
  1235. package/dist/wasm/module.js.map +1 -0
  1236. package/dist/wasm/translate.d.ts +48 -0
  1237. package/dist/wasm/translate.js +2129 -0
  1238. package/dist/wasm/translate.js.map +1 -0
  1239. package/dist/wasm/translate.test.d.ts +1 -0
  1240. package/dist/wasm/translate.test.js +207 -0
  1241. package/dist/wasm/translate.test.js.map +1 -0
  1242. package/package.json +21 -20
  1243. package/surface-manifest.json +332 -36
@@ -0,0 +1,3544 @@
1
+ /* Property reads (`a.b`): lowerExprInner's property-access branch, intrinsic and union properties, field reads and targets, and match-group reads. */
2
+ import * as ts from "../../ts7/adapter.js";
3
+ import { lowerHistogramProperty } from "../builtins/performance.js";
4
+ import { staticFunctionNameRead } from "../static-function-names.js";
5
+ import { typedArgumentsArity } from "../typed-arguments.js";
6
+ import { isThisParameter } from "../call-signatures.js";
7
+ import { localPrivateBrandClass } from "../private-brands.js";
8
+ import { PoisonError, jsFuncNameOf, neverTaintedJsType, own } from "../lowerer.js";
9
+ import { ARRAY_METHODS, MAP_METHODS, NARROW_FIRST, OBJECT_CALLABLE_VALUES, SET_METHODS, STDLIB_SURFACE, STRING_INDEX_METHODS, STR_METHODS, isChildSurfaceMember, stdlibGlobalNameOf, } from "../surfaces.js";
10
+ import { isGenericCallableMemberType, isLegacyUrlSymbol, isOsConstantsType, isParseArgsDynTypeName, } from "../../type-mapper.js";
11
+ import { BOOL, BYTES_ELEMENT_NAME, DYN, F64, NULL_T, SEARCH_PARAMS_T, STRING, SYMBOL_T, UNDEFINED_T, arrayOf, canBoxFuncIntoDyn, funcOf, isDynTypedRefType, isUnitType, typeEquals, typeKey, unionContainerArmsOk, } from "../../../ir/ir.js";
12
+ import { lowerNavigatorMember } from "../builtins/navigator.js";
13
+ import { NODE_COMPAT_VERSION } from "../builtins/process.js";
14
+ import { inlineNamespaceRequireOf, lowerWithInlineRequireInit, wholeExportValue, } from "../cjs-inline-require.js";
15
+ import { cjsAccessorCall, constInitializerOf, exactUnionWidening, hasClassPayload, lowerExpr, matchAllCallbackRegexOf, matchAllRegexOf, namedCaptureGroupsOfPattern, primitiveCtorClosure, recordKeyResultOk, representedClassFieldTarget, staticRegexPatternOf, } from "../lower-exprs.js";
16
+ import { cjsInFileExportGlobalOf, isCjsExportsIdentifier, lowerCjsExportsObjectValue, } from "../cjs-exports-object.js";
17
+ import { tscInteropDefaultValueOf } from "../cjs-tsc-interop.js";
18
+ import { lifetimeRegionMemberOf } from "../../experimental-import.js";
19
+ import { lowerInternTableProperty } from "../intern-tables.js";
20
+ import { lowerThreadSlotsProperty } from "../thread-slots.js";
21
+ import { builtinClassRefOf, runtimeClassValueOfType } from "../builtins/class-values.js";
22
+ import { lowerRuntimeConstructor, lowerRuntimeConstructorName, runtimeConstructorReceiver, } from "../builtins/runtime-constructor.js";
23
+ import { findGenericMethodOn, lowerStaticFieldRead } from "../lower-classes.js";
24
+ import { lowerClassPrototypeData } from "../class-prototypes.js";
25
+ import { lowerEnumAccess } from "../lower-enums.js";
26
+ import { hasOptionalChainGuard, isOptionalChainTail, isRequireMainFilename, } from "./optional-chains.js";
27
+ import { isCjsModuleGlobal, lowerNodeModuleProperty, lowerRequireMainProperty, } from "../lower-node-module.js";
28
+ import { dynUndefinedExpr, nodeThrowExpr, numLit, strLit, varRef } from "../../../ir/build.js";
29
+ import { TEMPORAL_GLOBAL } from "../../builtin-modules.js";
30
+ import { tryLowerExpression } from "./try-lower-expression.js";
31
+ import { cjsClassExprWholeExportOf, cjsExportAssignmentOf, cjsExportDiscardReason, isCjsExportTableLiteral, isCjsJsFile, isJsSourceFile, isModuleExportsAccess, isNodeEsmFile, locOf, } from "../../program.js";
32
+ import { ambientNsRootOf, ambientUndefReadType, ambientUndefVarRootOf, contextualUndefReadType, fenceEarlyNsMemberRef, nsMemberIdentOf, nsUndefRead, } from "../lower-namespaces.js";
33
+ import { expandoMemberRead } from "../lower-expando.js";
34
+ import { lowerProtocolPropertyRead } from "../class-protocol-dispatch.js";
35
+ import { lowerReadlineProperty } from "../builtins/readline.js";
36
+ import { lowerEventStaticProperty } from "../builtins/numbers.js";
37
+ import { lowerStreamProperty, lowerStreamStateProperty, streamSidesOf } from "../lower-stream.js";
38
+ import { lowerEventObjectProperty } from "../lower-event-target.js";
39
+ import { iteratorResultValueRead } from "../lower-generators.js";
40
+ import { lowerGlobalValue } from "../lower-global-value.js";
41
+ import { nullishGenericBindingUnitOf } from "../binding-analysis.js";
42
+ import { blockedBindingUseDiag } from "../../../diagnostics/diagnostic.js";
43
+ import { npmStaticPackageOfPath } from "../../npm-static.js";
44
+ import { importMetaField, isImportMeta } from "../import-meta.js";
45
+ import { builtinPrototypeMethod, lowerArrayIsArrayValue, lowerCheckedPredicateValue, lowerNumberParserValue, lowerObjectAssignValue, lowerStringCodesValue, } from "../lower-builtin-values.js";
46
+ import { lowerArrayFromValue } from "../containers/array-construction.js";
47
+ import { lowerNetAddressStaticRead } from "../builtins/net-address.js";
48
+ import { STATS_TYPE_TESTS } from "../builtins/filesystem.js";
49
+ import { arrayValueRead, arrayValueType } from "../array-values.js";
50
+ import { lowerClassMethodValue } from "../class-method-values.js";
51
+ import { objLitGenericFnInfoOf, objLitGenericFnNodeOf, requireObjLitGenericReceiver, } from "../generic-functions.js";
52
+ import { narrowStoredClassValue, structuralReadType } from "../class-unions.js";
53
+ import { InternalCompilerError } from "../../../errors.js";
54
+ import { lowerUnionFieldRead } from "./union-fields.js";
55
+ import { errorPropertyRead } from "../error-methods.js";
56
+ import { isSafeToRepeat } from "./evaluation-safety.js";
57
+ import { isZlibStreamMember, lowerZlibStreamBytesWritten } from "../builtins/compression.js";
58
+ import { isFsStreamMember, lowerFsStreamProperty } from "../builtins/fs-streams.js";
59
+ import { keyedFieldRead } from "./keyed-field-targets.js";
60
+ /** True when a property access names an ABSTRACT property declaration
61
+ * (`abstract p: number` — a PropertyDeclaration, not an accessor).
62
+ * These uses need concrete property dispatch because the base has no slot. */
63
+ export function abstractPropertyDeclOf(lowerer, expr) {
64
+ const sym = lowerer.checker.getSymbolAtLocation(expr.name);
65
+ if (!sym)
66
+ return false;
67
+ return sym.declarations.some((d) => ts.isPropertyDeclaration(d) &&
68
+ ts.getModifiers(d)?.some((m) => m.kind === ts.SyntaxKind.AbstractKeyword) === true);
69
+ }
70
+ /** A field declared by node:util's parseArgs checked-dynamic type family.
71
+ * Narrowing a ParseArgsToken exposes one anonymous union arm, so its alias
72
+ * identity no longer reaches mapType; declaration ancestry is the stable
73
+ * provenance check. */
74
+ /** The Uint8Array base64/hex prototype methods (ES2026) Node 24 lacks. */
75
+ const UINT8ARRAY_BASE64_METHODS = new Set([
76
+ "toBase64",
77
+ "toHex",
78
+ "setFromBase64",
79
+ "setFromHex",
80
+ ]);
81
+ /** `Uint8Array.prototype.<base64/hex method>` read off the global. */
82
+ function isUint8ArrayBase64Probe(lowerer, expr) {
83
+ if (!UINT8ARRAY_BASE64_METHODS.has(expr.name.text))
84
+ return false;
85
+ const proto = expr.expression;
86
+ return (ts.isPropertyAccessExpression(proto) &&
87
+ !proto.questionDotToken &&
88
+ proto.name.text === "prototype" &&
89
+ stdlibGlobalNameOf(lowerer, proto.expression) === "Uint8Array");
90
+ }
91
+ function isParseArgsDynProperty(lowerer, expr) {
92
+ const sym = lowerer.checker.getSymbolAtLocation(expr.name);
93
+ if (!sym)
94
+ return false;
95
+ return sym.declarations.some((d) => {
96
+ if (!lowerer.isStdlibFile(ts.getSourceFileOfNode(d)))
97
+ return false;
98
+ let inParseArgsType = false;
99
+ for (let node = d.parent; node; node = node.parent) {
100
+ if ((ts.isTypeAliasDeclaration(node) || ts.isInterfaceDeclaration(node)) &&
101
+ isParseArgsDynTypeName(node.name.text)) {
102
+ inParseArgsType = true;
103
+ }
104
+ if (ts.isModuleDeclaration(node) && ts.isStringLiteral(node.name)) {
105
+ return inParseArgsType && (node.name.text === "util" || node.name.text === "node:util");
106
+ }
107
+ }
108
+ return false;
109
+ });
110
+ }
111
+ function isStatFsDynProperty(lowerer, expr) {
112
+ if (!["type", "bsize", "blocks", "bfree", "bavail", "files", "ffree", "bigint"].includes(expr.name.text))
113
+ return false;
114
+ const symbol = lowerer.checker.getSymbolAtLocation(expr.name);
115
+ return (!!symbol &&
116
+ symbol.declarations.some((declaration) => {
117
+ if (!lowerer.isStdlibFile(ts.getSourceFileOfNode(declaration)))
118
+ return false;
119
+ const parent = declaration.parent;
120
+ if (!ts.isInterfaceDeclaration(parent))
121
+ return false;
122
+ if (expr.name.text === "bigint"
123
+ ? parent.name.text !== "StatFsOptions"
124
+ : !["StatsFsBase", "StatsFs", "BigIntStatsFs"].includes(parent.name.text))
125
+ return false;
126
+ for (let node = parent.parent; node; node = node.parent) {
127
+ if (ts.isModuleDeclaration(node) && ts.isStringLiteral(node.name))
128
+ return node.name.text === "fs" || node.name.text === "node:fs";
129
+ }
130
+ return false;
131
+ }));
132
+ }
133
+ export function lowerPropertyAccessExpr(lowerer, expr, loc) {
134
+ if (!expr.questionDotToken) {
135
+ const navigator = lowerNavigatorMember(lowerer, expr, NODE_COMPAT_VERSION);
136
+ if (navigator)
137
+ return navigator;
138
+ }
139
+ // `fn.name` on a function parameter of a generic instance keyed by
140
+ // its argument's static name (call-site specialization).
141
+ {
142
+ const staticName = staticFunctionNameRead(lowerer, expr);
143
+ if (staticName !== null)
144
+ return { kind: "strLit", value: staticName, type: STRING, loc };
145
+ }
146
+ // An IntervalHistogram's readings (min, max, mean, stddev, count, exceeds).
147
+ {
148
+ const reading = lowerHistogramProperty(lowerer, expr);
149
+ if (reading)
150
+ return reading;
151
+ }
152
+ // `.length` of a forwarded fixed tuple (a typed `arguments`, a tuple
153
+ // rest parameter, an alias of either): the signature's arity.
154
+ if (expr.name.text === "length" && !expr.questionDotToken) {
155
+ const arity = typedArgumentsArity(lowerer, expr.expression);
156
+ if (arity !== null)
157
+ return { kind: "numLit", value: arity, type: F64, loc };
158
+ }
159
+ // `require("./x").member` over a program module's export table: the
160
+ // module's %init at this position, then the member read exactly like
161
+ // a `const m = require("./x")` binding's (cjs-inline-require.ts).
162
+ if (!expr.questionDotToken) {
163
+ const req = inlineNamespaceRequireOf(lowerer, expr.expression);
164
+ if (req !== null && !lowerer.inlineRequireInitDone.has(req.call)) {
165
+ return lowerWithInlineRequireInit(lowerer, req, () => lowerExpr(lowerer, expr));
166
+ }
167
+ // `module.exports` compared by identity inside its own module, or
168
+ // refused by name as any other value (cjs-exports-object.ts).
169
+ if (expr.name.text === "exports") {
170
+ const exportsValue = lowerCjsExportsObjectValue(lowerer, expr);
171
+ if (exportsValue)
172
+ return exportsValue;
173
+ }
174
+ // tsc's `x_1.default` over a dependency whose whole export is one
175
+ // value: that value (cjs-tsc-interop.ts).
176
+ const interop = tscInteropDefaultValueOf(lowerer, expr);
177
+ if (interop !== null) {
178
+ const value = wholeExportValue(lowerer, interop.dep, expr);
179
+ if (value !== null)
180
+ return value;
181
+ }
182
+ }
183
+ {
184
+ const member = lifetimeRegionMemberOf(lowerer.program, expr, lowerer.experimentalFiles);
185
+ if (member !== null)
186
+ lowerer.noLowering(`LifetimeRegion.${member} (@scriptc/experimental) as a value`, expr, `call region.${member}(${member === "run" ? "fn" : ""}) directly`);
187
+ }
188
+ {
189
+ const table = lowerInternTableProperty(lowerer, expr);
190
+ if (table)
191
+ return table;
192
+ }
193
+ lowerThreadSlotsProperty(lowerer, expr);
194
+ // `EventEmitter.name`, `zlib.Gzip.name`, `C.name` over a builtin
195
+ // class alias.
196
+ if (expr.name.text === "name" && !expr.questionDotToken) {
197
+ const ref = builtinClassRefOf(lowerer, expr.expression);
198
+ if (ref !== null)
199
+ return { kind: "strLit", value: ref.name, type: STRING, loc };
200
+ }
201
+ // `x.constructor.name` and `x.constructor` on an instance of
202
+ // EventEmitter or a stream class (builtins/runtime-constructor.ts).
203
+ if (expr.name.text === "name" && !expr.questionDotToken) {
204
+ const ctor = runtimeConstructorReceiver(lowerer, expr.expression);
205
+ if (ctor)
206
+ return lowerRuntimeConstructorName(lowerer, ctor.receiver, loc);
207
+ }
208
+ {
209
+ const ctor = runtimeConstructorReceiver(lowerer, expr);
210
+ if (ctor)
211
+ return lowerRuntimeConstructor(lowerer, expr, ctor.info);
212
+ }
213
+ // `C.name` through a runtime-provided class VALUE (a `typeof Readable`
214
+ // parameter): the class object's stored name.
215
+ if (expr.name.text === "name" &&
216
+ !expr.questionDotToken &&
217
+ runtimeClassValueOfType(lowerer, lowerer.typeOf(expr.expression)) !== null) {
218
+ const read = lowerer.lowerFieldRead(expr);
219
+ if (read)
220
+ return read;
221
+ }
222
+ // Expando statics may still be absent even when JS inference sees
223
+ // the eventual assignment's scalar type. Preserve the checked value.
224
+ const staticField = lowerStaticFieldRead(lowerer, expr);
225
+ if (staticField)
226
+ return staticField;
227
+ const prototypeData = lowerClassPrototypeData(lowerer, expr);
228
+ if (prototypeData)
229
+ return prototypeData;
230
+ if (ts.isPropertyAccessExpression(expr.expression) && expr.expression.name.text === "prototype") {
231
+ const prototype = lowerClassPrototypeData(lowerer, expr.expression);
232
+ if (prototype)
233
+ return {
234
+ kind: "dynKeyGet",
235
+ value: prototype,
236
+ key: { kind: "strLit", value: expr.name.text, type: STRING, loc },
237
+ type: DYN,
238
+ loc,
239
+ };
240
+ }
241
+ // `super.x`: the base chain's GETTER, called directly (super
242
+ // dispatch is static in JS — never through the dynamic class).
243
+ // super.method() calls are routed at the call site; a bare super
244
+ // property read lands here.
245
+ if (expr.expression.kind === ts.SyntaxKind.SuperKeyword) {
246
+ return lowerer.lowerSuperAccessorRead(expr);
247
+ }
248
+ // Enum member reads (`E.A`) fold to their compile-time constants —
249
+ // claimed FIRST so no receiver-shaped path (records, the
250
+ // identifier fence on the enum object) sees them. lower-enums.ts.
251
+ {
252
+ const en = lowerEnumAccess(lowerer, expr);
253
+ if (en)
254
+ return en;
255
+ }
256
+ // `import.meta.<field>` — the file-backed ESM metadata that survives
257
+ // compilation as a constant. Only direct, identifier-named reads are
258
+ // claimed here; the bare meta object, computed access, writes, and
259
+ // unsupported members continue through the generic module-loader fence
260
+ // below. The source file is the module identity, so imported modules
261
+ // receive their own filename/dirname and only the entry receives main.
262
+ const importMeta = importMetaProperty(lowerer, expr);
263
+ if (importMeta)
264
+ return importMeta;
265
+ // `require.main.filename` / `require.main?.filename` — CommonJS
266
+ // entry-module identity: in a compiled binary require.main IS the
267
+ // entry module (never undefined in a CJS graph, so the chain's guard
268
+ // folds away), and its filename is the ENTRY file's real path —
269
+ // Node's exact value when the same tree runs in place, exactly the
270
+ // __filename stance. Checked BEFORE the optional-chain gate: the
271
+ // checker types the chain `string | undefined`, but the value is a
272
+ // compile-time string.
273
+ if (isRequireMainFilename(lowerer, expr)) {
274
+ return { kind: "strLit", value: lowerer.entry.fileName, type: STRING, loc };
275
+ }
276
+ const requireMain = lowerRequireMainProperty(lowerer, expr);
277
+ if (requireMain)
278
+ return requireMain;
279
+ const moduleProperty = lowerNodeModuleProperty(lowerer, expr);
280
+ if (moduleProperty)
281
+ return moduleProperty;
282
+ if (stdlibGlobalNameOf(lowerer, expr.expression) === "Symbol" &&
283
+ [
284
+ "iterator",
285
+ "asyncIterator",
286
+ "toStringTag",
287
+ "toPrimitive",
288
+ "hasInstance",
289
+ "isConcatSpreadable",
290
+ "match",
291
+ "matchAll",
292
+ "replace",
293
+ "search",
294
+ "split",
295
+ "species",
296
+ "unscopables",
297
+ "dispose",
298
+ "asyncDispose",
299
+ ].includes(expr.name.text)) {
300
+ return {
301
+ kind: "libCall",
302
+ fn: "sym.wellKnown",
303
+ args: [{ kind: "strLit", value: expr.name.text, type: STRING, loc }],
304
+ type: { kind: "symbol" },
305
+ loc,
306
+ };
307
+ }
308
+ if (lowerer.stdlibGlobalMember(expr, "Object") === "freeze") {
309
+ const name = "%builtin.Object.freeze";
310
+ if (!lowerer.liftedFns.some((fn) => fn.name === name))
311
+ lowerer.liftedFns.push({
312
+ name,
313
+ params: [{ localId: "value", name: "value", type: DYN }],
314
+ locals: [{ id: "value", name: "value", type: DYN, mutable: false }],
315
+ returnType: DYN,
316
+ body: [
317
+ {
318
+ kind: "return",
319
+ value: {
320
+ kind: "libCall",
321
+ fn: "dyn.freeze",
322
+ args: [varRef("value", DYN, loc)],
323
+ type: DYN,
324
+ loc,
325
+ },
326
+ loc,
327
+ },
328
+ ],
329
+ loc,
330
+ });
331
+ return { kind: "closure", fnName: name, captures: [], type: funcOf([DYN], DYN), loc };
332
+ }
333
+ // An Hmac has no copy() (Hash does): Node answers undefined, which
334
+ // `typeof mac.copy` feature checks read. TypeScript rejects the read.
335
+ if (expr.name.text === "copy" &&
336
+ lowerer.mapTypeOf(lowerer.typeOf(expr.expression))?.kind === "cryptoHmac") {
337
+ return {
338
+ kind: "seqExpr",
339
+ stmts: [{ kind: "exprStmt", expr: lowerer.lowerExpr(expr.expression), loc }],
340
+ result: dynUndefinedExpr(loc),
341
+ type: DYN,
342
+ loc,
343
+ };
344
+ }
345
+ if (lowerer.stdlibGlobalMember(expr, "globalThis") === "console") {
346
+ return { kind: "libCall", fn: "console.native", args: [], type: DYN, loc };
347
+ }
348
+ if (lowerer.stdlibGlobalMember(expr, "console") !== null) {
349
+ return {
350
+ kind: "dynKeyGet",
351
+ value: { kind: "libCall", fn: "console.native", args: [], type: DYN, loc },
352
+ key: { kind: "strLit", value: expr.name.text, type: STRING, loc },
353
+ type: DYN,
354
+ loc,
355
+ };
356
+ }
357
+ // Missing host globals (Bun/Deno capability probes) have no binding
358
+ // in a native program. Declared globals retain their own lowering;
359
+ // arbitrary global-object mutation remains fenced. Preserve a dyn
360
+ // undefined value so stored probes compose with optional calls.
361
+ if (stdlibGlobalNameOf(lowerer, expr.expression) === "globalThis" &&
362
+ !lowerer.checker.getPropertyOfType(lowerer.typeOf(expr.expression), expr.name.text)) {
363
+ return dynUndefinedExpr(loc);
364
+ }
365
+ // `Uint8Array.prototype.toBase64` and its siblings, the base64/hex
366
+ // feature probes libraries such as jose make: the methods are newer
367
+ // than Node 24, whose Uint8Array prototype answers undefined for them.
368
+ if (isUint8ArrayBase64Probe(lowerer, expr))
369
+ return dynUndefinedExpr(loc);
370
+ if (expr.questionDotToken && expr.name.text === "electron") {
371
+ const processProperty = lowerer.lowerProcessProperty(expr);
372
+ if (processProperty)
373
+ return processProperty;
374
+ }
375
+ // Optional chaining `a?.b`: the guard lowers here (a tag test around
376
+ // the plain property lowering below); the handled marker keeps this
377
+ // re-entrant dispatch from looping.
378
+ if (expr.questionDotToken && !lowerer.chainHandled.has(expr)) {
379
+ return lowerer.lowerOptionalChain(expr);
380
+ }
381
+ // `a?.b.c` — the tail of a chain whose token sits deeper: the whole
382
+ // tail short-circuits with the guard.
383
+ if (!expr.questionDotToken && isOptionalChainTail(lowerer, expr)) {
384
+ return lowerer.lowerOptionalChain(expr);
385
+ }
386
+ // Known Web handles retain their declared surface even when their
387
+ // storage uses checked values. Apply this before generic reads.
388
+ lowerer.fenceStaticAbortControllerMemberRead(expr);
389
+ lowerer.fenceStaticResponseMember(expr, "read");
390
+ lowerer.fenceStaticHeadersMember(expr, "read");
391
+ lowerer.fenceStaticReadableStreamMember(expr, "read");
392
+ // — reading off null/undefined — bridged catchably like everything
393
+ // at the boundary). `o?.x` arrives here too, through the chain
394
+ // lowering's re-dispatch (a questionDotToken past the gate above is
395
+ // always chain-handled; the receiver reads back as the chain's
396
+ // bound handle).
397
+ // `m.index` on a for-of-over-matchAll binding reads the companion-
398
+ // index array at this iteration's cursor — always a number: every
399
+ // drained row matched, so the lib's `.index` is never undefined
400
+ // here (lowerForOfMatchAll).
401
+ if (expr.name.text === "index" && !expr.questionDotToken && ts.isIdentifier(expr.expression)) {
402
+ const sym = lowerer.checker.getSymbolAtLocation(expr.expression);
403
+ const companion = sym !== undefined ? lowerer.matchAllIndexBindings.get(sym) : undefined;
404
+ if (companion !== undefined) {
405
+ return {
406
+ kind: "arrayGet",
407
+ arr: { kind: "varRef", localId: companion.idxsLocalId, type: arrayOf(F64), loc },
408
+ index: { kind: "varRef", localId: companion.curLocalId, type: F64, loc },
409
+ type: F64,
410
+ loc,
411
+ };
412
+ }
413
+ }
414
+ if ((expr.name.text === "index" || expr.name.text === "input") && !expr.questionDotToken) {
415
+ const represented = tryLowerExpression(lowerer, expr.expression);
416
+ if (represented &&
417
+ isMatchSliceType(lowerer, represented.type) &&
418
+ (lowerer.isStdlibMember(expr) || isJsSourceFile(ts.getSourceFileOfNode(expr)))) {
419
+ const recv = represented;
420
+ const key = { kind: "strLit", value: expr.name.text, type: STRING, loc };
421
+ // A plain slice answers from its match source without a dynamic copy.
422
+ const read = typeEquals(recv.type, arrayOf(STRING))
423
+ ? { kind: "libCall", fn: "regex.resultProp", args: [recv, key], type: DYN, loc }
424
+ : { kind: "dynKeyGet", value: lowerer.coerceToExpected(recv, DYN), key, type: DYN, loc };
425
+ return lowerer.maybeNarrow(read, expr);
426
+ }
427
+ }
428
+ // `m.groups` on a match result whose regex is statically known:
429
+ // the compile-time record projection over the honest slice (or
430
+ // Node's undefined when the pattern has no named groups) — see
431
+ // lowerMatchGroupsRead.
432
+ {
433
+ const g = lowerMatchGroupsRead(lowerer, expr);
434
+ if (g !== null)
435
+ return g;
436
+ }
437
+ // `arguments.length` in a TYPED function whose signature is
438
+ // FIXED-ARITY (no optional/default/rest parameters): tsc enforces
439
+ // exact arity at every call site and call/apply/bind indirection is
440
+ // fenced, so the actual count IS the declared count — a compile-time
441
+ // constant. Arrows don't bind `arguments` (the walk skips them,
442
+ // exactly JS's scoping); variable-arity signatures keep the fence
443
+ // (the count would need a hidden argc). The JS-source variadic
444
+ // `arguments` object (dynRest) was claimed at identifier lowering.
445
+ if (expr.name.text === "length" &&
446
+ !expr.questionDotToken &&
447
+ ts.isIdentifier(expr.expression) &&
448
+ expr.expression.text === "arguments" &&
449
+ !lowerer.ctx.argumentsLocal &&
450
+ ts.symbolNameOf(lowerer.typeOf(expr.expression).getSymbol()) === "IArguments" &&
451
+ lowerer.isStdlibSymbol(lowerer.typeOf(expr.expression).getSymbol())) {
452
+ let fn = expr.parent;
453
+ while (fn !== undefined &&
454
+ !ts.isFunctionDeclaration(fn) &&
455
+ !ts.isFunctionExpression(fn) &&
456
+ !ts.isMethodDeclaration(fn) &&
457
+ !ts.isConstructorDeclaration(fn) &&
458
+ !ts.isGetAccessorDeclaration(fn) &&
459
+ !ts.isSetAccessorDeclaration(fn)) {
460
+ fn = ts.isSourceFile(fn) ? undefined : fn.parent;
461
+ }
462
+ if (fn !== undefined) {
463
+ const fixedArity = fn.parameters.nodes.every((p) => p.questionToken === undefined &&
464
+ p.initializer === undefined &&
465
+ p.dotDotDotToken === undefined);
466
+ if (fixedArity) {
467
+ // A `this` parameter is type-only: callers never pass it.
468
+ return {
469
+ kind: "numLit",
470
+ value: fn.parameters.nodes.filter((p) => !isThisParameter(p)).length,
471
+ type: F64,
472
+ loc,
473
+ };
474
+ }
475
+ lowerer.unsupported("SC1090", expr, "'arguments.length' in functions with optional, default, or rest parameters (the count varies per call — a fixed-arity signature folds to a constant)");
476
+ }
477
+ }
478
+ // CommonJS namespace binding (`const lib = require("./lib.js")`):
479
+ // `lib.member` IS the member — the export table is alias plumbing,
480
+ // so the NAME resolves exactly like a bare identifier reference
481
+ // (resolveValueSymbol lands on the exporter's declaration and every
482
+ // existing path — globals, function values, classes — applies).
483
+ if (!expr.questionDotToken && lowerer.cjsLocalModuleBindingOf(expr.expression)) {
484
+ // A binding whose dep is a class-expression WHOLE export
485
+ // (`module.exports = class {…}`): the member surface is the
486
+ // CLASS's — `C.name` folds to NamedEvaluation's answer and own
487
+ // statics read their globals (lowerStaticFieldRead resolves the
488
+ // binding through the expression's own symbol). The plain
489
+ // member-name delegation below would resolve `name` against the
490
+ // stdlib var instead — a wrong VALUE, not a fence. Unknown
491
+ // members fall through to the delegation (expando statics ride
492
+ // their pre-registered export globals).
493
+ const viaClass = lowerStaticFieldRead(lowerer, expr);
494
+ if (viaClass)
495
+ return viaClass;
496
+ return lowerExpr(lowerer, expr.name);
497
+ }
498
+ // `module.exports` READ in a CommonJS file whose whole export IS a
499
+ // class expression (`module.exports = class …{}`): the read answers
500
+ // the class VALUE — `new module.exports()` inside the module is the
501
+ // requirer's `new C()` spelled locally. Top-level reads ABOVE the
502
+ // assignment fall through to their existing fences (Node still
503
+ // answers the original export object there); function bodies
504
+ // resolve unconditionally — they run after the module evaluated,
505
+ // the same approximation identifier exports already make. Every
506
+ // other module.exports read keeps its existing story.
507
+ if (!expr.questionDotToken &&
508
+ isModuleExportsAccess(expr) &&
509
+ isCjsJsFile(ts.getSourceFileOfNode(expr), lowerer.program)) {
510
+ const whole = cjsClassExprWholeExportOf(ts.getSourceFileOfNode(expr));
511
+ if (whole) {
512
+ let inBody = false;
513
+ for (let p = expr.parent; p !== undefined && !ts.isSourceFile(p); p = p.parent) {
514
+ if (ts.isFunctionLike(p) || ts.isClassDeclaration(p) || ts.isClassExpression(p)) {
515
+ inBody = true;
516
+ break;
517
+ }
518
+ }
519
+ if (inBody || ts.tokenStartOfNode(expr) > whole.stmt.end) {
520
+ return lowerer.classValueRef(lowerer.lowerClassExpressionInfo(whole.classExpr), expr);
521
+ }
522
+ }
523
+ }
524
+ // `module.exports.Sub` / `exports.Sub` READ in the same module: an
525
+ // EXPRESSION-valued member rides its pre-registered export global —
526
+ // exactly what requirers see through `require('./x').Sub`, and the
527
+ // global IS the storage every `exports.Sub =` statement assigns, so
528
+ // the read is Node's live member. Identifier-valued members have no
529
+ // global (pure alias plumbing) and fall through unchanged; write
530
+ // positions belong to the export-assignment machinery.
531
+ {
532
+ const writePos = ts.isBinaryExpression(expr.parent) &&
533
+ expr.parent.left === expr &&
534
+ expr.parent.operatorToken.kind === ts.SyntaxKind.EqualsToken;
535
+ const g = cjsInFileExportGlobalOf(lowerer, expr);
536
+ if (g && !writePos)
537
+ return { kind: "varRef", localId: g.id, type: g.type, loc };
538
+ }
539
+ // Namespace-qualified reads (`N.x`, `A.B.C.f`, import= alias
540
+ // chains): the member is a compile-time-known declaration of a
541
+ // lowered namespace block — it resolves exactly like a bare
542
+ // identifier reference (globals, function values, classes), guarded
543
+ // by the namespace source-order fences (lower-namespaces.ts).
544
+ if (!expr.questionDotToken) {
545
+ const nsMember = nsMemberIdentOf(lowerer, expr);
546
+ if (nsMember) {
547
+ const memberSym = lowerer.checker.getSymbolAtLocation(nsMember);
548
+ if (memberSym)
549
+ fenceEarlyNsMemberRef(lowerer, expr, memberSym);
550
+ return lowerExpr(lowerer, nsMember);
551
+ }
552
+ // Expando function members (`foo.bar` after `foo.bar = 12`): the
553
+ // member's module global (lower-expando.ts), before the ambient-
554
+ // namespace fence — a declare-namespace merge over a real function
555
+ // (`declare namespace Foo { var baz: number }` + `function Foo`)
556
+ // reads its assigned members, not the ambient ReferenceError.
557
+ {
558
+ const ex = expandoMemberRead(lowerer, expr);
559
+ if (ex)
560
+ return lowerer.maybeNarrow(ex, expr);
561
+ }
562
+ // An AMBIENT namespace receiver (`M.x` where only `declare
563
+ // namespace M` exists): the namespace object never exists at
564
+ // runtime — Node's exact catchable ReferenceError at the access,
565
+ // the ambient `declare const` stance.
566
+ const ambientRoot = ambientNsRootOf(lowerer, expr.expression);
567
+ if (ambientRoot !== null) {
568
+ const t = ambientUndefReadType(lowerer, expr);
569
+ if (t)
570
+ return nsUndefRead(lowerer, ambientRoot.text, expr, t);
571
+ }
572
+ }
573
+ // `exports.<name>` READS in a module whose export object was
574
+ // REPLACED (`module.exports = ...`): `exports` still references the
575
+ // ORIGINAL object — Node's aliasing rule — so when nothing ever
576
+ // attached this name to it (`exports.<name> =` nowhere in the
577
+ // file), the honest answer is undefined. tsc types the read off the
578
+ // REPLACEMENT (its CJS model is identity-blind), which is exactly
579
+ // the undiagnosed divergence this lowering closes. Reads in modules with
580
+ // real `exports.<name> =` attachments keep their fences.
581
+ {
582
+ const ex = lowerReplacedExportsRead(lowerer, expr);
583
+ if (ex)
584
+ return ex;
585
+ }
586
+ // `this.<name>` inside a CJS export-table getter: Node binds the
587
+ // receiver to module.exports — the read is the sibling getter's
588
+ // lifted call.
589
+ {
590
+ const tm = lowerCjsExportTableThisMember(lowerer, expr);
591
+ if (tm)
592
+ return tm;
593
+ }
594
+ // Property signatures of class-backed protocols read implementing
595
+ // classes' fields directly.
596
+ if (!hasOptionalChainGuard(expr.expression)) {
597
+ const typed = lowerProtocolPropertyRead(lowerer, expr);
598
+ if (typed)
599
+ return typed;
600
+ }
601
+ const handled = lowerer.lowerProcessEnvGet(expr) ??
602
+ lowerer.lowerServerProperty(expr) ??
603
+ // diagnostics_channel Channel receivers — name/hasSubscribers
604
+ // over the f64 channel handle.
605
+ lowerer.lowerDiagnosticsChannelProperty(expr) ??
606
+ // readline Interface receivers — the history and option members
607
+ // over the f64 interface handle.
608
+ lowerReadlineProperty(lowerer, expr) ??
609
+ // TracingChannel receivers — the five event channels and
610
+ // hasSubscribers over the f64 tracing handle.
611
+ lowerer.lowerTracingChannelProperty(expr) ??
612
+ lowerer.lowerTestCtxProperty(expr) ??
613
+ lowerer.lowerProcessProperty(expr) ??
614
+ lowerer.lowerProcessStreamProperty(expr) ??
615
+ lowerer.lowerFsConstantsProperty(expr) ??
616
+ // http2.constants.NGHTTP2_CANCEL (any constants-object spelling):
617
+ // the baked-literal table.
618
+ lowerer.lowerBuiltinConstantsProperty(expr) ??
619
+ // Builtin namespace imports (`path.sep`, `os.EOL`,
620
+ // `fs.constants.R_OK` where the root is `import * as ...`): the
621
+ // same constants and per-member fences as named builtin imports.
622
+ lowerer.lowerNamespaceBuiltinProperty(expr) ??
623
+ lowerer.lowerJsonProperty(expr) ??
624
+ lowerer.lowerErrorCodeProperty(expr) ??
625
+ lowerer.lowerNumberStaticProperty(expr) ??
626
+ lowerEventStaticProperty(lowerer, expr) ??
627
+ lowerer.lowerMathProperty(expr) ??
628
+ lowerer.lowerIntrinsicProperty(expr) ??
629
+ // The _readableState/_writableState scalar READS (the suite's
630
+ // asserts) — checked before the generic stream property surface:
631
+ // the inner access maps no type of its own.
632
+ lowerStreamStateProperty(lowerer, expr) ??
633
+ lowerStreamObjectProperty(lowerer, expr) ??
634
+ lowerEventObjectProperty(lowerer, expr) ??
635
+ lowerer.lowerUnionProperty(expr) ??
636
+ // A builtin constructor reached through another binding (`const D =
637
+ // Date; D.prototype`) holds its interned function value, which
638
+ // models only name, length and constructor: a static member or the
639
+ // prototype that no lowering above claimed keeps the SC2020 fence
640
+ // rather than reading undefined through the field and dynamic reads.
641
+ fenceBuiltinConstructorStaticRead(lowerer, expr) ??
642
+ lowerer.lowerFieldRead(expr);
643
+ // A union-typed field read narrows like an identifier when the
644
+ // checker has narrowed this use to one arm.
645
+ if (handled) {
646
+ if (handled.type.kind === "union" &&
647
+ lowerer.armTag(handled.type.unionId, UNDEFINED_T) >= 0 &&
648
+ handled.kind === "recordGet" &&
649
+ lowerer.isRuntimeOptionalField(handled.shapeId, handled.field))
650
+ return handled;
651
+ // A class field assigned a missing read: the checker narrows this
652
+ // read to the assigned value's bare type, but the stored undefined
653
+ // arm is real (`obj.n = bytes[i]; obj.n` is undefined in Node).
654
+ if (runtimeOptionalClassField(lowerer, handled, expr))
655
+ return handled;
656
+ return iteratorResultValueRead(lowerer, handled, expr) ?? lowerer.maybeNarrow(handled, expr);
657
+ }
658
+ // `globalThis.<name>` that no lowering above claimed
659
+ // (globalThis.crypto, globalThis.SubtleCrypto, globalThis.localStorage
660
+ // — the harness's capability-conditional knownGlobals adds): the
661
+ // PROPERTY spelling of the identifier chokepoint's JS rule — a stdlib
662
+ // global taken as a VALUE in a JavaScript source is the same opaque
663
+ // IDENTITY TOKEN the bare spelling answers (`globalThis.crypto` IS
664
+ // `crypto` — one global, one token, or identity flows through Sets
665
+ // and === would disagree between the two spellings). TypeScript
666
+ // sources keep the SC2020 member fence below, like the bare form.
667
+ if (!expr.questionDotToken &&
668
+ stdlibGlobalNameOf(lowerer, expr.expression) === "globalThis" &&
669
+ isJsSourceFile(ts.getSourceFileOfNode(expr))) {
670
+ const canonical = stdlibGlobalNameOf(lowerer, expr);
671
+ if (canonical !== null) {
672
+ if (canonical === "globalThis")
673
+ return lowerGlobalValue(lowerer, expr);
674
+ // Typed for the programs that name it, absent in Node 24.
675
+ if (canonical === TEMPORAL_GLOBAL)
676
+ return dynUndefinedExpr(loc);
677
+ if (canonical === "ArrayBuffer")
678
+ return { kind: "libCall", fn: "arrayBuffer.constructor", args: [], type: DYN, loc };
679
+ if (canonical === "fetch")
680
+ return { kind: "libCall", fn: "fetch.function", args: [], type: DYN, loc };
681
+ if (Object.values(BYTES_ELEMENT_NAME).includes(canonical))
682
+ return {
683
+ kind: "libCall",
684
+ fn: "bytes.constructor",
685
+ args: [{ kind: "strLit", value: canonical, type: STRING, loc }],
686
+ type: DYN,
687
+ loc,
688
+ };
689
+ return (builtinGlobalValueAt(lowerer, expr, canonical, loc, true) ?? {
690
+ kind: "strLit",
691
+ value: `[builtin ${canonical}]`,
692
+ type: STRING,
693
+ loc,
694
+ });
695
+ }
696
+ }
697
+ // A JS receiver whose CHECKER type has no mapping (`mustCallChecks
698
+ // .length` where the binding is an evolving any[] living as a
699
+ // checked-dynamic global): the stdlib member fence below would blame
700
+ // the unmappable checker type (`any[].length`), but the VALUE is a
701
+ // dyn node — lower the receiver first and read through the dyn keyed
702
+ // read (ARR answers length; everything else JS's own-property
703
+ // answer). Mapped receivers keep the fence-first order: their
704
+ // members' gaps are real surface gaps ([1,2].entries), not
705
+ // representation artifacts. `.length` on a receiver whose checker
706
+ // ARRAY type lowers to the checked-dynamic representation —
707
+ // `unknown[]`, the collapsed `(string | object)[]`, and the `any[]`
708
+ // an Array.isArray guard narrows a collapsed union to — is the checked-dynamic tree
709
+ // array's OWN length (a keyed read the ARR kind answers exactly),
710
+ // never an `Array.prototype` surface gap; both source languages.
711
+ // Prototype-method VALUE reads (`ps.map` unparenthesized) keep the
712
+ // fence-first order: a stored-member undefined would mis-answer
713
+ // them, and calls dispatch through the dyn method machinery
714
+ // instead.
715
+ if ((isJsSourceFile(ts.getSourceFileOfNode(expr)) &&
716
+ (lowerer.mapTypeOf(lowerer.typeOf(expr.expression)) === null ||
717
+ (lowerer.typeOf(expr.expression).flags & ts.TypeFlags.Never) !== 0 ||
718
+ // A never-tainted receiver type maps (never rides as f64) but
719
+ // its VALUE lowered checked-dynamic — same dyn read.
720
+ neverTaintedJsType(lowerer, expr.expression, lowerer.typeOf(expr.expression)))) ||
721
+ (expr.name.text === "length" &&
722
+ (lowerer.checkerAnyArray(expr.expression) ||
723
+ (lowerer.checker.isArrayType(lowerer.typeOf(expr.expression)) &&
724
+ lowerer.mapTypeOf(lowerer.typeOf(expr.expression))?.kind === "dyn")))) {
725
+ const recv = lowerer.lowerExpr(expr.expression);
726
+ if (recv.type.kind === "dyn") {
727
+ const key = {
728
+ kind: "strLit",
729
+ value: expr.name.text,
730
+ type: STRING,
731
+ loc: locOf(expr.name),
732
+ };
733
+ const opt = hasOptionalChainGuard(expr.expression);
734
+ return lowerer.maybeNarrow({
735
+ kind: "dynKeyGet",
736
+ key,
737
+ ...(opt ? { optional: true } : {}),
738
+ value: recv,
739
+ type: DYN,
740
+ loc,
741
+ }, expr);
742
+ }
743
+ if (expr.name.text === "length" &&
744
+ (recv.type.kind === "array" || recv.type.kind === "string")) {
745
+ return recv.type.kind === "array"
746
+ ? { kind: "arrIntrinsic", method: "length", receiver: recv, args: [], type: F64, loc }
747
+ : { kind: "strIntrinsic", method: "length", receiver: recv, args: [], type: F64, loc };
748
+ }
749
+ }
750
+ if (isJsSourceFile(ts.getSourceFileOfNode(expr)) && expr.name.text === "constructor") {
751
+ const receiver = tryLowerExpression(lowerer, expr.expression);
752
+ if (receiver?.type.kind === "dyn" ||
753
+ (receiver?.type.kind === "object" &&
754
+ !lowerer.classes.get(receiver.type.className)?.fields.has("constructor"))) {
755
+ return {
756
+ kind: "dynKeyGet",
757
+ value: lowerer.coerceToExpected(receiver, DYN),
758
+ key: { kind: "strLit", value: "constructor", type: STRING, loc },
759
+ type: DYN,
760
+ loc,
761
+ };
762
+ }
763
+ }
764
+ // A plain record's inherited Object.prototype members READ as values
765
+ // (`o.constructor`, `o.valueOf`, `({}).toString`, the isPlainObject and
766
+ // deep-equal idioms): the record boxes into its dynamic view, whose
767
+ // read answers the interned Object constructor and Object.prototype
768
+ // methods — the same values `Object` and `Object.prototype.valueOf`
769
+ // read, so identity comparisons are exact. Calls keep their own
770
+ // lowerings; a record declaring the name reads its field.
771
+ if (OBJECT_PROTOTYPE_VALUE_READS.has(expr.name.text) &&
772
+ !isCalleeOf(expr) &&
773
+ // `X.prototype.toString` keeps the builtin prototype-method lowering.
774
+ !(ts.isPropertyAccessExpression(expr.expression) && expr.expression.name.text === "prototype")) {
775
+ const receiver = tryLowerExpression(lowerer, expr.expression);
776
+ const name = expr.name.text;
777
+ const shape = receiver?.type.kind === "record" ? lowerer.shapes.get(receiver.type.shapeId) : undefined;
778
+ const info = receiver?.type.kind === "object" ? lowerer.classes.get(receiver.type.className) : undefined;
779
+ const inherits = receiver?.type.kind === "dyn" ||
780
+ (shape !== undefined && !shape.tuple && !shape.fields.some((field) => field.name === name)) ||
781
+ (info !== undefined &&
782
+ name !== "constructor" &&
783
+ !info.fields.has(name) &&
784
+ !lowerer.findMethodOn(info, name) &&
785
+ !lowerer.findMethodOn(info, `get:${name}`));
786
+ if (receiver !== null && receiver !== undefined && inherits) {
787
+ return {
788
+ kind: "dynKeyGet",
789
+ value: lowerer.coerceToExpected(receiver, DYN),
790
+ key: { kind: "strLit", value: name, type: STRING, loc },
791
+ type: DYN,
792
+ loc,
793
+ };
794
+ }
795
+ }
796
+ // `f.name` / `f.length` / own properties on a FUNCTION-typed JS
797
+ // value (the mustCall wrapper's function-instance members): read
798
+ // through the dyn box — the closure's own-property table answers
799
+ // first (defineProperties writes land there), then the box's
800
+ // best-effort static name and the declared arity; anything else is
801
+ // the own-property answer, undefined. Function.prototype METHOD
802
+ // names stay fenced (a stored-member undefined would mis-answer
803
+ // `f.call` as a value). Static callable values keep the existing TS fence; checked callable
804
+ // storage can expose its own name and length in both source languages.
805
+ if (!["apply", "bind", "call", "toString", "caller", "arguments"].includes(expr.name.text) &&
806
+ (isJsSourceFile(ts.getSourceFileOfNode(expr)) ||
807
+ expr.name.text === "name" ||
808
+ expr.name.text === "length" ||
809
+ expr.name.text === "constructor")) {
810
+ const probed = tryLowerExpression(lowerer, expr.expression);
811
+ // Inferred callable returns can use checked storage even when the
812
+ // checker still describes a function. Read its actual dyn value;
813
+ // the ambient Function member must not hide its own properties.
814
+ const receiverType = lowerer.typeOf(expr.expression);
815
+ const receiverSymbol = receiverType.getSymbol();
816
+ const checkedFunction = lowerer.checker.getCallSignatures(receiverType).length > 0 ||
817
+ (receiverSymbol !== undefined &&
818
+ ts.symbolName(receiverSymbol) === "Function" &&
819
+ lowerer.isStdlibSymbol(receiverSymbol));
820
+ if (probed?.type.kind === "dyn" && checkedFunction) {
821
+ const key = {
822
+ kind: "strLit",
823
+ value: expr.name.text,
824
+ type: STRING,
825
+ loc: locOf(expr.name),
826
+ };
827
+ const opt = hasOptionalChainGuard(expr.expression);
828
+ return lowerer.maybeNarrow({
829
+ kind: "dynKeyGet",
830
+ key,
831
+ value: probed,
832
+ ...(opt ? { optional: true } : {}),
833
+ type: DYN,
834
+ loc,
835
+ }, expr);
836
+ }
837
+ if ((isJsSourceFile(ts.getSourceFileOfNode(expr)) || expr.name.text === "constructor") &&
838
+ probed?.type.kind === "func" &&
839
+ canBoxFuncIntoDyn(probed.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) {
840
+ const fnName = jsFuncNameOf(expr.expression);
841
+ const boxed = {
842
+ kind: "dynFrom",
843
+ value: probed,
844
+ type: DYN,
845
+ ...(fnName !== null ? { fnName } : {}),
846
+ loc,
847
+ };
848
+ const key = {
849
+ kind: "strLit",
850
+ value: expr.name.text,
851
+ type: STRING,
852
+ loc: locOf(expr.name),
853
+ };
854
+ return lowerer.maybeNarrow({ kind: "dynKeyGet", key, value: boxed, type: DYN, loc }, expr);
855
+ }
856
+ }
857
+ // A NARROWED IteratorResult receiver (`if (!r.done) r.value` — the
858
+ // checker narrows to IteratorYieldResult/IteratorReturnResult, whose
859
+ // own type cannot map: the shared record shape needs BOTH channels):
860
+ // the receiver's LOWERED record still carries the field, so the read
861
+ // is an ordinary recordGet — maybeNarrow then bridges the union slot
862
+ // to the checker's narrowed arm, exactly like a union field read.
863
+ if (expr.name.text === "done" || expr.name.text === "value") {
864
+ const receiverType = lowerer.typeOf(expr.expression);
865
+ const recvSym = ts.symbolNameOf(receiverType.getAliasSymbol()) === "IteratorResult"
866
+ ? receiverType.getAliasSymbol()
867
+ : receiverType.getSymbol();
868
+ if (((recvSym !== undefined && ts.symbolName(recvSym) === "IteratorResult") ||
869
+ (recvSym !== undefined && ts.symbolName(recvSym) === "IteratorYieldResult") ||
870
+ (recvSym !== undefined && ts.symbolName(recvSym) === "IteratorReturnResult")) &&
871
+ recvSym.declarations.some((d) => (ts.isInterfaceDeclaration(d) || ts.isTypeAliasDeclaration(d)) &&
872
+ lowerer.isStdlibFile(ts.getSourceFileOfNode(d)))) {
873
+ const recv = lowerer.lowerExpr(expr.expression);
874
+ if (recv.type.kind === "dyn")
875
+ return lowerer.maybeNarrow({
876
+ kind: "dynKeyGet",
877
+ value: recv,
878
+ key: { kind: "strLit", value: expr.name.text, type: STRING, loc },
879
+ type: DYN,
880
+ loc,
881
+ }, expr);
882
+ if (recv.type.kind === "record") {
883
+ const shape = lowerer.shapes.get(recv.type.shapeId);
884
+ const field = shape?.fields.find((f) => f.name === expr.name.text);
885
+ if (field) {
886
+ const read = {
887
+ kind: "recordGet",
888
+ obj: recv,
889
+ shapeId: recv.type.shapeId,
890
+ field: field.name,
891
+ type: field.type,
892
+ loc,
893
+ };
894
+ return iteratorResultValueRead(lowerer, read, expr) ?? lowerer.maybeNarrow(read, expr);
895
+ }
896
+ }
897
+ }
898
+ }
899
+ // A chain rooted at an initializer-less ambient `declare const/var`
900
+ // whose declared type has NO mapping (mappable roots compose through
901
+ // the bare-read undefRead and never reach here): Node throws the
902
+ // catchable ReferenceError at the ROOT read before any member
903
+ // matters, so the whole access lowers to that throw — typed by the
904
+ // use site, or by the context it flows into (the throw never
905
+ // returns, so the dummy is never observed).
906
+ {
907
+ const ambientRoot = ambientUndefVarRootOf(lowerer, expr);
908
+ if (ambientRoot !== null) {
909
+ const t = ambientUndefReadType(lowerer, expr) ?? contextualUndefReadType(lowerer, expr);
910
+ if (t)
911
+ return nsUndefRead(lowerer, ambientRoot.text, expr, t);
912
+ }
913
+ }
914
+ // Checked-dynamic stdlib results retain ambient property symbols,
915
+ // including parseArgs tokens narrowed to anonymous union arms. Only
916
+ // members owned by these implemented families bypass the stdlib fence.
917
+ const segmentDataSymbol = lowerer.typeOf(expr.expression).getSymbol();
918
+ const segmentDataProperty = segmentDataSymbol !== undefined &&
919
+ ts.symbolName(segmentDataSymbol) === "SegmentData" &&
920
+ lowerer.isStdlibSymbol(segmentDataSymbol) &&
921
+ ["segment", "index", "input", "isWordLike"].includes(expr.name.text);
922
+ // os.constants members vary by platform (the declared groups list
923
+ // every platform's names): a number member reads as `number |
924
+ // undefined`, like an array element, and a group stays checked.
925
+ const osConstants = isOsConstantsType(lowerer.typeOf(expr.expression), lowerer);
926
+ if (isParseArgsDynProperty(lowerer, expr) ||
927
+ isStatFsDynProperty(lowerer, expr) ||
928
+ segmentDataProperty ||
929
+ osConstants ||
930
+ isLegacyUrlSymbol(lowerer.checker.getSymbolAtLocation(expr.name), lowerer)) {
931
+ const recv = lowerer.lowerExpr(expr.expression);
932
+ if (recv.type.kind === "dyn") {
933
+ const key = {
934
+ kind: "strLit",
935
+ value: expr.name.text,
936
+ type: STRING,
937
+ loc: locOf(expr.name),
938
+ };
939
+ const opt = hasOptionalChainGuard(expr.expression);
940
+ const read = {
941
+ kind: "dynKeyGet",
942
+ key,
943
+ ...(opt ? { optional: true } : {}),
944
+ value: recv,
945
+ type: DYN,
946
+ loc,
947
+ };
948
+ if (osConstants) {
949
+ return lowerer.mapTypeOf(lowerer.typeOf(expr))?.kind === "f64"
950
+ ? lowerer.coerceToExpected(read, lowerer.withUndefinedArm(F64))
951
+ : read;
952
+ }
953
+ return lowerer.maybeNarrow(read, expr);
954
+ }
955
+ }
956
+ // A member read through a NULLISH generic binding (`const i: I<A &
957
+ // B> = null as any; const _i: I<A> = i.something` — the receiver
958
+ // provably holds null/undefined forever): the read throws Node's
959
+ // exact TypeError at the access.
960
+ if (ts.isIdentifier(expr.expression) && expr.questionDotToken === undefined) {
961
+ const unit = nullishGenericBindingUnitOf(lowerer, lowerer.resolveValueSymbol(expr.expression));
962
+ if (unit !== null) {
963
+ const t = ambientUndefReadType(lowerer, expr) ?? contextualUndefReadType(lowerer, expr) ?? F64;
964
+ return nodeThrowExpr(1, "", `Cannot read properties of ${unit} (reading '${expr.name.text}')`, t, loc);
965
+ }
966
+ }
967
+ // A stdlib-declared member (`message` of an interface extending Error)
968
+ // on a catch binding narrowed to a structural type: the binding reads
969
+ // as its checked-dynamic value, so the member does too.
970
+ if (!expr.questionDotToken && lowerer.caughtLocalOf(expr.expression)) {
971
+ const recv = lowerer.lowerExpr(expr.expression);
972
+ if (recv.kind === "caughtToDyn") {
973
+ const read = {
974
+ kind: "dynKeyGet",
975
+ key: { kind: "strLit", value: expr.name.text, type: STRING, loc: locOf(expr.name) },
976
+ value: recv,
977
+ type: DYN,
978
+ loc,
979
+ };
980
+ const declared = lowerer.mapTypeOf(lowerer.typeOf(expr));
981
+ return declared && declared.kind !== "void" ? lowerer.coerceToExpected(read, declared) : read;
982
+ }
983
+ }
984
+ // The lib fence's PROPERTY chokepoint: a stdlib-declared member that
985
+ // no lowering above claimed ([1,2].entries, Math.SQRT2, Promise.all,
986
+ // re.exec as a value, ...) reports SC2020 here.
987
+ lowerer.stdlibMemberFence(expr);
988
+ // The npm chokepoint: a member on a package-typed receiver in a
989
+ // static build — attributed to the package, like every other site.
990
+ lowerer.npmMemberFence(expr);
991
+ // A property read rooted at a BLOCKED binding: the declaration
992
+ // carries the real diagnostic — the SC2004 cascade, not a generic
993
+ // "property access" rejection.
994
+ {
995
+ let root = expr.expression;
996
+ while (ts.isPropertyAccessExpression(root))
997
+ root = root.expression;
998
+ if (ts.isIdentifier(root) && lowerer.isBlockedBinding(lowerer.resolveValueSymbol(root))) {
999
+ lowerer.pushDiag(blockedBindingUseDiag(root.text, loc));
1000
+ throw new PoisonError();
1001
+ }
1002
+ }
1003
+ // Nothing claimed the member. Lower the RECEIVER before rejecting:
1004
+ // when the receiver itself is the blocker (`(await import(x)).y` —
1005
+ // the dynamic import is the unsupported part), ITS diagnostic is the
1006
+ // honest one, not a generic recitation about the outer dot. A
1007
+ // receiver that lowers cleanly means the MEMBER is the gap — name
1008
+ // the property and the receiver's type instead of "property access".
1009
+ const recvLowered = lowerer.lowerExpr(expr.expression);
1010
+ // A dyn receiver — JSON.parse's `any`, or `unknown` the checker
1011
+ // narrowed to `object` — reads through the dyn keyed read: member
1012
+ // or undefined (JS's own-property answer), throwing JS's TypeError
1013
+ // on undefined/null receivers unless an earlier `?.` guards the
1014
+ // chain. Scalar-narrowed occurrences bridge via maybeNarrow's
1015
+ // validated dynCheck as usual.
1016
+ if (recvLowered.type.kind === "dyn" ||
1017
+ (isJsSourceFile(ts.getSourceFileOfNode(expr)) &&
1018
+ (["f64", "bool", "bigint", "string", "symbol"].includes(recvLowered.type.kind) ||
1019
+ (recvLowered.type.kind === "union" && lowerer.dynConvertible(recvLowered.type))))) {
1020
+ const key = {
1021
+ kind: "strLit",
1022
+ value: expr.name.text,
1023
+ type: STRING,
1024
+ loc: locOf(expr.name),
1025
+ };
1026
+ const opt = hasOptionalChainGuard(expr.expression);
1027
+ return lowerer.maybeNarrow({
1028
+ kind: "dynKeyGet",
1029
+ key,
1030
+ ...(opt ? { optional: true } : {}),
1031
+ value: lowerer.coerceToExpected(recvLowered, DYN),
1032
+ type: DYN,
1033
+ loc,
1034
+ }, expr);
1035
+ }
1036
+ // The lowered receiver is a RECORD the checker spelled wider —
1037
+ // `s.match(re).groups.key` in a JS file: the checker says
1038
+ // `{ [key: string]: string } | undefined`, but the groups
1039
+ // projection already answered the record arm (its null trap
1040
+ // included). Declared fields read directly; an index-signature
1041
+ // shape serves undeclared keys through the overflow read, exactly
1042
+ // the dot-access rule on checker-spelled hybrids.
1043
+ if (recvLowered.type.kind === "record") {
1044
+ const recvShape = lowerer.shapes.get(recvLowered.type.shapeId);
1045
+ const field = recvShape?.fields.find((f) => f.name === expr.name.text);
1046
+ if (field) {
1047
+ return lowerer.maybeNarrow({
1048
+ kind: "recordGet",
1049
+ obj: recvLowered,
1050
+ shapeId: recvLowered.type.shapeId,
1051
+ field: field.name,
1052
+ type: field.type,
1053
+ loc,
1054
+ }, expr);
1055
+ }
1056
+ if (recvShape?.indexValue !== undefined && !recvShape.tuple) {
1057
+ return lowerer.maybeNarrow({
1058
+ kind: "recordKeyGet",
1059
+ obj: recvLowered,
1060
+ shapeId: recvLowered.type.shapeId,
1061
+ key: { kind: "strLit", value: expr.name.text, type: STRING, loc: locOf(expr.name) },
1062
+ overflowOnly: true,
1063
+ type: recvShape.indexValue,
1064
+ loc,
1065
+ }, expr);
1066
+ }
1067
+ // An inferred package-JS call specializes a parameter to the
1068
+ // caller's own record shape. Optional option names omitted by that
1069
+ // caller read undefined; the missing field is not a failed type
1070
+ // assertion. Known prototype members were handled/fenced above.
1071
+ if (recvShape &&
1072
+ !recvShape.tuple &&
1073
+ lowerer.implicitParamTypes !== null &&
1074
+ isJsSourceFile(ts.getSourceFileOfNode(expr)) &&
1075
+ npmStaticPackageOfPath(ts.getSourceFileOfNode(expr).fileName) !== null) {
1076
+ return {
1077
+ kind: "seqExpr",
1078
+ stmts: [{ kind: "exprStmt", expr: recvLowered, loc }],
1079
+ result: dynUndefinedExpr(loc),
1080
+ type: DYN,
1081
+ loc,
1082
+ };
1083
+ }
1084
+ }
1085
+ // An ABSTRACT property through an abstract-typed receiver: the
1086
+ // declaration is erased at runtime — Node defines no field for it,
1087
+ // each concrete subclass declares its OWN (at its own layout
1088
+ // position), so no shared base slot exists to read. Abstract
1089
+ // ACCESSORS are the supported spelling: they declare a vtable slot.
1090
+ if (recvLowered.type.kind === "object" && abstractPropertyDeclOf(lowerer, expr)) {
1091
+ lowerer.unsupported("SC1090", expr, `reading the abstract property '${expr.name.text}' through a '${lowerer.checker.typeToString(lowerer.typeOf(expr.expression))}'-typed receiver (abstract property declarations are erased at runtime, so no shared slot exists — type the receiver as the concrete class, or declare an abstract getter instead)`);
1092
+ }
1093
+ // Array reads may add an undefined arm even when the checker still
1094
+ // reports a class. Its property bag must remain reachable, while
1095
+ // an absent element takes the normal checked-value TypeError.
1096
+ const nativeReceiver = lowerer.stripUndefinedArm(recvLowered.type);
1097
+ if (ts.isPrivateIdentifier(expr.name) && recvLowered.type.kind === "object") {
1098
+ const field = lowerer.classes.get(recvLowered.type.className)?.fields.get(expr.name.text);
1099
+ if (field)
1100
+ return {
1101
+ kind: "fieldGet",
1102
+ obj: recvLowered,
1103
+ className: recvLowered.type.className,
1104
+ field: expr.name.text,
1105
+ type: field,
1106
+ loc,
1107
+ };
1108
+ }
1109
+ if (nativeReceiver.kind === "object" && nativeReceiver.className === "%Error") {
1110
+ return lowerer.maybeNarrow({
1111
+ kind: "dynKeyGet",
1112
+ value: lowerer.coerceToExpected(recvLowered, DYN),
1113
+ key: { kind: "strLit", value: expr.name.text, type: STRING, loc },
1114
+ type: DYN,
1115
+ loc,
1116
+ }, expr);
1117
+ }
1118
+ if (isDynTypedRefType(nativeReceiver)) {
1119
+ const info = lowerer.classes.get(nativeReceiver.className);
1120
+ if (info &&
1121
+ !info.def.runtime &&
1122
+ !info.builtinError &&
1123
+ !info.builtinEmitter &&
1124
+ !info.builtinStream) {
1125
+ return lowerer.maybeNarrow({
1126
+ kind: "dynKeyGet",
1127
+ value: lowerer.coerceToExpected(recvLowered, DYN),
1128
+ key: { kind: "strLit", value: expr.name.text, type: STRING, loc },
1129
+ type: DYN,
1130
+ loc,
1131
+ }, expr);
1132
+ }
1133
+ }
1134
+ // A member a JavaScript module attached to one of its functions
1135
+ // (`status.message = codes; module.exports = status`), read from
1136
+ // TypeScript: JavaScript stores such members on the function's own
1137
+ // property table (`fn.member = v` writes through the function's
1138
+ // checked-dynamic face), so the read takes the same path and enters
1139
+ // the static code at the type inference gave the member.
1140
+ if (recvLowered.type.kind === "func" && jsFunctionExpandoMember(lowerer, expr)) {
1141
+ const read = {
1142
+ kind: "dynKeyGet",
1143
+ value: lowerer.coerceToExpected(recvLowered, DYN),
1144
+ key: { kind: "strLit", value: expr.name.text, type: STRING, loc: locOf(expr.name) },
1145
+ type: DYN,
1146
+ loc,
1147
+ };
1148
+ const mapped = lowerer.mapTypeOf(lowerer.typeOf(expr));
1149
+ return mapped && mapped.kind !== "void" ? lowerer.coerceInto(expr, read, mapped) : read;
1150
+ }
1151
+ const asserted = assertedMemberRead(lowerer, expr, recvLowered, loc);
1152
+ if (asserted)
1153
+ return asserted;
1154
+ // A checker-`any` receiver whose value is a FRESH typed result of an
1155
+ // earlier step in the chain (`out.split(" ").length`, where split
1156
+ // extracted the string and answered a native string[]): the member read
1157
+ // goes through the boxed checked-dynamic value, as the method-call twin
1158
+ // does. The box copies; a call result has no other holder to observe it.
1159
+ if ((lowerer.typeOf(expr.expression).flags & ts.TypeFlags.Any) !== 0 &&
1160
+ isFreshCallResult(expr.expression) &&
1161
+ lowerer.dynConvertible(recvLowered.type)) {
1162
+ return lowerer.maybeNarrow({
1163
+ kind: "dynKeyGet",
1164
+ value: lowerer.coerceToExpected(recvLowered, DYN),
1165
+ key: { kind: "strLit", value: expr.name.text, type: STRING, loc },
1166
+ type: DYN,
1167
+ loc,
1168
+ }, expr);
1169
+ }
1170
+ lowerer.unsupported("SC1090", expr, `reading '${expr.name.text}' from a value of type '${lowerer.checker.typeToString(lowerer.typeOf(expr.expression))}'`);
1171
+ }
1172
+ /** A call expression, through parentheses: its value has no other holder. */
1173
+ function isFreshCallResult(node) {
1174
+ let e = node;
1175
+ while (ts.isParenthesizedExpression(e))
1176
+ e = e.expression;
1177
+ return ts.isCallExpression(e);
1178
+ }
1179
+ /** `(source as { repoName: string }).repoName` where the assertion names a
1180
+ * member some arms of the stored union of records do not declare: Node
1181
+ * reads the property off whichever object it is, so arms that declare it
1182
+ * answer their slot, and the others answer undefined (native records are
1183
+ * closed, so they cannot hold it). The result keeps that undefined arm
1184
+ * whatever the assertion claims; a consumer that needs the asserted type
1185
+ * checks it like any other narrowing. The arms that declare the member
1186
+ * must agree on its type. Null when the receiver is not such an
1187
+ * assertion over records, or no arm declares the member. */
1188
+ function assertedMemberRead(lowerer, expr, recv, loc) {
1189
+ let receiverNode = expr.expression;
1190
+ while (ts.isParenthesizedExpression(receiverNode))
1191
+ receiverNode = receiverNode.expression;
1192
+ if (!ts.isAsExpression(receiverNode) && !ts.isTypeAssertion(receiverNode))
1193
+ return null;
1194
+ if (recv.type.kind !== "union")
1195
+ return null;
1196
+ const unionId = recv.type.unionId;
1197
+ const arms = lowerer.unions.get(unionId)?.arms ?? [];
1198
+ const name = expr.name.text;
1199
+ let resultType = null;
1200
+ let records = 0;
1201
+ const declaring = [];
1202
+ const units = [];
1203
+ for (let tag = 0; tag < arms.length; tag++) {
1204
+ const arm = arms[tag];
1205
+ if (isUnitType(arm)) {
1206
+ units.push(tag);
1207
+ continue;
1208
+ }
1209
+ if (arm.kind !== "record")
1210
+ return null;
1211
+ records++;
1212
+ const shape = lowerer.shapes.get(arm.shapeId);
1213
+ if (!shape || shape.tuple || shape.indexValue)
1214
+ return null;
1215
+ const field = shape.fields.find((f) => f.name === name);
1216
+ if (!field)
1217
+ continue;
1218
+ // The declaring arms agree up to an undefined arm (`string` beside
1219
+ // `string | undefined`).
1220
+ const armResult = lowerer.withUndefinedArmOf(field.type);
1221
+ if (!armResult || (resultType && !typeEquals(resultType, armResult)))
1222
+ return null;
1223
+ resultType = armResult;
1224
+ declaring.push({ tag, shapeId: arm.shapeId, type: field.type });
1225
+ }
1226
+ if (!resultType || declaring.length === records)
1227
+ return null;
1228
+ const stable = lowerer.declareHiddenLocal("%assertedRecv", recv.type);
1229
+ const ref = () => ({ kind: "varRef", localId: stable.id, type: recv.type, loc });
1230
+ let result = lowerer.wrappedUndefined(resultType, loc);
1231
+ if (!result)
1232
+ return null;
1233
+ // A unit arm the checker narrowed away reads like Node would read it.
1234
+ for (const tag of units) {
1235
+ const unit = arms[tag].kind === "nullT" ? "null" : "undefined";
1236
+ result = {
1237
+ kind: "ternary",
1238
+ cond: { kind: "unionIsTag", unionId, tag, negated: false, value: ref(), type: BOOL, loc },
1239
+ then: nodeThrowExpr(1, "", `Cannot read properties of ${unit} (reading '${name}')`, resultType, loc),
1240
+ else_: result,
1241
+ type: resultType,
1242
+ loc,
1243
+ };
1244
+ }
1245
+ for (const { tag, shapeId, type: fieldType } of declaring) {
1246
+ const read = {
1247
+ kind: "recordGet",
1248
+ obj: { kind: "unionNarrow", unionId, tag, value: ref(), type: arms[tag], loc },
1249
+ shapeId,
1250
+ field: name,
1251
+ type: fieldType,
1252
+ loc,
1253
+ };
1254
+ result = {
1255
+ kind: "ternary",
1256
+ cond: { kind: "unionIsTag", unionId, tag, negated: false, value: ref(), type: BOOL, loc },
1257
+ then: lowerer.coerceToExpected(read, resultType),
1258
+ else_: result,
1259
+ type: resultType,
1260
+ loc,
1261
+ };
1262
+ }
1263
+ return {
1264
+ kind: "seqExpr",
1265
+ stmts: [{ kind: "varDecl", localId: stable.id, init: recv, loc }],
1266
+ result,
1267
+ type: resultType,
1268
+ loc,
1269
+ };
1270
+ }
1271
+ function importMetaProperty(lowerer, expr) {
1272
+ return isImportMeta(expr.expression) ? importMetaField(lowerer, expr, expr.name.text) : null;
1273
+ }
1274
+ /** The TypeError of a deferred-init field read that finds the field
1275
+ * unassigned where its declared type cannot hold undefined. */
1276
+ export const DEFERRED_READ_MESSAGE = "undefined is not representable in the target union (a value narrowed or asserted past it still held it)";
1277
+ /** Property access on a string or array receiver: `.length` lowers to the
1278
+ * matching intrinsic; a bare method reference (`const f = s.slice` — a
1279
+ * function value) is rejected with a specific message. Returns null for
1280
+ * other receivers (the generic property-access rejection applies). Both
1281
+ * the receiver type AND the ambient-file provenance of the member are
1282
+ * verified — the name alone proves nothing. */
1283
+ export function lowerIntrinsicProperty(lowerer, expr) {
1284
+ for (const name of ["String", "Number", "Boolean", "BigInt"]) {
1285
+ if (!lowerer.chainBlocked(expr) && lowerer.isStdlibGlobal(expr, name)) {
1286
+ return primitiveCtorClosure(lowerer, name, locOf(expr), isJsSourceFile(ts.getSourceFileOfNode(expr)));
1287
+ }
1288
+ }
1289
+ if (lowerer.stdlibGlobalMember(expr, "Reflect") === "ownKeys") {
1290
+ const value = lowerer.lowerNativeCallableValue({
1291
+ fn: "dyn.ownKeys",
1292
+ params: [DYN],
1293
+ result: DYN,
1294
+ valueParams: [{ mode: "required", type: DYN }],
1295
+ }, "Reflect.ownKeys", locOf(expr));
1296
+ return { kind: "dynFrom", value, fnName: "ownKeys", type: DYN, loc: locOf(expr) };
1297
+ }
1298
+ if (lowerer.chainBlocked(expr))
1299
+ return null;
1300
+ // Object.prototype.constructor: the Object constructor value.
1301
+ if (expr.name.text === "constructor" &&
1302
+ ts.isPropertyAccessExpression(expr.expression) &&
1303
+ lowerer.stdlibGlobalMember(expr.expression, "Object") === "prototype")
1304
+ return builtinGlobalValue("Object", locOf(expr));
1305
+ const builtinPrototype = builtinPrototypeMethod(lowerer, expr);
1306
+ if (builtinPrototype)
1307
+ return {
1308
+ kind: "libCall",
1309
+ fn: "dyn.builtinMethod",
1310
+ args: [
1311
+ { kind: "strLit", value: builtinPrototype, type: STRING, loc: locOf(expr) },
1312
+ { kind: "strLit", value: expr.name.text, type: STRING, loc: locOf(expr.name) },
1313
+ ],
1314
+ type: DYN,
1315
+ loc: locOf(expr),
1316
+ };
1317
+ if (ts.isPropertyAccessExpression(expr.expression) &&
1318
+ lowerer.stdlibGlobalMember(expr.expression, "Array") === "prototype") {
1319
+ return {
1320
+ kind: "dynKeyGet",
1321
+ value: {
1322
+ kind: "libCall",
1323
+ fn: "dyn.arrayPrototype",
1324
+ args: [],
1325
+ type: DYN,
1326
+ loc: locOf(expr.expression),
1327
+ },
1328
+ key: { kind: "strLit", value: expr.name.text, type: STRING, loc: locOf(expr.name) },
1329
+ type: DYN,
1330
+ loc: locOf(expr),
1331
+ };
1332
+ }
1333
+ if (expr.name.text === "apply" &&
1334
+ ts.isPropertyAccessExpression(expr.expression) &&
1335
+ lowerer.stdlibGlobalMember(expr.expression, "Function") === "prototype")
1336
+ return { kind: "libCall", fn: "dyn.functionApply", args: [], type: DYN, loc: locOf(expr) };
1337
+ if (lowerer.stdlibGlobalMember(expr, "Array") === "prototype")
1338
+ return { kind: "libCall", fn: "dyn.arrayPrototype", args: [], type: DYN, loc: locOf(expr) };
1339
+ if (lowerer.stdlibGlobalMember(expr, "Object") === "prototype")
1340
+ return { kind: "libCall", fn: "dyn.objectPrototype", args: [], type: DYN, loc: locOf(expr) };
1341
+ // Function.prototype as a VALUE (a prototype-chain link:
1342
+ // `Object.setPrototypeOf(F.prototype, Function.prototype)`): one
1343
+ // anonymous function answering undefined, length 0 — a zero-capture
1344
+ // closure of a compiler helper, so every read is the same function
1345
+ // (closure identity) and shares its property table. Reads through it
1346
+ // find the function members the checked runtime models for every
1347
+ // function (apply, constructor, name, length). Member forms keep their
1348
+ // own lowerings.
1349
+ if (lowerer.stdlibGlobalMember(expr, "Function") === "prototype") {
1350
+ const loc = locOf(expr);
1351
+ const name = "%dyn.functionPrototype";
1352
+ if (!lowerer.liftedFns.some((fn) => fn.name === name))
1353
+ lowerer.liftedFns.push({
1354
+ name,
1355
+ params: [],
1356
+ locals: [],
1357
+ returnType: DYN,
1358
+ body: [{ kind: "return", value: dynUndefinedExpr(loc), loc }],
1359
+ loc,
1360
+ });
1361
+ return {
1362
+ kind: "dynFrom",
1363
+ value: { kind: "closure", fnName: name, captures: [], type: funcOf([], DYN), loc },
1364
+ fnName: "",
1365
+ type: DYN,
1366
+ loc,
1367
+ };
1368
+ }
1369
+ if (lowerer.stdlibGlobalMember(expr, "Array") === "isArray")
1370
+ return lowerArrayIsArrayValue(lowerer, locOf(expr));
1371
+ if (lowerer.stdlibGlobalMember(expr, "Array") === "from")
1372
+ return lowerArrayFromValue(lowerer, locOf(expr));
1373
+ const stringMember = lowerer.stdlibGlobalMember(expr, "String");
1374
+ if (stringMember === "fromCharCode" || stringMember === "fromCodePoint")
1375
+ return lowerStringCodesValue(lowerer, stringMember, locOf(expr));
1376
+ const numberMember = lowerer.stdlibGlobalMember(expr, "Number");
1377
+ if (numberMember === "parseInt" || numberMember === "parseFloat")
1378
+ return lowerNumberParserValue(lowerer, numberMember, locOf(expr));
1379
+ if (lowerer.stdlibGlobalMember(expr, "Buffer") === "poolSize")
1380
+ return { kind: "libCall", fn: "buffer.poolSize", args: [], type: F64, loc: locOf(expr) };
1381
+ const netAddressStatic = lowerNetAddressStaticRead(lowerer, expr);
1382
+ if (netAddressStatic)
1383
+ return netAddressStatic;
1384
+ if (lowerer.stdlibGlobalMember(expr, "Buffer") === "isBuffer")
1385
+ return lowerCheckedPredicateValue(lowerer, "Buffer.isBuffer", "buffer", locOf(expr));
1386
+ if (lowerer.stdlibGlobalMember(expr, "Date") === "now")
1387
+ return lowerer.lowerNativeCallableValue({
1388
+ fn: "date.now",
1389
+ params: [],
1390
+ result: F64,
1391
+ valueParams: [],
1392
+ }, "Date.now", locOf(expr));
1393
+ if (stdlibGlobalNameOf(lowerer, expr.expression) === "Object") {
1394
+ if (expr.name.text === "assign")
1395
+ return lowerObjectAssignValue(lowerer, locOf(expr));
1396
+ const fn = own(OBJECT_CALLABLE_VALUES, expr.name.text);
1397
+ if (fn)
1398
+ return lowerer.lowerNativeCallableValue(fn, `Object.${expr.name.text}`, locOf(expr));
1399
+ }
1400
+ // A never-tainted JS receiver type lowered checked-dynamic
1401
+ // (neverTaintedJsType — `cmd.length` on `const cmd = ['pwd', []]`):
1402
+ // stand down so the dyn keyed read below the chain answers, instead
1403
+ // of an array libCall over a dyn receiver hitting the boundary fence.
1404
+ let kind = neverTaintedJsType(lowerer, expr.expression, lowerer.typeOf(expr.expression))
1405
+ ? undefined
1406
+ : lowerer.mapTypeOf(lowerer.typeOf(expr.expression))?.kind;
1407
+ // A checker-`any[]` receiver (the readonly-array Array.isArray quirk)
1408
+ // whose VALUE lowers to a real static array (maybeNarrow's isArray
1409
+ // bridge): `.length` and friends ride the array path on the lowered
1410
+ // value (re-lowering is pure IR construction).
1411
+ if (kind === undefined && lowerer.checkerAnyArray(expr.expression)) {
1412
+ const probe = lowerer.lowerExpr(expr.expression);
1413
+ if (probe.type.kind === "array")
1414
+ kind = "array";
1415
+ }
1416
+ if (kind !== "string" &&
1417
+ kind !== "array" &&
1418
+ kind !== "map" &&
1419
+ kind !== "set" &&
1420
+ kind !== "f64" &&
1421
+ kind !== "date" &&
1422
+ kind !== "regex" &&
1423
+ kind !== "url" &&
1424
+ kind !== "searchParams" &&
1425
+ kind !== "stats" &&
1426
+ kind !== "spawnRes" &&
1427
+ kind !== "child" &&
1428
+ kind !== "bytes" &&
1429
+ kind !== "symbol") {
1430
+ return null;
1431
+ }
1432
+ // child receivers also admit the user's own child-shaped interface
1433
+ // members (the NgrokChildProcess duck rule — see isChildSurfaceMember).
1434
+ // The EMPTY tuple `[]` rides the array REPRESENTATION (type-mapper.ts), but
1435
+ // its `length` member is the tuple's own synthesized property, not
1436
+ // Array.prototype's — provenance alone would refuse it. It reads the
1437
+ // runtime length (always 0) through the array intrinsic like any other
1438
+ // array; non-empty tuples never reach here (they map to records and
1439
+ // fold their arity constant on the record path).
1440
+ const tupleLengthOnArray = kind === "array" &&
1441
+ expr.name.text === "length" &&
1442
+ lowerer.checker.isTupleType(lowerer.checker.getBaseTypeOfLiteralType(lowerer.typeOf(expr.expression)));
1443
+ if (kind === "child"
1444
+ ? !isChildSurfaceMember(lowerer, expr)
1445
+ : !tupleLengthOnArray && !lowerer.isStdlibMember(expr))
1446
+ return null;
1447
+ const name = expr.name.text;
1448
+ if (kind === "array" && name === "constructor" && isJsSourceFile(ts.getSourceFileOfNode(expr))) {
1449
+ const receiver = lowerer.lowerExpr(expr.expression);
1450
+ if (receiver.type.kind === "dyn")
1451
+ return {
1452
+ kind: "dynKeyGet",
1453
+ value: receiver,
1454
+ key: { kind: "strLit", value: name, type: STRING, loc: locOf(expr) },
1455
+ type: DYN,
1456
+ loc: locOf(expr),
1457
+ };
1458
+ const result = {
1459
+ kind: "libCall",
1460
+ fn: "dyn.arrayConstructor",
1461
+ args: [],
1462
+ type: DYN,
1463
+ loc: locOf(expr),
1464
+ };
1465
+ return {
1466
+ kind: "seqExpr",
1467
+ stmts: [{ kind: "exprStmt", expr: receiver, loc: locOf(expr) }],
1468
+ result,
1469
+ type: DYN,
1470
+ loc: locOf(expr),
1471
+ };
1472
+ }
1473
+ const strictReceiver = (expected) => {
1474
+ const value = lowerer.lowerExpr(expr.expression);
1475
+ if (value.type.kind === "dyn") {
1476
+ if (isJsSourceFile(ts.getSourceFileOfNode(expr)) && name === "length")
1477
+ return value;
1478
+ return lowerer.coerceInto(expr.expression, value, expected);
1479
+ }
1480
+ return lowerer.runtimeOptionalPropertyReceiver(expr.expression, value, expected, name) ?? value;
1481
+ };
1482
+ if (kind === "child") {
1483
+ const loc = locOf(expr);
1484
+ // The lifecycle reads, Node's exact shapes (SEMANTICS.md pins the
1485
+ // matrix): pid is `number | undefined` (undefined = spawn failure),
1486
+ // exitCode `number | null` (null while running and after a signal
1487
+ // death; -errno once a spawn failure settled), killed the
1488
+ // sent-a-signal flag. The unions build type-directedly in the
1489
+ // backend (the spawnRes.status pattern); a checker-narrowed read
1490
+ // extracts through maybeNarrow like any union member.
1491
+ if (name === "pid") {
1492
+ const receiver = lowerer.lowerExpr(expr.expression);
1493
+ const type = { kind: "union", unionId: lowerer.unions.intern([F64, UNDEFINED_T]) };
1494
+ return { kind: "libCall", fn: "child.pid", args: [receiver], type, loc };
1495
+ }
1496
+ if (name === "exitCode") {
1497
+ const receiver = lowerer.lowerExpr(expr.expression);
1498
+ const type = { kind: "union", unionId: lowerer.unions.intern([F64, NULL_T]) };
1499
+ return { kind: "libCall", fn: "child.exitCode", args: [receiver], type, loc };
1500
+ }
1501
+ if (name === "killed") {
1502
+ const receiver = lowerer.lowerExpr(expr.expression);
1503
+ return { kind: "libCall", fn: "child.killed", args: [receiver], type: BOOL, loc };
1504
+ }
1505
+ if (name === "on" || name === "once" || name === "kill" || name === "unref") {
1506
+ lowerer.unsupported("SC1090", expr, `child methods as values (call '${name}' directly)`);
1507
+ }
1508
+ lowerer.noLowering(`ChildProcess.${name}`, expr, 'on/once("exit" | "close" | "error", cb), pid, exitCode, killed, kill(signal?), and unref() are the supported ChildProcess members', lowerer.checker.getSymbolAtLocation(expr.name));
1509
+ }
1510
+ if (kind === "spawnRes") {
1511
+ // The spawnSync-result reads. status is the interned `number | null`
1512
+ // union (null = signal death or spawn failure); stdout/stderr are
1513
+ // the captured utf8 strings — under @types/node WITHOUT the
1514
+ // {encoding: "utf8"} options argument the checker types them Buffer,
1515
+ // which is re-fenced here (the call site already said so).
1516
+ const loc = locOf(expr);
1517
+ if (name === "status") {
1518
+ // Always the interned `number | null` union; a checker-NARROWED
1519
+ // read (`missing.status === null ? ... : ${missing.status}`)
1520
+ // bridges through maybeNarrow like any union read.
1521
+ const receiver = lowerer.lowerExpr(expr.expression);
1522
+ const type = { kind: "union", unionId: lowerer.unions.intern([F64, NULL_T]) };
1523
+ const read = { kind: "libCall", fn: "spawnRes.status", args: [receiver], type, loc };
1524
+ return lowerer.maybeNarrow(read, expr);
1525
+ }
1526
+ if (name === "stdout" || name === "stderr") {
1527
+ if (lowerer.mapTypeOf(lowerer.typeOf(expr))?.kind !== "string") {
1528
+ lowerer.noLowering(`spawnSync's ${name} without the "utf8" encoding`, expr, 'Buffer captures are not representable — call spawnSync(cmd, args, { encoding: "utf8" }) so the outputs are strings');
1529
+ }
1530
+ const receiver = lowerer.lowerExpr(expr.expression);
1531
+ const fn = name === "stdout" ? "spawnRes.stdout" : "spawnRes.stderr";
1532
+ return { kind: "libCall", fn, args: [receiver], type: STRING, loc };
1533
+ }
1534
+ if (name === "error") {
1535
+ // Node's spawn-failure carrier: `Error | undefined` — a fresh
1536
+ // %Error ("spawnSync <file> ENOENT", `code` stamped) when the
1537
+ // spawn itself failed, the undefined arm otherwise. The libCall
1538
+ // always carries the interned union (the declared `error?: Error`),
1539
+ // and a checker-NARROWED read (`if (r.error) r.error.message`)
1540
+ // bridges through maybeNarrow like any union read.
1541
+ const receiver = lowerer.lowerExpr(expr.expression);
1542
+ const type = lowerer.withUndefinedArmOf({ kind: "object", className: "%Error" });
1543
+ if (!type)
1544
+ lowerer.badType(expr, lowerer.typeOf(expr));
1545
+ const read = { kind: "libCall", fn: "spawnRes.error", args: [receiver], type, loc };
1546
+ return lowerer.maybeNarrow(read, expr);
1547
+ }
1548
+ lowerer.noLowering(`SpawnSyncReturns.${name}`, expr, "status, stdout, stderr, and error are the supported spawnSync-result members", lowerer.checker.getSymbolAtLocation(expr.name));
1549
+ }
1550
+ if (kind === "stats") {
1551
+ if (name === "size") {
1552
+ const receiver = lowerer.lowerExpr(expr.expression);
1553
+ return { kind: "libCall", fn: "stats.size", args: [receiver], type: F64, loc: locOf(expr) };
1554
+ }
1555
+ if (Object.hasOwn(STATS_TYPE_TESTS, name)) {
1556
+ lowerer.unsupported("SC1090", expr, `Stats methods as values (call '${name}' directly)`);
1557
+ }
1558
+ lowerer.noLowering(`Stats.${name}`, expr, "isFile(), isDirectory(), isSymbolicLink(), isBlockDevice(), isCharacterDevice(), isFIFO(), isSocket(), dev, mode, nlink, uid, gid, rdev, blksize, ino, size, blocks, atimeMs, mtimeMs, ctimeMs, birthtimeMs, atime, mtime, ctime, and birthtime are the supported Stats members", lowerer.checker.getSymbolAtLocation(expr.name));
1559
+ }
1560
+ if (kind === "date") {
1561
+ const methods = new Set([
1562
+ "getTime",
1563
+ "valueOf",
1564
+ "toISOString",
1565
+ "getFullYear",
1566
+ "getUTCFullYear",
1567
+ "getMonth",
1568
+ "getUTCMonth",
1569
+ "getDate",
1570
+ "getUTCDate",
1571
+ "getDay",
1572
+ "getUTCDay",
1573
+ "getHours",
1574
+ "getUTCHours",
1575
+ "getMinutes",
1576
+ "getUTCMinutes",
1577
+ "getSeconds",
1578
+ "getUTCSeconds",
1579
+ "getMilliseconds",
1580
+ "getUTCMilliseconds",
1581
+ "getTimezoneOffset",
1582
+ ]);
1583
+ if (methods.has(name)) {
1584
+ lowerer.unsupported("SC1090", expr, `Date methods as values (call '${name}' directly)`);
1585
+ }
1586
+ lowerer.noLowering(`Date.prototype.${name}`, expr, "getTime(), valueOf(), toISOString(), the local/UTC calendar getters, and getTimezoneOffset() are supported; Date setters and locale/string formatters have no lowering", lowerer.checker.getSymbolAtLocation(expr.name));
1587
+ }
1588
+ if (kind === "symbol") {
1589
+ const loc = locOf(expr);
1590
+ // `.description`: the checker's `string | undefined` — undefined
1591
+ // exactly for the description-less Symbol()/Symbol(undefined) forms
1592
+ // (Symbol("") answers the EMPTY STRING arm, like Node). The interned
1593
+ // union builds in the backend from the runtime's +1-or-NULL answer
1594
+ // (the child.stdout pattern); a checker-narrowed read extracts
1595
+ // through maybeNarrow like any union member.
1596
+ if (name === "description") {
1597
+ const receiver = lowerer.coerceToExpected(lowerer.lowerExpr(expr.expression), SYMBOL_T);
1598
+ const type = { kind: "union", unionId: lowerer.unions.intern([STRING, UNDEFINED_T]) };
1599
+ return { kind: "libCall", fn: "sym.desc", args: [receiver], type, loc };
1600
+ }
1601
+ if (name === "toString" || name === "valueOf") {
1602
+ lowerer.unsupported("SC1090", expr, `symbol methods as values (call '${name}' directly)`);
1603
+ }
1604
+ lowerer.noLowering(`Symbol.prototype.${name}`, expr, "description and toString() are the supported symbol members", lowerer.checker.getSymbolAtLocation(expr.name));
1605
+ }
1606
+ if (kind === "url") {
1607
+ // The supported URL getters. Everything else the lib declares
1608
+ // (searchParams, setters-as-reads, ...) fences with the
1609
+ // member-qualified name and the supported list. `host` is the WHATWG
1610
+ // serialization: lowercased hostname, `:port` appended exactly when
1611
+ // a non-default port is present (scr_url_host — Node-exact,
1612
+ // opaque-path URLs answer ""); `hostname` is the stored port-less
1613
+ // host field verbatim, including IPv6 brackets.
1614
+ if (name === "protocol" ||
1615
+ name === "origin" ||
1616
+ name === "username" ||
1617
+ name === "password" ||
1618
+ name === "pathname" ||
1619
+ name === "href" ||
1620
+ name === "host" ||
1621
+ name === "hostname" ||
1622
+ name === "port" ||
1623
+ name === "search" ||
1624
+ name === "hash") {
1625
+ const receiver = lowerer.lowerExpr(expr.expression);
1626
+ const fn = name === "protocol"
1627
+ ? "url.protocol"
1628
+ : name === "origin"
1629
+ ? "url.origin"
1630
+ : name === "username"
1631
+ ? "url.username"
1632
+ : name === "password"
1633
+ ? "url.password"
1634
+ : name === "pathname"
1635
+ ? "url.pathname"
1636
+ : name === "host"
1637
+ ? "url.host"
1638
+ : name === "hostname"
1639
+ ? "url.hostname"
1640
+ : name === "port"
1641
+ ? "url.port"
1642
+ : name === "search"
1643
+ ? "url.search"
1644
+ : name === "hash"
1645
+ ? "url.hash"
1646
+ : "url.href";
1647
+ return { kind: "libCall", fn, args: [receiver], type: STRING, loc: locOf(expr) };
1648
+ }
1649
+ // `u.searchParams`: the LIVE cached view (one identity per URL —
1650
+ // mutations through it re-serialize into the URL's query, so href
1651
+ // reflects immediately; Node's binding exactly).
1652
+ if (name === "searchParams") {
1653
+ const receiver = lowerer.lowerExpr(expr.expression);
1654
+ return {
1655
+ kind: "libCall",
1656
+ fn: "url.searchParams",
1657
+ args: [receiver],
1658
+ type: SEARCH_PARAMS_T,
1659
+ loc: locOf(expr),
1660
+ };
1661
+ }
1662
+ if (name === "toString" || name === "toJSON") {
1663
+ lowerer.unsupported("SC1090", expr, `URL methods as values (call '${name}' directly)`);
1664
+ }
1665
+ lowerer.noLowering(`URL.${name}`, expr, "protocol, origin, username, password, pathname, href, host, hostname, port, search, hash, searchParams, and toString() are the supported URL members", lowerer.checker.getSymbolAtLocation(expr.name));
1666
+ }
1667
+ if (kind === "searchParams") {
1668
+ const SEARCH_PARAMS_METHODS = new Set([
1669
+ "get",
1670
+ "getAll",
1671
+ "set",
1672
+ "append",
1673
+ "delete",
1674
+ "has",
1675
+ "sort",
1676
+ "toString",
1677
+ "forEach",
1678
+ "keys",
1679
+ "values",
1680
+ "entries",
1681
+ ]);
1682
+ // The one data property; every method lowers at its CALL
1683
+ // (lowerSearchParamsMethodCall) — bare method references fence.
1684
+ if (name === "size") {
1685
+ const receiver = lowerer.lowerExpr(expr.expression);
1686
+ return { kind: "libCall", fn: "sp.size", args: [receiver], type: F64, loc: locOf(expr) };
1687
+ }
1688
+ if (SEARCH_PARAMS_METHODS.has(name)) {
1689
+ lowerer.unsupported("SC1090", expr, `URLSearchParams methods as values (call '${name}' directly)`);
1690
+ }
1691
+ lowerer.noLowering(`URLSearchParams.${name}`, expr, "get, getAll, set, append, delete, has, sort, size, toString(), forEach, and for-of iteration are the supported URLSearchParams members", lowerer.checker.getSymbolAtLocation(expr.name));
1692
+ }
1693
+ if (kind === "regex") {
1694
+ if (name === "lastIndex") {
1695
+ return {
1696
+ kind: "regexIntrinsic",
1697
+ method: "lastIndex",
1698
+ receiver: strictReceiver({ kind: "regex" }),
1699
+ args: [],
1700
+ type: F64,
1701
+ loc: locOf(expr),
1702
+ };
1703
+ }
1704
+ if (name === "source" || name === "flags") {
1705
+ const receiver = strictReceiver({ kind: "regex" });
1706
+ return {
1707
+ kind: "regexIntrinsic",
1708
+ method: name,
1709
+ receiver,
1710
+ args: [],
1711
+ type: STRING,
1712
+ loc: locOf(expr),
1713
+ };
1714
+ }
1715
+ // The flag getters answer whether `flags` holds the flag's letter.
1716
+ const flag = REGEX_FLAG_GETTERS.get(name);
1717
+ if (flag !== undefined) {
1718
+ const loc = locOf(expr);
1719
+ const flags = {
1720
+ kind: "regexIntrinsic",
1721
+ method: "flags",
1722
+ receiver: strictReceiver({ kind: "regex" }),
1723
+ args: [],
1724
+ type: STRING,
1725
+ loc,
1726
+ };
1727
+ return {
1728
+ kind: "strIntrinsic",
1729
+ method: "includes",
1730
+ receiver: flags,
1731
+ args: [{ kind: "strLit", value: flag, type: STRING, loc }],
1732
+ type: BOOL,
1733
+ loc,
1734
+ };
1735
+ }
1736
+ if (name === "test") {
1737
+ lowerer.unsupported("SC1090", expr, "regex methods as values (call 'test' directly)");
1738
+ }
1739
+ return null;
1740
+ }
1741
+ if (kind === "f64") {
1742
+ if (own(STDLIB_SURFACE.number, name) !== undefined) {
1743
+ lowerer.unsupported("SC1090", expr, `number methods as values (call '${name}' directly)`);
1744
+ }
1745
+ return null;
1746
+ }
1747
+ if (kind === "bytes") {
1748
+ const loc = locOf(expr);
1749
+ if (name === "constructor") {
1750
+ const expected = lowerer.mapTypeOf(lowerer.typeOf(expr.expression));
1751
+ const receiver = expected?.kind === "bytes" ? strictReceiver(expected) : lowerer.lowerExpr(expr.expression);
1752
+ return {
1753
+ kind: "dynKeyGet",
1754
+ value: lowerer.coerceInto(expr.expression, receiver, DYN),
1755
+ key: { kind: "strLit", value: name, type: STRING, loc },
1756
+ type: DYN,
1757
+ loc,
1758
+ };
1759
+ }
1760
+ if (name === "length" || name === "byteLength") {
1761
+ const expected = lowerer.mapTypeOf(lowerer.typeOf(expr.expression));
1762
+ let receiver = expected?.kind === "bytes" ? strictReceiver(expected) : lowerer.lowerExpr(expr.expression);
1763
+ if (receiver.type.kind === "dyn")
1764
+ return {
1765
+ kind: "dynCheck",
1766
+ value: {
1767
+ kind: "dynKeyGet",
1768
+ value: receiver,
1769
+ key: { kind: "strLit", value: name, type: STRING, loc: locOf(expr) },
1770
+ type: DYN,
1771
+ loc: locOf(expr),
1772
+ },
1773
+ type: F64,
1774
+ loc: locOf(expr),
1775
+ };
1776
+ if (receiver.type.kind === "union" &&
1777
+ lowerer.armTag(receiver.type.unionId, UNDEFINED_T) >= 0) {
1778
+ const present = lowerer.stripUndefinedArm(receiver.type);
1779
+ const helper = present.kind === "bytes"
1780
+ ? lowerer.narrowedArmHelper(receiver.type.unionId, present, locOf(expr.expression))
1781
+ : null;
1782
+ receiver = helper
1783
+ ? lowerer.checkedNarrowCall(helper, receiver, present, locOf(expr.expression))
1784
+ : lowerer.maybeNarrow(receiver, expr.expression);
1785
+ }
1786
+ // property read, exiting at the declared number type (the array
1787
+ return { kind: "bytesIntrinsic", method: name, receiver, args: [], type: F64, loc };
1788
+ }
1789
+ if (name === "byteOffset") {
1790
+ // 0 for owners (scriptc typed arrays own their whole storage —
1791
+ // SEMANTICS.md notes the divergence from Node's Buffer pooling),
1792
+ // the view's real offset for a DataView. A runtime read, so the
1793
+ // receiver's evaluation is never discarded.
1794
+ const expected = lowerer.mapTypeOf(lowerer.typeOf(expr.expression));
1795
+ const receiver = expected?.kind === "bytes" ? strictReceiver(expected) : lowerer.lowerExpr(expr.expression);
1796
+ return { kind: "bytesIntrinsic", method: "byteOffset", receiver, args: [], type: F64, loc };
1797
+ }
1798
+ if (name === "buffer") {
1799
+ const expected = lowerer.mapTypeOf(lowerer.typeOf(expr.expression));
1800
+ const receiver = expected?.kind === "bytes" ? strictReceiver(expected) : lowerer.lowerExpr(expr.expression);
1801
+ return { kind: "bytesIntrinsic", method: "buffer", receiver, args: [], type: DYN, loc };
1802
+ }
1803
+ if (name === "slice" || name === "subarray" || name === "set" || name === "toString") {
1804
+ lowerer.unsupported("SC1090", expr, `typed-array methods as values (call '${name}' directly)`);
1805
+ }
1806
+ return null; // fill, reverse, ... → the SC2020 member fence
1807
+ }
1808
+ if (kind === "map") {
1809
+ if (name === "size") {
1810
+ const expected = lowerer.mapTypeOf(lowerer.typeOf(expr.expression));
1811
+ const receiver = expected?.kind === "map" ? strictReceiver(expected) : lowerer.lowerExpr(expr.expression);
1812
+ return {
1813
+ kind: "mapIntrinsic",
1814
+ method: "size",
1815
+ receiver,
1816
+ args: [],
1817
+ type: F64,
1818
+ loc: locOf(expr),
1819
+ };
1820
+ }
1821
+ if (MAP_METHODS.has(name) || name === "forEach") {
1822
+ lowerer.unsupported("SC1090", expr, `Map methods as values (call '${name}' directly)`);
1823
+ }
1824
+ return null;
1825
+ }
1826
+ if (kind === "set") {
1827
+ if (name === "size") {
1828
+ const expected = lowerer.mapTypeOf(lowerer.typeOf(expr.expression));
1829
+ const receiver = expected?.kind === "set" ? strictReceiver(expected) : lowerer.lowerExpr(expr.expression);
1830
+ return {
1831
+ kind: "setIntrinsic",
1832
+ method: "size",
1833
+ receiver,
1834
+ args: [],
1835
+ type: F64,
1836
+ loc: locOf(expr),
1837
+ };
1838
+ }
1839
+ if (SET_METHODS.has(name)) {
1840
+ lowerer.unsupported("SC1090", expr, `Set methods as values (call '${name}' directly)`);
1841
+ }
1842
+ return null;
1843
+ }
1844
+ if (name === "length") {
1845
+ const expected = kind === "string" ? STRING : lowerer.mapTypeOf(lowerer.typeOf(expr.expression));
1846
+ let receiver = lowerer.lowerExpr(expr.expression);
1847
+ if (receiver.type.kind !== "dyn" &&
1848
+ expected &&
1849
+ (expected.kind === "string" || expected.kind === "array")) {
1850
+ receiver =
1851
+ lowerer.runtimeOptionalPropertyReceiver(expr.expression, receiver, expected, name) ??
1852
+ receiver;
1853
+ }
1854
+ if (receiver.type.kind === "union" &&
1855
+ lowerer.armTag(receiver.type.unionId, UNDEFINED_T) >= 0 &&
1856
+ kind === "array") {
1857
+ const present = lowerer.stripUndefinedArm(receiver.type);
1858
+ const helper = present.kind === "array"
1859
+ ? lowerer.narrowedArmHelper(receiver.type.unionId, present, locOf(expr.expression))
1860
+ : null;
1861
+ receiver = helper
1862
+ ? lowerer.checkedNarrowCall(helper, receiver, present, locOf(expr.expression))
1863
+ : lowerer.maybeNarrow(receiver, expr.expression);
1864
+ }
1865
+ // A CHECKED-DYNAMIC value behind an array-typed checker spelling
1866
+ // (`Object.keys(u).length` — the dyn walk answers a dyn array while
1867
+ // tsc spells string[]): the runtime-world dispatch — a dyn keyed
1868
+ // read validated into the declared number (a lying length throws
1869
+ // the catchable TypeError, the dynCheck stance).
1870
+ if (receiver.type.kind === "dyn") {
1871
+ const read = {
1872
+ kind: "dynKeyGet",
1873
+ key: { kind: "strLit", value: "length", type: STRING, loc: locOf(expr) },
1874
+ ...(expr.questionDotToken ? { optional: true } : {}),
1875
+ value: receiver,
1876
+ type: DYN,
1877
+ loc: locOf(expr),
1878
+ };
1879
+ if (expr.questionDotToken)
1880
+ return read;
1881
+ return { kind: "dynCheck", value: read, type: F64, loc: locOf(expr) };
1882
+ }
1883
+ return kind === "string"
1884
+ ? { kind: "strIntrinsic", method: "length", receiver, args: [], type: F64, loc: locOf(expr) }
1885
+ : { kind: "arrIntrinsic", method: "length", receiver, args: [], type: F64, loc: locOf(expr) };
1886
+ }
1887
+ if (kind === "string"
1888
+ ? own(STR_METHODS, name) !== undefined ||
1889
+ STRING_INDEX_METHODS.has(name) ||
1890
+ own(STDLIB_SURFACE.string, name) !== undefined
1891
+ : ARRAY_METHODS.has(name)) {
1892
+ lowerer.unsupported("SC1090", expr, `${kind} methods as values (call '${name}' directly)`);
1893
+ }
1894
+ return null;
1895
+ }
1896
+ /** A `T | undefined` class field read that the checker narrowed to `T`
1897
+ * where the field was assigned a value that may be missing (an unchecked
1898
+ * indexed read). TypeScript's assignment narrowing is not a runtime fact
1899
+ * there, so the read keeps the stored union instead of extracting `T`. */
1900
+ function runtimeOptionalClassField(lowerer, value, node) {
1901
+ if (value.kind !== "fieldGet" || value.type.kind !== "union")
1902
+ return false;
1903
+ if (lowerer.armTag(value.type.unionId, UNDEFINED_T) < 0)
1904
+ return false;
1905
+ if ((lowerer.unions.get(value.type.unionId)?.arms.length ?? 0) !== 2)
1906
+ return false;
1907
+ const symbol = lowerer.checker.getSymbolAtLocation(node.name);
1908
+ if (!symbol || !lowerer.runtimeOptionalAssignedSymbols.has(symbol))
1909
+ return false;
1910
+ const narrowed = lowerer.mapTypeOf(lowerer.typeOf(node));
1911
+ return narrowed !== null && typeEquals(narrowed, lowerer.stripUndefinedArm(value.type));
1912
+ }
1913
+ /** `exports.<name>` in a JS module whose `module.exports =` REPLACED the
1914
+ * export object, with no `exports.<name> =` attachment anywhere in the
1915
+ * file: the read observes the ORIGINAL (empty-here) exports object, so
1916
+ * the honest value is undefined (Node's object identity exactly; tsc's
1917
+ * CJS model types the read off the replacement — identity-blind). Null
1918
+ * everywhere else: no replacement, a real attachment of this name, a
1919
+ * shadowing binding named `exports`, or write position. */
1920
+ function lowerReplacedExportsRead(lowerer, expr) {
1921
+ if (expr.questionDotToken)
1922
+ return null;
1923
+ const recv = expr.expression;
1924
+ if (!ts.isIdentifier(recv) || recv.text !== "exports")
1925
+ return null;
1926
+ const sf = ts.getSourceFileOfNode(expr);
1927
+ if (!isJsSourceFile(sf) || isNodeEsmFile(sf, lowerer.program))
1928
+ return null;
1929
+ if (lowerer.peekLocal(recv) || lowerer.globalOf(recv))
1930
+ return null; // a user binding shadows
1931
+ // Write position is the export-assignment machinery's territory.
1932
+ if (ts.isBinaryExpression(expr.parent) &&
1933
+ expr.parent.left === expr &&
1934
+ expr.parent.operatorToken.kind === ts.SyntaxKind.EqualsToken) {
1935
+ return null;
1936
+ }
1937
+ let replaced = false;
1938
+ for (const stmt of sf.statements.nodes) {
1939
+ const cjs = cjsExportAssignmentOf(stmt);
1940
+ if (!cjs)
1941
+ continue;
1942
+ if (cjs.kind === "table" && cjsExportDiscardReason(stmt) === null)
1943
+ replaced = true;
1944
+ if (cjs.kind === "member" && ts.isIdentifier(cjs.name) && cjs.name.text === expr.name.text) {
1945
+ return null; // a real attachment of this name exists somewhere
1946
+ }
1947
+ }
1948
+ if (!replaced)
1949
+ return null;
1950
+ return { kind: "unitLit", unit: "undefined", type: UNDEFINED_T, loc: locOf(expr) };
1951
+ }
1952
+ /** `this.<name>` INSIDE a CJS export-table accessor (test/common's
1953
+ * `get localhostIPv4() { if (this.inFreeBSDJail) ... }`): Node binds the
1954
+ * getter's receiver to module.exports, so the read is the SIBLING table
1955
+ * property — a sibling GETTER's lifted call (per-read evaluation, like
1956
+ * any accessor read). Only arrows inherit the binding (a nested function
1957
+ * expression's `this` is its own). Null everywhere else — non-getter
1958
+ * siblings and absent names keep their per-site fences (none of the
1959
+ * probed suite shapes read them). */
1960
+ function lowerCjsExportTableThisMember(lowerer, expr) {
1961
+ if (expr.expression.kind !== ts.SyntaxKind.ThisKeyword || expr.questionDotToken)
1962
+ return null;
1963
+ if (!isJsSourceFile(ts.getSourceFileOfNode(expr)))
1964
+ return null;
1965
+ // The enclosing accessor, crossing only arrow boundaries (arrows
1966
+ // inherit `this`; any other function form rebinds it).
1967
+ let n = expr.parent;
1968
+ while (n !== undefined && !ts.isGetAccessorDeclaration(n) && !ts.isSetAccessorDeclaration(n)) {
1969
+ if (ts.isFunctionLike(n) && !ts.isArrowFunction(n))
1970
+ return null;
1971
+ if (ts.isSourceFile(n))
1972
+ return null;
1973
+ n = n.parent;
1974
+ }
1975
+ if (n === undefined ||
1976
+ !ts.isObjectLiteralExpression(n.parent) ||
1977
+ !isCjsExportTableLiteral(n.parent)) {
1978
+ return null;
1979
+ }
1980
+ const sibling = n.parent.properties.nodes.find((p) => ts.isGetAccessorDeclaration(p) && ts.isIdentifier(p.name) && p.name.text === expr.name.text);
1981
+ if (!sibling)
1982
+ return null;
1983
+ return cjsAccessorCall(lowerer, sibling, locOf(expr));
1984
+ }
1985
+ /** RegExp.prototype's flag getters and the flag each one reads. */
1986
+ const REGEX_FLAG_GETTERS = new Map([
1987
+ ["hasIndices", "d"],
1988
+ ["global", "g"],
1989
+ ["ignoreCase", "i"],
1990
+ ["multiline", "m"],
1991
+ ["dotAll", "s"],
1992
+ ["unicode", "u"],
1993
+ ["unicodeSets", "v"],
1994
+ ["sticky", "y"],
1995
+ ]);
1996
+ /** The named-group table of the regex that PRODUCED a match-result
1997
+ * expression — the `.groups` desugar's provenance question. Traces
1998
+ * (through parens, `!`, and const bindings):
1999
+ * - `re.exec(s)` / `s.match(re)` → re's static pattern
2000
+ * - a matchAll ROW: `rows[i]`, the for-of binding over a direct
2001
+ * `s.matchAll(re)` or a stored const drain → re's static pattern
2002
+ * Answers null when the producing regex isn't statically known (the
2003
+ * caller keeps its fence), or the groups list (possibly empty — a
2004
+ * traced regex WITHOUT named groups is the Node-undefined case). */
2005
+ export function matchResultNamedGroupsOf(lowerer, e) {
2006
+ let producer = e;
2007
+ while (ts.isParenthesizedExpression(producer) || ts.isNonNullExpression(producer))
2008
+ producer = producer.expression;
2009
+ if (ts.isIdentifier(producer)) {
2010
+ const init = constInitializerOf(lowerer, producer);
2011
+ if (init !== null)
2012
+ return matchResultNamedGroupsOf(lowerer, init);
2013
+ }
2014
+ const reExpr = matchProducerRegexOf(lowerer, e);
2015
+ if (reExpr === null)
2016
+ return null;
2017
+ if (ts.isCallExpression(producer) &&
2018
+ ts.isPropertyAccessExpression(producer.expression) &&
2019
+ producer.expression.name.text === "match") {
2020
+ const flags = staticRegexFlagsOf(lowerer, reExpr);
2021
+ if (flags === null)
2022
+ return null;
2023
+ // Global String.match returns whole matches without a groups
2024
+ // property, even when the pattern contains named captures.
2025
+ if (flags.includes("g"))
2026
+ return [];
2027
+ }
2028
+ const pattern = staticRegexPatternOf(lowerer, reExpr);
2029
+ if (pattern === null)
2030
+ return null;
2031
+ return namedCaptureGroupsOfPattern(pattern);
2032
+ }
2033
+ function staticRegexFlagsOf(lowerer, node) {
2034
+ let expr = node;
2035
+ while (ts.isParenthesizedExpression(expr) || ts.isNonNullExpression(expr))
2036
+ expr = expr.expression;
2037
+ if (ts.isRegularExpressionLiteral(expr))
2038
+ return expr.text.slice(expr.text.lastIndexOf("/") + 1);
2039
+ if (ts.isIdentifier(expr)) {
2040
+ const init = constInitializerOf(lowerer, expr);
2041
+ return init !== null ? staticRegexFlagsOf(lowerer, init) : null;
2042
+ }
2043
+ if (ts.isNewExpression(expr) &&
2044
+ ts.isIdentifier(expr.expression) &&
2045
+ lowerer.isStdlibGlobal(expr.expression, "RegExp")) {
2046
+ const flags = expr.arguments?.nodes[1];
2047
+ if (!flags)
2048
+ return "";
2049
+ if (ts.isStringLiteral(flags) || ts.isNoSubstitutionTemplateLiteral(flags))
2050
+ return flags.text;
2051
+ }
2052
+ return null;
2053
+ }
2054
+ /** The regex EXPRESSION whose match produced `e` (see
2055
+ * matchResultNamedGroupsOf for the traced shapes). */
2056
+ function matchProducerRegexOf(lowerer, e) {
2057
+ let expr = e;
2058
+ for (;;) {
2059
+ if (ts.isParenthesizedExpression(expr) || ts.isNonNullExpression(expr)) {
2060
+ expr = expr.expression;
2061
+ continue;
2062
+ }
2063
+ break;
2064
+ }
2065
+ // The direct producers: re.exec(s) / s.match(re) — the receiver's
2066
+ // mapped type pins the STDLIB operation (a regex for exec, a string
2067
+ // or its nullable spelling for match — the claim string-and-regexp
2068
+ // makes), so a user method that happens to be named `match` with a
2069
+ // regex argument never traces.
2070
+ if (ts.isCallExpression(expr) && ts.isPropertyAccessExpression(expr.expression)) {
2071
+ const name = expr.expression.name.text;
2072
+ const recvT = lowerer.mapTypeOf(lowerer.typeOf(expr.expression.expression));
2073
+ if (name === "exec" && expr.arguments.nodes.length === 1 && recvT?.kind === "regex") {
2074
+ return expr.expression.expression;
2075
+ }
2076
+ if (name === "match" &&
2077
+ expr.arguments.nodes.length === 1 &&
2078
+ (recvT?.kind === "string" ||
2079
+ (recvT !== null && recvT !== undefined && nullableStringType(lowerer, recvT))) &&
2080
+ lowerer.mapTypeOf(lowerer.typeOf(expr.arguments.nodes[0]))?.kind === "regex") {
2081
+ return expr.arguments.nodes[0];
2082
+ }
2083
+ }
2084
+ // A matchAll ROW by element access: rows[i] with rows tracing to the
2085
+ // drain call — or the direct s.matchAll(re)[i] spelling.
2086
+ if (ts.isElementAccessExpression(expr)) {
2087
+ return matchAllRegexOf(lowerer, expr.expression);
2088
+ }
2089
+ // A row picked by `rows.find(cb)`, `rows.findLast(cb)` or `rows.at(i)`.
2090
+ if (ts.isCallExpression(expr) &&
2091
+ ts.isPropertyAccessExpression(expr.expression) &&
2092
+ MATCH_ROW_PICK_METHODS.has(expr.expression.name.text) &&
2093
+ lowerer.isStdlibMember(expr.expression)) {
2094
+ return matchAllRegexOf(lowerer, expr.expression.expression);
2095
+ }
2096
+ if (ts.isIdentifier(expr)) {
2097
+ // The for-of binding over a matchAll drain: `for (const m of
2098
+ // s.matchAll(re))` (or over a stored const rows).
2099
+ const sym = lowerer.resolveValueSymbol(expr);
2100
+ const decl = sym ? sym.valueDeclaration : undefined;
2101
+ if (decl !== undefined &&
2102
+ ts.isVariableDeclaration(decl) &&
2103
+ ts.isVariableDeclarationList(decl.parent) &&
2104
+ ts.isForOfStatement(decl.parent.parent)) {
2105
+ return matchAllRegexOf(lowerer, decl.parent.parent.expression);
2106
+ }
2107
+ // A stored const match result: `const m = re.exec(s)`.
2108
+ const init = constInitializerOf(lowerer, expr);
2109
+ if (init !== null)
2110
+ return matchProducerRegexOf(lowerer, init);
2111
+ // The element parameter of an array callback over matchAll rows:
2112
+ // `[...s.matchAll(re)].map((m) => m.groups)`, and Array.from's
2113
+ // mapping function over `s.matchAll(re)`.
2114
+ if (decl !== undefined && ts.isParameter(decl))
2115
+ return matchAllCallbackRegexOf(lowerer, decl);
2116
+ }
2117
+ return null;
2118
+ }
2119
+ /** Array methods that return one row of the receiver. */
2120
+ const MATCH_ROW_PICK_METHODS = new Set(["find", "findLast", "at"]);
2121
+ /** `m.groups` on a match result whose producing regex is statically
2122
+ * known: the honest slice already HOLDS every named group's value at
2123
+ * its capture index, so the groups object is a compile-time record
2124
+ * projection — `{ year: m[1], month: m[2] }` — built by one interned
2125
+ * helper per (shape, index list, receiver type). Node's exact shape
2126
+ * decisions:
2127
+ * - no named groups → `undefined` (the identifier-receiver shapes —
2128
+ * a call receiver would lose its own null trap, so those keep the
2129
+ * member fence);
2130
+ * - a nullable receiver (the JS `s.match(re).groups` idiom) throws
2131
+ * Node's exact TypeError on the unit arms;
2132
+ * - every declared name is a key (nonparticipating groups hold undefined,
2133
+ * exactly the slice elements they project);
2134
+ * - ES2025 duplicate names (distinct alternatives) project the first
2135
+ * participating occurrence, including a participating empty string;
2136
+ * - key order is group declaration order (declaredOrder), Node's own.
2137
+ * The record has a null prototype, like Node's groups object. A
2138
+ * JavaScript callback parameter holds the row as a dynamic array; the
2139
+ * projection reads its elements through dynamic reads. Null when the
2140
+ * receiver isn't a match slice or the regex isn't traceable — the
2141
+ * caller's member fence (with the groups hint) names the gap. */
2142
+ function lowerMatchGroupsRead(lowerer, expr) {
2143
+ if (expr.name.text !== "groups")
2144
+ return null;
2145
+ // `m?.groups` re-dispatches through the optional-chain machinery, which
2146
+ // narrows the receiver to its match arm first.
2147
+ if (expr.questionDotToken !== undefined && !lowerer.chainHandled.has(expr))
2148
+ return null;
2149
+ const loc = locOf(expr);
2150
+ const strArr = arrayOf(STRING);
2151
+ const recvT = lowerer.mapTypeOf(lowerer.typeOf(expr.expression));
2152
+ if (!recvT || !isMatchSliceType(lowerer, recvT) || !lowerer.isStdlibMember(expr))
2153
+ return null;
2154
+ const groups = matchResultNamedGroupsOf(lowerer, expr.expression);
2155
+ // An untraced regex: TypeScript reaches the member fence; JavaScript
2156
+ // would otherwise read the slice's absent expando as undefined.
2157
+ if (groups === null && isJsSourceFile(ts.getSourceFileOfNode(expr)))
2158
+ lowerer.stdlibMemberFence(expr);
2159
+ if (groups === null)
2160
+ return null;
2161
+ if (groups.length === 0) {
2162
+ // Node: a match result of a group-less regex answers undefined —
2163
+ // the unit literal, exactly the `undefined` identifier's lowering.
2164
+ // Identifier receivers only (evaluation-free): a CALL receiver's
2165
+ // exec/match must still run and null-trap, which a folded unit
2166
+ // cannot carry — those keep the fence.
2167
+ let r = expr.expression;
2168
+ while (ts.isParenthesizedExpression(r) || ts.isNonNullExpression(r))
2169
+ r = r.expression;
2170
+ if (ts.isIdentifier(r) && typeEquals(recvT, strArr)) {
2171
+ return { kind: "unitLit", unit: "undefined", type: UNDEFINED_T, loc };
2172
+ }
2173
+ return null;
2174
+ }
2175
+ const recv = lowerer.lowerExpr(expr.expression);
2176
+ // A JavaScript callback parameter holds the row as a dynamic array.
2177
+ const dynRow = recv.type.kind === "dyn" && isJsSourceFile(ts.getSourceFileOfNode(expr));
2178
+ if (!dynRow && !isMatchSliceType(lowerer, recv.type))
2179
+ return null;
2180
+ return lowerGroupsProjection(lowerer, recv, groups, loc);
2181
+ }
2182
+ /** True when the IR type is a string-or-units union — the Dict<string>
2183
+ * member spelling (`process.versions.openssl`), match's nullable
2184
+ * receiver claim. */
2185
+ function nullableStringType(lowerer, t) {
2186
+ if (t.kind !== "union")
2187
+ return false;
2188
+ const arms = lowerer.unions.get(t.unionId)?.arms ?? [];
2189
+ return (arms.some((a) => a.kind === "string") && arms.every((a) => a.kind === "string" || isUnitType(a)));
2190
+ }
2191
+ /** True when the IR type is the honest match slice — `string[]`, or a
2192
+ * union of it with unit arms only (`string[] | null`). The groups
2193
+ * projection's receiver gate, shared with the destructure interception. */
2194
+ export function isMatchSliceType(lowerer, t) {
2195
+ if (typeEquals(t, arrayOf(STRING)))
2196
+ return true;
2197
+ return t.kind === "union" && matchSliceUnionArms(lowerer, t.unionId) !== null;
2198
+ }
2199
+ /** The union-arm layout of a nullable match slice (`string[] | null`,
2200
+ * matchAll's checker spellings with undefined arms included): the
2201
+ * string[] arm's tag plus each unit arm's tag and spelling. Null when
2202
+ * the union holds anything else. */
2203
+ function matchSliceUnionArms(lowerer, unionId) {
2204
+ const def = lowerer.unions.get(unionId);
2205
+ if (!def)
2206
+ return null;
2207
+ const strArr = arrayOf(STRING);
2208
+ const arrTag = def.arms.findIndex((a) => typeEquals(a, strArr));
2209
+ if (arrTag < 0)
2210
+ return null;
2211
+ const units = [];
2212
+ for (let i = 0; i < def.arms.length; i++) {
2213
+ if (i === arrTag)
2214
+ continue;
2215
+ const a = def.arms[i];
2216
+ if (!isUnitType(a))
2217
+ return null;
2218
+ units.push({ tag: i, unit: a.kind === "nullT" ? "null" : "undefined" });
2219
+ }
2220
+ return { arrTag, units };
2221
+ }
2222
+ /** Node's TypeError for `.groups` read off null or undefined. */
2223
+ function groupsReadTypeError(unit, loc) {
2224
+ return {
2225
+ kind: "throw",
2226
+ value: {
2227
+ kind: "libCall",
2228
+ fn: "error.new",
2229
+ args: [strLit(`Cannot read properties of ${unit} (reading 'groups')`, loc)],
2230
+ type: { kind: "object", className: "%TypeError" },
2231
+ loc,
2232
+ },
2233
+ loc,
2234
+ };
2235
+ }
2236
+ /** The groups-record projection holds string | undefined values, including
2237
+ * an own overflow entry for every nonparticipating capture. One lifted helper per
2238
+ * (index list, receiver representation) builds it; see
2239
+ * lowerMatchGroupsRead for the semantics the body encodes. */
2240
+ export function lowerGroupsProjection(lowerer, recv, groups, loc) {
2241
+ // Name → its capture indices, in declaration order (duplicates keep
2242
+ // every occurrence — the projection picks the participating one).
2243
+ const order = [];
2244
+ const indicesByName = new Map();
2245
+ for (const g of groups) {
2246
+ const got = indicesByName.get(g.name);
2247
+ if (got) {
2248
+ got.push(g.index);
2249
+ }
2250
+ else {
2251
+ indicesByName.set(g.name, [g.index]);
2252
+ order.push(g.name);
2253
+ }
2254
+ }
2255
+ const valueType = arrayValueType(lowerer, STRING);
2256
+ const shapeId = lowerer.shapes.intern([], false, valueType);
2257
+ const recordT = { kind: "record", shapeId };
2258
+ const recvKey = recv.type.kind === "union" ? recv.type.unionId : recv.type.kind === "dyn" ? "dyn" : "arr";
2259
+ const key = `regexgroups:${shapeId}:${groups.map((g) => `${g.name}=${g.index}`).join(",")}:${recvKey}`;
2260
+ let helper = lowerer.valueHelpers.get(key);
2261
+ if (!helper) {
2262
+ helper = `%regex.groups.${lowerer.valueHelpers.size}`;
2263
+ lowerer.valueHelpers.set(key, helper);
2264
+ const body = [];
2265
+ const locals = [{ id: "m.0", name: "m", type: recv.type, mutable: true }];
2266
+ let mRef = { kind: "varRef", localId: "m.0", type: recv.type, loc };
2267
+ if (recv.type.kind === "union") {
2268
+ // Node's exact TypeError per unit arm, then the checked narrow.
2269
+ const arms = matchSliceUnionArms(lowerer, recv.type.unionId);
2270
+ for (const u of arms.units) {
2271
+ body.push({
2272
+ kind: "if",
2273
+ cond: {
2274
+ kind: "unionIsTag",
2275
+ unionId: recv.type.unionId,
2276
+ tag: u.tag,
2277
+ negated: false,
2278
+ value: mRef,
2279
+ type: BOOL,
2280
+ loc,
2281
+ },
2282
+ then: [groupsReadTypeError(u.unit, loc)],
2283
+ else_: null,
2284
+ loc,
2285
+ });
2286
+ }
2287
+ const narrowed = {
2288
+ kind: "unionNarrow",
2289
+ unionId: recv.type.unionId,
2290
+ tag: arms.arrTag,
2291
+ value: mRef,
2292
+ type: arrayOf(STRING),
2293
+ loc,
2294
+ };
2295
+ locals.push({ id: "arr.0", name: "arr", type: arrayOf(STRING), mutable: false });
2296
+ body.push({ kind: "varDecl", localId: "arr.0", init: narrowed, loc });
2297
+ mRef = { kind: "varRef", localId: "arr.0", type: arrayOf(STRING), loc };
2298
+ }
2299
+ else if (recv.type.kind === "dyn") {
2300
+ // A JavaScript callback parameter holds the row as a dynamic array:
2301
+ // Node's TypeError for null and undefined, then dynamic element reads.
2302
+ for (const unit of ["null", "undefined"]) {
2303
+ body.push({
2304
+ kind: "if",
2305
+ cond: { kind: "dynTest", test: unit, value: mRef, type: BOOL, loc },
2306
+ then: [groupsReadTypeError(unit, loc)],
2307
+ else_: null,
2308
+ loc,
2309
+ });
2310
+ }
2311
+ }
2312
+ const elem = (index) => mRef.type.kind === "dyn"
2313
+ ? lowerer.coerceToExpected({
2314
+ kind: "dynKeyGet",
2315
+ value: mRef,
2316
+ key: strLit(String(index), loc),
2317
+ type: DYN,
2318
+ loc,
2319
+ }, valueType)
2320
+ : arrayValueRead(lowerer, mRef, numLit(index, loc), STRING, loc);
2321
+ const values = new Map();
2322
+ order.forEach((name, i) => {
2323
+ const idxs = indicesByName.get(name);
2324
+ if (idxs.length === 1) {
2325
+ values.set(name, elem(idxs[0]));
2326
+ return;
2327
+ }
2328
+ // Duplicates: the first participating occurrence. Empty strings
2329
+ // participate; undefined means this alternative did not match.
2330
+ const id = `g${i}.0`;
2331
+ locals.push({ id, name: `g${i}`, type: valueType, mutable: true });
2332
+ body.push({ kind: "varDecl", localId: id, init: elem(idxs[0]), loc });
2333
+ const gRef = { kind: "varRef", localId: id, type: valueType, loc };
2334
+ for (const idx of idxs.slice(1)) {
2335
+ body.push({
2336
+ kind: "if",
2337
+ cond: {
2338
+ kind: "unionIsTag",
2339
+ unionId: valueType.kind === "union" ? valueType.unionId : "",
2340
+ tag: valueType.kind === "union" ? lowerer.armTag(valueType.unionId, UNDEFINED_T) : -1,
2341
+ negated: false,
2342
+ value: gRef,
2343
+ type: BOOL,
2344
+ loc,
2345
+ },
2346
+ then: [{ kind: "assign", localId: id, value: elem(idx), loc }],
2347
+ else_: null,
2348
+ loc,
2349
+ });
2350
+ }
2351
+ values.set(name, gRef);
2352
+ });
2353
+ body.push({
2354
+ kind: "return",
2355
+ value: {
2356
+ kind: "recordLit",
2357
+ fields: order.map((name) => ({ name, value: values.get(name), overflow: true })),
2358
+ nullProto: true,
2359
+ type: recordT,
2360
+ loc,
2361
+ },
2362
+ loc,
2363
+ });
2364
+ lowerer.liftedFns.push({
2365
+ name: helper,
2366
+ params: [{ localId: "m.0", name: "m", type: recv.type }],
2367
+ returnType: recordT,
2368
+ locals,
2369
+ body,
2370
+ loc,
2371
+ });
2372
+ }
2373
+ return { kind: "call", callee: helper, args: [recv], type: recordT, loc };
2374
+ }
2375
+ /** Field reads use the shared FieldTarget union. Native method reads select
2376
+ * an interned unbound callable; invocation supplies its receiver separately. */
2377
+ export function lowerFieldRead(lowerer, expr) {
2378
+ // A checked receiver already owns its property table. An ambient
2379
+ // generic method signature must not divert its value into native
2380
+ // object-literal specialization (Array.prototype.map is one example).
2381
+ if (ts.isIdentifier(expr.expression)) {
2382
+ const stored = lowerer.peekLocal(expr.expression) ?? lowerer.globalOf(expr.expression);
2383
+ if (stored?.type.kind === "dyn") {
2384
+ const value = lowerer.lowerExpr(expr.expression);
2385
+ if (value.type.kind === "dyn")
2386
+ return {
2387
+ kind: "dynKeyGet",
2388
+ value,
2389
+ key: { kind: "strLit", value: expr.name.text, type: STRING, loc: locOf(expr.name) },
2390
+ ...(expr.questionDotToken || hasOptionalChainGuard(expr.expression)
2391
+ ? { optional: true }
2392
+ : {}),
2393
+ type: DYN,
2394
+ loc: locOf(expr),
2395
+ };
2396
+ }
2397
+ }
2398
+ const target = lowerer.fieldTarget(expr);
2399
+ if (target)
2400
+ return lowerer.fieldGetExpr(target, locOf(expr), expr);
2401
+ if (expr.questionDotToken)
2402
+ return null;
2403
+ let receiverIr = lowerer.mapTypeOf(lowerer.typeOf(expr.expression));
2404
+ // The readonly-tuple Array.isArray narrow has no directly mappable
2405
+ // checker type (`Result & any[]`), but maybeNarrow extracted the tuple
2406
+ // record behind it. Route tuple properties such as `.length` from that
2407
+ // lowered value, the element-access bridge's twin.
2408
+ const checkerArray = lowerer.checkerArrayValue(expr.expression);
2409
+ if (checkerArray?.type.kind === "record")
2410
+ receiverIr = checkerArray.type;
2411
+ if (receiverIr?.kind === "object" &&
2412
+ (lowerer.findMethodOn(lowerer.classes.get(receiverIr.className) ?? null, expr.name.text) ||
2413
+ findGenericMethodOn(lowerer, lowerer.classes.get(receiverIr.className) ?? null, expr.name.text))) {
2414
+ const info = lowerer.classes.get(receiverIr.className);
2415
+ if (info)
2416
+ return lowerClassMethodValue(lowerer, expr, info);
2417
+ }
2418
+ // An object-literal GENERIC method as a VALUE (`o.m` — the member is
2419
+ // excluded from the record shape): the pinned-value rule verbatim when
2420
+ // the receiver is the defining literal's own const binding (the value
2421
+ // is the pinned instance's closure — no `this` exists); anything else
2422
+ // fences by name inside the helpers.
2423
+ {
2424
+ const propSym = lowerer.checker.getPropertyOfType(lowerer.typeOf(expr.expression), expr.name.text);
2425
+ if (receiverIr?.kind !== "object" &&
2426
+ propSym &&
2427
+ isGenericCallableMemberType(lowerer.checker.getTypeOfSymbol(propSym), lowerer.checker) &&
2428
+ // CLASS members keep the class-path fences (a poisoned class's own
2429
+ // diagnostics, the bound-method fence above).
2430
+ !propSym.declarations.some((d) => d.parent !== undefined &&
2431
+ (ts.isClassDeclaration(d.parent) || ts.isClassExpression(d.parent)))) {
2432
+ const found = objLitGenericFnNodeOf(lowerer, propSym);
2433
+ if (!found) {
2434
+ lowerer.unsupported("SC1090", expr, `the generic method '${expr.name.text}' as a value with no defining object literal (only methods declared with a body in an object literal compile)`);
2435
+ }
2436
+ requireObjLitGenericReceiver(lowerer, expr, expr.expression, found.literal, expr.name.text);
2437
+ return lowerer.lowerGenericFnValue(expr, objLitGenericFnInfoOf(lowerer, expr, expr.name.text, found));
2438
+ }
2439
+ }
2440
+ // Dot access to an UNDECLARED key of an index-signature shape
2441
+ // (`bag.count` on `Record<string, number>`): tsc allows it without
2442
+ // noPropertyAccessFromIndexSignature, but the bracket spelling is the
2443
+ // canonical index-signature form here — point at it.
2444
+ if (receiverIr?.kind === "record") {
2445
+ const shape = lowerer.shapes.get(receiverIr.shapeId);
2446
+ if (shape?.indexValue && !shape.fields.some((f) => f.name === expr.name.text)) {
2447
+ const actual = tryLowerExpression(lowerer, expr.expression);
2448
+ if (actual?.type.kind === "dyn")
2449
+ return {
2450
+ kind: "dynKeyGet",
2451
+ value: actual,
2452
+ key: { kind: "strLit", value: expr.name.text, type: STRING, loc: locOf(expr.name) },
2453
+ type: DYN,
2454
+ loc: locOf(expr),
2455
+ };
2456
+ if (actual?.type.kind === "record") {
2457
+ const field = lowerer.shapes
2458
+ .get(actual.type.shapeId)
2459
+ ?.fields.find((field) => field.name === expr.name.text);
2460
+ if (field)
2461
+ return {
2462
+ kind: "recordGet",
2463
+ obj: actual,
2464
+ shapeId: actual.type.shapeId,
2465
+ field: field.name,
2466
+ type: field.type,
2467
+ loc: locOf(expr),
2468
+ };
2469
+ }
2470
+ // A member the checker declares on the receiver, stored in a pure
2471
+ // index-signature record (an object literal that spread one, see
2472
+ // dictSpreadLiteralShape): the key is always present, so the keyed
2473
+ // read answers the member through the slot type.
2474
+ if (actual?.type.kind === "record" &&
2475
+ shape.fields.length === 0 &&
2476
+ declaredMemberOf(lowerer, expr.expression, expr.name.text)) {
2477
+ return lowerer.maybeNarrow({
2478
+ kind: "recordKeyGet",
2479
+ obj: actual,
2480
+ shapeId: actual.type.shapeId,
2481
+ key: { kind: "strLit", value: expr.name.text, type: STRING, loc: locOf(expr.name) },
2482
+ type: shape.indexValue,
2483
+ loc: locOf(expr),
2484
+ }, expr);
2485
+ }
2486
+ lowerer.unsupported("SC1090", expr, `dot access to index-signature keys (spell it r["${expr.name.text}"] — brackets are the index-signature form)`);
2487
+ }
2488
+ }
2489
+ // `t.length` on a tuple: the arity CONSTANT (tuples are fixed-shape —
2490
+ // the checker types it as the literal arity too). Folding discards the
2491
+ // receiver's evaluation, so only side-effect-free receivers fold;
2492
+ // anything else (a call result) binds to a const first.
2493
+ if (receiverIr?.kind === "record" && expr.name.text === "length") {
2494
+ const shape = lowerer.shapes.get(receiverIr.shapeId);
2495
+ if (shape?.tuple) {
2496
+ let root = expr.expression;
2497
+ while (ts.isPropertyAccessExpression(root))
2498
+ root = root.expression;
2499
+ if (!ts.isIdentifier(root) && root.kind !== ts.SyntaxKind.ThisKeyword) {
2500
+ lowerer.unsupported("SC1090", expr, "'.length' of a computed tuple expression (the arity is a constant — bind the tuple to a const first)");
2501
+ }
2502
+ return { kind: "numLit", value: shape.fields.length, type: F64, loc: locOf(expr) };
2503
+ }
2504
+ }
2505
+ return null;
2506
+ }
2507
+ /** Shared-field read `r.f` on a UNION receiver: supported exactly when
2508
+ * every arm is a record/class possessing the field with ONE shared IR
2509
+ * type — the discriminant pattern (`r.kind`, primitive) and the
2510
+ * shared-payload pattern (`spec.config` where every ServiceSpec arm
2511
+ * carries the same record). Lowers to `unionDisc` (the backend switches
2512
+ * on the runtime tag and reads the field from the concrete arm), which
2513
+ * composes with existing strEq/bin/switch nodes, so `r.kind === "ok"`
2514
+ * and `switch (r.kind)` work without dedicated test nodes. Anything else
2515
+ * on a union receiver is rejected specifically (narrow first). */
2516
+ export function lowerUnionProperty(lowerer, expr) {
2517
+ if (lowerer.chainBlocked(expr))
2518
+ return null;
2519
+ const receiverIr = structuralReadType(lowerer, expr.expression) ??
2520
+ lowerer.mapTypeOf(lowerer.typeOf(expr.expression));
2521
+ if (receiverIr?.kind !== "union")
2522
+ return null;
2523
+ // Lower the receiver first: its runtime value can still carry the full
2524
+ // binding union even when the checker has removed several variants.
2525
+ let value = lowerer.lowerExpr(expr.expression);
2526
+ // A guard can remove several variants without selecting one record.
2527
+ // Materialize that sub-union before looking for common fields; arms
2528
+ // ruled out by the guard must not veto a field shared by the survivors.
2529
+ if (value.type.kind === "union" && !typeEquals(value.type, receiverIr)) {
2530
+ const helper = lowerer.narrowedRetagHelper(expr.expression, value.type.unionId, receiverIr.unionId, locOf(expr));
2531
+ if (helper)
2532
+ value = { kind: "call", callee: helper, args: [value], type: receiverIr, loc: locOf(expr) };
2533
+ // Optional storage of a base class (a runtime-optional binding holding
2534
+ // `Base | undefined`) that `instanceof` narrowed to several subclasses:
2535
+ // extract the instance and test its class, as typed slots do.
2536
+ else
2537
+ value = narrowStoredClassValue(lowerer, value, receiverIr) ?? value;
2538
+ }
2539
+ // A checker-union receiver whose VALUE lowered to a plain RECORD (the
2540
+ // merged-signature fiction — `runner(cmd, args)` where runner joined
2541
+ // a structural runner type with spawnSync's, and the local adopted
2542
+ // the record arm): read the record field directly, the dyn-receiver
2543
+ // fallback's discipline.
2544
+ // A checker-union receiver whose VALUE lowered checked-dynamic (a
2545
+ // never-tainted JS chain — `cmd[1].length` on `const cmd = ['pwd',
2546
+ // []]`, where the element read stayed a dyn node): read through the
2547
+ // dyn keyed read like the unmappable-receiver path below the chain.
2548
+ if (value.type.kind === "dyn") {
2549
+ const key = {
2550
+ kind: "strLit",
2551
+ value: expr.name.text,
2552
+ type: STRING,
2553
+ loc: locOf(expr.name),
2554
+ };
2555
+ return { kind: "dynKeyGet", key, value, type: DYN, loc: locOf(expr) };
2556
+ }
2557
+ if (value.type.kind === "record") {
2558
+ const shape = lowerer.shapes.get(value.type.shapeId);
2559
+ const f = shape?.fields.find((x) => x.name === expr.name.text);
2560
+ if (f) {
2561
+ return {
2562
+ kind: "recordGet",
2563
+ obj: value,
2564
+ shapeId: value.type.shapeId,
2565
+ field: f.name,
2566
+ type: f.type,
2567
+ loc: locOf(expr),
2568
+ };
2569
+ }
2570
+ return null;
2571
+ }
2572
+ // A class instance the checker sees through a wider union (`(concrete
2573
+ // as A | B).value`): the value is that class's instance, so read its
2574
+ // field directly.
2575
+ if (value.type.kind === "object") {
2576
+ const className = value.type.className;
2577
+ const info = lowerer.classes.get(className) ?? null;
2578
+ const field = expr.name.text;
2579
+ const fieldType = info?.fields.get(field);
2580
+ if (fieldType !== undefined)
2581
+ return lowerer.fieldGetExpr({ container: "class", obj: value, className, field, fieldType }, locOf(expr), expr);
2582
+ const getter = lowerer.findMethodOn(info, `get:${field}`);
2583
+ if (getter)
2584
+ return lowerer.fieldGetExpr({ container: "accessor", obj: value, className, field, fieldType: getter.sig.ret }, locOf(expr), expr);
2585
+ }
2586
+ if (value.type.kind !== "union") {
2587
+ lowerer.unsupported("SC1090", expr, "shared property access without a represented union receiver");
2588
+ }
2589
+ const def = lowerer.unions.get(value.type.unionId);
2590
+ if (!def)
2591
+ throw new InternalCompilerError(`lowerer bug: unknown union ${value.type.unionId}`);
2592
+ const field = expr.name.text;
2593
+ if (field === "length") {
2594
+ const presentArms = def.arms.filter((arm) => !isUnitType(arm));
2595
+ const present = presentArms.length === 1 ? presentArms[0] : null;
2596
+ if (present?.kind === "string" || present?.kind === "array") {
2597
+ const receiver = lowerer.runtimeOptionalPropertyReceiver(expr.expression, value, present, field);
2598
+ if (receiver !== null) {
2599
+ return present.kind === "string"
2600
+ ? {
2601
+ kind: "strIntrinsic",
2602
+ method: "length",
2603
+ receiver,
2604
+ args: [],
2605
+ type: F64,
2606
+ loc: locOf(expr),
2607
+ }
2608
+ : {
2609
+ kind: "arrIntrinsic",
2610
+ method: "length",
2611
+ receiver,
2612
+ args: [],
2613
+ type: F64,
2614
+ loc: locOf(expr),
2615
+ };
2616
+ }
2617
+ }
2618
+ }
2619
+ const nonUnitArms = def.arms.filter((arm) => !isUnitType(arm));
2620
+ if (nonUnitArms.length === 1 && nonUnitArms[0]?.kind === "object") {
2621
+ const objectType = nonUnitArms[0];
2622
+ const fieldType = lowerer.classes.get(objectType.className)?.fields.get(field);
2623
+ if (fieldType !== undefined) {
2624
+ let receiver = lowerer.runtimeOptionalPropertyReceiver(expr.expression, value, objectType, field);
2625
+ if (receiver === null) {
2626
+ const helper = lowerer.narrowedArmHelper(value.type.unionId, objectType, locOf(expr.expression));
2627
+ if (helper !== null)
2628
+ receiver = lowerer.checkedNarrowCall(helper, value, objectType, locOf(expr.expression));
2629
+ }
2630
+ if (receiver !== null) {
2631
+ return {
2632
+ kind: "fieldGet",
2633
+ obj: receiver,
2634
+ className: objectType.className,
2635
+ field,
2636
+ type: fieldType,
2637
+ loc: locOf(expr),
2638
+ };
2639
+ }
2640
+ }
2641
+ }
2642
+ let common = null;
2643
+ for (const arm of def.arms) {
2644
+ let ft;
2645
+ if (arm.kind === "record") {
2646
+ ft = lowerer.shapes.get(arm.shapeId)?.fields.find((f) => f.name === field)?.type;
2647
+ }
2648
+ else if (arm.kind === "object") {
2649
+ ft = lowerer.classes.get(arm.className)?.fields.get(field);
2650
+ }
2651
+ if (!ft || ft.kind === "void" || isUnitType(ft) || (common && !typeEquals(common, ft))) {
2652
+ common = null;
2653
+ break;
2654
+ }
2655
+ common = ft;
2656
+ }
2657
+ if (common) {
2658
+ return {
2659
+ kind: "unionDisc",
2660
+ unionId: value.type.unionId,
2661
+ field,
2662
+ value,
2663
+ type: common,
2664
+ loc: locOf(expr),
2665
+ };
2666
+ }
2667
+ // The arms answer DIFFERENT types (or through index signatures / unit
2668
+ // arms): the JOIN path — `env.PORTLESS_PORT` on `ProcessEnv |
2669
+ // Record<string, string>`, the tail read of `loaded?.config.script`.
2670
+ const key = { kind: "strLit", value: field, type: STRING, loc: locOf(expr.name) };
2671
+ const keyed = lowerUnionKeyedRead(lowerer, expr, value.type.unionId, value, key, field);
2672
+ if (keyed)
2673
+ return keyed;
2674
+ // Class arms declaring the field with compatible but different types
2675
+ // (`T | undefined` beside `T`): per-arm slot reads widened to one type.
2676
+ const widened = lowerUnionFieldRead(lowerer, expr, value);
2677
+ if (widened)
2678
+ return widened;
2679
+ // JavaScript overloads commonly inspect a class brand on a scalar-or-
2680
+ // instance argument (e.g. Matrix4.makeTranslation). Preserve primitive
2681
+ // missing-property semantics and dispatch class data through its native
2682
+ // capsule instead of demanding a field shared by every union arm.
2683
+ if (isJsSourceFile(ts.getSourceFileOfNode(expr)) && lowerer.dynConvertible(value.type)) {
2684
+ return {
2685
+ kind: "dynKeyGet",
2686
+ value: lowerer.coerceToExpected(value, DYN),
2687
+ key,
2688
+ ...(hasOptionalChainGuard(expr.expression) ? { optional: true } : {}),
2689
+ type: DYN,
2690
+ loc: locOf(expr),
2691
+ };
2692
+ }
2693
+ lowerer.unsupported("SC1090", expr, `reading '${field}' on a union-typed value (every arm must be an object/record ` +
2694
+ `with a same-typed field '${field}'; ` +
2695
+ `${NARROW_FIRST})`);
2696
+ }
2697
+ /** The unionDisc generalization: a keyed read on a union receiver whose
2698
+ * arms answer DIFFERENT (but joinable) types. Each arm contributes its
2699
+ * declared answer — an array element's type (number keys), a declared field's type (literal keys), an
2700
+ * index-signature arm's value type (plus its declared fields' types for
2701
+ * runtime keys, which reach them through the keyed-read helper), and
2702
+ * UNDEFINED for unit arms (reachable only through optional-chain tails,
2703
+ * where JS short-circuits to undefined; a unit arm the checker narrowed
2704
+ * away is simply unreachable). The result type is the JOIN of those
2705
+ * answers; every arm's answer must be the join itself, one of its
2706
+ * arms, or a sub-union whose payload representations are unchanged.
2707
+ * Array reads retain the ordinary invalid-index trap policy.
2708
+ * Returns null when any arm cannot answer — the caller owns the fence
2709
+ * message. The caller (the property/element dispatch) maybeNarrows. */
2710
+ export function lowerUnionKeyedRead(lowerer, expr, unionId, value, key, literalField) {
2711
+ const def = lowerer.unions.get(unionId);
2712
+ if (!def)
2713
+ return null;
2714
+ // Pass 1: per-arm declared answers, joined into the result type.
2715
+ const joinArms = [];
2716
+ const seen = new Set();
2717
+ const push = (t) => {
2718
+ const k = typeKey(t);
2719
+ if (!seen.has(k)) {
2720
+ seen.add(k);
2721
+ joinArms.push(t);
2722
+ }
2723
+ };
2724
+ const pushAnswer = (t) => {
2725
+ if (t.kind === "void")
2726
+ return false;
2727
+ if (t.kind === "union") {
2728
+ const inner = lowerer.unions.get(t.unionId);
2729
+ if (!inner)
2730
+ return false;
2731
+ for (const a of inner.arms)
2732
+ push(a);
2733
+ return true;
2734
+ }
2735
+ push(t);
2736
+ return true;
2737
+ };
2738
+ for (const arm of def.arms) {
2739
+ if (isUnitType(arm)) {
2740
+ push(UNDEFINED_T);
2741
+ continue;
2742
+ }
2743
+ if (key.type.kind === "f64") {
2744
+ if (arm.kind !== "array" || !pushAnswer(arm.elem))
2745
+ return null;
2746
+ continue;
2747
+ }
2748
+ if (arm.kind !== "record")
2749
+ return null;
2750
+ const shape = lowerer.shapes.get(arm.shapeId);
2751
+ if (!shape || shape.tuple)
2752
+ return null;
2753
+ const declared = literalField !== null ? shape.fields.find((f) => f.name === literalField)?.type : undefined;
2754
+ if (declared) {
2755
+ if (!pushAnswer(declared))
2756
+ return null;
2757
+ continue;
2758
+ }
2759
+ // Runtime keys can reach the declared fields through the keyed-read
2760
+ // helper's string switch — every one joins.
2761
+ if (literalField === null) {
2762
+ for (const f of shape.fields)
2763
+ if (!pushAnswer(f.type))
2764
+ return null;
2765
+ }
2766
+ if (!shape.indexValue) {
2767
+ if (literalField === null && shape.fields.length > 0)
2768
+ continue;
2769
+ return null;
2770
+ }
2771
+ if (!pushAnswer(shape.indexValue))
2772
+ return null;
2773
+ }
2774
+ if (joinArms.length === 0)
2775
+ return null;
2776
+ // The join must satisfy native union invariants. The caller owns the
2777
+ // diagnostic when a container or opaque arm prevents that join.
2778
+ if (joinArms.length > 1 &&
2779
+ (!unionContainerArmsOk(joinArms) ||
2780
+ joinArms.some((a) => a.kind === "dyn" || a.kind === "generator" || a.kind === "caught"))) {
2781
+ return null;
2782
+ }
2783
+ joinArms.sort((a, b) => (typeKey(a) < typeKey(b) ? -1 : 1));
2784
+ const type = joinArms.length === 1
2785
+ ? joinArms[0]
2786
+ : { kind: "union", unionId: lowerer.unions.intern(joinArms) };
2787
+ // Pass 2: every arm's answer must SURFACE as the join, and index arms
2788
+ // must pass the single-record keyed-read constraints (the helper is
2789
+ // shared with recordKeyGet, its missing-key policy included).
2790
+ const surfaces = (t) => typeEquals(t, type) ||
2791
+ (type.kind === "union" && lowerer.armTag(type.unionId, t) >= 0) ||
2792
+ exactUnionWidening(lowerer, t, type);
2793
+ for (const arm of def.arms) {
2794
+ if (isUnitType(arm)) {
2795
+ if (!(type.kind === "union" && lowerer.armTag(type.unionId, UNDEFINED_T) >= 0))
2796
+ return null;
2797
+ continue;
2798
+ }
2799
+ if (key.type.kind === "f64") {
2800
+ if (arm.kind !== "array" || !surfaces(arm.elem))
2801
+ return null;
2802
+ continue;
2803
+ }
2804
+ if (arm.kind !== "record")
2805
+ return null;
2806
+ const shape = lowerer.shapes.get(arm.shapeId);
2807
+ if (!shape)
2808
+ return null;
2809
+ const declared = literalField !== null ? shape.fields.find((f) => f.name === literalField)?.type : undefined;
2810
+ if (declared) {
2811
+ if (!surfaces(declared))
2812
+ return null;
2813
+ continue;
2814
+ }
2815
+ const ovfShape = literalField !== null && shape.indexValue ? { ...shape, fields: [] } : shape;
2816
+ if (!recordKeyResultOk(lowerer, ovfShape, type))
2817
+ return null;
2818
+ }
2819
+ return { kind: "unionKeyGet", unionId, key, value, type, loc: locOf(expr) };
2820
+ }
2821
+ /** A structural TypeScript view does not change a nominal object's layout
2822
+ * or accessor dispatch. Resolve the property from the represented class;
2823
+ * the optional checker view must not turn its getter into a record read. */
2824
+ export function classFieldTarget(lowerer, receiverNode, receiverType, fieldName, saved) {
2825
+ const represented = saved ?? lowerer.lowerExpr(receiverNode);
2826
+ if (represented.type.kind === "dyn" &&
2827
+ isJsSourceFile(ts.getSourceFileOfNode(receiverNode)) &&
2828
+ !fieldName.startsWith("#")) {
2829
+ return { container: "dynamic", obj: represented, field: fieldName, fieldType: DYN };
2830
+ }
2831
+ const info = lowerer.classes.get(receiverType.className);
2832
+ if (!info) {
2833
+ // A receiver typed as a class whose collection deferred: the
2834
+ // deferred diagnostics are what explains the miss.
2835
+ lowerer.flushDeferredClass(receiverType.className);
2836
+ return null;
2837
+ }
2838
+ const fieldType = info.fields.get(fieldName);
2839
+ const lowerObjectReceiver = () => {
2840
+ let obj = represented;
2841
+ if (obj.type.kind === "union") {
2842
+ // A receiver that may hold a missing value (a field assigned an
2843
+ // unchecked read): Node's member-read TypeError for the unit arm.
2844
+ const present = lowerer.runtimeOptionalPropertyReceiver(receiverNode, obj, receiverType, fieldName);
2845
+ if (present)
2846
+ return present;
2847
+ const helper = lowerer.narrowedArmHelper(obj.type.unionId, receiverType, locOf(receiverNode));
2848
+ obj = helper
2849
+ ? lowerer.checkedNarrowCall(helper, obj, receiverType, locOf(receiverNode))
2850
+ : lowerer.maybeNarrow(obj, receiverNode);
2851
+ }
2852
+ return lowerer.coerceInto(receiverNode, obj, receiverType);
2853
+ };
2854
+ if (fieldName === "cause" && receiverType.className !== "%DOMException") {
2855
+ let root = info;
2856
+ while (root.base)
2857
+ root = root.base;
2858
+ if (root.def.name === "%Error") {
2859
+ return {
2860
+ container: "errorCause",
2861
+ obj: lowerObjectReceiver(),
2862
+ field: "cause",
2863
+ fieldType: DYN,
2864
+ };
2865
+ }
2866
+ }
2867
+ if (fieldType) {
2868
+ const obj = lowerObjectReceiver();
2869
+ if (isJsSourceFile(ts.getSourceFileOfNode(receiverNode)) &&
2870
+ !fieldName.startsWith("#") &&
2871
+ [...lowerer.classes.values()].some((candidate) => lowerer.isSubclassOf(candidate.def.name, receiverType.className) &&
2872
+ (candidate.methods.has(`get:${fieldName}`) || candidate.methods.has(`set:${fieldName}`)))) {
2873
+ return {
2874
+ container: "dynamic",
2875
+ obj: lowerer.coerceToExpected(obj, DYN),
2876
+ field: fieldName,
2877
+ fieldType: DYN,
2878
+ };
2879
+ }
2880
+ return {
2881
+ container: "class",
2882
+ obj,
2883
+ className: receiverType.className,
2884
+ field: fieldName,
2885
+ fieldType,
2886
+ };
2887
+ }
2888
+ // Accessor property: either half declared anywhere on the chain
2889
+ // makes the name an accessor target (fields and accessors share a
2890
+ // namespace — tsc rejects mixing them, so the halves agree on kind).
2891
+ const getF = lowerer.findMethodOn(info, `get:${fieldName}`);
2892
+ const setF = lowerer.findMethodOn(info, `set:${fieldName}`);
2893
+ if (getF || setF) {
2894
+ const obj = lowerObjectReceiver();
2895
+ return {
2896
+ container: "accessor",
2897
+ obj,
2898
+ className: receiverType.className,
2899
+ field: fieldName,
2900
+ fieldType: getF ? getF.sig.ret : setF.sig.params[0].type,
2901
+ };
2902
+ }
2903
+ if (info.decl && isJsSourceFile(ts.getSourceFileOfNode(info.decl))) {
2904
+ const property = lowerer.checker.getPropertyOfType(lowerer.checker.getTypeAtLocation(receiverNode), fieldName);
2905
+ if (property &&
2906
+ property.declarations.some((declaration) => ts.isPropertyAccessExpression(declaration) ||
2907
+ ts.isBinaryExpression(declaration) ||
2908
+ ts.isElementAccessExpression(declaration))) {
2909
+ return {
2910
+ container: "dynamic",
2911
+ obj: lowerer.coerceToExpected(lowerObjectReceiver(), DYN),
2912
+ field: fieldName,
2913
+ fieldType: DYN,
2914
+ };
2915
+ }
2916
+ }
2917
+ return null;
2918
+ }
2919
+ /** Recognizes `obj.field` as an assignable field target: receiver is a
2920
+ * known class instance OR a record, and the member is a field or (class
2921
+ * receivers) a declared accessor property. Returns the pieces of a
2922
+ * fieldSet/recordSet/accessor-call (minus value/kind) or null. */
2923
+ export function fieldTarget(lowerer, access) {
2924
+ if (lowerer.cjsLocalModuleBindingOf(access.expression))
2925
+ return null;
2926
+ // `module.exports` / `module.id`: CommonJS module surface, never a field.
2927
+ if (isCjsModuleGlobal(lowerer, access.expression))
2928
+ return null;
2929
+ if (isCjsExportsIdentifier(lowerer, access.expression))
2930
+ return null;
2931
+ if (lowerer.chainBlocked(access))
2932
+ return null;
2933
+ if (access.name.text === "stackTraceLimit" &&
2934
+ lowerer.isStdlibGlobal(access.expression, "Error")) {
2935
+ return {
2936
+ container: "errorStackLimit",
2937
+ obj: { kind: "numLit", value: 0, type: F64, loc: locOf(access) },
2938
+ field: "stackTraceLimit",
2939
+ fieldType: F64,
2940
+ };
2941
+ }
2942
+ // `this.#x` in a function-local class's prototype method: the field of
2943
+ // the brand-checked receiver (checkedPrivateReceiver).
2944
+ if (ts.isPrivateIdentifier(access.name) &&
2945
+ access.expression.kind === ts.SyntaxKind.ThisKeyword &&
2946
+ lowerer.resolveThis()?.type.kind === "dyn") {
2947
+ const owner = localPrivateBrandClass(lowerer, access.name);
2948
+ if (owner) {
2949
+ const ownerType = {
2950
+ kind: "object",
2951
+ className: owner.info.def.name,
2952
+ };
2953
+ return classFieldTarget(lowerer, access.expression, ownerType, access.name.text);
2954
+ }
2955
+ }
2956
+ const stored = ts.isIdentifier(access.expression)
2957
+ ? (lowerer.peekLocal(access.expression)?.type ?? lowerer.globalOf(access.expression)?.type)
2958
+ : undefined;
2959
+ const narrowed = lowerer.mapTypeOf(lowerer.typeOf(access.expression));
2960
+ // Structural record views retain their storage layout, while a nominal
2961
+ // subclass guard proves a more specific layout of the same object.
2962
+ const receiverIr = stored?.kind === "record"
2963
+ ? stored
2964
+ : stored?.kind === "object" &&
2965
+ !(narrowed?.kind === "object" &&
2966
+ lowerer.isSubclassOf(narrowed.className, stored.className))
2967
+ ? stored
2968
+ : narrowed;
2969
+ if (receiverIr?.kind === "object") {
2970
+ const target = classFieldTarget(lowerer, access.expression, receiverIr, access.name.text);
2971
+ if (target)
2972
+ return target;
2973
+ // Abstract properties declare no base storage. Resolve the concrete
2974
+ // instance's live field or accessor through the existing class bridge;
2975
+ // inventing a shared field offset would misread subclass layouts.
2976
+ if (abstractPropertyDeclOf(lowerer, access)) {
2977
+ return {
2978
+ container: "dynamic",
2979
+ obj: lowerer.coerceInto(access.expression, lowerer.lowerExpr(access.expression), DYN),
2980
+ field: access.name.text,
2981
+ fieldType: lowerer.irTypeOf(access),
2982
+ };
2983
+ }
2984
+ return null;
2985
+ }
2986
+ if (receiverIr?.kind === "union" && hasClassPayload(lowerer, receiverIr)) {
2987
+ return representedClassFieldTarget(lowerer, access.expression, access.name.text, lowerer.lowerExpr(access.expression));
2988
+ }
2989
+ if (receiverIr?.kind === "record") {
2990
+ const shape = lowerer.shapes.get(receiverIr.shapeId);
2991
+ const fieldType = shape?.fields.find((f) => f.name === access.name.text)?.type;
2992
+ if (fieldType) {
2993
+ let obj = lowerer.lowerExpr(access.expression);
2994
+ const nominal = representedClassFieldTarget(lowerer, access.expression, access.name.text, obj);
2995
+ if (nominal)
2996
+ return nominal;
2997
+ // A checker-record receiver whose VALUE stayed dyn (the erased
2998
+ // all-unknown-fields cast — `(err as { code?: unknown }).code`):
2999
+ // decline, and the dyn keyed-read fallback answers.
3000
+ if (obj.type.kind === "union" && lowerer.armTag(obj.type.unionId, UNDEFINED_T) >= 0) {
3001
+ // A nested property read such as `rows[i].value` or
3002
+ // `table[k].value`: the outer read can miss. Validate the record
3003
+ // arm before fieldGet/recordGet so a missing outer value raises
3004
+ // Node's TypeError rather than reaching the backend with a union
3005
+ // receiver.
3006
+ const present = lowerer.stripUndefinedArm(obj.type);
3007
+ const parent = access.parent;
3008
+ const written = parent !== undefined &&
3009
+ ts.isBinaryExpression(parent) &&
3010
+ parent.left === access &&
3011
+ parent.operatorToken.kind === ts.SyntaxKind.EqualsToken;
3012
+ const helper = present.kind === "record"
3013
+ ? lowerer.narrowedArmHelper(obj.type.unionId, present, locOf(access.expression))
3014
+ : null;
3015
+ obj =
3016
+ (present.kind === "record"
3017
+ ? lowerer.runtimeOptionalPropertyReceiver(access.expression, obj, present, access.name.text, written ? "set" : "read")
3018
+ : null) ??
3019
+ (helper
3020
+ ? lowerer.checkedNarrowCall(helper, obj, present, locOf(access.expression))
3021
+ : lowerer.maybeNarrow(obj, access.expression));
3022
+ }
3023
+ if (obj.type.kind !== "record")
3024
+ return null;
3025
+ const actualShape = lowerer.shapes.get(obj.type.shapeId);
3026
+ const actualField = actualShape?.fields.find((f) => f.name === access.name.text);
3027
+ return {
3028
+ container: "record",
3029
+ obj,
3030
+ shapeId: obj.type.shapeId,
3031
+ field: access.name.text,
3032
+ fieldType: actualField?.type ?? fieldType,
3033
+ };
3034
+ }
3035
+ // A RECORD accessor property: either slot present makes the name an
3036
+ // accessor target (get/set share the property namespace — tsc
3037
+ // rejects mixing an accessor with a data property, so the halves
3038
+ // agree). Reads dispatch the %get: closure, writes the %set: one.
3039
+ {
3040
+ const getSlot = shape?.fields.find((f) => f.name === `%get:${access.name.text}`)?.type;
3041
+ const setSlot = shape?.fields.find((f) => f.name === `%set:${access.name.text}`)?.type;
3042
+ if (getSlot?.kind === "func" || setSlot?.kind === "func") {
3043
+ const obj = lowerer.lowerExpr(access.expression);
3044
+ if (obj.type.kind !== "record")
3045
+ return null; // dyn-valued receiver: the keyed fallback answers
3046
+ const getType = getSlot?.kind === "func" ? getSlot : undefined;
3047
+ const setType = setSlot?.kind === "func" ? setSlot : undefined;
3048
+ return {
3049
+ container: "recordAccessor",
3050
+ obj,
3051
+ shapeId: receiverIr.shapeId,
3052
+ field: access.name.text,
3053
+ fieldType: getType ? getType.ret : setType.params[0],
3054
+ ...(getType ? { getType } : {}),
3055
+ ...(setType ? { setType } : {}),
3056
+ };
3057
+ }
3058
+ }
3059
+ // Dot access to an UNDECLARED key of an index-signature shape: tsc
3060
+ // types it through the signature — the access resolves to NO property
3061
+ // symbol (mapped types like Record<string, T>) or to the signature's
3062
+ // own `__index` symbol (interface-declared signatures). A real member
3063
+ // symbol means a lib member like `toString` — not an index access;
3064
+ // those keep their fences below. It IS the bracket access in dot
3065
+ // spelling — the same overflow path.
3066
+ const nameSym = lowerer.checker.getSymbolAtLocation(access.name);
3067
+ if (shape?.indexValue && !shape.tuple) {
3068
+ // A member the shape CANONICALIZATION dropped into the overflow
3069
+ // (the header family: @types declares `host?: string` on
3070
+ // IncomingHttpHeaders while the canonical shape is a pure index
3071
+ // record) is the bracket access in dot spelling too: a PROPERTY
3072
+ // declaration whose own type fits within the index value. METHOD
3073
+ // members (`toString` — the lib's inherited surface) keep their
3074
+ // fences: JS finds the prototype function, never an overflow miss.
3075
+ const canonicalized = () => {
3076
+ if (!nameSym)
3077
+ return false;
3078
+ const nameDecls = nameSym.declarations;
3079
+ if (!nameDecls.length)
3080
+ return false;
3081
+ if (!nameDecls.every((d) => ts.isPropertySignature(d)))
3082
+ return false;
3083
+ const declared = lowerer.mapTypeOf(lowerer.typeOf(access));
3084
+ if (!declared)
3085
+ return false;
3086
+ const iv = shape.indexValue;
3087
+ if (typeEquals(declared, iv))
3088
+ return true;
3089
+ if (iv.kind !== "union")
3090
+ return false;
3091
+ const ivArms = lowerer.unions.get(iv.unionId)?.arms;
3092
+ if (!ivArms)
3093
+ return false;
3094
+ const declaredArms = declared.kind === "union"
3095
+ ? (lowerer.unions.get(declared.unionId)?.arms ?? [declared])
3096
+ : [declared];
3097
+ return declaredArms.every((a) => ivArms.some((b) => typeEquals(a, b)));
3098
+ };
3099
+ if (!nameSym || ts.symbolName(nameSym) === ts.InternalSymbolName.Index || canonicalized()) {
3100
+ let obj = lowerer.lowerExpr(access.expression);
3101
+ if (obj.type.kind === "union" && lowerer.armTag(obj.type.unionId, UNDEFINED_T) >= 0) {
3102
+ const present = lowerer.stripUndefinedArm(obj.type);
3103
+ obj =
3104
+ present.kind === "record"
3105
+ ? (lowerer.runtimeOptionalPropertyReceiver(access.expression, obj, present, access.name.text) ?? obj)
3106
+ : lowerer.maybeNarrow(obj, access.expression);
3107
+ }
3108
+ if (obj.type.kind !== "record")
3109
+ return null;
3110
+ const actualShape = lowerer.shapes.get(obj.type.shapeId);
3111
+ if (!actualShape?.indexValue)
3112
+ return null;
3113
+ return {
3114
+ container: "recordOvf",
3115
+ obj,
3116
+ shapeId: obj.type.shapeId,
3117
+ field: access.name.text,
3118
+ fieldType: actualShape.indexValue,
3119
+ };
3120
+ }
3121
+ }
3122
+ return null;
3123
+ }
3124
+ return null;
3125
+ }
3126
+ /** The read expression for a field target (fieldGet / recordGet /
3127
+ * getter call). `blame` locates the rejection of a setter-only read —
3128
+ * tsc-clean (the property types as the setter's param), but Node yields
3129
+ * undefined, which these property types cannot represent. */
3130
+ export function fieldGetExpr(lowerer, target, loc, blame) {
3131
+ // A member read through an unassigned deferred-init field throws Node's
3132
+ // member-read TypeError instead of the generic checked extraction.
3133
+ if (target.container === "class" &&
3134
+ ts.isPropertyAccessExpression(blame) &&
3135
+ target.obj.type.kind === "object" &&
3136
+ lowerer.deferredFieldSlot(target.obj) !== null) {
3137
+ const checked = lowerer.runtimeOptionalPropertyReceiver(blame.expression, target.obj, target.obj.type, target.field);
3138
+ if (checked)
3139
+ target = { ...target, obj: checked };
3140
+ }
3141
+ if (target.container === "recordKeyed")
3142
+ return keyedFieldRead(lowerer, target, loc);
3143
+ if (target.container === "dynamic")
3144
+ return lowerer.coerceInto(blame, {
3145
+ kind: "dynKeyGet",
3146
+ value: target.obj,
3147
+ key: { kind: "strLit", value: target.field, type: STRING, loc },
3148
+ type: DYN,
3149
+ loc,
3150
+ }, target.fieldType);
3151
+ if (target.container === "class" &&
3152
+ (target.field === "message" || target.field === "name") &&
3153
+ (target.className === "%Error" || lowerer.isSubclassOf(target.className, "%Error")))
3154
+ return errorPropertyRead(lowerer, target.obj, target.field);
3155
+ if (target.container === "errorStackLimit") {
3156
+ return { kind: "libCall", fn: "error.stackLimitGet", args: [], type: F64, loc };
3157
+ }
3158
+ if (target.container === "errorCause") {
3159
+ return { kind: "libCall", fn: "error.cause", args: [target.obj], type: DYN, loc };
3160
+ }
3161
+ // A record-shaped CHECKER target whose receiver VALUE lives in the checked-dynamic tree
3162
+ // (a JS file-scope object-literal global): the checked-dynamic keyed
3163
+ // read — dynKeyGet (a missing key answers the dyn undefined, exactly
3164
+ // JS); consumers validate (dynCheck) where a static type is required.
3165
+ if ((target.container === "record" || target.container === "recordOvf") &&
3166
+ target.obj.type.kind === "dyn") {
3167
+ return {
3168
+ kind: "dynKeyGet",
3169
+ key: { kind: "strLit", value: target.field, type: STRING, loc },
3170
+ value: target.obj,
3171
+ type: DYN,
3172
+ loc,
3173
+ };
3174
+ }
3175
+ if (target.container === "accessor") {
3176
+ const getF = lowerer.findMethodOn(lowerer.classes.get(target.className) ?? null, `get:${target.field}`);
3177
+ if (!getF) {
3178
+ lowerer.unsupported("SC1090", blame, `reading a property that has only a setter ('${target.field}' — Node would yield undefined)`);
3179
+ }
3180
+ if (!target.field.startsWith("#") &&
3181
+ isJsSourceFile(ts.getSourceFileOfNode(blame)) &&
3182
+ lowerer.dynConvertible(getF.sig.ret)) {
3183
+ const value = {
3184
+ kind: "dynKeyGet",
3185
+ value: lowerer.coerceToExpected(target.obj, DYN),
3186
+ key: { kind: "strLit", value: target.field, type: STRING, loc },
3187
+ type: DYN,
3188
+ loc,
3189
+ };
3190
+ return lowerer.coerceToExpected(value, getF.sig.ret);
3191
+ }
3192
+ return lowerer.accessorCall(target.className, `get:${target.field}`, target.obj, [], getF.sig.ret, loc);
3193
+ }
3194
+ // Record accessor properties: the read IS a call of the %get: closure
3195
+ // — once per read, side effects and all (JS's evaluation). The
3196
+ // setter-only read keeps the class-path fence: the property types as
3197
+ // the setter's param where Node yields undefined.
3198
+ if (target.container === "recordAccessor") {
3199
+ if (!target.getType) {
3200
+ lowerer.unsupported("SC1090", blame, `reading a property that has only a setter ('${target.field}' — Node would yield undefined)`);
3201
+ }
3202
+ const closure = {
3203
+ kind: "recordGet",
3204
+ obj: target.obj,
3205
+ shapeId: target.shapeId,
3206
+ field: `%get:${target.field}`,
3207
+ type: target.getType,
3208
+ loc,
3209
+ };
3210
+ return { kind: "callValue", callee: closure, args: [], type: target.getType.ret, loc };
3211
+ }
3212
+ // Overflow dot reads: exactly the bracket read with a literal key —
3213
+ // recordKeyGet, overflowOnly (the name declares no field by
3214
+ // construction), typed as the index value armed with undefined
3215
+ // (mirroring lowerRecordKeyRead).
3216
+ if (target.container === "recordOvf") {
3217
+ let obj = target.obj;
3218
+ if (obj.type.kind === "union" && ts.isPropertyAccessExpression(blame)) {
3219
+ const present = lowerer.stripUndefinedArm(obj.type);
3220
+ if (present.kind === "record") {
3221
+ obj =
3222
+ lowerer.runtimeOptionalPropertyReceiver(blame.expression, obj, present, target.field) ??
3223
+ obj;
3224
+ }
3225
+ }
3226
+ if (obj.type.kind !== "record") {
3227
+ lowerer.unsupported("SC1090", blame, `reading '${target.field}' on a non-record receiver (narrow first)`);
3228
+ }
3229
+ const shape = lowerer.shapes.get(obj.type.shapeId);
3230
+ if (!shape?.indexValue)
3231
+ lowerer.unsupported("SC1090", blame, `reading '${target.field}' on a record without an index signature`);
3232
+ let t = shape.indexValue;
3233
+ if (t.kind !== "dyn") {
3234
+ const armed = lowerer.withUndefinedArmOf(t);
3235
+ if (!armed)
3236
+ lowerer.badType(blame, lowerer.typeOf(blame));
3237
+ t = armed;
3238
+ }
3239
+ return {
3240
+ kind: "recordKeyGet",
3241
+ obj,
3242
+ shapeId: obj.type.shapeId,
3243
+ key: { kind: "strLit", value: target.field, type: STRING, loc },
3244
+ overflowOnly: true,
3245
+ type: t,
3246
+ loc,
3247
+ };
3248
+ }
3249
+ if (target.container === "class") {
3250
+ const read = {
3251
+ kind: "fieldGet",
3252
+ obj: target.obj,
3253
+ className: target.className,
3254
+ field: target.field,
3255
+ type: target.fieldType,
3256
+ loc,
3257
+ };
3258
+ // DEFERRED-INIT fields (`stream!: T` assigned past the constructor's
3259
+ // top level — ClassInfo.deferredInitFields): the SLOT is the
3260
+ // undefined-armed union; the read CHECKED-extracts the declared type
3261
+ // — a genuinely unassigned read throws the catchable TypeError
3262
+ // where Node reads an undefined the declared type cannot hold.
3263
+ if (lowerer.classes.get(target.className)?.deferredInitFields?.has(target.field) === true &&
3264
+ target.fieldType.kind === "union") {
3265
+ const inner = lowerer.stripUndefinedArm(target.fieldType);
3266
+ // Reference arms over a stable receiver check inline: the present
3267
+ // arm is a plain projection of the slot, so ordinary reads keep their
3268
+ // borrowed form and only an unassigned slot reaches the throw.
3269
+ const unionId = target.fieldType.unionId;
3270
+ const presentTag = lowerer.armTag(unionId, inner);
3271
+ const undefTag = lowerer.armTag(unionId, UNDEFINED_T);
3272
+ if (inner.kind === "object" &&
3273
+ presentTag >= 0 &&
3274
+ undefTag >= 0 &&
3275
+ lowerer.unions.get(unionId)?.arms.length === 2 &&
3276
+ isSafeToRepeat(read)) {
3277
+ return {
3278
+ kind: "ternary",
3279
+ cond: {
3280
+ kind: "unionIsTag",
3281
+ unionId,
3282
+ tag: undefTag,
3283
+ negated: false,
3284
+ value: read,
3285
+ type: BOOL,
3286
+ loc,
3287
+ },
3288
+ then: nodeThrowExpr(1, "", DEFERRED_READ_MESSAGE, inner, loc),
3289
+ else_: { kind: "unionNarrow", unionId, tag: presentTag, value: read, type: inner, loc },
3290
+ type: inner,
3291
+ loc,
3292
+ };
3293
+ }
3294
+ const helper = lowerer.deferredReadHelper(target.fieldType.unionId, inner, loc);
3295
+ if (helper)
3296
+ return { kind: "call", callee: helper, args: [read], type: inner, loc };
3297
+ }
3298
+ return read;
3299
+ }
3300
+ return {
3301
+ kind: "recordGet",
3302
+ obj: target.obj,
3303
+ shapeId: target.shapeId,
3304
+ field: target.field,
3305
+ type: target.fieldType,
3306
+ loc,
3307
+ };
3308
+ }
3309
+ /** Stream-rooted receivers' property surface (readableEnded, destroyed,
3310
+ * ...): the receiver's mapped class dispatches into lower-stream.ts.
3311
+ * Null off the stream hierarchy or for names the spoke does not own. */
3312
+ function lowerStreamObjectProperty(lowerer, expr) {
3313
+ if (expr.questionDotToken && !lowerer.chainHandled.has(expr))
3314
+ return null;
3315
+ const recvT = lowerer.mapTypeOf(lowerer.typeOf(expr.expression));
3316
+ if (recvT?.kind !== "object")
3317
+ return null;
3318
+ const info = lowerer.classes.get(recvT.className);
3319
+ if (!info || streamSidesOf(lowerer, info) === null)
3320
+ return null;
3321
+ if (expr.name.text === "bytesWritten" && isZlibStreamMember(lowerer, expr)) {
3322
+ return lowerZlibStreamBytesWritten(lowerer, expr);
3323
+ }
3324
+ if (isFsStreamMember(lowerer, expr)) {
3325
+ const member = lowerFsStreamProperty(lowerer, expr);
3326
+ if (member)
3327
+ return member;
3328
+ }
3329
+ return lowerStreamProperty(lowerer, expr, info);
3330
+ }
3331
+ /** The builtin constructors JavaScript sources read as real function
3332
+ * values rather than identity tokens: the runtime interns one function per
3333
+ * constructor, and dynamic values answer `.constructor` with the same one,
3334
+ * so `o.constructor === Object` is an exact identity test. */
3335
+ const GLOBAL_CONSTRUCTOR_VALUES = new Set([
3336
+ "Object",
3337
+ "Function",
3338
+ "Date",
3339
+ "RegExp",
3340
+ "Map",
3341
+ "Set",
3342
+ "Promise",
3343
+ "WeakMap",
3344
+ "WeakSet",
3345
+ ]);
3346
+ /** The builtin global functions JavaScript sources read as interned
3347
+ * function values (the `cond ? setImmediate : process.nextTick` feature
3348
+ * probe of bcryptjs and async libraries): typeof answers "function",
3349
+ * identity holds across spellings, and calls run the timer APIs. */
3350
+ const GLOBAL_FUNCTION_VALUES = new Set([
3351
+ "setTimeout",
3352
+ "setInterval",
3353
+ "setImmediate",
3354
+ "clearTimeout",
3355
+ "clearInterval",
3356
+ "clearImmediate",
3357
+ "queueMicrotask",
3358
+ ]);
3359
+ /** A builtin function value: one interned runtime function per name. */
3360
+ export function builtinFunctionValue(name, loc) {
3361
+ return {
3362
+ kind: "libCall",
3363
+ fn: "dyn.builtinFunction",
3364
+ args: [{ kind: "strLit", value: name, type: STRING, loc }],
3365
+ type: DYN,
3366
+ loc,
3367
+ };
3368
+ }
3369
+ /** The value a source reads for the stdlib global `canonical` (builtin
3370
+ * constructors in both languages, builtin functions in JavaScript), or
3371
+ * null when it stays an identity token (JavaScript) or fenced. */
3372
+ export function builtinGlobalValue(canonical, loc, js = false) {
3373
+ if (js && GLOBAL_FUNCTION_VALUES.has(canonical))
3374
+ return builtinFunctionValue(canonical, loc);
3375
+ if (GLOBAL_CONSTRUCTOR_VALUES.has(canonical)) {
3376
+ return {
3377
+ kind: "libCall",
3378
+ fn: "dyn.globalConstructor",
3379
+ args: [{ kind: "strLit", value: canonical, type: STRING, loc }],
3380
+ type: DYN,
3381
+ loc,
3382
+ };
3383
+ }
3384
+ return null;
3385
+ }
3386
+ /** The members the interned builtin function values model (the runtime
3387
+ * answers each one as Node does); any other member read through them would
3388
+ * answer undefined, so it keeps its static lowering or its fence. */
3389
+ const BUILTIN_VALUE_MEMBERS = new Set(["name", "length", "constructor"]);
3390
+ /** The Object statics whose answers for an interned builtin function value
3391
+ * match Node's (identity, and the empty enumerable own-key lists). */
3392
+ const BUILTIN_VALUE_REFLECTION = new Set(["is", "keys", "values", "entries"]);
3393
+ /** The value `builtinGlobalValue` gives the stdlib global `expr` read at its
3394
+ * use site: null when the use reads the global's members (they keep their
3395
+ * lowerings and fences), and SC2020 when it is the target of reflection or
3396
+ * redefinition (`Object.hasOwn(Object, "hasOwn")`,
3397
+ * `Object.defineProperty(Promise, ...)`, `hasOwnProperty.call(Map, ...)`),
3398
+ * which would observe or change members the interned value does not
3399
+ * model. */
3400
+ export function builtinGlobalValueAt(lowerer, expr, canonical, loc, js) {
3401
+ if (readsBuiltinGlobalMembers(expr))
3402
+ return null;
3403
+ const value = builtinGlobalValue(canonical, loc, js);
3404
+ if (value === null)
3405
+ return null;
3406
+ let node = expr;
3407
+ while (node.parent !== undefined && ts.isParenthesizedExpression(node.parent))
3408
+ node = node.parent;
3409
+ const call = node.parent;
3410
+ if (call !== undefined &&
3411
+ ts.isCallExpression(call) &&
3412
+ call.expression !== node &&
3413
+ ts.isPropertyAccessExpression(call.expression)) {
3414
+ const callee = call.expression;
3415
+ const owner = stdlibGlobalNameOf(lowerer, callee.expression);
3416
+ const reflects = owner === "Reflect" ||
3417
+ (owner === "Object" && !BUILTIN_VALUE_REFLECTION.has(callee.name.text)) ||
3418
+ ((callee.name.text === "call" || callee.name.text === "apply") &&
3419
+ call.arguments.nodes[0] === node &&
3420
+ lowerer.isStdlibSymbol(lowerer.checker.getSymbolAtLocation(ts.isPropertyAccessExpression(callee.expression)
3421
+ ? callee.expression.name
3422
+ : callee.expression)));
3423
+ if (reflects) {
3424
+ const name = owner !== null
3425
+ ? `${owner}.${callee.name.text}`
3426
+ : ts.getTextOfNode(callee).replace(/\s+/g, "");
3427
+ lowerer.noLowering(`${name}(${canonical}, ...)`, expr, "builtin constructor and function values model only name, length and constructor, so reflecting on or redefining their members has no lowering");
3428
+ }
3429
+ }
3430
+ return value;
3431
+ }
3432
+ /** Whether the stdlib global `expr` is read for its members (`Map.prototype`,
3433
+ * `Date["UTC"]`, `"prototype" in Map`) rather than as a value. Those reads
3434
+ * keep the global's member lowerings and fences: its interned function value
3435
+ * models only BUILTIN_VALUE_MEMBERS. */
3436
+ function readsBuiltinGlobalMembers(expr) {
3437
+ let node = expr;
3438
+ while (node.parent !== undefined && ts.isParenthesizedExpression(node.parent))
3439
+ node = node.parent;
3440
+ const parent = node.parent;
3441
+ if (parent === undefined)
3442
+ return false;
3443
+ if (ts.isPropertyAccessExpression(parent) && parent.expression === node)
3444
+ return !BUILTIN_VALUE_MEMBERS.has(parent.name.text);
3445
+ if (ts.isElementAccessExpression(parent) && parent.expression === node)
3446
+ return true;
3447
+ return (ts.isBinaryExpression(parent) &&
3448
+ parent.operatorToken.kind === ts.SyntaxKind.InKeyword &&
3449
+ parent.right === node);
3450
+ }
3451
+ /** Reports SC2020 when `access` reads a stdlib static member or the
3452
+ * prototype of a builtin constructor with an interned function value through
3453
+ * a receiver the checker types as the constructor's static side
3454
+ * (`MapConstructor`); null otherwise. Calls that lower statically never
3455
+ * reach the member read. */
3456
+ function fenceBuiltinConstructorStaticRead(lowerer, access) {
3457
+ if (BUILTIN_VALUE_MEMBERS.has(access.name.text))
3458
+ return null;
3459
+ const symbol = lowerer.typeOf(access.expression).getSymbol();
3460
+ if (symbol !== undefined &&
3461
+ ts.symbolName(symbol).endsWith("Constructor") &&
3462
+ GLOBAL_CONSTRUCTOR_VALUES.has(ts.symbolName(symbol).slice(0, -"Constructor".length)) &&
3463
+ lowerer.isStdlibSymbol(symbol))
3464
+ lowerer.stdlibMemberFence(access);
3465
+ return null;
3466
+ }
3467
+ /** Object.prototype members a plain record inherits, read as values. */
3468
+ const OBJECT_PROTOTYPE_VALUE_READS = new Set([
3469
+ "constructor",
3470
+ "valueOf",
3471
+ "toString",
3472
+ "hasOwnProperty",
3473
+ "propertyIsEnumerable",
3474
+ ]);
3475
+ /** Whether `expr` is the callee of a call (`o.toString()`), which keeps its
3476
+ * call lowering rather than reading the member as a value. */
3477
+ function isCalleeOf(expr) {
3478
+ let node = expr;
3479
+ while (node.parent !== undefined && ts.isParenthesizedExpression(node.parent))
3480
+ node = node.parent;
3481
+ const parent = node.parent;
3482
+ return (parent !== undefined &&
3483
+ (ts.isCallExpression(parent) || ts.isNewExpression(parent)) &&
3484
+ parent.expression === node);
3485
+ }
3486
+ /** The constructor a primitive dynamic value answers for `.constructor`:
3487
+ * the same interned closure the `Number`/`String`/`Boolean`/`BigInt`
3488
+ * identifiers read (dequal's `(ctor = foo.constructor) === bar.constructor`
3489
+ * over numbers), or `otherwise` for non-primitives. `value` must be safe to
3490
+ * read repeatedly. */
3491
+ export function primitiveConstructorOr(lowerer, value, otherwise, loc) {
3492
+ let result = otherwise;
3493
+ for (const [test, name] of [
3494
+ ["bigint", "BigInt"],
3495
+ ["boolean", "Boolean"],
3496
+ ["string", "String"],
3497
+ ["number", "Number"],
3498
+ ]) {
3499
+ result = {
3500
+ kind: "ternary",
3501
+ cond: { kind: "dynTest", test, value, type: BOOL, loc },
3502
+ then: {
3503
+ kind: "dynFrom",
3504
+ value: primitiveCtorClosure(lowerer, name, loc, true),
3505
+ type: DYN,
3506
+ loc,
3507
+ },
3508
+ else_: result,
3509
+ type: DYN,
3510
+ loc,
3511
+ };
3512
+ }
3513
+ return result;
3514
+ }
3515
+ /** True when `access` reads a member that JavaScript sources attach to a
3516
+ * function by assignment (`fn.member = value`): the receiver's type is
3517
+ * callable and every declaration of the member is such an assignment in a
3518
+ * JS file. */
3519
+ function jsFunctionExpandoMember(lowerer, access) {
3520
+ if (access.questionDotToken || !ts.isIdentifier(access.name))
3521
+ return false;
3522
+ const recvType = lowerer.typeOf(access.expression);
3523
+ if (lowerer.checker.getCallSignatures(recvType).length === 0)
3524
+ return false;
3525
+ const member = lowerer.checker.getPropertyOfType(recvType, access.name.text);
3526
+ const decls = member ? member.declarations : [];
3527
+ return (decls.length > 0 &&
3528
+ decls.every((d) => {
3529
+ if (!isJsSourceFile(ts.getSourceFileOfNode(d)))
3530
+ return false;
3531
+ const assign = ts.isBinaryExpression(d) ? d : d.parent;
3532
+ return (assign !== undefined &&
3533
+ ts.isBinaryExpression(assign) &&
3534
+ assign.operatorToken.kind === ts.SyntaxKind.EqualsToken &&
3535
+ ts.isPropertyAccessExpression(assign.left));
3536
+ }));
3537
+ }
3538
+ /** Whether the checker declares `name` as a property of `receiver`'s type
3539
+ * (as opposed to reading it through an index signature). */
3540
+ export function declaredMemberOf(lowerer, receiver, name) {
3541
+ const symbol = lowerer.checker.getPropertyOfType(lowerer.typeOf(receiver), name);
3542
+ return !!symbol && symbol.declarations.length > 0;
3543
+ }
3544
+ //# sourceMappingURL=property-access.js.map