@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,3 +1,4 @@
1
+ import { everyStmtList, everyTypeChild } from "../../ir/traverse.js";
1
2
  import { InternalCompilerError } from "../../errors.js";
2
3
  /* Module-graph lowering: splitting each source file into its parts, the
3
4
  * program-collection pass (signatures, classes, globals — reachability
@@ -16,16 +17,16 @@ import { BOOL, DYN, F64, JSVAL, RUNTIME_ERROR_CLASSES, STRING, VOID, arrayOf, ca
16
17
  import { ENTRY_NAME, PoisonError, boundIdentifiersOf, dynFallbackType, dynUndefinedExpr, importCallHandleType, newFnCtx, staticImportNamespaceType, uncheckedOverloadHandleCall } from "./lowerer.js";
17
18
  import { isNativeFfiRequire, builtinMemberRequireDecl, builtinNamespaceDestructureModuleOf, createRequireBindingDecl, createRequireNamespaceDecl, createRequireProgramModuleDecl, createRequireSpecOf, isPromisifyCall, registerBuiltinCallableAlias, stripTypeCasts } from "./lower-builtins.js";
18
19
  import { bindingContextualGenericFnNodeOf, bindingGenericFnAliasInfoOf, bindingGenericFnInfoOf, bindingGenericFnNodeOf, bindingNeverReassigned, deadUnmappableBinding, funcTypeFromParamShapes, implicitLocalFnInfoOf, implicitLocalFnNodeOf, nullishGenericBindingUnitOf, registerOverloadedCallableAlias } from "./lower-calls.js";
19
- import { hasJsTypeAnnotation, isVarDeclared, numericIteratorSourceOf, provenanceElidedConstDecl } from "./lower-stmts.js";
20
- import { objectFactorySignature } from "./object-factory-new.js";
20
+ import { jsBindingHasOpenWrites, hasJsTypeAnnotation, isVarDeclared, numericIteratorSourceOf, provenanceElidedConstDecl } from "./lower-stmts.js";
21
+ import { objectFactoryGlobalType } from "./object-factory-new.js";
21
22
  import { streamClassAliasDecl } from "./lower-stream.js";
22
23
  import { stdlibGlobalAliasDecl, stdlibGlobalAliasNameOf, stdlibGlobalNameOf } from "./surfaces.js";
23
24
  import { isNativeBuiltinValueInitializer } from "./lower-builtin-values.js";
24
- import { collectNamespaceStmt, nsPathPrefix, trapDeclRootOf } from "./lower-namespaces.js";
25
+ import { collectNamespaceStmt, nsMemberIdentOf, nsPathPrefix, trapDeclRootOf } from "./lower-namespaces.js";
25
26
  import { collectExpandoMembers } from "./lower-expando.js";
26
27
  import { recordTextCodecClass } from "../../ir/ir.js";
27
28
  import { isUnitOnlyTsType, unitOnlyUnion } from "../type-mapper.js";
28
- import { collectVirtualJsMethods, decoratorNodesOf, genericIfaceBindingKeepsClass, guaranteedDecorationThrow } from "./lower-classes.js";
29
+ import { collectInheritedJsFieldWrites, collectVirtualJsMethods, decoratorNodesOf, genericIfaceBindingKeepsClass, guaranteedDecorationThrow, storedClassValueType } from "./lower-classes.js";
29
30
  import { isMixinFnBinding, mixinResultBindingClassOf } from "./lower-mixins.js";
30
31
  import { cjsModuleRef, cjsModuleRegistryPrelude } from "./lower-node-module.js";
31
32
  import { forkTargetPaths } from "../fork-target.js";
@@ -228,12 +229,42 @@ export function appendDynamicImportModules(program, order, onCycle) {
228
229
  * signatures are cheap and calls resolve against them; only BODY lowering
229
230
  * is reachability-gated. */
