@scriptc/compiler 0.2.0 → 0.2.2

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 (284) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +84 -19
  2. package/dist/backend/cycle-analysis.js +1 -0
  3. package/dist/backend/cycle-analysis.js.map +1 -1
  4. package/dist/backend/llvm/classes.js +21 -5
  5. package/dist/backend/llvm/classes.js.map +1 -1
  6. package/dist/backend/llvm/dyn.d.ts +8 -0
  7. package/dist/backend/llvm/dyn.js +247 -108
  8. package/dist/backend/llvm/dyn.js.map +1 -1
  9. package/dist/backend/llvm/emitter.d.ts +6 -3
  10. package/dist/backend/llvm/emitter.js +99 -25
  11. package/dist/backend/llvm/emitter.js.map +1 -1
  12. package/dist/backend/llvm/emitter.test.js +9 -1
  13. package/dist/backend/llvm/emitter.test.js.map +1 -1
  14. package/dist/backend/llvm/expr-bytes.d.ts +1 -1
  15. package/dist/backend/llvm/expr-bytes.js +28 -17
  16. package/dist/backend/llvm/expr-bytes.js.map +1 -1
  17. package/dist/backend/llvm/expr-containers.js +5 -0
  18. package/dist/backend/llvm/expr-containers.js.map +1 -1
  19. package/dist/backend/llvm/expr-control.js +1 -1
  20. package/dist/backend/llvm/expr-control.js.map +1 -1
  21. package/dist/backend/llvm/expr-dynamic.js +47 -13
  22. package/dist/backend/llvm/expr-dynamic.js.map +1 -1
  23. package/dist/backend/llvm/expr-primitives.js +11 -1
  24. package/dist/backend/llvm/expr-primitives.js.map +1 -1
  25. package/dist/backend/llvm/expr-records.js +11 -3
  26. package/dist/backend/llvm/expr-records.js.map +1 -1
  27. package/dist/backend/llvm/expr-stream-bridges.js +187 -18
  28. package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
  29. package/dist/backend/llvm/expr-stream-callbacks.d.ts +2 -2
  30. package/dist/backend/llvm/expr-stream-callbacks.js +7 -57
  31. package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
  32. package/dist/backend/llvm/lib-dispatch.js +41 -3
  33. package/dist/backend/llvm/lib-dispatch.js.map +1 -1
  34. package/dist/backend/llvm/lib-filesystem.js +12 -9
  35. package/dist/backend/llvm/lib-filesystem.js.map +1 -1
  36. package/dist/backend/llvm/lib-process.js +23 -3
  37. package/dist/backend/llvm/lib-process.js.map +1 -1
  38. package/dist/backend/llvm/lib-shared.js +80 -3
  39. package/dist/backend/llvm/lib-shared.js.map +1 -1
  40. package/dist/backend/llvm/shapes.js +8 -2
  41. package/dist/backend/llvm/shapes.js.map +1 -1
  42. package/dist/backend/may-throw.js +4 -0
  43. package/dist/backend/may-throw.js.map +1 -1
  44. package/dist/backend/native-codegen.d.ts +1 -1
  45. package/dist/backend/native-codegen.js +4 -3
  46. package/dist/backend/native-codegen.js.map +1 -1
  47. package/dist/backend/native-codegen.test.js +11 -0
  48. package/dist/backend/native-codegen.test.js.map +1 -1
  49. package/dist/backend/native-toolchain.d.ts +3 -6
  50. package/dist/backend/native-toolchain.js +53 -23
  51. package/dist/backend/native-toolchain.js.map +1 -1
  52. package/dist/backend/native-toolchain.test.js +72 -0
  53. package/dist/backend/native-toolchain.test.js.map +1 -1
  54. package/dist/backend/runtime-abi.d.ts +2 -2
  55. package/dist/backend/runtime-abi.js +2 -2
  56. package/dist/backend/runtime-pack-native.js +4 -1
  57. package/dist/backend/runtime-pack-native.js.map +1 -1
  58. package/dist/backend/runtime-pack-targets.test.js +1 -1
  59. package/dist/backend/runtime-pack.test.js +1 -1
  60. package/dist/backend/target-diagnostics.d.ts +5 -0
  61. package/dist/backend/target-diagnostics.js +72 -1
  62. package/dist/backend/target-diagnostics.js.map +1 -1
  63. package/dist/backend/target-diagnostics.test.d.ts +1 -0
  64. package/dist/backend/target-diagnostics.test.js +68 -0
  65. package/dist/backend/target-diagnostics.test.js.map +1 -0
  66. package/dist/backend/targets.js +10 -6
  67. package/dist/backend/targets.js.map +1 -1
  68. package/dist/backend/targets.test.js +7 -0
  69. package/dist/backend/targets.test.js.map +1 -1
  70. package/dist/compat/fetch-profile.js +34 -4
  71. package/dist/compat/fetch-profile.js.map +1 -1
  72. package/dist/coverage/surface-manifest.js +5 -3
  73. package/dist/coverage/surface-manifest.js.map +1 -1
  74. package/dist/diagnostics/diagnostic.js +2 -7
  75. package/dist/diagnostics/diagnostic.js.map +1 -1
  76. package/dist/executable/executable-cache.d.ts +7 -3
  77. package/dist/executable/executable-cache.js +47 -11
  78. package/dist/executable/executable-cache.js.map +1 -1
  79. package/dist/executable/executable-cache.test.js +109 -2
  80. package/dist/executable/executable-cache.test.js.map +1 -1
  81. package/dist/executable/prepare.js +2 -1
  82. package/dist/executable/prepare.js.map +1 -1
  83. package/dist/frontend/builtin-modules.d.ts +1 -1
  84. package/dist/frontend/builtin-modules.js +1 -1
  85. package/dist/frontend/builtin-modules.js.map +1 -1
  86. package/dist/frontend/function-completion.d.ts +6 -0
  87. package/dist/frontend/function-completion.js +50 -0
  88. package/dist/frontend/function-completion.js.map +1 -0
  89. package/dist/frontend/lowering/abstract-equality.js +5 -1
  90. package/dist/frontend/lowering/abstract-equality.js.map +1 -1
  91. package/dist/frontend/lowering/checked-iterable-spread.d.ts +4 -0
  92. package/dist/frontend/lowering/checked-iterable-spread.js +30 -0
  93. package/dist/frontend/lowering/checked-iterable-spread.js.map +1 -0
  94. package/dist/frontend/lowering/checked-promise-all.d.ts +5 -0
  95. package/dist/frontend/lowering/checked-promise-all.js +31 -0
  96. package/dist/frontend/lowering/checked-promise-all.js.map +1 -0
  97. package/dist/frontend/lowering/class-callbacks.d.ts +4 -4
  98. package/dist/frontend/lowering/class-callbacks.js +29 -17
  99. package/dist/frontend/lowering/class-callbacks.js.map +1 -1
  100. package/dist/frontend/lowering/class-construction.d.ts +14 -0
  101. package/dist/frontend/lowering/class-construction.js +185 -0
  102. package/dist/frontend/lowering/class-construction.js.map +1 -0
  103. package/dist/frontend/lowering/class-descriptors.d.ts +2 -1
  104. package/dist/frontend/lowering/class-descriptors.js +58 -10
  105. package/dist/frontend/lowering/class-descriptors.js.map +1 -1
  106. package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +36 -1
  107. package/dist/frontend/lowering/class-dynamic-dispatch.js +965 -91
  108. package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
  109. package/dist/frontend/lowering/class-dynamic-dispatch.test.js +66 -3
  110. package/dist/frontend/lowering/class-dynamic-dispatch.test.js.map +1 -1
  111. package/dist/frontend/lowering/class-instance-constructor.d.ts +1 -1
  112. package/dist/frontend/lowering/class-instance-constructor.js +15 -42
  113. package/dist/frontend/lowering/class-instance-constructor.js.map +1 -1
  114. package/dist/frontend/lowering/class-method-values.d.ts +20 -1
  115. package/dist/frontend/lowering/class-method-values.js +120 -24
  116. package/dist/frontend/lowering/class-method-values.js.map +1 -1
  117. package/dist/frontend/lowering/class-prototypes.d.ts +10 -3
  118. package/dist/frontend/lowering/class-prototypes.js +188 -21
  119. package/dist/frontend/lowering/class-prototypes.js.map +1 -1
  120. package/dist/frontend/lowering/class-runtime-statics.d.ts +8 -0
  121. package/dist/frontend/lowering/class-runtime-statics.js +84 -0
  122. package/dist/frontend/lowering/class-runtime-statics.js.map +1 -0
  123. package/dist/frontend/lowering/class-static-data.d.ts +1 -0
  124. package/dist/frontend/lowering/class-static-data.js +6 -4
  125. package/dist/frontend/lowering/class-static-data.js.map +1 -1
  126. package/dist/frontend/lowering/containers/bytes.js +66 -17
  127. package/dist/frontend/lowering/containers/bytes.js.map +1 -1
  128. package/dist/frontend/lowering/containers/string-and-regexp.js +24 -47
  129. package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
  130. package/dist/frontend/lowering/deferred-module-initializers.d.ts +13 -0
  131. package/dist/frontend/lowering/deferred-module-initializers.js +410 -0
  132. package/dist/frontend/lowering/deferred-module-initializers.js.map +1 -0
  133. package/dist/frontend/lowering/deferred-module-initializers.test.d.ts +1 -0
  134. package/dist/frontend/lowering/deferred-module-initializers.test.js +92 -0
  135. package/dist/frontend/lowering/deferred-module-initializers.test.js.map +1 -0
  136. package/dist/frontend/lowering/error-methods.d.ts +4 -1
  137. package/dist/frontend/lowering/error-methods.js +100 -1
  138. package/dist/frontend/lowering/error-methods.js.map +1 -1
  139. package/dist/frontend/lowering/expressions/native-proxy.js +3 -1
  140. package/dist/frontend/lowering/expressions/native-proxy.js.map +1 -1
  141. package/dist/frontend/lowering/expressions/nullish-assignment.js +19 -11
  142. package/dist/frontend/lowering/expressions/nullish-assignment.js.map +1 -1
  143. package/dist/frontend/lowering/expressions/object-literals.js +68 -7
  144. package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
  145. package/dist/frontend/lowering/expressions/optional-chains.d.ts +3 -4
  146. package/dist/frontend/lowering/expressions/optional-chains.js +72 -20
  147. package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
  148. package/dist/frontend/lowering/function-context.d.ts +11 -3
  149. package/dist/frontend/lowering/function-context.js +11 -5
  150. package/dist/frontend/lowering/function-context.js.map +1 -1
  151. package/dist/frontend/lowering/generator-dynamic-dispatch.d.ts +1 -0
  152. package/dist/frontend/lowering/generator-dynamic-dispatch.js +39 -1
  153. package/dist/frontend/lowering/generator-dynamic-dispatch.js.map +1 -1
  154. package/dist/frontend/lowering/lib-boundary.d.ts +2 -0
  155. package/dist/frontend/lowering/lib-boundary.js +54 -1
  156. package/dist/frontend/lowering/lib-boundary.js.map +1 -1
  157. package/dist/frontend/lowering/lower-builtin-values.d.ts +7 -1
  158. package/dist/frontend/lowering/lower-builtin-values.js +113 -3
  159. package/dist/frontend/lowering/lower-builtin-values.js.map +1 -1
  160. package/dist/frontend/lowering/lower-builtins.d.ts +10 -14
  161. package/dist/frontend/lowering/lower-builtins.js +443 -88
  162. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  163. package/dist/frontend/lowering/lower-calls.d.ts +8 -5
  164. package/dist/frontend/lowering/lower-calls.js +717 -142
  165. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  166. package/dist/frontend/lowering/lower-classes.d.ts +18 -13
  167. package/dist/frontend/lowering/lower-classes.js +1076 -188
  168. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  169. package/dist/frontend/lowering/lower-containers.d.ts +9 -0
  170. package/dist/frontend/lowering/lower-containers.js +172 -51
  171. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  172. package/dist/frontend/lowering/lower-dgram.js +3 -2
  173. package/dist/frontend/lowering/lower-dgram.js.map +1 -1
  174. package/dist/frontend/lowering/lower-exprs.d.ts +12 -8
  175. package/dist/frontend/lowering/lower-exprs.js +802 -232
  176. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  177. package/dist/frontend/lowering/lower-generators.js +17 -2
  178. package/dist/frontend/lowering/lower-generators.js.map +1 -1
  179. package/dist/frontend/lowering/lower-inspect.js +15 -1
  180. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  181. package/dist/frontend/lowering/lower-island.d.ts +2 -0
  182. package/dist/frontend/lowering/lower-island.js +36 -10
  183. package/dist/frontend/lowering/lower-island.js.map +1 -1
  184. package/dist/frontend/lowering/lower-island.test.d.ts +1 -0
  185. package/dist/frontend/lowering/lower-island.test.js +51 -0
  186. package/dist/frontend/lowering/lower-island.test.js.map +1 -0
  187. package/dist/frontend/lowering/lower-modules.d.ts +1 -3
  188. package/dist/frontend/lowering/lower-modules.js +380 -73
  189. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  190. package/dist/frontend/lowering/lower-modules.test.d.ts +1 -0
  191. package/dist/frontend/lowering/lower-modules.test.js +107 -0
  192. package/dist/frontend/lowering/lower-modules.test.js.map +1 -0
  193. package/dist/frontend/lowering/lower-stmts.d.ts +7 -3
  194. package/dist/frontend/lowering/lower-stmts.js +221 -47
  195. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  196. package/dist/frontend/lowering/lower-stmts.test.d.ts +1 -0
  197. package/dist/frontend/lowering/lower-stmts.test.js +77 -0
  198. package/dist/frontend/lowering/lower-stmts.test.js.map +1 -0
  199. package/dist/frontend/lowering/lower-stream.js +3 -1
  200. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  201. package/dist/frontend/lowering/lower-url.d.ts +2 -1
  202. package/dist/frontend/lowering/lower-url.js +32 -9
  203. package/dist/frontend/lowering/lower-url.js.map +1 -1
  204. package/dist/frontend/lowering/lowerer.d.ts +53 -10
  205. package/dist/frontend/lowering/lowerer.js +390 -77
  206. package/dist/frontend/lowering/lowerer.js.map +1 -1
  207. package/dist/frontend/lowering/lowerer.test.js +187 -3
  208. package/dist/frontend/lowering/lowerer.test.js.map +1 -1
  209. package/dist/frontend/lowering/module-namespace-elements.d.ts +7 -0
  210. package/dist/frontend/lowering/module-namespace-elements.js +54 -0
  211. package/dist/frontend/lowering/module-namespace-elements.js.map +1 -0
  212. package/dist/frontend/lowering/object-factory-new.d.ts +4 -3
  213. package/dist/frontend/lowering/object-factory-new.js +27 -14
  214. package/dist/frontend/lowering/object-factory-new.js.map +1 -1
  215. package/dist/frontend/lowering/surfaces.d.ts +3 -0
  216. package/dist/frontend/lowering/surfaces.js +48 -19
  217. package/dist/frontend/lowering/surfaces.js.map +1 -1
  218. package/dist/frontend/lowering/text-decoder-encoding.d.ts +2 -0
  219. package/dist/frontend/lowering/text-decoder-encoding.js +8 -0
  220. package/dist/frontend/lowering/text-decoder-encoding.js.map +1 -1
  221. package/dist/frontend/lowering/text-decoder-encoding.test.js +2 -1
  222. package/dist/frontend/lowering/text-decoder-encoding.test.js.map +1 -1
  223. package/dist/frontend/lowering/unregistered-class-types.test.js +3 -3
  224. package/dist/frontend/lowering/unregistered-class-types.test.js.map +1 -1
  225. package/dist/frontend/npm-static-prune.js +116 -34
  226. package/dist/frontend/npm-static-prune.js.map +1 -1
  227. package/dist/frontend/npm-static-prune.test.js +8 -0
  228. package/dist/frontend/npm-static-prune.test.js.map +1 -1
  229. package/dist/frontend/program.d.ts +1 -1
  230. package/dist/frontend/program.js +57 -26
  231. package/dist/frontend/program.js.map +1 -1
  232. package/dist/frontend/program.test.js +18 -0
  233. package/dist/frontend/program.test.js.map +1 -1
  234. package/dist/frontend/ts7/ast.js +4 -3
  235. package/dist/frontend/ts7/ast.js.map +1 -1
  236. package/dist/frontend/ts7/semantic-json.js +5 -10
  237. package/dist/frontend/ts7/semantic-json.js.map +1 -1
  238. package/dist/frontend/type-mapper.d.ts +9 -1
  239. package/dist/frontend/type-mapper.js +169 -23
  240. package/dist/frontend/type-mapper.js.map +1 -1
  241. package/dist/frontend/type-mapper.test.js +23 -0
  242. package/dist/frontend/type-mapper.test.js.map +1 -1
  243. package/dist/frontend/union-discriminants.d.ts +1 -1
  244. package/dist/frontend/union-discriminants.js +24 -9
  245. package/dist/frontend/union-discriminants.js.map +1 -1
  246. package/dist/index.js +16 -10
  247. package/dist/index.js.map +1 -1
  248. package/dist/ir/analysis.js +2 -0
  249. package/dist/ir/analysis.js.map +1 -1
  250. package/dist/ir/ir.d.ts +74 -41
  251. package/dist/ir/ir.js +167 -43
  252. package/dist/ir/ir.js.map +1 -1
  253. package/dist/ir/ir.test.js +35 -0
  254. package/dist/ir/ir.test.js.map +1 -1
  255. package/dist/ir/serialize.js +35 -3
  256. package/dist/ir/serialize.js.map +1 -1
  257. package/dist/ir/serialize.test.js +26 -1
  258. package/dist/ir/serialize.test.js.map +1 -1
  259. package/dist/ir/traverse.d.ts +0 -3
  260. package/dist/ir/traverse.js +33 -20
  261. package/dist/ir/traverse.js.map +1 -1
  262. package/dist/ir/validate.js +136 -16
  263. package/dist/ir/validate.js.map +1 -1
  264. package/dist/ir/validate.test.js +77 -1
  265. package/dist/ir/validate.test.js.map +1 -1
  266. package/dist/library/compiler-self-identity.js +1 -1
  267. package/dist/library/compiler-self-identity.test.js +2 -2
  268. package/dist/library/compiler-self-identity.test.js.map +1 -1
  269. package/dist/library/int-infer.d.ts +2 -2
  270. package/dist/library/int-infer.js +10 -7
  271. package/dist/library/int-infer.js.map +1 -1
  272. package/dist/library/int-infer.test.js +44 -0
  273. package/dist/library/int-infer.test.js.map +1 -1
  274. package/dist/library/prepare.js +2 -1
  275. package/dist/library/prepare.js.map +1 -1
  276. package/dist/native/sanitizer.js +3 -1
  277. package/dist/native/sanitizer.js.map +1 -1
  278. package/dist/native/toolchain.d.ts +1 -1
  279. package/dist/native/toolchain.js +26 -6
  280. package/dist/native/toolchain.js.map +1 -1
  281. package/dist/native/toolchain.test.js +53 -1
  282. package/dist/native/toolchain.test.js.map +1 -1
  283. package/package.json +20 -20
  284. package/surface-manifest.json +170 -93
