@scriptc/compiler 0.2.1 → 0.2.3

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 (315) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +158 -31
  2. package/dist/backend/cycle-analysis.js +63 -50
  3. package/dist/backend/cycle-analysis.js.map +1 -1
  4. package/dist/backend/cycle-analysis.test.js +51 -0
  5. package/dist/backend/cycle-analysis.test.js.map +1 -1
  6. package/dist/backend/llvm/borrowed-receivers.d.ts +9 -0
  7. package/dist/backend/llvm/borrowed-receivers.js +58 -0
  8. package/dist/backend/llvm/borrowed-receivers.js.map +1 -0
  9. package/dist/backend/llvm/call-lifetimes.d.ts +20 -0
  10. package/dist/backend/llvm/call-lifetimes.js +179 -0
  11. package/dist/backend/llvm/call-lifetimes.js.map +1 -0
  12. package/dist/backend/llvm/call-lifetimes.test.d.ts +1 -0
  13. package/dist/backend/llvm/call-lifetimes.test.js +205 -0
  14. package/dist/backend/llvm/call-lifetimes.test.js.map +1 -0
  15. package/dist/backend/llvm/dyn.d.ts +5 -2
  16. package/dist/backend/llvm/dyn.js +163 -47
  17. package/dist/backend/llvm/dyn.js.map +1 -1
  18. package/dist/backend/llvm/emitter.d.ts +37 -1
  19. package/dist/backend/llvm/emitter.js +209 -21
  20. package/dist/backend/llvm/emitter.js.map +1 -1
  21. package/dist/backend/llvm/emitter.test.js +29 -2
  22. package/dist/backend/llvm/emitter.test.js.map +1 -1
  23. package/dist/backend/llvm/expr-async.js +1 -1
  24. package/dist/backend/llvm/expr-async.js.map +1 -1
  25. package/dist/backend/llvm/expr-calls.js +42 -5
  26. package/dist/backend/llvm/expr-calls.js.map +1 -1
  27. package/dist/backend/llvm/expr-containers.js +75 -13
  28. package/dist/backend/llvm/expr-containers.js.map +1 -1
  29. package/dist/backend/llvm/expr-dynamic.js +31 -6
  30. package/dist/backend/llvm/expr-dynamic.js.map +1 -1
  31. package/dist/backend/llvm/expr-primitives.js +6 -5
  32. package/dist/backend/llvm/expr-primitives.js.map +1 -1
  33. package/dist/backend/llvm/expr-records.js +1 -1
  34. package/dist/backend/llvm/expr-records.js.map +1 -1
  35. package/dist/backend/llvm/expr-stream-bridges.js +75 -19
  36. package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
  37. package/dist/backend/llvm/expr-stream-callbacks.d.ts +2 -2
  38. package/dist/backend/llvm/expr-stream-callbacks.js +7 -57
  39. package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
  40. package/dist/backend/llvm/lib-dispatch.js +41 -3
  41. package/dist/backend/llvm/lib-dispatch.js.map +1 -1
  42. package/dist/backend/llvm/lib-filesystem.js +12 -9
  43. package/dist/backend/llvm/lib-filesystem.js.map +1 -1
  44. package/dist/backend/llvm/lib-shared.js +70 -2
  45. package/dist/backend/llvm/lib-shared.js.map +1 -1
  46. package/dist/backend/llvm/local-array-reads.d.ts +44 -0
  47. package/dist/backend/llvm/local-array-reads.js +313 -0
  48. package/dist/backend/llvm/local-array-reads.js.map +1 -0
  49. package/dist/backend/llvm/local-array-reads.test.d.ts +1 -0
  50. package/dist/backend/llvm/local-array-reads.test.js +446 -0
  51. package/dist/backend/llvm/local-array-reads.test.js.map +1 -0
  52. package/dist/backend/llvm/map-read-lifetimes.d.ts +36 -0
  53. package/dist/backend/llvm/map-read-lifetimes.js +128 -0
  54. package/dist/backend/llvm/map-read-lifetimes.js.map +1 -0
  55. package/dist/backend/llvm/map-read-lifetimes.test.d.ts +1 -0
  56. package/dist/backend/llvm/map-read-lifetimes.test.js +123 -0
  57. package/dist/backend/llvm/map-read-lifetimes.test.js.map +1 -0
  58. package/dist/backend/llvm/shapes.js +1 -0
  59. package/dist/backend/llvm/shapes.js.map +1 -1
  60. package/dist/backend/llvm/split.js +15 -5
  61. package/dist/backend/llvm/split.js.map +1 -1
  62. package/dist/backend/llvm/split.test.js +17 -0
  63. package/dist/backend/llvm/split.test.js.map +1 -1
  64. package/dist/backend/llvm/stack-unions.d.ts +20 -0
  65. package/dist/backend/llvm/stack-unions.js +61 -0
  66. package/dist/backend/llvm/stack-unions.js.map +1 -0
  67. package/dist/backend/llvm/stack-unions.test.d.ts +1 -0
  68. package/dist/backend/llvm/stack-unions.test.js +241 -0
  69. package/dist/backend/llvm/stack-unions.test.js.map +1 -0
  70. package/dist/backend/llvm/string-lifetimes.d.ts +12 -0
  71. package/dist/backend/llvm/string-lifetimes.js +70 -0
  72. package/dist/backend/llvm/string-lifetimes.js.map +1 -0
  73. package/dist/backend/llvm/string-lifetimes.test.d.ts +1 -0
  74. package/dist/backend/llvm/string-lifetimes.test.js +230 -0
  75. package/dist/backend/llvm/string-lifetimes.test.js.map +1 -0
  76. package/dist/backend/mangle.d.ts +2 -0
  77. package/dist/backend/mangle.js +4 -0
  78. package/dist/backend/mangle.js.map +1 -1
  79. package/dist/backend/may-throw.js +71 -29
  80. package/dist/backend/may-throw.js.map +1 -1
  81. package/dist/backend/may-throw.test.js +104 -1
  82. package/dist/backend/may-throw.test.js.map +1 -1
  83. package/dist/backend/native-codegen.d.ts +1 -1
  84. package/dist/backend/native-codegen.js +4 -3
  85. package/dist/backend/native-codegen.js.map +1 -1
  86. package/dist/backend/native-codegen.test.js +11 -0
  87. package/dist/backend/native-codegen.test.js.map +1 -1
  88. package/dist/backend/native-toolchain.d.ts +2 -2
  89. package/dist/backend/native-toolchain.js +2 -0
  90. package/dist/backend/native-toolchain.js.map +1 -1
  91. package/dist/backend/target-diagnostics.d.ts +5 -0
  92. package/dist/backend/target-diagnostics.js +72 -1
  93. package/dist/backend/target-diagnostics.js.map +1 -1
  94. package/dist/backend/target-diagnostics.test.d.ts +1 -0
  95. package/dist/backend/target-diagnostics.test.js +68 -0
  96. package/dist/backend/target-diagnostics.test.js.map +1 -0
  97. package/dist/coverage/surface-manifest.js +5 -3
  98. package/dist/coverage/surface-manifest.js.map +1 -1
  99. package/dist/executable/executable-cache.d.ts +7 -3
  100. package/dist/executable/executable-cache.js +47 -11
  101. package/dist/executable/executable-cache.js.map +1 -1
  102. package/dist/executable/executable-cache.test.js +109 -2
  103. package/dist/executable/executable-cache.test.js.map +1 -1
  104. package/dist/executable/prepare.js +2 -1
  105. package/dist/executable/prepare.js.map +1 -1
  106. package/dist/frontend/builtin-modules.d.ts +1 -1
  107. package/dist/frontend/builtin-modules.js +1 -1
  108. package/dist/frontend/builtin-modules.js.map +1 -1
  109. package/dist/frontend/function-completion.d.ts +6 -0
  110. package/dist/frontend/function-completion.js +50 -0
  111. package/dist/frontend/function-completion.js.map +1 -0
  112. package/dist/frontend/input-tracker.js +3 -3
  113. package/dist/frontend/input-tracker.js.map +1 -1
  114. package/dist/frontend/input-tracker.test.js +38 -2
  115. package/dist/frontend/input-tracker.test.js.map +1 -1
  116. package/dist/frontend/lowering/abstract-equality.js +5 -1
  117. package/dist/frontend/lowering/abstract-equality.js.map +1 -1
  118. package/dist/frontend/lowering/checked-iterable-spread.d.ts +4 -0
  119. package/dist/frontend/lowering/checked-iterable-spread.js +30 -0
  120. package/dist/frontend/lowering/checked-iterable-spread.js.map +1 -0
  121. package/dist/frontend/lowering/checked-promise-all.d.ts +5 -0
  122. package/dist/frontend/lowering/checked-promise-all.js +31 -0
  123. package/dist/frontend/lowering/checked-promise-all.js.map +1 -0
  124. package/dist/frontend/lowering/class-callbacks.d.ts +1 -1
  125. package/dist/frontend/lowering/class-callbacks.js +7 -6
  126. package/dist/frontend/lowering/class-callbacks.js.map +1 -1
  127. package/dist/frontend/lowering/class-construction.d.ts +2 -0
  128. package/dist/frontend/lowering/class-construction.js +34 -5
  129. package/dist/frontend/lowering/class-construction.js.map +1 -1
  130. package/dist/frontend/lowering/class-descriptors.d.ts +1 -1
  131. package/dist/frontend/lowering/class-descriptors.js +12 -5
  132. package/dist/frontend/lowering/class-descriptors.js.map +1 -1
  133. package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +25 -0
  134. package/dist/frontend/lowering/class-dynamic-dispatch.js +597 -78
  135. package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
  136. package/dist/frontend/lowering/class-dynamic-dispatch.test.js +64 -2
  137. package/dist/frontend/lowering/class-dynamic-dispatch.test.js.map +1 -1
  138. package/dist/frontend/lowering/class-instance-constructor.d.ts +1 -1
  139. package/dist/frontend/lowering/class-instance-constructor.js +11 -41
  140. package/dist/frontend/lowering/class-instance-constructor.js.map +1 -1
  141. package/dist/frontend/lowering/class-method-values.d.ts +16 -0
  142. package/dist/frontend/lowering/class-method-values.js +60 -29
  143. package/dist/frontend/lowering/class-method-values.js.map +1 -1
  144. package/dist/frontend/lowering/class-prototypes.d.ts +5 -1
  145. package/dist/frontend/lowering/class-prototypes.js +69 -10
  146. package/dist/frontend/lowering/class-prototypes.js.map +1 -1
  147. package/dist/frontend/lowering/class-runtime-statics.d.ts +4 -4
  148. package/dist/frontend/lowering/class-runtime-statics.js +26 -8
  149. package/dist/frontend/lowering/class-runtime-statics.js.map +1 -1
  150. package/dist/frontend/lowering/class-static-data.d.ts +1 -0
  151. package/dist/frontend/lowering/class-static-data.js +4 -2
  152. package/dist/frontend/lowering/class-static-data.js.map +1 -1
  153. package/dist/frontend/lowering/collection-ingestion.d.ts +31 -0
  154. package/dist/frontend/lowering/collection-ingestion.js +215 -0
  155. package/dist/frontend/lowering/collection-ingestion.js.map +1 -0
  156. package/dist/frontend/lowering/containers/bytes.js +19 -4
  157. package/dist/frontend/lowering/containers/bytes.js.map +1 -1
  158. package/dist/frontend/lowering/containers/string-and-regexp.js +6 -1
  159. package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
  160. package/dist/frontend/lowering/deferred-module-initializers.d.ts +13 -0
  161. package/dist/frontend/lowering/deferred-module-initializers.js +410 -0
  162. package/dist/frontend/lowering/deferred-module-initializers.js.map +1 -0
  163. package/dist/frontend/lowering/deferred-module-initializers.test.d.ts +1 -0
  164. package/dist/frontend/lowering/deferred-module-initializers.test.js +92 -0
  165. package/dist/frontend/lowering/deferred-module-initializers.test.js.map +1 -0
  166. package/dist/frontend/lowering/expressions/object-literals.js +31 -1
  167. package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
  168. package/dist/frontend/lowering/expressions/optional-chains.js +3 -3
  169. package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
  170. package/dist/frontend/lowering/import-meta.d.ts +10 -0
  171. package/dist/frontend/lowering/import-meta.js +52 -0
  172. package/dist/frontend/lowering/import-meta.js.map +1 -0
  173. package/dist/frontend/lowering/lower-assert.js +105 -41
  174. package/dist/frontend/lowering/lower-assert.js.map +1 -1
  175. package/dist/frontend/lowering/lower-builtin-values.d.ts +2 -0
  176. package/dist/frontend/lowering/lower-builtin-values.js +22 -1
  177. package/dist/frontend/lowering/lower-builtin-values.js.map +1 -1
  178. package/dist/frontend/lowering/lower-builtins.d.ts +7 -22
  179. package/dist/frontend/lowering/lower-builtins.js +439 -95
  180. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  181. package/dist/frontend/lowering/lower-calls.js +289 -76
  182. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  183. package/dist/frontend/lowering/lower-classes.d.ts +5 -0
  184. package/dist/frontend/lowering/lower-classes.js +443 -29
  185. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  186. package/dist/frontend/lowering/lower-containers.d.ts +6 -2
  187. package/dist/frontend/lowering/lower-containers.js +79 -20
  188. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  189. package/dist/frontend/lowering/lower-exprs.d.ts +10 -6
  190. package/dist/frontend/lowering/lower-exprs.js +329 -170
  191. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  192. package/dist/frontend/lowering/lower-generators.js +5 -1
  193. package/dist/frontend/lowering/lower-generators.js.map +1 -1
  194. package/dist/frontend/lowering/lower-inspect.js +58 -1
  195. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  196. package/dist/frontend/lowering/lower-island.js +4 -0
  197. package/dist/frontend/lowering/lower-island.js.map +1 -1
  198. package/dist/frontend/lowering/lower-island.test.d.ts +1 -0
  199. package/dist/frontend/lowering/lower-island.test.js +51 -0
  200. package/dist/frontend/lowering/lower-island.test.js.map +1 -0
  201. package/dist/frontend/lowering/lower-modules.d.ts +1 -3
  202. package/dist/frontend/lowering/lower-modules.js +186 -82
  203. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  204. package/dist/frontend/lowering/lower-modules.test.js +69 -1
  205. package/dist/frontend/lowering/lower-modules.test.js.map +1 -1
  206. package/dist/frontend/lowering/lower-stmts.js +172 -103
  207. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  208. package/dist/frontend/lowering/lower-stmts.test.d.ts +1 -0
  209. package/dist/frontend/lowering/lower-stmts.test.js +77 -0
  210. package/dist/frontend/lowering/lower-stmts.test.js.map +1 -0
  211. package/dist/frontend/lowering/lower-stream.js +2 -0
  212. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  213. package/dist/frontend/lowering/lower-system-errors.d.ts +6 -0
  214. package/dist/frontend/lowering/lower-system-errors.js +29 -0
  215. package/dist/frontend/lowering/lower-system-errors.js.map +1 -0
  216. package/dist/frontend/lowering/lower-url.d.ts +2 -1
  217. package/dist/frontend/lowering/lower-url.js +32 -9
  218. package/dist/frontend/lowering/lower-url.js.map +1 -1
  219. package/dist/frontend/lowering/lowerer.d.ts +30 -12
  220. package/dist/frontend/lowering/lowerer.js +268 -49
  221. package/dist/frontend/lowering/lowerer.js.map +1 -1
  222. package/dist/frontend/lowering/lowerer.test.js +38 -0
  223. package/dist/frontend/lowering/lowerer.test.js.map +1 -1
  224. package/dist/frontend/lowering/module-namespace-elements.d.ts +7 -0
  225. package/dist/frontend/lowering/module-namespace-elements.js +54 -0
  226. package/dist/frontend/lowering/module-namespace-elements.js.map +1 -0
  227. package/dist/frontend/lowering/object-factory-new.d.ts +4 -3
  228. package/dist/frontend/lowering/object-factory-new.js +27 -14
  229. package/dist/frontend/lowering/object-factory-new.js.map +1 -1
  230. package/dist/frontend/lowering/surfaces.d.ts +3 -2
  231. package/dist/frontend/lowering/surfaces.js +93 -33
  232. package/dist/frontend/lowering/surfaces.js.map +1 -1
  233. package/dist/frontend/lowering/text-decoder-encoding.js +3 -0
  234. package/dist/frontend/lowering/text-decoder-encoding.js.map +1 -1
  235. package/dist/frontend/lowering/text-decoder-encoding.test.js +2 -1
  236. package/dist/frontend/lowering/text-decoder-encoding.test.js.map +1 -1
  237. package/dist/frontend/module-syntax.d.ts +1 -1
  238. package/dist/frontend/module-syntax.js +8 -1
  239. package/dist/frontend/module-syntax.js.map +1 -1
  240. package/dist/frontend/module-syntax.test.js +10 -0
  241. package/dist/frontend/module-syntax.test.js.map +1 -1
  242. package/dist/frontend/npm.d.ts +4 -0
  243. package/dist/frontend/npm.js +86 -33
  244. package/dist/frontend/npm.js.map +1 -1
  245. package/dist/frontend/npm.test.js +103 -0
  246. package/dist/frontend/npm.test.js.map +1 -1
  247. package/dist/frontend/pipeline-native.js +2 -1
  248. package/dist/frontend/pipeline-native.js.map +1 -1
  249. package/dist/frontend/program.js +4 -2
  250. package/dist/frontend/program.js.map +1 -1
  251. package/dist/frontend/services-node.js +3 -2
  252. package/dist/frontend/services-node.js.map +1 -1
  253. package/dist/frontend/services.d.ts +5 -1
  254. package/dist/frontend/services.js +9 -1
  255. package/dist/frontend/services.js.map +1 -1
  256. package/dist/frontend/services.test.js +21 -0
  257. package/dist/frontend/services.test.js.map +1 -1
  258. package/dist/frontend/ts7/ast-node.d.ts +2 -0
  259. package/dist/frontend/ts7/ast-node.js +30 -4
  260. package/dist/frontend/ts7/ast-node.js.map +1 -1
  261. package/dist/frontend/ts7/ast-node.test.js +60 -1
  262. package/dist/frontend/ts7/ast-node.test.js.map +1 -1
  263. package/dist/frontend/type-mapper.js +89 -14
  264. package/dist/frontend/type-mapper.js.map +1 -1
  265. package/dist/frontend/union-discriminants.js +22 -7
  266. package/dist/frontend/union-discriminants.js.map +1 -1
  267. package/dist/index.js +19 -12
  268. package/dist/index.js.map +1 -1
  269. package/dist/ir/analysis.js +1 -0
  270. package/dist/ir/analysis.js.map +1 -1
  271. package/dist/ir/integer-loops.d.ts +7 -0
  272. package/dist/ir/integer-loops.js +23 -0
  273. package/dist/ir/integer-loops.js.map +1 -1
  274. package/dist/ir/integer-loops.test.d.ts +1 -0
  275. package/dist/ir/integer-loops.test.js +41 -0
  276. package/dist/ir/integer-loops.test.js.map +1 -0
  277. package/dist/ir/ir.d.ts +44 -26
  278. package/dist/ir/ir.js +69 -11
  279. package/dist/ir/ir.js.map +1 -1
  280. package/dist/ir/ir.test.js +18 -0
  281. package/dist/ir/ir.test.js.map +1 -1
  282. package/dist/ir/serialize.js +21 -1
  283. package/dist/ir/serialize.js.map +1 -1
  284. package/dist/ir/serialize.test.js +21 -0
  285. package/dist/ir/serialize.test.js.map +1 -1
  286. package/dist/ir/traverse.d.ts +0 -3
  287. package/dist/ir/traverse.js +33 -20
  288. package/dist/ir/traverse.js.map +1 -1
  289. package/dist/ir/validate.js +216 -80
  290. package/dist/ir/validate.js.map +1 -1
  291. package/dist/ir/validate.test.js +244 -1
  292. package/dist/ir/validate.test.js.map +1 -1
  293. package/dist/library/compiler-self-identity.js +1 -1
  294. package/dist/library/compiler-self-identity.test.js +2 -2
  295. package/dist/library/compiler-self-identity.test.js.map +1 -1
  296. package/dist/library/fence-eval.js +9 -2
  297. package/dist/library/fence-eval.js.map +1 -1
  298. package/dist/library/fence-eval.test.d.ts +1 -0
  299. package/dist/library/fence-eval.test.js +21 -0
  300. package/dist/library/fence-eval.test.js.map +1 -0
  301. package/dist/library/int-infer.d.ts +2 -2
  302. package/dist/library/int-infer.js +10 -7
  303. package/dist/library/int-infer.js.map +1 -1
  304. package/dist/library/int-infer.test.js +44 -0
  305. package/dist/library/int-infer.test.js.map +1 -1
  306. package/dist/library/prepare.js +2 -1
  307. package/dist/library/prepare.js.map +1 -1
  308. package/dist/native/runtime-typescript.d.ts +4 -0
  309. package/dist/native/runtime-typescript.js +61 -0
  310. package/dist/native/runtime-typescript.js.map +1 -0
  311. package/dist/native/runtime-typescript.test.d.ts +1 -0
  312. package/dist/native/runtime-typescript.test.js +41 -0
  313. package/dist/native/runtime-typescript.test.js.map +1 -0
  314. package/package.json +20 -20
  315. package/surface-manifest.json +385 -29
