@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,2483 @@
1
+ /* Binary operators: arithmetic, comparisons and equality, logical and nullish pairs, and string conversion for concatenation. */
2
+ import * as ts from "../../ts7/adapter.js";
3
+ import { cleanFuncAdaptable } from "../coercions/function-adapters.js";
4
+ import { jsFuncNameOf } from "../lowerer.js";
5
+ import { BIGINT_T, BOOL, DYN, DYN_HANDLE_KINDS, F64, REF_TRUTHY_KINDS, STRING, UNDEFINED_T, VOID, canBoxFuncIntoDyn, isUnitType, typeEquals, typeKey, } from "../../../ir/ir.js";
6
+ import { isSafeToDiscard, isSafeToRepeat } from "./evaluation-safety.js";
7
+ import { bigintCompoundValue, compoundUnsupported, concatOperand, constructorGlobalTypeof, deferredSlotOr, dynCompoundValue, lowerAbsenceProbe, lowerDynMemberAssignment, lowerOptionalNumber, lowerPresenceOperand, nullishBranches, operandPairs, operatorUnsupported, runtimeOptionalStorageOperand, symbolFieldInfo, typeofAnswer, } from "../lower-exprs.js";
8
+ import { COMPOUND_ASSIGN_OPS, NARROW_FIRST } from "../surfaces.js";
9
+ import { lowerElementCompoundParts } from "./element-access.js";
10
+ import { InternalCompilerError } from "../../../errors.js";
11
+ import { isJsSourceFile, locOf } from "../../program.js";
12
+ import { storedClassValueType } from "../lower-classes.js";
13
+ import { hasRuntimeStatics } from "../class-runtime-statics.js";
14
+ import { tryLowerExpression } from "./try-lower-expression.js";
15
+ import { fenceNodeModuleMutation, lowerRequireCacheHas } from "../lower-node-module.js";
16
+ import { errorToStringCall } from "../error-methods.js";
17
+ import { classToStringConversion, classUnionToString } from "../class-to-primitive.js";
18
+ import { isPerfEntryType, perfEntryTag } from "../builtins/performance.js";
19
+ import { guardNullProto, nullProtoRecordShape } from "../null-prototype.js";
20
+ import { numLit, varRef } from "../../../ir/build.js";
21
+ import { lowerUrlAssignment } from "../builtins/url.js";
22
+ import { lowerClassPrototypeComputedAssignment } from "../class-prototypes.js";
23
+ import { lowerShortCircuitAssignment } from "./nullish-assignment.js";
24
+ import { lowerEventObjectPropertyWrite } from "../lower-event-target.js";
25
+ import { lowerFieldCompoundValue } from "./updates.js";
26
+ import { expandoWritableTarget } from "../lower-expando.js";
27
+ import { nsWritableTarget } from "../lower-namespaces.js";
28
+ import { arrayValueStore, tryLowerBytesReadNumberEquality } from "../array-values.js";
29
+ import { cjsExportMemberWriteGlobalOf, cjsInFileExportGlobalOf } from "../cjs-exports-object.js";
30
+ import { lowerUnionFieldWrite } from "./union-fields.js";
31
+ import { lowerAbstractEquality } from "../abstract-equality.js";
32
+ import { lowerInExpression } from "./relational.js";
33
+ import { lowerDynTypeofTest, lowerErrorCodeTypeofTest } from "./typeof.js";
34
+ import { builtinClassRefOf, sameBuiltinClass } from "../builtins/class-values.js";
35
+ import { lowerRuntimeConstructorIs, runtimeConstructorReceiver, } from "../builtins/runtime-constructor.js";
36
+ import { tryLowerIndexedComparison } from "../indexed-comparison.js";
37
+ import { lowerUnionEquality, tagEqualityMayMissAlias } from "../strict-equality.js";
38
+ import { withUnitArm } from "../../type-mapper.js";
39
+ import { npmStaticPackageOfPath } from "../../npm-static.js";
40
+ import { lowerWebAssemblyTypeof } from "../builtins/webassembly.js";
41
+ /** `v === undefined` / `v !== null` — the narrowing tests for unit-armed
42
+ * unions. A union operand compared with a unit literal lowers to a
43
+ * runtime TAG test (unionIsTag); afterwards tsc's control-flow narrowing
44
+ * types the branches and reads bridge through maybeNarrow as usual. When
45
+ * the checker already narrowed the non-literal side PAST the union
46
+ * (`w = 5; if (w !== null)`), the comparison is statically decided and
47
+ * folds to a bool literal — that drops only a side-effect-free read
48
+ * (flow narrowing applies to references, never to calls), and soundness
49
+ * rests on the same narrowing proof unionNarrow relies on. Null when
50
+ * neither side is a unit literal (not a unit comparison). */
51
+ export function lowerUnitComparison(lowerer, left, right, negated, loc) {
52
+ const unit = left.kind === "unitLit" ? left : right.kind === "unitLit" ? right : null;
53
+ if (!unit)
54
+ return null;
55
+ const other = unit === left ? right : left;
56
+ if (other.kind === "unitLit") {
57
+ // Two unit literals (`undefined === undefined`): statically decided.
58
+ return { kind: "boolLit", value: (other.unit === unit.unit) !== negated, type: BOOL, loc };
59
+ }
60
+ const slot = lowerer.deferredFieldSlot(other);
61
+ if (slot)
62
+ return lowerUnitComparison(lowerer, slot, unit, negated, loc);
63
+ // A binding the checker narrowed past the unit can still hold it at
64
+ // runtime when its value came from an unassigned deferred-init field;
65
+ // the stored tag answers either way.
66
+ if (other.kind === "unionNarrow" &&
67
+ other.value.kind === "varRef" &&
68
+ other.value.type.kind === "union" &&
69
+ lowerer.armTag(other.value.type.unionId, unit.type) >= 0)
70
+ return lowerUnitComparison(lowerer, other.value, unit, negated, loc);
71
+ if (other.type.kind === "union") {
72
+ const tag = lowerer.armTag(other.type.unionId, unit.type);
73
+ if (tag < 0) {
74
+ // A union WITHOUT that unit arm: legal TS (`miss === null` on a
75
+ // `number | undefined` — null/undefined guard comparisons are
76
+ // permitted against nullable-adjacent types), and === never
77
+ // coerces, so the answer is the constant `negated`. The literal
78
+ // must NOT flow into the union representation (the unionEq
79
+ // fallback would coerce it through the stranded-arm trap and
80
+ // throw where Node answers false). JS still evaluates the
81
+ // operand, so a non-droppable one (`xs.find(f) === null` — the
82
+ // callback's effects are observable) rides one throwaway tag
83
+ // test; droppable reads fold to the bare literal.
84
+ const answer = { kind: "boolLit", value: negated, type: BOOL, loc };
85
+ if (isSafeToDiscard(other))
86
+ return answer;
87
+ const evalOnce = {
88
+ kind: "unionIsTag",
89
+ unionId: other.type.unionId,
90
+ tag: 0,
91
+ negated: false,
92
+ value: other,
93
+ type: BOOL,
94
+ loc,
95
+ };
96
+ return {
97
+ kind: "logical",
98
+ op: negated ? "||" : "&&",
99
+ left: evalOnce,
100
+ right: answer,
101
+ type: BOOL,
102
+ loc,
103
+ };
104
+ }
105
+ return {
106
+ kind: "unionIsTag",
107
+ unionId: other.type.unionId,
108
+ tag,
109
+ negated,
110
+ value: other,
111
+ type: BOOL,
112
+ loc,
113
+ };
114
+ }
115
+ // A process.env read tsc narrowed past its union (an earlier write to
116
+ // the same key): the environment is VOLATILE — `delete process.env.K`
117
+ // undoes the write the narrowing rode on — so folding would bake a
118
+ // stale answer. Compare the fresh read's union tag instead.
119
+ const envRead = volatileEnvRead(other);
120
+ if (envRead && envRead.type.kind === "union") {
121
+ const tag = lowerer.armTag(envRead.type.unionId, unit.type);
122
+ if (tag >= 0) {
123
+ return {
124
+ kind: "unionIsTag",
125
+ unionId: envRead.type.unionId,
126
+ tag,
127
+ negated,
128
+ value: envRead,
129
+ type: BOOL,
130
+ loc,
131
+ };
132
+ }
133
+ }
134
+ // A VOID-typed operand (`foo() === undefined` where foo's declared
135
+ // return is undefined/void — the mapping folds both to void): JS
136
+ // yields undefined from such a call, so the compare is TRUE-when-equal
137
+ // — the opposite of the never-holds-units fold below — and the IR has
138
+ // no value (nor a sequence form to keep the call's effects). Fall
139
+ // through to the caller's comparison fence instead of folding a lie.
140
+ if (other.type.kind === "void")
141
+ return null;
142
+ // Non-union operand: it can never hold undefined/null at runtime (the
143
+ // checker narrowed it to a concrete arm), so `=== unit` is false and
144
+ // `!== unit` is true.
145
+ return { kind: "boolLit", value: negated, type: BOOL, loc };
146
+ }
147
+ /** The union-typed process.envGet read inside a checker-narrowed operand,
148
+ * or null — the volatility escape above (and lowerLooseNullCompare's). */
149
+ function volatileEnvRead(e) {
150
+ if (e.kind === "libCall" && e.fn === "process.envGet")
151
+ return e;
152
+ if (e.kind === "unionNarrow" && e.value.kind === "libCall" && e.value.fn === "process.envGet") {
153
+ return e.value;
154
+ }
155
+ return null;
156
+ }
157
+ function lowerLooseNullCompare(lowerer, expr, loc) {
158
+ const negated = expr.operatorToken.kind === ts.SyntaxKind.ExclamationEqualsToken;
159
+ const unwrap = (e) => ts.isParenthesizedExpression(e) ? unwrap(e.expression) : e;
160
+ const left = unwrap(expr.left);
161
+ const right = unwrap(expr.right);
162
+ const leftIsNull = left.kind === ts.SyntaxKind.NullKeyword;
163
+ if (!leftIsNull && right.kind !== ts.SyntaxKind.NullKeyword)
164
+ return null;
165
+ const otherNode = leftIsNull ? right : left;
166
+ const other = lowerPresenceOperand(lowerer, otherNode);
167
+ if (isUnitType(other.type)) {
168
+ // `null == null`, `undefined == null`: units are mutually loose-equal.
169
+ return { kind: "boolLit", value: !negated, type: BOOL, loc };
170
+ }
171
+ if (other.type.kind === "dyn") {
172
+ // `v != null` on unknown: one dyn kind test covers both units.
173
+ return {
174
+ kind: "dynTest",
175
+ test: "nullish",
176
+ ...(negated ? { negated: true } : {}),
177
+ value: other,
178
+ type: BOOL,
179
+ loc,
180
+ };
181
+ }
182
+ if (other.type.kind === "union") {
183
+ const ut = other.type;
184
+ const def = lowerer.unions.get(ut.unionId);
185
+ if (!def)
186
+ lowerer.badType(otherNode, lowerer.typeOf(otherNode));
187
+ const tags = def.arms.flatMap((a, i) => (isUnitType(a) ? [i] : []));
188
+ if (tags.length === 0) {
189
+ // No unit arms: never null-ish (defensive — the fold below).
190
+ return { kind: "boolLit", value: negated, type: BOOL, loc };
191
+ }
192
+ const isTag = (tag) => ({
193
+ kind: "unionIsTag",
194
+ unionId: ut.unionId,
195
+ tag,
196
+ negated,
197
+ value: other,
198
+ type: BOOL,
199
+ loc,
200
+ });
201
+ if (tags.length === 1)
202
+ return isTag(tags[0]);
203
+ // Both null AND undefined arms: tag-in-set as a short-circuit pair
204
+ // (De Morgan for `!=`). The operand IrExpr rides both tests, so the
205
+ // backend emits it per test — restricted to re-emittable pure reads;
206
+ // anything effectful gets its own actionable fence (the generic
207
+ // SC1040 hint would wrongly suggest `== null` as the fix).
208
+ if (!isSafeToRepeat(other)) {
209
+ lowerer.unsupported("SC1090", expr, `'== null' / '!= null' on a '${lowerer.fmt(ut)}' value that isn't a plain read ` +
210
+ `(both unit arms need the operand twice — bind it to a const first)`);
211
+ }
212
+ return {
213
+ kind: "logical",
214
+ op: negated ? "&&" : "||",
215
+ left: isTag(tags[0]),
216
+ right: isTag(tags[1]),
217
+ type: BOOL,
218
+ loc,
219
+ };
220
+ }
221
+ if (other.type.kind === "void") {
222
+ return null; // no static tag to test — keep the fence
223
+ }
224
+ // The env-volatility escape (see lowerUnitComparison): a narrowed
225
+ // process.env read compares its FRESH union tag instead of folding.
226
+ const envRead = volatileEnvRead(other);
227
+ if (envRead && envRead.type.kind === "union") {
228
+ const def = lowerer.unions.get(envRead.type.unionId);
229
+ const tag = def ? def.arms.findIndex((a) => isUnitType(a)) : -1;
230
+ if (tag >= 0) {
231
+ return {
232
+ kind: "unionIsTag",
233
+ unionId: envRead.type.unionId,
234
+ tag,
235
+ negated,
236
+ value: envRead,
237
+ type: BOOL,
238
+ loc,
239
+ };
240
+ }
241
+ }
242
+ // A non-nullable operand (tsc allows the comparison as a guard):
243
+ // `== null` is statically false, `!= null` statically true.
244
+ return { kind: "boolLit", value: negated, type: BOOL, loc };
245
+ }
246
+ /** A plain value read that may be runtime-optional: an unchecked element
247
+ * read, or a binding, member or call that carries one. Lowering these
248
+ * without a destination type is the same as lowering them into one. */
249
+ function isPlainValueRead(node) {
250
+ while (ts.isParenthesizedExpression(node))
251
+ node = node.expression;
252
+ return (ts.isElementAccessExpression(node) ||
253
+ ts.isIdentifier(node) ||
254
+ ts.isPropertyAccessExpression(node) ||
255
+ ts.isCallExpression(node));
256
+ }
257
+ /** A member access or call receiver needs the present value itself (JS
258
+ * throws a TypeError reading a member of undefined). */
259
+ function isMemberReceiver(node) {
260
+ let child = node;
261
+ let parent = node.parent;
262
+ while (ts.isParenthesizedExpression(parent)) {
263
+ child = parent;
264
+ parent = parent.parent;
265
+ }
266
+ return (((ts.isPropertyAccessExpression(parent) ||
267
+ ts.isElementAccessExpression(parent) ||
268
+ ts.isCallExpression(parent)) &&
269
+ parent.expression === child) ||
270
+ (ts.isTaggedTemplateExpression(parent) && parent.tag === child));
271
+ }
272
+ export function lowerNullishPair(lowerer, expr, loc, left) {
273
+ if (left.type.kind === "dyn") {
274
+ // `a ?? b` on a CHECKED-DYNAMIC left: the deciding test is the
275
+ // runtime kind (scr_dyn_is_nullish — UNDEF/NULL take the default).
276
+ // Both sides live in the checked-dynamic tree — the right converts through
277
+ // the usual boundary and evaluates lazily in its branch; a default
278
+ // with no dyn representation keeps the fence.
279
+ const right = lowerer.coerceToExpected(lowerer.lowerExpr(expr.right), DYN);
280
+ if (right.type.kind !== "dyn") {
281
+ lowerer.unsupported("SC1100", expr, "nullish coalescing on 'unknown' values against defaults with no dynamic representation");
282
+ }
283
+ return { kind: "nullish", left, right, type: DYN, loc };
284
+ }
285
+ if (left.type.kind !== "union")
286
+ return left;
287
+ const def = lowerer.unions.get(left.type.unionId);
288
+ if (!def)
289
+ lowerer.badType(expr.left, lowerer.typeOf(expr.left));
290
+ if (!def.arms.some(isUnitType))
291
+ return left;
292
+ const rest = def.arms.filter((a) => !isUnitType(a));
293
+ // `optionalMap ?? new Map()` carries its element contract on the left;
294
+ // the empty fallback may use it without constructing a Map<any, any>
295
+ // arm that has no first-class union representation.
296
+ const fresh = rest.length === 1 ? lowerer.emptyCollectionFor(expr.right, rest[0]) : null;
297
+ if (fresh)
298
+ return { kind: "nullish", left, right: fresh, type: fresh.type, loc };
299
+ let type = lowerer.irTypeOf(expr);
300
+ // A runtime-optional read can reach the default even when declarations
301
+ // call the left side present. Preserve a differently typed primitive
302
+ // fallback rather than checking it against that incomplete result type.
303
+ const rightType = lowerer.mapTypeOf(lowerer.typeOf(expr.right));
304
+ const primitive = (t) => t.kind === "f64" || t.kind === "string" || t.kind === "bool";
305
+ if (rightType &&
306
+ primitive(type) &&
307
+ primitive(rightType) &&
308
+ !typeEquals(type, rightType) &&
309
+ rest.every(primitive)) {
310
+ const arms = [...rest];
311
+ if (!arms.some((arm) => typeEquals(arm, rightType)))
312
+ arms.push(rightType);
313
+ arms.sort((a, b) => (typeKey(a) < typeKey(b) ? -1 : 1));
314
+ type = { kind: "union", unionId: lowerer.unions.intern(arms) };
315
+ lowerer.runtimeOptionalArithmeticTypes.set(expr, type);
316
+ }
317
+ if (type.kind === "dyn" && lowerer.dynConvertible(left.type)) {
318
+ return {
319
+ kind: "nullish",
320
+ left: lowerer.coerceToExpected(left, DYN),
321
+ right: lowerer.lowerExprExpecting(expr.right, DYN),
322
+ type: DYN,
323
+ loc,
324
+ };
325
+ }
326
+ // A runtime-optional default (`name ?? names[0]`): the checker types an
327
+ // unchecked element read as the bare element type, but an out-of-range
328
+ // read is undefined at runtime. When the default shares the left's
329
+ // optional union, that union is the result, so the undefined state
330
+ // reaches the consumer (an optional return or parameter takes it as its
331
+ // undefined arm; a plain slot still extracts the element with its
332
+ // checked narrow).
333
+ if (rest.length === 1 &&
334
+ typeEquals(type, rest[0]) &&
335
+ isPlainValueRead(expr.right) &&
336
+ !isMemberReceiver(expr)) {
337
+ const raw = lowerer.lowerExpr(expr.right);
338
+ if (typeEquals(raw.type, left.type))
339
+ return { kind: "nullish", left, right: raw, type: left.type, loc };
340
+ // `names[0] ?? undefined`: an explicit unit default stays the left's arm.
341
+ if (isUnitType(raw.type) && lowerer.armTag(left.type.unionId, raw.type) >= 0) {
342
+ const right = lowerer.coerceInto(expr.right, raw, left.type);
343
+ return { kind: "nullish", left, right, type: left.type, loc };
344
+ }
345
+ return { kind: "nullish", left, right: lowerer.coerceInto(expr.right, raw, type), type, loc };
346
+ }
347
+ if (typeEquals(type, left.type) || (rest.length === 1 && typeEquals(type, rest[0]))) {
348
+ const right = lowerer.lowerExprExpecting(expr.right, type);
349
+ return { kind: "nullish", left, right, type, loc };
350
+ }
351
+ if (type.kind !== "union" && rest.length > 1 && rest.some((arm) => typeEquals(arm, type))) {
352
+ const helper = lowerer.narrowedArmHelper(left.type.unionId, type, loc);
353
+ if (helper !== null) {
354
+ return nullishBranches(lowerer, left, left.type, def.arms, type, loc, () => lowerer.lowerExprExpecting(expr.right, type), (stable) => ({ kind: "call", callee: helper, args: [stable], type, loc }));
355
+ }
356
+ }
357
+ // A subclass value defaulted to a base-class value (`circle ?? shape`):
358
+ // the present arm upcasts after the original nullish test, and the
359
+ // default lowers lazily into the base-class result.
360
+ const present = rest.length === 1 ? rest[0] : null;
361
+ if (present?.kind === "object" &&
362
+ type.kind === "object" &&
363
+ present.className !== type.className &&
364
+ lowerer.isSubclassOf(present.className, type.className)) {
365
+ const helper = lowerer.narrowedArmHelper(left.type.unionId, present, loc);
366
+ if (helper !== null) {
367
+ return nullishBranches(lowerer, left, left.type, def.arms, type, loc, () => lowerer.lowerExprExpecting(expr.right, type), (stable) => ({
368
+ kind: "upcast",
369
+ value: { kind: "call", callee: helper, args: [stable], type: present, loc },
370
+ type,
371
+ loc,
372
+ }));
373
+ }
374
+ }
375
+ // A default may change the union or widen its records. Test the
376
+ // original tag before coercing: converting the whole left first can
377
+ // lose nullish arms, and evaluating the default eagerly loses laziness.
378
+ if (type.kind === "union") {
379
+ const retag = lowerer.unionRetagHelper(left.type.unionId, type.unionId, loc) ??
380
+ lowerer.narrowedRetagHelper(expr.left, left.type.unionId, type.unionId, loc);
381
+ if (retag !== null) {
382
+ // Narrowing may exclude a record/class arm while storage retains
383
+ // it. The checked retag traps that impossible arm, but only AFTER
384
+ // the original nullish test: null/undefined must reach the lazy
385
+ // default even when neither is representable in the result.
386
+ return nullishBranches(lowerer, left, left.type, def.arms, type, loc, () => lowerer.lowerExprExpecting(expr.right, type), (stable) => ({ kind: "call", callee: retag, args: [stable], type, loc }));
387
+ }
388
+ }
389
+ // An optional callback defaulted to a function of another signature
390
+ // (`o.tags ?? (() => ({}))`, fewer parameters or a narrower result): the
391
+ // result is the callback's own function type, and the default adapts into
392
+ // it (JavaScript ignores surplus arguments). The checker's merged union
393
+ // signature would lose the callback's result shape.
394
+ if (present?.kind === "func" && present.rest !== true) {
395
+ const raw = lowerer.lowerExpr(expr.right);
396
+ if (raw.type.kind === "func" &&
397
+ (typeEquals(raw.type, present) || cleanFuncAdaptable(lowerer, raw.type, present))) {
398
+ const right = lowerer.coerceInto(expr.right, raw, present);
399
+ lowerer.nullishFuncResults.add(expr);
400
+ return { kind: "nullish", left, right, type: present, loc };
401
+ }
402
+ }
403
+ lowerer.unsupported("SC1090", expr, rest.length !== 1
404
+ ? `'??' on '${lowerer.fmt(left.type)}' (the non-nullish result is a sub-union; check a discriminant field first)`
405
+ : `'??' where the default changes the result type (left is '${lowerer.fmt(left.type)}' but the whole expression is '${lowerer.fmt(type)}' — give both sides one type)`);
406
+ }
407
+ /** `a[i] op= rhs` over native arrays and byte views. A compound assignment
408
+ * evaluates the receiver and index, reads the old element, evaluates rhs,
409
+ * then writes. Capture each stage so a call in the index or rhs cannot
410
+ * change the target or the value used by the operator. The expression yields
411
+ * the computed value before a typed array or Buffer coerces it for storage. */
412
+ export function lowerElementCompound(lowerer, expr, op) {
413
+ const lowered = lowerElementCompoundParts(lowerer, expr, op, false);
414
+ if (!lowered.expr)
415
+ throw new InternalCompilerError("a compound element value lowered to statements");
416
+ return lowered.expr;
417
+ }
418
+ /** JavaScript callable members live on the closure, so aliases and chained
419
+ * writes share the same storage as Object.defineProperties. */
420
+ export function lowerNativeFunctionAssignment(lowerer, expr) {
421
+ const target = expr.left;
422
+ if (!isJsSourceFile(ts.getSourceFileOfNode(expr)) ||
423
+ (!ts.isPropertyAccessExpression(target) && !ts.isElementAccessExpression(target)) ||
424
+ target.questionDotToken)
425
+ return null;
426
+ // Checked constructors share the callable's live property descriptors.
427
+ const classType = storedClassValueType(lowerer, target.expression);
428
+ const staticClass = classType?.kind === "classval" ? lowerer.classes.get(classType.className) : undefined;
429
+ if (staticClass && hasRuntimeStatics(staticClass)) {
430
+ return lowerDynMemberAssignment(lowerer, expr, lowerer.lowerExprExpecting(target.expression, DYN));
431
+ }
432
+ // Other class statics and prototype tables have their own paths.
433
+ // Probing them as ordinary functions could materialize unused methods.
434
+ if (lowerer.exactClassOfReceiver(target.expression) ||
435
+ (ts.isPropertyAccessExpression(target.expression) &&
436
+ target.expression.name.text === "prototype" &&
437
+ lowerer.exactClassOfReceiver(target.expression.expression)))
438
+ return null;
439
+ const receiver = tryLowerExpression(lowerer, target.expression);
440
+ if (receiver?.type.kind !== "func" ||
441
+ !canBoxFuncIntoDyn(receiver.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id)))
442
+ return null;
443
+ fenceNodeModuleMutation(lowerer, target, "assignment");
444
+ const fnName = jsFuncNameOf(target.expression);
445
+ const boxed = {
446
+ kind: "dynFrom",
447
+ value: receiver,
448
+ type: DYN,
449
+ loc: locOf(target.expression),
450
+ ...(fnName !== null ? { fnName } : {}),
451
+ };
452
+ return lowerDynMemberAssignment(lowerer, expr, boxed);
453
+ }
454
+ /** `typeof globalThis.AbortSignal.any === "function"`: the comparison
455
+ * folds with constructorGlobalTypeof's answer. */
456
+ function lowerConstructorGlobalTypeofTest(lowerer, expr, loc) {
457
+ const negated = expr.operatorToken.kind === ts.SyntaxKind.ExclamationEqualsEqualsToken;
458
+ for (const [a, b] of operandPairs(expr)) {
459
+ if (!ts.isTypeOfExpression(a) || !ts.isStringLiteral(b))
460
+ continue;
461
+ const answer = constructorGlobalTypeof(lowerer, a.expression);
462
+ if (answer !== null)
463
+ return { kind: "boolLit", value: (answer === b.text) !== negated, type: BOOL, loc };
464
+ }
465
+ return null;
466
+ }
467
+ export function ensureString(lowerer, e, node) {
468
+ if (e.type.kind === "string")
469
+ return e;
470
+ if (e.type.kind === "url")
471
+ return { kind: "libCall", fn: "url.href", args: [e], type: STRING, loc: e.loc };
472
+ // String(date) / `${date}` / "" + date: Date's ToPrimitive prefers
473
+ // toString().
474
+ if (e.type.kind === "date")
475
+ return { kind: "libCall", fn: "date.toString", args: [e], type: STRING, loc: e.loc };
476
+ if (e.type.kind === "regex") {
477
+ return {
478
+ kind: "regexIntrinsic",
479
+ method: "toString",
480
+ receiver: e,
481
+ args: [],
482
+ type: STRING,
483
+ loc: e.loc,
484
+ };
485
+ }
486
+ if (e.type.kind === "bigint") {
487
+ return {
488
+ kind: "libCall",
489
+ fn: "bigint.toString",
490
+ args: [e, { kind: "numLit", value: 10, type: F64, loc: e.loc }],
491
+ type: STRING,
492
+ loc: e.loc,
493
+ };
494
+ }
495
+ if (e.type.kind === "dyn") {
496
+ // String(u) / `${u}`: a runtime dispatch over the dyn kind — Node's
497
+ // String() exactly (undefined/null texts, JS number formatting,
498
+ // strings verbatim, arrays via join, objects as "[object Object]").
499
+ return { kind: "toString", operand: e, type: STRING, loc: e.loc };
500
+ }
501
+ if (e.type.kind === "bytes") {
502
+ // Preserve the runtime brand: typed arrays join numeric elements,
503
+ // while a Buffer stored in a Uint8Array slot decodes its bytes.
504
+ const boxed = { kind: "dynFrom", value: e, type: DYN, loc: e.loc };
505
+ return { kind: "toString", operand: boxed, type: STRING, loc: e.loc };
506
+ }
507
+ if (e.type.kind === "object") {
508
+ // String(err) / `${err}` uses the same dispatch as err.toString().
509
+ for (let c = lowerer.classes.get(e.type.className) ?? null; c; c = c.base) {
510
+ if (c.builtinError) {
511
+ return errorToStringCall(lowerer, e);
512
+ }
513
+ }
514
+ // A program class instance converts through its own methods.
515
+ const converted = classToStringConversion(lowerer, e, "string", node);
516
+ if (converted)
517
+ return converted;
518
+ }
519
+ if (e.type.kind === "union") {
520
+ // `${u}` — the arm's ToString via a per-union interned helper
521
+ // (sc_us_*), Node-exact per arm kind: unit arms are the known texts
522
+ // "undefined"/"null", string arms pass through, f64/bool arms use the
523
+ // JS-exact formatters. Ref arms (records, arrays, ...) stay fenced:
524
+ // JS would print "[object Object]" and friends — narrow first.
525
+ const def = lowerer.unions.get(e.type.unionId);
526
+ const stringable = def?.arms.every((a) => a.kind === "undefinedT" ||
527
+ a.kind === "nullT" ||
528
+ a.kind === "string" ||
529
+ a.kind === "f64" ||
530
+ a.kind === "bigint" ||
531
+ a.kind === "bool");
532
+ if (stringable) {
533
+ return { kind: "toString", operand: e, type: STRING, loc: e.loc };
534
+ }
535
+ // Runtime-optional locals can retain their stored union after the
536
+ // checker has narrowed this use to a primitive arm. Validate that
537
+ // arm before converting it; an unguarded object arm stays fenced.
538
+ const narrowed = lowerer.mapTypeOf(lowerer.typeOf(node));
539
+ if (narrowed &&
540
+ (narrowed.kind === "string" ||
541
+ narrowed.kind === "f64" ||
542
+ narrowed.kind === "bool" ||
543
+ narrowed.kind === "bigint")) {
544
+ const helper = lowerer.narrowedArmHelper(e.type.unionId, narrowed, e.loc);
545
+ if (helper) {
546
+ return ensureString(lowerer, lowerer.checkedNarrowCall(helper, e, narrowed, e.loc), node);
547
+ }
548
+ }
549
+ if (narrowed?.kind === "union" &&
550
+ !typeEquals(narrowed, e.type) &&
551
+ lowerer.unions
552
+ .get(narrowed.unionId)
553
+ ?.arms.every((arm) => isUnitType(arm) ||
554
+ arm.kind === "string" ||
555
+ arm.kind === "f64" ||
556
+ arm.kind === "bool" ||
557
+ arm.kind === "bigint")) {
558
+ const helper = lowerer.narrowedRetagHelper(node, e.type.unionId, narrowed.unionId, e.loc);
559
+ if (helper)
560
+ return ensureString(lowerer, { kind: "call", callee: helper, args: [e], type: narrowed, loc: e.loc }, node);
561
+ }
562
+ const viaClasses = classUnionToString(lowerer, e, "string", node);
563
+ if (viaClasses)
564
+ return viaClasses;
565
+ lowerer.unsupported("SC1090", node, `string conversions of unions with object arms (${NARROW_FIRST})`);
566
+ }
567
+ if (e.type.kind === "symbol") {
568
+ // JS splits here: `${sym}` and concatenation THROW a TypeError,
569
+ // String(sym) answers "Symbol(desc)". One shared lowering cannot
570
+ // honor both — fence with the sanctioned spelling instead of
571
+ // guessing the context.
572
+ lowerer.unsupported("SC1090", node, "string conversions of symbol values (template literals throw in JS — call .toString() explicitly)");
573
+ }
574
+ if (isUnitType(e.type)) {
575
+ if (e.kind === "unitLit") {
576
+ return { kind: "strLit", value: e.unit, type: STRING, loc: e.loc };
577
+ }
578
+ // Keep sequencing and branch effects even though the final unit's
579
+ // spelling is constant. Never turn an unknown producer into a literal.
580
+ if (e.kind === "seqExpr") {
581
+ return { ...e, result: lowerer.ensureString(e.result, node), type: STRING };
582
+ }
583
+ if (e.kind === "ternary") {
584
+ return {
585
+ ...e,
586
+ then: lowerer.ensureString(e.then, node),
587
+ else_: lowerer.ensureString(e.else_, node),
588
+ type: STRING,
589
+ };
590
+ }
591
+ lowerer.unsupported("SC1090", node, `string conversions of '${e.type.kind === "undefinedT" ? "undefined" : "null"}' values`);
592
+ }
593
+ if (e.type.kind === "array") {
594
+ // `${[1,2,3]}` / String(arr): Array.prototype.toString IS join(",")
595
+ // — the SAME intrinsic the .join() lowering emits, fenced to the
596
+ // same element kinds (f64/string/bool, unions of those with unit
597
+ // arms printing empty). Nested arrays would need JS's recursive
598
+ // dispatch — the join fence already tells that story.
599
+ const elem = e.type.elem;
600
+ const joinableUnion = elem.kind === "union" &&
601
+ (lowerer.unions
602
+ .get(elem.unionId)
603
+ ?.arms.every((a) => a.kind === "f64" || a.kind === "string" || a.kind === "bool" || isUnitType(a)) ??
604
+ false);
605
+ if (elem.kind === "f64" || elem.kind === "string" || elem.kind === "bool" || joinableUnion) {
606
+ const sep = { kind: "strLit", value: ",", type: STRING, loc: e.loc };
607
+ return {
608
+ kind: "arrIntrinsic",
609
+ method: "join",
610
+ receiver: e,
611
+ args: [sep],
612
+ type: STRING,
613
+ loc: e.loc,
614
+ };
615
+ }
616
+ }
617
+ if (e.type.kind === "record") {
618
+ // `${obj}` / String(obj): a plain data record has no toString of its
619
+ // own (a func-typed `toString` FIELD would shadow the prototype's —
620
+ // JS would call it, so that shape keeps the fence), and a TUPLE
621
+ // prints its elements like an array (not lowered — fenced) — every
622
+ // other record is Object.prototype.toString's constant.
623
+ const shape = lowerer.shapes.get(e.type.shapeId);
624
+ if (isPerfEntryType(lowerer, e.type))
625
+ return perfEntryTag(lowerer, e, e.type, e.loc);
626
+ if (shape && !shape.tuple && !shape.fields.some((f) => f.name === "toString")) {
627
+ // A null-prototype record (Object.groupBy) has no toString or
628
+ // valueOf: ToPrimitive throws Node's TypeError.
629
+ const nullProtoT = nullProtoRecordShape(lowerer, e.type);
630
+ if (nullProtoT)
631
+ return nullProtoToString(lowerer, e, nullProtoT);
632
+ return { kind: "toString", operand: e, type: STRING, loc: e.loc };
633
+ }
634
+ }
635
+ if (e.type.kind !== "f64" && e.type.kind !== "bool")
636
+ lowerer.badType(node, lowerer.typeOf(node));
637
+ return { kind: "toString", operand: e, type: STRING, loc: e.loc };
638
+ }
639
+ /** String(r) over a record that may have a null prototype: an interned
640
+ * helper that throws Node's TypeError for a null-prototype record and
641
+ * answers "[object Object]" otherwise. */
642
+ function nullProtoToString(lowerer, e, t) {
643
+ const loc = e.loc;
644
+ const key = `nullProtoToString:${t.shapeId}`;
645
+ let helper = lowerer.valueHelpers.get(key);
646
+ if (!helper) {
647
+ helper = `%rec.tostr.${lowerer.valueHelpers.size}`;
648
+ lowerer.valueHelpers.set(key, helper);
649
+ const r = varRef("r.0", t, loc);
650
+ lowerer.liftedFns.push({
651
+ name: helper,
652
+ params: [{ localId: "r.0", name: "r", type: t }],
653
+ returnType: STRING,
654
+ locals: [{ id: "r.0", name: "r", type: t, mutable: false }],
655
+ body: [
656
+ {
657
+ kind: "return",
658
+ value: guardNullProto(r, t.shapeId, "Cannot convert object to primitive value", { kind: "toString", operand: r, type: STRING, loc }, loc),
659
+ loc,
660
+ },
661
+ ],
662
+ loc,
663
+ });
664
+ }
665
+ return { kind: "call", callee: helper, args: [e], type: STRING, loc };
666
+ }
667
+ /** Whether a lowered statement can live inside a seqExpr. These statements
668
+ * do not leave the expression through a jump; the native emitters can place
669
+ * their writes and local state branches before evaluating the final result.
670
+ * Blocks check their bodies recursively. */
671
+ function seqExprSafeStmt(s) {
672
+ switch (s.kind) {
673
+ case "varDecl":
674
+ case "assign":
675
+ case "exprStmt":
676
+ case "fieldSet":
677
+ case "recordSet":
678
+ case "recordKeySet":
679
+ case "arraySet":
680
+ case "arraySetLength":
681
+ case "bytesSet":
682
+ case "arraySetUndefined":
683
+ case "arrayDelete":
684
+ return true;
685
+ case "if":
686
+ return s.then.every(seqExprSafeStmt) && (s.else_?.every(seqExprSafeStmt) ?? true);
687
+ case "block":
688
+ return s.body.every(seqExprSafeStmt);
689
+ default:
690
+ return false;
691
+ }
692
+ }
693
+ export function lowerCompoundValueToTarget(lowerer, expr, compound, target) {
694
+ const loc = locOf(expr);
695
+ const read = {
696
+ kind: "varRef",
697
+ localId: target.id,
698
+ type: target.type,
699
+ loc: locOf(expr.left),
700
+ };
701
+ const rhs = lowerer.lowerExpr(expr.right);
702
+ const numericRead = lowerOptionalNumber(lowerer, read, loc);
703
+ const numericRhs = lowerOptionalNumber(lowerer, rhs, loc);
704
+ if (compound === "+" &&
705
+ (target.type.kind === "string" ||
706
+ (target.type.kind === "union" &&
707
+ lowerer.stripUndefinedArm(target.type).kind === "string" &&
708
+ rhs.type.kind === "string"))) {
709
+ return lowerer.coerceInto(expr, {
710
+ kind: "strConcat",
711
+ left: lowerer.ensureString(read, expr.left),
712
+ right: concatOperand(lowerer, rhs, expr.right),
713
+ type: STRING,
714
+ loc,
715
+ }, target.type);
716
+ }
717
+ if (numericRead.type.kind === "f64" && numericRhs.type.kind === "f64") {
718
+ return lowerer.coerceInto(expr, { kind: "bin", op: compound, left: numericRead, right: numericRhs, type: F64, loc }, target.type);
719
+ }
720
+ // An untyped operand: exactly the expanded `x = x op rhs` — the runtime
721
+ // operator on both values, then the checked conversion into the
722
+ // target's declared type (a string result for a number target throws the
723
+ // catchable TypeError, as the expanded assignment does).
724
+ if ((target.type.kind === "dyn" || rhs.type.kind === "dyn") &&
725
+ (isJsSourceFile(ts.getSourceFileOfNode(expr)) ||
726
+ (lowerer.dynConvertible(read.type) && lowerer.dynConvertible(rhs.type)))) {
727
+ const left = lowerer.coerceInto(expr.left, read, DYN);
728
+ const right = lowerer.coerceInto(expr.right, rhs, DYN);
729
+ return lowerer.coerceInto(expr, dynCompoundValue(compound, left, right, loc), target.type);
730
+ }
731
+ const bigint = bigintCompoundValue(compound, read, rhs, loc);
732
+ if (bigint)
733
+ return bigint;
734
+ compoundUnsupported(lowerer, expr, compound, read.type, rhs.type);
735
+ }
736
+ /** Equality of two NaN-coded values (nan-coded-reads.ts), each of which may
737
+ * stand for undefined and never holds a genuine NaN: Node's undefined equals
738
+ * undefined, so two NaNs compare equal here. Operands evaluate once, in
739
+ * order. */
740
+ function lowerNanCodedEquality(lowerer, expr) {
741
+ const loc = locOf(expr);
742
+ const left = lowerer.lowerExpr(expr.left);
743
+ const right = lowerer.lowerExpr(expr.right);
744
+ if (left.type.kind !== "f64" || right.type.kind !== "f64") {
745
+ throw new InternalCompilerError("NaN-coded equality operand is not a plain number");
746
+ }
747
+ const stmts = [];
748
+ const stable = (value, name) => {
749
+ if (value.kind === "varRef" || value.kind === "numLit")
750
+ return value;
751
+ const tmp = lowerer.declareHiddenLocal(name, F64);
752
+ stmts.push({ kind: "varDecl", localId: tmp.id, init: value, loc });
753
+ return varRef(tmp.id, F64, loc);
754
+ };
755
+ const a = stable(left, "%eqLeft");
756
+ const b = stable(right, "%eqRight");
757
+ const isNaN = (value) => ({
758
+ kind: "libCall",
759
+ fn: "num.isNaN",
760
+ args: [value],
761
+ type: BOOL,
762
+ loc,
763
+ });
764
+ const bothUndefined = {
765
+ kind: "logical",
766
+ op: "&&",
767
+ left: isNaN(a),
768
+ right: isNaN(b),
769
+ type: BOOL,
770
+ loc,
771
+ };
772
+ const op = expr.operatorToken.kind;
773
+ const negated = op === ts.SyntaxKind.ExclamationEqualsEqualsToken ||
774
+ op === ts.SyntaxKind.ExclamationEqualsToken;
775
+ const result = negated
776
+ ? {
777
+ kind: "logical",
778
+ op: "&&",
779
+ left: { kind: "bin", op: "!==", left: a, right: b, type: BOOL, loc },
780
+ right: { kind: "unary", op: "!", operand: bothUndefined, type: BOOL, loc },
781
+ type: BOOL,
782
+ loc,
783
+ }
784
+ : {
785
+ kind: "logical",
786
+ op: "||",
787
+ left: { kind: "bin", op: "===", left: a, right: b, type: BOOL, loc },
788
+ right: bothUndefined,
789
+ type: BOOL,
790
+ loc,
791
+ };
792
+ return stmts.length === 0 ? result : { kind: "seqExpr", stmts, result, type: BOOL, loc };
793
+ }
794
+ export function lowerBinary(lowerer, expr) {
795
+ const loc = locOf(expr);
796
+ const op = expr.operatorToken.kind;
797
+ const cacheHas = lowerRequireCacheHas(lowerer, expr);
798
+ if (cacheHas)
799
+ return cacheHas;
800
+ if (lowerer.nanCodedReads?.needsUndefinedEquality(expr)) {
801
+ const undefinedEquality = lowerNanCodedEquality(lowerer, expr);
802
+ if (undefinedEquality)
803
+ return undefinedEquality;
804
+ }
805
+ if (op === ts.SyntaxKind.EqualsToken ||
806
+ (op >= ts.SyntaxKind.FirstCompoundAssignment && op <= ts.SyntaxKind.LastCompoundAssignment)) {
807
+ const urlWrite = lowerUrlAssignment(lowerer, expr);
808
+ if (urlWrite)
809
+ return urlWrite;
810
+ if (op === ts.SyntaxKind.EqualsToken) {
811
+ const prototypeWrite = lowerClassPrototypeComputedAssignment(lowerer, expr);
812
+ if (prototypeWrite)
813
+ return prototypeWrite;
814
+ const callableWrite = lowerNativeFunctionAssignment(lowerer, expr);
815
+ if (callableWrite)
816
+ return callableWrite;
817
+ }
818
+ if (op === ts.SyntaxKind.QuestionQuestionEqualsToken ||
819
+ op === ts.SyntaxKind.AmpersandAmpersandEqualsToken ||
820
+ op === ts.SyntaxKind.BarBarEqualsToken) {
821
+ return lowerShortCircuitAssignment(lowerer, expr);
822
+ }
823
+ if (ts.isPropertyAccessExpression(expr.left) || ts.isElementAccessExpression(expr.left)) {
824
+ fenceNodeModuleMutation(lowerer, expr.left, "assignment");
825
+ }
826
+ // The writable Event accessors on Event subclass instances, in value
827
+ // position (`const r = (event.returnValue = false)`).
828
+ if (op === ts.SyntaxKind.EqualsToken && ts.isPropertyAccessExpression(expr.left)) {
829
+ const eventWrite = lowerEventObjectPropertyWrite(lowerer, expr.left, expr.right);
830
+ if (eventWrite)
831
+ return eventWrite;
832
+ }
833
+ // `x = e` in EXPRESSION position (`while ((idx = s.indexOf("\n")) !== -1)`,
834
+ // `f(x = v)`): evaluate e once, write the binding, yield the assigned
835
+ // value — JS evaluation order. Variable targets only (locals and module
836
+ // globals, captured/boxed included); the RHS coerces into the binding's
837
+ // type exactly like statement position, and the expression's value is
838
+ // the coerced binding-typed value (representation change only — never
839
+ // observably different from JS's raw-RHS yield). Indexed compounds
840
+ // use a sequenced read/modify/write; other member targets and
841
+ // destructuring targets stay fenced.
842
+ if (op === ts.SyntaxKind.EqualsToken && ts.isIdentifier(expr.left)) {
843
+ const target = lowerer.resolveWritable(expr.left);
844
+ if (!target) {
845
+ lowerer.rejectUnresolved(expr.left, `assignment to '${expr.left.text}' (not a writable local or module global)`);
846
+ }
847
+ const value = lowerer.lowerExprExpecting(expr.right, target.type);
848
+ const runtimeOptionalRoot = lowerer.runtimeOptionalRootOf(target);
849
+ if (lowerer.runtimeOptionalStorageLocals.has(runtimeOptionalRoot))
850
+ lowerer.runtimeOptionalLocals.add(runtimeOptionalRoot);
851
+ return { kind: "assignExpr", localId: target.id, value, type: target.type, loc };
852
+ }
853
+ const indexedCompound = COMPOUND_ASSIGN_OPS[op];
854
+ if (indexedCompound !== undefined && ts.isElementAccessExpression(expr.left)) {
855
+ if (symbolFieldInfo(lowerer, expr.left))
856
+ return lowerFieldCompoundValue(lowerer, expr.left, indexedCompound, expr.right, loc);
857
+ return lowerElementCompound(lowerer, expr, indexedCompound);
858
+ }
859
+ if (indexedCompound !== undefined && ts.isIdentifier(expr.left)) {
860
+ const target = lowerer.resolveWritable(expr.left);
861
+ if (!target) {
862
+ lowerer.rejectUnresolved(expr.left, "assignment to an unresolved variable");
863
+ }
864
+ const value = lowerCompoundValueToTarget(lowerer, expr, indexedCompound, target);
865
+ return { kind: "assignExpr", localId: target.id, value, type: target.type, loc };
866
+ }
867
+ if (indexedCompound !== undefined &&
868
+ (ts.isPropertyAccessExpression(expr.left) || ts.isElementAccessExpression(expr.left)) &&
869
+ !(ts.isPropertyAccessExpression(expr.left) && expr.left.questionDotToken)) {
870
+ const target = expandoWritableTarget(lowerer, expr.left) ??
871
+ (ts.isPropertyAccessExpression(expr.left) ? nsWritableTarget(lowerer, expr.left) : null);
872
+ if (target) {
873
+ const value = lowerCompoundValueToTarget(lowerer, expr, indexedCompound, target);
874
+ return { kind: "assignExpr", localId: target.id, value, type: target.type, loc };
875
+ }
876
+ return lowerFieldCompoundValue(lowerer, expr.left, indexedCompound, expr.right, loc);
877
+ }
878
+ // `events.defaultMaxListeners = v` — the module-property write
879
+ // Node validates (validateNumber(n, 'defaultMaxListeners', 0)):
880
+ // the value crosses into the checked-dynamic tree and the runtime ladder throws
881
+ // ERR_INVALID_ARG_TYPE / ERR_OUT_OF_RANGE with Node's exact slot
882
+ // name; valid numbers apply. The expression's value is the RHS
883
+ // (JS's assignment yield).
884
+ if (op === ts.SyntaxKind.EqualsToken &&
885
+ ts.isPropertyAccessExpression(expr.left) &&
886
+ !expr.left.questionDotToken &&
887
+ expr.left.name.text === "defaultMaxListeners") {
888
+ const bi = lowerer.builtinMemberOf(expr.left);
889
+ if (bi && bi.module === "events" && bi.member === "defaultMaxListeners") {
890
+ const rhs = lowerer.lowerExpr(expr.right);
891
+ if (rhs.type.kind === "dyn" || rhs.kind === "unitLit" || lowerer.dynConvertible(rhs.type)) {
892
+ const valTmp = lowerer.declareHiddenLocal("%setVal", rhs.type);
893
+ const valRef = () => ({
894
+ kind: "varRef",
895
+ localId: valTmp.id,
896
+ type: rhs.type,
897
+ loc,
898
+ });
899
+ const dynVal = rhs.type.kind === "dyn"
900
+ ? valRef()
901
+ : { kind: "dynFrom", value: valRef(), type: DYN, loc };
902
+ return {
903
+ kind: "seqExpr",
904
+ stmts: [
905
+ { kind: "varDecl", localId: valTmp.id, init: rhs, loc },
906
+ {
907
+ kind: "exprStmt",
908
+ expr: {
909
+ kind: "libCall",
910
+ fn: "emitter.setDefaultMaxChk",
911
+ args: [
912
+ dynVal,
913
+ { kind: "strLit", value: "defaultMaxListeners", type: STRING, loc },
914
+ ],
915
+ type: VOID,
916
+ loc,
917
+ },
918
+ loc,
919
+ },
920
+ ],
921
+ result: valRef(),
922
+ type: rhs.type,
923
+ loc,
924
+ };
925
+ }
926
+ }
927
+ }
928
+ // Member targets whose storage IS a module global — namespace
929
+ // members (`N.x`) and expando function members (`Foo.baz`): the
930
+ // same assignExpr, since the "member" is a variable.
931
+ if (op === ts.SyntaxKind.EqualsToken &&
932
+ (ts.isPropertyAccessExpression(expr.left) || ts.isElementAccessExpression(expr.left)) &&
933
+ !(ts.isPropertyAccessExpression(expr.left) && expr.left.questionDotToken)) {
934
+ const target = expandoWritableTarget(lowerer, expr.left) ??
935
+ (ts.isPropertyAccessExpression(expr.left) ? nsWritableTarget(lowerer, expr.left) : null);
936
+ if (target) {
937
+ const value = lowerer.lowerExprExpecting(expr.right, target.type);
938
+ return { kind: "assignExpr", localId: target.id, value, type: target.type, loc };
939
+ }
940
+ // Bundled numeric enums use e[e["name"] = value] = "name".
941
+ // Capture the receiver and key before the RHS. PutValue coerces the
942
+ // key afterward, then yields the RHS without rereading the property.
943
+ if (ts.isElementAccessExpression(expr.left) && !expr.left.questionDotToken) {
944
+ const recv = tryLowerExpression(lowerer, expr.left.expression);
945
+ if (recv &&
946
+ (recv.type.kind === "dyn" ||
947
+ (recv.type.kind === "array" &&
948
+ isJsSourceFile(ts.getSourceFileOfNode(expr)) &&
949
+ lowerer.dynConvertible(recv.type)))) {
950
+ return lowerDynMemberAssignment(lowerer, expr, lowerer.coerceInto(expr.left.expression, recv, DYN));
951
+ }
952
+ if (recv?.type.kind === "array" || recv?.type.kind === "bytes") {
953
+ const receiver = lowerer.declareHiddenLocal("%setArray", recv.type);
954
+ const index = lowerer.lowerExpr(expr.left.argumentExpression);
955
+ if (index.type.kind !== "f64")
956
+ lowerer.unsupported("SC1090", expr.left.argumentExpression, "indexing with non-number keys");
957
+ const key = lowerer.declareHiddenLocal("%setIndex", F64);
958
+ const raw = lowerer.lowerExpr(expr.right);
959
+ const value = lowerer.declareHiddenLocal("%setValue", raw.type);
960
+ const result = varRef(value.id, raw.type, loc);
961
+ const arr = varRef(receiver.id, recv.type, loc);
962
+ const idx = varRef(key.id, F64, loc);
963
+ const write = recv.type.kind === "array"
964
+ ? arrayValueStore(lowerer, arr, idx, result, recv.type.elem, loc)
965
+ : {
966
+ kind: "bytesSet",
967
+ arr,
968
+ index: idx,
969
+ value: lowerer.coerceInto(expr.right, result, F64),
970
+ loc,
971
+ };
972
+ return {
973
+ kind: "seqExpr",
974
+ stmts: [
975
+ { kind: "varDecl", localId: receiver.id, init: recv, loc },
976
+ { kind: "varDecl", localId: key.id, init: index, loc },
977
+ { kind: "varDecl", localId: value.id, init: raw, loc },
978
+ write,
979
+ ],
980
+ result,
981
+ type: result.type,
982
+ loc,
983
+ };
984
+ }
985
+ }
986
+ // `h.k = v` on a CHECKED-DYNAMIC receiver in VALUE position
987
+ // (`var _ = module.exports = foo`): receiver first, then RHS
988
+ // (JS's reference-before-value order), the keyed write, and the
989
+ // RHS value is the expression's value — its OWN type, so the
990
+ // consumer sees exactly what the checker typed.
991
+ if (ts.isPropertyAccessExpression(expr.left) && !expr.left.questionDotToken) {
992
+ // `const src = exports.src = []`: an export member assigned in
993
+ // value position writes its export global and yields the value.
994
+ {
995
+ let inFunction = false;
996
+ for (let p = expr.parent; p !== undefined; p = p.parent) {
997
+ if (ts.isFunctionLike(p) || ts.isClassDeclaration(p) || ts.isClassExpression(p)) {
998
+ inFunction = true;
999
+ break;
1000
+ }
1001
+ }
1002
+ const g = inFunction
1003
+ ? cjsExportMemberWriteGlobalOf(lowerer, expr.left)
1004
+ : cjsInFileExportGlobalOf(lowerer, expr.left);
1005
+ if (g) {
1006
+ const value = lowerer.lowerExprExpecting(expr.right, g.type);
1007
+ const tmp = lowerer.declareHiddenLocal("%exportValue", value.type);
1008
+ const result = varRef(tmp.id, value.type, loc);
1009
+ return {
1010
+ kind: "seqExpr",
1011
+ stmts: [
1012
+ { kind: "varDecl", localId: tmp.id, init: value, loc },
1013
+ { kind: "assign", localId: g.id, value: result, loc },
1014
+ ],
1015
+ result,
1016
+ type: value.type,
1017
+ loc,
1018
+ };
1019
+ }
1020
+ }
1021
+ const recv = tryLowerExpression(lowerer, expr.left.expression);
1022
+ if (recv && recv.type.kind === "dyn")
1023
+ return lowerDynMemberAssignment(lowerer, expr, recv);
1024
+ const unionWrite = lowerUnionFieldWrite(lowerer, expr.left, expr.right);
1025
+ if (unionWrite)
1026
+ return unionWrite;
1027
+ const field = lowerer.fieldTarget(expr.left);
1028
+ if (field) {
1029
+ const recvTmp = lowerer.declareHiddenLocal("%setReceiver", field.obj.type);
1030
+ const receiver = field.obj;
1031
+ field.obj = varRef(recvTmp.id, receiver.type, loc);
1032
+ const value = lowerer.lowerExprExpecting(expr.right, field.fieldType);
1033
+ const valTmp = lowerer.declareHiddenLocal("%setValue", value.type);
1034
+ const result = varRef(valTmp.id, value.type, loc);
1035
+ return {
1036
+ kind: "seqExpr",
1037
+ stmts: [
1038
+ { kind: "varDecl", localId: recvTmp.id, init: receiver, loc },
1039
+ { kind: "varDecl", localId: valTmp.id, init: value, loc },
1040
+ lowerer.fieldSetStmt(field, result, loc, expr.left),
1041
+ ],
1042
+ result,
1043
+ type: result.type,
1044
+ loc,
1045
+ };
1046
+ }
1047
+ }
1048
+ }
1049
+ // Destructuring assignment in VALUE position (`(() => [i] = [i+1])()`,
1050
+ // `({} = {x} = a)`, `var d = ([] = src)`): the statement machinery's
1051
+ // parts under a seqExpr — the expression's value is the RHS value
1052
+ // (JS's GetValue of the right reference), which is exactly the
1053
+ // parts' hidden temp.
1054
+ if (op === ts.SyntaxKind.EqualsToken &&
1055
+ (ts.isObjectLiteralExpression(expr.left) || ts.isArrayLiteralExpression(expr.left))) {
1056
+ const parts = lowerer.lowerDestructuringAssignParts(expr.left, expr.right, loc);
1057
+ return {
1058
+ kind: "seqExpr",
1059
+ stmts: parts.stmts,
1060
+ result: parts.value,
1061
+ type: parts.value.type,
1062
+ loc,
1063
+ };
1064
+ }
1065
+ lowerer.unsupported("SC1090", expr, op === ts.SyntaxKind.EqualsToken
1066
+ ? "assignment to non-variables as an expression (only `x = e` over a variable yields a value; write property/destructuring assignments as statements)"
1067
+ : "compound assignment as an expression (write `x op= e` as a statement, or spell out `x = x op e`)");
1068
+ }
1069
+ if (op === ts.SyntaxKind.EqualsEqualsToken || op === ts.SyntaxKind.ExclamationEqualsToken) {
1070
+ const nullTest = lowerLooseNullCompare(lowerer, expr, loc);
1071
+ if (nullTest)
1072
+ return nullTest;
1073
+ const loose = lowerAbstractEquality(lowerer, deferredSlotOr(lowerer, lowerer.lowerExpr(expr.left)), deferredSlotOr(lowerer, lowerer.lowerExpr(expr.right)), op === ts.SyntaxKind.ExclamationEqualsToken, loc);
1074
+ if (loose)
1075
+ return loose;
1076
+ lowerer.unsupported("SC1040", expr, undefined, "object-to-primitive loose equality can call user-defined valueOf/toString methods — compare explicit primitive conversions instead");
1077
+ }
1078
+ if (op === ts.SyntaxKind.AmpersandAmpersandToken || op === ts.SyntaxKind.BarBarToken) {
1079
+ return lowerLogicalChain(lowerer, expr);
1080
+ }
1081
+ if (op === ts.SyntaxKind.QuestionQuestionToken) {
1082
+ return lowerer.lowerNullishCoalesce(expr, loc);
1083
+ }
1084
+ if (op === ts.SyntaxKind.CommaToken) {
1085
+ // Comma expression in VALUE position (`r = ({} = a, [] = a)` — the
1086
+ // conformance corpus's paired-destructuring idiom): the left operand
1087
+ // runs for EFFECT exactly as its statement lowering (JS discards its
1088
+ // value), the right operand is the expression's value — a seqExpr.
1089
+ // The validator restricts seqExpr statements to straight-line writes
1090
+ // (the lowering point is mid-expression), so a left operand whose
1091
+ // statement lowering needs real control flow keeps a pointed fence
1092
+ // instead of tripping the validator downstream.
1093
+ const effect = lowerer.lowerExprStatement(expr.left);
1094
+ if (!seqExprSafeStmt(effect)) {
1095
+ lowerer.unsupported("SC1090", expr.left, "comma expressions whose left operand needs control flow (run it as its own statement first)");
1096
+ }
1097
+ const result = lowerer.lowerExpr(expr.right);
1098
+ return { kind: "seqExpr", stmts: [effect], result, type: result.type, loc };
1099
+ }
1100
+ if (op === ts.SyntaxKind.InstanceOfKeyword)
1101
+ return lowerer.lowerInstanceOf(expr, loc);
1102
+ if (op === ts.SyntaxKind.InKeyword) {
1103
+ return lowerInExpression(lowerer, expr, loc);
1104
+ }
1105
+ // `typeof e === "string"` on a catch binding or an `unknown` value: a
1106
+ // runtime kind test — intercepted BEFORE the operands lower (a raw
1107
+ // read of the binding is the narrowness fence, and bare `typeof e`
1108
+ // has no lowering).
1109
+ if (op === ts.SyntaxKind.EqualsEqualsEqualsToken ||
1110
+ op === ts.SyntaxKind.ExclamationEqualsEqualsToken) {
1111
+ const test = lowerConstructorGlobalTypeofTest(lowerer, expr, loc) ??
1112
+ lowerWebAssemblyTypeofTest(lowerer, expr, loc) ??
1113
+ lowerErrorCodeTypeofTest(lowerer, expr, loc) ??
1114
+ lowerer.lowerCaughtTypeofTest(expr, loc) ??
1115
+ lowerDynTypeofTest(lowerer, expr, loc) ??
1116
+ lowerUnionTypeofTest(lowerer, expr, loc);
1117
+ if (test)
1118
+ return test;
1119
+ }
1120
+ // `x.constructor === Readable` for an instance of EventEmitter or a
1121
+ // stream class: the instance's own class, compared without a class value.
1122
+ if (op === ts.SyntaxKind.EqualsEqualsEqualsToken ||
1123
+ op === ts.SyntaxKind.ExclamationEqualsEqualsToken) {
1124
+ for (const [side, other] of [
1125
+ [expr.left, expr.right],
1126
+ [expr.right, expr.left],
1127
+ ]) {
1128
+ const ctor = runtimeConstructorReceiver(lowerer, side);
1129
+ const target = ctor ? builtinClassRefOf(lowerer, other) : null;
1130
+ if (ctor && (target?.kind === "emitter" || target?.kind === "stream")) {
1131
+ const negated = op === ts.SyntaxKind.ExclamationEqualsEqualsToken;
1132
+ return lowerRuntimeConstructorIs(lowerer, ctor.receiver, target.info, negated, loc);
1133
+ }
1134
+ }
1135
+ }
1136
+ // `C === EventEmitter` between two builtin class references: the
1137
+ // classes are compile-time values, so the answer folds.
1138
+ if (op === ts.SyntaxKind.EqualsEqualsEqualsToken ||
1139
+ op === ts.SyntaxKind.ExclamationEqualsEqualsToken) {
1140
+ const leftClass = builtinClassRefOf(lowerer, expr.left);
1141
+ const rightClass = leftClass === null ? null : builtinClassRefOf(lowerer, expr.right);
1142
+ if (leftClass !== null && rightClass !== null) {
1143
+ const negated = op === ts.SyntaxKind.ExclamationEqualsEqualsToken;
1144
+ const same = sameBuiltinClass(leftClass, rightClass);
1145
+ return { kind: "boolLit", value: same !== negated, type: BOOL, loc };
1146
+ }
1147
+ }
1148
+ const strictEquality = op === ts.SyntaxKind.EqualsEqualsEqualsToken ||
1149
+ op === ts.SyntaxKind.ExclamationEqualsEqualsToken;
1150
+ // An identifier whose storage is runtime-optional is compared by its
1151
+ // stored value: the checker's narrowing to the present arm is not a
1152
+ // runtime proof. Identifier reads are pure, so taking the stored value
1153
+ // after both operands lowered keeps the evaluation order. A union on
1154
+ // the other side keeps the narrowed read (union-to-union comparison
1155
+ // has no lowering).
1156
+ let left = strictEquality
1157
+ ? (lowerAbsenceProbe(lowerer, expr.left) ?? lowerer.lowerExpr(expr.left))
1158
+ : lowerer.lowerExpr(expr.left);
1159
+ let right = strictEquality
1160
+ ? (lowerAbsenceProbe(lowerer, expr.right) ?? lowerer.lowerExpr(expr.right))
1161
+ : lowerer.lowerExpr(expr.right);
1162
+ if (strictEquality) {
1163
+ const storedLeft = runtimeOptionalStorageOperand(lowerer, expr.left);
1164
+ const storedRight = runtimeOptionalStorageOperand(lowerer, expr.right);
1165
+ if (storedLeft !== null && right.type.kind !== "union")
1166
+ left = storedLeft;
1167
+ if (storedRight !== null && left.type.kind !== "union")
1168
+ right = storedRight;
1169
+ // A typed-array read compared with a plain number needs no
1170
+ // `number | undefined` box.
1171
+ const fusedLeft = tryLowerBytesReadNumberEquality(lowerer, left, right, expr.right);
1172
+ if (fusedLeft)
1173
+ left = fusedLeft;
1174
+ else {
1175
+ const fusedRight = tryLowerBytesReadNumberEquality(lowerer, right, left, expr.left);
1176
+ if (fusedRight)
1177
+ right = fusedRight;
1178
+ }
1179
+ }
1180
+ if (strictEquality && (left.type.kind === "caught" || right.type.kind === "caught")) {
1181
+ if (left.type.kind === "caught")
1182
+ left = { kind: "caughtToDyn", value: left, type: DYN, loc: left.loc };
1183
+ if (right.type.kind === "caught")
1184
+ right = { kind: "caughtToDyn", value: right, type: DYN, loc: right.loc };
1185
+ }
1186
+ if (left.type.kind === "dyn" || right.type.kind === "dyn") {
1187
+ // The narrowing unit comparisons ARE answerable on unknown: `v ===
1188
+ // undefined` / `v !== null` test the dyn node's kind directly, and
1189
+ // tsc's control flow narrows the branches (reads then bridge through
1190
+ // maybeNarrow's validated extraction).
1191
+ if (op === ts.SyntaxKind.EqualsEqualsEqualsToken ||
1192
+ op === ts.SyntaxKind.ExclamationEqualsEqualsToken) {
1193
+ const negated = op === ts.SyntaxKind.ExclamationEqualsEqualsToken;
1194
+ const unit = left.kind === "unitLit" ? left : right.kind === "unitLit" ? right : null;
1195
+ const other = left.kind === "unitLit" ? right : left;
1196
+ if (unit && other.type.kind === "dyn") {
1197
+ return {
1198
+ kind: "dynTest",
1199
+ test: unit.unit,
1200
+ ...(negated ? { negated: true } : {}),
1201
+ value: other,
1202
+ type: BOOL,
1203
+ loc,
1204
+ };
1205
+ }
1206
+ // dyn vs SCALAR strict equality (`value !== ""`, `u === 5` — the
1207
+ // normalizePricing filter): a guarded kind test + payload compare,
1208
+ // JS-exact (strict equality never coerces; a non-matching dyn kind
1209
+ // answers false). dyn vs dyn keeps the fence below.
1210
+ const dynSide = left.type.kind === "dyn" ? left : right;
1211
+ const scalarSide = dynSide === left ? right : left;
1212
+ const reference = scalarSide.type;
1213
+ if ((reference.kind === "object" ||
1214
+ reference.kind === "record" ||
1215
+ reference.kind === "array" ||
1216
+ reference.kind === "bytes" ||
1217
+ reference.kind === "func" ||
1218
+ reference.kind === "classval" ||
1219
+ reference.kind === "regex" ||
1220
+ reference.kind === "url" ||
1221
+ reference.kind === "bigint" ||
1222
+ reference.kind === "symbol" ||
1223
+ reference.kind === "map" ||
1224
+ reference.kind === "set" ||
1225
+ reference.kind === "union" ||
1226
+ DYN_HANDLE_KINDS.has(reference.kind)) &&
1227
+ lowerer.dynConvertible(reference)) {
1228
+ // Records, arrays and byte views compare by the capsule identity
1229
+ // their dyn reads produce, including when they arrive through a
1230
+ // union (an optional array field read from a typed record).
1231
+ const liveArm = (type) => {
1232
+ if (type.kind === "array" || type.kind === "bytes")
1233
+ return true;
1234
+ const shape = type.kind === "record" ? lowerer.shapes.get(type.shapeId) : undefined;
1235
+ return !!shape && (shape.fields.length > 0 || shape.indexValue !== undefined);
1236
+ };
1237
+ const boxed = {
1238
+ kind: "dynFrom",
1239
+ value: scalarSide,
1240
+ type: DYN,
1241
+ loc: scalarSide.loc,
1242
+ ...(reference.kind === "record" ||
1243
+ liveArm(reference) ||
1244
+ (reference.kind === "union" &&
1245
+ (lowerer.unions.get(reference.unionId)?.arms.some(liveArm) ?? false))
1246
+ ? { liveRef: true }
1247
+ : {}),
1248
+ };
1249
+ return {
1250
+ kind: "dynScalarEq",
1251
+ left: scalarSide === left ? boxed : left,
1252
+ right: scalarSide === right ? boxed : right,
1253
+ ...(negated ? { negated: true } : {}),
1254
+ type: BOOL,
1255
+ loc,
1256
+ };
1257
+ }
1258
+ if (dynSide.type.kind === "dyn" &&
1259
+ (scalarSide.type.kind === "f64" ||
1260
+ scalarSide.type.kind === "string" ||
1261
+ scalarSide.type.kind === "bool" ||
1262
+ // dyn vs dyn (`context.actual !== context.exact` —
1263
+ // test/common's exit accounting): the runtime's whole-dyn
1264
+ // strict equality — scalars by value, units by kind,
1265
+ // reference kinds by identity (scr_dyn_strict_eq).
1266
+ scalarSide.type.kind === "dyn")) {
1267
+ return {
1268
+ kind: "dynScalarEq",
1269
+ left,
1270
+ right,
1271
+ ...(negated ? { negated: true } : {}),
1272
+ type: BOOL,
1273
+ loc,
1274
+ };
1275
+ }
1276
+ }
1277
+ const bitwise = {
1278
+ [ts.SyntaxKind.AmpersandToken]: "&",
1279
+ [ts.SyntaxKind.BarToken]: "|",
1280
+ [ts.SyntaxKind.CaretToken]: "^",
1281
+ [ts.SyntaxKind.LessThanLessThanToken]: "<<",
1282
+ [ts.SyntaxKind.GreaterThanGreaterThanToken]: ">>",
1283
+ [ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken]: ">>>",
1284
+ };
1285
+ if (bitwise[op]) {
1286
+ const l = lowerer.coerceToExpected(left, DYN);
1287
+ const r = lowerer.coerceToExpected(right, DYN);
1288
+ if (l.type.kind === "dyn" && r.type.kind === "dyn") {
1289
+ const value = {
1290
+ kind: "libCall",
1291
+ fn: "dyn.bitwise",
1292
+ args: [l, r, { kind: "strLit", value: bitwise[op], type: STRING, loc }],
1293
+ type: DYN,
1294
+ loc,
1295
+ };
1296
+ return left.type.kind === "f64" || right.type.kind === "f64"
1297
+ ? { kind: "dynCheck", value, type: F64, loc }
1298
+ : value;
1299
+ }
1300
+ }
1301
+ // Numeric operators dispatch on ToNumeric's actual Number/BigInt
1302
+ // result, including values flowing through native callable properties.
1303
+ if (isJsSourceFile(ts.getSourceFileOfNode(expr)) ||
1304
+ op === ts.SyntaxKind.PlusToken ||
1305
+ [
1306
+ ts.SyntaxKind.LessThanToken,
1307
+ ts.SyntaxKind.LessThanEqualsToken,
1308
+ ts.SyntaxKind.GreaterThanToken,
1309
+ ts.SyntaxKind.GreaterThanEqualsToken,
1310
+ ].includes(op) ||
1311
+ [
1312
+ ts.SyntaxKind.MinusToken,
1313
+ ts.SyntaxKind.AsteriskToken,
1314
+ ts.SyntaxKind.SlashToken,
1315
+ ts.SyntaxKind.PercentToken,
1316
+ ts.SyntaxKind.AsteriskAsteriskToken,
1317
+ ].includes(op)) {
1318
+ const other = left.type.kind === "dyn" ? right : left;
1319
+ const NUM_BIN = {
1320
+ [ts.SyntaxKind.MinusToken]: "-",
1321
+ [ts.SyntaxKind.AsteriskToken]: "*",
1322
+ [ts.SyntaxKind.SlashToken]: "/",
1323
+ [ts.SyntaxKind.PercentToken]: "%",
1324
+ [ts.SyntaxKind.AsteriskAsteriskToken]: "**",
1325
+ };
1326
+ const NUM_CMP = {
1327
+ [ts.SyntaxKind.LessThanToken]: "<",
1328
+ [ts.SyntaxKind.LessThanEqualsToken]: "<=",
1329
+ [ts.SyntaxKind.GreaterThanToken]: ">",
1330
+ [ts.SyntaxKind.GreaterThanEqualsToken]: ">=",
1331
+ };
1332
+ const arith = NUM_BIN[op];
1333
+ const cmp = NUM_CMP[op];
1334
+ if (arith) {
1335
+ const l = lowerer.coerceToExpected(left, DYN);
1336
+ const r = lowerer.coerceToExpected(right, DYN);
1337
+ if (l.type.kind === "dyn" && r.type.kind === "dyn") {
1338
+ const value = {
1339
+ kind: "libCall",
1340
+ fn: "dyn.arithmetic",
1341
+ args: [l, r, { kind: "strLit", value: arith, type: STRING, loc }],
1342
+ type: DYN,
1343
+ loc,
1344
+ };
1345
+ const numeric = left.type.kind === "bigint" || right.type.kind === "bigint"
1346
+ ? BIGINT_T
1347
+ : left.type.kind === "f64" || right.type.kind === "f64"
1348
+ ? F64
1349
+ : null;
1350
+ return numeric ? { kind: "dynCheck", value, type: numeric, loc } : value;
1351
+ }
1352
+ }
1353
+ if (cmp && lowerer.dynConvertible(left.type) && lowerer.dynConvertible(right.type)) {
1354
+ return {
1355
+ kind: "libCall",
1356
+ fn: "dyn.compare",
1357
+ args: [
1358
+ lowerer.coerceToExpected(left, DYN),
1359
+ lowerer.coerceToExpected(right, DYN),
1360
+ { kind: "strLit", value: cmp, type: STRING, loc },
1361
+ ],
1362
+ type: BOOL,
1363
+ loc,
1364
+ };
1365
+ }
1366
+ // Untyped addition chooses concatenation or numeric addition only
1367
+ // after both operands have undergone ToPrimitive at runtime.
1368
+ if (op === ts.SyntaxKind.PlusToken) {
1369
+ const l = lowerer.coerceToExpected(left, DYN);
1370
+ const r = lowerer.coerceToExpected(right, DYN);
1371
+ if (l.type.kind === "dyn" && r.type.kind === "dyn") {
1372
+ const value = { kind: "libCall", fn: "dyn.add", args: [l, r], type: DYN, loc };
1373
+ // A statically known string operand guarantees a string result.
1374
+ return other.type.kind === "string"
1375
+ ? { kind: "dynCheck", value, type: STRING, loc }
1376
+ : value;
1377
+ }
1378
+ }
1379
+ }
1380
+ // Unsupported `any`-origin operations get their specific diagnostic;
1381
+ // unknown retains the narrowing diagnostic below.
1382
+ if ((left.type.kind === "dyn" && lowerer.anyOrigin(expr.left)) ||
1383
+ (right.type.kind === "dyn" && lowerer.anyOrigin(expr.right))) {
1384
+ // `JSON.parse` and other checked-dynamic producers deliberately
1385
+ // remain dyn when assigned to an `any` local: eagerly converting
1386
+ // the binding would deep-copy its data and sever aliases. At an
1387
+ // unsupported operator, require an explicit represented type.
1388
+ lowerer.anyOpFence(`the '${ts.tokenToString(op) ?? ts.syntaxKindName(op)}' operator`, expr);
1389
+ }
1390
+ // tsc allows ===/!== on unknown (arithmetic/comparisons it rejects
1391
+ // itself); a dynamic equality would need a dyn walk — validate first.
1392
+ lowerer.unsupported("SC1100", expr, "operators on 'unknown' values");
1393
+ }
1394
+ if (left.type.kind === "bigint" && right.type.kind === "bigint") {
1395
+ const binary = {
1396
+ [ts.SyntaxKind.PlusToken]: "bigint.add",
1397
+ [ts.SyntaxKind.MinusToken]: "bigint.sub",
1398
+ [ts.SyntaxKind.AsteriskToken]: "bigint.mul",
1399
+ [ts.SyntaxKind.SlashToken]: "bigint.div",
1400
+ [ts.SyntaxKind.PercentToken]: "bigint.mod",
1401
+ [ts.SyntaxKind.AsteriskAsteriskToken]: "bigint.pow",
1402
+ [ts.SyntaxKind.AmpersandToken]: "bigint.and",
1403
+ [ts.SyntaxKind.BarToken]: "bigint.or",
1404
+ [ts.SyntaxKind.CaretToken]: "bigint.xor",
1405
+ [ts.SyntaxKind.LessThanLessThanToken]: "bigint.shl",
1406
+ [ts.SyntaxKind.GreaterThanGreaterThanToken]: "bigint.shr",
1407
+ };
1408
+ const fn = binary[op];
1409
+ if (fn)
1410
+ return { kind: "libCall", fn, args: [left, right], type: BIGINT_T, loc };
1411
+ if (op === ts.SyntaxKind.EqualsEqualsEqualsToken ||
1412
+ op === ts.SyntaxKind.ExclamationEqualsEqualsToken) {
1413
+ const equal = {
1414
+ kind: "libCall",
1415
+ fn: "bigint.eq",
1416
+ args: [left, right],
1417
+ type: BOOL,
1418
+ loc,
1419
+ };
1420
+ return op === ts.SyntaxKind.ExclamationEqualsEqualsToken
1421
+ ? { kind: "unary", op: "!", operand: equal, type: BOOL, loc }
1422
+ : equal;
1423
+ }
1424
+ if (op === ts.SyntaxKind.LessThanToken ||
1425
+ op === ts.SyntaxKind.LessThanEqualsToken ||
1426
+ op === ts.SyntaxKind.GreaterThanToken ||
1427
+ op === ts.SyntaxKind.GreaterThanEqualsToken) {
1428
+ const cmp = {
1429
+ kind: "libCall",
1430
+ fn: "bigint.cmp",
1431
+ args: [left, right],
1432
+ type: F64,
1433
+ loc,
1434
+ };
1435
+ const zero = { kind: "numLit", value: 0, type: F64, loc };
1436
+ const cmpOp = op === ts.SyntaxKind.LessThanToken
1437
+ ? "<"
1438
+ : op === ts.SyntaxKind.LessThanEqualsToken
1439
+ ? "<="
1440
+ : op === ts.SyntaxKind.GreaterThanToken
1441
+ ? ">"
1442
+ : ">=";
1443
+ return { kind: "bin", op: cmpOp, left: cmp, right: zero, type: BOOL, loc };
1444
+ }
1445
+ }
1446
+ if ((left.type.kind === "bigint" && right.type.kind === "f64") ||
1447
+ (left.type.kind === "f64" && right.type.kind === "bigint")) {
1448
+ if (op === ts.SyntaxKind.LessThanToken ||
1449
+ op === ts.SyntaxKind.LessThanEqualsToken ||
1450
+ op === ts.SyntaxKind.GreaterThanToken ||
1451
+ op === ts.SyntaxKind.GreaterThanEqualsToken) {
1452
+ const big = left.type.kind === "bigint" ? left : right;
1453
+ const num = left.type.kind === "f64" ? left : right;
1454
+ const cmp = {
1455
+ kind: "libCall",
1456
+ fn: "bigint.cmpNumber",
1457
+ args: [big, num],
1458
+ type: F64,
1459
+ loc,
1460
+ };
1461
+ const cmpLocal = lowerer.declareHiddenLocal("%bigcmp", F64);
1462
+ const cmpRef = { kind: "varRef", localId: cmpLocal.id, type: F64, loc };
1463
+ const unordered = {
1464
+ kind: "bin",
1465
+ op: "===",
1466
+ left: cmpRef,
1467
+ right: { kind: "numLit", value: 2, type: F64, loc },
1468
+ type: BOOL,
1469
+ loc,
1470
+ };
1471
+ const zero = { kind: "numLit", value: 0, type: F64, loc };
1472
+ const leftBig = left.type.kind === "bigint";
1473
+ const cmpOp = leftBig
1474
+ ? op === ts.SyntaxKind.LessThanToken
1475
+ ? "<"
1476
+ : op === ts.SyntaxKind.LessThanEqualsToken
1477
+ ? "<="
1478
+ : op === ts.SyntaxKind.GreaterThanToken
1479
+ ? ">"
1480
+ : ">="
1481
+ : op === ts.SyntaxKind.LessThanToken
1482
+ ? ">"
1483
+ : op === ts.SyntaxKind.LessThanEqualsToken
1484
+ ? ">="
1485
+ : op === ts.SyntaxKind.GreaterThanToken
1486
+ ? "<"
1487
+ : "<=";
1488
+ const result = {
1489
+ kind: "logical",
1490
+ op: "&&",
1491
+ left: { kind: "unary", op: "!", operand: unordered, type: BOOL, loc },
1492
+ right: { kind: "bin", op: cmpOp, left: cmpRef, right: zero, type: BOOL, loc },
1493
+ type: BOOL,
1494
+ loc,
1495
+ };
1496
+ return {
1497
+ kind: "seqExpr",
1498
+ stmts: [{ kind: "varDecl", localId: cmpLocal.id, init: cmp, loc }],
1499
+ result,
1500
+ type: BOOL,
1501
+ loc,
1502
+ };
1503
+ }
1504
+ }
1505
+ // An unchecked array read keeps its undefined arm in the IR even when
1506
+ // the checker typed the binding as `string`. An optional string is not
1507
+ // itself a string operand for `+`: `undefined + 1` and
1508
+ // `undefined + undefined` are NaN, while a present string concatenates.
1509
+ // Keep this predicate exact so a nullable string does not take the
1510
+ // string path either.
1511
+ const optionalStringType = (type) => {
1512
+ if (type.kind !== "union")
1513
+ return false;
1514
+ const arms = lowerer.unions.get(type.unionId)?.arms;
1515
+ return (!!arms &&
1516
+ arms.length === 2 &&
1517
+ arms.some((arm) => arm.kind === "string") &&
1518
+ arms.some((arm) => arm.kind === "undefinedT"));
1519
+ };
1520
+ const arithmeticNumber = (operand, node) => lowerOptionalNumber(lowerer, operand, loc, node);
1521
+ const arithmeticLeft = strictEquality ? left : arithmeticNumber(left, expr.left);
1522
+ const arithmeticRight = strictEquality ? right : arithmeticNumber(right, expr.right);
1523
+ const bothNum = arithmeticLeft.type.kind === "f64" && arithmeticRight.type.kind === "f64";
1524
+ const bothStr = left.type.kind === "string" && right.type.kind === "string";
1525
+ const lowerOptionalStringPlus = () => {
1526
+ const leftOptional = optionalStringType(left.type);
1527
+ const rightOptional = optionalStringType(right.type);
1528
+ if (!leftOptional && !rightOptional)
1529
+ return null;
1530
+ const allowed = (type) => type.kind === "f64" || type.kind === "string" || optionalStringType(type);
1531
+ if (!allowed(left.type) || !allowed(right.type))
1532
+ return null;
1533
+ // The tag tests and the chosen concatenation branch must see the same
1534
+ // operand values. This matters for `take()[0] + 1` and for two reads
1535
+ // with observable getters/calls.
1536
+ const prefix = [];
1537
+ const stable = (operand) => {
1538
+ if (isSafeToRepeat(operand) || isSafeToDiscard(operand))
1539
+ return operand;
1540
+ const tmp = lowerer.declareHiddenLocal("%plus", operand.type);
1541
+ prefix.push({ kind: "varDecl", localId: tmp.id, init: operand, loc });
1542
+ return varRef(tmp.id, operand.type, loc);
1543
+ };
1544
+ const stableLeft = stable(left);
1545
+ const stableRight = stable(right);
1546
+ const leftString = lowerer.ensureString(stableLeft, expr.left);
1547
+ const rightString = lowerer.ensureString(stableRight, expr.right);
1548
+ const concat = {
1549
+ kind: "strConcat",
1550
+ left: leftString,
1551
+ right: rightString,
1552
+ type: STRING,
1553
+ loc,
1554
+ };
1555
+ const nan = {
1556
+ kind: "bin",
1557
+ op: "/",
1558
+ left: numLit(0, loc),
1559
+ right: numLit(0, loc),
1560
+ type: F64,
1561
+ loc,
1562
+ };
1563
+ const resultT = { kind: "union", unionId: lowerer.unions.intern([F64, STRING]) };
1564
+ lowerer.runtimeOptionalArithmeticTypes.set(expr, resultT);
1565
+ const numberTag = lowerer.armTag(resultT.unionId, F64);
1566
+ const stringTag = lowerer.armTag(resultT.unionId, STRING);
1567
+ if (numberTag < 0 || stringTag < 0)
1568
+ throw new InternalCompilerError("lowerer bug: optional string plus result union");
1569
+ const number = () => ({
1570
+ kind: "unionWrap",
1571
+ unionId: resultT.unionId,
1572
+ tag: numberTag,
1573
+ value: nan,
1574
+ type: resultT,
1575
+ loc,
1576
+ });
1577
+ const string = () => ({
1578
+ kind: "unionWrap",
1579
+ unionId: resultT.unionId,
1580
+ tag: stringTag,
1581
+ value: concat,
1582
+ type: resultT,
1583
+ loc,
1584
+ });
1585
+ const undefinedTest = (operand) => ({
1586
+ kind: "unionIsTag",
1587
+ unionId: operand.type.kind === "union" ? operand.type.unionId : "",
1588
+ tag: operand.type.kind === "union" ? lowerer.armTag(operand.type.unionId, UNDEFINED_T) : -1,
1589
+ negated: false,
1590
+ value: operand,
1591
+ type: BOOL,
1592
+ loc,
1593
+ });
1594
+ let result;
1595
+ if (leftOptional && rightOptional) {
1596
+ const rightMissing = undefinedTest(stableRight);
1597
+ const bothMissing = {
1598
+ kind: "ternary",
1599
+ cond: rightMissing,
1600
+ then: number(),
1601
+ else_: string(),
1602
+ type: resultT,
1603
+ loc,
1604
+ };
1605
+ result = {
1606
+ kind: "ternary",
1607
+ cond: undefinedTest(stableLeft),
1608
+ then: bothMissing,
1609
+ else_: string(),
1610
+ type: resultT,
1611
+ loc,
1612
+ };
1613
+ }
1614
+ else if (leftOptional) {
1615
+ result = {
1616
+ kind: "ternary",
1617
+ cond: undefinedTest(stableLeft),
1618
+ then: number(),
1619
+ else_: string(),
1620
+ type: resultT,
1621
+ loc,
1622
+ };
1623
+ }
1624
+ else {
1625
+ result = {
1626
+ kind: "ternary",
1627
+ cond: undefinedTest(stableRight),
1628
+ then: number(),
1629
+ else_: string(),
1630
+ type: resultT,
1631
+ loc,
1632
+ };
1633
+ }
1634
+ return prefix.length === 0
1635
+ ? result
1636
+ : { kind: "seqExpr", stmts: prefix, result, type: resultT, loc };
1637
+ };
1638
+ switch (op) {
1639
+ case ts.SyntaxKind.PlusToken:
1640
+ if (bothNum)
1641
+ return {
1642
+ kind: "bin",
1643
+ op: "+",
1644
+ left: arithmeticLeft,
1645
+ right: arithmeticRight,
1646
+ type: F64,
1647
+ loc,
1648
+ };
1649
+ if (left.type.kind === "string" || right.type.kind === "string") {
1650
+ return {
1651
+ kind: "strConcat",
1652
+ left: concatOperand(lowerer, left, expr.left),
1653
+ right: concatOperand(lowerer, right, expr.right),
1654
+ type: STRING,
1655
+ loc,
1656
+ };
1657
+ }
1658
+ const optionalStringPlus = lowerOptionalStringPlus();
1659
+ if (optionalStringPlus)
1660
+ return optionalStringPlus;
1661
+ {
1662
+ const primitive = (type) => type.kind === "f64" ||
1663
+ type.kind === "string" ||
1664
+ type.kind === "bool" ||
1665
+ isUnitType(type) ||
1666
+ (type.kind === "union" &&
1667
+ (lowerer.unions.get(type.unionId)?.arms.every(primitive) ?? false));
1668
+ if ((left.type.kind === "union" || right.type.kind === "union") &&
1669
+ primitive(left.type) &&
1670
+ primitive(right.type)) {
1671
+ lowerer.runtimeOptionalArithmeticTypes.set(expr, DYN);
1672
+ return {
1673
+ kind: "libCall",
1674
+ fn: "dyn.add",
1675
+ args: [lowerer.coerceToExpected(left, DYN), lowerer.coerceToExpected(right, DYN)],
1676
+ type: DYN,
1677
+ loc,
1678
+ };
1679
+ }
1680
+ }
1681
+ operatorUnsupported(lowerer, expr, "+", [left.type, right.type]);
1682
+ break;
1683
+ case ts.SyntaxKind.MinusToken:
1684
+ case ts.SyntaxKind.AsteriskToken:
1685
+ case ts.SyntaxKind.SlashToken:
1686
+ case ts.SyntaxKind.PercentToken:
1687
+ case ts.SyntaxKind.AsteriskAsteriskToken: {
1688
+ if (!bothNum)
1689
+ operatorUnsupported(lowerer, expr, ts.tokenToString(op) ?? "?", [left.type, right.type]);
1690
+ const binOp = op === ts.SyntaxKind.MinusToken
1691
+ ? "-"
1692
+ : op === ts.SyntaxKind.AsteriskToken
1693
+ ? "*"
1694
+ : op === ts.SyntaxKind.SlashToken
1695
+ ? "/"
1696
+ : op === ts.SyntaxKind.PercentToken
1697
+ ? "%"
1698
+ : "**";
1699
+ return {
1700
+ kind: "bin",
1701
+ op: binOp,
1702
+ left: arithmeticLeft,
1703
+ right: arithmeticRight,
1704
+ type: F64,
1705
+ loc,
1706
+ };
1707
+ }
1708
+ // The bitwise six, JS-exact: operands through ToInt32/ToUint32
1709
+ // (NaN/±Infinity → 0, truncate, wrap mod 2^32), the operation in
1710
+ // 32-bit space (shift counts masked to 5 bits), the result back to
1711
+ // f64 — `>>>` as Uint32, the rest as Int32 (runtime scr_bit_*).
1712
+ case ts.SyntaxKind.AmpersandToken:
1713
+ case ts.SyntaxKind.BarToken:
1714
+ case ts.SyntaxKind.CaretToken:
1715
+ case ts.SyntaxKind.LessThanLessThanToken:
1716
+ case ts.SyntaxKind.GreaterThanGreaterThanToken:
1717
+ case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken: {
1718
+ if (!bothNum)
1719
+ operatorUnsupported(lowerer, expr, ts.tokenToString(op) ?? "?", [left.type, right.type]);
1720
+ const bitOp = op === ts.SyntaxKind.AmpersandToken
1721
+ ? "&"
1722
+ : op === ts.SyntaxKind.BarToken
1723
+ ? "|"
1724
+ : op === ts.SyntaxKind.CaretToken
1725
+ ? "^"
1726
+ : op === ts.SyntaxKind.LessThanLessThanToken
1727
+ ? "<<"
1728
+ : op === ts.SyntaxKind.GreaterThanGreaterThanToken
1729
+ ? ">>"
1730
+ : ">>>";
1731
+ return {
1732
+ kind: "bin",
1733
+ op: bitOp,
1734
+ left: arithmeticLeft,
1735
+ right: arithmeticRight,
1736
+ type: F64,
1737
+ loc,
1738
+ };
1739
+ }
1740
+ case ts.SyntaxKind.EqualsEqualsEqualsToken:
1741
+ case ts.SyntaxKind.ExclamationEqualsEqualsToken:
1742
+ return lowerStrictEquality(lowerer, expr, expr.left, expr.right, left, right, op === ts.SyntaxKind.ExclamationEqualsEqualsToken, loc);
1743
+ case ts.SyntaxKind.LessThanToken:
1744
+ case ts.SyntaxKind.LessThanEqualsToken:
1745
+ case ts.SyntaxKind.GreaterThanToken:
1746
+ case ts.SyntaxKind.GreaterThanEqualsToken: {
1747
+ const cmpOp = op === ts.SyntaxKind.LessThanToken
1748
+ ? "<"
1749
+ : op === ts.SyntaxKind.LessThanEqualsToken
1750
+ ? "<="
1751
+ : op === ts.SyntaxKind.GreaterThanToken
1752
+ ? ">"
1753
+ : ">=";
1754
+ if (bothNum)
1755
+ return {
1756
+ kind: "bin",
1757
+ op: cmpOp,
1758
+ left: arithmeticLeft,
1759
+ right: arithmeticRight,
1760
+ type: BOOL,
1761
+ loc,
1762
+ };
1763
+ if (bothStr)
1764
+ return { kind: "strCmp", op: cmpOp, left, right, type: BOOL, loc };
1765
+ // A Date converts to a new checked-dynamic Date on each crossing, so
1766
+ // comparisons keep their Date fence instead of comparing copies.
1767
+ if (left.type.kind !== "date" &&
1768
+ right.type.kind !== "date" &&
1769
+ lowerer.dynConvertible(left.type) &&
1770
+ lowerer.dynConvertible(right.type)) {
1771
+ return {
1772
+ kind: "libCall",
1773
+ fn: "dyn.compare",
1774
+ args: [
1775
+ lowerer.coerceToExpected(left, DYN),
1776
+ lowerer.coerceToExpected(right, DYN),
1777
+ { kind: "strLit", value: cmpOp, type: STRING, loc },
1778
+ ],
1779
+ type: BOOL,
1780
+ loc,
1781
+ };
1782
+ }
1783
+ lowerer.unsupported("SC1043", expr);
1784
+ break;
1785
+ }
1786
+ default:
1787
+ break;
1788
+ }
1789
+ lowerer.unsupported("SC1090", expr, `operator '${ts.tokenToString(op) ?? ts.syntaxKindName(op)}'`);
1790
+ }
1791
+ /** `left === right` (`!==` when negated) over lowered operands: JS strict
1792
+ * equality for every pair of static kinds the program can compare.
1793
+ * `node` anchors diagnostics, and `leftNode`/`rightNode` the coercions. */
1794
+ export function lowerStrictEquality(lowerer, node, leftNode, rightNode, left, right, negated, loc) {
1795
+ const plainBothNum = left.type.kind === "f64" && right.type.kind === "f64";
1796
+ const bothStr = left.type.kind === "string" && right.type.kind === "string";
1797
+ const indexed = tryLowerIndexedComparison(lowerer, left, right, negated, loc);
1798
+ if (indexed)
1799
+ return indexed;
1800
+ if (plainBothNum)
1801
+ return { kind: "bin", op: negated ? "!==" : "===", left, right, type: BOOL, loc };
1802
+ if (bothStr) {
1803
+ if (left.kind === "strLit" && right.kind === "strLit")
1804
+ return {
1805
+ kind: "boolLit",
1806
+ value: (left.value === right.value) !== negated,
1807
+ type: BOOL,
1808
+ loc,
1809
+ };
1810
+ return { kind: "strEq", negated, left, right, type: BOOL, loc };
1811
+ }
1812
+ // bool === bool: a plain value compare (the config-drift checks'
1813
+ // `desired.lanMode !== actual.lanMode` shape).
1814
+ if (left.type.kind === "bool" && right.type.kind === "bool") {
1815
+ return { kind: "bin", op: negated ? "!==" : "===", left, right, type: BOOL, loc };
1816
+ }
1817
+ const unitTest = lowerer.lowerUnitComparison(left, right, negated, loc);
1818
+ if (unitTest)
1819
+ return unitTest;
1820
+ if (left.type.kind === "union" || right.type.kind === "union") {
1821
+ const compared = lowerUnionEquality(lowerer, left, right, negated, false, loc);
1822
+ if (compared)
1823
+ return compared;
1824
+ const aliasRefusal = (type) => {
1825
+ if (tagEqualityMayMissAlias(lowerer, type))
1826
+ lowerer.unsupported("SC1090", node, `comparisons of related class values beside structural union members (${NARROW_FIRST})`);
1827
+ };
1828
+ // JS strict equality of the ARM values, per union tag (a
1829
+ // per-union helper): equal tags compare payloads (f64 ==, string
1830
+ // bytes, bool ==, ref-arm POINTER identity), different tags are
1831
+ // never equal. Two shapes lower: same union on both sides, and
1832
+ // union vs plain arm value (`u === "text"` where the checker
1833
+ // didn't narrow) — the plain side wraps into the union, which
1834
+ // preserves payload identity. Different unions (tsc admits
1835
+ // partially-overlapping ones) still need narrowing first.
1836
+ const ut = left.type.kind === "union" ? left.type : right.type;
1837
+ const bothUnion = left.type.kind === "union" && right.type.kind === "union";
1838
+ const sameUnion = bothUnion && typeEquals(left.type, right.type);
1839
+ const plainFunc = left.type.kind === "func" ? left : right.type.kind === "func" ? right : null;
1840
+ const unionArms = lowerer.unions.get(ut.unionId)?.arms ?? [];
1841
+ const funcArm = unionArms.find((arm) => arm.kind === "func");
1842
+ // `listeners()` reports original prefix callbacks, but the
1843
+ // checker views an indexed result as function | undefined. For
1844
+ // identity comparison, retain the original closure pointer rather
1845
+ // than adapting it to the tuple signature.
1846
+ if (!bothUnion &&
1847
+ plainFunc !== null &&
1848
+ funcArm?.kind === "func" &&
1849
+ unionArms.filter((arm) => arm.kind === "func").length === 1 &&
1850
+ unionArms.some(isUnitType)) {
1851
+ return {
1852
+ kind: "unionFuncEq",
1853
+ unionId: ut.unionId,
1854
+ tag: lowerer.armTag(ut.unionId, funcArm),
1855
+ union: left.type.kind === "union" ? left : right,
1856
+ func: plainFunc,
1857
+ negated,
1858
+ type: BOOL,
1859
+ loc,
1860
+ };
1861
+ }
1862
+ if ((sameUnion || !bothUnion) && lowerer.eqComparableUnion(ut.unionId)) {
1863
+ aliasRefusal(ut);
1864
+ return {
1865
+ kind: "unionEq",
1866
+ unionId: ut.unionId,
1867
+ negated,
1868
+ sameValue: false,
1869
+ left: lowerer.coerceInto(leftNode, left, ut),
1870
+ right: lowerer.coerceInto(rightNode, right, ut),
1871
+ type: BOOL,
1872
+ loc,
1873
+ };
1874
+ }
1875
+ if (left.type.kind === "union" && right.type.kind === "union") {
1876
+ const leftDef = lowerer.unions.get(left.type.unionId);
1877
+ const rightDef = lowerer.unions.get(right.type.unionId);
1878
+ if (leftDef && rightDef) {
1879
+ const leftValues = leftDef.arms.filter((arm) => !isUnitType(arm));
1880
+ const rightValues = rightDef.arms.filter((arm) => !isUnitType(arm));
1881
+ const sameValueArms = leftValues.length === rightValues.length &&
1882
+ leftValues.every((arm) => rightValues.some((candidate) => typeEquals(candidate, arm)));
1883
+ if (sameValueArms) {
1884
+ const arms = [...leftDef.arms];
1885
+ for (const arm of rightDef.arms) {
1886
+ if (!arms.some((candidate) => typeEquals(candidate, arm)))
1887
+ arms.push(arm);
1888
+ }
1889
+ arms.sort((a, b) => (typeKey(a) < typeKey(b) ? -1 : 1));
1890
+ const common = {
1891
+ kind: "union",
1892
+ unionId: lowerer.unions.intern(arms),
1893
+ };
1894
+ aliasRefusal(common);
1895
+ return {
1896
+ kind: "unionEq",
1897
+ unionId: common.unionId,
1898
+ negated,
1899
+ sameValue: false,
1900
+ left: lowerer.coerceInto(leftNode, left, common),
1901
+ right: lowerer.coerceInto(rightNode, right, common),
1902
+ type: BOOL,
1903
+ loc,
1904
+ };
1905
+ }
1906
+ }
1907
+ }
1908
+ lowerer.unsupported("SC1090", node, `comparisons of union-typed values (${NARROW_FIRST})`);
1909
+ }
1910
+ // Arrays, maps, functions, class instances and records compare by
1911
+ // reference identity (pointer compare) — JS-exact object equality.
1912
+ // Hierarchy-related classes compare after widening the derived side
1913
+ // (same pointer either way — prefix layout).
1914
+ let idLeft = left;
1915
+ let idRight = right;
1916
+ if (left.type.kind === "object" && right.type.kind === "object") {
1917
+ if (lowerer.isSubclassOf(left.type.className, right.type.className)) {
1918
+ idLeft = lowerer.upcastTo(left, right.type.className);
1919
+ }
1920
+ else if (lowerer.isSubclassOf(right.type.className, left.type.className)) {
1921
+ idRight = lowerer.upcastTo(right, left.type.className);
1922
+ }
1923
+ }
1924
+ // Two function values compare by identity whatever their STATIC
1925
+ // signatures (tsc admits the comparison when one side is
1926
+ // assignable to the other — a tuple-typed listeners() element
1927
+ // against a prefix-declared handler): the pointer answers it.
1928
+ if (idLeft.type.kind === "func" && idRight.type.kind === "func") {
1929
+ return {
1930
+ kind: "bin",
1931
+ op: negated ? "!==" : "===",
1932
+ left: idLeft,
1933
+ right: idRight,
1934
+ type: BOOL,
1935
+ loc,
1936
+ };
1937
+ }
1938
+ // Two CLASS values compare by identity whatever their static
1939
+ // classes — one immortal object per class, one pointer compare
1940
+ // (the function-identity rule verbatim; `X === D` through a
1941
+ // base-typed slot answers exactly JS).
1942
+ if (idLeft.type.kind === "classval" && idRight.type.kind === "classval") {
1943
+ return {
1944
+ kind: "bin",
1945
+ op: negated ? "!==" : "===",
1946
+ left: idLeft,
1947
+ right: idRight,
1948
+ type: BOOL,
1949
+ loc,
1950
+ };
1951
+ }
1952
+ if (idLeft.type.kind === "moduleNs" && idRight.type.kind === "moduleNs") {
1953
+ return {
1954
+ kind: "bin",
1955
+ op: negated ? "!==" : "===",
1956
+ left: idLeft,
1957
+ right: idRight,
1958
+ type: BOOL,
1959
+ loc,
1960
+ };
1961
+ }
1962
+ if ((idLeft.type.kind === "array" ||
1963
+ idLeft.type.kind === "map" ||
1964
+ idLeft.type.kind === "set" ||
1965
+ idLeft.type.kind === "regex" ||
1966
+ idLeft.type.kind === "url" ||
1967
+ idLeft.type.kind === "object" ||
1968
+ idLeft.type.kind === "record" ||
1969
+ // Symbols ARE identity: `Symbol('a') === Symbol('a')` is false,
1970
+ // a symbol equals exactly itself, and Symbol.for's interned
1971
+ // values compare equal across call sites — all one pointer
1972
+ // compare, JS's spec without approximation.
1973
+ idLeft.type.kind === "symbol" ||
1974
+ // Typed arrays / Buffers ARE objects to ===: pointer identity
1975
+ // (buf === buf.swap16() — the in-place mutators return this).
1976
+ idLeft.type.kind === "bytes" ||
1977
+ idLeft.type.kind === "promise") &&
1978
+ typeEquals(idLeft.type, idRight.type)) {
1979
+ return {
1980
+ kind: "bin",
1981
+ op: negated ? "!==" : "===",
1982
+ left: idLeft,
1983
+ right: idRight,
1984
+ type: BOOL,
1985
+ loc,
1986
+ };
1987
+ }
1988
+ // Runtime HANDLES are objects to === too: one handle per socket/
1989
+ // request/response, so pointer identity IS JS's object equality
1990
+ // (`c.pause() === c` — Node's chaining assertions). */
1991
+ if (DYN_HANDLE_KINDS.has(idLeft.type.kind) && typeEquals(idLeft.type, idRight.type)) {
1992
+ return {
1993
+ kind: "bin",
1994
+ op: negated ? "!==" : "===",
1995
+ left: idLeft,
1996
+ right: idRight,
1997
+ type: BOOL,
1998
+ loc,
1999
+ };
2000
+ }
2001
+ // A Date converts to a new checked-dynamic Date on each crossing; its
2002
+ // identity has no representation, so equality keeps the fence.
2003
+ if (idLeft.type.kind !== "date" &&
2004
+ idRight.type.kind !== "date" &&
2005
+ lowerer.dynConvertible(idLeft.type) &&
2006
+ lowerer.dynConvertible(idRight.type)) {
2007
+ return {
2008
+ kind: "dynScalarEq",
2009
+ left: lowerer.coerceToExpected(idLeft, DYN),
2010
+ right: lowerer.coerceToExpected(idRight, DYN),
2011
+ ...(negated ? { negated: true } : {}),
2012
+ type: BOOL,
2013
+ loc,
2014
+ };
2015
+ }
2016
+ return lowerer.unsupported("SC1043", node);
2017
+ }
2018
+ function lowerLogicalChain(lowerer, expr) {
2019
+ // Logical chains have a left-nested AST. Keep the native stack bounded
2020
+ // while retaining each pair's checker type and lazy operand evaluation.
2021
+ const parents = [];
2022
+ let current = expr;
2023
+ let result;
2024
+ while (true) {
2025
+ if (current.operatorToken.kind === ts.SyntaxKind.BarBarToken) {
2026
+ const fallback = lowerAbsenceAwareOrChain(lowerer, current);
2027
+ if (fallback !== null) {
2028
+ result = fallback;
2029
+ break;
2030
+ }
2031
+ }
2032
+ const left = current.left;
2033
+ if (ts.isBinaryExpression(left) &&
2034
+ (left.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken ||
2035
+ left.operatorToken.kind === ts.SyntaxKind.BarBarToken) &&
2036
+ !lowerer.chainRecvByNode.has(left)) {
2037
+ parents.push(current);
2038
+ current = left;
2039
+ continue;
2040
+ }
2041
+ result = lowerLogicalPair(lowerer, current, current.operatorToken.kind === ts.SyntaxKind.BarBarToken
2042
+ ? lowerPresenceOperand(lowerer, left)
2043
+ : (lowerAbsenceProbe(lowerer, left) ?? lowerer.lowerExpr(left)));
2044
+ break;
2045
+ }
2046
+ for (let i = parents.length - 1; i >= 0; i--) {
2047
+ result = lowerLogicalPair(lowerer, parents[i], result);
2048
+ }
2049
+ return result;
2050
+ }
2051
+ function lowerLogicalPair(lowerer, expr, left) {
2052
+ const op = expr.operatorToken.kind;
2053
+ const loc = locOf(expr);
2054
+ // Preserve short-circuiting during lowering too: an unreachable member
2055
+ // on a specialized value must not poison the surrounding JS statement.
2056
+ if (left.kind === "boolLit") {
2057
+ const takeRight = op === ts.SyntaxKind.AmpersandAmpersandToken ? left.value : !left.value;
2058
+ return takeRight ? lowerer.lowerExpr(expr.right) : left;
2059
+ }
2060
+ if (left.kind === "unitLit" && op === ts.SyntaxKind.AmpersandAmpersandToken)
2061
+ return left;
2062
+ if (op === ts.SyntaxKind.BarBarToken && REF_TRUTHY_KINDS.has(left.type.kind))
2063
+ return left;
2064
+ const right = lowerer.lowerExpr(expr.right);
2065
+ // A LITERAL-unit left operand (a compile-time undefined/null — the
2066
+ // capability-probe members: `process.features.inspector ||
2067
+ // !flag.startsWith('--inspect')` reads undefined in a compiled
2068
+ // binary): statically falsy, so the operator folds JS-exactly —
2069
+ // `unit || X` IS X, `unit && X` IS the unit (X's side effects never
2070
+ // run in JS either; the lowered right is simply dropped). Literal
2071
+ // units only — computed unit-typed values keep the fences below.
2072
+ if (left.kind === "unitLit") {
2073
+ return op === ts.SyntaxKind.BarBarToken ? right : left;
2074
+ }
2075
+ // JS objects and symbols are always truthy. In `ref || fallback`
2076
+ // the fallback is therefore unreachable and the result is the
2077
+ // already-evaluated left value — the browser-fallback idiom used by
2078
+ // packages for `process.argv || []` and `process.env || {}`. The
2079
+ // operand itself remains in the IR, preserving reads/calls that
2080
+ // produce the reference; only the unreachable right lowering drops.
2081
+ if (op === ts.SyntaxKind.BarBarToken && REF_TRUTHY_KINDS.has(left.type.kind)) {
2082
+ return left;
2083
+ }
2084
+ if (left.type.kind === "dyn" || right.type.kind === "dyn") {
2085
+ // A checked-dynamic operand (`fn.name || '<anonymous>'` —
2086
+ // test/common's _mustCallInner): both sides live in the checked-dynamic tree and
2087
+ // the deciding test is ToBoolean over the dyn kind
2088
+ // (scr_dyn_truthy) — JS value semantics exactly, result dyn. The
2089
+ // non-dyn side converts through the usual boundary; a value with
2090
+ // no dyn representation keeps the fence.
2091
+ const l = lowerer.coerceToExpected(left, DYN);
2092
+ const r = lowerer.coerceToExpected(right, DYN);
2093
+ if (l.type.kind !== "dyn" || r.type.kind !== "dyn") {
2094
+ lowerer.unsupported("SC1100", expr, "logical operators on 'unknown' values");
2095
+ }
2096
+ return {
2097
+ kind: "logical",
2098
+ op: op === ts.SyntaxKind.AmpersandAmpersandToken ? "&&" : "||",
2099
+ left: l,
2100
+ right: r,
2101
+ type: DYN,
2102
+ loc,
2103
+ };
2104
+ }
2105
+ if (isJsSourceFile(ts.getSourceFileOfNode(expr)) &&
2106
+ op === ts.SyntaxKind.AmpersandAmpersandToken &&
2107
+ left.type.kind === "union" &&
2108
+ lowerer.unions.get(left.type.unionId)?.arms.some((arm) => arm.kind === "bool") &&
2109
+ !typeEquals(left.type, right.type) &&
2110
+ lowerer.dynConvertible(left.type) &&
2111
+ lowerer.dynConvertible(right.type)) {
2112
+ return {
2113
+ kind: "logical",
2114
+ op: "&&",
2115
+ left: lowerer.coerceToExpected(left, DYN),
2116
+ right: lowerer.coerceToExpected(right, DYN),
2117
+ type: DYN,
2118
+ loc,
2119
+ };
2120
+ }
2121
+ if (left.type.kind === "union" || right.type.kind === "union") {
2122
+ // Test the deciding operand in its own representation. The result
2123
+ // contains only the values that can survive short-circuit evaluation.
2124
+ let target = lowerer.mapTypeOf(lowerer.typeOf(expr));
2125
+ // Index reads can be absent without noUncheckedIndexedAccess. Their
2126
+ // explicit nullish fallback still runs, even if the checker discarded it.
2127
+ if (target !== null) {
2128
+ const returned = [
2129
+ right.type,
2130
+ ...(op === ts.SyntaxKind.AmpersandAmpersandToken ? [left.type] : []),
2131
+ ];
2132
+ for (const type of returned) {
2133
+ const arms = type.kind === "union" ? (lowerer.unions.get(type.unionId)?.arms ?? []) : [type];
2134
+ for (const arm of arms) {
2135
+ if (arm.kind === "undefinedT" && !isUnitType(target))
2136
+ target = lowerer.runtimeOptionalType(target);
2137
+ if (arm.kind === "nullT")
2138
+ target = withUnitArm(target, arm.kind, lowerer.unions) ?? target;
2139
+ }
2140
+ }
2141
+ }
2142
+ // A broad-JSDoc npm-static body can leave the CHECKER result `any`
2143
+ // even after declaration-backed specialization has recovered both
2144
+ // operands (`helpOption && args.find(...)` in commander). When the
2145
+ // left consists only of always-truthy references and falsy units,
2146
+ // the static result is exactly the right operand plus those units.
2147
+ if (op === ts.SyntaxKind.AmpersandAmpersandToken &&
2148
+ target === null &&
2149
+ lowerer.implicitParamTypes !== null &&
2150
+ npmStaticPackageOfPath(ts.getSourceFileOfNode(expr).fileName) !== null &&
2151
+ (lowerer.typeOf(expr).flags & ts.TypeFlags.Any) !== 0 &&
2152
+ left.type.kind === "union") {
2153
+ const leftArms = lowerer.unions.get(left.type.unionId)?.arms;
2154
+ const rightArms = right.type.kind === "union" ? lowerer.unions.get(right.type.unionId)?.arms : [right.type];
2155
+ const rightIsStatic = rightArms?.every((arm) => arm.kind !== "dyn" && arm.kind !== "caught" && arm.kind !== "void") ?? false;
2156
+ if (leftArms &&
2157
+ rightArms &&
2158
+ rightIsStatic &&
2159
+ leftArms.some(isUnitType) &&
2160
+ leftArms.every((arm) => isUnitType(arm) || REF_TRUTHY_KINDS.has(arm.kind))) {
2161
+ const byKey = new Map();
2162
+ for (const arm of [...rightArms, ...leftArms.filter(isUnitType)]) {
2163
+ byKey.set(typeKey(arm), arm);
2164
+ }
2165
+ const arms = [...byKey.values()].sort((a, b) => (typeKey(a) < typeKey(b) ? -1 : 1));
2166
+ if (arms.length > 1) {
2167
+ const source = right.type.kind === "union" ? lowerer.unions.get(right.type.unionId) : undefined;
2168
+ target = {
2169
+ kind: "union",
2170
+ unionId: source ? lowerer.unions.transform(source, arms) : lowerer.unions.intern(arms),
2171
+ };
2172
+ }
2173
+ }
2174
+ }
2175
+ // `&&` over an always-truthy plain left operand (an array, object or
2176
+ // function value) whose result union has no arm for it: every JS
2177
+ // object is truthy, so `list && list[0]` evaluates the left for its
2178
+ // effects and answers the right. Coercing the left into that union
2179
+ // would trap at run time where Node answers the right operand.
2180
+ if (op === ts.SyntaxKind.AmpersandAmpersandToken &&
2181
+ target?.kind === "union" &&
2182
+ REF_TRUTHY_KINDS.has(left.type.kind) &&
2183
+ lowerer.armTag(target.unionId, left.type) < 0) {
2184
+ return {
2185
+ kind: "seqExpr",
2186
+ stmts: [{ kind: "exprStmt", expr: left, loc }],
2187
+ result: lowerer.coerceInto(expr.right, right, target),
2188
+ type: target,
2189
+ loc,
2190
+ };
2191
+ }
2192
+ if (target?.kind === "union") {
2193
+ // `&&` whose left does NOT fit the result union: the checker
2194
+ // built that result by DROPPING left arms which are always
2195
+ // truthy (`Option | undefined && string | undefined` answers
2196
+ // `string | undefined`, not `Option | string | undefined`).
2197
+ // Evaluate the left once, test it in its own union, and retag it
2198
+ // only on the falsy path. Any stranded reference arms are
2199
+ // unreachable there because every JS object is truthy.
2200
+ if (op === ts.SyntaxKind.AmpersandAmpersandToken &&
2201
+ left.type.kind === "union" &&
2202
+ !typeEquals(left.type, target)) {
2203
+ const def = lowerer.unions.get(left.type.unionId);
2204
+ const trappable = new Set();
2205
+ def?.arms.forEach((arm, tag) => {
2206
+ if (lowerer.armTag(target.unionId, arm) < 0 && REF_TRUTHY_KINDS.has(arm.kind)) {
2207
+ trappable.add(tag);
2208
+ }
2209
+ });
2210
+ const retag = trappable.size === 0
2211
+ ? null
2212
+ : lowerer.unionRetagHelper(left.type.unionId, target.unionId, loc, trappable);
2213
+ if (retag) {
2214
+ lowerer.requireTruthyUnion(left.type.unionId, expr);
2215
+ const stmts = [];
2216
+ let stable = left;
2217
+ if (!isSafeToRepeat(left)) {
2218
+ const local = lowerer.declareHiddenLocal("%and", left.type);
2219
+ stmts.push({ kind: "varDecl", localId: local.id, init: left, loc });
2220
+ stable = varRef(local.id, left.type, loc);
2221
+ }
2222
+ const result = {
2223
+ kind: "ternary",
2224
+ cond: lowerer.ensureBool(stable, expr.left),
2225
+ then: lowerer.coerceInto(expr.right, right, target),
2226
+ else_: { kind: "call", callee: retag, args: [stable], type: target, loc },
2227
+ type: target,
2228
+ loc,
2229
+ };
2230
+ return stmts.length === 0
2231
+ ? result
2232
+ : { kind: "seqExpr", stmts, result, type: target, loc };
2233
+ }
2234
+ }
2235
+ // `||` whose left does NOT fit the result union: the checker built
2236
+ // that result by DROPPING the left's falsy arms (`process.env.X ||
2237
+ // null` is `string | null`, `|| 3000` is `string | number` — the
2238
+ // `undefined` is gone from both), so coercing the left eagerly, as
2239
+ // the shared shape below does, retags an arm the test is about to
2240
+ // rule out and throws where Node yields the default. Single-eval
2241
+ // instead: test the left in its OWN union and retag only on the
2242
+ // truthy side, where the dropped arms are unreachable.
2243
+ if (op === ts.SyntaxKind.BarBarToken &&
2244
+ left.type.kind === "union" &&
2245
+ !typeEquals(left.type, target)) {
2246
+ const retag = lowerer.unionRetagHelper(left.type.unionId, target.unionId, loc);
2247
+ if (retag) {
2248
+ lowerer.requireTruthyUnion(left.type.unionId, expr);
2249
+ return {
2250
+ kind: "orDefault",
2251
+ left,
2252
+ right: lowerer.coerceInto(expr.right, right, target),
2253
+ retag,
2254
+ type: target,
2255
+ loc,
2256
+ };
2257
+ }
2258
+ }
2259
+ lowerer.requireTruthyUnion(target.unionId, expr);
2260
+ return {
2261
+ kind: "logical",
2262
+ op: op === ts.SyntaxKind.AmpersandAmpersandToken ? "&&" : "||",
2263
+ left: lowerer.coerceInto(expr.left, left, target),
2264
+ right: lowerer.coerceInto(expr.right, right, target),
2265
+ type: target,
2266
+ loc,
2267
+ };
2268
+ }
2269
+ // `u || d` NARROWED by the default: the checker types the result
2270
+ // as u's single non-unit arm (`marker() || "default"`) — evaluate
2271
+ // u once, truthy extracts the arm, falsy takes d lazily (the
2272
+ // orDefault node, nullish's truthiness sibling). An UNMAPPABLE
2273
+ // checker result takes the same rule (`options.runner ||
2274
+ // defaultRunner` — tsc's union of two structurally-compatible
2275
+ // function types has no representation, while the left's one
2276
+ // non-unit arm is the only representable answer): the default
2277
+ // must coerce into the arm or fence on its own.
2278
+ if (op === ts.SyntaxKind.BarBarToken && left.type.kind === "union") {
2279
+ const def = lowerer.unions.get(left.type.unionId);
2280
+ const rest = def ? def.arms.filter((a) => !isUnitType(a)) : [];
2281
+ const funcArmDefault = rest[0]?.kind === "func" && (target === null || target.kind === "func");
2282
+ if (rest.length === 1 &&
2283
+ ((target !== null && typeEquals(target, rest[0])) || funcArmDefault)) {
2284
+ lowerer.requireTruthyUnion(left.type.unionId, expr);
2285
+ const dflt = lowerer.lowerExprExpecting(expr.right, rest[0]);
2286
+ return { kind: "orDefault", left, right: dflt, type: rest[0], loc };
2287
+ }
2288
+ }
2289
+ // JavaScript defaults can join differently inferred object layouts.
2290
+ // When both operands have native checked representations, preserve
2291
+ // the deciding value and short-circuit evaluation in that domain.
2292
+ if (isJsSourceFile(ts.getSourceFileOfNode(expr)) &&
2293
+ lowerer.dynConvertible(left.type) &&
2294
+ lowerer.dynConvertible(right.type)) {
2295
+ return {
2296
+ kind: "logical",
2297
+ op: op === ts.SyntaxKind.AmpersandAmpersandToken ? "&&" : "||",
2298
+ left: lowerer.coerceInto(expr.left, left, DYN),
2299
+ right: lowerer.coerceInto(expr.right, right, DYN),
2300
+ type: DYN,
2301
+ loc,
2302
+ };
2303
+ }
2304
+ lowerer.unsupported("SC1090", expr, `logical operators on union-typed values outside conditions (${NARROW_FIRST})`);
2305
+ }
2306
+ const kind = left.type.kind;
2307
+ if (kind !== right.type.kind || (kind !== "f64" && kind !== "string" && kind !== "bool")) {
2308
+ // Mixed PLAIN operands (`value || null`, `flag || undefined`,
2309
+ // `s || 0`): JS value semantics still compile when the checker
2310
+ // types the RESULT as one union both operands coerce into — the
2311
+ // same lift the union-operand path above takes, arriving here
2312
+ // with two plain arm values instead.
2313
+ const target = lowerer.mapTypeOf(lowerer.typeOf(expr));
2314
+ // An always-truthy left operand (a record, object, array or function
2315
+ // value: every JS object is truthy): `o && x` evaluates `o` for its
2316
+ // effects and answers `x`; `o || x` answers `o` and never evaluates
2317
+ // `x`. supports-color's `stream && stream.isTTY` is the shape. Ahead
2318
+ // of the union lift below exactly where that lift would store the
2319
+ // object in a result union with no arm for it; a union holding the
2320
+ // operand keeps the lift.
2321
+ if (REF_TRUTHY_KINDS.has(kind) &&
2322
+ (target?.kind !== "union" ||
2323
+ (op === ts.SyntaxKind.AmpersandAmpersandToken &&
2324
+ lowerer.armTag(target.unionId, left.type) < 0))) {
2325
+ const and = op === ts.SyntaxKind.AmpersandAmpersandToken;
2326
+ const answer = and ? right : left;
2327
+ const answerT = target ?? answer.type;
2328
+ if (answerT.kind !== "void") {
2329
+ const value = lowerer.coerceInto(and ? expr.right : expr.left, answer, answerT);
2330
+ if (!and)
2331
+ return value;
2332
+ return {
2333
+ kind: "seqExpr",
2334
+ stmts: [{ kind: "exprStmt", expr: left, loc }],
2335
+ result: value,
2336
+ type: answerT,
2337
+ loc,
2338
+ };
2339
+ }
2340
+ }
2341
+ if (target?.kind === "union") {
2342
+ lowerer.requireTruthyUnion(target.unionId, expr);
2343
+ return {
2344
+ kind: "logical",
2345
+ op: op === ts.SyntaxKind.AmpersandAmpersandToken ? "&&" : "||",
2346
+ left: lowerer.coerceInto(expr.left, left, target),
2347
+ right: lowerer.coerceInto(expr.right, right, target),
2348
+ type: target,
2349
+ loc,
2350
+ };
2351
+ }
2352
+ lowerer.unsupported("SC1042", expr);
2353
+ }
2354
+ return {
2355
+ kind: "logical",
2356
+ op: op === ts.SyntaxKind.AmpersandAmpersandToken ? "&&" : "||",
2357
+ left,
2358
+ right,
2359
+ type: left.type,
2360
+ loc,
2361
+ };
2362
+ }
2363
+ function lowerAbsenceAwareOrChain(lowerer, expr) {
2364
+ const nodes = [];
2365
+ const pending = [expr];
2366
+ while (pending.length !== 0) {
2367
+ const node = pending.pop();
2368
+ if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.BarBarToken) {
2369
+ pending.push(node.right, node.left);
2370
+ }
2371
+ else {
2372
+ nodes.push(node);
2373
+ }
2374
+ }
2375
+ if (nodes.length < 3)
2376
+ return null;
2377
+ const lowered = nodes.map((node) => lowerAbsenceProbe(lowerer, node) ?? lowerer.lowerExpr(node));
2378
+ if (!lowered.some((value) => value.type.kind === "union" && lowerer.armTag(value.type.unionId, UNDEFINED_T) >= 0)) {
2379
+ return null;
2380
+ }
2381
+ let result = lowered[lowered.length - 1];
2382
+ for (let i = lowered.length - 2; i >= 0; i--) {
2383
+ const left = lowered[i];
2384
+ const loc = locOf(nodes[i]);
2385
+ if (left.type.kind === "union") {
2386
+ const def = lowerer.unions.get(left.type.unionId);
2387
+ const nonUnit = def?.arms.filter((arm) => !isUnitType(arm)) ?? [];
2388
+ if (nonUnit.length !== 1 || !typeEquals(nonUnit[0], result.type))
2389
+ return null;
2390
+ lowerer.requireTruthyUnion(left.type.unionId, expr);
2391
+ result = { kind: "orDefault", left, right: result, type: result.type, loc };
2392
+ continue;
2393
+ }
2394
+ if (!typeEquals(left.type, result.type))
2395
+ return null;
2396
+ result = { kind: "logical", op: "||", left, right: result, type: result.type, loc };
2397
+ }
2398
+ return result;
2399
+ }
2400
+ /** `typeof WebAssembly === "object"` and `typeof WebAssembly.<member> ===
2401
+ * "function"`: the operand needs no value, so the test folds as bare typeof
2402
+ * does (builtins/webassembly.ts) before any dyn-typed operand lowers. */
2403
+ function lowerWebAssemblyTypeofTest(lowerer, expr, loc) {
2404
+ const negated = expr.operatorToken.kind === ts.SyntaxKind.ExclamationEqualsEqualsToken;
2405
+ for (const [a, b] of operandPairs(expr)) {
2406
+ if (!ts.isTypeOfExpression(a) || !ts.isStringLiteral(b))
2407
+ continue;
2408
+ const folded = lowerWebAssemblyTypeof(lowerer, a.expression);
2409
+ if (folded?.kind !== "strLit")
2410
+ continue;
2411
+ return { kind: "boolLit", value: (folded.value === b.text) !== negated, type: BOOL, loc };
2412
+ }
2413
+ return null;
2414
+ }
2415
+ /** `typeof v === "lit"` / `typeof v !== "lit"` where v is UNION-typed: the
2416
+ * arms whose static typeof answer equals the literal form a tag set, and
2417
+ * the test is a runtime tag test — one `unionIsTag` for a single matching
2418
+ * arm (the operand embeds once, so even effectful operands compose), a
2419
+ * short-circuit chain for several (pure reads only — the operand rides
2420
+ * every test, exactly the `== null` composition rule). When every arm
2421
+ * answers the same way the comparison is statically decided and folds to
2422
+ * a bool literal — dropping only a side-effect-free read, the same
2423
+ * trust-the-checker bet as lowerUnitComparison. tsc's control-flow
2424
+ * narrowing then types the branches, and reads bridge through
2425
+ * maybeNarrow's unionNarrow as usual. Null when neither side is a typeof
2426
+ * over a union-typed operand or the literal side isn't a literal (the
2427
+ * bare-typeof value form then composes with strEq for pure operands). */
2428
+ function lowerUnionTypeofTest(lowerer, expr, loc) {
2429
+ const negated = expr.operatorToken.kind === ts.SyntaxKind.ExclamationEqualsEqualsToken;
2430
+ for (const [a, b] of operandPairs(expr)) {
2431
+ if (!ts.isTypeOfExpression(a))
2432
+ continue;
2433
+ const stored = runtimeOptionalStorageOperand(lowerer, a.expression);
2434
+ if (stored === null && lowerer.mapTypeOf(lowerer.typeOf(a.expression))?.kind !== "union")
2435
+ continue;
2436
+ if (!ts.isStringLiteral(b))
2437
+ continue; // bare-typeof + strEq handles pure operands
2438
+ const value = stored ?? lowerer.lowerExpr(a.expression);
2439
+ if (value.type.kind !== "union")
2440
+ continue; // defensive: an already-narrowed use
2441
+ const unionId = value.type.unionId;
2442
+ const def = lowerer.unions.get(unionId);
2443
+ const answers = def?.arms.map(typeofAnswer);
2444
+ if (!def || !answers || !answers.every((s) => s !== null))
2445
+ continue;
2446
+ const tags = answers.flatMap((s, i) => (s === b.text ? [i] : []));
2447
+ if (tags.length === 0 || tags.length === def.arms.length) {
2448
+ if (!isSafeToRepeat(value)) {
2449
+ lowerer.unsupported("SC1090", expr, "statically-decided 'typeof' tests over effectful operands (bind the value to a const first)");
2450
+ }
2451
+ return { kind: "boolLit", value: (tags.length !== 0) !== negated, type: BOOL, loc };
2452
+ }
2453
+ const isTag = (tag) => ({
2454
+ kind: "unionIsTag",
2455
+ unionId,
2456
+ tag,
2457
+ negated,
2458
+ value,
2459
+ type: BOOL,
2460
+ loc,
2461
+ });
2462
+ if (tags.length === 1)
2463
+ return isTag(tags[0]);
2464
+ if (!isSafeToRepeat(value)) {
2465
+ lowerer.unsupported("SC1090", expr, "'typeof' tests matching several union arms over operands that aren't plain reads (bind the value to a const first)");
2466
+ }
2467
+ // Tag-in-set as a short-circuit chain (De Morgan for `!==`).
2468
+ let acc = isTag(tags[0]);
2469
+ for (const t of tags.slice(1)) {
2470
+ acc = {
2471
+ kind: "logical",
2472
+ op: negated ? "&&" : "||",
2473
+ left: acc,
2474
+ right: isTag(t),
2475
+ type: BOOL,
2476
+ loc,
2477
+ };
2478
+ }
2479
+ return acc;
2480
+ }
2481
+ return null;
2482
+ }
2483
+ //# sourceMappingURL=binary.js.map