@scriptc/compiler 0.2.5 → 0.2.7

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 (520) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +62 -48
  2. package/dist/backend/cycle-analysis.d.ts +21 -9
  3. package/dist/backend/cycle-analysis.js +139 -67
  4. package/dist/backend/cycle-analysis.js.map +1 -1
  5. package/dist/backend/cycle-analysis.test.js +283 -3
  6. package/dist/backend/cycle-analysis.test.js.map +1 -1
  7. package/dist/backend/cycle-mutability.d.ts +39 -0
  8. package/dist/backend/cycle-mutability.js +205 -0
  9. package/dist/backend/cycle-mutability.js.map +1 -0
  10. package/dist/backend/executable-features.js +1 -0
  11. package/dist/backend/executable-features.js.map +1 -1
  12. package/dist/backend/link-plan-core.d.ts +4 -1
  13. package/dist/backend/link-plan-core.js +16 -3
  14. package/dist/backend/link-plan-core.js.map +1 -1
  15. package/dist/backend/link-plan.d.ts +3 -1
  16. package/dist/backend/link-plan.js +3 -0
  17. package/dist/backend/link-plan.js.map +1 -1
  18. package/dist/backend/llvm/alloc.d.ts +40 -0
  19. package/dist/backend/llvm/alloc.js +205 -0
  20. package/dist/backend/llvm/alloc.js.map +1 -0
  21. package/dist/backend/llvm/alloc.test.d.ts +1 -0
  22. package/dist/backend/llvm/alloc.test.js +102 -0
  23. package/dist/backend/llvm/alloc.test.js.map +1 -0
  24. package/dist/backend/llvm/byte-numbers.js +32 -4
  25. package/dist/backend/llvm/byte-numbers.js.map +1 -1
  26. package/dist/backend/llvm/byte-windows.d.ts +31 -0
  27. package/dist/backend/llvm/byte-windows.js +334 -0
  28. package/dist/backend/llvm/byte-windows.js.map +1 -0
  29. package/dist/backend/llvm/byte-windows.test.d.ts +1 -0
  30. package/dist/backend/llvm/byte-windows.test.js +244 -0
  31. package/dist/backend/llvm/byte-windows.test.js.map +1 -0
  32. package/dist/backend/llvm/call-lifetimes.d.ts +17 -5
  33. package/dist/backend/llvm/call-lifetimes.js +58 -24
  34. package/dist/backend/llvm/call-lifetimes.js.map +1 -1
  35. package/dist/backend/llvm/call-lifetimes.test.js +170 -0
  36. package/dist/backend/llvm/call-lifetimes.test.js.map +1 -1
  37. package/dist/backend/llvm/classes.d.ts +18 -2
  38. package/dist/backend/llvm/classes.js +115 -41
  39. package/dist/backend/llvm/classes.js.map +1 -1
  40. package/dist/backend/llvm/classes.test.d.ts +1 -0
  41. package/dist/backend/llvm/classes.test.js +132 -0
  42. package/dist/backend/llvm/classes.test.js.map +1 -0
  43. package/dist/backend/llvm/common.d.ts +13 -0
  44. package/dist/backend/llvm/common.js +30 -0
  45. package/dist/backend/llvm/common.js.map +1 -1
  46. package/dist/backend/llvm/constant-callbacks.d.ts +27 -0
  47. package/dist/backend/llvm/constant-callbacks.js +450 -0
  48. package/dist/backend/llvm/constant-callbacks.js.map +1 -0
  49. package/dist/backend/llvm/constant-callbacks.test.d.ts +1 -0
  50. package/dist/backend/llvm/constant-callbacks.test.js +261 -0
  51. package/dist/backend/llvm/constant-callbacks.test.js.map +1 -0
  52. package/dist/backend/llvm/dense-array-access.d.ts +29 -0
  53. package/dist/backend/llvm/dense-array-access.js +335 -0
  54. package/dist/backend/llvm/dense-array-access.js.map +1 -0
  55. package/dist/backend/llvm/dense-array-access.test.d.ts +1 -0
  56. package/dist/backend/llvm/dense-array-access.test.js +149 -0
  57. package/dist/backend/llvm/dense-array-access.test.js.map +1 -0
  58. package/dist/backend/llvm/dyn.d.ts +35 -1
  59. package/dist/backend/llvm/dyn.js +196 -35
  60. package/dist/backend/llvm/dyn.js.map +1 -1
  61. package/dist/backend/llvm/emitter.d.ts +143 -4
  62. package/dist/backend/llvm/emitter.js +882 -136
  63. package/dist/backend/llvm/emitter.js.map +1 -1
  64. package/dist/backend/llvm/emitter.test.js +82 -14
  65. package/dist/backend/llvm/emitter.test.js.map +1 -1
  66. package/dist/backend/llvm/expr-async.js +58 -4
  67. package/dist/backend/llvm/expr-async.js.map +1 -1
  68. package/dist/backend/llvm/expr-async.test.d.ts +1 -0
  69. package/dist/backend/llvm/expr-async.test.js +62 -0
  70. package/dist/backend/llvm/expr-async.test.js.map +1 -0
  71. package/dist/backend/llvm/expr-bytes.js +11 -0
  72. package/dist/backend/llvm/expr-bytes.js.map +1 -1
  73. package/dist/backend/llvm/expr-calls.js +151 -25
  74. package/dist/backend/llvm/expr-calls.js.map +1 -1
  75. package/dist/backend/llvm/expr-containers.js +37 -14
  76. package/dist/backend/llvm/expr-containers.js.map +1 -1
  77. package/dist/backend/llvm/expr-control.js +92 -2
  78. package/dist/backend/llvm/expr-control.js.map +1 -1
  79. package/dist/backend/llvm/expr-dispatch.js +2 -0
  80. package/dist/backend/llvm/expr-dispatch.js.map +1 -1
  81. package/dist/backend/llvm/expr-dynamic.js +210 -28
  82. package/dist/backend/llvm/expr-dynamic.js.map +1 -1
  83. package/dist/backend/llvm/expr-primitives.d.ts +1 -1
  84. package/dist/backend/llvm/expr-primitives.js +58 -23
  85. package/dist/backend/llvm/expr-primitives.js.map +1 -1
  86. package/dist/backend/llvm/expr-primitives.test.js +1 -1
  87. package/dist/backend/llvm/expr-records.js +3 -3
  88. package/dist/backend/llvm/expr-records.js.map +1 -1
  89. package/dist/backend/llvm/expr-stream-bridges.js +59 -2
  90. package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
  91. package/dist/backend/llvm/expr-stream-bridges.test.js +1 -1
  92. package/dist/backend/llvm/integer-remainder.d.ts +18 -0
  93. package/dist/backend/llvm/integer-remainder.js +117 -0
  94. package/dist/backend/llvm/integer-remainder.js.map +1 -0
  95. package/dist/backend/llvm/layouts.d.ts +2 -1
  96. package/dist/backend/llvm/layouts.js +4 -3
  97. package/dist/backend/llvm/layouts.js.map +1 -1
  98. package/dist/backend/llvm/lazy-captures.d.ts +16 -0
  99. package/dist/backend/llvm/lazy-captures.js +96 -0
  100. package/dist/backend/llvm/lazy-captures.js.map +1 -0
  101. package/dist/backend/llvm/lazy-captures.test.d.ts +1 -0
  102. package/dist/backend/llvm/lazy-captures.test.js +78 -0
  103. package/dist/backend/llvm/lazy-captures.test.js.map +1 -0
  104. package/dist/backend/llvm/lib-abi.js +7 -0
  105. package/dist/backend/llvm/lib-abi.js.map +1 -1
  106. package/dist/backend/llvm/lib-dispatch.js +7 -22
  107. package/dist/backend/llvm/lib-dispatch.js.map +1 -1
  108. package/dist/backend/llvm/lib-filesystem.js +3 -4
  109. package/dist/backend/llvm/lib-filesystem.js.map +1 -1
  110. package/dist/backend/llvm/lib-shared.js +15 -0
  111. package/dist/backend/llvm/lib-shared.js.map +1 -1
  112. package/dist/backend/llvm/local-array-reads.d.ts +13 -3
  113. package/dist/backend/llvm/local-array-reads.js +159 -77
  114. package/dist/backend/llvm/local-array-reads.js.map +1 -1
  115. package/dist/backend/llvm/local-array-reads.test.js +105 -4
  116. package/dist/backend/llvm/local-array-reads.test.js.map +1 -1
  117. package/dist/backend/llvm/local-union-storage.d.ts +5 -1
  118. package/dist/backend/llvm/local-union-storage.js +48 -6
  119. package/dist/backend/llvm/local-union-storage.js.map +1 -1
  120. package/dist/backend/llvm/local-union-storage.test.js +91 -4
  121. package/dist/backend/llvm/local-union-storage.test.js.map +1 -1
  122. package/dist/backend/llvm/loop-array-borrows.d.ts +11 -0
  123. package/dist/backend/llvm/loop-array-borrows.js +70 -0
  124. package/dist/backend/llvm/loop-array-borrows.js.map +1 -0
  125. package/dist/backend/llvm/loop-array-borrows.test.d.ts +1 -0
  126. package/dist/backend/llvm/loop-array-borrows.test.js +145 -0
  127. package/dist/backend/llvm/loop-array-borrows.test.js.map +1 -0
  128. package/dist/backend/llvm/map-read-lifetimes.d.ts +5 -0
  129. package/dist/backend/llvm/map-read-lifetimes.js +20 -5
  130. package/dist/backend/llvm/map-read-lifetimes.js.map +1 -1
  131. package/dist/backend/llvm/map-read-lifetimes.test.js +1 -1
  132. package/dist/backend/llvm/nullable-fields.d.ts +28 -0
  133. package/dist/backend/llvm/nullable-fields.js +45 -0
  134. package/dist/backend/llvm/nullable-fields.js.map +1 -0
  135. package/dist/backend/llvm/nullable-fields.test.d.ts +1 -0
  136. package/dist/backend/llvm/nullable-fields.test.js +48 -0
  137. package/dist/backend/llvm/nullable-fields.test.js.map +1 -0
  138. package/dist/backend/llvm/reference-effects.d.ts +2 -1
  139. package/dist/backend/llvm/reference-effects.js +7 -0
  140. package/dist/backend/llvm/reference-effects.js.map +1 -1
  141. package/dist/backend/llvm/serialized-ir-emission.test.d.ts +1 -0
  142. package/dist/backend/llvm/serialized-ir-emission.test.js +52 -0
  143. package/dist/backend/llvm/serialized-ir-emission.test.js.map +1 -0
  144. package/dist/backend/llvm/shapes.d.ts +73 -3
  145. package/dist/backend/llvm/shapes.js +281 -34
  146. package/dist/backend/llvm/shapes.js.map +1 -1
  147. package/dist/backend/llvm/shapes.test.js +114 -5
  148. package/dist/backend/llvm/shapes.test.js.map +1 -1
  149. package/dist/backend/llvm/split-loops.d.ts +48 -0
  150. package/dist/backend/llvm/split-loops.js +183 -0
  151. package/dist/backend/llvm/split-loops.js.map +1 -0
  152. package/dist/backend/llvm/split.js +0 -7
  153. package/dist/backend/llvm/split.js.map +1 -1
  154. package/dist/backend/llvm/split.test.js +66 -2
  155. package/dist/backend/llvm/split.test.js.map +1 -1
  156. package/dist/backend/llvm/stack-callbacks.d.ts +14 -0
  157. package/dist/backend/llvm/stack-callbacks.js +72 -0
  158. package/dist/backend/llvm/stack-callbacks.js.map +1 -0
  159. package/dist/backend/llvm/stack-captures.d.ts +27 -0
  160. package/dist/backend/llvm/stack-captures.js +152 -0
  161. package/dist/backend/llvm/stack-captures.js.map +1 -0
  162. package/dist/backend/llvm/stack-unions.test.js +38 -1
  163. package/dist/backend/llvm/stack-unions.test.js.map +1 -1
  164. package/dist/backend/llvm/string-construction.test.js +1 -1
  165. package/dist/backend/llvm/string-key-hash.d.ts +8 -0
  166. package/dist/backend/llvm/string-key-hash.js +59 -0
  167. package/dist/backend/llvm/string-key-hash.js.map +1 -0
  168. package/dist/backend/llvm/string-key-hash.test.d.ts +1 -0
  169. package/dist/backend/llvm/string-key-hash.test.js +34 -0
  170. package/dist/backend/llvm/string-key-hash.test.js.map +1 -0
  171. package/dist/backend/llvm/string-lifetimes.test.js +48 -7
  172. package/dist/backend/llvm/string-lifetimes.test.js.map +1 -1
  173. package/dist/backend/llvm/string-slices.d.ts +20 -0
  174. package/dist/backend/llvm/string-slices.js +87 -0
  175. package/dist/backend/llvm/string-slices.js.map +1 -0
  176. package/dist/backend/llvm/string-slices.test.d.ts +1 -0
  177. package/dist/backend/llvm/string-slices.test.js +98 -0
  178. package/dist/backend/llvm/string-slices.test.js.map +1 -0
  179. package/dist/backend/llvm/switch-dispatch.js +1 -1
  180. package/dist/backend/llvm/switch-dispatch.js.map +1 -1
  181. package/dist/backend/llvm/switch-dispatch.test.js +2 -2
  182. package/dist/backend/llvm/switch-dispatch.test.js.map +1 -1
  183. package/dist/backend/llvm/walkers.d.ts +4 -14
  184. package/dist/backend/llvm/walkers.js +53 -311
  185. package/dist/backend/llvm/walkers.js.map +1 -1
  186. package/dist/backend/may-throw.js +4 -1
  187. package/dist/backend/may-throw.js.map +1 -1
  188. package/dist/backend/may-throw.test.js +1 -1
  189. package/dist/backend/native/cache-warm.d.ts +2 -1
  190. package/dist/backend/native/cache-warm.js.map +1 -1
  191. package/dist/backend/native/contracts.d.ts +5 -2
  192. package/dist/backend/native/contracts.js.map +1 -1
  193. package/dist/backend/native/executable.js +12 -4
  194. package/dist/backend/native/executable.js.map +1 -1
  195. package/dist/backend/native/runtime-inputs.d.ts +1 -1
  196. package/dist/backend/native/runtime-inputs.js +3 -0
  197. package/dist/backend/native/runtime-inputs.js.map +1 -1
  198. package/dist/backend/native-codegen-core.d.ts +7 -0
  199. package/dist/backend/native-codegen-core.js +21 -0
  200. package/dist/backend/native-codegen-core.js.map +1 -1
  201. package/dist/backend/native-codegen.d.ts +9 -0
  202. package/dist/backend/native-codegen.js +38 -18
  203. package/dist/backend/native-codegen.js.map +1 -1
  204. package/dist/backend/native-codegen.test.js +70 -2
  205. package/dist/backend/native-codegen.test.js.map +1 -1
  206. package/dist/backend/native-link-info-core.d.ts +4 -2
  207. package/dist/backend/native-link-info-core.js.map +1 -1
  208. package/dist/backend/native-link-info.d.ts +2 -1
  209. package/dist/backend/native-link-info.js.map +1 -1
  210. package/dist/backend/native-link-info.test.js +2 -2
  211. package/dist/backend/native-link-info.test.js.map +1 -1
  212. package/dist/backend/native-tools.d.ts +6 -2
  213. package/dist/backend/native-tools.js +6 -5
  214. package/dist/backend/native-tools.js.map +1 -1
  215. package/dist/backend/optimization.d.ts +25 -0
  216. package/dist/backend/optimization.js +21 -0
  217. package/dist/backend/optimization.js.map +1 -0
  218. package/dist/backend/optimization.test.d.ts +1 -0
  219. package/dist/backend/optimization.test.js +24 -0
  220. package/dist/backend/optimization.test.js.map +1 -0
  221. package/dist/backend/runtime-abi.d.ts +2 -2
  222. package/dist/backend/runtime-abi.js +2 -2
  223. package/dist/backend/runtime-pack-core.d.ts +16 -4
  224. package/dist/backend/runtime-pack-core.js +31 -13
  225. package/dist/backend/runtime-pack-core.js.map +1 -1
  226. package/dist/backend/runtime-pack-native.d.ts +7 -3
  227. package/dist/backend/runtime-pack-native.js +0 -3
  228. package/dist/backend/runtime-pack-native.js.map +1 -1
  229. package/dist/backend/runtime-pack-targets.test.js +41 -4
  230. package/dist/backend/runtime-pack-targets.test.js.map +1 -1
  231. package/dist/backend/runtime-pack.d.ts +20 -2
  232. package/dist/backend/runtime-pack.js +23 -0
  233. package/dist/backend/runtime-pack.js.map +1 -1
  234. package/dist/backend/runtime-pack.test.js +125 -2
  235. package/dist/backend/runtime-pack.test.js.map +1 -1
  236. package/dist/backend/target-diagnostics.test.js +1 -1
  237. package/dist/backend/targets.d.ts +2 -1
  238. package/dist/backend/targets.js +1 -1
  239. package/dist/backend/targets.js.map +1 -1
  240. package/dist/cli/command.js +5 -4
  241. package/dist/cli/command.js.map +1 -1
  242. package/dist/cli/host.d.ts +2 -1
  243. package/dist/cli/usage.d.ts +1 -1
  244. package/dist/cli/usage.js +5 -2
  245. package/dist/cli/usage.js.map +1 -1
  246. package/dist/compile-types.d.ts +5 -2
  247. package/dist/diagnostics/diagnostic.js +10 -8
  248. package/dist/diagnostics/diagnostic.js.map +1 -1
  249. package/dist/executable/executable-cache.d.ts +3 -2
  250. package/dist/executable/executable-cache.js +8 -4
  251. package/dist/executable/executable-cache.js.map +1 -1
  252. package/dist/executable/executable-cache.test.js +35 -0
  253. package/dist/executable/executable-cache.test.js.map +1 -1
  254. package/dist/frontend/fork-target.d.ts +5 -0
  255. package/dist/frontend/fork-target.js +40 -8
  256. package/dist/frontend/fork-target.js.map +1 -1
  257. package/dist/frontend/fork-target.test.d.ts +1 -0
  258. package/dist/frontend/fork-target.test.js +59 -0
  259. package/dist/frontend/fork-target.test.js.map +1 -0
  260. package/dist/frontend/lowering/abstract-equality.js +5 -49
  261. package/dist/frontend/lowering/abstract-equality.js.map +1 -1
  262. package/dist/frontend/lowering/array-values.d.ts +23 -0
  263. package/dist/frontend/lowering/array-values.js +129 -0
  264. package/dist/frontend/lowering/array-values.js.map +1 -1
  265. package/dist/frontend/lowering/binding-analysis.js +2 -2
  266. package/dist/frontend/lowering/binding-analysis.js.map +1 -1
  267. package/dist/frontend/lowering/builtins/atomics.d.ts +2 -11
  268. package/dist/frontend/lowering/builtins/atomics.js +64 -28
  269. package/dist/frontend/lowering/builtins/atomics.js.map +1 -1
  270. package/dist/frontend/lowering/builtins/errors.js +17 -2
  271. package/dist/frontend/lowering/builtins/errors.js.map +1 -1
  272. package/dist/frontend/lowering/builtins/filesystem-calls.d.ts +3 -0
  273. package/dist/frontend/lowering/builtins/filesystem-calls.js +51 -4
  274. package/dist/frontend/lowering/builtins/filesystem-calls.js.map +1 -1
  275. package/dist/frontend/lowering/builtins/module-calls.js +6 -1
  276. package/dist/frontend/lowering/builtins/module-calls.js.map +1 -1
  277. package/dist/frontend/lowering/builtins/process.d.ts +6 -17
  278. package/dist/frontend/lowering/builtins/process.js +56 -29
  279. package/dist/frontend/lowering/builtins/process.js.map +1 -1
  280. package/dist/frontend/lowering/builtins/workers.d.ts +5 -0
  281. package/dist/frontend/lowering/builtins/workers.js +65 -0
  282. package/dist/frontend/lowering/builtins/workers.js.map +1 -0
  283. package/dist/frontend/lowering/caught-value-dispatch.d.ts +11 -0
  284. package/dist/frontend/lowering/caught-value-dispatch.js +87 -0
  285. package/dist/frontend/lowering/caught-value-dispatch.js.map +1 -0
  286. package/dist/frontend/lowering/class-assertions.d.ts +11 -0
  287. package/dist/frontend/lowering/class-assertions.js +104 -0
  288. package/dist/frontend/lowering/class-assertions.js.map +1 -0
  289. package/dist/frontend/lowering/class-callbacks.d.ts +3 -3
  290. package/dist/frontend/lowering/class-callbacks.js +18 -5
  291. package/dist/frontend/lowering/class-callbacks.js.map +1 -1
  292. package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +1 -0
  293. package/dist/frontend/lowering/class-dynamic-dispatch.js +4 -1
  294. package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
  295. package/dist/frontend/lowering/class-method-mutations.d.ts +5 -0
  296. package/dist/frontend/lowering/class-method-mutations.js +472 -0
  297. package/dist/frontend/lowering/class-method-mutations.js.map +1 -0
  298. package/dist/frontend/lowering/class-method-values.js +25 -5
  299. package/dist/frontend/lowering/class-method-values.js.map +1 -1
  300. package/dist/frontend/lowering/class-protocols.d.ts +17 -0
  301. package/dist/frontend/lowering/class-protocols.js +126 -0
  302. package/dist/frontend/lowering/class-protocols.js.map +1 -0
  303. package/dist/frontend/lowering/class-prototypes.js +8 -2
  304. package/dist/frontend/lowering/class-prototypes.js.map +1 -1
  305. package/dist/frontend/lowering/class-unions.d.ts +16 -0
  306. package/dist/frontend/lowering/class-unions.js +127 -0
  307. package/dist/frontend/lowering/class-unions.js.map +1 -0
  308. package/dist/frontend/lowering/coercions/builders.js +8 -1
  309. package/dist/frontend/lowering/coercions/builders.js.map +1 -1
  310. package/dist/frontend/lowering/coercions/function-adapters.js +2 -0
  311. package/dist/frontend/lowering/coercions/function-adapters.js.map +1 -1
  312. package/dist/frontend/lowering/coercions/identity.d.ts +7 -0
  313. package/dist/frontend/lowering/coercions/identity.js +26 -0
  314. package/dist/frontend/lowering/coercions/identity.js.map +1 -0
  315. package/dist/frontend/lowering/coercions/structural.js +9 -6
  316. package/dist/frontend/lowering/coercions/structural.js.map +1 -1
  317. package/dist/frontend/lowering/collection-narrowing.d.ts +6 -0
  318. package/dist/frontend/lowering/collection-narrowing.js +31 -0
  319. package/dist/frontend/lowering/collection-narrowing.js.map +1 -0
  320. package/dist/frontend/lowering/containers/array-callback-call.d.ts +7 -0
  321. package/dist/frontend/lowering/containers/array-callback-call.js +52 -0
  322. package/dist/frontend/lowering/containers/array-callback-call.js.map +1 -0
  323. package/dist/frontend/lowering/containers/array-callbacks.d.ts +8 -12
  324. package/dist/frontend/lowering/containers/array-callbacks.js +415 -136
  325. package/dist/frontend/lowering/containers/array-callbacks.js.map +1 -1
  326. package/dist/frontend/lowering/containers/array-concat.d.ts +7 -0
  327. package/dist/frontend/lowering/containers/array-concat.js +130 -0
  328. package/dist/frontend/lowering/containers/array-concat.js.map +1 -0
  329. package/dist/frontend/lowering/containers/array-construction.d.ts +2 -0
  330. package/dist/frontend/lowering/containers/array-construction.js +95 -3
  331. package/dist/frontend/lowering/containers/array-construction.js.map +1 -1
  332. package/dist/frontend/lowering/containers/array-methods.d.ts +1 -11
  333. package/dist/frontend/lowering/containers/array-methods.js +43 -132
  334. package/dist/frontend/lowering/containers/array-methods.js.map +1 -1
  335. package/dist/frontend/lowering/containers/bytes.js +12 -34
  336. package/dist/frontend/lowering/containers/bytes.js.map +1 -1
  337. package/dist/frontend/lowering/containers/collection-methods.js +10 -1
  338. package/dist/frontend/lowering/containers/collection-methods.js.map +1 -1
  339. package/dist/frontend/lowering/containers/indexed-objects.js +56 -70
  340. package/dist/frontend/lowering/containers/indexed-objects.js.map +1 -1
  341. package/dist/frontend/lowering/containers/string-and-regexp.js +22 -3
  342. package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
  343. package/dist/frontend/lowering/cycle-initialization.d.ts +41 -0
  344. package/dist/frontend/lowering/cycle-initialization.js +277 -0
  345. package/dist/frontend/lowering/cycle-initialization.js.map +1 -0
  346. package/dist/frontend/lowering/expressions/evaluation-safety.js +4 -0
  347. package/dist/frontend/lowering/expressions/evaluation-safety.js.map +1 -1
  348. package/dist/frontend/lowering/expressions/object-literals.js +140 -38
  349. package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
  350. package/dist/frontend/lowering/expressions/union-field-write.d.ts +4 -4
  351. package/dist/frontend/lowering/expressions/union-field-write.js +54 -44
  352. package/dist/frontend/lowering/expressions/union-field-write.js.map +1 -1
  353. package/dist/frontend/lowering/generic-functions.d.ts +2 -5
  354. package/dist/frontend/lowering/generic-functions.js +13 -10
  355. package/dist/frontend/lowering/generic-functions.js.map +1 -1
  356. package/dist/frontend/lowering/instantiation-path.d.ts +8 -0
  357. package/dist/frontend/lowering/instantiation-path.js +10 -0
  358. package/dist/frontend/lowering/instantiation-path.js.map +1 -0
  359. package/dist/frontend/lowering/instantiation-path.test.d.ts +1 -0
  360. package/dist/frontend/lowering/instantiation-path.test.js +23 -0
  361. package/dist/frontend/lowering/instantiation-path.test.js.map +1 -0
  362. package/dist/frontend/lowering/iterator-adapters.d.ts +20 -0
  363. package/dist/frontend/lowering/iterator-adapters.js +605 -0
  364. package/dist/frontend/lowering/iterator-adapters.js.map +1 -0
  365. package/dist/frontend/lowering/lower-array-sort.d.ts +1 -1
  366. package/dist/frontend/lowering/lower-array-sort.js +44 -5
  367. package/dist/frontend/lowering/lower-array-sort.js.map +1 -1
  368. package/dist/frontend/lowering/lower-array-sort.test.d.ts +1 -0
  369. package/dist/frontend/lowering/lower-array-sort.test.js +31 -0
  370. package/dist/frontend/lowering/lower-array-sort.test.js.map +1 -0
  371. package/dist/frontend/lowering/lower-assert.js +7 -0
  372. package/dist/frontend/lowering/lower-assert.js.map +1 -1
  373. package/dist/frontend/lowering/lower-builtin-values.js +12 -7
  374. package/dist/frontend/lowering/lower-builtin-values.js.map +1 -1
  375. package/dist/frontend/lowering/lower-calls.d.ts +3 -3
  376. package/dist/frontend/lowering/lower-calls.js +198 -124
  377. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  378. package/dist/frontend/lowering/lower-classes.d.ts +7 -0
  379. package/dist/frontend/lowering/lower-classes.js +166 -96
  380. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  381. package/dist/frontend/lowering/lower-event-emitter.js +1 -1
  382. package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
  383. package/dist/frontend/lowering/lower-exprs.d.ts +9 -2
  384. package/dist/frontend/lowering/lower-exprs.js +421 -167
  385. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  386. package/dist/frontend/lowering/lower-functions.d.ts +1 -1
  387. package/dist/frontend/lowering/lower-functions.js +33 -20
  388. package/dist/frontend/lowering/lower-functions.js.map +1 -1
  389. package/dist/frontend/lowering/lower-inspect.js +26 -2
  390. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  391. package/dist/frontend/lowering/lower-island.js +1 -1
  392. package/dist/frontend/lowering/lower-island.js.map +1 -1
  393. package/dist/frontend/lowering/lower-modules.d.ts +1 -0
  394. package/dist/frontend/lowering/lower-modules.js +54 -11
  395. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  396. package/dist/frontend/lowering/lower-stmts.js +59 -69
  397. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  398. package/dist/frontend/lowering/lower-stream.js +1 -1
  399. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  400. package/dist/frontend/lowering/lowerer.d.ts +50 -1
  401. package/dist/frontend/lowering/lowerer.js +333 -26
  402. package/dist/frontend/lowering/lowerer.js.map +1 -1
  403. package/dist/frontend/lowering/native-ffi.js +3 -1
  404. package/dist/frontend/lowering/native-ffi.js.map +1 -1
  405. package/dist/frontend/lowering/runtime-optional-provenance.d.ts +15 -0
  406. package/dist/frontend/lowering/runtime-optional-provenance.js +40 -0
  407. package/dist/frontend/lowering/runtime-optional-provenance.js.map +1 -0
  408. package/dist/frontend/lowering/sanitize-class-types.test.js +2 -2
  409. package/dist/frontend/lowering/split-consumers.d.ts +7 -0
  410. package/dist/frontend/lowering/split-consumers.js +64 -0
  411. package/dist/frontend/lowering/split-consumers.js.map +1 -0
  412. package/dist/frontend/lowering/strict-equality.d.ts +9 -0
  413. package/dist/frontend/lowering/strict-equality.js +116 -0
  414. package/dist/frontend/lowering/strict-equality.js.map +1 -0
  415. package/dist/frontend/lowering/surfaces.d.ts +3 -4
  416. package/dist/frontend/lowering/surfaces.js +38 -7
  417. package/dist/frontend/lowering/surfaces.js.map +1 -1
  418. package/dist/frontend/lowering/union-comparison.d.ts +5 -0
  419. package/dist/frontend/lowering/union-comparison.js +47 -0
  420. package/dist/frontend/lowering/union-comparison.js.map +1 -0
  421. package/dist/frontend/module-source-candidates.d.ts +10 -0
  422. package/dist/frontend/module-source-candidates.js +40 -0
  423. package/dist/frontend/module-source-candidates.js.map +1 -0
  424. package/dist/frontend/module-source-candidates.test.d.ts +1 -0
  425. package/dist/frontend/module-source-candidates.test.js +53 -0
  426. package/dist/frontend/module-source-candidates.test.js.map +1 -0
  427. package/dist/frontend/pipeline.js +2 -2
  428. package/dist/frontend/pipeline.js.map +1 -1
  429. package/dist/frontend/program-analysis.d.ts +2 -0
  430. package/dist/frontend/program-analysis.js +2 -0
  431. package/dist/frontend/program-analysis.js.map +1 -1
  432. package/dist/frontend/program.d.ts +38 -2
  433. package/dist/frontend/program.js +457 -88
  434. package/dist/frontend/program.js.map +1 -1
  435. package/dist/frontend/program.test.js +59 -6
  436. package/dist/frontend/program.test.js.map +1 -1
  437. package/dist/frontend/ts7/ast-node.js +6 -8
  438. package/dist/frontend/ts7/ast-node.js.map +1 -1
  439. package/dist/frontend/ts7/ast-node.test.js +42 -1
  440. package/dist/frontend/ts7/ast-node.test.js.map +1 -1
  441. package/dist/frontend/ts7/ast-wire.d.ts +4 -0
  442. package/dist/frontend/ts7/ast-wire.js +28 -0
  443. package/dist/frontend/ts7/ast-wire.js.map +1 -1
  444. package/dist/frontend/ts7/ast.d.ts +2 -1
  445. package/dist/frontend/ts7/ast.js +8 -4
  446. package/dist/frontend/ts7/ast.js.map +1 -1
  447. package/dist/frontend/ts7/checker.d.ts +8 -2
  448. package/dist/frontend/ts7/checker.js +41 -5
  449. package/dist/frontend/ts7/checker.js.map +1 -1
  450. package/dist/frontend/ts7/checker.test.js +42 -0
  451. package/dist/frontend/ts7/checker.test.js.map +1 -1
  452. package/dist/frontend/ts7/program-host.d.ts +7 -0
  453. package/dist/frontend/ts7/program-host.js +26 -2
  454. package/dist/frontend/ts7/program-host.js.map +1 -1
  455. package/dist/frontend/ts7/program-host.test.js +29 -0
  456. package/dist/frontend/ts7/program-host.test.js.map +1 -1
  457. package/dist/frontend/type-mapper.d.ts +4 -1
  458. package/dist/frontend/type-mapper.js +133 -16
  459. package/dist/frontend/type-mapper.js.map +1 -1
  460. package/dist/frontend/type-mapper.test.js +15 -3
  461. package/dist/frontend/type-mapper.test.js.map +1 -1
  462. package/dist/frontend/worker-target.d.ts +6 -0
  463. package/dist/frontend/worker-target.js +108 -0
  464. package/dist/frontend/worker-target.js.map +1 -0
  465. package/dist/frontend/worker-target.test.d.ts +1 -0
  466. package/dist/frontend/worker-target.test.js +71 -0
  467. package/dist/frontend/worker-target.test.js.map +1 -0
  468. package/dist/index.js +47 -14
  469. package/dist/index.js.map +1 -1
  470. package/dist/ir/analysis.d.ts +3 -1
  471. package/dist/ir/analysis.js +4 -0
  472. package/dist/ir/analysis.js.map +1 -1
  473. package/dist/ir/builtin-effects.js +12 -0
  474. package/dist/ir/builtin-effects.js.map +1 -1
  475. package/dist/ir/builtin-signatures.d.ts +1 -1
  476. package/dist/ir/builtin-signatures.js +15 -15
  477. package/dist/ir/builtin-signatures.js.map +1 -1
  478. package/dist/ir/constant-tables.test.js +1 -1
  479. package/dist/ir/initializer-bindings.test.js +1 -1
  480. package/dist/ir/ir.d.ts +85 -23
  481. package/dist/ir/ir.js +20 -6
  482. package/dist/ir/ir.js.map +1 -1
  483. package/dist/ir/numeric-call-specialization.d.ts +8 -0
  484. package/dist/ir/numeric-call-specialization.js +198 -0
  485. package/dist/ir/numeric-call-specialization.js.map +1 -0
  486. package/dist/ir/runtime-features.js +4 -3
  487. package/dist/ir/runtime-features.js.map +1 -1
  488. package/dist/ir/scalar-records.test.js +1 -1
  489. package/dist/ir/serialize.d.ts +1 -1
  490. package/dist/ir/serialize.js +3 -3
  491. package/dist/ir/serialize.js.map +1 -1
  492. package/dist/ir/traverse.js +8 -0
  493. package/dist/ir/traverse.js.map +1 -1
  494. package/dist/ir/validate.js +207 -43
  495. package/dist/ir/validate.js.map +1 -1
  496. package/dist/ir/validate.test.js +356 -8
  497. package/dist/ir/validate.test.js.map +1 -1
  498. package/dist/library/fence-eval.test.js +1 -1
  499. package/dist/library/int-infer.test.js +4 -4
  500. package/dist/library/ir-policy.js +2 -0
  501. package/dist/library/ir-policy.js.map +1 -1
  502. package/dist/library/library-cache.test.js +5 -5
  503. package/dist/library/library-profile.d.ts +2 -1
  504. package/dist/library/library-profile.js +4 -3
  505. package/dist/library/library-profile.js.map +1 -1
  506. package/dist/native/compiler.js +24 -11
  507. package/dist/native/compiler.js.map +1 -1
  508. package/dist/native/compiler.test.js +7 -3
  509. package/dist/native/compiler.test.js.map +1 -1
  510. package/dist/native/library.d.ts +2 -1
  511. package/dist/native/library.js.map +1 -1
  512. package/dist/native/prepare.js +29 -3
  513. package/dist/native/prepare.js.map +1 -1
  514. package/dist/native/sanitizer.d.ts +3 -2
  515. package/dist/native/sanitizer.js +3 -13
  516. package/dist/native/sanitizer.js.map +1 -1
  517. package/dist/native/sanitizer.test.js +1 -0
  518. package/dist/native/sanitizer.test.js.map +1 -1
  519. package/package.json +20 -20
  520. package/surface-manifest.json +37 -3
