@scriptc/compiler 0.0.34 → 0.0.35

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 (66) hide show
  1. package/dist/backend/cc-cache.test.js +969 -7
  2. package/dist/backend/cc-cache.test.js.map +1 -1
  3. package/dist/backend/cc.d.ts +90 -18
  4. package/dist/backend/cc.js +953 -276
  5. package/dist/backend/cc.js.map +1 -1
  6. package/dist/backend/llvm/split.d.ts +43 -0
  7. package/dist/backend/llvm/split.js +227 -0
  8. package/dist/backend/llvm/split.js.map +1 -0
  9. package/dist/backend/llvm/split.test.d.ts +1 -0
  10. package/dist/backend/llvm/split.test.js +102 -0
  11. package/dist/backend/llvm/split.test.js.map +1 -0
  12. package/dist/backend/object-localize.test.js +20 -0
  13. package/dist/backend/object-localize.test.js.map +1 -1
  14. package/dist/executable/early-cache.d.ts +86 -0
  15. package/dist/executable/early-cache.js +460 -0
  16. package/dist/executable/early-cache.js.map +1 -0
  17. package/dist/executable/early-cache.test.d.ts +1 -0
  18. package/dist/executable/early-cache.test.js +300 -0
  19. package/dist/executable/early-cache.test.js.map +1 -0
  20. package/dist/ffi/profile.d.ts +7 -2
  21. package/dist/ffi/profile.js +1 -0
  22. package/dist/ffi/profile.js.map +1 -1
  23. package/dist/frontend/lowering/lower-builtins.js +2 -2
  24. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  25. package/dist/frontend/lowering/lower-calls.js +14 -4
  26. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  27. package/dist/frontend/lowering/lower-containers.js +18 -23
  28. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  29. package/dist/frontend/lowering/lower-exprs.js +22 -10
  30. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  31. package/dist/frontend/lowering/lower-island.js +3 -3
  32. package/dist/frontend/lowering/lower-island.js.map +1 -1
  33. package/dist/frontend/lowering/lower-mixins.js +1 -1
  34. package/dist/frontend/lowering/lower-mixins.js.map +1 -1
  35. package/dist/frontend/lowering/lower-stmts.js +1 -1
  36. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  37. package/dist/frontend/lowering/lowerer.d.ts +6 -0
  38. package/dist/frontend/lowering/lowerer.js +230 -81
  39. package/dist/frontend/lowering/lowerer.js.map +1 -1
  40. package/dist/frontend/lowering/surfaces.js +1 -1
  41. package/dist/frontend/lowering/surfaces.js.map +1 -1
  42. package/dist/frontend/program.js +42 -13
  43. package/dist/frontend/program.js.map +1 -1
  44. package/dist/frontend/ts7/checker.d.ts +40 -2
  45. package/dist/frontend/ts7/checker.js +194 -32
  46. package/dist/frontend/ts7/checker.js.map +1 -1
  47. package/dist/frontend/types.js +20 -42
  48. package/dist/frontend/types.js.map +1 -1
  49. package/dist/index.d.ts +4 -1
  50. package/dist/index.js +219 -101
  51. package/dist/index.js.map +1 -1
  52. package/dist/ir/nodes.d.ts +6 -0
  53. package/dist/ir/nodes.js +28 -0
  54. package/dist/ir/nodes.js.map +1 -1
  55. package/dist/ir/validate.js +7 -1
  56. package/dist/ir/validate.js.map +1 -1
  57. package/dist/library/early-cache.js +4 -23
  58. package/dist/library/early-cache.js.map +1 -1
  59. package/dist/library/implementation-identity.d.ts +23 -0
  60. package/dist/library/implementation-identity.js +84 -0
  61. package/dist/library/implementation-identity.js.map +1 -0
  62. package/dist/startup-cache.d.ts +6 -0
  63. package/dist/startup-cache.js +6 -0
  64. package/dist/startup-cache.js.map +1 -0
  65. package/package.json +3 -2
  66. package/surface-manifest.json +1 -1
