@scriptc/compiler 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (315) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +158 -31
  2. package/dist/backend/cycle-analysis.js +63 -50
  3. package/dist/backend/cycle-analysis.js.map +1 -1
  4. package/dist/backend/cycle-analysis.test.js +51 -0
  5. package/dist/backend/cycle-analysis.test.js.map +1 -1
  6. package/dist/backend/llvm/borrowed-receivers.d.ts +9 -0
  7. package/dist/backend/llvm/borrowed-receivers.js +58 -0
  8. package/dist/backend/llvm/borrowed-receivers.js.map +1 -0
  9. package/dist/backend/llvm/call-lifetimes.d.ts +20 -0
  10. package/dist/backend/llvm/call-lifetimes.js +179 -0
  11. package/dist/backend/llvm/call-lifetimes.js.map +1 -0
  12. package/dist/backend/llvm/call-lifetimes.test.d.ts +1 -0
  13. package/dist/backend/llvm/call-lifetimes.test.js +205 -0
  14. package/dist/backend/llvm/call-lifetimes.test.js.map +1 -0
  15. package/dist/backend/llvm/dyn.d.ts +5 -2
  16. package/dist/backend/llvm/dyn.js +163 -47
  17. package/dist/backend/llvm/dyn.js.map +1 -1
  18. package/dist/backend/llvm/emitter.d.ts +37 -1
  19. package/dist/backend/llvm/emitter.js +209 -21
  20. package/dist/backend/llvm/emitter.js.map +1 -1
  21. package/dist/backend/llvm/emitter.test.js +29 -2
  22. package/dist/backend/llvm/emitter.test.js.map +1 -1
  23. package/dist/backend/llvm/expr-async.js +1 -1
  24. package/dist/backend/llvm/expr-async.js.map +1 -1
  25. package/dist/backend/llvm/expr-calls.js +42 -5
  26. package/dist/backend/llvm/expr-calls.js.map +1 -1
  27. package/dist/backend/llvm/expr-containers.js +75 -13
  28. package/dist/backend/llvm/expr-containers.js.map +1 -1
  29. package/dist/backend/llvm/expr-dynamic.js +31 -6
  30. package/dist/backend/llvm/expr-dynamic.js.map +1 -1
  31. package/dist/backend/llvm/expr-primitives.js +6 -5
  32. package/dist/backend/llvm/expr-primitives.js.map +1 -1
  33. package/dist/backend/llvm/expr-records.js +1 -1
  34. package/dist/backend/llvm/expr-records.js.map +1 -1
  35. package/dist/backend/llvm/expr-stream-bridges.js +75 -19
  36. package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
  37. package/dist/backend/llvm/expr-stream-callbacks.d.ts +2 -2
  38. package/dist/backend/llvm/expr-stream-callbacks.js +7 -57
  39. package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
  40. package/dist/backend/llvm/lib-dispatch.js +41 -3
  41. package/dist/backend/llvm/lib-dispatch.js.map +1 -1
  42. package/dist/backend/llvm/lib-filesystem.js +12 -9
  43. package/dist/backend/llvm/lib-filesystem.js.map +1 -1
  44. package/dist/backend/llvm/lib-shared.js +70 -2
  45. package/dist/backend/llvm/lib-shared.js.map +1 -1
  46. package/dist/backend/llvm/local-array-reads.d.ts +44 -0
  47. package/dist/backend/llvm/local-array-reads.js +313 -0
  48. package/dist/backend/llvm/local-array-reads.js.map +1 -0
  49. package/dist/backend/llvm/local-array-reads.test.d.ts +1 -0
  50. package/dist/backend/llvm/local-array-reads.test.js +446 -0
  51. package/dist/backend/llvm/local-array-reads.test.js.map +1 -0
  52. package/dist/backend/llvm/map-read-lifetimes.d.ts +36 -0
  53. package/dist/backend/llvm/map-read-lifetimes.js +128 -0
  54. package/dist/backend/llvm/map-read-lifetimes.js.map +1 -0
  55. package/dist/backend/llvm/map-read-lifetimes.test.d.ts +1 -0
  56. package/dist/backend/llvm/map-read-lifetimes.test.js +123 -0
  57. package/dist/backend/llvm/map-read-lifetimes.test.js.map +1 -0
  58. package/dist/backend/llvm/shapes.js +1 -0
  59. package/dist/backend/llvm/shapes.js.map +1 -1
  60. package/dist/backend/llvm/split.js +15 -5
  61. package/dist/backend/llvm/split.js.map +1 -1
  62. package/dist/backend/llvm/split.test.js +17 -0
  63. package/dist/backend/llvm/split.test.js.map +1 -1
  64. package/dist/backend/llvm/stack-unions.d.ts +20 -0
  65. package/dist/backend/llvm/stack-unions.js +61 -0
  66. package/dist/backend/llvm/stack-unions.js.map +1 -0
  67. package/dist/backend/llvm/stack-unions.test.d.ts +1 -0
  68. package/dist/backend/llvm/stack-unions.test.js +241 -0
  69. package/dist/backend/llvm/stack-unions.test.js.map +1 -0
  70. package/dist/backend/llvm/string-lifetimes.d.ts +12 -0
  71. package/dist/backend/llvm/string-lifetimes.js +70 -0
  72. package/dist/backend/llvm/string-lifetimes.js.map +1 -0
  73. package/dist/backend/llvm/string-lifetimes.test.d.ts +1 -0
  74. package/dist/backend/llvm/string-lifetimes.test.js +230 -0
  75. package/dist/backend/llvm/string-lifetimes.test.js.map +1 -0
  76. package/dist/backend/mangle.d.ts +2 -0
  77. package/dist/backend/mangle.js +4 -0
  78. package/dist/backend/mangle.js.map +1 -1
  79. package/dist/backend/may-throw.js +71 -29
  80. package/dist/backend/may-throw.js.map +1 -1
  81. package/dist/backend/may-throw.test.js +104 -1
  82. package/dist/backend/may-throw.test.js.map +1 -1
  83. package/dist/backend/native-codegen.d.ts +1 -1
  84. package/dist/backend/native-codegen.js +4 -3
  85. package/dist/backend/native-codegen.js.map +1 -1
  86. package/dist/backend/native-codegen.test.js +11 -0
  87. package/dist/backend/native-codegen.test.js.map +1 -1
  88. package/dist/backend/native-toolchain.d.ts +2 -2
  89. package/dist/backend/native-toolchain.js +2 -0
  90. package/dist/backend/native-toolchain.js.map +1 -1
  91. package/dist/backend/target-diagnostics.d.ts +5 -0
  92. package/dist/backend/target-diagnostics.js +72 -1
  93. package/dist/backend/target-diagnostics.js.map +1 -1
  94. package/dist/backend/target-diagnostics.test.d.ts +1 -0
  95. package/dist/backend/target-diagnostics.test.js +68 -0
  96. package/dist/backend/target-diagnostics.test.js.map +1 -0
  97. package/dist/coverage/surface-manifest.js +5 -3
  98. package/dist/coverage/surface-manifest.js.map +1 -1
  99. package/dist/executable/executable-cache.d.ts +7 -3
  100. package/dist/executable/executable-cache.js +47 -11
  101. package/dist/executable/executable-cache.js.map +1 -1
  102. package/dist/executable/executable-cache.test.js +109 -2
  103. package/dist/executable/executable-cache.test.js.map +1 -1
  104. package/dist/executable/prepare.js +2 -1
  105. package/dist/executable/prepare.js.map +1 -1
  106. package/dist/frontend/builtin-modules.d.ts +1 -1
  107. package/dist/frontend/builtin-modules.js +1 -1
  108. package/dist/frontend/builtin-modules.js.map +1 -1
  109. package/dist/frontend/function-completion.d.ts +6 -0
  110. package/dist/frontend/function-completion.js +50 -0
  111. package/dist/frontend/function-completion.js.map +1 -0
  112. package/dist/frontend/input-tracker.js +3 -3
  113. package/dist/frontend/input-tracker.js.map +1 -1
  114. package/dist/frontend/input-tracker.test.js +38 -2
  115. package/dist/frontend/input-tracker.test.js.map +1 -1
  116. package/dist/frontend/lowering/abstract-equality.js +5 -1
  117. package/dist/frontend/lowering/abstract-equality.js.map +1 -1
  118. package/dist/frontend/lowering/checked-iterable-spread.d.ts +4 -0
  119. package/dist/frontend/lowering/checked-iterable-spread.js +30 -0
  120. package/dist/frontend/lowering/checked-iterable-spread.js.map +1 -0
  121. package/dist/frontend/lowering/checked-promise-all.d.ts +5 -0
  122. package/dist/frontend/lowering/checked-promise-all.js +31 -0
  123. package/dist/frontend/lowering/checked-promise-all.js.map +1 -0
  124. package/dist/frontend/lowering/class-callbacks.d.ts +1 -1
  125. package/dist/frontend/lowering/class-callbacks.js +7 -6
  126. package/dist/frontend/lowering/class-callbacks.js.map +1 -1
  127. package/dist/frontend/lowering/class-construction.d.ts +2 -0
  128. package/dist/frontend/lowering/class-construction.js +34 -5
  129. package/dist/frontend/lowering/class-construction.js.map +1 -1
  130. package/dist/frontend/lowering/class-descriptors.d.ts +1 -1
  131. package/dist/frontend/lowering/class-descriptors.js +12 -5
  132. package/dist/frontend/lowering/class-descriptors.js.map +1 -1
  133. package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +25 -0
  134. package/dist/frontend/lowering/class-dynamic-dispatch.js +597 -78
  135. package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
  136. package/dist/frontend/lowering/class-dynamic-dispatch.test.js +64 -2
  137. package/dist/frontend/lowering/class-dynamic-dispatch.test.js.map +1 -1
  138. package/dist/frontend/lowering/class-instance-constructor.d.ts +1 -1
  139. package/dist/frontend/lowering/class-instance-constructor.js +11 -41
  140. package/dist/frontend/lowering/class-instance-constructor.js.map +1 -1
  141. package/dist/frontend/lowering/class-method-values.d.ts +16 -0
  142. package/dist/frontend/lowering/class-method-values.js +60 -29
  143. package/dist/frontend/lowering/class-method-values.js.map +1 -1
  144. package/dist/frontend/lowering/class-prototypes.d.ts +5 -1
  145. package/dist/frontend/lowering/class-prototypes.js +69 -10
  146. package/dist/frontend/lowering/class-prototypes.js.map +1 -1
  147. package/dist/frontend/lowering/class-runtime-statics.d.ts +4 -4
  148. package/dist/frontend/lowering/class-runtime-statics.js +26 -8
  149. package/dist/frontend/lowering/class-runtime-statics.js.map +1 -1
  150. package/dist/frontend/lowering/class-static-data.d.ts +1 -0
  151. package/dist/frontend/lowering/class-static-data.js +4 -2
  152. package/dist/frontend/lowering/class-static-data.js.map +1 -1
  153. package/dist/frontend/lowering/collection-ingestion.d.ts +31 -0
  154. package/dist/frontend/lowering/collection-ingestion.js +215 -0
  155. package/dist/frontend/lowering/collection-ingestion.js.map +1 -0
  156. package/dist/frontend/lowering/containers/bytes.js +19 -4
  157. package/dist/frontend/lowering/containers/bytes.js.map +1 -1
  158. package/dist/frontend/lowering/containers/string-and-regexp.js +6 -1
  159. package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
  160. package/dist/frontend/lowering/deferred-module-initializers.d.ts +13 -0
  161. package/dist/frontend/lowering/deferred-module-initializers.js +410 -0
  162. package/dist/frontend/lowering/deferred-module-initializers.js.map +1 -0
  163. package/dist/frontend/lowering/deferred-module-initializers.test.d.ts +1 -0
  164. package/dist/frontend/lowering/deferred-module-initializers.test.js +92 -0
  165. package/dist/frontend/lowering/deferred-module-initializers.test.js.map +1 -0
  166. package/dist/frontend/lowering/expressions/object-literals.js +31 -1
  167. package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
  168. package/dist/frontend/lowering/expressions/optional-chains.js +3 -3
  169. package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
  170. package/dist/frontend/lowering/import-meta.d.ts +10 -0
  171. package/dist/frontend/lowering/import-meta.js +52 -0
  172. package/dist/frontend/lowering/import-meta.js.map +1 -0
  173. package/dist/frontend/lowering/lower-assert.js +105 -41
  174. package/dist/frontend/lowering/lower-assert.js.map +1 -1
  175. package/dist/frontend/lowering/lower-builtin-values.d.ts +2 -0
  176. package/dist/frontend/lowering/lower-builtin-values.js +22 -1
  177. package/dist/frontend/lowering/lower-builtin-values.js.map +1 -1
  178. package/dist/frontend/lowering/lower-builtins.d.ts +7 -22
  179. package/dist/frontend/lowering/lower-builtins.js +439 -95
  180. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  181. package/dist/frontend/lowering/lower-calls.js +289 -76
  182. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  183. package/dist/frontend/lowering/lower-classes.d.ts +5 -0
  184. package/dist/frontend/lowering/lower-classes.js +443 -29
  185. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  186. package/dist/frontend/lowering/lower-containers.d.ts +6 -2
  187. package/dist/frontend/lowering/lower-containers.js +79 -20
  188. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  189. package/dist/frontend/lowering/lower-exprs.d.ts +10 -6
  190. package/dist/frontend/lowering/lower-exprs.js +329 -170
  191. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  192. package/dist/frontend/lowering/lower-generators.js +5 -1
  193. package/dist/frontend/lowering/lower-generators.js.map +1 -1
  194. package/dist/frontend/lowering/lower-inspect.js +58 -1
  195. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  196. package/dist/frontend/lowering/lower-island.js +4 -0
  197. package/dist/frontend/lowering/lower-island.js.map +1 -1
  198. package/dist/frontend/lowering/lower-island.test.d.ts +1 -0
  199. package/dist/frontend/lowering/lower-island.test.js +51 -0
  200. package/dist/frontend/lowering/lower-island.test.js.map +1 -0
  201. package/dist/frontend/lowering/lower-modules.d.ts +1 -3
  202. package/dist/frontend/lowering/lower-modules.js +186 -82
  203. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  204. package/dist/frontend/lowering/lower-modules.test.js +69 -1
  205. package/dist/frontend/lowering/lower-modules.test.js.map +1 -1
  206. package/dist/frontend/lowering/lower-stmts.js +172 -103
  207. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  208. package/dist/frontend/lowering/lower-stmts.test.d.ts +1 -0
  209. package/dist/frontend/lowering/lower-stmts.test.js +77 -0
  210. package/dist/frontend/lowering/lower-stmts.test.js.map +1 -0
  211. package/dist/frontend/lowering/lower-stream.js +2 -0
  212. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  213. package/dist/frontend/lowering/lower-system-errors.d.ts +6 -0
  214. package/dist/frontend/lowering/lower-system-errors.js +29 -0
  215. package/dist/frontend/lowering/lower-system-errors.js.map +1 -0
  216. package/dist/frontend/lowering/lower-url.d.ts +2 -1
  217. package/dist/frontend/lowering/lower-url.js +32 -9
  218. package/dist/frontend/lowering/lower-url.js.map +1 -1
  219. package/dist/frontend/lowering/lowerer.d.ts +30 -12
  220. package/dist/frontend/lowering/lowerer.js +268 -49
  221. package/dist/frontend/lowering/lowerer.js.map +1 -1
  222. package/dist/frontend/lowering/lowerer.test.js +38 -0
  223. package/dist/frontend/lowering/lowerer.test.js.map +1 -1
  224. package/dist/frontend/lowering/module-namespace-elements.d.ts +7 -0
  225. package/dist/frontend/lowering/module-namespace-elements.js +54 -0
  226. package/dist/frontend/lowering/module-namespace-elements.js.map +1 -0
  227. package/dist/frontend/lowering/object-factory-new.d.ts +4 -3
  228. package/dist/frontend/lowering/object-factory-new.js +27 -14
  229. package/dist/frontend/lowering/object-factory-new.js.map +1 -1
  230. package/dist/frontend/lowering/surfaces.d.ts +3 -2
  231. package/dist/frontend/lowering/surfaces.js +93 -33
  232. package/dist/frontend/lowering/surfaces.js.map +1 -1
  233. package/dist/frontend/lowering/text-decoder-encoding.js +3 -0
  234. package/dist/frontend/lowering/text-decoder-encoding.js.map +1 -1
  235. package/dist/frontend/lowering/text-decoder-encoding.test.js +2 -1
  236. package/dist/frontend/lowering/text-decoder-encoding.test.js.map +1 -1
  237. package/dist/frontend/module-syntax.d.ts +1 -1
  238. package/dist/frontend/module-syntax.js +8 -1
  239. package/dist/frontend/module-syntax.js.map +1 -1
  240. package/dist/frontend/module-syntax.test.js +10 -0
  241. package/dist/frontend/module-syntax.test.js.map +1 -1
  242. package/dist/frontend/npm.d.ts +4 -0
  243. package/dist/frontend/npm.js +86 -33
  244. package/dist/frontend/npm.js.map +1 -1
  245. package/dist/frontend/npm.test.js +103 -0
  246. package/dist/frontend/npm.test.js.map +1 -1
  247. package/dist/frontend/pipeline-native.js +2 -1
  248. package/dist/frontend/pipeline-native.js.map +1 -1
  249. package/dist/frontend/program.js +4 -2
  250. package/dist/frontend/program.js.map +1 -1
  251. package/dist/frontend/services-node.js +3 -2
  252. package/dist/frontend/services-node.js.map +1 -1
  253. package/dist/frontend/services.d.ts +5 -1
  254. package/dist/frontend/services.js +9 -1
  255. package/dist/frontend/services.js.map +1 -1
  256. package/dist/frontend/services.test.js +21 -0
  257. package/dist/frontend/services.test.js.map +1 -1
  258. package/dist/frontend/ts7/ast-node.d.ts +2 -0
  259. package/dist/frontend/ts7/ast-node.js +30 -4
  260. package/dist/frontend/ts7/ast-node.js.map +1 -1
  261. package/dist/frontend/ts7/ast-node.test.js +60 -1
  262. package/dist/frontend/ts7/ast-node.test.js.map +1 -1
  263. package/dist/frontend/type-mapper.js +89 -14
  264. package/dist/frontend/type-mapper.js.map +1 -1
  265. package/dist/frontend/union-discriminants.js +22 -7
  266. package/dist/frontend/union-discriminants.js.map +1 -1
  267. package/dist/index.js +19 -12
  268. package/dist/index.js.map +1 -1
  269. package/dist/ir/analysis.js +1 -0
  270. package/dist/ir/analysis.js.map +1 -1
  271. package/dist/ir/integer-loops.d.ts +7 -0
  272. package/dist/ir/integer-loops.js +23 -0
  273. package/dist/ir/integer-loops.js.map +1 -1
  274. package/dist/ir/integer-loops.test.d.ts +1 -0
  275. package/dist/ir/integer-loops.test.js +41 -0
  276. package/dist/ir/integer-loops.test.js.map +1 -0
  277. package/dist/ir/ir.d.ts +44 -26
  278. package/dist/ir/ir.js +69 -11
  279. package/dist/ir/ir.js.map +1 -1
  280. package/dist/ir/ir.test.js +18 -0
  281. package/dist/ir/ir.test.js.map +1 -1
  282. package/dist/ir/serialize.js +21 -1
  283. package/dist/ir/serialize.js.map +1 -1
  284. package/dist/ir/serialize.test.js +21 -0
  285. package/dist/ir/serialize.test.js.map +1 -1
  286. package/dist/ir/traverse.d.ts +0 -3
  287. package/dist/ir/traverse.js +33 -20
  288. package/dist/ir/traverse.js.map +1 -1
  289. package/dist/ir/validate.js +216 -80
  290. package/dist/ir/validate.js.map +1 -1
  291. package/dist/ir/validate.test.js +244 -1
  292. package/dist/ir/validate.test.js.map +1 -1
  293. package/dist/library/compiler-self-identity.js +1 -1
  294. package/dist/library/compiler-self-identity.test.js +2 -2
  295. package/dist/library/compiler-self-identity.test.js.map +1 -1
  296. package/dist/library/fence-eval.js +9 -2
  297. package/dist/library/fence-eval.js.map +1 -1
  298. package/dist/library/fence-eval.test.d.ts +1 -0
  299. package/dist/library/fence-eval.test.js +21 -0
  300. package/dist/library/fence-eval.test.js.map +1 -0
  301. package/dist/library/int-infer.d.ts +2 -2
  302. package/dist/library/int-infer.js +10 -7
  303. package/dist/library/int-infer.js.map +1 -1
  304. package/dist/library/int-infer.test.js +44 -0
  305. package/dist/library/int-infer.test.js.map +1 -1
  306. package/dist/library/prepare.js +2 -1
  307. package/dist/library/prepare.js.map +1 -1
  308. package/dist/native/runtime-typescript.d.ts +4 -0
  309. package/dist/native/runtime-typescript.js +61 -0
  310. package/dist/native/runtime-typescript.js.map +1 -0
  311. package/dist/native/runtime-typescript.test.d.ts +1 -0
  312. package/dist/native/runtime-typescript.test.js +41 -0
  313. package/dist/native/runtime-typescript.test.js.map +1 -0
  314. package/package.json +20 -20
  315. package/surface-manifest.json +385 -29
