@scriptc/compiler 0.3.0 → 0.3.1

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 (252) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +5 -2
  2. package/dist/backend/llvm/bigint-wrap.d.ts +4 -0
  3. package/dist/backend/llvm/bigint-wrap.js +590 -0
  4. package/dist/backend/llvm/bigint-wrap.js.map +1 -0
  5. package/dist/backend/llvm/blocks.d.ts +2 -0
  6. package/dist/backend/llvm/blocks.js +4 -0
  7. package/dist/backend/llvm/blocks.js.map +1 -1
  8. package/dist/backend/llvm/call-lifetimes.js +15 -4
  9. package/dist/backend/llvm/call-lifetimes.js.map +1 -1
  10. package/dist/backend/llvm/call-lifetimes.test.js +14 -3
  11. package/dist/backend/llvm/call-lifetimes.test.js.map +1 -1
  12. package/dist/backend/llvm/checked-narrows.test.js +1 -1
  13. package/dist/backend/llvm/checked-narrows.test.js.map +1 -1
  14. package/dist/backend/llvm/classes.js +57 -12
  15. package/dist/backend/llvm/classes.js.map +1 -1
  16. package/dist/backend/llvm/classes.test.js +4 -4
  17. package/dist/backend/llvm/classes.test.js.map +1 -1
  18. package/dist/backend/llvm/common.d.ts +7 -5
  19. package/dist/backend/llvm/common.js +7 -5
  20. package/dist/backend/llvm/common.js.map +1 -1
  21. package/dist/backend/llvm/constant-callbacks.js +10 -28
  22. package/dist/backend/llvm/constant-callbacks.js.map +1 -1
  23. package/dist/backend/llvm/dense-array-access.js +133 -45
  24. package/dist/backend/llvm/dense-array-access.js.map +1 -1
  25. package/dist/backend/llvm/dense-array-access.test.js +53 -1
  26. package/dist/backend/llvm/dense-array-access.test.js.map +1 -1
  27. package/dist/backend/llvm/dyn.d.ts +2 -0
  28. package/dist/backend/llvm/dyn.js +4 -0
  29. package/dist/backend/llvm/dyn.js.map +1 -1
  30. package/dist/backend/llvm/emitter.d.ts +120 -6
  31. package/dist/backend/llvm/emitter.js +676 -77
  32. package/dist/backend/llvm/emitter.js.map +1 -1
  33. package/dist/backend/llvm/emitter.test.js +14 -7
  34. package/dist/backend/llvm/emitter.test.js.map +1 -1
  35. package/dist/backend/llvm/expr-async.js +120 -43
  36. package/dist/backend/llvm/expr-async.js.map +1 -1
  37. package/dist/backend/llvm/expr-async.test.js +1 -1
  38. package/dist/backend/llvm/expr-async.test.js.map +1 -1
  39. package/dist/backend/llvm/expr-bytes.js +51 -36
  40. package/dist/backend/llvm/expr-bytes.js.map +1 -1
  41. package/dist/backend/llvm/expr-callbacks.js +72 -3
  42. package/dist/backend/llvm/expr-callbacks.js.map +1 -1
  43. package/dist/backend/llvm/expr-calls.d.ts +1 -1
  44. package/dist/backend/llvm/expr-calls.js +159 -30
  45. package/dist/backend/llvm/expr-calls.js.map +1 -1
  46. package/dist/backend/llvm/expr-calls.test.d.ts +1 -0
  47. package/dist/backend/llvm/expr-calls.test.js +132 -0
  48. package/dist/backend/llvm/expr-calls.test.js.map +1 -0
  49. package/dist/backend/llvm/expr-containers.js +13 -0
  50. package/dist/backend/llvm/expr-containers.js.map +1 -1
  51. package/dist/backend/llvm/expr-context.d.ts +2 -0
  52. package/dist/backend/llvm/expr-dispatch.js +3 -0
  53. package/dist/backend/llvm/expr-dispatch.js.map +1 -1
  54. package/dist/backend/llvm/expr-dynamic.js +26 -4
  55. package/dist/backend/llvm/expr-dynamic.js.map +1 -1
  56. package/dist/backend/llvm/expr-primitives.d.ts +7 -0
  57. package/dist/backend/llvm/expr-primitives.js +80 -22
  58. package/dist/backend/llvm/expr-primitives.js.map +1 -1
  59. package/dist/backend/llvm/expr-primitives.test.js +95 -5
  60. package/dist/backend/llvm/expr-primitives.test.js.map +1 -1
  61. package/dist/backend/llvm/expr-records.d.ts +9 -0
  62. package/dist/backend/llvm/expr-records.js +134 -16
  63. package/dist/backend/llvm/expr-records.js.map +1 -1
  64. package/dist/backend/llvm/expr-stream-bridges.d.ts +1 -1
  65. package/dist/backend/llvm/expr-stream-bridges.js +80 -1
  66. package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
  67. package/dist/backend/llvm/expr-stream-bridges.test.js +50 -1
  68. package/dist/backend/llvm/expr-stream-bridges.test.js.map +1 -1
  69. package/dist/backend/llvm/int32-abi.d.ts +31 -0
  70. package/dist/backend/llvm/int32-abi.js +62 -0
  71. package/dist/backend/llvm/int32-abi.js.map +1 -0
  72. package/dist/backend/llvm/int32-abi.test.d.ts +1 -0
  73. package/dist/backend/llvm/int32-abi.test.js +107 -0
  74. package/dist/backend/llvm/int32-abi.test.js.map +1 -0
  75. package/dist/backend/llvm/int32-locals.d.ts +30 -0
  76. package/dist/backend/llvm/int32-locals.js +95 -0
  77. package/dist/backend/llvm/int32-locals.js.map +1 -0
  78. package/dist/backend/llvm/integer-values.d.ts +4 -0
  79. package/dist/backend/llvm/integer-values.js +30 -1
  80. package/dist/backend/llvm/integer-values.js.map +1 -1
  81. package/dist/backend/llvm/integer-views.d.ts +8 -1
  82. package/dist/backend/llvm/integer-views.js +47 -2
  83. package/dist/backend/llvm/integer-views.js.map +1 -1
  84. package/dist/backend/llvm/lazy-captures.d.ts +16 -0
  85. package/dist/backend/llvm/lazy-captures.js +88 -2
  86. package/dist/backend/llvm/lazy-captures.js.map +1 -1
  87. package/dist/backend/llvm/lazy-captures.test.js +48 -0
  88. package/dist/backend/llvm/lazy-captures.test.js.map +1 -1
  89. package/dist/backend/llvm/lib-dispatch.js +14 -0
  90. package/dist/backend/llvm/lib-dispatch.js.map +1 -1
  91. package/dist/backend/llvm/lib-filesystem.js +3 -0
  92. package/dist/backend/llvm/lib-filesystem.js.map +1 -1
  93. package/dist/backend/llvm/lib-shared.js +7 -0
  94. package/dist/backend/llvm/lib-shared.js.map +1 -1
  95. package/dist/backend/llvm/local-array-reads.js +21 -2
  96. package/dist/backend/llvm/local-array-reads.js.map +1 -1
  97. package/dist/backend/llvm/local-array-reads.test.js +3 -2
  98. package/dist/backend/llvm/local-array-reads.test.js.map +1 -1
  99. package/dist/backend/llvm/local-union-storage.test.js +2 -2
  100. package/dist/backend/llvm/local-union-storage.test.js.map +1 -1
  101. package/dist/backend/llvm/map-read-lifetimes.test.js +2 -2
  102. package/dist/backend/llvm/map-read-lifetimes.test.js.map +1 -1
  103. package/dist/backend/llvm/reference-effects.js +2 -0
  104. package/dist/backend/llvm/reference-effects.js.map +1 -1
  105. package/dist/backend/llvm/reference-writes.d.ts +3 -0
  106. package/dist/backend/llvm/reference-writes.js +10 -2
  107. package/dist/backend/llvm/reference-writes.js.map +1 -1
  108. package/dist/backend/llvm/regex-matchers.d.ts +39 -0
  109. package/dist/backend/llvm/regex-matchers.js +1649 -0
  110. package/dist/backend/llvm/regex-matchers.js.map +1 -0
  111. package/dist/backend/llvm/regex-matchers.test.d.ts +1 -0
  112. package/dist/backend/llvm/regex-matchers.test.js +96 -0
  113. package/dist/backend/llvm/regex-matchers.test.js.map +1 -0
  114. package/dist/backend/llvm/shapes.d.ts +36 -1
  115. package/dist/backend/llvm/shapes.js +127 -14
  116. package/dist/backend/llvm/shapes.js.map +1 -1
  117. package/dist/backend/llvm/stack-unions.test.js +1 -1
  118. package/dist/backend/llvm/stack-unions.test.js.map +1 -1
  119. package/dist/backend/llvm/string-construction.test.js +2 -2
  120. package/dist/backend/llvm/string-construction.test.js.map +1 -1
  121. package/dist/backend/llvm/string-lifetimes.test.js +5 -5
  122. package/dist/backend/llvm/string-lifetimes.test.js.map +1 -1
  123. package/dist/backend/llvm/string-literal-equality.d.ts +22 -0
  124. package/dist/backend/llvm/string-literal-equality.js +78 -0
  125. package/dist/backend/llvm/string-literal-equality.js.map +1 -0
  126. package/dist/backend/llvm/switch-dispatch.js +59 -13
  127. package/dist/backend/llvm/switch-dispatch.js.map +1 -1
  128. package/dist/backend/llvm/switch-dispatch.test.js +71 -6
  129. package/dist/backend/llvm/switch-dispatch.test.js.map +1 -1
  130. package/dist/backend/llvm/union-retype.test.d.ts +1 -0
  131. package/dist/backend/llvm/union-retype.test.js +229 -0
  132. package/dist/backend/llvm/union-retype.test.js.map +1 -0
  133. package/dist/backend/llvm/wrapping-sums.d.ts +17 -0
  134. package/dist/backend/llvm/wrapping-sums.js +113 -0
  135. package/dist/backend/llvm/wrapping-sums.js.map +1 -0
  136. package/dist/backend/loop-polls.js +1 -0
  137. package/dist/backend/loop-polls.js.map +1 -1
  138. package/dist/backend/mangle.d.ts +9 -0
  139. package/dist/backend/mangle.js +15 -0
  140. package/dist/backend/mangle.js.map +1 -1
  141. package/dist/backend/may-throw.js +6 -3
  142. package/dist/backend/may-throw.js.map +1 -1
  143. package/dist/backend/runtime-abi.d.ts +2 -2
  144. package/dist/backend/runtime-abi.js +2 -2
  145. package/dist/backend/runtime-pack-targets.test.js +1 -1
  146. package/dist/backend/runtime-pack.test.js +1 -1
  147. package/dist/contracts/check.js +4 -0
  148. package/dist/contracts/check.js.map +1 -1
  149. package/dist/frontend/lowering/array-values.d.ts +14 -0
  150. package/dist/frontend/lowering/array-values.js +29 -0
  151. package/dist/frontend/lowering/array-values.js.map +1 -1
  152. package/dist/frontend/lowering/containers/array-callbacks.js +40 -0
  153. package/dist/frontend/lowering/containers/array-callbacks.js.map +1 -1
  154. package/dist/frontend/lowering/containers/array-pipelines.d.ts +54 -0
  155. package/dist/frontend/lowering/containers/array-pipelines.js +1827 -0
  156. package/dist/frontend/lowering/containers/array-pipelines.js.map +1 -0
  157. package/dist/frontend/lowering/containers/exec-result-uses.d.ts +10 -0
  158. package/dist/frontend/lowering/containers/exec-result-uses.js +88 -0
  159. package/dist/frontend/lowering/containers/exec-result-uses.js.map +1 -0
  160. package/dist/frontend/lowering/containers/string-and-regexp.js +15 -7
  161. package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
  162. package/dist/frontend/lowering/containers/string-replacement.d.ts +2 -1
  163. package/dist/frontend/lowering/containers/string-replacement.js +32 -136
  164. package/dist/frontend/lowering/containers/string-replacement.js.map +1 -1
  165. package/dist/frontend/lowering/devirtualize.d.ts +33 -0
  166. package/dist/frontend/lowering/devirtualize.js +199 -0
  167. package/dist/frontend/lowering/devirtualize.js.map +1 -0
  168. package/dist/frontend/lowering/expressions/nullish-assignment.js +55 -7
  169. package/dist/frontend/lowering/expressions/nullish-assignment.js.map +1 -1
  170. package/dist/frontend/lowering/identifier-uses.d.ts +7 -0
  171. package/dist/frontend/lowering/identifier-uses.js +23 -0
  172. package/dist/frontend/lowering/identifier-uses.js.map +1 -0
  173. package/dist/frontend/lowering/iterator-adapters.js +51 -3
  174. package/dist/frontend/lowering/iterator-adapters.js.map +1 -1
  175. package/dist/frontend/lowering/lower-array-sort.js +13 -0
  176. package/dist/frontend/lowering/lower-array-sort.js.map +1 -1
  177. package/dist/frontend/lowering/lower-calls.js +64 -30
  178. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  179. package/dist/frontend/lowering/lower-classes.js +1 -11
  180. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  181. package/dist/frontend/lowering/lower-console.d.ts +14 -0
  182. package/dist/frontend/lowering/lower-console.js +195 -0
  183. package/dist/frontend/lowering/lower-console.js.map +1 -0
  184. package/dist/frontend/lowering/lower-exprs.js +135 -3
  185. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  186. package/dist/frontend/lowering/lower-functions.js +7 -3
  187. package/dist/frontend/lowering/lower-functions.js.map +1 -1
  188. package/dist/frontend/lowering/lower-generators.d.ts +10 -0
  189. package/dist/frontend/lowering/lower-generators.js +108 -41
  190. package/dist/frontend/lowering/lower-generators.js.map +1 -1
  191. package/dist/frontend/lowering/lower-modules.js +4 -0
  192. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  193. package/dist/frontend/lowering/lower-stream.js +13 -10
  194. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  195. package/dist/frontend/lowering/lowerer.d.ts +25 -4
  196. package/dist/frontend/lowering/lowerer.js +120 -47
  197. package/dist/frontend/lowering/lowerer.js.map +1 -1
  198. package/dist/frontend/lowering/nan-coded-reads.d.ts +16 -0
  199. package/dist/frontend/lowering/nan-coded-reads.js +108 -1
  200. package/dist/frontend/lowering/nan-coded-reads.js.map +1 -1
  201. package/dist/frontend/lowering/runtime-optional-bounds.d.ts +4 -0
  202. package/dist/frontend/lowering/runtime-optional-bounds.js +2 -0
  203. package/dist/frontend/lowering/runtime-optional-bounds.js.map +1 -1
  204. package/dist/frontend/lowering/runtime-optional-bounds.test.js +27 -0
  205. package/dist/frontend/lowering/runtime-optional-bounds.test.js.map +1 -1
  206. package/dist/frontend/lowering/split-consumers.js +2 -18
  207. package/dist/frontend/lowering/split-consumers.js.map +1 -1
  208. package/dist/frontend/lowering/surfaces.js +3 -8
  209. package/dist/frontend/lowering/surfaces.js.map +1 -1
  210. package/dist/frontend/lowering/union-retag.d.ts +6 -1
  211. package/dist/frontend/lowering/union-retag.js +64 -1
  212. package/dist/frontend/lowering/union-retag.js.map +1 -1
  213. package/dist/frontend/lowering/union-retag.test.js +46 -0
  214. package/dist/frontend/lowering/union-retag.test.js.map +1 -1
  215. package/dist/frontend/type-mapper.js +16 -3
  216. package/dist/frontend/type-mapper.js.map +1 -1
  217. package/dist/ir/builtin-effects.js +2 -0
  218. package/dist/ir/builtin-effects.js.map +1 -1
  219. package/dist/ir/builtin-signatures.d.ts +1 -1
  220. package/dist/ir/builtin-signatures.js +12 -1
  221. package/dist/ir/builtin-signatures.js.map +1 -1
  222. package/dist/ir/function-references.d.ts +12 -0
  223. package/dist/ir/function-references.js +29 -0
  224. package/dist/ir/function-references.js.map +1 -0
  225. package/dist/ir/function-references.test.d.ts +1 -0
  226. package/dist/ir/function-references.test.js +276 -0
  227. package/dist/ir/function-references.test.js.map +1 -0
  228. package/dist/ir/int32-slots.d.ts +7 -4
  229. package/dist/ir/int32-slots.js +214 -49
  230. package/dist/ir/int32-slots.js.map +1 -1
  231. package/dist/ir/int32-slots.test.js +38 -1
  232. package/dist/ir/int32-slots.test.js.map +1 -1
  233. package/dist/ir/integer-ranges.d.ts +4 -4
  234. package/dist/ir/integer-ranges.js +89 -64
  235. package/dist/ir/integer-ranges.js.map +1 -1
  236. package/dist/ir/integer-ranges.test.js +71 -9
  237. package/dist/ir/integer-ranges.test.js.map +1 -1
  238. package/dist/ir/intrinsic-signatures.js +1 -0
  239. package/dist/ir/intrinsic-signatures.js.map +1 -1
  240. package/dist/ir/ir.d.ts +52 -6
  241. package/dist/ir/ir.js +1 -0
  242. package/dist/ir/ir.js.map +1 -1
  243. package/dist/ir/runtime-features.js +3 -2
  244. package/dist/ir/runtime-features.js.map +1 -1
  245. package/dist/ir/traverse.js +4 -0
  246. package/dist/ir/traverse.js.map +1 -1
  247. package/dist/ir/validate.js +57 -6
  248. package/dist/ir/validate.js.map +1 -1
  249. package/dist/ir/validate.test.js +25 -7
  250. package/dist/ir/validate.test.js.map +1 -1
  251. package/package.json +20 -20
  252. package/surface-manifest.json +1 -17