@@ -1,6 +1,9 @@
1
1
  import * as ts from "../ts7/adapter.js";
2
2
  import type { Lowerer } from "./lowerer.js";
3
3
  import { type IrExpr, type IrFunction, type IrRecordShape, type IrStmt, type IrType, type SrcLoc } from "../../ir/ir.js";
4
+ /** Object() and new Object() preserve known object inputs. Primitive
5
+ * boxing and unproven checked-dynamic values retain their refusal. */
6
+ export declare function lowerObjectConstructor(lowerer: Lowerer, args: readonly ts.Expression[], loc: SrcLoc): IrExpr | null;
4
7
  /** Ambient array method calls. `push`/`unshift`/`pop`/`reverse`/
5
8
  * `indexOf`/`includes`/`join`
6
9
  * lower to arrIntrinsic; the HOF family — `map`/`filter`/`forEach`/
@@ -29,6 +32,12 @@ export declare const lowerNpmStaticSafeIndexRead: typeof lowerSafeIndexRead;
29
32
  export declare function lowerArrayConstructor(lowerer: Lowerer, expr: ts.CallExpression | ts.NewExpression, args: readonly ts.Expression[]): IrExpr;
30
33
  /** `Array.of` creates an array of its arguments, including a lone number. */
31
34
  export declare function lowerArrayOfCall(lowerer: Lowerer, call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
35
+ /** Mapper-less checked Array.from: acquire once, then step through emitted
36
+ * property and call dispatch so native class iterators retain their methods. */
37
+ export declare function lowerCheckedArrayFrom(lowerer: Lowerer, source: IrExpr, loc: SrcLoc, mapper?: IrExpr, receiver?: IrExpr, numeric?: boolean, iterable?: IrExpr): Extract<IrExpr, {
38
+ kind: "seqExpr";
39
+ }>;
40
+ export declare function lowerArrayFromValue(lowerer: Lowerer, loc: SrcLoc): IrExpr;
32
41
  /** `Array.from({ length: n }, mapfn)` — the counted-generation idiom — on
33
42
  * THE stdlib Array global. The source must be an OBJECT LITERAL whose
34
43
  * single property is `length` (the shape the idiom always spells; the
@@ -6,7 +6,7 @@ import { InternalCompilerError } from "../../errors.js";
6
6
  * record operations. */
7
7
  import * as ts from "../ts7/adapter.js";
8
8
  import { BOOL, CAUGHT, DYN, F64, JSVAL, STRING, UNDEFINED_T, VOID, arrayOf, funcOf, isRefCounted, isSupportedArrayElem, isSupportedIndexValue, isUnitType, typeEquals } from "../../ir/ir.js";
9
- import { ARRAY_METHODS, MAP_METHODS, SET_COMBINE_METHODS, SET_METHODS } from "./surfaces.js";
9
+ import { ARRAY_METHODS, COLLECTION_ITERATOR_METHODS, MAP_METHODS, SET_COMBINE_METHODS, SET_METHODS } from "./surfaces.js";
10
10
  import { tryLowerExpression } from "./expressions/try-lower-expression.js";
11
11
  import { forOfVarTarget, lowerDestructuringAssign } from "./lower-stmts.js";
12
12
  import { isJsSourceFile, locOf } from "../program.js";
@@ -14,10 +14,25 @@ import { islandPrimitiveExit, lowerDynDispatchMethodCall } from "./lower-calls.j
14
14
  import { buildArraySortFn } from "./lower-array-sort.js";
15
15
  import { arrayIndexPresent, arrayValueRead, arrayValueStore, arrayValueType, currentArrayIndexPresent } from "./array-values.js";
16
16
  import { typeKey } from "../type-mapper.js";
17
- import { nodeThrowExpr } from "./lowerer.js";
17
+ import { dynUndefinedExpr, newFnCtx, nodeThrowExpr } from "./lowerer.js";
18
18
  import { boolLit, countedFor, numLit, strLit, varRef } from "../../ir/build.js";
19
19
  import { defaultAfterUndefined, lowerPositionArgument, lowerStaticallyUndefinedArgument, positionNumber } from "./optional-arguments.js";
20
20
  import { lowerArrayCopyWithin, lowerArrayFill } from "./array-indexed-mutation.js";
21
+ /** Object() and new Object() preserve known object inputs. Primitive
22
+ * boxing and unproven checked-dynamic values retain their refusal. */
23
+ export function lowerObjectConstructor(lowerer, args, loc) {
24
+ if (args.length === 0) {
25
+ return { kind: "recordLit", fields: [], type: { kind: "record", shapeId: lowerer.shapes.intern([]) }, loc };
26
+ }
27
+ if (args.length !== 1 || ts.isSpreadElement(args[0]))
28
+ return null;
29
+ const value = lowerer.lowerExpr(args[0]);
30
+ if (value.kind === "dynObjLit" || value.kind === "dynArrLit")
31
+ return value;
32
+ if (["record", "array", "object", "regex", "date", "bytes", "map", "set", "func", "classval"].includes(value.type.kind))
33
+ return value;
34
+ return null;
35
+ }
21
36
  function primitivePositionType(lowerer, type) {
22
37
  if (type.kind === "union") {
23
38
  return lowerer.unions.get(type.unionId)?.arms.every((arm) => primitivePositionType(lowerer, arm)) ?? false;
@@ -144,9 +159,6 @@ function lowerArrayJoinSeparator(lowerer, node, loc) {
144
159
  * directly from its IR return type. Fence element kinds ScrArr cannot hold
145
160
  * before constructing that array type. */
146
161
  function fenceProducedArrayElem(lowerer, node, producer, elem) {
147
- if (elem.kind === "dyn") {
148
- lowerer.unsupported("SC1090", node, `${producer} with a callback returning 'unknown'-typed values (the result array has no static element type — annotate the callback's return)`);
149
- }
150
162
  if (!isSupportedArrayElem(elem)) {
151
163
  lowerer.unsupported("SC1090", node, `${producer} with a callback returning '${lowerer.fmt(elem)}' values (arrays of this element kind have no representation — store the values individually)`);
152
164
  }
@@ -545,7 +557,12 @@ export function lowerArrayMethodCall(lowerer, call, access) {
545
557
  // IsArray says spread; no honest static answer exists.
546
558
  lowerer.unsupported("SC1090", argNode, "concat of a bare inner array onto an array-of-arrays (JS would SPREAD it one level — wrap it: a.concat([inner]))");
547
559
  }
548
- const arg = lowerer.lowerExpr(argNode);
560
+ // Declaration-backed JS methods can return checked values even
561
+ // when their public signature names a concrete array. Validate
562
+ // that boundary before spreading the represented elements.
563
+ let arg = lowerer.lowerExpr(argNode);
564
+ if (arg.type.kind === "dyn")
565
+ arg = lowerer.coerceInto(argNode, arg, argArrayType);
549
566
  if (arg.type.kind !== "array")
550
567
  lowerer.badType(argNode, lowerer.typeOf(argNode));
551
568
  shape.push("a");
@@ -615,6 +632,12 @@ export function lowerArrayMethodCall(lowerer, call, access) {
615
632
  return { kind: "arrIntrinsic", method: "shift", receiver, args: [], type: arrayValueType(lowerer, elem), loc };
616
633
  }
617
634
  if (name === "join") {
635
+ if (elem.kind === "dyn") {
636
+ const receiver = lowerer.coerceToExpected(lowerer.lowerExpr(access.expression), DYN);
637
+ const args = call.arguments.length ? [lowerer.lowerExprExpecting(call.arguments[0], DYN)] : [];
638
+ return lowerer.coerceToExpected({ kind: "dynInvoke", recv: receiver, method: "join",
639
+ calleeName: access.getText(), args, type: DYN, loc }, STRING);
640
+ }
618
641
  // The ambient declares join on every Array<T> (a per-element-type
619
642
  // interface split isn't expressible there), so string-convertible
620
643
  // elements are enforced here: nested arrays would need JS's recursive
@@ -1686,6 +1709,9 @@ export function lowerTupleReadMethodCall(lowerer, call, access, tupleReceiver) {
1686
1709
  const ret = fnArg.type.ret;
1687
1710
  if (ret.kind === "void" || ret.kind === "func")
1688
1711
  lowerer.badType(call, lowerer.typeOf(call));
1712
+ if (method === "flatMap" && (ret.kind === "dyn" || ret.kind === "jsval" || (ret.kind === "record" && lowerer.shapes.get(ret.shapeId)?.tuple))) {
1713
+ return { kind: "dynInvoke", recv: { kind: "dynFrom", value: receiver, type: DYN, loc }, method: "flatMap", calleeName: access.getText(), args: [{ kind: "dynFrom", value: fnArg, type: DYN, loc }], type: DYN, loc };
1714
+ }
1689
1715
  if (method === "flatMap" && ret.kind === "union" && lowerer.unions.get(ret.unionId).arms.some(arm => arm.kind === "array")) {
1690
1716
  lowerer.noLowering("tuple .flatMap callback mixing array and scalar results", callback, "return an array from every path");
1691
1717
  }
@@ -1975,8 +2001,7 @@ function buildArrayHofFn(lowerer, name, method, elem, fnRet, arity, loc, outElem
1975
2001
  * undefined unit arm (for REF elements that arm is the unit instance, the
1976
2002
  * standard union machinery). The Last pair is the SAME loop walked
1977
2003
  * backwards (`i = n - 1; i >= 0; i--`), exactly the es2023 spec's
1978
- * descending index walk. All require a bool-returning callback
1979
- * (JS's ToBoolean of arbitrary predicate results has no lowering). */
2004
+ * descending index walk. Predicate results use JavaScript ToBoolean. */
1980
2005
  function lowerArrayFindLikeCall(lowerer, call, access, method, elem, bindUntyped = false) {
1981
2006
  const loc = locOf(call);
1982
2007
  const receiver = lowerer.lowerExpr(access.expression);
@@ -1991,7 +2016,7 @@ function lowerArrayFindLikeCall(lowerer, call, access, method, elem, bindUntyped
1991
2016
  // `packages.some((p) => p.scripts[name])` idiom, whose callback
1992
2017
  // returns the index read's `string | undefined`).
1993
2018
  const fnRet = fnArg.type.ret;
1994
- const truthyRet = fnRet.kind === "bool" || fnRet.kind === "f64" || fnRet.kind === "string" ||
2019
+ const truthyRet = fnRet.kind === "bool" || fnRet.kind === "f64" || fnRet.kind === "string" || fnRet.kind === "dyn" ||
1995
2020
  (fnRet.kind === "union" &&
1996
2021
  (lowerer.unions.get(fnRet.unionId)?.arms ?? []).every((a) => a.kind !== "dyn" && a.kind !== "caught" && a.kind !== "jsval"));
1997
2022
  if (!truthyRet)
@@ -2044,11 +2069,13 @@ function lowerArrayFindLikeCall(lowerer, call, access, method, elem, bindUntyped
2044
2069
  return { kind: "call", callee: helper, args: [receiver, fnArg], type: resultT, loc };
2045
2070
  }
2046
2071
  /** ToBoolean of a predicate result inside a synthesized HOF helper — the
2047
- * ensureBool subset the find-like path admits (bool through; f64/string/
2048
- * truthy-answerable unions via toBool). */
2072
+ * ensureBool subset the find-like path admits (bool through; checked
2073
+ * values via dynTest; f64/string/truthy-answerable unions via toBool). */
2049
2074
  function predToBool(e) {
2050
2075
  if (e.type.kind === "bool")
2051
2076
  return e;
2077
+ if (e.type.kind === "dyn")
2078
+ return { kind: "dynTest", test: "truthy", value: e, type: BOOL, loc: e.loc };
2052
2079
  return { kind: "toBool", operand: e, type: BOOL, loc: e.loc };
2053
2080
  }
2054
2081
  /** The find loop, from existing IR nodes:
@@ -2250,6 +2277,9 @@ function lowerArrayFlatMapCall(lowerer, call, access, elem) {
2250
2277
  lowerer.unsupported("SC1090", call, "this call form"); // tsc-guarded
2251
2278
  const { fnArg, arity } = hofCallbackArg(lowerer, argNode, [arrayValueType(lowerer, elem)], arrT);
2252
2279
  const fnRet = fnArg.type.ret;
2280
+ if (fnRet.kind === "dyn" || fnRet.kind === "jsval" || (fnRet.kind === "record" && lowerer.shapes.get(fnRet.shapeId)?.tuple)) {
2281
+ return { kind: "dynInvoke", recv: { kind: "dynFrom", value: receiver, liveRef: true, type: DYN, loc }, method: "flatMap", calleeName: access.getText(), args: [{ kind: "dynFrom", value: fnArg, type: DYN, loc }], type: DYN, loc };
2282
+ }
2253
2283
  if (fnRet.kind === "union") {
2254
2284
  const def = lowerer.unions.get(fnRet.unionId);
2255
2285
  if (def?.arms.some((a) => a.kind === "array")) {
@@ -2778,6 +2808,14 @@ export function lowerArrayConstructor(lowerer, expr, args) {
2778
2808
  lowerer.noLowering("Array constructor with spread arguments", expr);
2779
2809
  }
2780
2810
  let result = lowerer.mapTypeOf(lowerer.typeOf(expr));
2811
+ // Constructors without a concrete element layout keep their checked
2812
+ // reference. Known element forms retain native arrays, including their
2813
+ // existing sparse storage and indexed property contracts.
2814
+ if (!lowerer.dynamic && isJsSourceFile(expr.getSourceFile()) &&
2815
+ (result?.kind !== "array" || result.elem.kind === "dyn")) {
2816
+ return { kind: "dynCall", callee: { kind: "libCall", fn: "dyn.arrayConstructor", args: [], type: DYN, loc },
2817
+ calleeName: "Array", args: args.map((arg) => lowerer.lowerExprExpecting(arg, DYN)), type: DYN, loc };
2818
+ }
2781
2819
  if (result?.kind !== "array") {
2782
2820
  const contextual = lowerer.checker.getContextualType(expr);
2783
2821
  if (contextual)
@@ -2866,31 +2904,82 @@ export function lowerArrayOfCall(lowerer, call, access) {
2866
2904
  }
2867
2905
  /** Mapper-less checked Array.from: acquire once, then step through emitted
2868
2906
  * property and call dispatch so native class iterators retain their methods. */
2869
- function lowerCheckedArrayFrom(lowerer, source, loc) {
2907
+ export function lowerCheckedArrayFrom(lowerer, source, loc, mapper, receiver, numeric = false, iterable) {
2870
2908
  const iterator = lowerer.declareHiddenLocal("%fromIterator", DYN);
2871
2909
  const next = lowerer.declareHiddenLocal("%fromNext", DYN);
2872
2910
  const step = lowerer.declareHiddenLocal("%fromStep", DYN);
2873
2911
  const out = lowerer.declareHiddenLocal("%fromArray", DYN);
2874
2912
  const done = lowerer.declareHiddenLocal("%fromDone", BOOL);
2875
2913
  done.mutable = true;
2914
+ const index = mapper ? lowerer.declareHiddenLocal("%fromIndex", F64) : null;
2915
+ if (index)
2916
+ index.mutable = true;
2876
2917
  const get = (value, key) => ({ kind: "dynKeyGet", value, key: strLit(key, loc), type: DYN, loc });
2918
+ const item = get(varRef(step.id, DYN, loc), "value");
2919
+ const mapped = mapper && index ? { kind: "ternary", cond: { kind: "dynTest", test: "undefined", value: mapper, type: BOOL, loc },
2920
+ then: item, else_: { kind: "dynCall", callee: mapper, ...(receiver ? { receiver } : {}), calleeName: "Array.from mapper", args: [item, lowerer.coerceToExpected(varRef(index.id, F64, loc), DYN)], type: DYN, loc }, type: DYN, loc } : item;
2921
+ const element = numeric ? lowerer.coerceToExpected({ kind: "libCall", fn: "dyn.toNumberCoerce", args: [mapped], type: F64, loc }, DYN) : mapped;
2922
+ let append = { kind: "exprStmt", expr: { kind: "dynInvoke", recv: varRef(out.id, DYN, loc), method: "push", calleeName: "Array.from", args: [element], type: DYN, loc }, loc };
2923
+ if (mapper) {
2924
+ const error = lowerer.declareHiddenLocal("%fromError", CAUGHT);
2925
+ const close = lowerer.declareHiddenLocal("%fromReturn", DYN);
2926
+ append = { kind: "tryCatch", tryBody: [append], catchLocalId: error.id, finallyBody: null, loc, catchBody: [
2927
+ { kind: "tryCatch", catchLocalId: null, catchBody: [], finallyBody: null, loc, tryBody: [
2928
+ { kind: "varDecl", localId: close.id, init: get(varRef(iterator.id, DYN, loc), "return"), loc },
2929
+ { kind: "if", cond: { kind: "dynTest", test: "function", value: varRef(close.id, DYN, loc), type: BOOL, loc }, then: [
2930
+ { kind: "exprStmt", expr: { kind: "dynCall", callee: varRef(close.id, DYN, loc), receiver: varRef(iterator.id, DYN, loc), calleeName: "iterator.return", args: [], type: DYN, loc }, loc },
2931
+ ], else_: null, loc },
2932
+ ] },
2933
+ { kind: "rethrow", localId: error.id, loc },
2934
+ ] };
2935
+ }
2877
2936
  const stmts = [
2878
- { kind: "varDecl", localId: iterator.id, init: { kind: "libCall", fn: "dyn.iteratorResult", args: [{ kind: "libCall", fn: "dyn.arrayFromIterator", args: [source], type: DYN, loc }], type: DYN, loc }, loc },
2937
+ ...(mapper ? [{ kind: "if", cond: { kind: "dynTest", test: "undefined", value: mapper, type: BOOL, loc }, then: [], else_: [
2938
+ { kind: "if", cond: { kind: "dynTest", test: "function", value: mapper, type: BOOL, loc }, then: [], else_: [
2939
+ { kind: "exprStmt", expr: nodeThrowExpr(1, "", "Array.from mapper is not a function", DYN, loc), loc },
2940
+ ], loc },
2941
+ ], loc }] : []),
2942
+ { kind: "varDecl", localId: iterator.id, init: { kind: "libCall", fn: "dyn.iteratorResult", args: [{ kind: "libCall", fn: iterable ? "dyn.iterator" : "dyn.arrayFromIterator", args: iterable ? [source, iterable] : [source], type: DYN, loc }], type: DYN, loc }, loc },
2879
2943
  { kind: "varDecl", localId: next.id, init: get(varRef(iterator.id, DYN, loc), "next"), loc },
2880
2944
  { kind: "varDecl", localId: out.id, init: { kind: "dynArrLit", elems: [], type: DYN, loc }, loc },
2881
2945
  { kind: "varDecl", localId: done.id, init: boolLit(false, loc), loc },
2946
+ ...(index ? [{ kind: "varDecl", localId: index.id, init: numLit(0, loc), loc }] : []),
2882
2947
  { kind: "while", cond: { kind: "unary", op: "!", operand: varRef(done.id, BOOL, loc), type: BOOL, loc }, body: [
2883
2948
  { kind: "varDecl", localId: step.id, init: { kind: "libCall", fn: "dyn.iteratorResult", args: [{
2884
2949
  kind: "dynCall", callee: varRef(next.id, DYN, loc), receiver: varRef(iterator.id, DYN, loc), calleeName: "iterator.next", args: [], type: DYN, loc,
2885
2950
  }], type: DYN, loc }, loc },
2886
2951
  { kind: "assign", localId: done.id, value: { kind: "dynTest", test: "truthy", value: get(varRef(step.id, DYN, loc), "done"), type: BOOL, loc }, loc },
2887
2952
  { kind: "if", cond: { kind: "unary", op: "!", operand: varRef(done.id, BOOL, loc), type: BOOL, loc }, then: [
2888
- { kind: "exprStmt", expr: { kind: "dynInvoke", recv: varRef(out.id, DYN, loc), method: "push", calleeName: "Array.from", args: [get(varRef(step.id, DYN, loc), "value")], type: DYN, loc }, loc },
2953
+ append,
2954
+ ...(index ? [{ kind: "assign", localId: index.id, value: { kind: "bin", op: "+", left: varRef(index.id, F64, loc), right: numLit(1, loc), type: F64, loc }, loc }] : []),
2889
2955
  ], else_: null, loc },
2890
2956
  ], loc },
2891
2957
  ];
2892
2958
  return { kind: "seqExpr", stmts, result: varRef(out.id, DYN, loc), type: DYN, loc };
2893
2959
  }
2960
+ export function lowerArrayFromValue(lowerer, loc) {
2961
+ const name = "%builtin.Array.from";
2962
+ if (!lowerer.liftedFns.some((fn) => fn.name === name)) {
2963
+ const context = newFnCtx(false, null, null, DYN);
2964
+ lowerer.fnStack.push(context);
2965
+ try {
2966
+ const params = ["source", "options"].map((name) => {
2967
+ const local = lowerer.declareHiddenLocal(name, DYN);
2968
+ return { localId: local.id, name, type: DYN };
2969
+ });
2970
+ const [source, options] = params.map((p) => varRef(p.localId, DYN, loc));
2971
+ const argument = (index) => ({ kind: "dynKeyGet", value: options, key: strLit(index, loc), type: DYN, loc });
2972
+ const value = lowerCheckedArrayFrom(lowerer, source, loc, argument("0"), argument("1"));
2973
+ const constructorCheck = { kind: "if", cond: { kind: "dynTest", test: "function", value: { kind: "libCall", fn: "dyn.this", args: [], type: DYN, loc }, type: BOOL, loc },
2974
+ then: [{ kind: "runtimeFence", code: "SC2020", message: "Array.from with a custom constructor receiver is not supported", loc }], else_: null, loc };
2975
+ lowerer.liftedFns.push({ name, params, returnType: DYN, locals: context.locals, body: [constructorCheck, ...value.stmts, { kind: "return", value: value.result, loc }], loc });
2976
+ }
2977
+ finally {
2978
+ lowerer.fnStack.pop();
2979
+ }
2980
+ }
2981
+ return { kind: "dynFrom", value: { kind: "closure", fnName: name, captures: [], type: { kind: "func", params: [DYN], ret: DYN, rest: true }, loc }, fnName: "from", type: DYN, loc };
2982
+ }
2894
2983
  /** `Array.from({ length: n }, mapfn)` — the counted-generation idiom — on
2895
2984
  * THE stdlib Array global. The source must be an OBJECT LITERAL whose
2896
2985
  * single property is `length` (the shape the idiom always spells; the
@@ -2914,6 +3003,28 @@ export function lowerArrayFromCall(lowerer, call, access) {
2914
3003
  return null;
2915
3004
  const loc = locOf(call);
2916
3005
  const args = call.arguments;
3006
+ if (isJsSourceFile(call.getSourceFile()) && args.length >= 1 && args.length <= 3 && !args.some(ts.isSpreadElement)) {
3007
+ const name = "%builtin.Array.fromDirect";
3008
+ if (!lowerer.liftedFns.some((fn) => fn.name === name)) {
3009
+ const context = newFnCtx(false, null, null, DYN);
3010
+ lowerer.fnStack.push(context);
3011
+ try {
3012
+ const params = ["source", "mapper", "receiver"].map((name) => {
3013
+ const local = lowerer.declareHiddenLocal(name, DYN);
3014
+ return { localId: local.id, name, type: DYN };
3015
+ });
3016
+ const refs = params.map((param) => varRef(param.localId, DYN, loc));
3017
+ const value = lowerCheckedArrayFrom(lowerer, refs[0], loc, refs[1], refs[2]);
3018
+ lowerer.liftedFns.push({ name, params, returnType: DYN, locals: context.locals,
3019
+ body: [...value.stmts, { kind: "return", value: value.result, loc }], loc });
3020
+ }
3021
+ finally {
3022
+ lowerer.fnStack.pop();
3023
+ }
3024
+ }
3025
+ return { kind: "call", callee: name, args: [0, 1, 2].map((i) => args[i]
3026
+ ? lowerer.lowerExprExpecting(args[i], DYN) : dynUndefinedExpr(loc)), type: DYN, loc };
3027
+ }
2917
3028
  // MAPPER-LESS `Array.from({ length: n })` (usually with an explicit
2918
3029
  // type argument — the pMap results-array idiom): a length-n array of
2919
3030
  // ABSENT slots, filled by index before any read. Union elements with
@@ -3211,7 +3322,7 @@ export function lowerMapMethodCall(lowerer, call, access) {
3211
3322
  if (lowerer.chainBlocked(access, call))
3212
3323
  return null;
3213
3324
  const name = access.name.text;
3214
- if (!MAP_METHODS.has(name) && !MAP_ITER_METHODS.has(name))
3325
+ if (!MAP_METHODS.has(name))
3215
3326
  return null;
3216
3327
  let receiverIr = lowerer.mapTypeOf(lowerer.typeOf(access.expression));
3217
3328
  let probedUntyped = false;
@@ -3225,14 +3336,11 @@ export function lowerMapMethodCall(lowerer, call, access) {
3225
3336
  if (receiverIr?.kind !== "map")
3226
3337
  return null;
3227
3338
  // Collection views can refine has() while retaining its native ABI.
3228
- if (!lowerer.isStdlibMember(access) && name !== "has")
3339
+ if (!probedUntyped && !lowerer.isStdlibMember(access) && name !== "has")
3229
3340
  return null;
3230
3341
  const loc = locOf(call);
3231
3342
  const value = lowerer.lowerExpr(access.expression);
3232
3343
  const receiver = lowerer.runtimeOptionalPropertyReceiver(access.expression, value, receiverIr, name) ?? value;
3233
- // The lib's `set` returns the Map (chaining typechecks); the lowered
3234
- // set is a void statement, so a chained receiver has no value — fence
3235
- // it instead of emitting a void receiver.
3236
3344
  if (receiver.type.kind !== "map") {
3237
3345
  lowerer.noLowering("chained Map method calls", access.expression, "the lowered set() produces no value — call each set(k, v) as its own statement");
3238
3346
  }
@@ -3256,7 +3364,12 @@ export function lowerMapMethodCall(lowerer, call, access) {
3256
3364
  const v = receiverIr.value.kind === "dyn"
3257
3365
  ? lowerer.lowerCollectionKey(call.arguments[1], receiverIr.value)
3258
3366
  : lowerer.lowerExprExpecting(call.arguments[1], receiverIr.value);
3259
- return { kind: "mapIntrinsic", method: "set", receiver, args: [k, v], type: VOID, loc };
3367
+ const slot = lowerer.declareHiddenLocal("%mapSetReceiver", receiver.type);
3368
+ const ref = varRef(slot.id, receiver.type, loc);
3369
+ return { kind: "seqExpr", stmts: [
3370
+ { kind: "varDecl", localId: slot.id, init: receiver, loc },
3371
+ { kind: "exprStmt", expr: { kind: "mapIntrinsic", method: "set", receiver: ref, args: [k, v], type: VOID, loc }, loc },
3372
+ ], result: ref, type: receiver.type, loc };
3260
3373
  }
3261
3374
  if (name === "has" || name === "delete") {
3262
3375
  const k = lowerer.lowerCollectionKey(call.arguments[0], receiverIr.key);
@@ -3265,31 +3378,39 @@ export function lowerMapMethodCall(lowerer, call, access) {
3265
3378
  if (name === "clear") {
3266
3379
  return { kind: "mapIntrinsic", method: "clear", receiver, args: [], type: VOID, loc };
3267
3380
  }
3268
- if (MAP_ITER_METHODS.has(name)) {
3381
+ if (COLLECTION_ITERATOR_METHODS.has(name)) {
3269
3382
  return lowerMapIterDrainCall(lowerer, call, receiver, receiverIr, name);
3270
3383
  }
3271
3384
  // forEach
3272
3385
  return lowerMapForEachCall(lowerer, call, receiver, receiverIr, probedUntyped);
3273
3386
  }
3274
- /** The iterator methods the lowering DOES cover — in exactly one context. */
3275
- const MAP_ITER_METHODS = new Set(["keys", "values", "entries"]);
3387
+ /** Stored collection iterators retain the native collection by reference. The
3388
+ * checked-value runtime supplies the live cursor without embedding an engine. */
3389
+ function lowerCollectionIteratorCall(lowerer, call, receiver, method) {
3390
+ const access = call.expression;
3391
+ if (!ts.isPropertyAccessExpression(access))
3392
+ throw new InternalCompilerError("collection iterator requires a member call");
3393
+ const boxed = lowerer.coerceInto(access.expression, receiver, DYN);
3394
+ const result = lowerDynDispatchMethodCall(lowerer, call, access, boxed, false);
3395
+ if (!result)
3396
+ throw new InternalCompilerError(`missing collection iterator dispatch: ${method}`);
3397
+ return result;
3398
+ }
3276
3399
  /** `[...m.keys()]` / `[...m.values()]` / `[...m.entries()]` — the iterator
3277
- * methods, lowered ONLY as the operand of a spread inside an array
3400
+ * methods use an optimized drain as the operand of a spread inside an array
3278
3401
  * literal, where JS drains the iterator on the spot. The call desugars to
3279
3402
  * a direct call of a synthetic drain function whose loop walks the same
3280
3403
  * iteration primitives as the forEach desugar and pushes each live entry
3281
3404
  * into a fresh array — key, value, or `[K, V]` tuple record per method.
3282
3405
  * No user code runs mid-drain (and nothing here mutates the map), so no
3283
3406
  * compaction can shift indices: the enter/exit bracket is unnecessary and
3284
- * the snapshot IS what JS's immediate drain observes. Every other context
3285
- * (storing the iterator, .next(), passing it along) would need a real
3286
- * iterator value — fenced with the spread spelling as the hint. */
3407
+ * the snapshot IS what JS's immediate drain observes. Other contexts keep
3408
+ * a live iterator through the native checked-value runtime. */
3287
3409
  function lowerMapIterDrainCall(lowerer, call, receiver, mapT, method) {
3288
3410
  const loc = locOf(call);
3289
3411
  const inArraySpread = ts.isSpreadElement(call.parent) && ts.isArrayLiteralExpression(call.parent.parent);
3290
- if (!inArraySpread) {
3291
- lowerer.noLowering(`.${method}() outside an immediate array spread`, call, `iterator objects have no lowering — drain it into an array where it is made: [...m.${method}()]`);
3292
- }
3412
+ if (!inArraySpread)
3413
+ return lowerCollectionIteratorCall(lowerer, call, receiver, method);
3293
3414
  // The pushed element type. For entries the checker's own element type —
3294
3415
  // the [K, V] tuple behind MapIterator<[K, V]> — carries the interned
3295
3416
  // tuple shape the surrounding literal will intern too.
@@ -3612,21 +3733,24 @@ export function lowerSetMethodCall(lowerer, call, access) {
3612
3733
  if (!SET_METHODS.has(name) && !SET_COMBINE_METHODS.has(name))
3613
3734
  return null;
3614
3735
  let receiverIr = lowerer.mapTypeOf(lowerer.typeOf(access.expression));
3736
+ let probedUntyped = false;
3615
3737
  // The identity-Set idiom (JS): the CHECKER type is an unmappable
3616
3738
  // Set<union-of-signatures>, but the VALUE lowered as a real Set of
3617
3739
  // identity tokens (the new-Set probe) — the lowered receiver's type
3618
3740
  // is the honest dispatch key.
3619
3741
  if (receiverIr?.kind !== "set" && isJsSourceFile(access.getSourceFile())) {
3620
3742
  const probed = tryLowerExpression(lowerer, access.expression);
3621
- if (probed?.type.kind === "set")
3743
+ if (probed?.type.kind === "set") {
3622
3744
  receiverIr = probed.type;
3745
+ probedUntyped = true;
3746
+ }
3623
3747
  }
3624
3748
  if (receiverIr?.kind !== "set")
3625
3749
  return null;
3626
3750
  // A collection interface may refine has() into a type predicate.
3627
3751
  // Type mapping checked that view's native ABI; the value check below
3628
3752
  // still rejects structural mocks and assertions over other objects.
3629
- if (!lowerer.isStdlibMember(access) && name !== "has")
3753
+ if (!probedUntyped && !lowerer.isStdlibMember(access) && name !== "has")
3630
3754
  return null;
3631
3755
  const loc = locOf(call);
3632
3756
  const value = lowerer.lowerExpr(access.expression);
@@ -3639,6 +3763,9 @@ export function lowerSetMethodCall(lowerer, call, access) {
3639
3763
  if (name === "forEach" && call.arguments.length !== 1) {
3640
3764
  lowerer.noLowering(`.forEach with ${call.arguments.length} arguments`, call, "the thisArg parameter has no lowering — use an arrow function");
3641
3765
  }
3766
+ if (COLLECTION_ITERATOR_METHODS.has(name)) {
3767
+ return lowerCollectionIteratorCall(lowerer, call, receiver, name);
3768
+ }
3642
3769
  if (SET_COMBINE_METHODS.has(name)) {
3643
3770
  return lowerSetCombineCall(lowerer, call, name, receiver, receiverIr);
3644
3771
  }
@@ -5067,22 +5194,12 @@ function lowerForOfMapOrSet(lowerer, stmt, iterable, contT, proj) {
5067
5194
  }
5068
5195
  }
5069
5196
  else {
5070
- // Identifier heads and the remaining patterns bind through the
5071
- // checker's own element type — the [K, V] tuple for pair yields,
5072
- // T otherwise — built/read once into a hidden per-iteration
5073
- // local, the array for-of's exact desugar.
5074
- const elemT = lowerer.mapTypeOf(lowerer.checker.getTypeAtLocation(decl.name));
5075
- if (yieldsPair) {
5076
- const shape = elemT?.kind === "record" ? lowerer.shapes.get(elemT.shapeId) : null;
5077
- if (elemT?.kind !== "record" || !shape?.tuple || shape.fields.length !== 2 ||
5078
- !typeEquals(shape.fields.find((f) => f.name === "0").type, keyT) ||
5079
- !typeEquals(shape.fields.find((f) => f.name === "1").type, secondT)) {
5080
- lowerer.badType(decl.name, lowerer.checker.getTypeAtLocation(decl.name)); // defensive: the lib declares [K, V]
5081
- }
5082
- }
5083
- else if (!elemT || !typeEquals(elemT, singleT)) {
5084
- lowerer.badType(decl.name, lowerer.checker.getTypeAtLocation(decl.name)); // defensive: the lib declares T
5085
- }
5197
+ // Derive the yielded layout from the represented container. JS
5198
+ // inference can leave the pattern at any even when the Map's
5199
+ // native key/value types are known after specialization.
5200
+ const elemT = yieldsPair
5201
+ ? { kind: "record", shapeId: lowerer.shapes.intern([{ name: "0", type: keyT }, { name: "1", type: secondT }], true) }
5202
+ : singleT;
5086
5203
  const elemInit = yieldsPair
5087
5204
  ? {
5088
5205
  kind: "recordLit",
@@ -5253,8 +5370,8 @@ export function lowerSetSeedNew(lowerer, node, setT) {
5253
5370
  (source.type.kind === "dyn" || source.type.kind === "jsval")) {
5254
5371
  source = lowerer.coerceInto(node, source, STRING);
5255
5372
  }
5256
- if (source.type.kind === "dyn" && setT.elem.kind === "dyn") {
5257
- return { kind: "dynCheck", value: { kind: "libCall", fn: "dyn.nativeSetNew", args: [source], type: DYN, loc }, type: setT, loc };
5373
+ if (setT.elem.kind === "dyn" && lowerer.dynConvertible(source.type)) {
5374
+ return { kind: "dynCheck", value: { kind: "libCall", fn: "dyn.nativeSetNew", args: [lowerer.coerceInto(node, source, DYN)], type: DYN, loc }, type: setT, loc };
5258
5375
  }
5259
5376
  if (declared?.kind === "array" && typeEquals(declared.elem, setT.elem)) {
5260
5377
  // Preserve the existing checked scalar-iterable bridge. Reference
@@ -5447,7 +5564,8 @@ function mapFromSeedValue(lowerer, seed, mapT) {
5447
5564
  }
5448
5565
  return { kind: "call", callee: name, args: [seed], type: mapT, loc };
5449
5566
  }
5450
- if (seed.type.kind === "dyn" || seed.type.kind === "array" && seed.type.elem.kind === "dyn") {
5567
+ if (seed.type.kind === "dyn" || seed.type.kind === "array" &&
5568
+ !(seed.type.elem.kind === "record" && lowerer.shapes.get(seed.type.elem.shapeId)?.tuple)) {
5451
5569
  const key = `checked-seed:${typeKey(mapT)}`;
5452
5570
  let name = lowerer.mapHofHelpers.get(key);
5453
5571
  if (!name) {
@@ -5802,6 +5920,9 @@ function lowerTypedObjectFromEntriesCall(lowerer, call, callee) {
5802
5920
  const argIr = lowerer.mapTypeOf(lowerer.typeOf(argNode));
5803
5921
  if (argIr?.kind !== "array")
5804
5922
  return null;
5923
+ const represented = tryLowerExpression(lowerer, argNode);
5924
+ if (represented && !typeEquals(represented.type, argIr))
5925
+ return null;
5805
5926
  // `Object.fromEntries(rows)` over a `string[][]` VALUE — the env-line
5806
5927
  // idiom (`envArray.map((env) => env.split('='))`). The checker has no
5807
5928
  // tuple to type here (string[] misses the lib's [PropertyKey, T]