230
231
  export function collectProgram(lowerer, parts) {
232
+ const computed = new Set();
233
+ for (const fp of parts)
234
+ for (const decl of fp.classDecls) {
235
+ const heritage = decl.heritageClauses?.find((clause) => clause.token === ts.SyntaxKind.ExtendsKeyword)?.types[0]?.expression;
236
+ if (heritage && ts.isCallExpression(heritage))
237
+ computed.add(decl);
238
+ }
239
+ // Descendants need the computed ancestor's completed layout before
240
+ // their own fields and inherited methods can be collected.
241
+ const computedSymbols = new Set([...computed].map((decl) => declSymbolOf(lowerer, decl)).filter((symbol) => symbol !== undefined));
242
+ let expanded = true;
243
+ while (expanded) {
244
+ expanded = false;
245
+ for (const fp of parts)
246
+ for (const decl of fp.classDecls) {
247
+ if (computed.has(decl))
248
+ continue;
249
+ const heritage = decl.heritageClauses?.find((clause) => clause.token === ts.SyntaxKind.ExtendsKeyword)?.types[0]?.expression;
250
+ const base = heritage && ts.isIdentifier(heritage) ? lowerer.resolveValueSymbol(heritage) : undefined;
251
+ if (!base || !computedSymbols.has(base))
252
+ continue;
253
+ computed.add(decl);
254
+ const symbol = declSymbolOf(lowerer, decl);
255
+ if (symbol)
256
+ computedSymbols.add(symbol);
257
+ expanded = true;
258
+ }
259
+ }
231
260
  lowerer.collecting = true;
232
261
  try {
233
262
  collectVirtualJsMethods(lowerer, parts.map((part) => part.sf));
263
+ collectInheritedJsFieldWrites(lowerer, parts.map((part) => part.sf));
234
264
  for (const fp of parts)
235
265
  for (const decl of fp.classDecls)
236
- lowerer.collectClassShape(decl);
266
+ if (!computed.has(decl))
267
+ lowerer.collectClassShape(decl);
237
268
  for (const fp of parts)
238
269
  for (const decl of fp.fnDecls)
239
270
  lowerer.collectSignature(decl);
@@ -263,6 +294,60 @@ export function collectProgram(lowerer, parts) {
263
294
  lowerer.collectNpmImports(parts);
264
295
  lowerer.collectJsonImports(parts);
265
296
  }
297
+ for (const decl of computed) {
298
+ const symbol = declSymbolOf(lowerer, decl);
299
+ const wasCollecting = lowerer.collecting;
300
+ lowerer.collecting = true;
301
+ const previousSink = lowerer.diagSink;
302
+ const deferred = [];
303
+ lowerer.diagSink = deferred;
304
+ const expression = decl.heritageClauses.find((clause) => clause.token === ts.SyntaxKind.ExtendsKeyword).types[0].expression;
305
+ const context = newFnCtx(false, null, null, DYN);
306
+ lowerer.fnStack.push(context);
307
+ try {
308
+ let value = lowerer.lowerExpr(expression);
309
+ const known = value.type.kind === "dyn" ? storedClassValueType(lowerer, expression) : null;
310
+ if (known?.kind === "classval")
311
+ value = lowerer.coerceToExpected(value, known);
312
+ if (value.type.kind === "dyn" || value.type.kind === "func") {
313
+ const name = `%class.base.${lowerer.classNamer(decl)}`;
314
+ const loc = locOf(expression);
315
+ lowerer.liftedFns.push({ name, params: [], returnType: value.type, locals: context.locals,
316
+ body: [{ kind: "return", value, loc }], loc });
317
+ lowerer.computedCallableBases.set(decl, { kind: "call", callee: name, args: [], type: value.type, loc });
318
+ }
319
+ if (value.type.kind === "classval") {
320
+ const classInfo = lowerer.classes.get(value.type.className);
321
+ if (classInfo) {
322
+ const name = `%class.base.${lowerer.classNamer(decl)}`;
323
+ const loc = locOf(expression);
324
+ lowerer.liftedFns.push({ name, params: [], returnType: value.type, locals: context.locals,
325
+ body: [{ kind: "return", value, loc }], loc });
326
+ lowerer.computedClassBases.set(lowerer.classNamer(decl), { value: { kind: "call", callee: name, args: [], type: value.type, loc }, classInfo });
327
+ }
328
+ }
329
+ }
330
+ catch (error) {
331
+ if (!(error instanceof PoisonError))
332
+ throw error;
333
+ }
334
+ finally {
335
+ lowerer.fnStack.pop();
336
+ lowerer.diagSink = previousSink;
337
+ }
338
+ lowerer.diagSink = deferred;
339
+ try {
340
+ lowerer.collectClassShape(decl);
341
+ }
342
+ finally {
343
+ lowerer.diagSink = previousSink;
344
+ }
345
+ if (symbol && deferred.length) {
346
+ lowerer.deferredDiags.set(symbol, [...(lowerer.deferredDiags.get(symbol) ?? []), ...deferred]);
347
+ lowerer.deferredClassByName.set(lowerer.classNamer(decl), symbol);
348
+ }
349
+ lowerer.collecting = wasCollecting;
350
+ }
266
351
  }
267
352
  /** The npm-import chokepoint, run once per pass during collection (so
268
353
  * bodies lowered in ANY pass resolve the bindings). In a static build
@@ -640,49 +725,172 @@ export function collectJsonImports(lowerer, parts) {
640
725
  /** The classes, records, and unions the emitted module carries: exactly
641
726
  * what the lowered functions and globals reference, closed transitively
642
727
  * over record fields, union arms, class field types, base chains, and
643
- * WHOLE hierarchies (hierarchy membership decides object layout:
644
- * dropping an unused subclass must not turn its base into a standalone
645
- * class at emit time). Registry entries interned while collecting
728
+ * constructible descendants and their base chains. Registry entries interned while collecting
646
729
  * signatures nothing reaches stay out — an unreached type leaves no
647
730
  * trace. A referenced class with no registration had its collection
648
731
  * deferred: the reference flushes those diagnostics. Methods whose
649
732
  * bodies were not lowered leave the def's method list, so vtable slots
650
733
  * exist exactly for emitted overrides. */
651
734
  export function moduleArtifacts(lowerer, functions) {
735
+ const valueInstanceOfRoots = new Set();
652
736
  const classNames = new Set();
653
737
  const shapeIds = new Set();
654
738
  const unionIds = new Set();
655
739
  const pendingClasses = [];
656
740
  const pendingShapes = [];
657
741
  const pendingUnions = [];
658
- const visit = (node) => {
659
- if (Array.isArray(node)) {
660
- for (const item of node)
661
- visit(item);
662
- return;
742
+ const boxedChild = (type, seen = new Set()) => {
743
+ switch (type.kind) {
744
+ case "child": return true;
745
+ case "array":
746
+ case "set": return boxedChild(type.elem, seen);
747
+ case "promise": return boxedChild(type.inner, seen);
748
+ case "map": return boxedChild(type.key, seen) || boxedChild(type.value, seen);
749
+ case "func": return boxedChild(type.ret, seen);
750
+ case "record":
751
+ if (seen.has(type.shapeId))
752
+ return false;
753
+ seen.add(type.shapeId);
754
+ return lowerer.shapes.get(type.shapeId)?.fields.some((field) => boxedChild(field.type, seen)) ?? false;
755
+ case "union":
756
+ if (seen.has(type.unionId))
757
+ return false;
758
+ seen.add(type.unionId);
759
+ return lowerer.unions.get(type.unionId)?.arms.some((arm) => boxedChild(arm, seen)) ?? false;
760
+ default: return false;
663
761
  }
664
- if (node === null || typeof node !== "object")
762
+ };
763
+ const visitClass = (name) => {
764
+ if (classNames.has(name))
665
765
  return;
666
- const rec = node;
667
- if (typeof rec["className"] === "string" && !classNames.has(rec["className"])) {
668
- classNames.add(rec["className"]);
669
- pendingClasses.push(rec["className"]);
670
- }
671
- if (typeof rec["shapeId"] === "string" && !shapeIds.has(rec["shapeId"])) {
672
- shapeIds.add(rec["shapeId"]);
673
- pendingShapes.push(rec["shapeId"]);
674
- }
675
- if (typeof rec["unionId"] === "string" && !unionIds.has(rec["unionId"])) {
676
- unionIds.add(rec["unionId"]);
677
- pendingUnions.push(rec["unionId"]);
678
- }
679
- for (const key of Object.keys(rec)) {
680
- if (key !== "loc")
681
- visit(rec[key]);
766
+ classNames.add(name);
767
+ pendingClasses.push(name);
768
+ };
769
+ const visitShape = (id) => {
770
+ if (shapeIds.has(id))
771
+ return;
772
+ shapeIds.add(id);
773
+ pendingShapes.push(id);
774
+ };
775
+ const visitUnion = (id) => {
776
+ if (unionIds.has(id))
777
+ return;
778
+ unionIds.add(id);
779
+ pendingUnions.push(id);
780
+ };
781
+ const visitType = (type) => {
782
+ switch (type.kind) {
783
+ case "object":
784
+ case "classval":
785
+ visitClass(type.className);
786
+ break;
787
+ case "record":
788
+ visitShape(type.shapeId);
789
+ break;
790
+ case "union":
791
+ visitUnion(type.unionId);
792
+ break;
682
793
  }
794
+ return everyTypeChild(type, visitType);
795
+ };
796
+ const visitor = {
797
+ expr: (node) => {
798
+ visitType(node.type);
799
+ switch (node.kind) {
800
+ case "fieldIncDec":
801
+ case "new":
802
+ case "classRef":
803
+ case "instanceOf":
804
+ case "virtualCall":
805
+ case "fieldGet":
806
+ case "caughtCheck":
807
+ visitClass(node.className);
808
+ break;
809
+ case "caughtTest":
810
+ if (node.className !== undefined)
811
+ visitClass(node.className);
812
+ break;
813
+ case "recordGet":
814
+ case "recordKeyGet":
815
+ case "recordOvfKeys":
816
+ case "recordOvfHas":
817
+ visitShape(node.shapeId);
818
+ break;
819
+ case "unionWrap":
820
+ case "unionFuncEq":
821
+ case "unionNarrow":
822
+ case "unionDisc":
823
+ case "unionKeyGet":
824
+ case "unionIsTag":
825
+ case "unionEq":
826
+ visitUnion(node.unionId);
827
+ break;
828
+ case "yieldExpr":
829
+ if (node.captureCompletion !== undefined)
830
+ visitType(node.captureCompletion.returnType);
831
+ break;
832
+ case "instanceOfValue":
833
+ for (const type of [node.value.type, node.classValue.type]) {
834
+ if (type.kind !== "object" && type.kind !== "classval")
835
+ continue;
836
+ let root = lowerer.classes.get(type.className);
837
+ if (!root)
838
+ continue;
839
+ while (root.base)
840
+ root = root.base;
841
+ valueInstanceOfRoots.add(root.def.name);
842
+ }
843
+ break;
844
+ case "dynFrom":
845
+ if (boxedChild(node.value.type)) {
846
+ // A generic child can expose native stdio without importing stream.
847
+ visitClass("%Readable");
848
+ visitClass("%Writable");
849
+ }
850
+ break;
851
+ default:
852
+ // A new node with a named artifact reference must join this switch.
853
+ node;
854
+ }
855
+ return true;
856
+ },
857
+ stmt: (node) => {
858
+ switch (node.kind) {
859
+ case "fieldSet":
860
+ visitClass(node.className);
861
+ break;
862
+ case "recordSet":
863
+ case "recordKeySet":
864
+ case "recordKeyDelete":
865
+ visitShape(node.shapeId);
866
+ break;
867
+ default:
868
+ node;
869
+ }
870
+ return true;
871
+ },
683
872
  };
684
- visit(functions);
685
- visit(lowerer.globalsList);
873
+ // Visit compiler-owned typed storage and executable trees directly, without
874
+ // creating dynamic snapshots of every node's properties and metadata.
875
+ for (const fn of functions) {
876
+ for (const param of fn.params)
877
+ visitType(param.type);
878
+ visitType(fn.returnType);
879
+ for (const local of fn.locals)
880
+ visitType(local.type);
881
+ for (const capture of fn.captures ?? [])
882
+ visitType(capture.type);
883
+ for (const capture of fn.classCaptures ?? [])
884
+ visitType(capture.type);
885
+ if (fn.generator !== undefined) {
886
+ visitType(fn.generator.yieldT);
887
+ visitType(fn.generator.nextT);
888
+ visitType(fn.generator.resultType);
889
+ }
890
+ everyStmtList(fn.body, visitor);
891
+ }
892
+ for (const global of lowerer.globalsList)
893
+ visitType(global.type);
686
894
  // The builtin error classes ride EVERY module: the runtime's own throws
687
895
  // (JSON/dynCheck/regex failures) mint instances of them whether or not
688
896
  // user code mentions Error, and the uncaught printer tells Error
@@ -703,12 +911,19 @@ export function moduleArtifacts(lowerer, functions) {
703
911
  // overflow-valued shape (`{ [key: string]: {script?: string} }`)
704
912
  // references its value shape through indexValue alone.
705
913
  const shape = lowerer.shapes.get(pendingShapes.pop());
706
- visit(shape?.fields);
707
- if (shape?.indexValue)
708
- visit(shape.indexValue);
914
+ if (shape !== undefined) {
915
+ for (const field of shape.fields)
916
+ visitType(field.type);
917
+ if (shape.indexValue !== undefined)
918
+ visitType(shape.indexValue);
919
+ }
920
+ }
921
+ while (pendingUnions.length > 0) {
922
+ const union = lowerer.unions.get(pendingUnions.pop());
923
+ if (union !== undefined)
924
+ for (const arm of union.arms)
925
+ visitType(arm);
709
926
  }
710
- while (pendingUnions.length > 0)
711
- visit(lowerer.unions.get(pendingUnions.pop())?.arms);
712
927
  while (pendingClasses.length > 0) {
713
928
  const name = pendingClasses.pop();
714
929
  const info = lowerer.classes.get(name);
@@ -718,15 +933,17 @@ export function moduleArtifacts(lowerer, functions) {
718
933
  lowerer.flushDeferredClass(name);
719
934
  continue;
720
935
  }
721
- visit(info.def.fields);
936
+ for (const field of info.def.fields)
937
+ visitType(field.type);
722
938
  if (info.base)
723
- visit([{ className: info.base.def.name }]);
939
+ visitClass(info.base.def.name);
724
940
  if (lowerer.inHierarchy(info)) {
725
941
  let root = info;
726
942
  while (root.base)
727
943
  root = root.base;
728
944
  const wholeTree = (c) => {
729
- visit([{ className: c.def.name }]);
945
+ if (valueInstanceOfRoots.has(root.def.name) || lowerer.classCanBeConstructed(c))
946
+ visitClass(c.def.name);
730
947
  for (const s of c.subclasses)
731
948
  wholeTree(s);
732
949
  };
@@ -803,7 +1020,7 @@ function cjsScalarLiteral(e) {
803
1020
  * a checked-dynamic (or unit) value, so a DYN module global can hold it:
804
1021
  * no initializer, a unit literal, or a checker-`any` call/member/
805
1022
  * identifier read (any-typed operations lower through the checked-dynamic tree in JS).
806
- * `new` expressions stay OUT even when checker-any (`new Anon.Sub()` over
1023
+ * User-class `new` expressions stay OUT even when checker-any (`new Anon.Sub()` over
807
1024
  * an expando class member constructs a TYPED instance — corpus 2032), as
808
1025
  * does everything else (object/array literals have their own rules;
809
1026
  * typed-but-unmappable initializers keep the %init-local adoption). */
@@ -827,6 +1044,16 @@ function jsDynHoldableInitializer(lowerer, init) {
827
1044
  e = e.expression;
828
1045
  if (checkedGlobalReference(lowerer, e))
829
1046
  return true;
1047
+ if (ts.isCallExpression(e) && ts.isPropertyAccessExpression(e.expression) &&
1048
+ ["freeze", "seal", "preventExtensions"].includes(e.expression.name.text) &&
1049
+ lowerer.stdlibGlobalMember(e.expression, "Object") !== null && e.arguments[0] &&
1050
+ ts.isArrayLiteralExpression(e.arguments[0]))
1051
+ return true;
1052
+ // The built-in Array constructor can create an evolving array whose
1053
+ // inferred element type has no native mapping. Its checked reference
1054
+ // must remain shared with separately declared functions and aliases.
1055
+ if ((ts.isCallExpression(e) || ts.isNewExpression(e)) && lowerer.isStdlibGlobal(e.expression, "Array"))
1056
+ return true;
830
1057
  // JavaScript process streams lower to native checked handles even when
831
1058
  // their declared method overloads prevent a structural type mapping.
832
1059
  // Register the shared slot before separately declared functions lower.
@@ -834,6 +1061,8 @@ function jsDynHoldableInitializer(lowerer, init) {
834
1061
  const member = lowerer.stdlibGlobalMember(e, "process");
835
1062
  if (member === "stdin" || member === "stdout" || member === "stderr")
836
1063
  return true;
1064
+ if (e.name.text === "constructor" && lowerer.checker.getCallSignatures(lowerer.typeOf(e.expression)).length > 0)
1065
+ return true;
837
1066
  }
838
1067
  if (e.kind === ts.SyntaxKind.NullKeyword)
839
1068
  return true;
@@ -851,6 +1080,11 @@ function jsDynHoldableInitializer(lowerer, init) {
851
1080
  if ((ts.isPropertyAccessExpression(e) || ts.isElementAccessExpression(e)) &&
852
1081
  ts.isIdentifier(e.expression) && lowerer.globalOf(e.expression)?.type.kind === "dyn")
853
1082
  return true;
1083
+ if (ts.isPropertyAccessExpression(e)) {
1084
+ const member = nsMemberIdentOf(lowerer, e);
1085
+ if (member && (lowerer.globalOf(member)?.type.kind === "dyn" || lowerer.genericFnOf(member)?.implicitParams))
1086
+ return true;
1087
+ }
854
1088
  // Optional callable reads (for example descriptor?.get) can be held in
855
1089
  // the same checked slot as a callable. Their nullish arm must remain
856
1090
  // observable by functions declared outside the module initializer.
@@ -862,6 +1096,8 @@ function jsDynHoldableInitializer(lowerer, init) {
862
1096
  if (arms?.some(arm => arm.kind === "func") && arms.every(arm => isUnitType(arm) || (arm.kind === "func" && canBoxFuncIntoDyn(arm, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id)))))
863
1097
  return true;
864
1098
  }
1099
+ if ((ts.isFunctionExpression(e) || ts.isArrowFunction(e)) && !e.typeParameters?.length && isJsSourceFile(e.getSourceFile()))
1100
+ return true;
865
1101
  if (ts.isIdentifier(e) || ts.isArrowFunction(e) || ts.isFunctionExpression(e)) {
866
1102
  if (ts.isIdentifier(e)) {
867
1103
  if (lowerer.globalOf(e)?.type.kind === "dyn")
@@ -976,6 +1212,10 @@ export function collectGlobals(lowerer, sf, topStmts) {
976
1212
  let type = lowerer.mapTypeOf(tsType) ?? dynFallbackType(lowerer, stmt.expression, tsType);
977
1213
  if (type === null)
978
1214
  lowerer.badType(stmt.expression, tsType);
1215
+ // Inferred JavaScript factory exports keep their original value,
1216
+ // including callable objects decorated with Object.assign.
1217
+ if (isJsSourceFile(sf) && ts.isCallExpression(stmt.expression) && type.kind === "record" && lowerer.dynConvertible(type))
1218
+ type = DYN;
979
1219
  // `export default undefined` — the unit-only union, like any
980
1220
  // unit-only binding (`export default null` maps via mapType).
981
1221
  if (type.kind === "void" && isUnitOnlyTsType(tsType)) {
@@ -1024,16 +1264,9 @@ export function collectGlobals(lowerer, sf, topStmts) {
1024
1264
  const t = lowerer.mapTypeOf(strict) ?? dynFallbackType(lowerer, nameNode, strict);
1025
1265
  if (!t || t.kind === "void")
1026
1266
  lowerer.badType(typeNode, strict);
1027
- // `module.exports.Strings = Strings` naming a dyn-HOLDING
1028
- // const (the JS file-scope object-literal identity story): the
1029
- // export ALIASES the const's own dyn global — one storage, one
1030
- // owner, identity by construction (a record-typed second slot
1031
- // would either copy or mismatch the dyn value — that mismatch
1032
- // was an ICE; a second same-named global double-released at
1033
- // teardown). The statement's assign degenerates to a harmless
1034
- // self-assign. Mutable (`let`) sources keep the registration
1035
- // below: Node copies the VALUE at this statement, and separate
1036
- // storage is exactly that copy.
1267
+ // An immutable export source shares its live storage and native
1268
+ // callable ABI. Mutable sources need a separate snapshot slot:
1269
+ // later writes to the binding do not change the exported value.
1037
1270
  {
1038
1271
  let rhs = typeNode;
1039
1272
  while (ts.isParenthesizedExpression(rhs))
@@ -1041,19 +1274,14 @@ export function collectGlobals(lowerer, sf, topStmts) {
1041
1274
  if (ts.isIdentifier(rhs)) {
1042
1275
  const vSym = lowerer.checker.getSymbolAtLocation(rhs);
1043
1276
  const vG = vSym && lowerer.globalsBySymbol.get(vSym);
1044
- if (vG?.type.kind === "dyn") {
1277
+ if (vG) {
1045
1278
  if (!vG.mutable) {
1046
1279
  lowerer.globalsBySymbol.set(symbol, vG);
1047
1280
  for (const d of lowerer.checker.declarationsOf(symbol))
1048
1281
  lowerer.globalsByDeclNode.set(d, vG);
1049
1282
  return;
1050
1283
  }
1051
- // A mutable (`let`) dyn source: separate DYN storage IS
1052
- // Node's copy-of-the-reference at this statement (later
1053
- // reassignments of the let stay invisible through the
1054
- // export). The id must not collide with the let's own
1055
- // `%g.<tag><name>` global.
1056
- const g = { id: `%g.${tag}%export.${name}`, name, type: DYN, mutable: false };
1284
+ const g = { id: `%g.${tag}%export.${name}`, name, type: vG.type, mutable: false };
1057
1285
  lowerer.globalsBySymbol.set(symbol, g);
1058
1286
  for (const d of lowerer.checker.declarationsOf(symbol))
1059
1287
  lowerer.globalsByDeclNode.set(d, g);
@@ -1062,7 +1290,7 @@ export function collectGlobals(lowerer, sf, topStmts) {
1062
1290
  }
1063
1291
  }
1064
1292
  }
1065
- const g = { id: `%g.${tag}${name}`, name, type: t, mutable: false };
1293
+ const g = { id: `%g.${tag}%export.${name}`, name, type: t, mutable: false };
1066
1294
  lowerer.globalsBySymbol.set(symbol, g);
1067
1295
  // Importer aliases resolve to a DISTINCT late-bound symbol with
1068
1296
  // the same declaration — key the node too (globalOf's fallback).
@@ -1123,8 +1351,12 @@ export function collectGlobals(lowerer, sf, topStmts) {
1123
1351
  const diagsBefore = lowerer.diags.length;
1124
1352
  try {
1125
1353
  const strict = lowerer.typeOf(rhs);
1126
- const t = lowerer.mapTypeOf(strict) ??
1354
+ let t = lowerer.mapTypeOf(strict) ??
1127
1355
  (fnValued || factoryValued ? dynFallbackType(lowerer, rhs, strict) : null);
1356
+ // A returned object remains the live CommonJS root; later
1357
+ // exports.member writes must update that same open object.
1358
+ if (factoryValued && t?.kind === "record" && lowerer.dynConvertible(t))
1359
+ t = DYN;
1128
1360
  if (t && t.kind !== "void") {
1129
1361
  const g = { id: `%g.${tag}exports`, name: "exports", type: t, mutable: false };
1130
1362
  lowerer.globalsByDeclNode.set(cjs.expr, g);
@@ -1493,6 +1725,23 @@ export function collectGlobals(lowerer, sf, topStmts) {
1493
1725
  for (const nameNode of boundIdentifiersOf(decl.name)) {
1494
1726
  const diagsBefore = lowerer.diags.length;
1495
1727
  try {
1728
+ // Checked JavaScript factories can expose inferred callables by
1729
+ // destructuring. Keep each exported binding in module storage so
1730
+ // separately lowered functions see the initialized value.
1731
+ if (isJsSourceFile(sf) && !ts.isIdentifier(decl.name) && decl.initializer &&
1732
+ !decl.type && !hasJsTypeAnnotation(decl) && !lowerer.mapTypeOf(lowerer.typeOf(nameNode))) {
1733
+ const symbol = lowerer.checker.getSymbolAtLocation(nameNode);
1734
+ if (symbol && !lowerer.globalsBySymbol.has(symbol)) {
1735
+ const g = { id: `%g.${tag}${nsPrefix}${nameNode.text}`, name: nameNode.text,
1736
+ type: DYN, mutable: isLet, source: bindingSource(nameNode),
1737
+ ...(!isVarDeclared(decl) ? { tdz: true } : {}) };
1738
+ lowerer.globalsBySymbol.set(symbol, g);
1739
+ lowerer.globalsList.push(g);
1740
+ if (isVarDeclared(decl))
1741
+ noteVarGlobalEntryInit(lowerer, sf, g);
1742
+ }
1743
+ continue;
1744
+ }
1496
1745
  // Builtin declarations do not always describe the concrete native
1497
1746
  // callable ABI. Preserve checked-native values in shared storage;
1498
1747
  // adapting the loader to (string) would replace its validation.
@@ -1543,7 +1792,8 @@ export function collectGlobals(lowerer, sf, topStmts) {
1543
1792
  if (isJsSourceFile(sf) && ts.isIdentifier(decl.name) && nameNode === decl.name &&
1544
1793
  decl.initializer && ts.isObjectLiteralExpression(decl.initializer) &&
1545
1794
  decl.initializer.properties.some((p) => !ts.isSpreadAssignment(p) &&
1546
- (ts.isMethodDeclaration(p) || ts.isAccessor(p) || ts.isComputedPropertyName(p.name)))) {
1795
+ (ts.isMethodDeclaration(p) || ts.isAccessor(p) || ts.isComputedPropertyName(p.name) ||
1796
+ ts.isShorthandPropertyAssignment(p) && lowerer.checker.getCallSignatures(lowerer.typeOf(p.name)).length > 0))) {
1547
1797
  const symbol = lowerer.checker.getSymbolAtLocation(nameNode);
1548
1798
  if (symbol && !lowerer.globalsBySymbol.has(symbol)) {
1549
1799
  const g = { id: `%g.${tag}${nsPrefix}${nameNode.text}`, name: nameNode.text, type: DYN, mutable: isLet, source: bindingSource(nameNode) };
@@ -1649,9 +1899,16 @@ export function collectGlobals(lowerer, sf, topStmts) {
1649
1899
  if (isJsSourceFile(sf) && !lowerer.mapTypeOf(lowerer.typeOf(nameNode)) &&
1650
1900
  ts.isIdentifier(decl.name) && nameNode === decl.name && decl.initializer &&
1651
1901
  jsDynHoldableInitializer(lowerer, decl.initializer)) {
1652
- const fallback = dynFallbackType(lowerer, nameNode, lowerer.typeOf(nameNode));
1902
+ const initializer = decl.initializer;
1903
+ const member = ts.isPropertyAccessExpression(initializer) ? nsMemberIdentOf(lowerer, initializer) : null;
1904
+ const generic = member && lowerer.genericFnOf(member);
1905
+ const fallback = (ts.isArrowFunction(initializer) || ts.isFunctionExpression(initializer)) && !initializer.typeParameters?.length
1906
+ ? lowerer.lambdaSignature(initializer).funcType
1907
+ : member && lowerer.globalOf(member)?.type.kind === "dyn" ? DYN
1908
+ : member && generic?.implicitParams ? lowerer.lowerGenericFnValue(member, generic).type
1909
+ : dynFallbackType(lowerer, nameNode, lowerer.typeOf(nameNode));
1653
1910
  const symbol = lowerer.checker.getSymbolAtLocation(nameNode);
1654
- if (symbol && fallback && (fallback.kind === "func" || fallback.kind === "union") && lowerer.dynConvertible(fallback)) {
1911
+ if (symbol && fallback && (fallback.kind === "dyn" || fallback.kind === "func" || fallback.kind === "union") && lowerer.dynConvertible(fallback)) {
1655
1912
  if (!lowerer.globalsBySymbol.has(symbol)) {
1656
1913
  const g = {
1657
1914
  id: `%g.${tag}${nsPrefix}${nameNode.text}`, name: nameNode.text,
@@ -1675,9 +1932,7 @@ export function collectGlobals(lowerer, sf, topStmts) {
1675
1932
  // their own per-site runtime fences.
1676
1933
  const factoryType = !isLet && isJsSourceFile(sf) && !decl.type && !hasJsTypeAnnotation(decl) &&
1677
1934
  ts.isIdentifier(decl.name) && nameNode === decl.name && decl.initializer && ts.isNewExpression(decl.initializer)
1678
- ? objectFactorySignature(lowerer, decl.initializer)?.returnType : undefined;
1679
- if (!factoryType && isJsSourceFile(sf) && !lowerer.mapTypeOf(lowerer.typeOf(nameNode)))
1680
- continue;
1935
+ ? objectFactoryGlobalType(lowerer, decl.initializer) ?? undefined : undefined;
1681
1936
  // `var p1 = import("./m")` at file scope: the global holds the
1682
1937
  // island promise/handle — the import expression's only
1683
1938
  // production — whatever the checker's namespace type mapped to
@@ -1691,12 +1946,53 @@ export function collectGlobals(lowerer, sf, topStmts) {
1691
1946
  // exactly the local rule (uncheckedOverloadHandleCall).
1692
1947
  (uncheckedOverloadHandleCall(lowerer, decl.initializer) ? JSVAL : null) : null)
1693
1948
  : null;
1694
- let type = handleT ?? factoryType ?? lowerer.irTypeOf(nameNode);
1949
+ // JavaScript factory results with unmappable annotations still
1950
+ // need shared storage. Unannotated callable unions also use a
1951
+ // checked slot; mappable authored annotations keep their layout.
1952
+ const unannotatedCall = !decl.type && !hasJsTypeAnnotation(decl);
1953
+ const callSignature = (isJsSourceFile(sf) || unannotatedCall) && decl.initializer && ts.isCallExpression(decl.initializer)
1954
+ ? lowerer.checker.getResolvedSignature(decl.initializer) : undefined;
1955
+ const callDeclaration = callSignature && lowerer.checker.signatureDeclaration(callSignature);
1956
+ const callType = callDeclaration && isJsSourceFile(callDeclaration.getSourceFile())
1957
+ ? lowerer.mapTypeOf(lowerer.typeOf(nameNode)) : null;
1958
+ const inferredJsCall = callDeclaration && isJsSourceFile(callDeclaration.getSourceFile()) &&
1959
+ (!callType || unannotatedCall && callType.kind === "union" && lowerer.unions.get(callType.unionId)?.arms.some((arm) => arm.kind === "func"));
1960
+ if (!factoryType && !inferredJsCall && isJsSourceFile(sf) && !lowerer.mapTypeOf(lowerer.typeOf(nameNode)))
1961
+ continue;
1962
+ let type = handleT ?? factoryType ?? (inferredJsCall ? DYN : lowerer.irTypeOf(nameNode));
1963
+ if (isJsSourceFile(sf) && !decl.type && !hasJsTypeAnnotation(decl) && decl.initializer &&
1964
+ (ts.isArrowFunction(decl.initializer) || ts.isFunctionExpression(decl.initializer)) &&
1965
+ !decl.initializer.typeParameters?.length) {
1966
+ type = lowerer.lambdaSignature(decl.initializer).funcType;
1967
+ }
1968
+ // Namespace aliases of inferred helpers carry the helper's
1969
+ // settled callable, whose return can differ from checker inference.
1970
+ // Keep a shared checked slot before any consumer specializes it.
1971
+ if (isJsSourceFile(sf) && !decl.type && !hasJsTypeAnnotation(decl) && type.kind === "func" &&
1972
+ decl.initializer && ts.isPropertyAccessExpression(decl.initializer)) {
1973
+ const member = nsMemberIdentOf(lowerer, decl.initializer);
1974
+ if (member && lowerer.genericFnOf(member)?.implicitParams)
1975
+ type = DYN;
1976
+ else if (member) {
1977
+ const source = lowerer.globalOf(member);
1978
+ if (source?.type.kind === "func")
1979
+ type = source.type;
1980
+ }
1981
+ }
1982
+ if (isJsSourceFile(sf) && !decl.type && !hasJsTypeAnnotation(decl) &&
1983
+ decl.initializer && ts.isCallExpression(decl.initializer) && type.kind === "union") {
1984
+ const arms = lowerer.unions.get(type.unionId)?.arms;
1985
+ if (arms?.some((arm) => arm.kind === "record") && arms.every((arm) => isUnitType(arm) || arm.kind === "record"))
1986
+ type = DYN;
1987
+ }
1988
+ if (isJsSourceFile(sf) && !decl.type && !hasJsTypeAnnotation(decl) && decl.initializer &&
1989
+ ts.isNewExpression(decl.initializer) && lowerer.mapTypeOf(lowerer.typeOf(decl.initializer.expression))?.kind === "dyn" &&
1990
+ !(ts.isIdentifier(decl.initializer.expression) && lowerer.isStdlibSymbol(lowerer.checker.getSymbolAtLocation(decl.initializer.expression))))
1991
+ type = DYN;
1695
1992
  // Calls through checked function values retain their object
1696
1993
  // identity, including symbol keys absent from inferred records.
1697
1994
  if (isJsSourceFile(sf) && !decl.type && !hasJsTypeAnnotation(decl) && type.kind === "record" &&
1698
- decl.initializer && ts.isCallExpression(decl.initializer) &&
1699
- ts.isIdentifier(decl.initializer.expression) && lowerer.globalOf(decl.initializer.expression)?.type.kind === "dyn") {
1995
+ decl.initializer && ts.isCallExpression(decl.initializer) && lowerer.dynConvertible(type)) {
1700
1996
  type = DYN;
1701
1997
  }
1702
1998
  if (isJsSourceFile(sf) && !decl.type && !hasJsTypeAnnotation(decl) && type.kind === "record" &&
@@ -1711,11 +2007,18 @@ export function collectGlobals(lowerer, sf, topStmts) {
1711
2007
  // a fixed-signature adapter to reconstruct its hidden rest ABI.
1712
2008
  if (!decl.type && !hasJsTypeAnnotation(decl) && type.kind === "func" && type.rest === true && type.restAbi === undefined)
1713
2009
  type = DYN;
2010
+ if (isJsSourceFile(sf) && isLet && !decl.type && !hasJsTypeAnnotation(decl) &&
2011
+ (type.kind === "object" || jsBindingHasOpenWrites(lowerer, decl)))
2012
+ type = DYN;
1714
2013
  // JavaScript call results may retain a checked array supplied by
1715
2014
  // the caller. A typed global here would copy it on extraction.
1716
2015
  if (isJsSourceFile(sf) && !decl.type && !hasJsTypeAnnotation(decl) && type.kind === "array" &&
1717
2016
  decl.initializer && ts.isCallExpression(decl.initializer))
1718
2017
  type = DYN;
2018
+ if (!lowerer.dynamic && isJsSourceFile(sf) && !decl.type && !hasJsTypeAnnotation(decl) &&
2019
+ decl.initializer && ts.isNewExpression(decl.initializer) && lowerer.isStdlibGlobal(decl.initializer.expression, "Array") &&
2020
+ (type.kind !== "array" || type.elem.kind === "dyn"))
2021
+ type = DYN;
1719
2022
  // Unannotated JavaScript aliases retain an existing native
1720
2023
  // checked object instead of copying it into an inferred record.
1721
2024
  if (isJsSourceFile(sf) && !decl.type && !hasJsTypeAnnotation(decl) &&
@@ -1793,8 +2096,7 @@ export function collectGlobals(lowerer, sf, topStmts) {
1793
2096
  // adapter would re-copy at the assignment.
1794
2097
  if (isJsSourceFile(sf) &&
1795
2098
  type.kind === "func" &&
1796
- type.ret.kind === "record" &&
1797
- lowerer.dynConvertible(type.ret) &&
2099
+ (type.ret.kind === "date" || type.ret.kind === "record" && lowerer.dynConvertible(type.ret)) &&
1798
2100
  decl.initializer !== undefined &&
1799
2101
  (ts.isFunctionExpression(decl.initializer) || ts.isArrowFunction(decl.initializer)) &&
1800
2102
  decl.initializer.type === undefined &&
@@ -1811,6 +2113,10 @@ export function collectGlobals(lowerer, sf, topStmts) {
1811
2113
  type = DYN;
1812
2114
  }
1813
2115
  // Module vars hold real undefined until their declaration runs.
2116
+ // Unannotated JS function values need that state too: callers
2117
+ // before the initializer must see undefined and a TypeError.
2118
+ if (isJsSourceFile(sf) && isVarDeclared(decl) && type.kind === "func" && lowerer.dynConvertible(type))
2119
+ type = DYN;
1814
2120
  // Codec records keep that state in the ordinary optional union;
1815
2121
  // lexical codec declarations retain their separate TDZ guard.
1816
2122
  const codec = type.kind === "record" && recordTextCodecClass(lowerer.shapes.get(type.shapeId)) !== null;
@@ -2214,7 +2520,7 @@ export function lowerFileInit(lowerer, sf, stmts, name) {
2214
2520
  // SITE's position instead (below) — their inner class node may
2215
2521
  // even live in another file.
2216
2522
  c.decl && ts.isClassDeclaration(c.decl) && !c.mixinInstance && c.decl.getSourceFile() === sf &&
2217
- (c.callableBase !== undefined || c.staticFields.length > 0 || (c.staticBlocks?.length ?? 0) > 0 || c.classDecorators !== undefined))
2523
+ (c.callableBase !== undefined || c.def.baseValueGlobal !== undefined || c.runtimeStatics !== undefined || c.staticFields.length > 0 || (c.staticBlocks?.length ?? 0) > 0 || c.classDecorators !== undefined))
2218
2524
  .map((c) => ({ pos: c.decl.getStart(), info: c }));
2219
2525
  // Statics-bearing MIXIN instantiations whose call evaluates in THIS
2220
2526
  // file: their declaration-time code runs when the call does — the
@@ -2240,7 +2546,8 @@ export function lowerFileInit(lowerer, sf, stmts, name) {
2240
2546
  body.push(...lowerer.lowerStaticFieldInits(statics[at].info));
2241
2547
  at++;
2242
2548
  }
2243
- const stmtIr = lowerer.lowerStmts([stmt]);
2549
+ const deferred = lowerer.deferredModuleInitializers?.defer(lowerer, stmt);
2550
+ const stmtIr = deferred ? [deferred] : lowerer.lowerStmts([stmt]);
2244
2551
  // Class EXPRESSIONS inside this statement queued their static
2245
2552
  // inits while it lowered: they land immediately before it — JS's
2246
2553
  // order for the supported whole-initializer positions.