@scriptc/compiler 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ambient/scriptc-node-fallback.d.ts +59 -4
- package/dist/backend/llvm/dyn.d.ts +3 -0
- package/dist/backend/llvm/dyn.js +84 -12
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.d.ts +4 -1
- package/dist/backend/llvm/emitter.js +20 -5
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/emitter.test.js +9 -1
- package/dist/backend/llvm/emitter.test.js.map +1 -1
- package/dist/backend/llvm/expr-containers.js +5 -0
- package/dist/backend/llvm/expr-containers.js.map +1 -1
- package/dist/backend/llvm/expr-dynamic.js +30 -5
- package/dist/backend/llvm/expr-dynamic.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.js +70 -9
- package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
- package/dist/backend/llvm/expr-stream-callbacks.d.ts +2 -2
- package/dist/backend/llvm/expr-stream-callbacks.js +7 -57
- package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
- package/dist/backend/llvm/lib-dispatch.js +41 -3
- package/dist/backend/llvm/lib-dispatch.js.map +1 -1
- package/dist/backend/llvm/lib-filesystem.js +12 -9
- package/dist/backend/llvm/lib-filesystem.js.map +1 -1
- package/dist/backend/llvm/lib-shared.js +35 -1
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/may-throw.js +4 -0
- package/dist/backend/may-throw.js.map +1 -1
- package/dist/backend/native-codegen.d.ts +1 -1
- package/dist/backend/native-codegen.js +4 -3
- package/dist/backend/native-codegen.js.map +1 -1
- package/dist/backend/native-codegen.test.js +11 -0
- package/dist/backend/native-codegen.test.js.map +1 -1
- package/dist/backend/target-diagnostics.d.ts +5 -0
- package/dist/backend/target-diagnostics.js +72 -1
- package/dist/backend/target-diagnostics.js.map +1 -1
- package/dist/backend/target-diagnostics.test.d.ts +1 -0
- package/dist/backend/target-diagnostics.test.js +68 -0
- package/dist/backend/target-diagnostics.test.js.map +1 -0
- package/dist/coverage/surface-manifest.js +5 -3
- package/dist/coverage/surface-manifest.js.map +1 -1
- package/dist/executable/executable-cache.d.ts +7 -3
- package/dist/executable/executable-cache.js +47 -11
- package/dist/executable/executable-cache.js.map +1 -1
- package/dist/executable/executable-cache.test.js +109 -2
- package/dist/executable/executable-cache.test.js.map +1 -1
- package/dist/executable/prepare.js +2 -1
- package/dist/executable/prepare.js.map +1 -1
- package/dist/frontend/builtin-modules.d.ts +1 -1
- package/dist/frontend/builtin-modules.js +1 -1
- package/dist/frontend/builtin-modules.js.map +1 -1
- package/dist/frontend/function-completion.d.ts +6 -0
- package/dist/frontend/function-completion.js +50 -0
- package/dist/frontend/function-completion.js.map +1 -0
- package/dist/frontend/lowering/abstract-equality.js +5 -1
- package/dist/frontend/lowering/abstract-equality.js.map +1 -1
- package/dist/frontend/lowering/checked-iterable-spread.d.ts +4 -0
- package/dist/frontend/lowering/checked-iterable-spread.js +30 -0
- package/dist/frontend/lowering/checked-iterable-spread.js.map +1 -0
- package/dist/frontend/lowering/checked-promise-all.d.ts +5 -0
- package/dist/frontend/lowering/checked-promise-all.js +31 -0
- package/dist/frontend/lowering/checked-promise-all.js.map +1 -0
- package/dist/frontend/lowering/class-callbacks.d.ts +1 -1
- package/dist/frontend/lowering/class-callbacks.js +7 -6
- package/dist/frontend/lowering/class-callbacks.js.map +1 -1
- package/dist/frontend/lowering/class-construction.d.ts +2 -0
- package/dist/frontend/lowering/class-construction.js +34 -5
- package/dist/frontend/lowering/class-construction.js.map +1 -1
- package/dist/frontend/lowering/class-descriptors.d.ts +1 -1
- package/dist/frontend/lowering/class-descriptors.js +12 -5
- package/dist/frontend/lowering/class-descriptors.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +25 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.js +597 -78
- package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js +64 -2
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js.map +1 -1
- package/dist/frontend/lowering/class-instance-constructor.d.ts +1 -1
- package/dist/frontend/lowering/class-instance-constructor.js +11 -41
- package/dist/frontend/lowering/class-instance-constructor.js.map +1 -1
- package/dist/frontend/lowering/class-method-values.d.ts +16 -0
- package/dist/frontend/lowering/class-method-values.js +60 -29
- package/dist/frontend/lowering/class-method-values.js.map +1 -1
- package/dist/frontend/lowering/class-prototypes.d.ts +5 -1
- package/dist/frontend/lowering/class-prototypes.js +69 -10
- package/dist/frontend/lowering/class-prototypes.js.map +1 -1
- package/dist/frontend/lowering/class-runtime-statics.d.ts +4 -4
- package/dist/frontend/lowering/class-runtime-statics.js +26 -8
- package/dist/frontend/lowering/class-runtime-statics.js.map +1 -1
- package/dist/frontend/lowering/class-static-data.d.ts +1 -0
- package/dist/frontend/lowering/class-static-data.js +4 -2
- package/dist/frontend/lowering/class-static-data.js.map +1 -1
- package/dist/frontend/lowering/containers/bytes.js +17 -4
- package/dist/frontend/lowering/containers/bytes.js.map +1 -1
- package/dist/frontend/lowering/containers/string-and-regexp.js +6 -1
- package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
- package/dist/frontend/lowering/deferred-module-initializers.d.ts +13 -0
- package/dist/frontend/lowering/deferred-module-initializers.js +410 -0
- package/dist/frontend/lowering/deferred-module-initializers.js.map +1 -0
- package/dist/frontend/lowering/deferred-module-initializers.test.d.ts +1 -0
- package/dist/frontend/lowering/deferred-module-initializers.test.js +92 -0
- package/dist/frontend/lowering/deferred-module-initializers.test.js.map +1 -0
- package/dist/frontend/lowering/expressions/object-literals.js +31 -1
- package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
- package/dist/frontend/lowering/expressions/optional-chains.js +3 -3
- package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
- package/dist/frontend/lowering/lower-builtins.d.ts +4 -9
- package/dist/frontend/lowering/lower-builtins.js +291 -51
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.js +283 -73
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +5 -0
- package/dist/frontend/lowering/lower-classes.js +439 -25
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.d.ts +1 -1
- package/dist/frontend/lowering/lower-containers.js +39 -17
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +10 -6
- package/dist/frontend/lowering/lower-exprs.js +294 -129
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-generators.js +5 -1
- package/dist/frontend/lowering/lower-generators.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.js +15 -1
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-island.js +4 -0
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-island.test.d.ts +1 -0
- package/dist/frontend/lowering/lower-island.test.js +51 -0
- package/dist/frontend/lowering/lower-island.test.js.map +1 -0
- package/dist/frontend/lowering/lower-modules.d.ts +1 -3
- package/dist/frontend/lowering/lower-modules.js +186 -82
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.test.js +69 -1
- package/dist/frontend/lowering/lower-modules.test.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.js +100 -35
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.test.d.ts +1 -0
- package/dist/frontend/lowering/lower-stmts.test.js +77 -0
- package/dist/frontend/lowering/lower-stmts.test.js.map +1 -0
- package/dist/frontend/lowering/lower-stream.js +2 -0
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lower-url.d.ts +2 -1
- package/dist/frontend/lowering/lower-url.js +32 -9
- package/dist/frontend/lowering/lower-url.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +26 -9
- package/dist/frontend/lowering/lowerer.js +218 -27
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/lowerer.test.js +38 -0
- package/dist/frontend/lowering/lowerer.test.js.map +1 -1
- package/dist/frontend/lowering/module-namespace-elements.d.ts +7 -0
- package/dist/frontend/lowering/module-namespace-elements.js +54 -0
- package/dist/frontend/lowering/module-namespace-elements.js.map +1 -0
- package/dist/frontend/lowering/object-factory-new.d.ts +4 -3
- package/dist/frontend/lowering/object-factory-new.js +27 -14
- package/dist/frontend/lowering/object-factory-new.js.map +1 -1
- package/dist/frontend/lowering/surfaces.d.ts +1 -0
- package/dist/frontend/lowering/surfaces.js +24 -12
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/lowering/text-decoder-encoding.js +3 -0
- package/dist/frontend/lowering/text-decoder-encoding.js.map +1 -1
- package/dist/frontend/lowering/text-decoder-encoding.test.js +2 -1
- package/dist/frontend/lowering/text-decoder-encoding.test.js.map +1 -1
- package/dist/frontend/program.js +4 -2
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/type-mapper.js +83 -14
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/frontend/union-discriminants.js +22 -7
- package/dist/frontend/union-discriminants.js.map +1 -1
- package/dist/index.js +16 -10
- package/dist/index.js.map +1 -1
- package/dist/ir/ir.d.ts +27 -13
- package/dist/ir/ir.js +26 -2
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/serialize.js +21 -1
- package/dist/ir/serialize.js.map +1 -1
- package/dist/ir/serialize.test.js +21 -0
- package/dist/ir/serialize.test.js.map +1 -1
- package/dist/ir/traverse.d.ts +0 -3
- package/dist/ir/traverse.js +33 -20
- package/dist/ir/traverse.js.map +1 -1
- package/dist/ir/validate.js +56 -5
- package/dist/ir/validate.js.map +1 -1
- package/dist/ir/validate.test.js +17 -1
- package/dist/ir/validate.test.js.map +1 -1
- package/dist/library/compiler-self-identity.js +1 -1
- package/dist/library/compiler-self-identity.test.js +2 -2
- package/dist/library/compiler-self-identity.test.js.map +1 -1
- package/dist/library/int-infer.d.ts +2 -2
- package/dist/library/int-infer.js +10 -7
- package/dist/library/int-infer.js.map +1 -1
- package/dist/library/int-infer.test.js +44 -0
- package/dist/library/int-infer.test.js.map +1 -1
- package/dist/library/prepare.js +2 -1
- package/dist/library/prepare.js.map +1 -1
- package/package.json +20 -20
- package/surface-manifest.json +115 -13
|
@@ -4,6 +4,7 @@ export type { WidthLift } from "./width-lift.js";
|
|
|
4
4
|
import { type FnCtx } from "./function-context.js";
|
|
5
5
|
export { newFnCtx, type FnCtx } from "./function-context.js";
|
|
6
6
|
import type { FrontendServices } from "../services.js";
|
|
7
|
+
import { DeferredModuleInitializers } from "./deferred-module-initializers.js";
|
|
7
8
|
import type { ClassSymbolKey } from "./symbol-fields.js";
|
|
8
9
|
import type { HttpClientFnBinding } from "./lower-server.js";
|
|
9
10
|
import * as ts from "../ts7/adapter.js";
|
|
@@ -324,15 +325,13 @@ export declare function ladderFenceExpr(lowerer: Lowerer, surface: string, node:
|
|
|
324
325
|
*
|
|
325
326
|
* Null for void (no value exists to represent). */
|
|
326
327
|
export declare function dynFallbackType(lowerer: Lowerer, node: ts.Node, t: ts.Type): IrType | null;
|
|
327
|
-
/** The
|
|
328
|
-
*
|
|
329
|
-
*
|
|
330
|
-
* REFERENCE-SITE approximation of JS's creation-site naming — an aliased
|
|
331
|
-
* binding reports the alias; SEMANTICS.md), named function expressions
|
|
328
|
+
/** The JS `Function.prototype.name` of an expression flowing into a dyn
|
|
329
|
+
* slot. Immutable identifier aliases retain their creation-site name; property
|
|
330
|
+
* reads answer the referenced name. Named function expressions
|
|
332
331
|
* their own name, anonymous function/arrow expressions their
|
|
333
332
|
* NamedEvaluation home (a variable initializer or property assignment).
|
|
334
333
|
* Null when nothing names the value (the box stays anonymous). */
|
|
335
|
-
export declare function jsFuncNameOf(node: ts.Node): string | null;
|
|
334
|
+
export declare function jsFuncNameOf(node: ts.Node, lowerer?: Lowerer): string | null;
|
|
336
335
|
export declare class Lowerer {
|
|
337
336
|
readonly program: ts.Program;
|
|
338
337
|
readonly entry: ts.SourceFile;
|
|
@@ -361,6 +360,9 @@ export declare class Lowerer {
|
|
|
361
360
|
/** Per-symbol result of the never-reassigned file scan
|
|
362
361
|
* (bindingNeverReassigned — object-literal generic-method receivers). */
|
|
363
362
|
readonly neverReassignedCache: Map<ts.Symbol, boolean>;
|
|
363
|
+
/** Syntactic writes indexed once per JS scope. Symbol and RHS type
|
|
364
|
+
* checks remain contextual to each binding probe. */
|
|
365
|
+
readonly jsBindingWritesByOwner: Map<import("../ts7/ast-node.js").AstNode, Map<string, ts.BinaryExpression[]>>;
|
|
364
366
|
/** TRAP bindings: declarations whose initializer provably throws before
|
|
365
367
|
* producing a value (its chain roots at an ambient-undefined name —
|
|
366
368
|
* ambientUndefVarRootOf). Module init unwinds at the declaration, so no
|
|
@@ -508,8 +510,8 @@ export declare class Lowerer {
|
|
|
508
510
|
} | null;
|
|
509
511
|
/** Recover the original optional union when a checked single-arm helper
|
|
510
512
|
* was installed before a strict property consumer could name its member.
|
|
511
|
-
* Recovery
|
|
512
|
-
*
|
|
513
|
+
* Recovery covers member reads and storage roots marked by the
|
|
514
|
+
* optional-read analysis, so ordinary assertions keep their generic
|
|
513
515
|
* checked-narrow behavior. */
|
|
514
516
|
runtimeOptionalSourceValue(node: ts.Expression, value: IrExpr): IrExpr | null;
|
|
515
517
|
/** A strict property or method receiver over an array-derived optional
|
|
@@ -594,10 +596,12 @@ export declare class Lowerer {
|
|
|
594
596
|
private readonly copyRetagHelpers;
|
|
595
597
|
private readonly unionLiteralOwners;
|
|
596
598
|
private readonly strippedUndefinedArms;
|
|
599
|
+
private readonly addedUndefinedArms;
|
|
597
600
|
private readonly stdlibSymbols;
|
|
598
601
|
/** Method adapter names are owned by class-method-values. Looking them
|
|
599
602
|
* up must not scan and retain every unrelated lifted function. */
|
|
600
603
|
readonly classMethodValueHelpers: Set<string>;
|
|
604
|
+
readonly classMethodValueSelections: Map<string, import("./class-method-values.js").ClassMethodValueSelection>;
|
|
601
605
|
/** Callee names of every interned coercion helper whose CALL mints a
|
|
602
606
|
* FRESH closure per evaluation (%fn.width.*, %fn.adapt.*,
|
|
603
607
|
* %fnval.spawnres.*). Registered at the mint site — NOT recovered by
|
|
@@ -705,9 +709,15 @@ export declare class Lowerer {
|
|
|
705
709
|
/** Inferred JS methods participating in an override chain keep a vtable
|
|
706
710
|
* ABI instead of call-site specialization. Filled before class collection. */
|
|
707
711
|
readonly virtualJsMethods: Set<ts.MethodDeclaration>;
|
|
712
|
+
/** Descendant writes must widen the original JS field before collecting
|
|
713
|
+
* any class layout; base and derived instances share its storage ABI. */
|
|
714
|
+
readonly inheritedJsFieldWrites: Map<ts.ClassDeclaration | ts.ClassExpression, Map<string, ts.ExpressionBase[]>>;
|
|
708
715
|
/** Largest fixed argument list below a JS method, discovered before any
|
|
709
716
|
* base vtable signature is collected. Unused checked slots carry undefined. */
|
|
710
717
|
readonly virtualJsMethodArity: Map<ts.MethodDeclaration, number>;
|
|
718
|
+
readonly checkedVirtualJsMethods: Set<ts.MethodDeclaration>;
|
|
719
|
+
readonly checkedVirtualJsAccessors: Set<ts.GetAccessorDeclaration | ts.SetAccessorDeclaration>;
|
|
720
|
+
readonly checkedVirtualJsValueReturns: Set<ts.MethodDeclaration>;
|
|
711
721
|
/** The class whose members are lowering — `super` binds lexically to it
|
|
712
722
|
* (arrows inside methods lower within this window, so they see it too). */
|
|
713
723
|
currentClass: ClassInfo | null;
|
|
@@ -849,6 +859,7 @@ export declare class Lowerer {
|
|
|
849
859
|
* a reference to a lowerable body reports its name here — recorded even
|
|
850
860
|
* when the enclosing statement later poisons. */
|
|
851
861
|
onEdge: ((name: string) => void) | null;
|
|
862
|
+
deferredModuleInitializers: DeferredModuleInitializers | null;
|
|
852
863
|
fnStack: FnCtx[];
|
|
853
864
|
readonly liftedFns: IrFunction[];
|
|
854
865
|
/** One Error-method helper belongs to this lowering session. Its cached
|
|
@@ -884,6 +895,12 @@ export declare class Lowerer {
|
|
|
884
895
|
* is assembled directly. The configured reachable set remains null so
|
|
885
896
|
* demand-driven instance lowering keeps its existing gates. */
|
|
886
897
|
reachableForArtifacts: ReadonlySet<string> | null;
|
|
898
|
+
/** Constructors retained by the active worklist. A boxed base receiver
|
|
899
|
+
* can contain any retained descendant, but importing its declaration
|
|
900
|
+
* alone does not make every descendant constructible. */
|
|
901
|
+
private constructedClasses;
|
|
902
|
+
private readonly virtualEdges;
|
|
903
|
+
classCanBeConstructed(info: ClassInfo): boolean;
|
|
887
904
|
/** Coverage remainder mode: the reachability gate inverts (see wantBody)
|
|
888
905
|
* and no module is built. */
|
|
889
906
|
readonly remainder: boolean;
|
|
@@ -2245,7 +2262,7 @@ export declare class Lowerer {
|
|
|
2245
2262
|
lowerDcChannelProperty(access: ts.PropertyAccessExpression): IrExpr | null;
|
|
2246
2263
|
lowerDcTracingChannelMethodCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
|
|
2247
2264
|
lowerDcTracingChannelProperty(access: ts.PropertyAccessExpression): IrExpr | null;
|
|
2248
|
-
strdecHelper(op: "write" | "end", shapeId: string, loc: SrcLoc): string;
|
|
2265
|
+
strdecHelper(op: "write" | "end" | "endChunk" | "endString" | "writeString", shapeId: string, loc: SrcLoc): string;
|
|
2249
2266
|
lowerProcessProperty(expr: ts.PropertyAccessExpression): IrExpr | null;
|
|
2250
2267
|
lowerFsConstantsProperty(expr: ts.PropertyAccessExpression): IrExpr | null;
|
|
2251
2268
|
lowerBuiltinConstantsProperty(expr: ts.PropertyAccessExpression): IrExpr | null;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { pathModuleValue } from "./lower-builtin-values.js";
|
|
2
|
-
import { everyExprChild, everyStmtChild } from "../../ir/traverse.js";
|
|
2
|
+
import { everyExprChild, everyStmtChild, transformStmtList } from "../../ir/traverse.js";
|
|
3
3
|
import { RuntimeOptionalLocals } from "./runtime-optional-locals.js";
|
|
4
4
|
import { sanitizeUnregisteredClassTypes } from "./sanitize-class-types.js";
|
|
5
5
|
import { UnregisteredClassTypes } from "./unregistered-class-types.js";
|
|
@@ -9,7 +9,8 @@ import { bindingInContext, captureContextBinding, declareContextLocal, declareCo
|
|
|
9
9
|
export { newFnCtx } from "./function-context.js";
|
|
10
10
|
import { InternalCompilerError } from "../../errors.js";
|
|
11
11
|
import { defaultAfterUndefined, lowerStaticallyUndefinedArgument } from "./optional-arguments.js";
|
|
12
|
-
import { ClassDynamicDispatch } from "./class-dynamic-dispatch.js";
|
|
12
|
+
import { ClassDynamicDispatch, trackClassFieldCreation } from "./class-dynamic-dispatch.js";
|
|
13
|
+
import { DeferredModuleInitializers } from "./deferred-module-initializers.js";
|
|
13
14
|
import { finalizeClassMethodValues } from "./class-method-values.js";
|
|
14
15
|
/* AST + checker → IR.
|
|
15
16
|
*
|
|
@@ -37,7 +38,7 @@ import {} from "../npm.js";
|
|
|
37
38
|
import { provenanceActive } from "../provenance-registry.js";
|
|
38
39
|
import { ambientDtsPath, canonicalBuiltinModule, cjsExportAssignmentOf, cjsExportDiscardReason, fallbackDtsPath, isCjsExportTableLiteral, isCjsJsFile, isJsSourceFile, isNodeEsmFile, isNodeTypesPath, locOf, orderedImportsOf, overridesDtsPath, npmStaticDepSf7, requireSpecOf, resolveImport, workspacePackageOfPath, } from "../program.js";
|
|
39
40
|
import { containsRecord, containsUnion, describeComponentBlocker, describeRecordMemberBlocker, formatIrType, ISLAND_AMBIENT_TYPES, isUnitOnlyTsType, jsOpenObjectType, mapType, ShapeRegistry, typeKey, UnionRegistry, withUndefinedArm as withUndefinedArmCanonical, } from "../type-mapper.js";
|
|
40
|
-
import { boundaryIntoIslandMsg, boundaryOutOfIslandMsg, builtinConstLit, builtinModuleConstOf, builtinModulesArrayLit, builtinFenceHintOf, builtinModuleFnOf, stdlibMemberFence, isStdlibMember, isStdlibSymbol, isStdlibGlobal, stdlibGlobalMember, nodeTypesOnlySymbol } from "./surfaces.js";
|
|
41
|
+
import { boundaryIntoIslandMsg, boundaryOutOfIslandMsg, builtinConstLit, builtinModuleConstOf, builtinModulesArrayLit, builtinFenceHintOf, builtinModuleFnOf, stdlibMemberFence, isStdlibMember, isStdlibSymbol, isStdlibGlobal, stdlibGlobalNameOf, stdlibGlobalMember, nodeTypesOnlySymbol } from "./surfaces.js";
|
|
41
42
|
import { splitFiles, collectProgram, collectNpmImports, collectJsonImports, moduleArtifacts, collectGlobals, declSymbolOf, defaultExportSymbolOf, lowerFileInit, lowerDefaultExport, buildMain, appendDynamicImportModules, appendForkModules } from "./lower-modules.js";
|
|
42
43
|
import { prepareCjsModuleGraph } from "./lower-node-module.js";
|
|
43
44
|
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, errorConstructorArgs, lowerNew, accessorCall } from "./lower-classes.js";
|
|
@@ -58,7 +59,7 @@ import { lowerNodeTestModuleCall, lowerTestDirectCall, lowerTestMethodCall, lowe
|
|
|
58
59
|
import { lowerAssertModuleCall, lowerAssertDirectCall } from "./lower-assert.js";
|
|
59
60
|
import { lowerUtilModuleCall } from "./lower-inspect.js";
|
|
60
61
|
import { lowerComptime, comptimeBakeable, rejectComptimeCaptures, comptimeValueToIr } from "./lower-comptime.js";
|
|
61
|
-
import { lowerStmts, noteBlockedBindings, isBlockedBinding, lowerScopedBlock, predeclareForwardCapture, predeclareForwardFnDecl, predeclareForwardVar, lowerStmt, lowerVarStatement, lowerDestructuringDecl, lowerDestructuringAssignParts, lowerBindingPattern, lowerJsvalBindingPattern, checkBindingElement, bindPatternTarget, isParseArgsDynCheckerType, lowerVarDeclList, lowerVarDecl, lowerSwitch, lowerTry, lowerExprStatement, lowerForOf, lowerForStatement } from "./lower-stmts.js";
|
|
62
|
+
import { lowerStmts, hasJsTypeAnnotation, noteBlockedBindings, isBlockedBinding, lowerScopedBlock, predeclareForwardCapture, predeclareForwardFnDecl, predeclareForwardVar, lowerStmt, lowerVarStatement, lowerDestructuringDecl, lowerDestructuringAssignParts, lowerBindingPattern, lowerJsvalBindingPattern, checkBindingElement, bindPatternTarget, isParseArgsDynCheckerType, lowerVarDeclList, lowerVarDecl, lowerSwitch, lowerTry, lowerExprStatement, lowerForOf, lowerForStatement } from "./lower-stmts.js";
|
|
62
63
|
import { lowerExpr, maybeNarrow, lowerUnitComparison, lowerNullishCoalesce, lowerCondition, ensureBool, requireTruthyUnion, eqComparableUnion, lowerIntrinsicProperty, lowerArrayLiteral, lowerElementAccess, lowerElementWrite, lowerRecordKeyRead, ensureString, lowerTemplate, lowerAsExpression, lowerPrefixUnary, lowerBinary, lowerCaughtTypeofTest, caughtRead, caughtLocalOf, caughtToString, lowerInstanceOf, lowerRegexLiteral, lowerFieldRead, lowerUnionProperty, fieldTarget, fieldGetExpr, fieldSetStmt, lowerFieldCompound, uniqueSymbolKeyOf } from "./lower-exprs.js";
|
|
63
64
|
import { finishOptionalChain, isOptionalChainTail, lowerOptionalChain } from "./expressions/optional-chains.js";
|
|
64
65
|
import { foldedStringKeyOf, lowerDynObjectLiteral, lowerObjectLiteral, lowerShorthandValue, rejectThisInObjectMethod } from "./expressions/object-literals.js";
|
|
@@ -751,18 +752,34 @@ function anyPiecedFuncType(lowerer, node, t) {
|
|
|
751
752
|
return null;
|
|
752
753
|
return { kind: "func", params, ret };
|
|
753
754
|
}
|
|
754
|
-
/** The
|
|
755
|
-
*
|
|
756
|
-
*
|
|
757
|
-
* REFERENCE-SITE approximation of JS's creation-site naming — an aliased
|
|
758
|
-
* binding reports the alias; SEMANTICS.md), named function expressions
|
|
755
|
+
/** The JS `Function.prototype.name` of an expression flowing into a dyn
|
|
756
|
+
* slot. Immutable identifier aliases retain their creation-site name; property
|
|
757
|
+
* reads answer the referenced name. Named function expressions
|
|
759
758
|
* their own name, anonymous function/arrow expressions their
|
|
760
759
|
* NamedEvaluation home (a variable initializer or property assignment).
|
|
761
760
|
* Null when nothing names the value (the box stays anonymous). */
|
|
762
|
-
export function jsFuncNameOf(node) {
|
|
761
|
+
export function jsFuncNameOf(node, lowerer) {
|
|
763
762
|
let n = node;
|
|
764
763
|
while (ts.isParenthesizedExpression(n))
|
|
765
764
|
n = n.expression;
|
|
765
|
+
const seen = new Set();
|
|
766
|
+
while (lowerer && ts.isIdentifier(n)) {
|
|
767
|
+
const symbol = lowerer.resolveValueSymbol(n);
|
|
768
|
+
if (!symbol || seen.has(symbol))
|
|
769
|
+
break;
|
|
770
|
+
seen.add(symbol);
|
|
771
|
+
const declaration = lowerer.checker.valueDeclarationOf(symbol);
|
|
772
|
+
if (declaration && ts.isFunctionDeclaration(declaration)) {
|
|
773
|
+
n = declaration;
|
|
774
|
+
break;
|
|
775
|
+
}
|
|
776
|
+
if (!declaration || !ts.isVariableDeclaration(declaration) || !declaration.initializer ||
|
|
777
|
+
(ts.getCombinedNodeFlags(declaration) & ts.NodeFlags.Const) === 0)
|
|
778
|
+
break;
|
|
779
|
+
n = declaration.initializer;
|
|
780
|
+
while (ts.isParenthesizedExpression(n))
|
|
781
|
+
n = n.expression;
|
|
782
|
+
}
|
|
766
783
|
if (ts.isIdentifier(n))
|
|
767
784
|
return n.text;
|
|
768
785
|
if (ts.isPropertyAccessExpression(n))
|
|
@@ -811,6 +828,9 @@ export class Lowerer {
|
|
|
811
828
|
/** Per-symbol result of the never-reassigned file scan
|
|
812
829
|
* (bindingNeverReassigned — object-literal generic-method receivers). */
|
|
813
830
|
neverReassignedCache = new Map();
|
|
831
|
+
/** Syntactic writes indexed once per JS scope. Symbol and RHS type
|
|
832
|
+
* checks remain contextual to each binding probe. */
|
|
833
|
+
jsBindingWritesByOwner = new Map();
|
|
814
834
|
/** TRAP bindings: declarations whose initializer provably throws before
|
|
815
835
|
* producing a value (its chain roots at an ambient-undefined name —
|
|
816
836
|
* ambientUndefVarRootOf). Module init unwinds at the declaration, so no
|
|
@@ -1090,7 +1110,7 @@ export class Lowerer {
|
|
|
1090
1110
|
// the initializer cannot fall back to a narrowing adapter.
|
|
1091
1111
|
if (ts.isIdentifier(node) && fallback?.kind === "func") {
|
|
1092
1112
|
const decl = this.checker.valueDeclarationOf(symbol);
|
|
1093
|
-
if (decl && ts.isVariableDeclaration(decl) && decl.initializer) {
|
|
1113
|
+
if (decl && ts.isVariableDeclaration(decl) && !decl.type && !hasJsTypeAnnotation(decl) && decl.initializer) {
|
|
1094
1114
|
let init = decl.initializer;
|
|
1095
1115
|
while (ts.isParenthesizedExpression(init))
|
|
1096
1116
|
init = init.expression;
|
|
@@ -1124,14 +1144,14 @@ export class Lowerer {
|
|
|
1124
1144
|
}
|
|
1125
1145
|
/** Recover the original optional union when a checked single-arm helper
|
|
1126
1146
|
* was installed before a strict property consumer could name its member.
|
|
1127
|
-
* Recovery
|
|
1128
|
-
*
|
|
1147
|
+
* Recovery covers member reads and storage roots marked by the
|
|
1148
|
+
* optional-read analysis, so ordinary assertions keep their generic
|
|
1129
1149
|
* checked-narrow behavior. */
|
|
1130
1150
|
runtimeOptionalSourceValue(node, value) {
|
|
1131
1151
|
let origin = node;
|
|
1132
1152
|
while (ts.isParenthesizedExpression(origin))
|
|
1133
1153
|
origin = origin.expression;
|
|
1134
|
-
let optionalOrigin = ts.isElementAccessExpression(origin);
|
|
1154
|
+
let optionalOrigin = ts.isElementAccessExpression(origin) || ts.isPropertyAccessExpression(origin);
|
|
1135
1155
|
if (ts.isIdentifier(origin)) {
|
|
1136
1156
|
const local = this.resolveLocal(origin);
|
|
1137
1157
|
const root = local ? this.runtimeOptionalRootOf(local) : null;
|
|
@@ -1143,6 +1163,10 @@ export class Lowerer {
|
|
|
1143
1163
|
}
|
|
1144
1164
|
if (!optionalOrigin)
|
|
1145
1165
|
return null;
|
|
1166
|
+
// A checked JavaScript indexed read can already be boxed. The checker
|
|
1167
|
+
// calls the element present, but that inference is not a runtime guard.
|
|
1168
|
+
if (isJsSourceFile(node.getSourceFile()) && value.kind === "dynCheck" && value.value.type.kind === "dyn")
|
|
1169
|
+
return value.value;
|
|
1146
1170
|
let source = value;
|
|
1147
1171
|
if (value.kind === "call" &&
|
|
1148
1172
|
this.checkedNarrowHelpers.has(value.callee) &&
|
|
@@ -1348,10 +1372,12 @@ export class Lowerer {
|
|
|
1348
1372
|
copyRetagHelpers = new Map();
|
|
1349
1373
|
unionLiteralOwners = new Map();
|
|
1350
1374
|
strippedUndefinedArms = new Map();
|
|
1375
|
+
addedUndefinedArms = new Map();
|
|
1351
1376
|
stdlibSymbols = new Map();
|
|
1352
1377
|
/** Method adapter names are owned by class-method-values. Looking them
|
|
1353
1378
|
* up must not scan and retain every unrelated lifted function. */
|
|
1354
1379
|
classMethodValueHelpers = new Set();
|
|
1380
|
+
classMethodValueSelections = new Map();
|
|
1355
1381
|
/** Callee names of every interned coercion helper whose CALL mints a
|
|
1356
1382
|
* FRESH closure per evaluation (%fn.width.*, %fn.adapt.*,
|
|
1357
1383
|
* %fnval.spawnres.*). Registered at the mint site — NOT recovered by
|
|
@@ -1442,9 +1468,15 @@ export class Lowerer {
|
|
|
1442
1468
|
/** Inferred JS methods participating in an override chain keep a vtable
|
|
1443
1469
|
* ABI instead of call-site specialization. Filled before class collection. */
|
|
1444
1470
|
virtualJsMethods = new Set();
|
|
1471
|
+
/** Descendant writes must widen the original JS field before collecting
|
|
1472
|
+
* any class layout; base and derived instances share its storage ABI. */
|
|
1473
|
+
inheritedJsFieldWrites = new Map();
|
|
1445
1474
|
/** Largest fixed argument list below a JS method, discovered before any
|
|
1446
1475
|
* base vtable signature is collected. Unused checked slots carry undefined. */
|
|
1447
1476
|
virtualJsMethodArity = new Map();
|
|
1477
|
+
checkedVirtualJsMethods = new Set();
|
|
1478
|
+
checkedVirtualJsAccessors = new Set();
|
|
1479
|
+
checkedVirtualJsValueReturns = new Set();
|
|
1448
1480
|
/** The class whose members are lowering — `super` binds lexically to it
|
|
1449
1481
|
* (arrows inside methods lower within this window, so they see it too). */
|
|
1450
1482
|
currentClass = null;
|
|
@@ -1583,6 +1615,7 @@ export class Lowerer {
|
|
|
1583
1615
|
* a reference to a lowerable body reports its name here — recorded even
|
|
1584
1616
|
* when the enclosing statement later poisons. */
|
|
1585
1617
|
onEdge = null;
|
|
1618
|
+
deferredModuleInitializers = null;
|
|
1586
1619
|
// Stack of function contexts (bottom = the function being declared at
|
|
1587
1620
|
// top level, top = the innermost nested function currently lowering).
|
|
1588
1621
|
fnStack = [];
|
|
@@ -1621,6 +1654,15 @@ export class Lowerer {
|
|
|
1621
1654
|
* is assembled directly. The configured reachable set remains null so
|
|
1622
1655
|
* demand-driven instance lowering keeps its existing gates. */
|
|
1623
1656
|
reachableForArtifacts = null;
|
|
1657
|
+
/** Constructors retained by the active worklist. A boxed base receiver
|
|
1658
|
+
* can contain any retained descendant, but importing its declaration
|
|
1659
|
+
* alone does not make every descendant constructible. */
|
|
1660
|
+
constructedClasses = null;
|
|
1661
|
+
virtualEdges = new Map();
|
|
1662
|
+
classCanBeConstructed(info) {
|
|
1663
|
+
return this.constructedClasses === null || this.constructedClasses.has(info.def.name) ||
|
|
1664
|
+
info.genericInstance !== undefined || info.mixinInstance !== undefined;
|
|
1665
|
+
}
|
|
1624
1666
|
/** Coverage remainder mode: the reachability gate inverts (see wantBody)
|
|
1625
1667
|
* and no module is built. */
|
|
1626
1668
|
remainder;
|
|
@@ -2467,8 +2509,11 @@ export class Lowerer {
|
|
|
2467
2509
|
if (!symbol)
|
|
2468
2510
|
return null;
|
|
2469
2511
|
const g = this.globalsBySymbol.get(symbol);
|
|
2470
|
-
if (g)
|
|
2512
|
+
if (g) {
|
|
2513
|
+
if (g.type.kind === "func")
|
|
2514
|
+
g.type = this.runtimeOptionalBindingType(ident, g.type);
|
|
2471
2515
|
return g;
|
|
2516
|
+
}
|
|
2472
2517
|
for (const d of this.checker.declarationsOf(symbol)) {
|
|
2473
2518
|
const byDecl = this.globalsByDeclNode.get(d);
|
|
2474
2519
|
if (byDecl)
|
|
@@ -2713,6 +2758,14 @@ export class Lowerer {
|
|
|
2713
2758
|
return null;
|
|
2714
2759
|
return s.flags & ts.SymbolFlags.Alias ? this.checker.getAliasedSymbol(s) : s;
|
|
2715
2760
|
};
|
|
2761
|
+
const signatureOf = (node) => {
|
|
2762
|
+
const symbol = symbolOf(node);
|
|
2763
|
+
if (!symbol)
|
|
2764
|
+
return null;
|
|
2765
|
+
const projection = this.staticCallables.get(symbol);
|
|
2766
|
+
return this.fnSigsBySymbol.get(symbol) ??
|
|
2767
|
+
(projection?.kind === "declared-function" ? projection.signature : null);
|
|
2768
|
+
};
|
|
2716
2769
|
const functionDeclBySymbol = new Map();
|
|
2717
2770
|
const signatureBySymbol = new Map();
|
|
2718
2771
|
const methodFamilies = new Map();
|
|
@@ -2866,9 +2919,11 @@ export class Lowerer {
|
|
|
2866
2919
|
}
|
|
2867
2920
|
if (ts.isBinaryExpression(e)) {
|
|
2868
2921
|
const op = e.operatorToken.kind;
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2922
|
+
// Nullish/falsy left values select the fallback, so only that
|
|
2923
|
+
// fallback can make the whole expression undefined.
|
|
2924
|
+
if (op === ts.SyntaxKind.BarBarToken || op === ts.SyntaxKind.QuestionQuestionToken)
|
|
2925
|
+
return mayBeOptional(e.right);
|
|
2926
|
+
if (op === ts.SyntaxKind.AmpersandAmpersandToken)
|
|
2872
2927
|
return mayBeOptional(e.left) || mayBeOptional(e.right);
|
|
2873
2928
|
}
|
|
2874
2929
|
if (ts.isPropertyAccessExpression(e) && ts.isIdentifier(e.expression)) {
|
|
@@ -2994,6 +3049,29 @@ export class Lowerer {
|
|
|
2994
3049
|
found = true;
|
|
2995
3050
|
return found;
|
|
2996
3051
|
};
|
|
3052
|
+
const jsLambdas = [];
|
|
3053
|
+
for (const sf of sourceFiles) {
|
|
3054
|
+
if (!isJsSourceFile(sf))
|
|
3055
|
+
continue;
|
|
3056
|
+
ts.walkPreorder(sf, (node) => {
|
|
3057
|
+
if (ts.isArrowFunction(node) || ts.isFunctionExpression(node))
|
|
3058
|
+
jsLambdas.push(node);
|
|
3059
|
+
});
|
|
3060
|
+
}
|
|
3061
|
+
for (const [symbol, signature] of signatureBySymbol) {
|
|
3062
|
+
const declaration = functionDeclBySymbol.get(symbol);
|
|
3063
|
+
if (!declaration || !isJsSourceFile(declaration.getSourceFile()))
|
|
3064
|
+
continue;
|
|
3065
|
+
const checked = this.checker.getSignatureFromDeclaration(declaration);
|
|
3066
|
+
const checkedReturn = checked ? this.checker.getReturnTypeOfSignature(checked) : null;
|
|
3067
|
+
// Checker-known optional results already narrow at each use. Only
|
|
3068
|
+
// propagate undefined that JavaScript's runtime ABI adds beyond them.
|
|
3069
|
+
if (checkedReturn && ((checkedReturn.flags & ts.TypeFlags.Undefined) !== 0 ||
|
|
3070
|
+
checkedReturn.isUnionType() && ts.constituentTypes(checkedReturn).some((arm) => (arm.flags & ts.TypeFlags.Undefined) !== 0)))
|
|
3071
|
+
continue;
|
|
3072
|
+
if (signature.returnType.kind === "union" && this.armTag(signature.returnType.unionId, UNDEFINED_T) >= 0)
|
|
3073
|
+
optionalReturns.add(symbol);
|
|
3074
|
+
}
|
|
2997
3075
|
const promoteHofCallback = (callback, parameterIndices, seen = new Set()) => {
|
|
2998
3076
|
let changed = false;
|
|
2999
3077
|
const checkerTypeContainsTypeParameter = (type) => {
|
|
@@ -3431,6 +3509,23 @@ export class Lowerer {
|
|
|
3431
3509
|
for (const [symbol, decl] of functionDeclBySymbol)
|
|
3432
3510
|
if (scanReturns(symbol, decl))
|
|
3433
3511
|
changed = true;
|
|
3512
|
+
for (const fn of jsLambdas) {
|
|
3513
|
+
if (!bodyReturnsOptional(fn))
|
|
3514
|
+
continue;
|
|
3515
|
+
const mapped = this.mapTypeOf(this.typeOf(fn));
|
|
3516
|
+
if (mapped?.kind !== "func")
|
|
3517
|
+
continue;
|
|
3518
|
+
const previous = this.runtimeOptionalFunctionReturnType(fn, mapped.ret);
|
|
3519
|
+
if (previous.kind === "generator")
|
|
3520
|
+
continue;
|
|
3521
|
+
const next = previous.kind === "promise"
|
|
3522
|
+
? { ...previous, inner: this.runtimeOptionalType(previous.inner) }
|
|
3523
|
+
: this.runtimeOptionalType(previous);
|
|
3524
|
+
if (!typeEquals(previous, next)) {
|
|
3525
|
+
this.runtimeOptionalFunctionReturns.set(fn, next);
|
|
3526
|
+
changed = true;
|
|
3527
|
+
}
|
|
3528
|
+
}
|
|
3434
3529
|
// Every implementation of a virtual slot must retain the same ABI,
|
|
3435
3530
|
// including when just one body forwards an omitted parameter.
|
|
3436
3531
|
for (const family of optionalMethodFamilies) {
|
|
@@ -3475,6 +3570,14 @@ export class Lowerer {
|
|
|
3475
3570
|
this.runtimeOptionalFunctionReturns.set(decl, arithmetic);
|
|
3476
3571
|
}
|
|
3477
3572
|
}
|
|
3573
|
+
for (const [declaration, global] of this.globalsByDeclNode) {
|
|
3574
|
+
if (global.type.kind !== "func" || !ts.isBinaryExpression(declaration) || !isJsSourceFile(declaration.getSourceFile()))
|
|
3575
|
+
continue;
|
|
3576
|
+
const value = peel(declaration.right);
|
|
3577
|
+
if (!ts.isFunctionExpression(value) && !ts.isArrowFunction(value))
|
|
3578
|
+
continue;
|
|
3579
|
+
global.type = { ...global.type, ret: this.runtimeOptionalFunctionReturnType(value, global.type.ret) };
|
|
3580
|
+
}
|
|
3478
3581
|
for (const sf of sourceFiles) {
|
|
3479
3582
|
ts.walkPreorder(sf, (node) => {
|
|
3480
3583
|
if (!ts.isVariableDeclaration(node) || !ts.isIdentifier(node.name))
|
|
@@ -3482,6 +3585,23 @@ export class Lowerer {
|
|
|
3482
3585
|
const symbol = symbolOf(node.name);
|
|
3483
3586
|
if (!symbol)
|
|
3484
3587
|
return;
|
|
3588
|
+
if (isJsSourceFile(sf) && !node.type && !hasJsTypeAnnotation(node) && node.initializer &&
|
|
3589
|
+
(ts.isArrowFunction(node.initializer) || ts.isFunctionExpression(node.initializer))) {
|
|
3590
|
+
const global = this.globalsBySymbol.get(symbol);
|
|
3591
|
+
if (global?.type.kind === "func")
|
|
3592
|
+
global.type = { ...global.type, ret: this.runtimeOptionalFunctionReturnType(node.initializer, global.type.ret) };
|
|
3593
|
+
}
|
|
3594
|
+
if (!node.type && !hasJsTypeAnnotation(node) && node.initializer && ts.isIdentifier(node.initializer)) {
|
|
3595
|
+
const global = this.globalsBySymbol.get(symbol);
|
|
3596
|
+
const current = global?.type ?? this.mapTypeOf(this.typeOf(node.name));
|
|
3597
|
+
const source = current?.kind === "func" ? signatureOf(node.initializer) : null;
|
|
3598
|
+
if (source && current?.kind === "func") {
|
|
3599
|
+
const promoted = { ...current, params: source.params.filter((param) => param.mode !== "dynRest" && param.mode !== "arguments").map((param) => param.type), ret: source.returnType };
|
|
3600
|
+
this.runtimeOptionalBindingTypes.set(symbol, promoted);
|
|
3601
|
+
if (global)
|
|
3602
|
+
global.type = promoted;
|
|
3603
|
+
}
|
|
3604
|
+
}
|
|
3485
3605
|
const fields = optionalFields.get(symbol);
|
|
3486
3606
|
if (!dynamicObjectEntryRows.has(symbol) && !optionalSymbols.has(symbol) && !fields)
|
|
3487
3607
|
return;
|
|
@@ -3492,7 +3612,7 @@ export class Lowerer {
|
|
|
3492
3612
|
if (!dynamicObjectEntryRows.has(symbol) && optionalSymbols.has(symbol))
|
|
3493
3613
|
promoted = addUndefined(promoted);
|
|
3494
3614
|
if (promoted.kind === "func" && node.initializer && ts.isIdentifier(node.initializer)) {
|
|
3495
|
-
const sourceSig =
|
|
3615
|
+
const sourceSig = signatureOf(node.initializer);
|
|
3496
3616
|
if (sourceSig) {
|
|
3497
3617
|
promoted = {
|
|
3498
3618
|
...promoted,
|
|
@@ -3692,6 +3812,7 @@ export class Lowerer {
|
|
|
3692
3812
|
* and the retained reachability worklist. */
|
|
3693
3813
|
finishModule(functions) {
|
|
3694
3814
|
finalizeClassMethodValues(this, functions);
|
|
3815
|
+
trackClassFieldCreation(this, functions);
|
|
3695
3816
|
// Globals typed by a class that never REGISTERED (a JS class whose
|
|
3696
3817
|
// collection fenced — Symbol-keyed fields, an unsupported base): the
|
|
3697
3818
|
// declaration statement and every use compiled to runtime fences, but
|
|
@@ -3862,6 +3983,7 @@ export class Lowerer {
|
|
|
3862
3983
|
* body; both fire edges through the same hooks and are not units
|
|
3863
3984
|
* themselves. */
|
|
3864
3985
|
emitReachable(extraRoots) {
|
|
3986
|
+
this.deferredModuleInitializers = new DeferredModuleInitializers();
|
|
3865
3987
|
const parts = this.splitFiles();
|
|
3866
3988
|
// Direct lowering callers do not necessarily run program preflight.
|
|
3867
3989
|
// Establish the same managed header/top-level batch here before
|
|
@@ -4028,6 +4150,7 @@ export class Lowerer {
|
|
|
4028
4150
|
return owner;
|
|
4029
4151
|
};
|
|
4030
4152
|
const reachable = new Set();
|
|
4153
|
+
this.constructedClasses = new Set();
|
|
4031
4154
|
const queue = [];
|
|
4032
4155
|
const loweredUnits = new Map();
|
|
4033
4156
|
const initFunctions = [];
|
|
@@ -4038,6 +4161,12 @@ export class Lowerer {
|
|
|
4038
4161
|
reachable.add(name);
|
|
4039
4162
|
if (units.has(name))
|
|
4040
4163
|
queue.push(name);
|
|
4164
|
+
if (this.constructedClasses && name.endsWith(".constructor")) {
|
|
4165
|
+
this.constructedClasses.add(name.slice(1, -".constructor".length));
|
|
4166
|
+
for (const [owner, methods] of this.virtualEdges)
|
|
4167
|
+
for (const method of methods)
|
|
4168
|
+
this.noteVirtualEdge(owner, method);
|
|
4169
|
+
}
|
|
4041
4170
|
};
|
|
4042
4171
|
// Class EXPRESSIONS collect while init bodies lower (below): their
|
|
4043
4172
|
// member units register the moment collection finishes — before any
|
|
@@ -4188,10 +4317,13 @@ export class Lowerer {
|
|
|
4188
4317
|
const classDispatch = new ClassDynamicDispatch(extraRoots !== undefined);
|
|
4189
4318
|
for (;;) {
|
|
4190
4319
|
drainInstances();
|
|
4320
|
+
const initializerChanged = this.deferredModuleInitializers.process(this, [
|
|
4321
|
+
...loweredUnits.values(), ...initFunctions, ...instanceFunctions, ...this.liftedFns, ...this.implicitFns,
|
|
4322
|
+
]);
|
|
4191
4323
|
const dispatchChanged = classDispatch.process(this, [
|
|
4192
4324
|
...loweredUnits.values(), ...initFunctions, ...instanceFunctions, ...this.liftedFns, ...this.implicitFns,
|
|
4193
4325
|
]);
|
|
4194
|
-
if (queue.length === 0 && !dispatchChanged)
|
|
4326
|
+
if (queue.length === 0 && !dispatchChanged && !initializerChanged)
|
|
4195
4327
|
break;
|
|
4196
4328
|
drainUnits();
|
|
4197
4329
|
this.restoreGenericInstanceOrder(instLowered);
|
|
@@ -4214,6 +4346,20 @@ export class Lowerer {
|
|
|
4214
4346
|
...this.liftedFns,
|
|
4215
4347
|
...this.implicitFns,
|
|
4216
4348
|
];
|
|
4349
|
+
// The worklist can leave a virtual site with only its base method.
|
|
4350
|
+
// Devirtualize after construction/override reachability has settled.
|
|
4351
|
+
for (const fn of functions)
|
|
4352
|
+
fn.body = transformStmtList(fn.body, { stmt: (statement) => statement, expr: (expression) => {
|
|
4353
|
+
if (expression.kind !== "virtualCall")
|
|
4354
|
+
return expression;
|
|
4355
|
+
const info = this.classes.get(expression.className);
|
|
4356
|
+
const method = info && this.findMethodOn(info, expression.method);
|
|
4357
|
+
if (!method || method.sig.abstract || [...this.classes.values()].some((candidate) => this.isSubclassOf(candidate.def.name, expression.className) && candidate.def.name !== expression.className &&
|
|
4358
|
+
candidate.methods.has(expression.method) && reachable.has(`%${candidate.def.name}.${expression.method}`)))
|
|
4359
|
+
return expression;
|
|
4360
|
+
return { kind: "call", callee: `%${method.declarer.def.name}.${expression.method}`,
|
|
4361
|
+
args: [this.upcastTo(expression.args[0], method.declarer.def.name), ...expression.args.slice(1)], type: expression.type, loc: expression.loc };
|
|
4362
|
+
} });
|
|
4217
4363
|
this.reachableForArtifacts = reachable;
|
|
4218
4364
|
return { reachable, result: this.finishModule(functions) };
|
|
4219
4365
|
}
|
|
@@ -4231,12 +4377,17 @@ export class Lowerer {
|
|
|
4231
4377
|
noteVirtualEdge(info, method) {
|
|
4232
4378
|
if (!this.onEdge)
|
|
4233
4379
|
return;
|
|
4380
|
+
if (this.constructedClasses) {
|
|
4381
|
+
const methods = this.virtualEdges.get(info) ?? new Set();
|
|
4382
|
+
methods.add(method);
|
|
4383
|
+
this.virtualEdges.set(info, methods);
|
|
4384
|
+
}
|
|
4234
4385
|
const above = this.findMethodOn(info, method);
|
|
4235
4386
|
if (above)
|
|
4236
4387
|
this.noteEdge(`%${above.declarer.def.name}.${method}`);
|
|
4237
4388
|
const below = (c) => {
|
|
4238
4389
|
for (const s of c.subclasses) {
|
|
4239
|
-
if (s.methods.has(method))
|
|
4390
|
+
if (this.classCanBeConstructed(s) && s.methods.has(method))
|
|
4240
4391
|
this.noteEdge(`%${s.def.name}.${method}`);
|
|
4241
4392
|
below(s);
|
|
4242
4393
|
}
|
|
@@ -4587,6 +4738,16 @@ export class Lowerer {
|
|
|
4587
4738
|
return fenceStaticReadableStreamMember(this, access, use);
|
|
4588
4739
|
}
|
|
4589
4740
|
typeOf(node) {
|
|
4741
|
+
if (ts.isPropertyAccessExpression(node) && isJsSourceFile(node.getSourceFile())) {
|
|
4742
|
+
const receiver = node.expression.kind === ts.SyntaxKind.ThisKeyword && this.fnStack.length > 0
|
|
4743
|
+
? this.resolveThis()?.type : this.mapTypeOf(this.checker.getTypeAtLocation(node.expression));
|
|
4744
|
+
const checkedThis = node.expression.kind === ts.SyntaxKind.ThisKeyword && this.fnStack.length > 0 && receiver?.kind === "dyn"
|
|
4745
|
+
? this.currentClass : null;
|
|
4746
|
+
if (receiver?.kind === "object" && this.classes.get(receiver.className)?.fields.get(node.name.text)?.kind === "dyn" ||
|
|
4747
|
+
checkedThis?.fields.get(node.name.text)?.kind === "dyn") {
|
|
4748
|
+
return this.checker.getUnknownType();
|
|
4749
|
+
}
|
|
4750
|
+
}
|
|
4590
4751
|
// A checked JS method receives its actual call-site receiver. Its
|
|
4591
4752
|
// declaration's inferred class type must not turn property reads back
|
|
4592
4753
|
// into native field loads when the method is borrowed by another object.
|
|
@@ -4637,8 +4798,15 @@ export class Lowerer {
|
|
|
4637
4798
|
// A checked value can contain any runtime kind. A checker-proven
|
|
4638
4799
|
// branch narrow therefore cannot contradict this specialization;
|
|
4639
4800
|
// reads still validate the payload through maybeNarrow.
|
|
4640
|
-
if (boundIr.kind === "dyn")
|
|
4641
|
-
|
|
4801
|
+
if (boundIr.kind === "dyn") {
|
|
4802
|
+
// JSDoc and initializer inference are declaration types, not flow
|
|
4803
|
+
// proofs. A checked specialization must not reinstate those
|
|
4804
|
+
// stale layouts (mutable/null slots and heterogeneous JS arrays).
|
|
4805
|
+
const declaration = sym && this.checker.valueDeclarationOf(sym);
|
|
4806
|
+
const declared = declaration && ts.isParameter(declaration)
|
|
4807
|
+
? this.mapTypeOf(this.checker.getTypeAtLocation(declaration.name)) : null;
|
|
4808
|
+
return declared && typeEquals(declared, narrowedIr) ? bound : t;
|
|
4809
|
+
}
|
|
4642
4810
|
// A union binding narrowed to one of its arms (typeof/equality
|
|
4643
4811
|
// guards over string|number bindings) — the narrow is truth.
|
|
4644
4812
|
if (boundIr.kind === "union") {
|
|
@@ -5063,7 +5231,14 @@ export class Lowerer {
|
|
|
5063
5231
|
// undefined/null literals store the dyn unit values. Types outside the
|
|
5064
5232
|
// dyn's domain (bytes, classes, Maps, ...) fall through to
|
|
5065
5233
|
// requireExactShape's SC1101 fence.
|
|
5066
|
-
//
|
|
5234
|
+
// Promise payloads may widen at a checked return boundary, including
|
|
5235
|
+
// arrays inferred as tuple results by Promise.all. Keep both payload
|
|
5236
|
+
// ABIs explicit: box settlement, then validate the destination payload.
|
|
5237
|
+
if (expected.kind === "promise" && expected.inner.kind !== "void" && expr.type.kind === "promise" &&
|
|
5238
|
+
!typeEquals(expected, expr.type) && this.dynConvertible(expr.type) &&
|
|
5239
|
+
canDynCheckTo(expected, (id) => this.shapes.get(id), (id) => this.unions.get(id))) {
|
|
5240
|
+
return { kind: "dynCheck", value: this.coerceToExpected(expr, DYN), type: expected, loc: expr.loc };
|
|
5241
|
+
}
|
|
5067
5242
|
// Promise<never> return holding a `return Promise.reject(value)` the
|
|
5068
5243
|
// dyn arm typed promise<dyn>): awaiting through the slot ignores the
|
|
5069
5244
|
// fulfillment payload (scr_await_void) and rejections flow untyped,
|
|
@@ -7749,7 +7924,7 @@ export class Lowerer {
|
|
|
7749
7924
|
// NamedEvaluation through a variable initializer) — inspect prints
|
|
7750
7925
|
// [Function: name] and call errors spell it, like Node.
|
|
7751
7926
|
if (e.kind === "dynFrom" && e.value.type.kind === "func" && e.fnName === undefined) {
|
|
7752
|
-
const name = jsFuncNameOf(node);
|
|
7927
|
+
const name = jsFuncNameOf(node, this);
|
|
7753
7928
|
if (name !== null)
|
|
7754
7929
|
e = { ...e, fnName: name };
|
|
7755
7930
|
}
|
|
@@ -8039,7 +8214,7 @@ export class Lowerer {
|
|
|
8039
8214
|
}
|
|
8040
8215
|
}
|
|
8041
8216
|
let e = this.lowerExpr(node);
|
|
8042
|
-
if (expected?.kind === "union" && this.armTag(expected.unionId, UNDEFINED_T) >= 0) {
|
|
8217
|
+
if (expected?.kind === "union" && this.armTag(expected.unionId, UNDEFINED_T) >= 0 || expected?.kind === "dyn" && isJsSourceFile(node.getSourceFile())) {
|
|
8043
8218
|
// A destination that accepts undefined must retain an unchecked
|
|
8044
8219
|
// read's storage value even when the checker still calls it present.
|
|
8045
8220
|
e = this.runtimeOptionalSourceValue(node, e) ?? e;
|
|
@@ -8100,7 +8275,19 @@ export class Lowerer {
|
|
|
8100
8275
|
* declared result type of an index-signature read under
|
|
8101
8276
|
* noUncheckedIndexedAccess. Null when the type cannot take the arm. */
|
|
8102
8277
|
withUndefinedArmOf(t) {
|
|
8103
|
-
|
|
8278
|
+
if (t.kind !== "union")
|
|
8279
|
+
return withUndefinedArmCanonical(t, this.unions);
|
|
8280
|
+
const cached = this.addedUndefinedArms.get(t.unionId);
|
|
8281
|
+
if (cached && cached.unions === this.unions.revision)
|
|
8282
|
+
return cached.type;
|
|
8283
|
+
// As with removing undefined, repeated optional-read propagation can
|
|
8284
|
+
// reuse the exact union transformation until a recursive contract closes.
|
|
8285
|
+
// An unknown id is not cached: a later interning can create it.
|
|
8286
|
+
if (!this.unions.get(t.unionId))
|
|
8287
|
+
return null;
|
|
8288
|
+
const type = withUndefinedArmCanonical(t, this.unions);
|
|
8289
|
+
this.addedUndefinedArms.set(t.unionId, { type, unions: this.unions.revision });
|
|
8290
|
+
return type;
|
|
8104
8291
|
}
|
|
8105
8292
|
/** True when a static type converts to a dyn value (the dynFrom
|
|
8106
8293
|
* walker's domain): JSON-safe, bytes<u8> (Uint8Array/Buffer — the checked-dynamic tree's
|
|
@@ -9755,6 +9942,10 @@ export class Lowerer {
|
|
|
9755
9942
|
* member access that IS a module in its own right (`fs.promises` — the
|
|
9756
9943
|
* same object as node:fs/promises, Node's rule). Null otherwise. */
|
|
9757
9944
|
builtinNamespaceModuleOf(expr) {
|
|
9945
|
+
// Default and CommonJS process bindings alias the global object, whose
|
|
9946
|
+
// methods and properties keep their existing process lowerings.
|
|
9947
|
+
if (stdlibGlobalNameOf(this, expr) === "process")
|
|
9948
|
+
return null;
|
|
9758
9949
|
const stored = ts.isIdentifier(expr)
|
|
9759
9950
|
? (this.peekLocal(expr)?.type ?? this.globalOf(expr)?.type)
|
|
9760
9951
|
: undefined;
|