@@ -15,7 +15,7 @@ import { widthCoerce, applyWidthLift, unionRecordWidthHelper, recordWidthHelper,
15
15
  import { funcReturnWidthAdapter, coercibleValue, cleanFuncAdaptable, funcCoerceAdapter, spawnResFnAdapterPlan, spawnResFnAdapter, } from "./coercions/function-adapters.js";
16
16
  import { unionRetagMappable, narrowedRetagHelper, strandedUnitTrap, strandedCoercionTrap, recordUnionWrapHelper, unionRetagHelper, narrowedArmHelper, checkedNarrowCall, checkedNarrowOperand, deferredReadHelper, } from "./coercions/unions.js";
17
17
  import { lowerUtilTypeValue, pathModuleValue, utilTypesModuleValue, } from "./lower-builtin-values.js";
18
- import { transformStmtList } from "../../ir/traverse.js";
18
+ import { devirtualizeVirtualCalls } from "./devirtualize.js";
19
19
  import { RuntimeOptionalProvenance } from "./runtime-optional-provenance.js";
20
20
  import { presentAtUse, reassignedBindings } from "./runtime-optional-guards.js";
21
21
  import { NarrowingStability } from "./narrowing-stability.js";
@@ -77,6 +77,7 @@ import { lowerCall, lowerPromiseMethodCall, lowerFilterNarrowCall } from "./lowe
77
77
  import { lowerFfiCall, validateFfiImports } from "./native-ffi.js";
78
78
  import { isTopLevelFnSymbol, lowerNestedFunctionDecl, lowerLambda, lowerFunction, } from "./lower-functions.js";
79
79
  import { lowerArrayMethodCall } from "./containers/array-methods.js";
80
+ import { fuseArrayPipelines } from "./containers/array-pipelines.js";
80
81
  import { lowerMapMethodCall, lowerMapForEachCall, lowerSetMethodCall, lowerSetForEachCall, } from "./containers/collection-methods.js";
81
82
  import { lowerEnvToPairsHelper } from "./containers/indexed-objects.js";
82
83
  import { lowerBufferStaticCall, lowerBytesMethodCall, lowerBytesNew } from "./containers/bytes.js";
@@ -104,6 +105,7 @@ import { lowerDiagnosticsChannelMethodCall, lowerDiagnosticsChannelProperty, low
104
105
  import { lowerErrorCodeProperty } from "./builtins/errors.js";
105
106
  import { lowerProcessProperty, lowerProcessMethodCall, lowerProcessOptionalMethodCall, lowerProcessStreamProperty, } from "./builtins/process.js";
106
107
  import { isConsoleLog, consoleCallMember } from "./builtins/console.js";
108
+ import { lowerConsoleNew } from "./lower-console.js";
107
109
  import { lowerNumberStaticCall, lowerNumberStaticProperty } from "./builtins/numbers.js";
108
110
  import { lowerDateCall } from "./builtins/dates.js";
109
111
  import { lowerFsConstantsProperty, lowerBuiltinConstantsProperty, builtinConstantBindingOf, builtinConstantsDestructureDecl, } from "./builtins/constants.js";
@@ -1471,6 +1473,9 @@ export class Lowerer {
1471
1473
  /** Synthetic array-HOF loop functions (map/filter/forEach desugar),
1472
1474
  * interned per method + element/callback-result type: key → fn name. */
1473
1475
  arrHofHelpers = new Map();
1476
+ /** What each array-HOF helper computes, keyed by helper name: the chain
1477
+ * fusion pass reads it to recognize pipelines of helper calls. */
1478
+ arrHofInfo = new Map();
1474
1479
  /** Per-arm calls through union-typed class receivers, interned by the
1475
1480
  * receiver union, member, completed argument ABI, and result type. */
1476
1481
  unionCallHelpers = new Map();
@@ -1776,6 +1781,9 @@ export class Lowerer {
1776
1781
  * can contain any retained descendant, but importing its declaration
1777
1782
  * alone does not make every descendant constructible. */
1778
1783
  constructedClasses = null;
1784
+ /** Set while a subclass constructor's super() call notes its base
1785
+ * constructor edge: that edge does not instantiate the base exactly. */
1786
+ superConstructorEdge = false;
1779
1787
  virtualEdges = new Map();
1780
1788
  classCanBeConstructed(info) {
1781
1789
  return (this.constructedClasses === null ||
@@ -2961,7 +2969,6 @@ export class Lowerer {
2961
2969
  const signatureBySymbol = new Map();
2962
2970
  const methodFamilies = new Map();
2963
2971
  const familyBySymbol = new Map();
2964
- const optionalMethodFamilies = new Set();
2965
2972
  for (const [symbol, sig] of this.fnSigsBySymbol)
2966
2973
  signatureBySymbol.set(symbol, { params: sig.params, returnType: sig.returnType, top: sig });
2967
2974
  for (const decl of fnDecls) {
@@ -3252,6 +3259,11 @@ export class Lowerer {
3252
3259
  const symbol = symbolOf(e.name);
3253
3260
  if (symbol && optionalSymbols.has(symbol))
3254
3261
  return true;
3262
+ // A getter read is a call of its body.
3263
+ if (symbol &&
3264
+ (symbol.flags & ts.SymbolFlags.GetAccessor) !== 0 &&
3265
+ optionalReturns.has(symbol))
3266
+ return true;
3255
3267
  }
3256
3268
  if (ts.isCallExpression(e) && ts.isIdentifier(e.expression)) {
3257
3269
  const symbol = callableSymbolOf(e.expression);
@@ -3326,6 +3338,27 @@ export class Lowerer {
3326
3338
  return null;
3327
3339
  return { kind: "union", unionId: this.unions.intern([F64, STRING]) };
3328
3340
  };
3341
+ /** The union of primitive result types, or null when any is missing or
3342
+ * not a number, string or boolean (or a union of them). */
3343
+ const joinPrimitiveTypes = (types) => {
3344
+ const arms = new Map();
3345
+ for (const type of types) {
3346
+ if (!type)
3347
+ return null;
3348
+ const parts = type.kind === "union" ? this.unions.get(type.unionId)?.arms : [type];
3349
+ if (!parts)
3350
+ return null;
3351
+ for (const arm of parts) {
3352
+ if (arm.kind !== "f64" && arm.kind !== "string" && arm.kind !== "bool")
3353
+ return null;
3354
+ arms.set(typeKey(arm), arm);
3355
+ }
3356
+ }
3357
+ const sorted = [...arms.entries()].sort(([a], [b]) => (a < b ? -1 : 1)).map(([, t]) => t);
3358
+ if (sorted.length === 1)
3359
+ return sorted[0];
3360
+ return { kind: "union", unionId: this.unions.intern(sorted) };
3361
+ };
3329
3362
  const noteField = (decl, name) => {
3330
3363
  if (!ts.isIdentifier(decl.name))
3331
3364
  return false;
@@ -4333,9 +4366,6 @@ export class Lowerer {
4333
4366
  if (arg &&
4334
4367
  (this.typeOf(arg).flags & (ts.TypeFlags.Undefined | ts.TypeFlags.Void)) === 0)
4335
4368
  continue;
4336
- const family = familyBySymbol.get(symbol);
4337
- if (family)
4338
- optionalMethodFamilies.add(family);
4339
4369
  for (const target of familyBySymbol.get(symbol) ?? [symbol]) {
4340
4370
  const shape = signatureBySymbol.get(target)?.params[i];
4341
4371
  if (!shape || shape.mode !== "required")
@@ -4452,8 +4482,6 @@ export class Lowerer {
4452
4482
  // Promote every implementation and its parameter bindings so
4453
4483
  // downstream calls and returns see the same optional value.
4454
4484
  const family = familyBySymbol.get(symbol);
4455
- if (family)
4456
- optionalMethodFamilies.add(family);
4457
4485
  for (const target of family ?? [symbol]) {
4458
4486
  const parameterShape = signatureBySymbol.get(target)?.params[i];
4459
4487
  if (!parameterShape)
@@ -4580,18 +4608,35 @@ export class Lowerer {
4580
4608
  changed = true;
4581
4609
  }
4582
4610
  }
4583
- // Every implementation of a virtual slot must retain the same ABI,
4584
- // including when just one body forwards an omitted parameter.
4585
- for (const family of optionalMethodFamilies) {
4586
- if (!family.some((symbol) => optionalReturns.has(symbol)))
4611
+ // Every implementation of a virtual slot must retain the same ABI:
4612
+ // when one body can return undefined at runtime (an unchecked element
4613
+ // read, a forwarded omitted parameter), the abstract or base
4614
+ // declaration and every override return the widened type too.
4615
+ for (const family of methodFamilies.values()) {
4616
+ if (family.length < 2)
4587
4617
  continue;
4588
- for (const symbol of family) {
4618
+ const optional = family.some((symbol) => optionalReturns.has(symbol));
4619
+ for (const symbol of optional ? family : []) {
4589
4620
  if (!optionalReturns.has(symbol)) {
4590
4621
  optionalReturns.add(symbol);
4591
4622
  provenance?.note("return", functionDeclBySymbol.get(symbol), undefined, "(override family)");
4592
4623
  changed = true;
4593
4624
  }
4594
4625
  }
4626
+ // A primitive-widened result (`names[i] + 1` is NaN for a missing
4627
+ // string) likewise becomes the slot's result for every member.
4628
+ if (!family.some((symbol) => arithmeticReturns.has(symbol)))
4629
+ continue;
4630
+ const joined = joinPrimitiveTypes(family.map((symbol) => arithmeticReturns.get(symbol) ?? signatureBySymbol.get(symbol)?.returnType));
4631
+ if (!joined)
4632
+ continue;
4633
+ for (const symbol of family) {
4634
+ const previous = arithmeticReturns.get(symbol);
4635
+ if (previous && typeEquals(previous, joined))
4636
+ continue;
4637
+ arithmeticReturns.set(symbol, joined);
4638
+ changed = true;
4639
+ }
4595
4640
  }
4596
4641
  }
4597
4642
  // NaN-coded slots convert optional values on entry instead of holding
@@ -4959,6 +5004,8 @@ export class Lowerer {
4959
5004
  /** Final retention, pruning, and module assembly shared by ordinary emit
4960
5005
  * and the retained reachability worklist. */
4961
5006
  finishModule(functions) {
5007
+ if (this.diags.length === 0)
5008
+ fuseArrayPipelines(this, functions);
4962
5009
  finalizeClassMethodValues(this, functions);
4963
5010
  trackClassFieldCreation(this, functions);
4964
5011
  // Globals typed by a class that never REGISTERED (a JS class whose
@@ -5343,11 +5390,17 @@ export class Lowerer {
5343
5390
  };
5344
5391
  const reachable = new Set();
5345
5392
  this.constructedClasses = new Set();
5393
+ // Every constructor edge except super() may create an instance of
5394
+ // exactly that class (`new C`, class values, library roots, dynamic
5395
+ // construction, ...).
5396
+ const instantiated = new Set();
5346
5397
  const queue = [];
5347
5398
  const loweredUnits = new Map();
5348
5399
  const initFunctions = [];
5349
5400
  const instanceFunctions = [];
5350
5401
  this.onEdge = (name) => {
5402
+ if (!this.superConstructorEdge && name.endsWith(".constructor"))
5403
+ instantiated.add(name.slice(1, -".constructor".length));
5351
5404
  if (reachable.has(name))
5352
5405
  return;
5353
5406
  reachable.add(name);
@@ -5553,35 +5606,14 @@ export class Lowerer {
5553
5606
  ...this.liftedFns,
5554
5607
  ...this.implicitFns,
5555
5608
  ];
5556
- // The worklist can leave a virtual site with only its base method.
5609
+ // The worklist can leave a virtual site with a single implementation.
5557
5610
  // Devirtualize after construction/override reachability has settled.
5558
- for (const fn of functions)
5559
- fn.body = transformStmtList(fn.body, {
5560
- stmt: (statement) => statement,
5561
- expr: (expression) => {
5562
- if (expression.kind !== "virtualCall")
5563
- return expression;
5564
- const info = this.classes.get(expression.className);
5565
- const method = info && this.findMethodOn(info, expression.method);
5566
- if (!method ||
5567
- method.sig.abstract ||
5568
- [...this.classes.values()].some((candidate) => this.isSubclassOf(candidate.def.name, expression.className) &&
5569
- candidate.def.name !== expression.className &&
5570
- candidate.methods.has(expression.method) &&
5571
- reachable.has(`%${candidate.def.name}.${expression.method}`)))
5572
- return expression;
5573
- return {
5574
- kind: "call",
5575
- callee: `%${method.declarer.def.name}.${expression.method}`,
5576
- args: [
5577
- this.upcastTo(expression.args[0], method.declarer.def.name),
5578
- ...expression.args.slice(1),
5579
- ],
5580
- type: expression.type,
5581
- loc: expression.loc,
5582
- };
5583
- },
5584
- });
5611
+ devirtualizeVirtualCalls(this, functions, {
5612
+ reachable,
5613
+ instantiated,
5614
+ library: extraRoots !== undefined,
5615
+ files: parts.map((fp) => fp.sf),
5616
+ });
5585
5617
  this.reachableForArtifacts = reachable;
5586
5618
  return { reachable, result: this.finishModule(functions) };
5587
5619
  }
@@ -5591,6 +5623,17 @@ export class Lowerer {
5591
5623
  if (this.onEdge)
5592
5624
  this.onEdge(name);
5593
5625
  }
5626
+ /** A subclass constructor's super() edge: the base constructor runs, but
5627
+ * no instance of exactly the base class is created. */
5628
+ noteSuperConstructorEdge(name) {
5629
+ this.superConstructorEdge = true;
5630
+ try {
5631
+ this.noteEdge(name);
5632
+ }
5633
+ finally {
5634
+ this.superConstructorEdge = false;
5635
+ }
5636
+ }
5594
5637
  /** Discovery hook for virtual dispatch: a virtualCall on `info`'s static
5595
5638
  * class reaches the nearest declaration at/above it plus every override
5596
5639
  * on a STRICT descendant (receivers of sibling branches can't flow into
@@ -7391,10 +7434,10 @@ export class Lowerer {
7391
7434
  }
7392
7435
  /** The value of a `return` statement. In an async function `return p`
7393
7436
  * where p is a promise flattens (JS: the returned promise's settlement
7394
- * becomes the async function's result), so it lowers exactly as
7395
- * `return await p` — the awaitExpr parks the fiber and re-throws
7396
- * rejections, which IS the flattening. Everything else flows into the
7397
- * function's return slot through the usual coercion path. */
7437
+ * becomes the async function's result) through an adopting awaitExpr,
7438
+ * which parks the fiber and re-throws rejections after the adoption's
7439
+ * then-job turn. Everything else flows into the function's return slot
7440
+ * through the usual coercion path. */
7398
7441
  /** The value of `return <expr>` against the context's declared return —
7399
7442
  * or NULL for a bare return: `return undefined`/`return null` in a
7400
7443
  * void-returning function (`{ bar() { return undefined } }`, inferred
@@ -7425,11 +7468,38 @@ export class Lowerer {
7425
7468
  if (expected.kind === "void" && e.kind === "unitLit")
7426
7469
  return null;
7427
7470
  if (this.ctx.isAsync && e.type.kind === "promise" && expected.kind !== "promise") {
7428
- const awaited = { kind: "awaitExpr", value: e, type: e.type.inner, loc: e.loc };
7471
+ const awaited = this.returnedPromiseAwait(e);
7429
7472
  return this.coerceInto(node, awaited, expected);
7430
7473
  }
7431
7474
  return this.coerceInto(node, e, expected);
7432
7475
  }
7476
+ /** Whether a promise returned here resolves the function's own promise
7477
+ * by adoption (async functions; async generators await their return
7478
+ * operand instead). */
7479
+ adoptsReturnedPromise() {
7480
+ return this.ctx.isAsync === true && !this.ctx.generator;
7481
+ }
7482
+ /** `return p` of a promise into a non-promise result `R` (a void result
7483
+ * drops the settled value; widening keeps the adopting await the return's
7484
+ * own value). */
7485
+ adoptingReturn(e, R, coerce) {
7486
+ const loc = e.loc;
7487
+ if (R.kind !== "void")
7488
+ return { kind: "return", value: coerce(this.returnedPromiseAwait(e)), loc };
7489
+ const widened = e.type.kind === "promise" && e.type.inner.kind !== "void"
7490
+ ? { kind: "promiseVoidWiden", value: e, type: { kind: "promise", inner: VOID }, loc }
7491
+ : e;
7492
+ return { kind: "return", value: this.returnedPromiseAwait(widened), loc };
7493
+ }
7494
+ /** The await a returned promise `e` lowers to: adopting in async
7495
+ * functions (one then-job turn first, outside the function's handlers). */
7496
+ returnedPromiseAwait(e) {
7497
+ if (e.type.kind !== "promise")
7498
+ throw new InternalCompilerError("returned-promise await of a non-promise");
7499
+ if (!this.adoptsReturnedPromise())
7500
+ return { kind: "awaitExpr", value: e, type: e.type.inner, loc: e.loc };
7501
+ return { kind: "awaitExpr", value: e, type: e.type.inner, adopt: true, loc: e.loc };
7502
+ }
7433
7503
  /** `return <expr>` lowered as a STATEMENT against the declared return.
7434
7504
  * Void-returning contexts get the JS drop: a contextually void-typed
7435
7505
  * function may return a value (`fv = function() { return 0; }` into a
@@ -7441,7 +7511,9 @@ export class Lowerer {
7441
7511
  if (expected.kind === "void") {
7442
7512
  let e = this.lowerExpr(node);
7443
7513
  if (this.ctx.isAsync && e.type.kind === "promise") {
7444
- e = { kind: "awaitExpr", value: e, type: e.type.inner, loc: e.loc };
7514
+ if (this.adoptsReturnedPromise())
7515
+ return this.adoptingReturn(e, VOID, (x) => x);
7516
+ e = this.returnedPromiseAwait(e);
7445
7517
  }
7446
7518
  if (e.kind === "unitLit")
7447
7519
  return { kind: "return", value: null, loc };
@@ -9011,7 +9083,8 @@ export class Lowerer {
9011
9083
  const builtin = lowerAbortControllerNew(this, expr) ??
9012
9084
  lowerFetchWebNew(this, expr) ??
9013
9085
  lowerResponseNew(this, expr) ??
9014
- lowerStaticReadableStreamNew(this, expr);
9086
+ lowerStaticReadableStreamNew(this, expr) ??
9087
+ lowerConsoleNew(this, expr);
9015
9088
  return (builtin ?? this.withRuntimeOptionalClassValue(expr.expression, () => lowerNew(this, expr)));
9016
9089
  }
9017
9090
  lowerFieldRead(expr) {