@@ -1,4 +1,8 @@
1
- import { dynUndefinedExpr, nodeThrowExpr, countedFor, numLit, strLit, varRef, } from "../../ir/build.js";
1
+ import { generatorDrain } from "./iterator-adapters.js";
2
+ import { lowerUnionEquality, tagEqualityMayMissAlias } from "./strict-equality.js";
3
+ import { isOptionalProcessStreamProperty } from "./builtins/process.js";
4
+ import { lowerWorkerMetadata } from "./builtins/workers.js";
5
+ import { dynUndefinedExpr, nodeThrowExpr, numLit, strLit, varRef } from "../../ir/build.js";
2
6
  import { InternalCompilerError } from "../../errors.js";
3
7
  import { SYMBOL_T } from "../../ir/ir.js";
4
8
  import { literalValues } from "../literal-values.js";
@@ -10,8 +14,12 @@ import { literalUnionArm } from "../union-discriminants.js";
10
14
  * ToBoolean/ToString coercion helpers, and field/element reads and writes
11
15
  * (FieldTarget). */
12
16
  import * as ts from "../ts7/adapter.js";
17
+ import { constituentTypes } from "../ts7/checker.js";
13
18
  import { dirname } from "node:path";
14
19
  import * as posix from "node:path/posix";
20
+ import { checkedClassAssertion } from "./class-assertions.js";
21
+ import { narrowClassUnion, narrowStoredClassValue } from "./class-unions.js";
22
+ import { lowerUnionFieldWrite } from "./expressions/union-field-write.js";
15
23
  import { captureContextArguments } from "./function-context.js";