@@ -31,8 +31,9 @@ import { lowerObjectFactoryNew } from "./object-factory-new.js";
31
31
  import { tryLowerExpression } from "./expressions/try-lower-expression.js";
32
32
  import { lowerInstanceConstructorNew } from "./class-instance-constructor.js";
33
33
  import { classPrototypeData } from "./class-prototypes.js";
34
- import { checkedClassConstruction } from "./class-construction.js";
34
+ import { checkedClassConstruction, checkedClassConstructionPacked } from "./class-construction.js";
35
35
  import { initializeRuntimeStatics, hasRuntimeStatics } from "./class-runtime-statics.js";
36
+ import { reflectedClassStaticMethodValue } from "./class-method-values.js";
36
37
  export function returnsOnlyThis(member) {
37
38
  const body = member.body;
38
39
  const last = body?.statements.at(-1);
@@ -492,9 +493,83 @@ export function builtinStreamInfoOf(lowerer, symbol) {
492
493
  /** A dictionary lookup may be absent even when its checker type is a
493
494
  * required reference. Keep literal nullish fallbacks in inferred JS storage. */
494
495
  function jsFieldInitializerType(lowerer, type, expression) {
496
+ if (ts.isIdentifier(expression)) {
497
+ const symbol = lowerer.checker.getSymbolAtLocation(expression);
498
+ if (symbol && lowerer.checker.declarationsOf(symbol).some((decl) => ts.isParameter(decl) && (ts.isConstructorDeclaration(decl.parent) ||
499
+ (lowerer.typeOf(expression).flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) !== 0)))
500
+ return DYN;
501
+ }
502
+ if (type.kind === "array" || type.kind === "record")
503
+ return DYN;
504
+ // JavaScript documentation cannot guarantee that a call or an indexed
505
+ // read returns a present number. Numeric fields receiving those values
506
+ // must retain undefined, so later arithmetic performs JS coercion (NaN).
507
+ if (type.kind === "f64" && isJsSourceFile(expression.getSourceFile())) {
508
+ const assignment = expression.parent;
509
+ const left = ts.isBinaryExpression(assignment) ? assignment.left : null;
510
+ const field = left && ts.isPropertyAccessExpression(left) && left.expression.kind === ts.SyntaxKind.ThisKeyword ? left.name.text : null;
511
+ let owner = expression.parent;
512
+ while (owner && !ts.isClassDeclaration(owner) && !ts.isClassExpression(owner))
513
+ owner = owner.parent;
514
+ if (field && owner) {
515
+ let acceptsUnchecked = false;
516
+ const scan = (node) => {
517
+ if (acceptsUnchecked || node !== owner && (ts.isClassDeclaration(node) || ts.isClassExpression(node)))
518
+ return;
519
+ if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.EqualsToken &&
520
+ ts.isPropertyAccessExpression(node.left) && node.left.expression.kind === ts.SyntaxKind.ThisKeyword && node.left.name.text === field) {
521
+ let rhs = node.right;
522
+ while (ts.isParenthesizedExpression(rhs))
523
+ rhs = rhs.expression;
524
+ if (ts.isCallExpression(rhs) || ts.isElementAccessExpression(rhs))
525
+ acceptsUnchecked = true;
526
+ }
527
+ node.forEachChild(scan);
528
+ };
529
+ scan(owner);
530
+ if (acceptsUnchecked)
531
+ return DYN;
532
+ }
533
+ }
495
534
  let node = expression;
496
535
  while (ts.isParenthesizedExpression(node))
497
536
  node = node.expression;
537
+ if (ts.isCallExpression(node) && type.kind === "bytes") {
538
+ let prototypeArgument = false;
539
+ for (const argument of node.arguments)
540
+ ts.walkPreorder(argument, (part) => {
541
+ if (!ts.isPropertyAccessExpression(part) || part.expression.kind !== ts.SyntaxKind.ThisKeyword)
542
+ return;
543
+ const symbol = lowerer.checker.getSymbolAtLocation(part.name);
544
+ if (symbol && lowerer.checker.declarationsOf(symbol).some((decl) => {
545
+ const member = ts.isBinaryExpression(decl) ? decl.left : decl;
546
+ return ts.isPropertyAccessExpression(member) && ts.isPropertyAccessExpression(member.expression) &&
547
+ member.expression.name.text === "prototype";
548
+ }))
549
+ prototypeArgument = true;
550
+ // JS checkers can synthesize a property declaration for prototype
551
+ // assignments. Keep the source ownership proof when that happens.
552
+ let owner = node.parent;
553
+ while (owner && !(ts.isClassDeclaration(owner) || ts.isClassExpression(owner)))
554
+ owner = owner.parent;
555
+ if (owner && (ts.isClassDeclaration(owner) || ts.isClassExpression(owner)) && owner.name) {
556
+ const className = owner.name.text;
557
+ for (const statement of owner.getSourceFile().statements) {
558
+ if (!ts.isExpressionStatement(statement) || !ts.isBinaryExpression(statement.expression))
559
+ continue;
560
+ const left = statement.expression.left;
561
+ if (statement.expression.operatorToken.kind === ts.SyntaxKind.EqualsToken && ts.isPropertyAccessExpression(left) &&
562
+ left.name.text === part.name.text && ts.isPropertyAccessExpression(left.expression) && left.expression.name.text === "prototype" &&
563
+ ts.isIdentifier(left.expression.expression) && left.expression.expression.text === className)
564
+ prototypeArgument = true;
565
+ }
566
+ }
567
+ });
568
+ // A prototype-selected conversion can return different container kinds
569
+ // in subclasses even when JSDoc describes the base class's default.
570
+ if (prototypeArgument)
571
+ return DYN;
572
+ }
498
573
  if (ts.isFunctionExpression(node) || ts.isArrowFunction(node)) {
499
574
  const ret = lowerer.declaredReturnType(node, node);
500
575
  const arms = type.kind === "union" ? lowerer.unions.get(type.unionId)?.arms ?? [] : [type];
@@ -506,6 +581,14 @@ function jsFieldInitializerType(lowerer, type, expression) {
506
581
  if (node.kind === ts.SyntaxKind.NullKeyword)
507
582
  return withUnitArm(type, "nullT", lowerer.unions) ?? type;
508
583
  const inferred = lowerer.typeOf(node);
584
+ const scalar = (inferred.flags & ts.TypeFlags.BooleanLike) !== 0 ? "bool"
585
+ : (inferred.flags & ts.TypeFlags.NumberLike) !== 0 ? "f64"
586
+ : (inferred.flags & ts.TypeFlags.StringLike) !== 0 ? "string"
587
+ : (inferred.flags & ts.TypeFlags.BigIntLike) !== 0 ? "bigint"
588
+ : (inferred.flags & ts.TypeFlags.ESSymbolLike) !== 0 ? "symbol" : null;
589
+ if (scalar && type.kind !== "dyn" && type.kind !== scalar &&
590
+ !(type.kind === "union" && lowerer.unions.get(type.unionId)?.arms.some((arm) => arm.kind === scalar)))
591
+ return DYN;
509
592
  for (const arm of inferred.isUnionType() ? ts.constituentTypes(inferred) : [inferred]) {
510
593
  if ((arm.flags & ts.TypeFlags.Undefined) !== 0)
511
594
  type = lowerer.withUndefinedArmOf(type) ?? type;
@@ -525,6 +608,56 @@ function jsFieldInitializerType(lowerer, type, expression) {
525
608
  }
526
609
  return type;
527
610
  }
611
+ function inheritedJsFieldType(lowerer, decl, name, type) {
612
+ for (const expression of lowerer.inheritedJsFieldWrites.get(decl)?.get(name) ?? []) {
613
+ // Keep one shared layout, including sibling subclasses. A descendant
614
+ // initializer that exceeds the base slot needs checked JS storage.
615
+ if (!typeEquals(type, jsFieldInitializerType(lowerer, type, expression)))
616
+ return DYN;
617
+ }
618
+ return type;
619
+ }
620
+ function returnsWidenedJsField(lowerer, decl, member, fields, ret) {
621
+ if (!isJsSourceFile(member.getSourceFile()) || member.type || member.asteriskToken || hasExplicitJsDocReturn(member))
622
+ return false;
623
+ const widened = (expression) => {
624
+ if (ts.isParenthesizedExpression(expression))
625
+ return widened(expression.expression);
626
+ if (ts.isConditionalExpression(expression))
627
+ return widened(expression.whenTrue) || widened(expression.whenFalse);
628
+ if (ts.isCallExpression(expression)) {
629
+ const callee = expression.expression;
630
+ const symbol = ts.isPropertyAccessExpression(callee) ? lowerer.checker.getSymbolAtLocation(callee.name)
631
+ : ts.isElementAccessExpression(callee) ? lowerer.checker.getPropertyOfType(lowerer.typeOf(callee.expression), lowerer.foldedStringKeyOf(callee.argumentExpression) ?? "")
632
+ : undefined;
633
+ if (symbol && lowerer.checker.declarationsOf(symbol).some((declaration) => ts.isMethodDeclaration(declaration) && lowerer.checkedVirtualJsMethods.has(declaration)))
634
+ return true;
635
+ }
636
+ const name = ts.isPropertyAccessExpression(expression) ? expression.name.text
637
+ : ts.isElementAccessExpression(expression) ? lowerer.foldedStringKeyOf(expression.argumentExpression) : null;
638
+ if (ts.isPropertyAccessExpression(expression)) {
639
+ const symbol = lowerer.checker.getSymbolAtLocation(expression.name);
640
+ if (symbol && lowerer.checker.declarationsOf(symbol).some((declaration) => (ts.isGetAccessorDeclaration(declaration) || ts.isSetAccessorDeclaration(declaration)) && lowerer.checkedVirtualJsAccessors.has(declaration)))
641
+ return true;
642
+ }
643
+ if (name !== null && (ts.isPropertyAccessExpression(expression) || ts.isElementAccessExpression(expression)) &&
644
+ expression.expression.kind === ts.SyntaxKind.ThisKeyword) {
645
+ return fields.get(name)?.kind === "dyn" || inheritedJsFieldType(lowerer, decl, name, ret).kind === "dyn";
646
+ }
647
+ return false;
648
+ };
649
+ let result = false;
650
+ const scan = (node) => {
651
+ if (result || ts.isFunctionLike(node))
652
+ return;
653
+ if (ts.isReturnStatement(node) && node.expression && widened(node.expression))
654
+ result = true;
655
+ node.forEachChild(scan);
656
+ };
657
+ if (member.body)
658
+ scan(member.body);
659
+ return result;
660
+ }
528
661
  /** The undefined-armed union of a JS class property's inferred type — the
529
662
  * honest slot for a field first assigned outside the constructor's top
530
663
  * level (undefined until the write runs, Node-exact). Null when the
@@ -1262,6 +1395,12 @@ mixin) {
1262
1395
  const staticBlocks = [];
1263
1396
  const runtimeStatics = [];
1264
1397
  const runtimePrototypeMembers = [];
1398
+ // Public JS accessors need live constructor descriptors, including
1399
+ // receiver-sensitive getters and setters inherited by subclasses.
1400
+ const checkedStatics = isJsSourceFile(decl.getSourceFile()) && (base && hasRuntimeStatics(base) || decl.members.some((member) => ts.isAccessor(member) && !ts.isPrivateIdentifier(member.name) &&
1401
+ member.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword))) &&
1402
+ !decl.members.some((member) => member.name && ts.isPrivateIdentifier(member.name) &&
1403
+ ts.getModifiers(member)?.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword));
1265
1404
  // GENERIC methods (own type parameters), instance and static: only
1266
1405
  // the SYNTAX is checked here — parameter/return types mention the
1267
1406
  // type parameters and cannot map yet; bodies lower per call-site
@@ -1310,7 +1449,7 @@ mixin) {
1310
1449
  });
1311
1450
  };
1312
1451
  for (const member of decl.members) {
1313
- if (functionLocalClass(decl) && isJsSourceFile(decl.getSourceFile()) &&
1452
+ if ((functionLocalClass(decl) || checkedStatics) && isJsSourceFile(decl.getSourceFile()) &&
1314
1453
  (ts.isClassStaticBlockDeclaration(member) || ts.getModifiers(member)?.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword))) {
1315
1454
  runtimeStatics.push(member);
1316
1455
  continue;
@@ -1368,6 +1507,10 @@ mixin) {
1368
1507
  (ts.isIdentifier(member.name) || ts.isPrivateIdentifier(member.name)) &&
1369
1508
  member.initializer &&
1370
1509
  member.postfixToken?.kind !== ts.SyntaxKind.QuestionToken) {
1510
+ const initializerSymbol = ts.isIdentifier(member.initializer) ? lowerer.resolveValueSymbol(member.initializer) : null;
1511
+ // Enum namespace aliases are erased; member reads fold through the checker.
1512
+ if (initializerSymbol && (initializerSymbol.flags & ts.SymbolFlags.Enum) !== 0)
1513
+ continue;
1371
1514
  const type = lowerer.irTypeOf(member.name);
1372
1515
  if (type.kind === "void")
1373
1516
  lowerer.badType(member.name, lowerer.typeOf(member.name));
@@ -1566,10 +1709,17 @@ mixin) {
1566
1709
  const declared = lowerer.typeOf(member);
1567
1710
  const inferred = member.type || !member.initializer ? declared : lowerer.checker.getBaseTypeOfLiteralType(lowerer.typeOf(member.initializer));
1568
1711
  const mapped = member.initializer ? lowerer.mapTypeOf(inferred) ?? dynFallbackType(lowerer, member, inferred) : DYN;
1569
- const type = mapped?.kind === "record" && isJsSourceFile(member.getSourceFile()) && !member.type
1712
+ let type = mapped?.kind === "record" && isJsSourceFile(member.getSourceFile()) && !member.type
1570
1713
  ? DYN : mapped ? jsOpenObjectType(member, mapped, lowerer.shapes, lowerer.unions) : null;
1571
1714
  if (!type || type.kind === "void" || (type.kind === "dyn" && !isJsSourceFile(member.getSourceFile())))
1572
1715
  lowerer.badType(member, inferred);
1716
+ if (isJsSourceFile(member.getSourceFile())) {
1717
+ type = inheritedJsFieldType(lowerer, decl, fieldName, type);
1718
+ if (base?.fields.get(fieldName)?.kind === "dyn")
1719
+ type = DYN;
1720
+ if (base && !fields.has(fieldName) && lowerer.dynConvertible(type))
1721
+ type = DYN;
1722
+ }
1573
1723
  const undefinedInitializer = !member.initializer ? locOf(member) : undefined;
1574
1724
  const previous = fields.get(fieldName);
1575
1725
  if (previous) {
@@ -1635,6 +1785,18 @@ mixin) {
1635
1785
  // as undefined on construction, verified), and reads/writes ride
1636
1786
  // the ordinary undefined-armed union machinery.
1637
1787
  let type = lowerer.irTypeOf(member.name);
1788
+ if (isJsSourceFile(member.getSourceFile()) && !member.initializer) {
1789
+ const constructor = decl.members.find((part) => ts.isConstructorDeclaration(part) && !!part.body);
1790
+ for (const statement of constructor?.body?.statements ?? []) {
1791
+ if (!ts.isExpressionStatement(statement) || !ts.isBinaryExpression(statement.expression) ||
1792
+ statement.expression.operatorToken.kind !== ts.SyntaxKind.EqualsToken)
1793
+ continue;
1794
+ const left = statement.expression.left;
1795
+ if (!ts.isPropertyAccessExpression(left) || left.expression.kind !== ts.SyntaxKind.ThisKeyword || left.name.text !== member.name.text)
1796
+ continue;
1797
+ type = statement.expression.right.kind === ts.SyntaxKind.NullKeyword ? DYN : jsFieldInitializerType(lowerer, type, statement.expression.right);
1798
+ }
1799
+ }
1638
1800
  // Unannotated JavaScript callback slots retain the original
1639
1801
  // callable and its receiver instead of adapting its signature.
1640
1802
  if (isJsSourceFile(member.getSourceFile()) && !member.type &&
@@ -1646,6 +1808,13 @@ mixin) {
1646
1808
  if (isJsSourceFile(member.getSourceFile()) && !member.initializer && type.kind !== "dyn") {
1647
1809
  type = lowerer.withUndefinedArmOf(type) ?? DYN;
1648
1810
  }
1811
+ if (isJsSourceFile(member.getSourceFile())) {
1812
+ type = inheritedJsFieldType(lowerer, decl, member.name.text, type);
1813
+ if (base?.fields.get(member.name.text)?.kind === "dyn")
1814
+ type = DYN;
1815
+ if (base && !fields.has(member.name.text) && lowerer.dynConvertible(type))
1816
+ type = DYN;
1817
+ }
1649
1818
  if (type.kind === "void")
1650
1819
  lowerer.badType(member.name, lowerer.typeOf(member.name));
1651
1820
  // Bundled JS declares fields without annotations before assigning
@@ -1884,6 +2053,20 @@ mixin) {
1884
2053
  }
1885
2054
  }
1886
2055
  const { shapes, funcType: ft } = lowerer.lambdaSignature(member);
2056
+ const fieldRet = ft.ret.kind === "promise" ? ft.ret.inner : ft.ret;
2057
+ if (returnsWidenedJsField(lowerer, decl, member, fields, fieldRet)) {
2058
+ ft.ret = ft.ret.kind === "promise" ? { ...ft.ret, inner: DYN } : DYN;
2059
+ }
2060
+ if (lowerer.checkedVirtualJsMethods.has(member)) {
2061
+ for (const shape of shapes) {
2062
+ shape.type = DYN;
2063
+ if (shape.bodyType)
2064
+ shape.bodyType = DYN;
2065
+ }
2066
+ ft.params = shapes.map((shape) => shape.type);
2067
+ if (ft.ret.kind !== "void" || lowerer.checkedVirtualJsValueReturns.has(member))
2068
+ ft.ret = DYN;
2069
+ }
1887
2070
  // JS inference may retain only a symbol sentinel while a method
1888
2071
  // also returns values from an untyped mutable field or local.
1889
2072
  if (isJsSourceFile(member.getSourceFile()) && !member.type && !hasExplicitJsDocReturn(member) && ft.ret.kind === "symbol")
@@ -1972,14 +2155,13 @@ mixin) {
1972
2155
  shapes.push(...overridden.sig.params.slice(shapes.length).map((p) => ({ type: p.type, mode: "omittable" })));
1973
2156
  }
1974
2157
  if (overridden &&
2158
+ member.asteriskToken === undefined &&
1975
2159
  (overridden.sig.params.length !== shapes.length ||
1976
2160
  !overridden.sig.params.every((p, i) => typeEquals(p.type, shapes[i].type)) ||
1977
2161
  !typeEquals(overridden.sig.ret, ft.ret))) {
1978
2162
  const fencedJsOverride = isJsSourceFile(member.getSourceFile()) &&
1979
2163
  overridden.declarer.decl !== null && isJsSourceFile(overridden.declarer.decl.getSourceFile()) &&
1980
- member.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword) !== true &&
1981
- overridden.sig.async !== true &&
1982
- member.asteriskToken === undefined && overridden.sig.gen === undefined;
2164
+ overridden.sig.gen === undefined;
1983
2165
  if (fencedJsOverride) {
1984
2166
  // A dormant JS method must not poison the whole class. Keep
1985
2167
  // the inherited call/dispatch ABI and refuse at method entry;
@@ -2013,10 +2195,18 @@ mixin) {
2013
2195
  // an override chain touching an async method on either end would
2014
2196
  // put a spawn wrapper behind a virtual slot, so it fences.
2015
2197
  if (overridden && (asyncMember || overridden.sig.async === true)) {
2016
- lowerer.unsupported("SC1090", member.name, `overriding ${overridden.sig.async === true ? "the async method" : "a method with an async method"} '${mName}' (async methods dispatch statically — the vtable slot machinery has no fiber-spawn story)`);
2198
+ const message = `overriding ${overridden.sig.async === true ? "the async method" : "a method with an async method"} '${mName}' (async methods dispatch statically — the vtable slot machinery has no fiber-spawn story)`;
2199
+ if (isJsSourceFile(member.getSourceFile()))
2200
+ methodEntryFences.set(mName, unsupportedDiag("SC1090", locOf(member.name), message));
2201
+ else
2202
+ lowerer.unsupported("SC1090", member.name, message);
2017
2203
  }
2018
2204
  if (overridden && (member.asteriskToken !== undefined || overridden.sig.gen !== undefined)) {
2019
- lowerer.unsupported("SC1090", member.name, `overriding the generator method '${mName}' (generator methods dispatch statically — a virtual slot cannot enter their spawn wrapper)`);
2205
+ const message = `overriding the generator method '${mName}' (generator methods dispatch statically — a virtual slot cannot enter their spawn wrapper)`;
2206
+ if (isJsSourceFile(member.getSourceFile()))
2207
+ methodEntryFences.set(mName, unsupportedDiag("SC1090", locOf(member.name), message));
2208
+ else
2209
+ lowerer.unsupported("SC1090", member.name, message);
2020
2210
  }
2021
2211
  // A GENERATOR method carries its channels on the sig:
2022
2212
  // the body lowers as a generator IrFunction (`this` as param 0),
@@ -2072,6 +2262,13 @@ mixin) {
2072
2262
  if (!member.body && !abstractAccessor)
2073
2263
  lowerer.unsupported("SC1090", member, "bodyless accessors");
2074
2264
  const mName = `${isGet ? "get" : "set"}:${prop}`;
2265
+ if (fields.has(prop) && isJsSourceFile(decl.getSourceFile()) && base?.fields.has(prop) &&
2266
+ !fieldOrder.some((field) => field.name === prop)) {
2267
+ // JS may override an inherited data field with a prototype
2268
+ // accessor. Retain the base storage prefix for its constructor;
2269
+ // property dispatch on this subclass selects the accessor.
2270
+ fields.delete(prop);
2271
+ }
2075
2272
  if (fields.has(prop) && !((prop === "message" || prop === "name") && base && (base.def.name === "%Error" || lowerer.isSubclassOf(base.def.name, "%Error")))) {
2076
2273
  // tsc rejects field/accessor mixing (TS2610/2611); defensive.
2077
2274
  lowerer.unsupported("SC1090", member.name, "accessors sharing a name with a field");
@@ -2087,6 +2284,13 @@ mixin) {
2087
2284
  // tsc rejects optional/default/rest setter params (TS1051-53).
2088
2285
  sig = { params: lowerer.paramShapes(member.parameters), ret: VOID };
2089
2286
  }
2287
+ if (lowerer.checkedVirtualJsAccessors.has(member)) {
2288
+ if (isGet)
2289
+ sig.ret = DYN;
2290
+ else
2291
+ for (const parameter of sig.params)
2292
+ parameter.type = DYN;
2293
+ }
2090
2294
  // One property, ONE type: tsc (5.1+) admits get/set pairs with
2091
2295
  // unrelated annotated types; a property slot here has a single
2092
2296
  // IR type, so the pair must agree exactly.
@@ -2273,7 +2477,11 @@ mixin) {
2273
2477
  if (fields.has(name) || hasAccessor(name))
2274
2478
  continue;
2275
2479
  if (methods.has(name) || lowerer.findMethodOn(base, name)) {
2276
- lowerer.unsupported("SC1090", assign, "constructor-assigned fields shadowing methods");
2480
+ // An own JS callable shadows its prototype declaration.
2481
+ // Keep the method in the prototype and store the assigned
2482
+ // value in the instance property bag.
2483
+ lowerer.prototypeMethodAccesses.set(name, assign);
2484
+ continue;
2277
2485
  }
2278
2486
  const sym = lowerer.checker.getSymbolAtLocation(assign);
2279
2487
  const t = sym ? lowerer.checker.getTypeOfSymbol(sym) : undefined;
@@ -2314,6 +2522,11 @@ mixin) {
2314
2522
  type = widened;
2315
2523
  }
2316
2524
  }
2525
+ type = inheritedJsFieldType(lowerer, decl, name, type);
2526
+ // super() can invoke a subclass setter or method before its
2527
+ // constructor assignments run. These slots start undefined.
2528
+ if (base && lowerer.dynConvertible(type))
2529
+ type = DYN;
2317
2530
  fields.set(name, type);
2318
2531
  fieldOrder.push({ name, type, initializer: undefined });
2319
2532
  continue;
@@ -2341,7 +2554,8 @@ mixin) {
2341
2554
  if (!key && (fields.has(fieldName) || hasAccessor(fieldName)))
2342
2555
  continue;
2343
2556
  if (!key && (methods.has(fieldName) || lowerer.findMethodOn(base, fieldName))) {
2344
- lowerer.unsupported("SC1090", lhs, "constructor-assigned fields shadowing methods");
2557
+ lowerer.prototypeMethodAccesses.set(fieldName, lhs);
2558
+ continue;
2345
2559
  }
2346
2560
  // A key already declared (own or inherited) makes later
2347
2561
  // assignments writes, not declarations.
@@ -2372,6 +2586,9 @@ mixin) {
2372
2586
  type = jsOpenObjectType(lhs, type, lowerer.shapes, lowerer.unions);
2373
2587
  if (!type || type.kind === "void")
2374
2588
  lowerer.badType(lhs, t ?? lowerer.typeOf(lhs));
2589
+ type = inheritedJsFieldType(lowerer, decl, fieldName, type);
2590
+ if (base && lowerer.dynConvertible(type))
2591
+ type = DYN;
2375
2592
  fields.set(fieldName, type);
2376
2593
  if (key)
2377
2594
  symbolFields.set(key.identity, fieldName);
@@ -2421,7 +2638,8 @@ mixin) {
2421
2638
  // TypeScript classes keep the loud fence too: an annotated
2422
2639
  // program can spell `T | undefined` itself.
2423
2640
  if (isJsSourceFile(decl.getSourceFile())) {
2424
- const armed = undefArmedFieldType(lowerer, p);
2641
+ const original = undefArmedFieldType(lowerer, p);
2642
+ const armed = original === null ? null : inheritedJsFieldType(lowerer, decl, p.name, original);
2425
2643
  if (armed !== null) {
2426
2644
  // Unknown JS properties use the instance bag: they do not
2427
2645
  // exist until assigned, and a subclass may declare the same
@@ -2471,7 +2689,7 @@ mixin) {
2471
2689
  ctorParams.push({ type: DYN, mode: "arguments" });
2472
2690
  }
2473
2691
  const info = {
2474
- ...(runtimeStatics.length ? { runtimeStatics } : {}),
2692
+ ...(runtimeStatics.length || checkedStatics ? { runtimeStatics } : {}),
2475
2693
  ...(runtimePrototypeMembers.length ? { runtimePrototypeMembers } : {}),
2476
2694
  def: {
2477
2695
  name: className,
@@ -2833,6 +3051,9 @@ function lowerStaticFieldInitsInner(lowerer, info) {
2833
3051
  { kind: "varRef", localId: constructorId, type: DYN, loc },
2834
3052
  ], type: DYN, loc }, loc });
2835
3053
  }
3054
+ if (info.runtimeStatics && !info.localClass && info.decl) {
3055
+ out.push({ kind: "exprStmt", expr: initializeRuntimeStatics(lowerer, info, classValueRef(lowerer, info, info.decl)), loc: locOf(info.decl) });
3056
+ }
2836
3057
  const items = [
2837
3058
  ...info.staticFields.map((f) => ({ pos: f.initializer.getStart(), kind: "field", f })),
2838
3059
  ...(info.staticBlocks ?? []).map((b) => ({ pos: b.getStart(), kind: "block", b })),
@@ -3130,6 +3351,9 @@ export function findGenericStaticOn(lowerer, info, name) {
3130
3351
  * module function — the declared-function-as-value rule verbatim
3131
3352
  * (interned by the backend, so `C.m === C.m` holds). */
3132
3353
  function staticMethodValue(lowerer, declarer, name, sig, blame, loc) {
3354
+ const reflected = reflectedClassStaticMethodValue(lowerer, declarer, name);
3355
+ if (reflected)
3356
+ return reflected;
3133
3357
  const fnName = `%${declarer.def.name}.static:${name}`;
3134
3358
  lowerer.noteEdge(fnName);
3135
3359
  const funcType = {
@@ -3225,7 +3449,8 @@ export function lowerStaticFieldRead(lowerer, expr) {
3225
3449
  return null;
3226
3450
  if (expr.questionDotToken)
3227
3451
  return null;
3228
- if (!ts.isIdentifier(expr.expression) && expr.expression.kind !== ts.SyntaxKind.ThisKeyword)
3452
+ if (!ts.isIdentifier(expr.expression) && expr.expression.kind !== ts.SyntaxKind.ThisKeyword &&
3453
+ exactClassOfReceiver(lowerer, expr.expression) === null)
3229
3454
  return null;
3230
3455
  const symbol = ts.isIdentifier(expr.expression) ? lowerer.resolveValueSymbol(expr.expression) : null;
3231
3456
  const info = (symbol ? lowerer.classBySymbol.get(symbol) : undefined) ??
@@ -3281,8 +3506,14 @@ export function lowerStaticFieldRead(lowerer, expr) {
3281
3506
  return { kind: "dynKeyGet", value: lowerer.coerceToExpected(classValueRef(lowerer, info, expr.expression), DYN),
3282
3507
  key: { kind: "strLit", value: expr.name.text, type: STRING, loc }, type: DYN, loc };
3283
3508
  const data = classStaticDataFor(lowerer, info, expr.name.text, loc);
3284
- if (data)
3285
- return { kind: "dynKeyGet", value: data, key: { kind: "strLit", value: expr.name.text, type: STRING, loc }, type: DYN, loc };
3509
+ if (data) {
3510
+ const value = { kind: "dynKeyGet", value: data, key: { kind: "strLit", value: expr.name.text, type: STRING, loc }, type: DYN, loc };
3511
+ // JavaScript often assigns public statics after the class declaration.
3512
+ // Their storage stays mutable and checked, while reads retain the
3513
+ // checker's concrete type instead of losing the method receiver.
3514
+ const type = isJsSourceFile(expr.getSourceFile()) ? null : lowerer.mapTypeOf(lowerer.typeOf(expr));
3515
+ return type ? lowerer.coerceToExpected(value, type) : value;
3516
+ }
3286
3517
  return null;
3287
3518
  }
3288
3519
  /** NamedEvaluation's answer for a class expression's `.name`: its own
@@ -3388,7 +3619,7 @@ export function lowerClassExpressionInfo(lowerer, expr) {
3388
3619
  // drains it), which is JS's order for whole-initializer positions.
3389
3620
  // Anything subtler (multi-declarator statements, arguments evaluated
3390
3621
  // after other side effects) is a named fence, never a reordering.
3391
- if (!local && (info.callableBase || info.def.baseValueGlobal || info.staticFields.length > 0 || (info.staticBlocks?.length ?? 0) > 0)) {
3622
+ if (!local && (info.callableBase || info.def.baseValueGlobal || info.runtimeStatics || info.staticFields.length > 0 || (info.staticBlocks?.length ?? 0) > 0)) {
3392
3623
  let holder = expr.parent;
3393
3624
  while (ts.isParenthesizedExpression(holder) || ts.isClassExpression(holder) ||
3394
3625
  ts.isHeritageClause(holder) || ts.isExpressionWithTypeArguments(holder)) {
@@ -3434,7 +3665,7 @@ export function lowerClassExpression(lowerer, expr) {
3434
3665
  }
3435
3666
  const info = lowerClassExpressionInfo(lowerer, expr);
3436
3667
  if (!info.localClass && !info.expressionInitializationEmitted &&
3437
- (info.callableBase || info.def.baseValueGlobal || info.staticFields.length > 0 || (info.staticBlocks?.length ?? 0) > 0)) {
3668
+ (info.callableBase || info.def.baseValueGlobal || info.runtimeStatics || info.staticFields.length > 0 || (info.staticBlocks?.length ?? 0) > 0)) {
3438
3669
  info.expressionInitializationEmitted = true;
3439
3670
  lowerer.pendingClassExprInits.push(...lowerer.lowerStaticFieldInits(info));
3440
3671
  }
@@ -3500,9 +3731,8 @@ export function lowerClassExpression(lowerer, expr) {
3500
3731
  ], type: DYN, loc }, loc },
3501
3732
  ], result: clsRef, type: value.type, loc });
3502
3733
  }
3503
- return initializeRuntimeStatics(lowerer, info, info.localClass && value.kind === "classRef"
3504
- ? { ...value, captures: info.localClass.captureSources }
3505
- : value);
3734
+ return info.localClass ? initializeRuntimeStatics(lowerer, info, value.kind === "classRef"
3735
+ ? { ...value, captures: info.localClass.captureSources } : value) : value;
3506
3736
  }
3507
3737
  /** The EXACT class a receiver expression is statically known to BE (not
3508
3738
  * merely be typed by): the class name itself, or a `const` binding
@@ -3511,6 +3741,11 @@ export function lowerClassExpression(lowerer, expr) {
3511
3741
  * hit the declaring class's storage exactly (the shadowing hazards of
3512
3742
  * general class values don't arise). Null for everything else. */
3513
3743
  export function exactClassOfReceiver(lowerer, expr) {
3744
+ if (ts.isPropertyAccessExpression(expr) && !expr.questionDotToken) {
3745
+ const member = nsMemberIdentOf(lowerer, expr);
3746
+ if (member)
3747
+ return exactClassOfReceiver(lowerer, member);
3748
+ }
3514
3749
  // A class-valued lexical this is introduced only for an exact static
3515
3750
  // receiver specialization; ordinary instance this remains an object.
3516
3751
  if (expr.kind === ts.SyntaxKind.ThisKeyword) {
@@ -3667,7 +3902,7 @@ export function lowerStaticMethodCall(lowerer, call, access) {
3667
3902
  if (!ts.isIdentifier(access.expression)) {
3668
3903
  if (!isModuleExportsAccess(access.expression) || !isCjsJsFile(access.getSourceFile(), lowerer.program)) {
3669
3904
  let receiverType = lowerer.mapTypeOf(lowerer.typeOf(access.expression));
3670
- if (receiverType?.kind !== "classval" && isJsSourceFile(call.getSourceFile()) && ts.isCallExpression(access.expression)) {
3905
+ if (receiverType?.kind !== "classval" && isJsSourceFile(call.getSourceFile())) {
3671
3906
  const receiver = tryLowerExpression(lowerer, access.expression);
3672
3907
  if (receiver?.type.kind === "classval")
3673
3908
  receiverType = receiver.type;
@@ -3958,11 +4193,98 @@ export function findGenericMethodOn(lowerer, info, name) {
3958
4193
  export function genericOverrideBelow(lowerer, info, name) {
3959
4194
  return info.subclasses.some((s) => s.genericMethods?.has(name) === true || genericOverrideBelow(lowerer, s, name));
3960
4195
  }
4196
+ /** Discover inherited data writes before any base storage ABI is chosen.
4197
+ * The checker does not widen a base field for assignments in JS subclasses. */
4198
+ export function collectInheritedJsFieldWrites(lowerer, files) {
4199
+ for (const file of files) {
4200
+ if (!isJsSourceFile(file))
4201
+ continue;
4202
+ ts.walkPreorder(file, (node) => {
4203
+ if ((!ts.isClassDeclaration(node) && !ts.isClassExpression(node)) || !node.heritageClauses?.length)
4204
+ return;
4205
+ const writes = new Map();
4206
+ const addWrite = (name, expression) => {
4207
+ const existing = writes.get(name);
4208
+ if (existing)
4209
+ existing.push(expression);
4210
+ else
4211
+ writes.set(name, [expression]);
4212
+ };
4213
+ const scan = (part) => {
4214
+ if (ts.isClassDeclaration(part) || ts.isClassExpression(part) ||
4215
+ ts.isFunctionLike(part) && !ts.isArrowFunction(part))
4216
+ return;
4217
+ if (ts.isBinaryExpression(part) && part.operatorToken.kind === ts.SyntaxKind.EqualsToken) {
4218
+ const left = part.left;
4219
+ if (ts.isPropertyAccessExpression(left) && left.expression.kind === ts.SyntaxKind.ThisKeyword)
4220
+ addWrite(left.name.text, part.right);
4221
+ else if (ts.isElementAccessExpression(left) && left.expression.kind === ts.SyntaxKind.ThisKeyword) {
4222
+ const name = lowerer.foldedStringKeyOf(left.argumentExpression);
4223
+ if (name !== null)
4224
+ addWrite(name, part.right);
4225
+ }
4226
+ }
4227
+ part.forEachChild(scan);
4228
+ };
4229
+ for (const member of node.members) {
4230
+ if (member.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword))
4231
+ continue;
4232
+ if (ts.isPropertyDeclaration(member) && member.initializer) {
4233
+ const name = ts.isPrivateIdentifier(member.name) ? null : classMemberNameOf(lowerer, member.name);
4234
+ if (name !== null)
4235
+ addWrite(name, member.initializer);
4236
+ scan(member.initializer);
4237
+ }
4238
+ if (ts.isConstructorDeclaration(member) || ts.isMethodDeclaration(member) || ts.isAccessor(member)) {
4239
+ if (member.body)
4240
+ scan(member.body);
4241
+ }
4242
+ }
4243
+ if (writes.size === 0)
4244
+ return;
4245
+ const symbol = lowerer.typeOf(node).getSymbol();
4246
+ const instance = symbol ? lowerer.checker.getDeclaredTypeOfSymbol(symbol) : null;
4247
+ const seen = new Set();
4248
+ const markBases = (type) => {
4249
+ const target = type.isTypeReference() ? type.getTarget() : type;
4250
+ if (!target?.isClassOrInterface() || seen.has(target))
4251
+ return;
4252
+ seen.add(target);
4253
+ for (const base of lowerer.checker.getBaseTypes(target)) {
4254
+ for (const [name, expressions] of writes) {
4255
+ const property = lowerer.checker.getPropertyOfType(base, name);
4256
+ for (const declaration of property ? lowerer.checker.declarationsOf(property) : []) {
4257
+ if (ts.isMethodDeclaration(declaration) || ts.isAccessor(declaration))
4258
+ continue;
4259
+ let owner = declaration.parent;
4260
+ while (owner && !ts.isClassDeclaration(owner) && !ts.isClassExpression(owner))
4261
+ owner = owner.parent;
4262
+ if (!owner || (!ts.isClassDeclaration(owner) && !ts.isClassExpression(owner)) || !isJsSourceFile(owner.getSourceFile()))
4263
+ continue;
4264
+ let fields = lowerer.inheritedJsFieldWrites.get(owner);
4265
+ if (!fields)
4266
+ lowerer.inheritedJsFieldWrites.set(owner, fields = new Map());
4267
+ const existing = fields.get(name);
4268
+ if (existing)
4269
+ existing.push(...expressions);
4270
+ else
4271
+ fields.set(name, [...expressions]);
4272
+ }
4273
+ }
4274
+ markBases(base);
4275
+ }
4276
+ };
4277
+ if (instance)
4278
+ markBases(instance);
4279
+ });
4280
+ }
4281
+ }
3961
4282
  /** Discover overrides before choosing inferred method ABIs. Class collection
3962
4283
  * visits bases first, including imported bases and class expressions, so the
3963
4284
  * collected subclass graph cannot answer this question yet. The checker
3964
4285
  * hierarchy identifies the original declarations through aliases as well. */
3965
4286
  export function collectVirtualJsMethods(lowerer, files) {
4287
+ const families = [];
3966
4288
  // Record named prototype accesses before collecting method signatures.
3967
4289
  // Those slots need a callable ABI even when JavaScript would otherwise
3968
4290
  // specialize each call independently.
@@ -3985,6 +4307,39 @@ export function collectVirtualJsMethods(lowerer, files) {
3985
4307
  });
3986
4308
  const visit = (node) => {
3987
4309
  if (ts.isClassDeclaration(node) || ts.isClassExpression(node)) {
4310
+ const accessors = node.members.filter((member) => (ts.isGetAccessorDeclaration(member) || ts.isSetAccessorDeclaration(member)) && ts.isIdentifier(member.name) &&
4311
+ !member.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword));
4312
+ if (node.heritageClauses?.length && accessors.length && isJsSourceFile(node.getSourceFile())) {
4313
+ const symbol = lowerer.typeOf(node).getSymbol();
4314
+ const instance = symbol ? lowerer.checker.getDeclaredTypeOfSymbol(symbol) : null;
4315
+ const seen = new Set();
4316
+ const markAccessors = (type) => {
4317
+ const target = type.isTypeReference() ? type.getTarget() : type;
4318
+ if (!target?.isClassOrInterface() || seen.has(target))
4319
+ return;
4320
+ seen.add(target);
4321
+ for (const base of lowerer.checker.getBaseTypes(target)) {
4322
+ for (const member of accessors) {
4323
+ if (!ts.isIdentifier(member.name))
4324
+ continue;
4325
+ const property = lowerer.checker.getPropertyOfType(base, member.name.text);
4326
+ for (const declaration of property ? lowerer.checker.declarationsOf(property) : []) {
4327
+ if ((ts.isGetAccessorDeclaration(declaration) || ts.isSetAccessorDeclaration(declaration)) && isJsSourceFile(declaration.getSourceFile())) {
4328
+ lowerer.checkedVirtualJsAccessors.add(declaration);
4329
+ lowerer.checkedVirtualJsAccessors.add(member);
4330
+ for (const twin of node.members)
4331
+ if ((ts.isGetAccessorDeclaration(twin) || ts.isSetAccessorDeclaration(twin)) &&
4332
+ ts.isIdentifier(twin.name) && twin.name.text === member.name.text)
4333
+ lowerer.checkedVirtualJsAccessors.add(twin);
4334
+ }
4335
+ }
4336
+ }
4337
+ markAccessors(base);
4338
+ }
4339
+ };
4340
+ if (instance)
4341
+ markAccessors(instance);
4342
+ }
3988
4343
  const members = node.members.filter((member) => ts.isMethodDeclaration(member) && ts.isIdentifier(member.name) &&
3989
4344
  !member.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword));
3990
4345
  if (node.heritageClauses?.length && members.length > 0) {
@@ -4007,8 +4362,17 @@ export function collectVirtualJsMethods(lowerer, files) {
4007
4362
  if (isJsSourceFile(member.getSourceFile()) && !member.typeParameters &&
4008
4363
  !member.asteriskToken && !member.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword) &&
4009
4364
  !bodyReadsArguments(member) &&
4010
- member.parameters.every((p) => !p.initializer && !p.dotDotDotToken)) {
4365
+ member.parameters.every((p) => !p.dotDotDotToken)) {
4011
4366
  lowerer.virtualJsMethodArity.set(declaration, Math.max(lowerer.virtualJsMethodArity.get(declaration) ?? 0, member.parameters.length));
4367
+ const checked = !declaration.typeParameters && !declaration.asteriskToken &&
4368
+ !declaration.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword) &&
4369
+ !bodyReadsArguments(declaration) &&
4370
+ [...member.parameters, ...declaration.parameters].every((p) => !p.dotDotDotToken);
4371
+ if (checked) {
4372
+ lowerer.checkedVirtualJsMethods.add(declaration);
4373
+ lowerer.checkedVirtualJsMethods.add(member);
4374
+ families.push([declaration, member]);
4375
+ }
4012
4376
  }
4013
4377
  }
4014
4378
  }
@@ -4023,6 +4387,29 @@ export function collectVirtualJsMethods(lowerer, files) {
4023
4387
  };
4024
4388
  for (const file of files)
4025
4389
  ts.walkPreorder(file, visit);
4390
+ for (const member of lowerer.checkedVirtualJsMethods) {
4391
+ const scan = (node) => {
4392
+ if (node !== member && ts.isFunctionLike(node))
4393
+ return;
4394
+ if (ts.isReturnStatement(node) && node.expression)
4395
+ lowerer.checkedVirtualJsValueReturns.add(member);
4396
+ node.forEachChild(scan);
4397
+ };
4398
+ scan(member);
4399
+ }
4400
+ let changed = true;
4401
+ while (changed) {
4402
+ changed = false;
4403
+ for (const [base, derived] of families) {
4404
+ if (!lowerer.checkedVirtualJsValueReturns.has(base) && !lowerer.checkedVirtualJsValueReturns.has(derived))
4405
+ continue;
4406
+ for (const member of [base, derived])
4407
+ if (!lowerer.checkedVirtualJsValueReturns.has(member)) {
4408
+ lowerer.checkedVirtualJsValueReturns.add(member);
4409
+ changed = true;
4410
+ }
4411
+ }
4412
+ }
4026
4413
  }
4027
4414
  /** The receiver's EXACT runtime class, when the expression proves it: a
4028
4415
  * `new C(...)` expression directly, or a const binding initialized with
@@ -4382,6 +4769,10 @@ function lowerClassCtorInner(lowerer, info) {
4382
4769
  export function classMemberNameOf(lowerer, name) {
4383
4770
  if (ts.isIdentifier(name))
4384
4771
  return name.text;
4772
+ if (ts.isStringLiteralLike(name))
4773
+ return name.text;
4774
+ if (ts.isNumericLiteral(name))
4775
+ return String(Number(name.text));
4385
4776
  // #private methods key by their spelled name ('#m') — '#' is
4386
4777
  // unspellable in public identifiers, the accessor-colon precedent.
4387
4778
  if (ts.isPrivateIdentifier(name))
@@ -5341,6 +5732,16 @@ function assignedThisFieldType(lowerer, expr) {
5341
5732
  }
5342
5733
  export function lowerNew(lowerer, expr) {
5343
5734
  const loc = locOf(expr);
5735
+ let intlConstructor = expr.expression;
5736
+ if (ts.isIdentifier(intlConstructor)) {
5737
+ const symbol = lowerer.resolveValueSymbol(intlConstructor);
5738
+ const declaration = symbol ? lowerer.checker.valueDeclarationOf(symbol) : undefined;
5739
+ if (declaration && ts.isVariableDeclaration(declaration) && declaration.initializer)
5740
+ intlConstructor = declaration.initializer;
5741
+ }
5742
+ const intl = ts.isPropertyAccessExpression(intlConstructor) ? lowerer.stdlibGlobalMember(intlConstructor, "Intl") : null;
5743
+ if (intl && intl !== "Segmenter")
5744
+ lowerer.noLowering(`new Intl.${intl}`, expr, undefined, lowerer.checker.getSymbolAtLocation(expr.expression));
5344
5745
  const instanceConstructor = lowerInstanceConstructorNew(lowerer, expr);
5345
5746
  if (instanceConstructor)
5346
5747
  return instanceConstructor;
@@ -5834,7 +6235,7 @@ export function lowerNew(lowerer, expr) {
5834
6235
  }
5835
6236
  if ((expr.arguments?.length ?? 0) > 0 && !entriesLit) {
5836
6237
  lowerer.noLowering("new Map(entries)", expr, "supported seeds: an array literal of [key, value] pair literals, or a " +
5837
- "[K, V][]-typed tuple-array value, a matching Map, or null/undefined");
6238
+ "[K, V][]-typed tuple-array value, a matching collection or collection iterator, or null/undefined");
5838
6239
  }
5839
6240
  if (mapped?.kind === "map") {
5840
6241
  if (!entriesLit)
@@ -5890,8 +6291,8 @@ export function lowerNew(lowerer, expr) {
5890
6291
  type: DYN, loc,
5891
6292
  };
5892
6293
  }
5893
- // `new Set<T>()`: construct + bulk add from native arrays, tuples,
5894
- // or strings. Duplicates collapse in insertion order.
6294
+ // `new Set<T>()`: construct + bulk add from supported values,
6295
+ // including live collection cursors. Duplicates collapse in insertion order.
5895
6296
  if (symbol?.name === "Set" && lowerer.isStdlibSymbol(symbol)) {
5896
6297
  const tsType = lowerer.typeOf(expr);
5897
6298
  let mapped = lowerer.mapTypeOf(tsType);
@@ -5929,7 +6330,7 @@ export function lowerNew(lowerer, expr) {
5929
6330
  }
5930
6331
  }
5931
6332
  if ((expr.arguments?.length ?? 0) > 0) {
5932
- lowerer.noLowering("new Set(values)", expr, "construct the Set empty and add() each value — only nullish values or a matching Set, string, array, or fixed tuple of " +
6333
+ lowerer.noLowering("new Set(values)", expr, "construct the Set empty and add() each value — only nullish values or a matching Set, collection iterator, string, array, or fixed tuple of " +
5933
6334
  "already-legal elements (numbers, strings, or identity references) seeds a Set");
5934
6335
  }
5935
6336
  if (mapped?.kind === "set")
@@ -6164,7 +6565,7 @@ export function lowerNew(lowerer, expr) {
6164
6565
  }
6165
6566
  const callee = lowerer.lowerExpr(expr.expression);
6166
6567
  if (callee.type.kind === "dyn")
6167
- return checkedClassConstruction(lowerer, callee, (expr.arguments ?? []).map((arg) => lowerer.lowerExprExpecting(arg, DYN)), loc);
6568
+ return lowerCheckedConstructor(lowerer, expr, callee);
6168
6569
  if (callee.type.kind !== "classval")
6169
6570
  lowerer.badType(expr.expression, lowerer.typeOf(expr.expression));
6170
6571
  lowerer.noteEdge(`%${info.def.name}.constructor`);
@@ -6189,6 +6590,10 @@ export function lowerNew(lowerer, expr) {
6189
6590
  if (calleeT?.kind === "union") {
6190
6591
  const def = lowerer.unions.get(calleeT.unionId);
6191
6592
  if (def?.arms.some((a) => a.kind === "classval")) {
6593
+ if (def.arms.every((arm) => arm.kind === "classval" || isJsSourceFile(expr.getSourceFile()) && isUnitType(arm)) && lowerer.dynConvertible(calleeT)) {
6594
+ const callee = lowerer.lowerExprExpecting(expr.expression, DYN);
6595
+ return lowerCheckedConstructor(lowerer, expr, callee);
6596
+ }
6192
6597
  lowerer.unsupported("SC1090", expr, "constructing through a union of class values (annotate the slot with the common constructor type — e.g. `new () => Base` — or narrow first)");
6193
6598
  }
6194
6599
  }
@@ -6216,11 +6621,20 @@ export function lowerNew(lowerer, expr) {
6216
6621
  }
6217
6622
  // Checked construction supports emitted classes and builtin typed arrays.
6218
6623
  const callee = tryLowerExpression(lowerer, expr.expression);
6219
- if (callee && (callee.type.kind === "dyn" || callee.type.kind === "func" && lowerer.dynConvertible(callee.type)) && !(expr.arguments ?? []).some(ts.isSpreadElement)) {
6220
- return checkedClassConstruction(lowerer, lowerer.coerceToExpected(callee, DYN), (expr.arguments ?? []).map((arg) => lowerer.lowerExprExpecting(arg, DYN)), loc);
6624
+ if (callee && (callee.type.kind === "dyn" || (callee.type.kind === "func" || callee.type.kind === "classval") && lowerer.dynConvertible(callee.type))) {
6625
+ return lowerCheckedConstructor(lowerer, expr, lowerer.coerceToExpected(callee, DYN));
6221
6626
  }
6222
6627
  lowerer.unsupported("SC1090", expr, "constructing values other than classes declared in the program");
6223
6628
  }
6629
+ function lowerCheckedConstructor(lowerer, expr, callee) {
6630
+ const loc = locOf(expr);
6631
+ const args = expr.arguments ?? [];
6632
+ if (args.some(ts.isSpreadElement)) {
6633
+ const packed = lowerer.completeArgs(args, [{ type: DYN, mode: "dynRest" }], loc, expr)[0];
6634
+ return checkedClassConstructionPacked(lowerer, callee, packed, loc);
6635
+ }
6636
+ return checkedClassConstruction(lowerer, callee, args.map((arg) => lowerer.lowerExprExpecting(arg, DYN)), loc);
6637
+ }
6224
6638
  /** A getter/setter invocation over an accessor target's receiver — the
6225
6639
  * same whole-program devirtualization as method calls: a virtualCall
6226
6640
  * when some strict subclass of the receiver's static class overrides