@@ -1,4 +1,5 @@
1
1
  import { lowerDynObjectLiteral } from "./expressions/object-literals.js";
2
+ import { importMetaBindingSource } from "./import-meta.js";
2
3
  import { InternalCompilerError } from "../../errors.js";
3
4
  /* Statement lowering: the statement dispatch (lowerStmt), variable
4
5
  * declarations including destructuring patterns, scoped blocks, control
@@ -19,20 +20,19 @@ import { isProvenanceSourceFile } from "../provenance-registry.js";
19
20
  import { ambientUndefVarRootOf, lowerImportEquals, nsUndefRead, nsWritableTarget, trapDeclRootOf } from "./lower-namespaces.js";
20
21
  import { expandoWritableTarget, lowerExpandoAssignStmt } from "./lower-expando.js";
21
22
  import { lowerForOfArrayIter, lowerForOfMap, lowerForOfSearchParams, lowerForOfSet, lowerSafeIndexRead, objectIterOverIndexShape, strCharsCall } from "./lower-containers.js";
22
- import { bindingContextualGenericFnNodeOf, bindingGenericFnAliasInfoOf, bindingGenericFnInfoOf, bindingGenericFnNodeOf, bindingNeverReassigned, deadUnmappableBinding, implicitLocalFnInfoOf, implicitLocalFnNodeOf, implicitMethodCallInfersReturn, nullishExprUnitOf, nullishGenericBindingUnitOf, recordKeysArrayCall, registerOverloadedCallableAlias } from "./lower-calls.js";
23
+ import { bindingContextualGenericFnNodeOf, bindingGenericFnAliasInfoOf, bindingGenericFnInfoOf, bindingGenericFnNodeOf, bindingNeverReassigned, deadUnmappableBinding, hasExplicitJsDocReturn, implicitLocalFnInfoOf, implicitLocalFnNodeOf, implicitMethodCallInfersReturn, nullishExprUnitOf, nullishGenericBindingUnitOf, recordKeysArrayCall, registerOverloadedCallableAlias } from "./lower-calls.js";
23
24
  import { isMixinFnBinding, mixinResultBindingClassOf } from "./lower-mixins.js";
24
25
  import { isCompiledPrototypeMember } from "./class-prototypes.js";
25
26
  import { classStaticDataFor } from "./class-static-data.js";
26
27
  import { objectFactorySignature } from "./object-factory-new.js";
27
28
  import { isClassCallback, lowerClassCallbackAssign } from "./class-callbacks.js";
28
- import { classPropertiesHelper } from "./class-dynamic-dispatch.js";
29
+ import { classForInHasKey, classPropertiesHelper } from "./class-dynamic-dispatch.js";
29
30
  import { genericIfaceBindingKeepsClass, staticFieldWriteTarget } from "./lower-classes.js";
30
31
  import { lowerStreamUnderscoreAssign, streamClassAliasDecl } from "./lower-stream.js";
31
32
  import { lowerHttpResPropertyAssignment, lowerHttpServerTimeoutAssignment, lowerServerCloseOverrideAssignment } from "./lower-server.js";
32
- import { isNativeFfiRequire, builtinMemberRequireDecl, builtinNamespaceDestructureModuleOf, createRequireBindingDecl, createRequireCalleeFileOf, createRequireNamespaceDecl, createRequireProgramModuleDecl, createRequireProgramModuleOf, lowerNodeModuleCall, registerBuiltinCallableAlias } from "./lower-builtins.js";
33
+ import { lowerUrlAssignment, isNativeFfiRequire, builtinMemberRequireDecl, builtinNamespaceDestructureModuleOf, createRequireBindingDecl, createRequireCalleeFileOf, createRequireNamespaceDecl, createRequireProgramModuleDecl, createRequireProgramModuleOf, lowerNodeModuleCall, registerBuiltinCallableAlias } from "./lower-builtins.js";
33
34
  import { lowerEnumDeclaration } from "./lower-enums.js";
34
- import { abstractPropertyDeclOf, aliasTypeofNarrows, isMatchSliceType, lowerAbsenceProbe, lowerCompoundValueToTarget, lowerElementCompound, lowerGroupsProjection, matchResultNamedGroupsOf, runtimeOptionalGuardIds, runtimeOptionalTrueIds, symbolFieldInfo, withRuntimeOptionalNarrowed } from "./lower-exprs.js";
35
- import { isSafeToRepeat } from "./expressions/evaluation-safety.js";
35
+ import { abstractPropertyDeclOf, aliasTypeofNarrows, isMatchSliceType, lowerAbsenceProbe, lowerCompoundValueToTarget, lowerElementCompound, lowerIncDec, lowerGroupsProjection, matchResultNamedGroupsOf, runtimeOptionalGuardIds, runtimeOptionalTrueIds, symbolFieldInfo, withRuntimeOptionalNarrowed } from "./lower-exprs.js";
36
36
  import { globalSymbolKey } from "./expressions/global-symbols.js";
37
37
  import { lowerShortCircuitAssignment } from "./expressions/nullish-assignment.js";
38
38
  import { lowerEnvironmentKey, lowerNativeFunctionAssignment } from "./lower-exprs.js";
@@ -71,6 +71,8 @@ function npmStaticReturnedEmptyArrayType(lowerer, decl) {
71
71
  const ownerBody = owner !== undefined && ts.isFunctionLike(owner) ? owner.body : undefined;
72
72
  if (ownerBody === undefined || !ts.isBlock(ownerBody))
73
73
  return null;
74
+ if (owner && ts.isFunctionLike(owner) && !owner.type && !hasExplicitJsDocReturn(owner))
75
+ return null;
74
76
  let returned = false;
75
77
  ts.walkPreorder(ownerBody, (node) => {
76
78
  if (node !== ownerBody && ts.isFunctionLike(node))
@@ -593,7 +595,12 @@ export function predeclareForwardCapture(lowerer, symbol) {
593
595
  // TDZ read until the initializing assign completes — JS exactly.
594
596
  if (idx < entry.index || entry.ctx === lowerer.ctx || entry.ctx.tdzPredeclared.has(symbol))
595
597
  return false;
596
- const type = lowerer.irTypeOf(decl.name);
598
+ let type = lowerer.irTypeOf(decl.name);
599
+ if (isJsSourceFile(decl.getSourceFile()) && !decl.type && !hasJsTypeAnnotation(decl) &&
600
+ (ts.isObjectLiteralExpression(decl.initializer) ||
601
+ (ts.isCallExpression(decl.initializer) && ts.isPropertyAccessExpression(decl.initializer.expression) &&
602
+ decl.initializer.expression.name.text === "assign" && lowerer.isStdlibGlobal(decl.initializer.expression.expression, "Object"))) && lowerer.dynConvertible(type))
603
+ type = DYN;
597
604
  if (!TDZ_KINDS.has(type.kind) || isUnitType(type))
598
605
  return false;
599
606
  const name = decl.name.text;
@@ -1035,12 +1042,9 @@ export function lowerStmt(lowerer, stmt) {
1035
1042
  // (JS), which the undefined arm carries — tsc only allows the bare
1036
1043
  // form when the return type includes undefined/void. A CHECKED-
1037
1044
  // DYNAMIC return slot holds the dyn undefined directly (the
1038
- // appendImplicitUndefinedReturn rule). What remains is JS-only —
1039
- // a JSDoc return claim the body contradicts (ms's parse: `@return
1040
- // {Number}` with a bare early `return;`): no undefined fits the
1041
- // declared representation, so the statement fences honestly (the
1042
- // per-statement JS deferral — the claimed paths still run) instead
1043
- // of slipping an empty return past the validator.
1045
+ // appendImplicitUndefinedReturn rule). JavaScript signatures include
1046
+ // observed empty returns even when JSDoc omits undefined. Any remaining
1047
+ // incompatible boundary keeps the ordinary per-statement refusal.
1044
1048
  let value = null;
1045
1049
  if (stmt.expression) {
1046
1050
  return lowerer.lowerReturnStmt(stmt.expression, locOf(stmt));
@@ -1092,9 +1096,18 @@ export function lowerStmt(lowerer, stmt) {
1092
1096
  // cell. `throw f()` of a void call has no value; Date has numeric
1093
1097
  // storage internally, but cannot preserve its object kind through the
1094
1098
  // untyped catch boundary. Reject both rather than changing JS identity.
1095
- const value = lowerer.lowerExpr(stmt.expression);
1099
+ let value = lowerer.lowerExpr(stmt.expression);
1096
1100
  if (value.type.kind === "void")
1097
1101
  lowerer.badType(stmt.expression, lowerer.typeOf(stmt.expression));
1102
+ // Preserve primitive reasons and readable record identity across the
1103
+ // untyped catch boundary. Unit literals have no standalone native
1104
+ // value, and native reference payloads otherwise lose their shape.
1105
+ if (isUnitType(value.type) || value.type.kind === "symbol" || value.type.kind === "bigint") {
1106
+ value = lowerer.coerceToExpected(value, DYN);
1107
+ }
1108
+ else if (value.type.kind === "record" && lowerer.dynConvertible(value.type)) {
1109
+ value = { kind: "dynFrom", value, liveRef: true, type: DYN, loc: locOf(stmt.expression) };
1110
+ }
1098
1111
  if (value.type.kind === "date") {
1099
1112
  lowerer.unsupported("SC1090", stmt.expression, "throwing Date values (catch bindings cannot preserve Date's object kind; throw an Error or primitive instead)");
1100
1113
  }
@@ -1424,7 +1437,7 @@ export function lowerDestructuringDecl(lowerer, decl, isLet) {
1424
1437
  if (tokenBound !== null)
1425
1438
  return tokenBound;
1426
1439
  }
1427
- let init = lowerer.lowerExpr(decl.initializer);
1440
+ let init = importMetaBindingSource(lowerer, decl.name, decl.initializer) ?? lowerer.lowerExpr(decl.initializer);
1428
1441
  const parseArgsDynObject = init.type.kind === "dyn" && isParseArgsDynCheckerType(lowerer, lowerer.typeOf(decl.initializer));
1429
1442
  // A TS `any`-origin source whose lowered value is NOT a destructurable
1430
1443
  // shape (`var { x } = <any>0` — the cast erases to the f64; a dyn
@@ -1885,6 +1898,10 @@ export function lowerBindingPattern(lowerer, pattern, srcRef, srcType, isLet, ou
1885
1898
  // scoped TypeScript exception: its declared result/token types are
1886
1899
  // deliberately carried by the checked-dynamic tree, so their ordinary
1887
1900
  // object patterns use the same exact keyed-read desugar.
1901
+ if (srcType.kind === "union" && isJsSourceFile(pattern.getSourceFile()) && lowerer.dynConvertible(srcType)) {
1902
+ lowerer.lowerBindingPattern(pattern, () => lowerer.coerceToExpected(srcRef(), DYN), DYN, isLet, out, dynSpell, allowDynObject);
1903
+ return;
1904
+ }
1888
1905
  if (srcType.kind === "dyn") {
1889
1906
  for (const el of pattern.elements) {
1890
1907
  if (el.name === undefined)
@@ -3323,7 +3340,7 @@ function inferredEvolvingLetType(lowerer, decl) {
3323
3340
  invalid = true;
3324
3341
  return "stop";
3325
3342
  }
3326
- if (ts.isCallExpression(node.right) && implicitMethodCallInfersReturn(lowerer, node.right)) {
3343
+ if (ts.isCallExpression(node.right) && (implicitMethodCallInfersReturn(lowerer, node.right) || isJsSourceFile(node.right.getSourceFile()))) {
3327
3344
  invalid = true;
3328
3345
  return "stop";
3329
3346
  }
@@ -3545,7 +3562,8 @@ export function lowerVarDecl(lowerer, decl, isLet) {
3545
3562
  : (declSymbol ? lowerer.globalsBySymbol.get(declSymbol) : undefined);
3546
3563
  if (g) {
3547
3564
  let promotedGlobal = lowerer.runtimeOptionalBindingType(decl.name, g.type);
3548
- if (g.type.kind === "func" && decl.initializer !== undefined && ts.isIdentifier(decl.initializer)) {
3565
+ if (g.type.kind === "func" && !decl.type && !hasJsTypeAnnotation(decl) &&
3566
+ decl.initializer !== undefined && ts.isIdentifier(decl.initializer)) {
3549
3567
  const sig = lowerer.fnSigOf(decl.initializer);
3550
3568
  if (sig) {
3551
3569
  promotedGlobal = {
@@ -3579,6 +3597,10 @@ export function lowerVarDecl(lowerer, decl, isLet) {
3579
3597
  }
3580
3598
  const raw = lowerVariableInitializer(lowerer, decl.initializer, g.type.kind === "dyn" && (isNativeBuiltinValueInitializer(lowerer, decl.initializer) ||
3581
3599
  ts.isArrayLiteralExpression(decl.initializer) || ts.isObjectLiteralExpression(decl.initializer)) ? DYN : undefined);
3600
+ if (isJsSourceFile(decl.getSourceFile()) && !decl.type && !hasJsTypeAnnotation(decl) && raw.type.kind === "dyn" &&
3601
+ (g.type.kind === "record" || g.type.kind === "object"))
3602
+ g.type = DYN;
3603
+ g.type = inferredOptionalRecordType(lowerer, decl, g.type, raw.type);
3582
3604
  const arithmetic = raw.type.kind === "union"
3583
3605
  ? lowerer.unions.get(raw.type.unionId)?.arms
3584
3606
  : undefined;
@@ -3651,7 +3673,10 @@ export function lowerVarDecl(lowerer, decl, isLet) {
3651
3673
  ? lowerer.unions.get(inferredObjectType.unionId)?.arms ?? [] : inferredObjectType ? [inferredObjectType] : [];
3652
3674
  const expandsObject = !decl.type && !hasJsTypeAnnotation(decl) && inferredObjectType !== null &&
3653
3675
  jsOpenObjectType(decl, inferredObjectType, lowerer.shapes, lowerer.unions).kind === "dyn" ||
3654
- inferredObjectArms.some((arm) => arm.kind === "record" && jsObjectBindingExpands(lowerer, decl, arm));
3676
+ inferredObjectArms.some((arm) => arm.kind === "record" && jsObjectBindingExpands(lowerer, decl, arm)) ||
3677
+ isJsSourceFile(decl.getSourceFile()) && !decl.type && !hasJsTypeAnnotation(decl) &&
3678
+ ts.isObjectLiteralExpression(decl.initializer) && decl.initializer.properties.some((property) => ts.isMethodDeclaration(property) || ts.isAccessor(property) || ts.isPropertyAssignment(property) &&
3679
+ (ts.isFunctionExpression(property.initializer) || ts.isArrowFunction(property.initializer)));
3655
3680
  let init;
3656
3681
  try {
3657
3682
  init = expandsObject || (isJsSourceFile(decl.getSourceFile()) && !decl.type &&
@@ -3806,6 +3831,8 @@ export function lowerVarDecl(lowerer, decl, isLet) {
3806
3831
  type = init.type;
3807
3832
  runtimeOptional = true;
3808
3833
  }
3834
+ if (type !== null)
3835
+ type = inferredOptionalRecordType(lowerer, decl, type, init.type);
3809
3836
  // A JS binding whose checker type spells a FUNCTION but whose VALUE is
3810
3837
  // already checked-dynamic (`const cb = mustCall(fn)` — the helper's
3811
3838
  // return rides its own box): keep the box. Extracting into the spelled
@@ -3817,6 +3844,9 @@ export function lowerVarDecl(lowerer, decl, isLet) {
3817
3844
  !decl.type && !hasJsTypeAnnotation(decl) && type.rest === true && type.restAbi === undefined)) {
3818
3845
  type = DYN;
3819
3846
  }
3847
+ if (isJsSourceFile(decl.getSourceFile()) && !decl.type && !hasJsTypeAnnotation(decl) && init.type.kind === "dyn" &&
3848
+ (type?.kind === "record" || type?.kind === "object"))
3849
+ type = DYN;
3820
3850
  // A checker-`any` CONST whose initializer lowered to a STATIC type
3821
3851
  // (`const name = rawName ? rawName.replace(...) : null` — the
3822
3852
  // dyn-receiver machinery and the any-ternary join answer static IR):
@@ -3987,6 +4017,21 @@ export function lowerVarDecl(lowerer, decl, isLet) {
3987
4017
  }
3988
4018
  return { kind: "varDecl", localId: local.id, init, loc: locOf(decl) };
3989
4019
  }
4020
+ // lib.d.ts declares named captures as strings, but nonparticipating captures
4021
+ // are undefined. Inferred index records retain that runtime representation;
4022
+ // explicit annotations still require a checked conversion at the boundary.
4023
+ function inferredOptionalRecordType(lowerer, decl, declared, actual) {
4024
+ if (decl.type || hasJsTypeAnnotation(decl) || declared.kind !== "record" || actual.kind !== "record")
4025
+ return declared;
4026
+ const target = lowerer.shapes.get(declared.shapeId);
4027
+ const source = lowerer.shapes.get(actual.shapeId);
4028
+ if (!target || !source || target.fields.length || source.fields.length || target.tuple || source.tuple ||
4029
+ !target.indexValue || source.indexValue?.kind !== "union" ||
4030
+ lowerer.armTag(source.indexValue.unionId, UNDEFINED_T) < 0 ||
4031
+ !typeEquals(lowerer.stripUndefinedArm(source.indexValue), target.indexValue))
4032
+ return declared;
4033
+ return actual;
4034
+ }
3990
4035
  function lowerVariableInitializer(lowerer, node, expected) {
3991
4036
  let value = node;
3992
4037
  while (ts.isParenthesizedExpression(value) ||
@@ -4132,18 +4177,24 @@ export function jsBindingHasOpenWrites(lowerer, decl) {
4132
4177
  let owner = decl;
4133
4178
  while (owner.parent && !ts.isFunctionLike(owner) && !ts.isSourceFile(owner))
4134
4179
  owner = owner.parent;
4135
- let open = false;
4136
- ts.walkPreorder(owner, (node) => {
4137
- if (ts.isBinaryExpression(node) && node.operatorToken.kind >= ts.SyntaxKind.FirstAssignment &&
4138
- node.operatorToken.kind <= ts.SyntaxKind.LastAssignment && ts.isIdentifier(node.left) &&
4139
- lowerer.resolveValueSymbol(node.left) === symbol &&
4140
- (lowerer.typeOf(node.right).flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) !== 0) {
4141
- open = true;
4142
- return "stop";
4143
- }
4144
- return undefined;
4145
- });
4146
- return open;
4180
+ let writes = lowerer.jsBindingWritesByOwner.get(owner);
4181
+ if (!writes) {
4182
+ const indexed = new Map();
4183
+ ts.walkPreorder(owner, (node) => {
4184
+ if (!ts.isBinaryExpression(node) || node.operatorToken.kind < ts.SyntaxKind.FirstAssignment ||
4185
+ node.operatorToken.kind > ts.SyntaxKind.LastAssignment || !ts.isIdentifier(node.left))
4186
+ return;
4187
+ const entries = indexed.get(node.left.text);
4188
+ if (entries)
4189
+ entries.push(node);
4190
+ else
4191
+ indexed.set(node.left.text, [node]);
4192
+ });
4193
+ writes = indexed;
4194
+ lowerer.jsBindingWritesByOwner.set(owner, writes);
4195
+ }
4196
+ return (writes.get(decl.name.text) ?? []).some((node) => lowerer.resolveValueSymbol(node.left) === symbol &&
4197
+ (lowerer.typeOf(node.right).flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) !== 0);
4147
4198
  }
4148
4199
  function immediatelyGuardedAbsenceProbe(lowerer, decl) {
4149
4200
  if (decl.type || !ts.isIdentifier(decl.name) || !decl.initializer)
@@ -4257,11 +4308,10 @@ function lowerDynSwitch(lowerer, stmt, disc, labels) {
4257
4308
  if (test.kind === "unitLit") {
4258
4309
  return { kind: "dynTest", test: test.unit, value: stableDisc, type: BOOL, loc: locOf(expression) };
4259
4310
  }
4260
- if (test.type.kind !== "string" && test.type.kind !== "f64" &&
4261
- test.type.kind !== "bool" && test.type.kind !== "dyn") {
4311
+ if (!lowerer.dynConvertible(test.type)) {
4262
4312
  lowerer.unsupported("SC1100", expression, "switch case values that cannot compare strictly with 'unknown'");
4263
4313
  }
4264
- return { kind: "dynScalarEq", left: stableDisc, right: test, type: BOOL, loc: locOf(expression) };
4314
+ return { kind: "dynScalarEq", left: stableDisc, right: lowerer.coerceInto(expression, test, DYN), type: BOOL, loc: locOf(expression) };
4265
4315
  });
4266
4316
  }
4267
4317
  function lowerBranchSwitch(lowerer, stmt, disc, labels, compare) {
@@ -4954,6 +5004,11 @@ export function lowerExprStatement(lowerer, expr) {
4954
5004
  loc: locOf(expr),
4955
5005
  };
4956
5006
  }
5007
+ if (opKind === ts.SyntaxKind.EqualsToken || (opKind >= ts.SyntaxKind.FirstCompoundAssignment && opKind <= ts.SyntaxKind.LastCompoundAssignment)) {
5008
+ const urlWrite = lowerUrlAssignment(lowerer, expr);
5009
+ if (urlWrite)
5010
+ return { kind: "exprStmt", expr: urlWrite, loc: locOf(expr) };
5011
+ }
4957
5012
  if (opKind === ts.SyntaxKind.EqualsToken) {
4958
5013
  const callableWrite = lowerNativeFunctionAssignment(lowerer, expr);
4959
5014
  if (callableWrite)
@@ -5213,6 +5268,13 @@ export function lowerExprStatement(lowerer, expr) {
5213
5268
  }
5214
5269
  if (!expr.left.questionDotToken) {
5215
5270
  const recv = tryLowerExpression(lowerer, expr.left.expression);
5271
+ if (recv && (recv.type.kind === "dyn" || isJsSourceFile(expr.getSourceFile()) &&
5272
+ recv.type.kind === "union" && lowerer.dynConvertible(recv.type))) {
5273
+ const loc = locOf(expr);
5274
+ return { kind: "exprStmt", expr: { kind: "libCall", fn: "dyn.keySet", args: [lowerer.coerceInto(expr.left.expression, recv, DYN),
5275
+ { kind: "strLit", value: expr.left.name.text, type: STRING, loc },
5276
+ lowerer.lowerExprExpecting(expr.right, DYN)], type: VOID, loc }, loc };
5277
+ }
5216
5278
  if (recv?.type.kind === "object" && recv.type.className === "%Error") {
5217
5279
  const loc = locOf(expr);
5218
5280
  return { kind: "exprStmt", expr: { kind: "libCall", fn: "dyn.keySet", args: [
@@ -5322,6 +5384,16 @@ export function lowerExprStatement(lowerer, expr) {
5322
5384
  if ((ts.isPrefixUnaryExpression(expr) || ts.isPostfixUnaryExpression(expr)) &&
5323
5385
  (expr.operator === ts.SyntaxKind.PlusPlusToken ||
5324
5386
  expr.operator === ts.SyntaxKind.MinusMinusToken)) {
5387
+ if (ts.isPropertyAccessExpression(expr.operand) || ts.isElementAccessExpression(expr.operand)) {
5388
+ // Statement and value positions share ToNumeric and reference order.
5389
+ // Namespace/expando globals retain their direct binding path below.
5390
+ const binding = ts.isPropertyAccessExpression(expr.operand)
5391
+ ? expandoWritableTarget(lowerer, expr.operand) ?? nsWritableTarget(lowerer, expr.operand)
5392
+ : null;
5393
+ if (binding)
5394
+ return lowerIncDecToTarget(lowerer, expr, binding);
5395
+ return { kind: "exprStmt", expr: lowerIncDec(lowerer, expr, ts.isPrefixUnaryExpression(expr)), loc: locOf(expr) };
5396
+ }
5325
5397
  // Statement position only: pre/post distinction is unobservable, so
5326
5398
  // both desugar to `x = x ± 1`.
5327
5399
  if (ts.isPropertyAccessExpression(expr.operand) ||
@@ -6638,6 +6710,7 @@ export function lowerForOf(lowerer, stmt) {
6638
6710
  }
6639
6711
  iterSrc ??= stmt.expression;
6640
6712
  let iterable = lowerer.lowerExpr(iterSrc);
6713
+ let tupleSource = null;
6641
6714
  // A nested loop receiver can be an OOB-safe array read from the outer
6642
6715
  // loop (`for (const row of grid) for (const cell of row)`). The checker
6643
6716
  // sees the inner value as an array, while its runtime slot retains
@@ -6650,7 +6723,8 @@ export function lowerForOf(lowerer, stmt) {
6650
6723
  if (iterable.type.kind === "union" && checkerIterable !== null &&
6651
6724
  (checkerIterable.kind === "array" || checkerIterable.kind === "map" || checkerIterable.kind === "set" ||
6652
6725
  checkerIterable.kind === "bytes" || checkerIterable.kind === "string" || checkerIterable.kind === "searchParams" ||
6653
- checkerIterable.kind === "generator" || checkerIterable.kind === "object")) {
6726
+ checkerIterable.kind === "generator" || checkerIterable.kind === "object" ||
6727
+ (checkerIterable.kind === "record" && lowerer.shapes.get(checkerIterable.shapeId)?.tuple))) {
6654
6728
  const helper = lowerer.narrowedArmHelper(iterable.type.unionId, checkerIterable, locOf(iterSrc));
6655
6729
  if (helper)
6656
6730
  iterable = { kind: "call", callee: helper, args: [iterable], type: checkerIterable, loc: locOf(iterSrc) };
@@ -6702,62 +6776,28 @@ export function lowerForOf(lowerer, stmt) {
6702
6776
  }
6703
6777
  if (iterable.type.kind === "record" &&
6704
6778
  lowerer.shapes.get(iterable.type.shapeId)?.tuple) {
6705
- // A tuple read PURELY iterates: the positions snapshot into a
6706
- // fresh array at loop entry and the ordinary array for-of runs
6707
- // over it — the allowlist-iteration idiom. HOMOGENEOUS tuples
6708
- // (`["a", "b"] as const`) snapshot at their one position type;
6709
- // heterogeneous tuples ([string, boolean]) snapshot into the
6710
- // positions' UNION when it interns, each read wrapping into its
6711
- // arm — exactly the string|boolean the checker gives the loop
6712
- // variable. Pure receivers only (the reads re-emit per position);
6713
- // JS reads positions lazily, so a body that WRITES a later
6714
- // position of a mutable tuple would observe its old value here —
6715
- // readonly (as-const) tuples, the shape that actually occurs,
6716
- // cannot be written at all.
6779
+ // Retain the tuple once and read positions lazily through the
6780
+ // indexed loop below. Copying positions into an array would hide
6781
+ // writes made by earlier iterations and reject computed receivers.
6717
6782
  const shape = lowerer.shapes.get(iterable.type.shapeId);
6718
- const byIndex = [...shape.fields].sort((a, b) => Number(a.name) - Number(b.name));
6719
- const first = byIndex[0]?.type;
6720
- const homogeneous = first !== undefined && byIndex.every((f) => typeEquals(f.type, first));
6721
- let elemT = homogeneous ? first : null;
6722
- if (!homogeneous && byIndex.length > 0) {
6723
- const arms = [];
6724
- for (const f of byIndex) {
6725
- const arm = f.type.kind === "union" ? null : f.type;
6726
- if (arm === null) {
6727
- elemT = null;
6728
- break;
6729
- }
6730
- if (!arms.some((a) => typeEquals(a, arm)))
6731
- arms.push(arm);
6732
- elemT = { kind: "union", unionId: lowerer.unions.intern(arms) };
6783
+ const fields = [...shape.fields].sort((a, b) => Number(a.name) - Number(b.name));
6784
+ const first = fields[0]?.type;
6785
+ const homogeneous = first !== undefined && fields.every((field) => typeEquals(field.type, first));
6786
+ const arms = [];
6787
+ if (!homogeneous) {
6788
+ for (const field of fields) {
6789
+ const types = field.type.kind === "union" ? lowerer.unions.get(field.type.unionId).arms : [field.type];
6790
+ for (const type of types)
6791
+ if (!arms.some((arm) => typeEquals(arm, type)))
6792
+ arms.push(type);
6733
6793
  }
6734
6794
  }
6735
- if (elemT !== null && isSafeToRepeat(iterable)) {
6736
- const loc = locOf(stmt.expression);
6737
- const shapeId = iterable.type.shapeId;
6738
- const snapshotElem = elemT;
6739
- iterable = {
6740
- kind: "arrayLit",
6741
- elems: byIndex.map((f) => {
6742
- const read = {
6743
- kind: "recordGet",
6744
- obj: iterable,
6745
- shapeId,
6746
- field: f.name,
6747
- type: f.type,
6748
- loc,
6749
- };
6750
- return typeEquals(f.type, snapshotElem)
6751
- ? read
6752
- : lowerer.coerceInto(stmt.expression, read, snapshotElem);
6753
- }),
6754
- type: arrayOf(snapshotElem),
6755
- loc,
6756
- };
6757
- }
6758
- else {
6759
- lowerer.noLowering("for-of over tuples", stmt.expression, "tuples with union-typed or unrepresentable positions are fixed-shape — read t[0], t[1], ... directly (plain-position tuples purely iterate)");
6795
+ const elem = homogeneous ? first : arms.length === 1 ? arms[0] : arms.length > 1
6796
+ ? { kind: "union", unionId: lowerer.unions.intern(arms) } : undefined;
6797
+ if (elem === undefined) {
6798
+ lowerer.noLowering("for-of over tuples", stmt.expression, "tuple positions must have represented value types");
6760
6799
  }
6800
+ tupleSource = { shapeId: iterable.type.shapeId, fields, elem };
6761
6801
  }
6762
6802
  // An ISLAND value (`for (const store of stores)` where stores is a
6763
6803
  // package-typed array — one engine handle): the engine's OWN
@@ -6775,20 +6815,21 @@ export function lowerForOf(lowerer, stmt) {
6775
6815
  if (iterable.type.kind === "dyn") {
6776
6816
  return lowerForOfDyn(lowerer, stmt, iterable, labels);
6777
6817
  }
6778
- if (iterable.type.kind !== "array") {
6818
+ if (tupleSource === null) {
6779
6819
  lowerer.badType(stmt.expression, lowerer.typeOf(stmt.expression));
6780
6820
  }
6781
6821
  }
6782
- const yieldedT = arrayValueType(lowerer, iterable.type.elem);
6822
+ const elementType = iterable.type.kind === "array" ? iterable.type.elem : tupleSource.elem;
6823
+ const yieldedT = tupleSource === null ? arrayValueType(lowerer, elementType) : elementType;
6783
6824
  let elemValueT = yieldedT;
6784
6825
  let awaitPromiseTag = null;
6785
6826
  if (awaitArray) {
6786
6827
  let promiseElem = null;
6787
- if (iterable.type.elem.kind === "promise") {
6788
- promiseElem = iterable.type.elem;
6828
+ if (elementType.kind === "promise") {
6829
+ promiseElem = elementType;
6789
6830
  }
6790
- else if (iterable.type.elem.kind === "union") {
6791
- const arms = lowerer.unions.get(iterable.type.elem.unionId)?.arms;
6831
+ else if (elementType.kind === "union") {
6832
+ const arms = lowerer.unions.get(elementType.unionId)?.arms;
6792
6833
  if (arms?.length === 2 && arms.some((arm) => arm.kind === "undefinedT")) {
6793
6834
  const arm = arms.find((candidate) => candidate.kind === "promise");
6794
6835
  if (arm?.kind === "promise")
@@ -6813,7 +6854,7 @@ export function lowerForOf(lowerer, stmt) {
6813
6854
  awaitPromiseTag = lowerer.armTag(yieldedT.unionId, promiseElem);
6814
6855
  elemValueT = lowerer.withUndefinedArm(promiseElem.inner);
6815
6856
  }
6816
- else if (!nonThenable(iterable.type.elem)) {
6857
+ else if (!nonThenable(elementType)) {
6817
6858
  lowerer.unsupported("SC1070", stmt.expression, "for-await over array values that may be promises or thenables");
6818
6859
  }
6819
6860
  }
@@ -6828,7 +6869,28 @@ export function lowerForOf(lowerer, stmt) {
6828
6869
  const needsClose = awaitArray ? lowerer.declareHiddenLocal("%arrayIteratorNeedsClose", BOOL) : null;
6829
6870
  if (needsClose)
6830
6871
  needsClose.mutable = true;
6831
- const yielded = arrayValueRead(lowerer, varRef(source.id, sourceT, loc), varRef(cursor.id, F64, loc), sourceT.elem, loc);
6872
+ let yielded;
6873
+ if (tupleSource !== null) {
6874
+ const tuple = tupleSource;
6875
+ const read = (index) => {
6876
+ const field = tuple.fields[index];
6877
+ return lowerer.coerceInto(stmt.expression, {
6878
+ kind: "recordGet", obj: varRef(source.id, sourceT, loc), shapeId: tuple.shapeId,
6879
+ field: field.name, type: field.type, loc,
6880
+ }, elementType);
6881
+ };
6882
+ yielded = read(tuple.fields.length - 1);
6883
+ for (let index = tuple.fields.length - 2; index >= 0; index--) {
6884
+ yielded = {
6885
+ kind: "ternary", cond: {
6886
+ kind: "bin", op: "===", left: varRef(cursor.id, F64, loc), right: numLit(index, loc), type: BOOL, loc,
6887
+ }, then: read(index), else_: yielded, type: elementType, loc,
6888
+ };
6889
+ }
6890
+ }
6891
+ else {
6892
+ yielded = arrayValueRead(lowerer, varRef(source.id, sourceT, loc), varRef(cursor.id, F64, loc), elementType, loc);
6893
+ }
6832
6894
  const init = awaitPromiseTag === null ? yielded : {
6833
6895
  kind: "awaitUnionExpr", value: yielded, promiseTag: awaitPromiseTag, type: elemValueT, loc,
6834
6896
  };
@@ -6853,9 +6915,9 @@ export function lowerForOf(lowerer, stmt) {
6853
6915
  finallyBody: null,
6854
6916
  loc,
6855
6917
  } : readValue;
6856
- const length = () => ({
6918
+ const length = () => tupleSource !== null ? numLit(tupleSource.fields.length, loc) : {
6857
6919
  kind: "arrIntrinsic", method: "length", receiver: varRef(source.id, sourceT, loc), args: [], type: F64, loc,
6858
- });
6920
+ };
6859
6921
  const loop = {
6860
6922
  kind: "for",
6861
6923
  init: { kind: "varDecl", localId: cursor.id, init: numLit(0, loc), loc },
@@ -6992,7 +7054,7 @@ export function lowerForOf(lowerer, stmt) {
6992
7054
  }
6993
7055
  const local = lowerer.declareLocal(decl.name, decl.name.text, elemValueT, isLet);
6994
7056
  const declaredElement = lowerer.mapTypeOf(lowerer.typeOf(decl.name));
6995
- if (!typeEquals(elemValueT, sourceT.elem) ||
7057
+ if (!typeEquals(elemValueT, elementType) ||
6996
7058
  (declaredElement !== null && lowerer.runtimeOptionalWidening(elemValueT, declaredElement) !== null)) {
6997
7059
  const root = lowerer.runtimeOptionalRootOf(local);
6998
7060
  lowerer.runtimeOptionalLocals.add(root);
@@ -7822,9 +7884,8 @@ function lowerForOfString(lowerer, stmt, iterable, labels) {
7822
7884
  * properties, so the enumeration is honestly EMPTY (zero iterations;
7823
7885
  * the body typechecked but never evaluates — SEMANTICS.md documents
7824
7886
  * the divergence).
7825
- * - class instances fence: which keys exist on one depends on runtime
7826
- * property creation (unset declared fields, useDefineForClassFields)
7827
- * that the struct model does not track — named, not guessed.
7887
+ * - JavaScript program classes use their live property-creation table.
7888
+ * TypeScript and runtime-owned layouts keep the class-instance fence.
7828
7889
  * Bindings mirror for-of's: const/let declare the per-iteration string
7829
7890
  * local, `var` assigns the hoisted shared slot, a pre-declared
7830
7891
  * identifier target assigns per pass; destructuring heads are tsc
@@ -7835,7 +7896,17 @@ function lowerForIn(lowerer, stmt) {
7835
7896
  if (stdlibGlobalNameOf(lowerer, stmt.expression) === "globalThis") {
7836
7897
  return { kind: "block", body: [], loc };
7837
7898
  }
7838
- const receiver = lowerer.lowerExpr(stmt.expression);
7899
+ let receiver = lowerer.lowerExpr(stmt.expression);
7900
+ if (receiver.type.kind === "object") {
7901
+ const info = lowerer.classes.get(receiver.type.className);
7902
+ let root = info;
7903
+ while (root?.base)
7904
+ root = root.base;
7905
+ if (info?.decl && isJsSourceFile(info.decl.getSourceFile()) && !info.def.runtime &&
7906
+ !root?.def.runtime && !info.builtinError && !info.builtinEmitter && !info.builtinStream) {
7907
+ receiver = lowerer.coerceToExpected(receiver, DYN);
7908
+ }
7909
+ }
7839
7910
  const recvT = receiver.type;
7840
7911
  if (recvT.kind === "dyn") {
7841
7912
  const recv = lowerer.declareHiddenLocal("%indyn", DYN);
@@ -7844,9 +7915,7 @@ function lowerForIn(lowerer, stmt) {
7844
7915
  kind: "dynCheck", value: { kind: "libCall", fn: "dyn.forInKeys", args: [ref], type: DYN, loc },
7845
7916
  type: arrayOf(STRING), loc,
7846
7917
  };
7847
- const loop = lowerForInOverKeys(lowerer, stmt, keys, labels, (key) => ({
7848
- kind: "libCall", fn: "dyn.hasKey", args: [ref, key], type: BOOL, loc,
7849
- }));
7918
+ const loop = lowerForInOverKeys(lowerer, stmt, keys, labels, (key) => classForInHasKey(lowerer, ref, key, loc));
7850
7919
  return { kind: "block", body: [{ kind: "varDecl", localId: recv.id, init: receiver, loc }, loop], loc };
7851
7920
  }
7852
7921
  if (recvT.kind === "array")