16
24
  import { OBJECT_CALLABLE_VALUES } from "./surfaces.js";
17
25
  import { wasiGuestPath } from "../../wasi-paths.js";
@@ -21,9 +29,8 @@ import { ARRAY_METHODS, builtinConstLit, builtinFenceHintOf, builtinModuleConstO
21
29
  import { UNSUPPORTED, blockedBindingUseDiag, requiresDynamicPackageDiag, unsupportedDiag, } from "../../diagnostics/diagnostic.js";
22
30
  import { PoisonError, dynFallbackType, jsFuncNameOf, neverTaintedJsType, own } from "./lowerer.js";
23
31
  import { lowerCollectionSpread } from "./containers/collection-methods.js";
24
- import { lowerNpmStaticSafeIndexRead, lowerSafeIndexRead, tryLowerNumericIndexRead, } from "./containers/array-methods.js";
32
+ import { arrayValueRead, arrayValueStore, arrayValueType, lowerSafeIndexRead, tryLowerIndexTruthiness, tryLowerNumericIndexRead, } from "./array-values.js";
25
33
  import { strCharsCall } from "./containers/array-construction.js";
26
- import { arrayValueRead, arrayValueStore, arrayValueType } from "./array-values.js";
27
34
  import { lowerOptionalStringIndex } from "./string-index.js";
28
35
  import { tryLowerIndexedComparison } from "./indexed-comparison.js";
29
36
  import { npmStaticPackageOfPath } from "../npm-static.js";
@@ -96,8 +103,8 @@ export function templateRawTextOf(node) {
96
103
  const LOWER_EXPR_MAX_DEPTH = 200;
97
104
  let lowerExprDepth = 0;
98
105
  /** True when a property access names an ABSTRACT property declaration
99
- * (`abstract p: number` — a PropertyDeclaration, not an accessor): the
100
- * named-fence test for reads/writes through abstract-typed receivers. */
106
+ * (`abstract p: number` — a PropertyDeclaration, not an accessor).
107
+ * These uses need concrete property dispatch because the base has no slot. */
101
108
  export function abstractPropertyDeclOf(lowerer, expr) {
102
109
  const sym = lowerer.checker.getSymbolAtLocation(expr.name);
103
110
  if (!sym)
@@ -159,7 +166,10 @@ export function lowerExpr(lowerer, expr) {
159
166
  }
160
167
  lowerExprDepth++;
161
168
  try {
162
- return lowerExprInner(lowerer, expr);
169
+ const lowered = lowerExprInner(lowerer, expr);
170
+ if (lowered.type.kind === "void" && (lowerer.typeOf(expr).flags & ts.TypeFlags.Never) !== 0)
171
+ lowerer.neverValued.add(lowered);
172
+ return lowered;
163
173
  }
164
174
  finally {
165
175
  lowerExprDepth--;
@@ -286,6 +296,11 @@ function lowerExprInner(lowerer, expr) {
286
296
  if (ts.isNonNullExpression(expr)) {
287
297
  const inner = lowerer.lowerExpr(expr.expression);
288
298
  if (inner.type.kind === "union") {
299
+ // `!` performs no runtime check: a missing array element stays
300
+ // undefined where its destination can hold it.
301
+ if (ts.isElementAccessExpression(expr.expression) &&
302
+ assertedElementKeepsUndefined(lowerer, expr))
303
+ return inner;
289
304
  const use = runtimeOptionalUseOf(expr);
290
305
  if (runtimeOptionalAssertionErases(lowerer, expr, inner, use))
291
306
  return inner;
@@ -1112,6 +1127,11 @@ function lowerExprInner(lowerer, expr) {
1112
1127
  {
1113
1128
  const bi = lowerer.builtinImportOf(expr);
1114
1129
  if (bi) {
1130
+ if (bi.module === "worker_threads") {
1131
+ const value = lowerWorkerMetadata(bi.member, loc);
1132
+ if (value)
1133
+ return value;
1134
+ }
1115
1135
  const c = builtinModuleConstOf(lowerer, bi.module, bi.member);
1116
1136
  if (c !== undefined)
1117
1137
  return builtinConstLit(c, loc);
@@ -1323,7 +1343,7 @@ function lowerExprInner(lowerer, expr) {
1323
1343
  Proxy: "Proxy constructor values have no native lowering; use a direct new Proxy with checked-native plain objects",
1324
1344
  Reflect: "reflective property access has no static lowering — read and call members directly",
1325
1345
  Intl: 'native Intl supports default Unicode grapheme segmentation and the composed new Intl.NumberFormat("en-US").format(x); locale negotiation and other ICU-backed operations remain unsupported',
1326
- SharedArrayBuffer: "no shared-memory threads exist in a compiled program — Uint8Array is the byte storage",
1346
+ SharedArrayBuffer: "use direct new SharedArrayBuffer(length) for fixed shared storage",
1327
1347
  ArrayBuffer: "ArrayBuffer constructor values have no native lowering; use new ArrayBuffer(length) for fixed-length shared storage",
1328
1348
  WeakRef: "deref()-after-collect exposes GC timing — genuinely dynamic; hold a strong reference instead",
1329
1349
  FinalizationRegistry: "finalization callbacks expose GC timing — genuinely dynamic; release resources explicitly instead",
@@ -3068,6 +3088,11 @@ export function maybeNarrow(lowerer, expr, node) {
3068
3088
  // same trust-the-checker contract as the union bridge below.
3069
3089
  if (expr.type.kind === "object") {
3070
3090
  const narrowed = lowerer.mapTypeOf(lowerer.typeOf(node));
3091
+ if (narrowed?.kind === "union") {
3092
+ const union = narrowClassUnion(lowerer, expr, narrowed);
3093
+ if (union)
3094
+ return union;
3095
+ }
3071
3096
  if (narrowed?.kind === "object" &&
3072
3097
  narrowed.className !== expr.type.className &&
3073
3098
  lowerer.isSubclassOf(narrowed.className, expr.type.className)) {
@@ -3077,6 +3102,8 @@ export function maybeNarrow(lowerer, expr, node) {
3077
3102
  }
3078
3103
  if (expr.type.kind !== "union")
3079
3104
  return expr;
3105
+ if (ts.isPropertyAccessExpression(node) && isOptionalProcessStreamProperty(lowerer, node))
3106
+ return expr;
3080
3107
  // Represented fields and index values can include undefined even when
3081
3108
  // checker inference or lib.d.ts declares strings (RegExp captures).
3082
3109
  // Only a declaration that represents the optional arm can provide a
@@ -3221,6 +3248,9 @@ function runtimeOptionalReceiverRead(lowerer, expr, local, property, loc) {
3221
3248
  lowerer.unsupported("SC1090", expr, "a runtime-optional capture whose narrowed value type is not representable");
3222
3249
  }
3223
3250
  if (narrowed.kind === "union") {
3251
+ const classView = narrowStoredClassValue(lowerer, varRef(local.id, local.type, loc), narrowed);
3252
+ if (classView)
3253
+ return classView;
3224
3254
  // The checker may keep the receiver at the storage union unchanged
3225
3255
  // (`string | undefined` on a JS `.match()` call). There is no
3226
3256
  // sub-union to re-tag: preserve the value for the downstream
@@ -3235,7 +3265,7 @@ function runtimeOptionalReceiverRead(lowerer, expr, local, property, loc) {
3235
3265
  // undefined arm; re-tag it to the checker-narrowed value union with a
3236
3266
  // checked trap for that arm, then let union property lowering inspect
3237
3267
  // the surviving record arms.
3238
- const helper = lowerer.narrowedRetagHelper(expr, local.type.unionId, narrowed.unionId, loc);
3268
+ const helper = lowerer.narrowedRetagHelper(narrowedNode, local.type.unionId, narrowed.unionId, loc);
3239
3269
  if (!helper) {
3240
3270
  lowerer.unsupported("SC1090", expr, "a runtime-optional capture whose narrowed union is not representable");
3241
3271
  }
@@ -3247,6 +3277,13 @@ function runtimeOptionalReceiverRead(lowerer, expr, local, property, loc) {
3247
3277
  loc,
3248
3278
  };
3249
3279
  }
3280
+ if (narrowed.kind === "object") {
3281
+ const view = checkedClassAssertion(lowerer, varRef(local.id, local.type, loc), narrowed, loc);
3282
+ // Preserve the member-specific missing-value error on the two-arm
3283
+ // path below; mixed storage also needs to validate its concrete class.
3284
+ if (view && (lowerer.unions.get(local.type.unionId)?.arms.length ?? 0) > 2)
3285
+ return view;
3286
+ }
3250
3287
  const undefTag = lowerer.armTag(local.type.unionId, UNDEFINED_T);
3251
3288
  const def = lowerer.unions.get(local.type.unionId);
3252
3289
  if (!def || undefTag < 0)
@@ -3401,6 +3438,45 @@ function runtimeOptionalElementKey(expr) {
3401
3438
  return expr.text;
3402
3439
  return null;
3403
3440
  }
3441
+ /** Whether `xs[i]!` lands where an absent element's undefined is
3442
+ * representable: array storage (a literal element, a push/unshift
3443
+ * argument, an element assignment — arrays record the undefined state),
3444
+ * an equality operand, or a slot whose contextual type admits undefined.
3445
+ * TypeScript's `!` has no runtime effect, so such reads stay optional. */
3446
+ function assertedElementKeepsUndefined(lowerer, node) {
3447
+ let outer = node;
3448
+ while (ts.isParenthesizedExpression(outer.parent))
3449
+ outer = outer.parent;
3450
+ const parent = outer.parent;
3451
+ if (ts.isArrayLiteralExpression(parent))
3452
+ return true;
3453
+ // An equality test observes the missing element itself.
3454
+ if (ts.isBinaryExpression(parent) &&
3455
+ (parent.operatorToken.kind === ts.SyntaxKind.EqualsEqualsEqualsToken ||
3456
+ parent.operatorToken.kind === ts.SyntaxKind.ExclamationEqualsEqualsToken ||
3457
+ parent.operatorToken.kind === ts.SyntaxKind.EqualsEqualsToken ||
3458
+ parent.operatorToken.kind === ts.SyntaxKind.ExclamationEqualsToken))
3459
+ return true;
3460
+ const isArray = (receiver) => lowerer.checker.isArrayType(lowerer.typeOf(receiver));
3461
+ if (ts.isCallExpression(parent) &&
3462
+ parent.arguments.includes(outer) &&
3463
+ ts.isPropertyAccessExpression(parent.expression) &&
3464
+ (parent.expression.name.text === "push" || parent.expression.name.text === "unshift") &&
3465
+ isArray(parent.expression.expression))
3466
+ return true;
3467
+ if (ts.isBinaryExpression(parent) &&
3468
+ parent.operatorToken.kind === ts.SyntaxKind.EqualsToken &&
3469
+ parent.right === outer &&
3470
+ ts.isElementAccessExpression(parent.left) &&
3471
+ isArray(parent.left.expression))
3472
+ return true;
3473
+ const contextual = lowerer.checker.getContextualType(outer);
3474
+ if (!contextual)
3475
+ return false;
3476
+ const admits = (type) => (type.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown | ts.TypeFlags.Undefined)) !== 0;
3477
+ return (admits(contextual) ||
3478
+ ((contextual.flags & ts.TypeFlags.Union) !== 0 && constituentTypes(contextual).some(admits)));
3479
+ }
3404
3480
  function runtimeOptionalAssertionErases(lowerer, expr, inner, use) {
3405
3481
  if (inner.type.kind !== "union" ||
3406
3482
  !use?.optional ||
@@ -3648,6 +3724,32 @@ export function lowerNullishCoalesce(lowerer, expr, loc) {
3648
3724
  }
3649
3725
  return result;
3650
3726
  }
3727
+ /** A plain value read that may be runtime-optional: an unchecked element
3728
+ * read, or a binding, member or call that carries one. Lowering these
3729
+ * without a destination type is the same as lowering them into one. */
3730
+ function isPlainValueRead(node) {
3731
+ while (ts.isParenthesizedExpression(node))
3732
+ node = node.expression;
3733
+ return (ts.isElementAccessExpression(node) ||
3734
+ ts.isIdentifier(node) ||
3735
+ ts.isPropertyAccessExpression(node) ||
3736
+ ts.isCallExpression(node));
3737
+ }
3738
+ /** A member access or call receiver needs the present value itself (JS
3739
+ * throws a TypeError reading a member of undefined). */
3740
+ function isMemberReceiver(node) {
3741
+ let child = node;
3742
+ let parent = node.parent;
3743
+ while (ts.isParenthesizedExpression(parent)) {
3744
+ child = parent;
3745
+ parent = parent.parent;
3746
+ }
3747
+ return (((ts.isPropertyAccessExpression(parent) ||
3748
+ ts.isElementAccessExpression(parent) ||
3749
+ ts.isCallExpression(parent)) &&
3750
+ parent.expression === child) ||
3751
+ (ts.isTaggedTemplateExpression(parent) && parent.tag === child));
3752
+ }
3651
3753
  function lowerNullishPair(lowerer, expr, loc, left) {
3652
3754
  if (left.type.kind === "dyn") {
3653
3755
  // `a ?? b` on a CHECKED-DYNAMIC left: the deciding test is the
@@ -3684,7 +3786,24 @@ function lowerNullishPair(lowerer, expr, loc, left) {
3684
3786
  const fresh = rest.length === 1 ? lowerer.emptyCollectionFor(expr.right, rest[0]) : null;
3685
3787
  if (fresh)
3686
3788
  return { kind: "nullish", left, right: fresh, type: fresh.type, loc };
3687
- const type = lowerer.irTypeOf(expr);
3789
+ let type = lowerer.irTypeOf(expr);
3790
+ // A runtime-optional read can reach the default even when declarations
3791
+ // call the left side present. Preserve a differently typed primitive
3792
+ // fallback rather than checking it against that incomplete result type.
3793
+ const rightType = lowerer.mapTypeOf(lowerer.typeOf(expr.right));
3794
+ const primitive = (t) => t.kind === "f64" || t.kind === "string" || t.kind === "bool";
3795
+ if (rightType &&
3796
+ primitive(type) &&
3797
+ primitive(rightType) &&
3798
+ !typeEquals(type, rightType) &&
3799
+ rest.every(primitive)) {
3800
+ const arms = [...rest];
3801
+ if (!arms.some((arm) => typeEquals(arm, rightType)))
3802
+ arms.push(rightType);
3803
+ arms.sort((a, b) => (typeKey(a) < typeKey(b) ? -1 : 1));
3804
+ type = { kind: "union", unionId: lowerer.unions.intern(arms) };
3805
+ lowerer.runtimeOptionalArithmeticTypes.set(expr, type);
3806
+ }
3688
3807
  if (type.kind === "dyn" && lowerer.dynConvertible(left.type)) {
3689
3808
  return {
3690
3809
  kind: "nullish",
@@ -3694,6 +3813,27 @@ function lowerNullishPair(lowerer, expr, loc, left) {
3694
3813
  loc,
3695
3814
  };
3696
3815
  }
3816
+ // A runtime-optional default (`name ?? names[0]`): the checker types an
3817
+ // unchecked element read as the bare element type, but an out-of-range
3818
+ // read is undefined at runtime. When the default shares the left's
3819
+ // optional union, that union is the result, so the undefined state
3820
+ // reaches the consumer (an optional return or parameter takes it as its
3821
+ // undefined arm; a plain slot still extracts the element with its
3822
+ // checked narrow).
3823
+ if (rest.length === 1 &&
3824
+ typeEquals(type, rest[0]) &&
3825
+ isPlainValueRead(expr.right) &&
3826
+ !isMemberReceiver(expr)) {
3827
+ const raw = lowerer.lowerExpr(expr.right);
3828
+ if (typeEquals(raw.type, left.type))
3829
+ return { kind: "nullish", left, right: raw, type: left.type, loc };
3830
+ // `names[0] ?? undefined`: an explicit unit default stays the left's arm.
3831
+ if (isUnitType(raw.type) && lowerer.armTag(left.type.unionId, raw.type) >= 0) {
3832
+ const right = lowerer.coerceInto(expr.right, raw, left.type);
3833
+ return { kind: "nullish", left, right, type: left.type, loc };
3834
+ }
3835
+ return { kind: "nullish", left, right: lowerer.coerceInto(expr.right, raw, type), type, loc };
3836
+ }
3697
3837
  if (typeEquals(type, left.type) || (rest.length === 1 && typeEquals(type, rest[0]))) {
3698
3838
  const right = lowerer.lowerExprExpecting(expr.right, type);
3699
3839
  return { kind: "nullish", left, right, type, loc };
@@ -3817,7 +3957,8 @@ export function lowerCondition(lowerer, expr) {
3817
3957
  };
3818
3958
  }
3819
3959
  }
3820
- return lowerer.ensureBool(lowerAbsenceProbe(lowerer, expr) ?? lowerer.lowerExpr(expr), expr);
3960
+ const value = lowerAbsenceProbe(lowerer, expr) ?? lowerer.lowerExpr(expr);
3961
+ return (tryLowerIndexTruthiness(lowerer, value, expr, locOf(expr)) ?? lowerer.ensureBool(value, expr));
3821
3962
  }
3822
3963
  function lowerPromiseThenPresence(lowerer, access, result) {
3823
3964
  if (access.name.text !== "then")
@@ -5024,6 +5165,13 @@ export function lowerArrayLiteral(lowerer, expr, expected) {
5024
5165
  loc: locOf(el),
5025
5166
  };
5026
5167
  }
5168
+ // `[...it]` over a generator (or an iterator adapted into one):
5169
+ // drain it once, in order, into a fresh element array.
5170
+ if (src.type.kind === "generator") {
5171
+ const drained = generatorDrain(lowerer, src, type.elem, locOf(el));
5172
+ if (drained)
5173
+ src = drained;
5174
+ }
5027
5175
  // A native checked iterable can supply scalar elements even when
5028
5176
  // the checker inferred a typed array from its producer. Drain once
5029
5177
  // and validate the elements before the ordinary spread copy.
@@ -5547,7 +5695,7 @@ export function lowerElementAccess(lowerer, expr) {
5547
5695
  // declared number type.
5548
5696
  if (recv.type.kind === "jsval")
5549
5697
  return islandElementRead(lowerer, expr, recv);
5550
- const index = lowerer.lowerExpr(expr.argumentExpression);
5698
+ const index = lowerOptionalNumber(lowerer, lowerer.lowerExpr(expr.argumentExpression), locOf(expr.argumentExpression), expr.argumentExpression);
5551
5699
  if (isJsSourceFile(expr.getSourceFile()) && recv.type.kind === "bytes") {
5552
5700
  return {
5553
5701
  kind: "dynKeyGet",
@@ -5804,36 +5952,12 @@ export function lowerElementAccess(lowerer, expr) {
5804
5952
  }
5805
5953
  }
5806
5954
  if (receiverIr?.kind === "string") {
5807
- // `s[i]` with a number index reads a UTF-16 code unit — charAt's
5808
- // exact job (the UTF-16-exact runtime). Without
5809
- // noUncheckedIndexedAccess the checker types the read `string`,
5810
- // and charAt's "" is the only string-typed answer for an
5811
- // out-of-range or fractional index where JS reads `undefined` —
5812
- // SEMANTICS.md documents the divergence; in-range integer reads
5813
- // (the loop pattern) are JS-exact. Optional results instead retain
5814
- // undefined for missing string properties.
5955
+ // An indexed string property is absent for non-integer and missing
5956
+ // indexes. charAt has different coercion and out-of-range semantics.
5815
5957
  const recv = lowerer.lowerExpr(expr.expression);
5816
- const index = lowerer.lowerExpr(expr.argumentExpression);
5817
- const resultType = lowerer.mapTypeOf(lowerer.typeOf(expr));
5958
+ const index = lowerOptionalNumber(lowerer, lowerer.lowerExpr(expr.argumentExpression), locOf(expr.argumentExpression), expr.argumentExpression);
5818
5959
  if (index.type.kind === "f64" && recv.type.kind === "string") {
5819
- if (resultType?.kind === "string") {
5820
- return {
5821
- kind: "strIntrinsic",
5822
- method: "charAt",
5823
- receiver: recv,
5824
- args: [index],
5825
- type: STRING,
5826
- loc: locOf(expr),
5827
- };
5828
- }
5829
- if (resultType?.kind === "union") {
5830
- const arms = lowerer.unions.get(resultType.unionId)?.arms;
5831
- if (arms?.length === 2 &&
5832
- lowerer.armTag(resultType.unionId, STRING) >= 0 &&
5833
- lowerer.armTag(resultType.unionId, UNDEFINED_T) >= 0) {
5834
- return lowerOptionalStringIndex(lowerer, recv, index, resultType, locOf(expr));
5835
- }
5836
- }
5960
+ return lowerOptionalStringIndex(lowerer, recv, index, lowerer.withUndefinedArm(STRING), locOf(expr));
5837
5961
  }
5838
5962
  lowerer.unsupported("SC1090", expr, "string indexing with this index/result shape (expected a number index and a string or string | undefined result)");
5839
5963
  }
@@ -5955,10 +6079,13 @@ export function lowerElementAccess(lowerer, expr) {
5955
6079
  // change the storage representation or the low-level getter itself.
5956
6080
  if (arr.type.kind === "array") {
5957
6081
  // A non-null assertion is the explicit proven-present form. Preserve
5958
- // the dense getter's established bounds trap here; turning `xs[i]!`
5959
- // into an optional union would change library ABI checks and the
5960
- // existing catchable RangeError contract for an out-of-bounds assert.
5961
- const provenPresent = ts.isNonNullExpression(expr.parent) && expr.parent.expression === expr;
6082
+ // the dense getter's established bounds trap where the asserted value
6083
+ // must be the element type (library ABI checks and the catchable
6084
+ // RangeError contract for an out-of-bounds assert). Where undefined is
6085
+ // representable, the assertion keeps JavaScript's unchecked read.
6086
+ const provenPresent = ts.isNonNullExpression(expr.parent) &&
6087
+ expr.parent.expression === expr &&
6088
+ !assertedElementKeepsUndefined(lowerer, expr.parent);
5962
6089
  if (provenPresent) {
5963
6090
  return lowerer.maybeNarrow({ kind: "arrayGet", arr, index, type: elemT, loc: locOf(expr) }, expr);
5964
6091
  }
@@ -5972,7 +6099,7 @@ export function lowerElementAccess(lowerer, expr) {
5972
6099
  arr.kind === "arrIntrinsic" &&
5973
6100
  arr.method === "slice" &&
5974
6101
  npmStaticPackageOfPath(expr.getSourceFile().fileName) !== null) {
5975
- const safe = lowerNpmStaticSafeIndexRead(lowerer, arr, index, locOf(expr));
6102
+ const safe = lowerSafeIndexRead(lowerer, arr, index, locOf(expr));
5976
6103
  if (safe)
5977
6104
  return safe;
5978
6105
  }
@@ -6218,6 +6345,10 @@ export function lowerAbsenceProbe(lowerer, node) {
6218
6345
  expr = expr.expression;
6219
6346
  }
6220
6347
  if (ts.isPropertyAccessExpression(expr)) {
6348
+ // Namespace members are bindings, not fields of a runtime namespace
6349
+ // object. Their ordinary read already preserves optional storage.
6350
+ if (!expr.questionDotToken && nsMemberIdentOf(lowerer, expr))
6351
+ return null;
6221
6352
  const target = lowerer.fieldTarget(expr);
6222
6353
  if (target?.container === "class" &&
6223
6354
  target.fieldType.kind === "union" &&
@@ -7180,6 +7311,19 @@ export function ensureString(lowerer, e, node) {
7180
7311
  return ensureString(lowerer, { kind: "call", callee: helper, args: [e], type: narrowed, loc: e.loc }, node);
7181
7312
  }
7182
7313
  }
7314
+ if (narrowed?.kind === "union" &&
7315
+ !typeEquals(narrowed, e.type) &&
7316
+ lowerer.unions
7317
+ .get(narrowed.unionId)
7318
+ ?.arms.every((arm) => isUnitType(arm) ||
7319
+ arm.kind === "string" ||
7320
+ arm.kind === "f64" ||
7321
+ arm.kind === "bool" ||
7322
+ arm.kind === "bigint")) {
7323
+ const helper = lowerer.narrowedRetagHelper(node, e.type.unionId, narrowed.unionId, e.loc);
7324
+ if (helper)
7325
+ return ensureString(lowerer, { kind: "call", callee: helper, args: [e], type: narrowed, loc: e.loc }, node);
7326
+ }
7183
7327
  lowerer.unsupported("SC1090", node, `string conversions of unions with object arms (${NARROW_FIRST})`);
7184
7328
  }
7185
7329
  if (e.type.kind === "symbol") {
@@ -7353,20 +7497,16 @@ export function lowerAsExpression(lowerer, expr) {
7353
7497
  };
7354
7498
  }
7355
7499
  }
7356
- // Narrowed reads (`err instanceof Error` proven) still pass below;
7357
- // other targets keep the narrowness fence with the checked-cast fix.
7358
- // In a JS FILE the AsExpression is tsgo's spelling of a JSDoc cast
7359
- // (`/** @type {T} */ (e)` — JS has no `as`); 5.9.3 parsed that as a
7360
- // plain parenthesized read, which lowered caught→dyn and met the
7361
- // target through the ordinary checked-cast coercion — so the dyn
7362
- // bridge stays open here exactly for that shape.
7500
+ // Structural assertions use the ordinary checked dynamic bridge. It
7501
+ // retains primitive values and native class identity before validating
7502
+ // the requested shape; an assertion does not bypass runtime checks.
7363
7503
  const narrowed = lowerer.mapTypeOf(lowerer.typeOf(expr.expression));
7364
7504
  const bridged = narrowed &&
7365
7505
  (narrowed.kind === "f64" ||
7366
7506
  narrowed.kind === "bool" ||
7367
7507
  narrowed.kind === "string" ||
7368
7508
  narrowed.kind === "object" ||
7369
- (narrowed.kind === "dyn" && isJsSourceFile(expr.getSourceFile())));
7509
+ narrowed.kind === "dyn");
7370
7510
  if (!bridged)
7371
7511
  lowerer.unsupported("SC1063", expr);
7372
7512
  }
@@ -7381,6 +7521,11 @@ export function lowerAsExpression(lowerer, expr) {
7381
7521
  return lowerer.jsvalIn(inner, expr.expression);
7382
7522
  }
7383
7523
  const target = lowerer.mapTypeOf(targetTs0);
7524
+ if (target?.kind === "object") {
7525
+ const asserted = checkedClassAssertion(lowerer, inner, target, locOf(expr));
7526
+ if (asserted)
7527
+ return asserted;
7528
+ }
7384
7529
  // Unknown-only record views use the checked-dynamic representation.
7385
7530
  // A native record asserted to such a view still denotes the original
7386
7531
  // object. Box a live reference instead of erasing the assertion and
@@ -7613,11 +7758,11 @@ export function lowerIncDec(lowerer, expr, prefix) {
7613
7758
  }
7614
7759
  fenceNodeModuleMutation(lowerer, access, "assignment");
7615
7760
  if (ts.isPropertyAccessExpression(access)) {
7616
- const target = staticFieldWriteTarget(lowerer, access);
7761
+ const target = staticFieldWriteTarget(lowerer, access) ??
7762
+ expandoWritableTarget(lowerer, access) ??
7763
+ nsWritableTarget(lowerer, access);
7617
7764
  if (target) {
7618
- if (target.type.kind !== "f64")
7619
- lowerer.unsupported("SC1043", expr);
7620
- return { kind: "incDec", op, prefix, localId: target.id, type: F64, loc };
7765
+ return lowerIncDecTarget(lowerer, expr, target, prefix);
7621
7766
  }
7622
7767
  }
7623
7768
  const stmts = [];
@@ -7729,10 +7874,18 @@ export function lowerIncDec(lowerer, expr, prefix) {
7729
7874
  if (!target) {
7730
7875
  lowerer.rejectUnresolved(expr.operand, `increment/decrement of '${expr.operand.text}' (not a writable local or module global)`);
7731
7876
  }
7877
+ return lowerIncDecTarget(lowerer, expr, target, prefix);
7878
+ }
7879
+ /** Numeric updates read the represented slot once and write the computed
7880
+ * value back in that same representation. In particular, an unchecked
7881
+ * indexed initializer can leave undefined in an otherwise numeric binding. */
7882
+ export function lowerIncDecTarget(lowerer, expr, target, prefix) {
7883
+ const loc = locOf(expr);
7884
+ const op = expr.operator === ts.SyntaxKind.PlusPlusToken ? "+" : "-";
7732
7885
  if (target.type.kind === "dyn") {
7733
7886
  const old = lowerer.declareHiddenLocal("%numericOld", DYN);
7734
7887
  const next = lowerer.declareHiddenLocal("%numericNext", DYN);
7735
- const read = lowerer.lowerExpr(expr.operand);
7888
+ const read = varRef(target.id, target.type, loc);
7736
7889
  return {
7737
7890
  kind: "seqExpr",
7738
7891
  stmts: [
@@ -7764,6 +7917,42 @@ export function lowerIncDec(lowerer, expr, prefix) {
7764
7917
  loc,
7765
7918
  };
7766
7919
  }
7920
+ if (target.type.kind === "union") {
7921
+ const read = lowerOptionalNumber(lowerer, varRef(target.id, target.type, loc), loc, expr.operand);
7922
+ if (read.type.kind === "f64") {
7923
+ const old = lowerer.declareHiddenLocal("%numericOld", F64);
7924
+ const next = lowerer.declareHiddenLocal("%numericNext", F64);
7925
+ const result = varRef(prefix ? next.id : old.id, F64, loc);
7926
+ return {
7927
+ kind: "seqExpr",
7928
+ stmts: [
7929
+ { kind: "varDecl", localId: old.id, init: read, loc },
7930
+ {
7931
+ kind: "varDecl",
7932
+ localId: next.id,
7933
+ init: {
7934
+ kind: "bin",
7935
+ op,
7936
+ left: varRef(old.id, F64, loc),
7937
+ right: numLit(1, loc),
7938
+ type: F64,
7939
+ loc,
7940
+ },
7941
+ loc,
7942
+ },
7943
+ {
7944
+ kind: "assign",
7945
+ localId: target.id,
7946
+ value: lowerer.coerceInto(expr.operand, varRef(next.id, F64, loc), target.type),
7947
+ loc,
7948
+ },
7949
+ ],
7950
+ result,
7951
+ type: F64,
7952
+ loc,
7953
+ };
7954
+ }
7955
+ }
7767
7956
  if (target.type.kind !== "f64")
7768
7957
  lowerer.unsupported("SC1043", expr);
7769
7958
  return { kind: "incDec", op, prefix, localId: target.id, type: F64, loc };
@@ -7858,14 +8047,18 @@ export function lowerCompoundValueToTarget(lowerer, expr, compound, target) {
7858
8047
  };
7859
8048
  return lowerer.coerceInto(expr, wrapped, target.type);
7860
8049
  }
7861
- if (compound === "+" && target.type.kind === "string") {
7862
- return {
8050
+ if (compound === "+" &&
8051
+ (target.type.kind === "string" ||
8052
+ (target.type.kind === "union" &&
8053
+ lowerer.stripUndefinedArm(target.type).kind === "string" &&
8054
+ rhs.type.kind === "string"))) {
8055
+ return lowerer.coerceInto(expr, {
7863
8056
  kind: "strConcat",
7864
- left: read,
8057
+ left: lowerer.ensureString(read, expr.left),
7865
8058
  right: lowerer.ensureString(rhs, expr.right),
7866
8059
  type: STRING,
7867
8060
  loc,
7868
- };
8061
+ }, target.type);
7869
8062
  }
7870
8063
  if (numericRead.type.kind === "f64" && numericRhs.type.kind === "f64") {
7871
8064
  return lowerer.coerceInto(expr, { kind: "bin", op: compound, left: numericRead, right: numericRhs, type: F64, loc }, target.type);
@@ -8120,6 +8313,9 @@ export function lowerBinary(lowerer, expr) {
8120
8313
  const recv = tryLowerExpression(lowerer, expr.left.expression);
8121
8314
  if (recv && recv.type.kind === "dyn")
8122
8315
  return lowerDynMemberAssignment(lowerer, expr, recv);
8316
+ const unionWrite = lowerUnionFieldWrite(lowerer, expr.left, expr.right);
8317
+ if (unionWrite)
8318
+ return unionWrite;
8123
8319
  const field = lowerer.fieldTarget(expr.left);
8124
8320
  if (field) {
8125
8321
  const recvTmp = lowerer.declareHiddenLocal("%setReceiver", field.obj.type);
@@ -8705,7 +8901,7 @@ export function lowerBinary(lowerer, expr) {
8705
8901
  const optionalStringPlus = lowerOptionalStringPlus();
8706
8902
  if (optionalStringPlus)
8707
8903
  return optionalStringPlus;
8708
- if (isJsSourceFile(expr.getSourceFile())) {
8904
+ {
8709
8905
  const primitive = (type) => type.kind === "f64" ||
8710
8906
  type.kind === "string" ||
8711
8907
  type.kind === "bool" ||
@@ -8811,6 +9007,13 @@ export function lowerBinary(lowerer, expr) {
8811
9007
  if (unitTest)
8812
9008
  return unitTest;
8813
9009
  if (left.type.kind === "union" || right.type.kind === "union") {
9010
+ const compared = lowerUnionEquality(lowerer, left, right, negated, false, loc);
9011
+ if (compared)
9012
+ return compared;
9013
+ const aliasRefusal = (type) => {
9014
+ if (tagEqualityMayMissAlias(lowerer, type))
9015
+ lowerer.unsupported("SC1090", expr, `comparisons of related class values beside structural union members (${NARROW_FIRST})`);
9016
+ };
8814
9017
  // JS strict equality of the ARM values, per union tag (a
8815
9018
  // per-union helper): equal tags compare payloads (f64 ==, string
8816
9019
  // bytes, bool ==, ref-arm POINTER identity), different tags are
@@ -8846,6 +9049,7 @@ export function lowerBinary(lowerer, expr) {
8846
9049
  };
8847
9050
  }
8848
9051
  if ((sameUnion || !bothUnion) && lowerer.eqComparableUnion(ut.unionId)) {
9052
+ aliasRefusal(ut);
8849
9053
  return {
8850
9054
  kind: "unionEq",
8851
9055
  unionId: ut.unionId,
@@ -8876,6 +9080,7 @@ export function lowerBinary(lowerer, expr) {
8876
9080
  kind: "union",
8877
9081
  unionId: lowerer.unions.intern(arms),
8878
9082
  };
9083
+ aliasRefusal(common);
8879
9084
  return {
8880
9085
  kind: "unionEq",
8881
9086
  unionId: common.unionId,
@@ -10021,17 +10226,30 @@ export function caughtRead(lowerer, node, local, loc) {
10021
10226
  }
10022
10227
  if (narrowed?.kind === "object") {
10023
10228
  const info = lowerer.classes.get(narrowed.className);
10024
- if (info && lowerer.inHierarchy(info)) {
10025
- return { kind: "caughtNarrow", value: ref, type: narrowed, loc };
10229
+ if (info) {
10230
+ const value = { kind: "caughtNarrow", value: ref, type: narrowed, loc };
10231
+ if (lowerer.inHierarchy(info))
10232
+ return value;
10233
+ return {
10234
+ kind: "ternary",
10235
+ cond: {
10236
+ kind: "caughtTest",
10237
+ value: ref,
10238
+ test: "instanceof",
10239
+ className: info.def.name,
10240
+ type: BOOL,
10241
+ loc,
10242
+ },
10243
+ then: value,
10244
+ else_: lowerer.coerceInto(node, { kind: "caughtToDyn", value: ref, type: DYN, loc }, narrowed),
10245
+ type: narrowed,
10246
+ loc,
10247
+ };
10026
10248
  }
10027
10249
  }
10028
- // An UN-narrowed use — the occurrence still types `unknown` — converts
10029
- // to a dyn value (`options.onError?.(error)` — the caught snapshot
10030
- // flowing into an unknown slot): the typed→unknown deep-copy stance
10031
- // extended to exception payloads. Error payloads keep their
10032
- // observability (instanceof Error / .message / String() — the checked-dynamic tree's
10033
- // error encoding); other object payloads are type-erased at runtime and
10034
- // convert to the "[object Object]" approximation — SEMANTICS.md 67.
10250
+ // Unnarrowed reads cross into unknown. The caught-value dispatch pass
10251
+ // retains known native class payloads through live identity capsules;
10252
+ // other payload kinds use the runtime's ordinary conversion.
10035
10253
  if (narrowed?.kind === "dyn") {
10036
10254
  return { kind: "caughtToDyn", value: ref, type: DYN, loc };
10037
10255
  }
@@ -10097,6 +10315,38 @@ export function lowerInstanceOf(lowerer, expr, loc) {
10097
10315
  (lowerer.isStdlibGlobal(expr.right, "Set") || lowerer.isStdlibGlobal(expr.right, "Map"))) {
10098
10316
  const collection = lowerer.isStdlibGlobal(expr.right, "Map") ? "map" : "set";
10099
10317
  const value = lowerer.lowerExpr(expr.left);
10318
+ if (value.type.kind === "union") {
10319
+ const union = lowerer.unions.get(value.type.unionId);
10320
+ if (union) {
10321
+ const local = lowerer.declareHiddenLocal("%collectionTest", value.type);
10322
+ const reference = varRef(local.id, value.type, loc);
10323
+ let result = { kind: "boolLit", value: false, type: BOOL, loc };
10324
+ union.arms.forEach((arm, tag) => {
10325
+ if (arm.kind !== collection)
10326
+ return;
10327
+ const test = {
10328
+ kind: "unionIsTag",
10329
+ unionId: union.id,
10330
+ value: reference,
10331
+ tag,
10332
+ negated: false,
10333
+ type: BOOL,
10334
+ loc,
10335
+ };
10336
+ result =
10337
+ result.kind === "boolLit"
10338
+ ? test
10339
+ : { kind: "logical", op: "||", left: result, right: test, type: BOOL, loc };
10340
+ });
10341
+ return {
10342
+ kind: "seqExpr",
10343
+ stmts: [{ kind: "varDecl", localId: local.id, init: value, loc }],
10344
+ result,
10345
+ type: BOOL,
10346
+ loc,
10347
+ };
10348
+ }
10349
+ }
10100
10350
  if (value.type.kind === "dyn")
10101
10351
  return {
10102
10352
  kind: "libCall",
@@ -10158,6 +10408,10 @@ export function lowerInstanceOf(lowerer, expr, loc) {
10158
10408
  const value = lowerer.coerceInto(expr.left, lowerer.lowerExpr(expr.left), DYN);
10159
10409
  return { kind: "libCall", fn: "dyn.dataViewIs", args: [value], type: BOOL, loc };
10160
10410
  }
10411
+ if (lowerer.isStdlibGlobal(expr.right, "SharedArrayBuffer")) {
10412
+ const value = lowerer.coerceInto(expr.left, lowerer.lowerExpr(expr.left), DYN);
10413
+ return { kind: "libCall", fn: "sharedArrayBuffer.is", args: [value], type: BOOL, loc };
10414
+ }
10161
10415
  if (lowerer.isStdlibGlobal(expr.right, "ArrayBuffer")) {
10162
10416
  const value = lowerer.coerceInto(expr.left, lowerer.lowerExpr(expr.left), DYN);
10163
10417
  return { kind: "libCall", fn: "arrayBuffer.is", args: [value], type: BOOL, loc };
@@ -10370,8 +10624,22 @@ export function lowerInstanceOf(lowerer, expr, loc) {
10370
10624
  const caughtLocal = lowerer.caughtLocalOf(expr.left);
10371
10625
  if (caughtLocal) {
10372
10626
  if (!lowerer.inHierarchy(target)) {
10373
- lowerer.unsupported("SC1090", expr, `'instanceof' on a catch binding against the standalone class '${target.def.name}' ` +
10374
- `(only classes in extends hierarchies carry the vtable the payload test needs)`);
10627
+ const value = varRef(caughtLocal.id, CAUGHT, loc);
10628
+ return {
10629
+ kind: "ternary",
10630
+ cond: {
10631
+ kind: "caughtTest",
10632
+ value,
10633
+ test: "instanceof",
10634
+ className: target.def.name,
10635
+ type: BOOL,
10636
+ loc,
10637
+ },
10638
+ then: { kind: "boolLit", value: true, type: BOOL, loc },
10639
+ else_: classInstanceOf(lowerer, { kind: "caughtToDyn", value, type: DYN, loc }, target, loc),
10640
+ type: BOOL,
10641
+ loc,
10642
+ };
10375
10643
  }
10376
10644
  return {
10377
10645
  kind: "caughtTest",
@@ -10669,11 +10937,10 @@ function lowerPrivateIn(lowerer, expr, priv, loc) {
10669
10937
  * type-directed: a declared non-optional field is a compile-time `true`,
10670
10938
  * a missing field (no index signature) a compile-time `false` — both
10671
10939
  * folds limited to side-effect-free receivers, the lowerInstanceOf rule —
10672
- * and an OPTIONAL field (undefined-armed union) is a runtime tag test on
10673
- * the slot: present iff the arm is not undefined. That last case is the
10674
- * representation's honest answer — a field explicitly assigned
10675
- * `undefined` reads as absent (`"a" in {a: undefined}` is true in JS,
10676
- * false here; SEMANTICS.md 55). Union receivers (the `in`-narrowing
10940
+ * and an OPTIONAL field (undefined-armed union) is a runtime presence
10941
+ * test on the slot: an omitted or deleted property is absent, while a
10942
+ * property explicitly holding `undefined` is present, as in JS
10943
+ * (`"a" in {a: undefined}` is true). Union receivers (the `in`-narrowing
10677
10944
  * idiom over multiple shapes), index-signature keys, class instances,
10678
10945
  * and dyn/unknown stay fenced. Keys are literal strings — a computed key
10679
10946
  * over a shape would need the runtime key table. */
@@ -10717,13 +10984,42 @@ function lowerInExpression(lowerer, expr, loc) {
10717
10984
  }
10718
10985
  }
10719
10986
  }
10987
+ // A RUNTIME numeric key over an ARRAY receiver (`if (i in arr)` in a
10988
+ // loop) asks the same slot/property presence query as the literal fold
10989
+ // above and `Object.hasOwn`. The checked-dynamic fallback below would
10990
+ // box the receiver and materialize every element on each evaluation,
10991
+ // which makes such loops quadratic. A Number key never names an
10992
+ // inherited property: neither Array.prototype nor Object.prototype has
10993
+ // index-like or numeric-string keys. JS evaluates the key before the
10994
+ // receiver, so the key is stabilized in a hidden local first.
10995
+ if (lowerer.mapTypeOf(lowerer.typeOf(expr.left))?.kind === "f64" &&
10996
+ lowerer.mapTypeOf(lowerer.typeOf(expr.right))?.kind === "array") {
10997
+ const k = lowerer.lowerExpr(expr.left);
10998
+ const recvArr = lowerer.lowerExpr(expr.right);
10999
+ if (k.type.kind === "f64" && recvArr.type.kind === "array") {
11000
+ const keyLocal = lowerer.declareHiddenLocal("%inIndex", F64);
11001
+ return {
11002
+ kind: "seqExpr",
11003
+ stmts: [{ kind: "varDecl", localId: keyLocal.id, init: k, loc }],
11004
+ result: {
11005
+ kind: "arrayHas",
11006
+ arr: recvArr,
11007
+ index: varRef(keyLocal.id, F64, loc),
11008
+ type: BOOL,
11009
+ loc,
11010
+ },
11011
+ type: BOOL,
11012
+ loc,
11013
+ };
11014
+ }
11015
+ }
10720
11016
  const key = foldedStringKeyOf(lowerer, expr.left);
10721
11017
  if (key === null) {
10722
11018
  // A RUNTIME string key over an INDEX-SIGNATURE record receiver (the
10723
11019
  // `names.filter((k) => k in config)` idiom): the interned key-
10724
11020
  // presence helper — declared fields answer statically per name
10725
- // (optional slots per value: the undefined arm reads absent, stance
10726
- // 55), then the overflow map's live keys. Other receivers keep the
11021
+ // (optional slots by their runtime presence), then the overflow
11022
+ // map's live keys. Other receivers keep the
10727
11023
  // fence: fixed shapes want the literal folds above, and there is no
10728
11024
  // runtime key table to ask.
10729
11025
  const rIn = lowerRuntimeKeyIn(lowerer, expr, loc);
@@ -10966,24 +11262,9 @@ function lowerInExpression(lowerer, expr, loc) {
10966
11262
  const field = shape.fields.find((f) => f.name === key);
10967
11263
  if (field) {
10968
11264
  if (field.type.kind === "union" && lowerer.armTag(field.type.unionId, UNDEFINED_T) >= 0) {
10969
- // Optional slot: the key is present iff the arm is not undefined.
10970
- const read = {
10971
- kind: "recordGet",
10972
- obj: recv,
10973
- shapeId: recv.type.shapeId,
10974
- field: key,
10975
- type: field.type,
10976
- loc,
10977
- };
10978
- return {
10979
- kind: "unionIsTag",
10980
- unionId: field.type.unionId,
10981
- tag: lowerer.armTag(field.type.unionId, UNDEFINED_T),
10982
- negated: true,
10983
- value: read,
10984
- type: BOOL,
10985
- loc,
10986
- };
11265
+ // Optional slot: the key is present unless the field is absent
11266
+ // (omitted or deleted); an explicit undefined is present.
11267
+ return lowerer.recordFieldPresent(recv, recv.type.shapeId, key, loc);
10987
11268
  }
10988
11269
  // A declared non-optional field always exists on every value of the
10989
11270
  // shape — statically true, but folding may only drop a
@@ -11023,9 +11304,9 @@ function lowerInExpression(lowerer, expr, loc) {
11023
11304
  * runtime string and r an index-signature record — an interned
11024
11305
  * `%rec.haskey.<n>(k, r)` walks the declared names (a string-equality
11025
11306
  * chain: non-optional fields and accessor slots answer true, optional
11026
- * slots answer their per-value tag test) and then the overflow map's
11027
- * live keys. Null when the pair is outside that shape (the caller keeps
11028
- * its fence). */
11307
+ * slots answer their per-value tag test) and then probes the overflow
11308
+ * map's hashed key set. Null when the pair is outside that shape (the
11309
+ * caller keeps its fence). */
11029
11310
  function lowerRuntimeKeyIn(lowerer, expr, loc) {
11030
11311
  if (lowerer.mapTypeOf(lowerer.typeOf(expr.left))?.kind !== "string")
11031
11312
  return null;
@@ -11060,62 +11341,15 @@ function lowerRuntimeKeyIn(lowerer, expr, loc) {
11060
11341
  type: BOOL,
11061
11342
  loc,
11062
11343
  };
11063
- const utag = !accessor && f.type.kind === "union" ? lowerer.armTag(f.type.unionId, UNDEFINED_T) : -1;
11064
- const answer = utag >= 0 && f.type.kind === "union"
11065
- ? {
11066
- kind: "unionIsTag",
11067
- unionId: f.type.unionId,
11068
- tag: utag,
11069
- negated: true,
11070
- value: {
11071
- kind: "recordGet",
11072
- obj: r,
11073
- shapeId: recvT.shapeId,
11074
- field: f.name,
11075
- type: f.type,
11076
- loc,
11077
- },
11078
- type: BOOL,
11079
- loc,
11080
- }
11081
- : { kind: "boolLit", value: true, type: BOOL, loc };
11344
+ const answer = accessor
11345
+ ? { kind: "boolLit", value: true, type: BOOL, loc }
11346
+ : lowerer.recordFieldPresent(r, recvT.shapeId, f.name, loc);
11082
11347
  body.push({ kind: "if", cond: eq, then: [ret(answer)], else_: null, loc });
11083
11348
  }
11084
- const ksT = arrayOf(STRING);
11085
- body.push({
11086
- kind: "varDecl",
11087
- localId: "ks.0",
11088
- init: { kind: "recordOvfKeys", obj: r, shapeId: recvT.shapeId, type: ksT, loc },
11089
- loc,
11090
- }, countedFor(loc, {
11091
- kind: "arrIntrinsic",
11092
- method: "length",
11093
- receiver: varRef("ks.0", ksT, loc),
11094
- args: [],
11095
- type: F64,
11096
- loc,
11097
- }, () => [
11098
- {
11099
- kind: "if",
11100
- cond: {
11101
- kind: "strEq",
11102
- negated: false,
11103
- left: k,
11104
- right: {
11105
- kind: "arrayGet",
11106
- arr: varRef("ks.0", ksT, loc),
11107
- index: varRef("i.0", F64, loc),
11108
- type: STRING,
11109
- loc,
11110
- },
11111
- type: BOOL,
11112
- loc,
11113
- },
11114
- then: [ret({ kind: "boolLit", value: true, type: BOOL, loc })],
11115
- else_: null,
11116
- loc,
11117
- },
11118
- ]), ret({ kind: "boolLit", value: false, type: BOOL, loc }));
11349
+ // Overflow keys answer through the map's hashed presence probe (a
11350
+ // stored undefined value is still present), not a scan over a fresh
11351
+ // key snapshot, which made `k in dict` loops quadratic.
11352
+ body.push(ret({ kind: "recordOvfHas", obj: r, shapeId: recvT.shapeId, key: k, type: BOOL, loc }));
11119
11353
  lowerer.liftedFns.push({
11120
11354
  name: helper,
11121
11355
  params: [
@@ -11126,8 +11360,6 @@ function lowerRuntimeKeyIn(lowerer, expr, loc) {
11126
11360
  locals: [
11127
11361
  { id: "k.0", name: "k", type: STRING, mutable: true },
11128
11362
  { id: "r.0", name: "r", type: recT, mutable: true },
11129
- { id: "ks.0", name: "ks", type: ksT, mutable: false },
11130
- { id: "i.0", name: "i", type: F64, mutable: true },
11131
11363
  ],
11132
11364
  body,
11133
11365
  loc,
@@ -11815,7 +12047,7 @@ export function lowerUnionProperty(lowerer, expr) {
11815
12047
  return null;
11816
12048
  }
11817
12049
  if (value.type.kind !== "union") {
11818
- throw new InternalCompilerError("lowerer bug: union-typed receiver lowered to a non-union");
12050
+ lowerer.unsupported("SC1090", expr, "shared property access without a represented union receiver");
11819
12051
  }
11820
12052
  const def = lowerer.unions.get(value.type.unionId);
11821
12053
  if (!def)
@@ -12192,11 +12424,32 @@ export function fieldTarget(lowerer, access) {
12192
12424
  const stored = ts.isIdentifier(access.expression)
12193
12425
  ? (lowerer.peekLocal(access.expression)?.type ?? lowerer.globalOf(access.expression)?.type)
12194
12426
  : undefined;
12195
- const receiverIr = stored?.kind === "record" || stored?.kind === "object"
12427
+ const narrowed = lowerer.mapTypeOf(lowerer.typeOf(access.expression));
12428
+ // Structural record views retain their storage layout, while a nominal
12429
+ // subclass guard proves a more specific layout of the same object.
12430
+ const receiverIr = stored?.kind === "record"
12196
12431
  ? stored
12197
- : lowerer.mapTypeOf(lowerer.typeOf(access.expression));
12432
+ : stored?.kind === "object" &&
12433
+ !(narrowed?.kind === "object" &&
12434
+ lowerer.isSubclassOf(narrowed.className, stored.className))
12435
+ ? stored
12436
+ : narrowed;
12198
12437
  if (receiverIr?.kind === "object") {
12199
- return classFieldTarget(lowerer, access.expression, receiverIr, access.name.text);
12438
+ const target = classFieldTarget(lowerer, access.expression, receiverIr, access.name.text);
12439
+ if (target)
12440
+ return target;
12441
+ // Abstract properties declare no base storage. Resolve the concrete
12442
+ // instance's live field or accessor through the existing class bridge;
12443
+ // inventing a shared field offset would misread subclass layouts.
12444
+ if (abstractPropertyDeclOf(lowerer, access)) {
12445
+ return {
12446
+ container: "dynamic",
12447
+ obj: lowerer.coerceInto(access.expression, lowerer.lowerExpr(access.expression), DYN),
12448
+ field: access.name.text,
12449
+ fieldType: lowerer.irTypeOf(access),
12450
+ };
12451
+ }
12452
+ return null;
12200
12453
  }
12201
12454
  if (receiverIr?.kind === "union" && hasClassPayload(lowerer, receiverIr)) {
12202
12455
  return representedClassFieldTarget(lowerer, access.expression, access.name.text, lowerer.lowerExpr(access.expression));
@@ -12437,13 +12690,13 @@ function symbolFieldTarget(lowerer, expr) {
12437
12690
  * undefined, which these property types cannot represent. */
12438
12691
  export function fieldGetExpr(lowerer, target, loc, blame) {
12439
12692
  if (target.container === "dynamic")
12440
- return {
12693
+ return lowerer.coerceInto(blame, {
12441
12694
  kind: "dynKeyGet",
12442
12695
  value: target.obj,
12443
12696
  key: { kind: "strLit", value: target.field, type: STRING, loc },
12444
12697
  type: DYN,
12445
12698
  loc,
12446
- };
12699
+ }, target.fieldType);
12447
12700
  if (target.container === "class" &&
12448
12701
  (target.field === "message" || target.field === "name") &&
12449
12702
  (target.className === "%Error" || lowerer.isSubclassOf(target.className, "%Error")))
@@ -12904,7 +13157,8 @@ function lowerFieldCompoundValue(lowerer, access, op, rhsNode, loc) {
12904
13157
  ? { kind: "dynCheck", value: rhs, type: F64, loc: rhs.loc }
12905
13158
  : lowerOptionalNumber(lowerer, rhs, loc);
12906
13159
  let value;
12907
- if (op === "+" && target.fieldType.kind === "string") {
13160
+ const numericRead = lowerOptionalNumber(lowerer, read, loc, access);
13161
+ if (op === "+" && read.type.kind === "string") {
12908
13162
  value = {
12909
13163
  kind: "strConcat",
12910
13164
  left: read,
@@ -12913,8 +13167,8 @@ function lowerFieldCompoundValue(lowerer, access, op, rhsNode, loc) {
12913
13167
  loc,
12914
13168
  };
12915
13169
  }
12916
- else if (target.fieldType.kind === "f64" && numericRhs.type.kind === "f64") {
12917
- value = { kind: "bin", op, left: read, right: numericRhs, type: F64, loc };
13170
+ else if (numericRead.type.kind === "f64" && numericRhs.type.kind === "f64") {
13171
+ value = { kind: "bin", op, left: numericRead, right: numericRhs, type: F64, loc };
12918
13172
  }
12919
13173
  else if (target.fieldType.kind === "dyn" && isJsSourceFile(access.getSourceFile())) {
12920
13174
  const numeric = ["-", "*", "/", "%", "**"].includes(op);
@@ -12934,7 +13188,7 @@ function lowerFieldCompoundValue(lowerer, access, op, rhsNode, loc) {
12934
13188
  lowerer.unsupported("SC1043", access);
12935
13189
  }
12936
13190
  const result = save(value, "%compoundResult");
12937
- body.push(lowerer.fieldSetStmt(target, result, loc, access));
13191
+ body.push(lowerer.fieldSetStmt(target, lowerer.coerceInto(access, result, target.fieldType), loc, access));
12938
13192
  return { kind: "seqExpr", stmts: body, result, type: result.type, loc };
12939
13193
  }
12940
13194
  /** Stream-rooted receivers' property surface (readableEnded, destroyed,