@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.
- package/dist/backend/cc-cache.test.js +969 -7
- package/dist/backend/cc-cache.test.js.map +1 -1
- package/dist/backend/cc.d.ts +90 -18
- package/dist/backend/cc.js +953 -276
- package/dist/backend/cc.js.map +1 -1
- package/dist/backend/llvm/split.d.ts +43 -0
- package/dist/backend/llvm/split.js +227 -0
- package/dist/backend/llvm/split.js.map +1 -0
- package/dist/backend/llvm/split.test.d.ts +1 -0
- package/dist/backend/llvm/split.test.js +102 -0
- package/dist/backend/llvm/split.test.js.map +1 -0
- package/dist/backend/object-localize.test.js +20 -0
- package/dist/backend/object-localize.test.js.map +1 -1
- package/dist/executable/early-cache.d.ts +86 -0
- package/dist/executable/early-cache.js +460 -0
- package/dist/executable/early-cache.js.map +1 -0
- package/dist/executable/early-cache.test.d.ts +1 -0
- package/dist/executable/early-cache.test.js +300 -0
- package/dist/executable/early-cache.test.js.map +1 -0
- package/dist/ffi/profile.d.ts +7 -2
- package/dist/ffi/profile.js +1 -0
- package/dist/ffi/profile.js.map +1 -1
- package/dist/frontend/lowering/lower-builtins.js +2 -2
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.js +14 -4
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.js +18 -23
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.js +22 -10
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-island.js +3 -3
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-mixins.js +1 -1
- package/dist/frontend/lowering/lower-mixins.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.js +1 -1
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +6 -0
- package/dist/frontend/lowering/lowerer.js +230 -81
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/surfaces.js +1 -1
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/program.js +42 -13
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/ts7/checker.d.ts +40 -2
- package/dist/frontend/ts7/checker.js +194 -32
- package/dist/frontend/ts7/checker.js.map +1 -1
- package/dist/frontend/types.js +20 -42
- package/dist/frontend/types.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +219 -101
- package/dist/index.js.map +1 -1
- package/dist/ir/nodes.d.ts +6 -0
- package/dist/ir/nodes.js +28 -0
- package/dist/ir/nodes.js.map +1 -1
- package/dist/ir/validate.js +7 -1
- package/dist/ir/validate.js.map +1 -1
- package/dist/library/early-cache.js +4 -23
- package/dist/library/early-cache.js.map +1 -1
- package/dist/library/implementation-identity.d.ts +23 -0
- package/dist/library/implementation-identity.js +84 -0
- package/dist/library/implementation-identity.js.map +1 -0
- package/dist/startup-cache.d.ts +6 -0
- package/dist/startup-cache.js +6 -0
- package/dist/startup-cache.js.map +1 -0
- package/package.json +3 -2
- 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
|
|
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, {
|
|
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`, {
|
|
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}`, {
|
|
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}`, {
|
|
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
|
|
2390
|
-
units.set(`%${cName}.static:${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
|
|
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
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
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
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
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
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
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
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
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
|
-
|
|
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() ?
|
|
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
|
|
3173
|
+
return ts.constituentTypes(part).some(visit);
|
|
3098
3174
|
}
|
|
3099
3175
|
if (part.isUnionType())
|
|
3100
|
-
return
|
|
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() ?
|
|
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() ?
|
|
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
|
}
|