@@ -1677,6 +1677,12 @@ export declare class Lowerer {
1677
1677
  lowerGenericFnValue(ref: ts.Expression, info: GenericFnInfo): IrExpr;
1678
1678
  inferTypeParamBindings(expr: ts.CallExpression, info: GenericFnInfo, rsig: ts.Signature, tsBindings?: Map<ts.Symbol, ts.Type>): Map<ts.Symbol, IrType>;
1679
1679
  lowerGenericInstance(info: GenericFnInfo, inst: GenericInstance): IrFunction;
1680
+ /** Checker work class SHAPE collection performs inside otherwise
1681
+ * deferred JavaScript bodies. Constructor assignments declare fields,
1682
+ * so collection asks for each `this.x` symbol and RHS type even when the
1683
+ * constructor is unreachable. Keep that mandatory work batched without
1684
+ * sweeping unrelated dead method bodies. */
1685
+ private prefetchClassCollection;
1680
1686
  collectClassShape(decl: ts.ClassDeclaration): void;
1681
1687
  collectClassShapeInner(decl: ts.ClassLikeDeclaration, jsNameOverride?: string, inst?: {
1682
1688
  family: ClassInfo;
@@ -24,7 +24,7 @@ import { boundaryIntoIslandMsg, boundaryOutOfIslandMsg, builtinConstLit, builtin
24
24
  import { splitFiles, collectProgram, collectNpmImports, collectJsonImports, moduleArtifacts, collectGlobals, declSymbolOf, defaultExportSymbolOf, lowerFileInit, lowerDefaultExport, buildMain, appendDynamicImportModules } from "./lower-modules.js";
25
25
  import { registerBuiltinErrorClasses, registerBuiltinEmitterClass, registerBuiltinStreamClasses, builtinErrorInfoOf, builtinEmitterInfoOf, builtinStreamInfoOf, analyzeClassDecoration, classIteratorDrainCall, classIteratorNextCall, classIteratorOf, classIteratorOpenCall, classIteratorRestDrainCall, classMemberNameOf, classValueRef, collectClassShape, exactClassOfReceiver, collectClassShapeInner, ctorAbiEquals, findMethodOn, findStaticOn, findGenericMethodOn, findGenericStaticOn, genericClassInstanceType, isSubclassOf, inHierarchy, overrideBelow, staticShadowBelow, upcastTo, lowerClassMembers, lowerClassCtor, lowerClassExpression, lowerClassExpressionInfo, lowerClassMethodMember, lowerClassValueProperty, lowerStaticMethod, throwingSetterFn, fieldInitStmts, lowerStaticFieldInits, lowerStaticFieldRead, lowerDerivedCtorBody, superCallStmt, lowerSuperMethodCall, superThisRef, lowerSuperAccessorRead, lowerSuperAccessorWrite, inheritsBuiltinErrorCtor, inheritsBuiltinEmitterCtor, errorMessageArg, lowerNew, accessorCall } from "./lower-classes.js";
26
26
  import { mixinCallClassInfoOf, mixinIntersectionInstanceType } from "./lower-mixins.js";
27
- import { bindingNeverReassigned, bodyReadsArguments, isThisParameter, paramShape, paramShapes, checkDefaultParamBodyType, completeArgs, wrappedUndefined, undefinedArgFor, requireExactArityValue, bodyReturnType, declaredReturnType, collectSignature, collectSignatureInner, collectGenericSignature, genericFnOf, lowerGenericCall, lowerGenericFnValue, inferTypeParamBindings, lowerGenericInstance, lowerCall, lowerFfiCall, lowerTimersMemberCall, lowerPromiseMethodCall, lowerFilterNarrowCall, isTopLevelFnSymbol, lowerNestedFunctionDecl, lambdaSignature, lowerLambda, lowerFunction, validateFfiImports } from "./lower-calls.js";
27
+ import { bindingNeverReassigned, bodyReadsArguments, implicitMonoFile, isThisParameter, paramShape, paramShapes, checkDefaultParamBodyType, completeArgs, wrappedUndefined, undefinedArgFor, requireExactArityValue, bodyReturnType, declaredReturnType, collectSignature, collectSignatureInner, collectGenericSignature, genericFnOf, lowerGenericCall, lowerGenericFnValue, inferTypeParamBindings, lowerGenericInstance, lowerCall, lowerFfiCall, lowerTimersMemberCall, lowerPromiseMethodCall, lowerFilterNarrowCall, isTopLevelFnSymbol, lowerNestedFunctionDecl, lambdaSignature, lowerLambda, lowerFunction, validateFfiImports } from "./lower-calls.js";
28
28
  import { lowerArrayMethodCall, lowerBufferStaticCall, lowerBytesMethodCall, lowerBytesNew, lowerMapMethodCall, lowerMapForEachCall, buildMapForEachFn, lowerRecordOvfCaptureHelper, lowerEnvToPairsHelper, lowerSetMethodCall, lowerSetForEachCall, buildSetForEachFn, lowerRegexMethodCall, lowerStringMethodCall } from "./lower-containers.js";
29
29
  import { lowerStreamModuleCall } from "./lower-stream.js";
30
30
  import { lowerEmitOverrideSpec } from "./lower-emitter.js";
@@ -363,7 +363,7 @@ export function neverTaintedJsType(L, node, t) {
363
363
  if (depth === 0)
364
364
  return false;
365
365
  if (x.isUnionType())
366
- return x.getTypes().some((a) => walk(a, depth - 1));
366
+ return ts.constituentTypes(x).some((a) => walk(a, depth - 1));
367
367
  if (L.checker.isArrayType(x) || L.checker.isTupleType(x)) {
368
368
  return L.checker
369
369
  .getTypeArguments(x)
@@ -1985,6 +1985,16 @@ export class Lowerer {
1985
1985
  }
1986
1986
  run() {
1987
1987
  const parts = this.splitFiles();
1988
+ // The coverage remainder deliberately visits every body that reachable
1989
+ // emit skipped. Those files are already phase-managed, so an ordinary
1990
+ // checker miss would stay a one-node IPC query instead of falling back
1991
+ // to the facade's whole-file batch. Coverage has no dead-body boundary
1992
+ // to preserve: prime each complete file now, reusing the answers the
1993
+ // reachable pass already memoized and batching only the cold remainder.
1994
+ if (this.remainder) {
1995
+ for (const fp of parts)
1996
+ this.checker.prefetchSourceFile(fp.sf);
1997
+ }
1988
1998
  this.collectProgram(parts);
1989
1999
  // Decorated classes analyze AFTER the whole collection pass: a
1990
2000
  // decorator's return type may name a subclass declared below the
@@ -2339,6 +2349,23 @@ export class Lowerer {
2339
2349
  * themselves. */
2340
2350
  emitReachable(extraRoots) {
2341
2351
  const parts = this.splitFiles();
2352
+ // Direct lowering callers do not necessarily run program preflight.
2353
+ // Establish the same managed header/top-level batch here before
2354
+ // collection, while the production path simply finds warm memos.
2355
+ this.checker.prefetchSourceFileStructures(parts.map((fp) => fp.sf));
2356
+ // Signature collection may read the initializer type of a default whose
2357
+ // body type still admits undefined (for example `value =
2358
+ // process.env.VALUE`). The expression executes only when reached, but
2359
+ // that type query is mandatory now; batch hot defaults across ordinary
2360
+ // declarations before collectProgram visits their signatures.
2361
+ this.checker.prefetchCollectionTypes(parts.flatMap((fp) => fp.fnDecls
2362
+ .filter((decl) => decl.body !== undefined && decl.typeParameters === undefined)
2363
+ .flatMap((decl) => decl.parameters.flatMap((param) => param.initializer ? [param.initializer] : []))));
2364
+ // JavaScript class shapes are partly declared by constructor-body
2365
+ // assignments. Batch those collection-time queries across declarations
2366
+ // before collectProgram visits them one by one; reached body lowering
2367
+ // will reuse the same answers later.
2368
+ this.prefetchClassCollection(parts.flatMap((fp) => fp.classDecls));
2342
2369
  this.collectProgram(parts);
2343
2370
  // Decorated classes analyze post-collection here too: the %init seeds
2344
2371
  // lower the decoration calls, whose edges (decorator bodies, construct
@@ -2350,6 +2377,14 @@ export class Lowerer {
2350
2377
  // retained-function keys and are deterministic by construction
2351
2378
  // (qualified declaration names).
2352
2379
  const units = new Map();
2380
+ const bodyRoots = (...roots) => roots.filter((root) => root !== undefined && root !== null);
2381
+ const functionRoots = (decl) => bodyRoots(...decl.parameters.map((param) => param.initializer), decl.body);
2382
+ const classCtorRoots = (info) => bodyRoots(...(info.ctor?.parameters ?? []).map((param) => param.initializer), info.ctor?.body, ...info.fieldOrder.map((field) => field.initializer));
2383
+ const classMemberRoots = (info) => [
2384
+ ...classCtorRoots(info),
2385
+ ...[...this.classMethodMembers(info)].flatMap(({ member }) => functionRoots(member)),
2386
+ ...[...(info.staticMethods?.values() ?? [])].flatMap(({ member }) => functionRoots(member)),
2387
+ ];
2353
2388
  let unitOrder = 0;
2354
2389
  for (const fp of parts) {
2355
2390
  for (const decl of fp.fnDecls) {
@@ -2362,8 +2397,13 @@ export class Lowerer {
2362
2397
  if (!declSymbol || this.genericFnsBySymbol.has(declSymbol))
2363
2398
  continue;
2364
2399
  const sig = this.fnSigsBySymbol.get(declSymbol);
2365
- if (sig)
2366
- units.set(sig.name, { order: unitOrder++, lower: () => this.lowerFunction(decl) });
2400
+ if (sig) {
2401
+ units.set(sig.name, {
2402
+ order: unitOrder++,
2403
+ roots: functionRoots(decl),
2404
+ lower: () => this.lowerFunction(decl),
2405
+ });
2406
+ }
2367
2407
  }
2368
2408
  }
2369
2409
  for (const info of this.classes.values()) {
@@ -2378,16 +2418,32 @@ export class Lowerer {
2378
2418
  // A FAMILY has no constructor function and no instance members —
2379
2419
  // only its statics are units.
2380
2420
  if (!info.generic) {
2381
- units.set(`%${cName}.constructor`, { order: unitOrder++, lower: () => this.lowerClassCtor(info) });
2421
+ units.set(`%${cName}.constructor`, {
2422
+ order: unitOrder++,
2423
+ roots: classCtorRoots(info),
2424
+ lower: () => this.lowerClassCtor(info),
2425
+ });
2382
2426
  for (const { mName, member } of this.classMethodMembers(info)) {
2383
- units.set(`%${cName}.${mName}`, { order: unitOrder++, lower: () => this.lowerClassMethodMember(info, member) });
2427
+ units.set(`%${cName}.${mName}`, {
2428
+ order: unitOrder++,
2429
+ roots: functionRoots(member),
2430
+ lower: () => this.lowerClassMethodMember(info, member),
2431
+ });
2384
2432
  }
2385
2433
  for (const prop of info.throwingSetters) {
2386
- units.set(`%${cName}.set:${prop}`, { order: unitOrder++, lower: () => this.throwingSetterFn(info, prop) });
2434
+ units.set(`%${cName}.set:${prop}`, {
2435
+ order: unitOrder++,
2436
+ roots: [],
2437
+ lower: () => this.throwingSetterFn(info, prop),
2438
+ });
2387
2439
  }
2388
2440
  }
2389
- for (const name of info.staticMethods?.keys() ?? []) {
2390
- units.set(`%${cName}.static:${name}`, { order: unitOrder++, lower: () => lowerStaticMethod(this, info, name) });
2441
+ for (const [name, entry] of info.staticMethods ?? []) {
2442
+ units.set(`%${cName}.static:${name}`, {
2443
+ order: unitOrder++,
2444
+ roots: functionRoots(entry.member),
2445
+ lower: () => lowerStaticMethod(this, info, name),
2446
+ });
2391
2447
  }
2392
2448
  }
2393
2449
  // The old emit pass visited each file's functions and then its classes,
@@ -2461,19 +2517,19 @@ export class Lowerer {
2461
2517
  // edge to them can fire (references require the collected class).
2462
2518
  this.onExprClassCollected = (info) => {
2463
2519
  const cName = info.def.name;
2464
- const register = (name, lower) => {
2465
- units.set(name, { order: unitOrder++, lower });
2520
+ const register = (name, roots, lower) => {
2521
+ units.set(name, { order: unitOrder++, roots, lower });
2466
2522
  metadataPriority.set(name, [3, expressionMetadataOrder++]);
2467
2523
  };
2468
- register(`%${cName}.constructor`, () => this.lowerClassCtor(info));
2524
+ register(`%${cName}.constructor`, classCtorRoots(info), () => this.lowerClassCtor(info));
2469
2525
  for (const { mName, member } of this.classMethodMembers(info)) {
2470
- register(`%${cName}.${mName}`, () => this.lowerClassMethodMember(info, member));
2526
+ register(`%${cName}.${mName}`, functionRoots(member), () => this.lowerClassMethodMember(info, member));
2471
2527
  }
2472
- for (const name of info.staticMethods?.keys() ?? []) {
2473
- register(`%${cName}.static:${name}`, () => lowerStaticMethod(this, info, name));
2528
+ for (const [name, entry] of info.staticMethods ?? []) {
2529
+ register(`%${cName}.static:${name}`, functionRoots(entry.member), () => lowerStaticMethod(this, info, name));
2474
2530
  }
2475
2531
  for (const prop of info.throwingSetters) {
2476
- register(`%${cName}.set:${prop}`, () => this.throwingSetterFn(info, prop));
2532
+ register(`%${cName}.set:${prop}`, [], () => this.throwingSetterFn(info, prop));
2477
2533
  }
2478
2534
  };
2479
2535
  // Generic instances queued by the bodies above lower here (an instance
@@ -2488,45 +2544,73 @@ export class Lowerer {
2488
2544
  clsInstLowered < this.genericClassInstances.length ||
2489
2545
  specLowered < this.emitSpecQueue.length) {
2490
2546
  while (clsInstLowered < this.genericClassInstances.length) {
2491
- const info = this.genericClassInstances[clsInstLowered++];
2492
- const owner = demandOwner();
2493
- this.genericClassDemandOwner.set(info, owner);
2494
- const ref = this.genericClassDemandPriority.get(info) ?? { rank: [4, instanceMetadataOrder++] };
2495
- this.genericClassDemandPriority.set(info, ref);
2496
- instanceFunctions.push(...this.withGenericDemandOwner(owner, () => this.shapes.withDeclaredOrderPriority(ref, () => this.lowerClassMembers(info))));
2547
+ const waveEnd = this.genericClassInstances.length;
2548
+ this.checker.prefetchRoots(this.genericClassInstances.slice(clsInstLowered, waveEnd).flatMap(classMemberRoots));
2549
+ while (clsInstLowered < waveEnd) {
2550
+ const info = this.genericClassInstances[clsInstLowered++];
2551
+ const owner = demandOwner();
2552
+ this.genericClassDemandOwner.set(info, owner);
2553
+ const ref = this.genericClassDemandPriority.get(info) ?? { rank: [4, instanceMetadataOrder++] };
2554
+ this.genericClassDemandPriority.set(info, ref);
2555
+ instanceFunctions.push(...this.withGenericDemandOwner(owner, () => this.shapes.withDeclaredOrderPriority(ref, () => this.lowerClassMembers(info))));
2556
+ }
2497
2557
  }
2498
2558
  while (instLowered < this.instantiationQueue.length) {
2499
- const { info, inst } = this.instantiationQueue[instLowered++];
2500
- const owner = demandOwner();
2501
- this.genericFunctionDemandOwner.set(inst, owner);
2502
- const ref = this.genericDemandPriority.get(inst) ?? { rank: [4, instanceMetadataOrder++] };
2503
- this.genericDemandPriority.set(inst, ref);
2504
- // Body-level poisons skip the instance after retaining the
2505
- // diagnostic and every edge fired before poisoning.
2506
- try {
2507
- instanceFunctions.push(this.withGenericDemandOwner(owner, () => this.shapes.withDeclaredOrderPriority(ref, () => this.lowerGenericInstance(info, inst))));
2508
- }
2509
- catch (e) {
2510
- if (!(e instanceof PoisonError))
2511
- throw e;
2559
+ const waveEnd = this.instantiationQueue.length;
2560
+ this.checker.prefetchRoots(this.instantiationQueue
2561
+ .slice(instLowered, waveEnd)
2562
+ .flatMap(({ info }) => functionRoots(info.decl)));
2563
+ while (instLowered < waveEnd) {
2564
+ const { info, inst } = this.instantiationQueue[instLowered++];
2565
+ const owner = demandOwner();
2566
+ this.genericFunctionDemandOwner.set(inst, owner);
2567
+ const ref = this.genericDemandPriority.get(inst) ?? { rank: [4, instanceMetadataOrder++] };
2568
+ this.genericDemandPriority.set(inst, ref);
2569
+ // Body-level poisons skip the instance after retaining the
2570
+ // diagnostic and every edge fired before poisoning.
2571
+ try {
2572
+ instanceFunctions.push(this.withGenericDemandOwner(owner, () => this.shapes.withDeclaredOrderPriority(ref, () => this.lowerGenericInstance(info, inst))));
2573
+ }
2574
+ catch (e) {
2575
+ if (!(e instanceof PoisonError))
2576
+ throw e;
2577
+ }
2512
2578
  }
2513
2579
  }
2514
2580
  // Emit-override specialization bodies fire edges of their own
2515
2581
  // (the super-forward chain, closures, generic calls) — lower them
2516
2582
  // exactly like generic instances.
2517
2583
  while (specLowered < this.emitSpecQueue.length) {
2518
- try {
2519
- const fn = this.shapes.withDeclaredOrderPriority([4, instanceMetadataOrder++], () => lowerEmitOverrideSpec(this, this.emitSpecQueue[specLowered++]));
2520
- if (fn)
2521
- instanceFunctions.push(fn);
2522
- }
2523
- catch (e) {
2524
- if (!(e instanceof PoisonError))
2525
- throw e;
2584
+ const waveEnd = this.emitSpecQueue.length;
2585
+ this.checker.prefetchRoots(this.emitSpecQueue
2586
+ .slice(specLowered, waveEnd)
2587
+ .flatMap(({ info }) => info.emitOverride ? functionRoots(info.emitOverride.decl) : []));
2588
+ while (specLowered < waveEnd) {
2589
+ try {
2590
+ const fn = this.shapes.withDeclaredOrderPriority([4, instanceMetadataOrder++], () => lowerEmitOverrideSpec(this, this.emitSpecQueue[specLowered++]));
2591
+ if (fn)
2592
+ instanceFunctions.push(fn);
2593
+ }
2594
+ catch (e) {
2595
+ if (!(e instanceof PoisonError))
2596
+ throw e;
2597
+ }
2526
2598
  }
2527
2599
  }
2528
2600
  }
2529
2601
  };
2602
+ // Module inits are the unconditional root wave. Structure prefetch
2603
+ // already covered ordinary top-level expressions, but this full-root
2604
+ // pass also picks up nested/lifted function bodies and the class
2605
+ // declaration-time code that splitFiles hoists out of topStmts.
2606
+ this.checker.prefetchRoots([
2607
+ ...parts.flatMap((fp) => fp.topStmts),
2608
+ ...[...this.classes.values()].flatMap((info) => [
2609
+ ...info.staticFields.map((field) => field.initializer),
2610
+ ...(info.staticBlocks ?? []),
2611
+ ...(info.classDecorators?.nodes ?? []),
2612
+ ]),
2613
+ ]);
2530
2614
  parts.forEach((fp, index) => {
2531
2615
  const priority = [2, index];
2532
2616
  const owner = demandOwner(priority);
@@ -2538,25 +2622,31 @@ export class Lowerer {
2538
2622
  // (the export-map resolution reports them as SC4002 later).
2539
2623
  for (const root of extraRoots ?? [])
2540
2624
  this.onEdge?.(root);
2541
- while (queue.length > 0) {
2542
- // A body-level poison outside the per-statement catches (a fenced
2543
- // constructor/method parameter default lowered by declareParams):
2544
- // every edge fired before poisoning remains retained; the diagnostic
2545
- // stays recorded and the member stays omitted.
2546
- try {
2547
- const name = queue.shift();
2548
- const unit = units.get(name);
2549
- const priority = metadataPriority.get(name) ?? [3, expressionMetadataOrder++];
2550
- const owner = demandOwner(priority);
2551
- const fn = this.withGenericDemandOwner(owner, () => this.shapes.withDeclaredOrderPriority(priority, unit.lower));
2552
- if (fn)
2553
- loweredUnits.set(name, fn);
2554
- }
2555
- catch (e) {
2556
- if (!(e instanceof PoisonError))
2557
- throw e;
2625
+ const drainUnits = () => {
2626
+ while (queue.length > 0) {
2627
+ const wave = queue.splice(0);
2628
+ this.checker.prefetchRoots(wave.flatMap((name) => units.get(name).roots));
2629
+ for (const name of wave) {
2630
+ // A body-level poison outside the per-statement catches (a fenced
2631
+ // constructor/method parameter default lowered by declareParams):
2632
+ // every edge fired before poisoning remains retained; the diagnostic
2633
+ // stays recorded and the member stays omitted.
2634
+ try {
2635
+ const unit = units.get(name);
2636
+ const priority = metadataPriority.get(name) ?? [3, expressionMetadataOrder++];
2637
+ const owner = demandOwner(priority);
2638
+ const fn = this.withGenericDemandOwner(owner, () => this.shapes.withDeclaredOrderPriority(priority, unit.lower));
2639
+ if (fn)
2640
+ loweredUnits.set(name, fn);
2641
+ }
2642
+ catch (e) {
2643
+ if (!(e instanceof PoisonError))
2644
+ throw e;
2645
+ }
2646
+ }
2558
2647
  }
2559
- }
2648
+ };
2649
+ drainUnits();
2560
2650
  this.restoreGenericInstanceOrder();
2561
2651
  this.restoreGenericClassInstanceOrder();
2562
2652
  // Generic bodies can reach ordinary declarations, whose bodies can in
@@ -2567,21 +2657,7 @@ export class Lowerer {
2567
2657
  drainInstances();
2568
2658
  if (queue.length === 0)
2569
2659
  break;
2570
- while (queue.length > 0) {
2571
- try {
2572
- const name = queue.shift();
2573
- const unit = units.get(name);
2574
- const priority = metadataPriority.get(name) ?? [3, expressionMetadataOrder++];
2575
- const owner = demandOwner(priority);
2576
- const fn = this.withGenericDemandOwner(owner, () => this.shapes.withDeclaredOrderPriority(priority, unit.lower));
2577
- if (fn)
2578
- loweredUnits.set(name, fn);
2579
- }
2580
- catch (e) {
2581
- if (!(e instanceof PoisonError))
2582
- throw e;
2583
- }
2584
- }
2660
+ drainUnits();
2585
2661
  this.restoreGenericInstanceOrder(instLowered);
2586
2662
  this.restoreGenericClassInstanceOrder(clsInstLowered);
2587
2663
  }
@@ -2781,7 +2857,7 @@ export class Lowerer {
2781
2857
  // story through its callable arm. After the package check: a
2782
2858
  // package-declared generic signature stays the package's story.
2783
2859
  {
2784
- const parts = widened.isUnionType() ? widened.getTypes() : [widened];
2860
+ const parts = widened.isUnionType() ? ts.constituentTypes(widened) : [widened];
2785
2861
  if (parts.some((p) => this.checker.getCallSignatures(p).some((s) => (s.typeParameters?.length ?? 0) > 0))) {
2786
2862
  this.pushDiag(genericSignatureTypeDiag(this.checker.typeToString(type), locOf(node)));
2787
2863
  throw new PoisonError();
@@ -3094,10 +3170,10 @@ export class Lowerer {
3094
3170
  // when one constituent is; a union is array-proven only when EVERY
3095
3171
  // arm is, so an ordinary `any[] | string` never qualifies.
3096
3172
  if ((part.flags & ts.TypeFlags.Intersection) !== 0) {
3097
- return part.getTypes().some(visit);
3173
+ return ts.constituentTypes(part).some(visit);
3098
3174
  }
3099
3175
  if (part.isUnionType())
3100
- return part.getTypes().every(visit);
3176
+ return ts.constituentTypes(part).every(visit);
3101
3177
  return false;
3102
3178
  };
3103
3179
  return visit(t);
@@ -6050,7 +6126,7 @@ export class Lowerer {
6050
6126
  const t = this.typeOf(d.initializer);
6051
6127
  if (!isUnitOnlyTsType(t))
6052
6128
  return null;
6053
- for (const p of t.isUnionType() ? t.getTypes() : [t]) {
6129
+ for (const p of t.isUnionType() ? ts.constituentTypes(t) : [t]) {
6054
6130
  units.add((p.flags & ts.TypeFlags.Null) !== 0 ? "null" : "undefined");
6055
6131
  }
6056
6132
  }
@@ -6414,10 +6490,83 @@ export class Lowerer {
6414
6490
  return lowerGenericInstance(this, info, inst);
6415
6491
  }
6416
6492
  /* ── classes ──────────────────────────────────────────────────────── */
6493
+ /** Checker work class SHAPE collection performs inside otherwise
6494
+ * deferred JavaScript bodies. Constructor assignments declare fields,
6495
+ * so collection asks for each `this.x` symbol and RHS type even when the
6496
+ * constructor is unreachable. Keep that mandatory work batched without
6497
+ * sweeping unrelated dead method bodies. */
6498
+ prefetchClassCollection(decls) {
6499
+ const defaultTypeNodes = [];
6500
+ const typeNodes = [];
6501
+ const symbolRoots = [];
6502
+ for (const decl of decls) {
6503
+ for (const member of decl.members) {
6504
+ if ((ts.isConstructorDeclaration(member) ||
6505
+ ts.isMethodDeclaration(member) ||
6506
+ ts.isGetAccessor(member) ||
6507
+ ts.isSetAccessor(member)) &&
6508
+ (!ts.isMethodDeclaration(member) || member.typeParameters === undefined)) {
6509
+ for (const param of member.parameters) {
6510
+ if (param.initializer)
6511
+ defaultTypeNodes.push(param.initializer);
6512
+ }
6513
+ }
6514
+ }
6515
+ if (!isJsSourceFile(decl.getSourceFile()))
6516
+ continue;
6517
+ for (const member of decl.members) {
6518
+ if (ts.isConstructorDeclaration(member)) {
6519
+ for (const param of member.parameters) {
6520
+ if (param.initializer)
6521
+ typeNodes.push(param.initializer);
6522
+ }
6523
+ for (const stmt of member.body?.statements ?? []) {
6524
+ if (!ts.isExpressionStatement(stmt) || !ts.isBinaryExpression(stmt.expression))
6525
+ continue;
6526
+ if (stmt.expression.operatorToken.kind !== ts.SyntaxKind.EqualsToken)
6527
+ continue;
6528
+ const lhs = stmt.expression.left;
6529
+ if ((ts.isPropertyAccessExpression(lhs) || ts.isElementAccessExpression(lhs)) &&
6530
+ lhs.expression.kind === ts.SyntaxKind.ThisKeyword) {
6531
+ symbolRoots.push(lhs);
6532
+ // Field inference normally uses the symbol's type, but its
6533
+ // panic/undefined fallback asks for the assignment node too.
6534
+ typeNodes.push(lhs, stmt.expression.right);
6535
+ }
6536
+ }
6537
+ continue;
6538
+ }
6539
+ if (ts.isMethodDeclaration(member) ||
6540
+ ts.isGetAccessor(member) ||
6541
+ ts.isSetAccessor(member)) {
6542
+ for (const param of member.parameters) {
6543
+ if (param.initializer)
6544
+ typeNodes.push(param.initializer);
6545
+ }
6546
+ // npm-static implicit-any classification resolves body parameter
6547
+ // references while collecting the method's shape.
6548
+ if (implicitMonoFile(decl.getSourceFile()) && member.body) {
6549
+ symbolRoots.push(member.body);
6550
+ }
6551
+ }
6552
+ }
6553
+ }
6554
+ if (defaultTypeNodes.length > 0) {
6555
+ this.checker.prefetchCollectionTypes(defaultTypeNodes);
6556
+ }
6557
+ if (typeNodes.length > 0 || symbolRoots.length > 0) {
6558
+ this.checker.prefetchClassCollection(typeNodes, symbolRoots);
6559
+ }
6560
+ }
6417
6561
  collectClassShape(decl) {
6418
6562
  return collectClassShape(this, decl);
6419
6563
  }
6420
6564
  collectClassShapeInner(decl, jsNameOverride, inst, mixin) {
6565
+ // Late class expressions and mixin/generic instances do not participate
6566
+ // in emitReachable's initial declaration wave. Prime their mandatory
6567
+ // shape queries at the collection boundary; initial declarations are
6568
+ // already warm and this is memo-free.
6569
+ this.prefetchClassCollection([decl]);
6421
6570
  return collectClassShapeInner(this, decl, jsNameOverride, inst, mixin);
6422
6571
  }
6423
6572
  lowerClassExpressionInfo(expr) {
@@ -7069,7 +7218,7 @@ export class Lowerer {
7069
7218
  }
7070
7219
  if (d && ts.isVariableDeclaration(d) && d.initializer === undefined) {
7071
7220
  const t = this.checker.getTypeOfSymbol(symbol);
7072
- const parts = t.isUnionType() ? t.getTypes() : [t];
7221
+ const parts = t.isUnionType() ? ts.constituentTypes(t) : [t];
7073
7222
  if (parts.some((p) => this.checker.getCallSignatures(p).some((s) => (s.typeParameters?.length ?? 0) > 0))) {
7074
7223
  this.unsupported("SC1030", node, `the generic-signature binding '${name}' (its type keeps type parameters and the declaration has no initializer — no function body exists to monomorphize, so nothing can pin a concrete signature)`);
7075
7224
  }