@scriptc/compiler 0.2.0 → 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 +84 -19
- package/dist/backend/cycle-analysis.js +1 -0
- package/dist/backend/cycle-analysis.js.map +1 -1
- package/dist/backend/llvm/classes.js +21 -5
- package/dist/backend/llvm/classes.js.map +1 -1
- package/dist/backend/llvm/dyn.d.ts +8 -0
- package/dist/backend/llvm/dyn.js +247 -108
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.d.ts +6 -3
- package/dist/backend/llvm/emitter.js +99 -25
- 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-bytes.d.ts +1 -1
- package/dist/backend/llvm/expr-bytes.js +28 -17
- package/dist/backend/llvm/expr-bytes.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-control.js +1 -1
- package/dist/backend/llvm/expr-control.js.map +1 -1
- package/dist/backend/llvm/expr-dynamic.js +47 -13
- package/dist/backend/llvm/expr-dynamic.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.js +11 -1
- package/dist/backend/llvm/expr-primitives.js.map +1 -1
- package/dist/backend/llvm/expr-records.js +11 -3
- package/dist/backend/llvm/expr-records.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.js +187 -18
- 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-process.js +23 -3
- package/dist/backend/llvm/lib-process.js.map +1 -1
- package/dist/backend/llvm/lib-shared.js +80 -3
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/llvm/shapes.js +8 -2
- package/dist/backend/llvm/shapes.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/native-toolchain.d.ts +3 -6
- package/dist/backend/native-toolchain.js +53 -23
- package/dist/backend/native-toolchain.js.map +1 -1
- package/dist/backend/native-toolchain.test.js +72 -0
- package/dist/backend/native-toolchain.test.js.map +1 -1
- package/dist/backend/runtime-abi.d.ts +2 -2
- package/dist/backend/runtime-abi.js +2 -2
- package/dist/backend/runtime-pack-native.js +4 -1
- package/dist/backend/runtime-pack-native.js.map +1 -1
- package/dist/backend/runtime-pack-targets.test.js +1 -1
- package/dist/backend/runtime-pack.test.js +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/backend/targets.js +10 -6
- package/dist/backend/targets.js.map +1 -1
- package/dist/backend/targets.test.js +7 -0
- package/dist/backend/targets.test.js.map +1 -1
- package/dist/compat/fetch-profile.js +34 -4
- package/dist/compat/fetch-profile.js.map +1 -1
- package/dist/coverage/surface-manifest.js +5 -3
- package/dist/coverage/surface-manifest.js.map +1 -1
- package/dist/diagnostics/diagnostic.js +2 -7
- package/dist/diagnostics/diagnostic.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 +4 -4
- package/dist/frontend/lowering/class-callbacks.js +29 -17
- package/dist/frontend/lowering/class-callbacks.js.map +1 -1
- package/dist/frontend/lowering/class-construction.d.ts +14 -0
- package/dist/frontend/lowering/class-construction.js +185 -0
- package/dist/frontend/lowering/class-construction.js.map +1 -0
- package/dist/frontend/lowering/class-descriptors.d.ts +2 -1
- package/dist/frontend/lowering/class-descriptors.js +58 -10
- package/dist/frontend/lowering/class-descriptors.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +36 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.js +965 -91
- package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js +66 -3
- 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 +15 -42
- package/dist/frontend/lowering/class-instance-constructor.js.map +1 -1
- package/dist/frontend/lowering/class-method-values.d.ts +20 -1
- package/dist/frontend/lowering/class-method-values.js +120 -24
- package/dist/frontend/lowering/class-method-values.js.map +1 -1
- package/dist/frontend/lowering/class-prototypes.d.ts +10 -3
- package/dist/frontend/lowering/class-prototypes.js +188 -21
- package/dist/frontend/lowering/class-prototypes.js.map +1 -1
- package/dist/frontend/lowering/class-runtime-statics.d.ts +8 -0
- package/dist/frontend/lowering/class-runtime-statics.js +84 -0
- package/dist/frontend/lowering/class-runtime-statics.js.map +1 -0
- package/dist/frontend/lowering/class-static-data.d.ts +1 -0
- package/dist/frontend/lowering/class-static-data.js +6 -4
- package/dist/frontend/lowering/class-static-data.js.map +1 -1
- package/dist/frontend/lowering/containers/bytes.js +66 -17
- package/dist/frontend/lowering/containers/bytes.js.map +1 -1
- package/dist/frontend/lowering/containers/string-and-regexp.js +24 -47
- 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/error-methods.d.ts +4 -1
- package/dist/frontend/lowering/error-methods.js +100 -1
- package/dist/frontend/lowering/error-methods.js.map +1 -1
- package/dist/frontend/lowering/expressions/native-proxy.js +3 -1
- package/dist/frontend/lowering/expressions/native-proxy.js.map +1 -1
- package/dist/frontend/lowering/expressions/nullish-assignment.js +19 -11
- package/dist/frontend/lowering/expressions/nullish-assignment.js.map +1 -1
- package/dist/frontend/lowering/expressions/object-literals.js +68 -7
- package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
- package/dist/frontend/lowering/expressions/optional-chains.d.ts +3 -4
- package/dist/frontend/lowering/expressions/optional-chains.js +72 -20
- package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
- package/dist/frontend/lowering/function-context.d.ts +11 -3
- package/dist/frontend/lowering/function-context.js +11 -5
- package/dist/frontend/lowering/function-context.js.map +1 -1
- package/dist/frontend/lowering/generator-dynamic-dispatch.d.ts +1 -0
- package/dist/frontend/lowering/generator-dynamic-dispatch.js +39 -1
- package/dist/frontend/lowering/generator-dynamic-dispatch.js.map +1 -1
- package/dist/frontend/lowering/lib-boundary.d.ts +2 -0
- package/dist/frontend/lowering/lib-boundary.js +54 -1
- package/dist/frontend/lowering/lib-boundary.js.map +1 -1
- package/dist/frontend/lowering/lower-builtin-values.d.ts +7 -1
- package/dist/frontend/lowering/lower-builtin-values.js +113 -3
- package/dist/frontend/lowering/lower-builtin-values.js.map +1 -1
- package/dist/frontend/lowering/lower-builtins.d.ts +10 -14
- package/dist/frontend/lowering/lower-builtins.js +443 -88
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +8 -5
- package/dist/frontend/lowering/lower-calls.js +717 -142
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +18 -13
- package/dist/frontend/lowering/lower-classes.js +1076 -188
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.d.ts +9 -0
- package/dist/frontend/lowering/lower-containers.js +172 -51
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-dgram.js +3 -2
- package/dist/frontend/lowering/lower-dgram.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +12 -8
- package/dist/frontend/lowering/lower-exprs.js +802 -232
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-generators.js +17 -2
- 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.d.ts +2 -0
- package/dist/frontend/lowering/lower-island.js +36 -10
- 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 +380 -73
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.test.d.ts +1 -0
- package/dist/frontend/lowering/lower-modules.test.js +107 -0
- package/dist/frontend/lowering/lower-modules.test.js.map +1 -0
- package/dist/frontend/lowering/lower-stmts.d.ts +7 -3
- package/dist/frontend/lowering/lower-stmts.js +221 -47
- 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 +3 -1
- 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 +53 -10
- package/dist/frontend/lowering/lowerer.js +390 -77
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/lowerer.test.js +187 -3
- 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 +3 -0
- package/dist/frontend/lowering/surfaces.js +48 -19
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/lowering/text-decoder-encoding.d.ts +2 -0
- package/dist/frontend/lowering/text-decoder-encoding.js +8 -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/lowering/unregistered-class-types.test.js +3 -3
- package/dist/frontend/lowering/unregistered-class-types.test.js.map +1 -1
- package/dist/frontend/npm-static-prune.js +116 -34
- package/dist/frontend/npm-static-prune.js.map +1 -1
- package/dist/frontend/npm-static-prune.test.js +8 -0
- package/dist/frontend/npm-static-prune.test.js.map +1 -1
- package/dist/frontend/program.d.ts +1 -1
- package/dist/frontend/program.js +57 -26
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/program.test.js +18 -0
- package/dist/frontend/program.test.js.map +1 -1
- package/dist/frontend/ts7/ast.js +4 -3
- package/dist/frontend/ts7/ast.js.map +1 -1
- package/dist/frontend/ts7/semantic-json.js +5 -10
- package/dist/frontend/ts7/semantic-json.js.map +1 -1
- package/dist/frontend/type-mapper.d.ts +9 -1
- package/dist/frontend/type-mapper.js +169 -23
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/frontend/type-mapper.test.js +23 -0
- package/dist/frontend/type-mapper.test.js.map +1 -1
- package/dist/frontend/union-discriminants.d.ts +1 -1
- package/dist/frontend/union-discriminants.js +24 -9
- 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/analysis.js +2 -0
- package/dist/ir/analysis.js.map +1 -1
- package/dist/ir/ir.d.ts +74 -41
- package/dist/ir/ir.js +167 -43
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/ir.test.js +35 -0
- package/dist/ir/ir.test.js.map +1 -1
- package/dist/ir/serialize.js +35 -3
- package/dist/ir/serialize.js.map +1 -1
- package/dist/ir/serialize.test.js +26 -1
- 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 +136 -16
- package/dist/ir/validate.js.map +1 -1
- package/dist/ir/validate.test.js +77 -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/dist/native/sanitizer.js +3 -1
- package/dist/native/sanitizer.js.map +1 -1
- package/dist/native/toolchain.d.ts +1 -1
- package/dist/native/toolchain.js +26 -6
- package/dist/native/toolchain.js.map +1 -1
- package/dist/native/toolchain.test.js +53 -1
- package/dist/native/toolchain.test.js.map +1 -1
- package/package.json +20 -20
- package/surface-manifest.json +170 -93
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { pathModuleValue } from "./lower-builtin-values.js";
|
|
2
|
+
import { everyExprChild, everyStmtChild, transformStmtList } from "../../ir/traverse.js";
|
|
2
3
|
import { RuntimeOptionalLocals } from "./runtime-optional-locals.js";
|
|
3
4
|
import { sanitizeUnregisteredClassTypes } from "./sanitize-class-types.js";
|
|
4
5
|
import { UnregisteredClassTypes } from "./unregistered-class-types.js";
|
|
@@ -8,7 +9,8 @@ import { bindingInContext, captureContextBinding, declareContextLocal, declareCo
|
|
|
8
9
|
export { newFnCtx } from "./function-context.js";
|
|
9
10
|
import { InternalCompilerError } from "../../errors.js";
|
|
10
11
|
import { defaultAfterUndefined, lowerStaticallyUndefinedArgument } from "./optional-arguments.js";
|
|
11
|
-
import { ClassDynamicDispatch } from "./class-dynamic-dispatch.js";
|
|
12
|
+
import { ClassDynamicDispatch, trackClassFieldCreation } from "./class-dynamic-dispatch.js";
|
|
13
|
+
import { DeferredModuleInitializers } from "./deferred-module-initializers.js";
|
|
12
14
|
import { finalizeClassMethodValues } from "./class-method-values.js";
|
|
13
15
|
/* AST + checker → IR.
|
|
14
16
|
*
|
|
@@ -29,14 +31,14 @@ import { bindingSource } from "../binding-source.js";
|
|
|
29
31
|
import { tsgoPath } from "../dts-paths.js";
|
|
30
32
|
import * as ts from "../ts7/adapter.js";
|
|
31
33
|
import { literalValues } from "../literal-values.js";
|
|
32
|
-
import { literalUnionArm } from "../union-discriminants.js";
|
|
34
|
+
import { discriminantOwners, literalUnionArm } from "../union-discriminants.js";
|
|
33
35
|
import { anyOpRequiresDynamicDiag, blockedBindingUseDiag, checkerPanicDiag, componentTypeDiag, isCheckerPanic, genericSignatureTypeDiag, indexSignatureTypeDiag, intersectionTypeDiag, noLoweringDiag, overloadedSignatureTypeDiag, recordShapeMismatchDiag, requiresDynamicApiDiag, requiresDynamicPackageDiag, requiresDynamicTypeDiag, unionMismatchDiag, UNSUPPORTED, unsupportedDiag, unsupportedTypeDiag, } from "../../diagnostics/diagnostic.js";
|
|
34
36
|
import { arrayOf, BOOL, canAdaptDynFuncTo, canDynCheckTo, canConvertToDyn, canCrossIslandBoundary, canExitIslandToType, canMarshalTypedFuncIntoIsland, DYN, DYN_HANDLE_KINDS, F64, isDynTypedRefType, isJsonSafeType, isJsonStringifySafeType, isSupportedMapKey, isSupportedMapValue, isUndefinedArmedUnion, isUnitType, JSVAL, NULL_T, RUNTIME_ERROR_CLASSES, STRING, typeEquals, UNDEFINED_T, VOID } from "../../ir/ir.js";
|
|
35
37
|
import {} from "../npm.js";
|
|
36
38
|
import { provenanceActive } from "../provenance-registry.js";
|
|
37
39
|
import { ambientDtsPath, canonicalBuiltinModule, cjsExportAssignmentOf, cjsExportDiscardReason, fallbackDtsPath, isCjsExportTableLiteral, isCjsJsFile, isJsSourceFile, isNodeEsmFile, isNodeTypesPath, locOf, orderedImportsOf, overridesDtsPath, npmStaticDepSf7, requireSpecOf, resolveImport, workspacePackageOfPath, } from "../program.js";
|
|
38
40
|
import { containsRecord, containsUnion, describeComponentBlocker, describeRecordMemberBlocker, formatIrType, ISLAND_AMBIENT_TYPES, isUnitOnlyTsType, jsOpenObjectType, mapType, ShapeRegistry, typeKey, UnionRegistry, withUndefinedArm as withUndefinedArmCanonical, } from "../type-mapper.js";
|
|
39
|
-
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";
|
|
40
42
|
import { splitFiles, collectProgram, collectNpmImports, collectJsonImports, moduleArtifacts, collectGlobals, declSymbolOf, defaultExportSymbolOf, lowerFileInit, lowerDefaultExport, buildMain, appendDynamicImportModules, appendForkModules } from "./lower-modules.js";
|
|
41
43
|
import { prepareCjsModuleGraph } from "./lower-node-module.js";
|
|
42
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";
|
|
@@ -50,14 +52,14 @@ import { lowerRegexMethodCall, lowerStringMethodCall } from "./containers/string
|
|
|
50
52
|
import { lowerStreamModuleCall } from "./lower-stream.js";
|
|
51
53
|
import { lowerEmitOverrideSpec } from "./lower-event-emitter.js";
|
|
52
54
|
import { builtinImportOf, createRequireBindingDecl, createRequireNamespaceDecl, createRequireProgramModuleOf, createRequireSpecOf, stripTypeCasts, lowerBuiltinModuleCall, lowerNodeModuleCall, lowerTimersPromisesSetInterval, lowerFsToUnixTimestampCall, lowerFsLadderCall, lowerChildArgsArg, lowerSpawnSyncCall, lowerSpawnCall, lowerExecFileCall, lowerExecSyncCall, recordToEnvPairs, lowerJsonMethodCall, fencedBuiltinImportOf, lowerCryptoComposedCall, lowerUrlMethodCall, lowerSearchParamsMethodCall, lowerStatsMethodCall, lowerChildMethodCall, lowerAtomicsCall, lowerBuiltinExtraProperty, registerPromisifiedBuiltinDecl, lowerExecFileAsyncCall, execFileAsyncHelper, lowerStringDecoderMethodCall, strdecHelper, lowerReadlineMethodCall, lowerDcChannelMethodCall, lowerDcChannelProperty, lowerAlsMethodCall, lowerDcTracingChannelMethodCall, lowerDcTracingChannelProperty, lowerJsonProperty, lowerErrorCodeProperty, lowerProcessProperty, isProcessEnv, envValueType, lowerProcessEnvGet, lowerProcessMethodCall, lowerProcessOptionalMethodCall, lowerTimeoutMethodCall, envSnapshotHelper, isConsoleLog, consoleCallMember, lowerNumberStaticCall, lowerNumberStaticProperty, lowerDateCall, lowerTextCodecCall, lowerCryptoModuleCall, lowerFsConstantsProperty, lowerBuiltinConstantsProperty, builtinConstantBindingOf, builtinConstantsDestructureDecl, lowerProcessStreamProperty, lowerStringStaticCall, lowerStringLastIndexOfCall, lowerPromiseStaticCall } from "./lower-builtins.js";
|
|
53
|
-
import { fenceFetchObjectAssignment, fenceFetchObjectBinding, fenceStaticAbortControllerMemberRead, fenceStaticHeadersIteration, fenceStaticHeadersMember, fenceStaticReadableStreamMember, fenceStaticResponseMember, fenceUnsupportedFetchConstructorMember, isIslandExpr, islandFuncValueFence, islandRegexpOf, jsvalIn, requireDynamicApi, islandGlobalFnOf, lowerAbortControllerNew, lowerDynamicHeadersIteratorCall, lowerDynamicHeadersSpread, lowerDynamicImportCall, lowerFetchCall, lowerFetchElementMethodCall, lowerResponseNew, lowerStaticFetchCompanionCall, lowerStaticAbortControllerCall, lowerStaticAbortSignalListenerCall, lowerStaticReadableStreamCancelCall, lowerStaticReadableStreamControllerCall, lowerStaticReadableStreamNew, lowerStaticReadableStreamReaderCall, lowerStaticResponseCall, lowerIslandMethodCall, lowerMathProperty, npmPackageOf, npmMemberFence, npmPackageOfSymbol } from "./lower-island.js";
|
|
55
|
+
import { fenceFetchObjectAssignment, fenceFetchObjectBinding, fenceStaticAbortControllerMemberRead, fenceStaticHeadersIteration, fenceStaticHeadersMember, fenceStaticReadableStreamMember, fenceStaticResponseMember, fenceUnsupportedFetchConstructorMember, isIslandExpr, islandFuncValueFence, islandRegexpOf, jsvalIn, requireDynamicApi, islandGlobalFnOf, lowerAbortControllerNew, lowerDynamicHeadersIteratorCall, lowerDynamicHeadersSpread, lowerDynamicImportCall, lowerFetchCall, lowerFetchElementMethodCall, lowerResponseNew, lowerFetchWebNew, lowerStaticFetchCompanionCall, lowerStaticAbortControllerCall, lowerStaticAbortSignalListenerCall, lowerStaticReadableStreamCancelCall, lowerStaticReadableStreamControllerCall, lowerStaticReadableStreamNew, lowerStaticReadableStreamReaderCall, lowerStaticResponseCall, lowerIslandMethodCall, lowerMathProperty, npmPackageOf, npmMemberFence, npmPackageOfSymbol } from "./lower-island.js";
|
|
54
56
|
import { lowerHttpHeadersElement, lowerNetModuleCall, lowerServerMethodCall, lowerServerProperty, lowerTlsRootCertificates } from "./lower-server.js";
|
|
55
57
|
import { lowerDgramDnsModuleCall, lowerDgramMethodCall } from "./lower-dgram.js";
|
|
56
58
|
import { lowerNodeTestModuleCall, lowerTestDirectCall, lowerTestMethodCall, lowerTestCtxProperty } from "./lower-test.js";
|
|
57
59
|
import { lowerAssertModuleCall, lowerAssertDirectCall } from "./lower-assert.js";
|
|
58
60
|
import { lowerUtilModuleCall } from "./lower-inspect.js";
|
|
59
61
|
import { lowerComptime, comptimeBakeable, rejectComptimeCaptures, comptimeValueToIr } from "./lower-comptime.js";
|
|
60
|
-
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";
|
|
61
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";
|
|
62
64
|
import { finishOptionalChain, isOptionalChainTail, lowerOptionalChain } from "./expressions/optional-chains.js";
|
|
63
65
|
import { foldedStringKeyOf, lowerDynObjectLiteral, lowerObjectLiteral, lowerShorthandValue, rejectThisInObjectMethod } from "./expressions/object-literals.js";
|
|
@@ -514,6 +516,14 @@ export function dynFallbackType(lowerer, node, t) {
|
|
|
514
516
|
if (!isJsSourceFile(node.getSourceFile())) {
|
|
515
517
|
if (t.flags & ts.TypeFlags.Any)
|
|
516
518
|
return DYN;
|
|
519
|
+
const symbol = t.getSymbol();
|
|
520
|
+
const args = symbol && lowerer.isStdlibSymbol(symbol) ? lowerer.checker.getTypeArguments(t) : [];
|
|
521
|
+
if (symbol?.name === "Promise" && args[0] && args[0].flags & ts.TypeFlags.Any)
|
|
522
|
+
return jsFallbackPromiseType(lowerer, t);
|
|
523
|
+
if (symbol && ["Generator", "AsyncGenerator", "IterableIterator"].includes(symbol.name) && args.some((arg) => arg.flags & ts.TypeFlags.Any))
|
|
524
|
+
return jsFallbackGeneratorType(lowerer, t);
|
|
525
|
+
if (lowerer.checker.isArrayType(t) && ((lowerer.checker.getTypeArguments(t)[0]?.flags ?? 0) & ts.TypeFlags.Any) !== 0)
|
|
526
|
+
return DYN;
|
|
517
527
|
// TS single-call-signature function types: per-piece fallback, but
|
|
518
528
|
// ONLY `any` pieces fall to dyn — any other unmappable piece keeps
|
|
519
529
|
// the whole type's own fence.
|
|
@@ -742,18 +752,34 @@ function anyPiecedFuncType(lowerer, node, t) {
|
|
|
742
752
|
return null;
|
|
743
753
|
return { kind: "func", params, ret };
|
|
744
754
|
}
|
|
745
|
-
/** The
|
|
746
|
-
*
|
|
747
|
-
*
|
|
748
|
-
* REFERENCE-SITE approximation of JS's creation-site naming — an aliased
|
|
749
|
-
* 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
|
|
750
758
|
* their own name, anonymous function/arrow expressions their
|
|
751
759
|
* NamedEvaluation home (a variable initializer or property assignment).
|
|
752
760
|
* Null when nothing names the value (the box stays anonymous). */
|
|
753
|
-
export function jsFuncNameOf(node) {
|
|
761
|
+
export function jsFuncNameOf(node, lowerer) {
|
|
754
762
|
let n = node;
|
|
755
763
|
while (ts.isParenthesizedExpression(n))
|
|
756
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
|
+
}
|
|
757
783
|
if (ts.isIdentifier(n))
|
|
758
784
|
return n.text;
|
|
759
785
|
if (ts.isPropertyAccessExpression(n))
|
|
@@ -765,6 +791,9 @@ export function jsFuncNameOf(node) {
|
|
|
765
791
|
if (p && ts.isVariableDeclaration(p) && p.initializer === n && ts.isIdentifier(p.name)) {
|
|
766
792
|
return p.name.text;
|
|
767
793
|
}
|
|
794
|
+
if (p && ts.isBindingElement(p) && p.initializer === n && ts.isIdentifier(p.name)) {
|
|
795
|
+
return p.name.text;
|
|
796
|
+
}
|
|
768
797
|
if (p && ts.isPropertyAssignment(p) && p.initializer === n && ts.isIdentifier(p.name)) {
|
|
769
798
|
return p.name.text;
|
|
770
799
|
}
|
|
@@ -799,6 +828,9 @@ export class Lowerer {
|
|
|
799
828
|
/** Per-symbol result of the never-reassigned file scan
|
|
800
829
|
* (bindingNeverReassigned — object-literal generic-method receivers). */
|
|
801
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();
|
|
802
834
|
/** TRAP bindings: declarations whose initializer provably throws before
|
|
803
835
|
* producing a value (its chain roots at an ambient-undefined name —
|
|
804
836
|
* ambientUndefVarRootOf). Module init unwinds at the declaration, so no
|
|
@@ -1078,7 +1110,7 @@ export class Lowerer {
|
|
|
1078
1110
|
// the initializer cannot fall back to a narrowing adapter.
|
|
1079
1111
|
if (ts.isIdentifier(node) && fallback?.kind === "func") {
|
|
1080
1112
|
const decl = this.checker.valueDeclarationOf(symbol);
|
|
1081
|
-
if (decl && ts.isVariableDeclaration(decl) && decl.initializer) {
|
|
1113
|
+
if (decl && ts.isVariableDeclaration(decl) && !decl.type && !hasJsTypeAnnotation(decl) && decl.initializer) {
|
|
1082
1114
|
let init = decl.initializer;
|
|
1083
1115
|
while (ts.isParenthesizedExpression(init))
|
|
1084
1116
|
init = init.expression;
|
|
@@ -1112,14 +1144,14 @@ export class Lowerer {
|
|
|
1112
1144
|
}
|
|
1113
1145
|
/** Recover the original optional union when a checked single-arm helper
|
|
1114
1146
|
* was installed before a strict property consumer could name its member.
|
|
1115
|
-
* Recovery
|
|
1116
|
-
*
|
|
1147
|
+
* Recovery covers member reads and storage roots marked by the
|
|
1148
|
+
* optional-read analysis, so ordinary assertions keep their generic
|
|
1117
1149
|
* checked-narrow behavior. */
|
|
1118
1150
|
runtimeOptionalSourceValue(node, value) {
|
|
1119
1151
|
let origin = node;
|
|
1120
1152
|
while (ts.isParenthesizedExpression(origin))
|
|
1121
1153
|
origin = origin.expression;
|
|
1122
|
-
let optionalOrigin = ts.isElementAccessExpression(origin);
|
|
1154
|
+
let optionalOrigin = ts.isElementAccessExpression(origin) || ts.isPropertyAccessExpression(origin);
|
|
1123
1155
|
if (ts.isIdentifier(origin)) {
|
|
1124
1156
|
const local = this.resolveLocal(origin);
|
|
1125
1157
|
const root = local ? this.runtimeOptionalRootOf(local) : null;
|
|
@@ -1131,6 +1163,10 @@ export class Lowerer {
|
|
|
1131
1163
|
}
|
|
1132
1164
|
if (!optionalOrigin)
|
|
1133
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;
|
|
1134
1170
|
let source = value;
|
|
1135
1171
|
if (value.kind === "call" &&
|
|
1136
1172
|
this.checkedNarrowHelpers.has(value.callee) &&
|
|
@@ -1331,6 +1367,17 @@ export class Lowerer {
|
|
|
1331
1367
|
/** Union re-tag helpers (%union.retag.N), interned per (from, to)
|
|
1332
1368
|
* unionId pair — see unionRetagHelper. */
|
|
1333
1369
|
retagHelpers = new Map();
|
|
1370
|
+
/** Copy-only routes depend on the two union contracts and discriminator
|
|
1371
|
+
* layouts, without recursive width assumptions or evolving class members. */
|
|
1372
|
+
copyRetagHelpers = new Map();
|
|
1373
|
+
unionLiteralOwners = new Map();
|
|
1374
|
+
strippedUndefinedArms = new Map();
|
|
1375
|
+
addedUndefinedArms = new Map();
|
|
1376
|
+
stdlibSymbols = new Map();
|
|
1377
|
+
/** Method adapter names are owned by class-method-values. Looking them
|
|
1378
|
+
* up must not scan and retain every unrelated lifted function. */
|
|
1379
|
+
classMethodValueHelpers = new Set();
|
|
1380
|
+
classMethodValueSelections = new Map();
|
|
1334
1381
|
/** Callee names of every interned coercion helper whose CALL mints a
|
|
1335
1382
|
* FRESH closure per evaluation (%fn.width.*, %fn.adapt.*,
|
|
1336
1383
|
* %fnval.spawnres.*). Registered at the mint site — NOT recovered by
|
|
@@ -1415,12 +1462,21 @@ export class Lowerer {
|
|
|
1415
1462
|
/** Keyed by program-wide qualified class name (what IR object types carry). */
|
|
1416
1463
|
classes = new Map();
|
|
1417
1464
|
classBySymbol = new Map();
|
|
1465
|
+
/** Named method slots observed before class collection need a callable
|
|
1466
|
+
* ABI and shared prototype descriptors instead of call-site specialization. */
|
|
1467
|
+
prototypeMethodAccesses = new Map();
|
|
1418
1468
|
/** Inferred JS methods participating in an override chain keep a vtable
|
|
1419
1469
|
* ABI instead of call-site specialization. Filled before class collection. */
|
|
1420
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();
|
|
1421
1474
|
/** Largest fixed argument list below a JS method, discovered before any
|
|
1422
1475
|
* base vtable signature is collected. Unused checked slots carry undefined. */
|
|
1423
1476
|
virtualJsMethodArity = new Map();
|
|
1477
|
+
checkedVirtualJsMethods = new Set();
|
|
1478
|
+
checkedVirtualJsAccessors = new Set();
|
|
1479
|
+
checkedVirtualJsValueReturns = new Set();
|
|
1424
1480
|
/** The class whose members are lowering — `super` binds lexically to it
|
|
1425
1481
|
* (arrows inside methods lower within this window, so they see it too). */
|
|
1426
1482
|
currentClass = null;
|
|
@@ -1559,6 +1615,7 @@ export class Lowerer {
|
|
|
1559
1615
|
* a reference to a lowerable body reports its name here — recorded even
|
|
1560
1616
|
* when the enclosing statement later poisons. */
|
|
1561
1617
|
onEdge = null;
|
|
1618
|
+
deferredModuleInitializers = null;
|
|
1562
1619
|
// Stack of function contexts (bottom = the function being declared at
|
|
1563
1620
|
// top level, top = the innermost nested function currently lowering).
|
|
1564
1621
|
fnStack = [];
|
|
@@ -1566,7 +1623,10 @@ export class Lowerer {
|
|
|
1566
1623
|
/** One Error-method helper belongs to this lowering session. Its cached
|
|
1567
1624
|
* dispatch revision needs no weak-key identity or process-global state. */
|
|
1568
1625
|
errorMethodDispatchRevision = null;
|
|
1626
|
+
errorPropertyDispatchRevision = null;
|
|
1569
1627
|
lambdaCounter = 0;
|
|
1628
|
+
preparedClassFactories = new Map();
|
|
1629
|
+
preparingClassFactories = new Set();
|
|
1570
1630
|
/** Statement lists currently mid-lowering, innermost last: the forward-
|
|
1571
1631
|
* capture machinery needs to know which later statements of an OPEN list
|
|
1572
1632
|
* a symbol's declaration sits in, which scope frame list-level declarations
|
|
@@ -1594,6 +1654,15 @@ export class Lowerer {
|
|
|
1594
1654
|
* is assembled directly. The configured reachable set remains null so
|
|
1595
1655
|
* demand-driven instance lowering keeps its existing gates. */
|
|
1596
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
|
+
}
|
|
1597
1666
|
/** Coverage remainder mode: the reachability gate inverts (see wantBody)
|
|
1598
1667
|
* and no module is built. */
|
|
1599
1668
|
remainder;
|
|
@@ -1703,6 +1772,27 @@ export class Lowerer {
|
|
|
1703
1772
|
? { kind: "object", className: this.mixinTypeContext.className }
|
|
1704
1773
|
: null,
|
|
1705
1774
|
localClassInstance: (decl) => {
|
|
1775
|
+
// Computed heritage can close over parameters of its factory.
|
|
1776
|
+
// A speculative checker query outside that factory must not lower
|
|
1777
|
+
// the extends expression in the caller's lexical scope.
|
|
1778
|
+
if (!this.classes.has(this.classNamer(decl)) && !this.collectingExprClasses.has(decl) &&
|
|
1779
|
+
decl.heritageClauses?.some((clause) => clause.token === ts.SyntaxKind.ExtendsKeyword && clause.types.some((base) => {
|
|
1780
|
+
const expression = base.expression;
|
|
1781
|
+
if (ts.isCallExpression(expression))
|
|
1782
|
+
return true;
|
|
1783
|
+
if (ts.isIdentifier(expression) && this.isStdlibGlobal(expression, expression.text))
|
|
1784
|
+
return false;
|
|
1785
|
+
const symbol = this.checker.getSymbolAtLocation(ts.isPropertyAccessExpression(expression) ? expression.name : expression);
|
|
1786
|
+
const resolved = symbol && symbol.flags & ts.SymbolFlags.Alias ? this.checker.getAliasedSymbol(symbol) : symbol;
|
|
1787
|
+
if (ts.isPropertyAccessExpression(expression) && this.isStdlibGlobal(expression.expression, "globalThis") &&
|
|
1788
|
+
this.builtinErrorInfoOf(resolved))
|
|
1789
|
+
return false;
|
|
1790
|
+
if (resolved && this.classBySymbol.has(resolved))
|
|
1791
|
+
return false;
|
|
1792
|
+
const mapped = this.mapTypeOf(this.typeOf(expression));
|
|
1793
|
+
return mapped?.kind !== "classval" || !this.classes.has(mapped.className);
|
|
1794
|
+
})))
|
|
1795
|
+
return null;
|
|
1706
1796
|
for (let parent = decl.parent; parent && !ts.isSourceFile(parent); parent = parent.parent) {
|
|
1707
1797
|
if (!ts.isFunctionDeclaration(parent) && !ts.isFunctionExpression(parent) &&
|
|
1708
1798
|
!ts.isArrowFunction(parent) && !ts.isMethodDeclaration(parent))
|
|
@@ -2266,7 +2356,7 @@ export class Lowerer {
|
|
|
2266
2356
|
return null;
|
|
2267
2357
|
const directSpec = requireSpecOf(decl.initializer);
|
|
2268
2358
|
if (directSpec !== null) {
|
|
2269
|
-
return resolveImport(this.program, decl.getSourceFile(), directSpec) ??
|
|
2359
|
+
return resolveImport(this.program, decl.getSourceFile(), directSpec, "require") ??
|
|
2270
2360
|
npmStaticDepSf7(this.program, decl.getSourceFile(), directSpec, "require");
|
|
2271
2361
|
}
|
|
2272
2362
|
return createRequireProgramModuleOf(this, decl.initializer)?.dep ?? null;
|
|
@@ -2419,8 +2509,11 @@ export class Lowerer {
|
|
|
2419
2509
|
if (!symbol)
|
|
2420
2510
|
return null;
|
|
2421
2511
|
const g = this.globalsBySymbol.get(symbol);
|
|
2422
|
-
if (g)
|
|
2512
|
+
if (g) {
|
|
2513
|
+
if (g.type.kind === "func")
|
|
2514
|
+
g.type = this.runtimeOptionalBindingType(ident, g.type);
|
|
2423
2515
|
return g;
|
|
2516
|
+
}
|
|
2424
2517
|
for (const d of this.checker.declarationsOf(symbol)) {
|
|
2425
2518
|
const byDecl = this.globalsByDeclNode.get(d);
|
|
2426
2519
|
if (byDecl)
|
|
@@ -2586,7 +2679,7 @@ export class Lowerer {
|
|
|
2586
2679
|
// Without the guarded %init call at this position
|
|
2587
2680
|
// those globals stay uninitialized: the dep's module body would never
|
|
2588
2681
|
// run.
|
|
2589
|
-
const dep = resolveImport(this.program, node.getSourceFile(), spec) ??
|
|
2682
|
+
const dep = resolveImport(this.program, node.getSourceFile(), spec, "require") ??
|
|
2590
2683
|
npmStaticDepSf7(this.program, node.getSourceFile(), spec, "require");
|
|
2591
2684
|
if (!dep || dep.fileName.endsWith(".json"))
|
|
2592
2685
|
return null;
|
|
@@ -2665,6 +2758,14 @@ export class Lowerer {
|
|
|
2665
2758
|
return null;
|
|
2666
2759
|
return s.flags & ts.SymbolFlags.Alias ? this.checker.getAliasedSymbol(s) : s;
|
|
2667
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
|
+
};
|
|
2668
2769
|
const functionDeclBySymbol = new Map();
|
|
2669
2770
|
const signatureBySymbol = new Map();
|
|
2670
2771
|
const methodFamilies = new Map();
|
|
@@ -2818,9 +2919,11 @@ export class Lowerer {
|
|
|
2818
2919
|
}
|
|
2819
2920
|
if (ts.isBinaryExpression(e)) {
|
|
2820
2921
|
const op = e.operatorToken.kind;
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
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)
|
|
2824
2927
|
return mayBeOptional(e.left) || mayBeOptional(e.right);
|
|
2825
2928
|
}
|
|
2826
2929
|
if (ts.isPropertyAccessExpression(e) && ts.isIdentifier(e.expression)) {
|
|
@@ -2946,6 +3049,29 @@ export class Lowerer {
|
|
|
2946
3049
|
found = true;
|
|
2947
3050
|
return found;
|
|
2948
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
|
+
}
|
|
2949
3075
|
const promoteHofCallback = (callback, parameterIndices, seen = new Set()) => {
|
|
2950
3076
|
let changed = false;
|
|
2951
3077
|
const checkerTypeContainsTypeParameter = (type) => {
|
|
@@ -3383,6 +3509,23 @@ export class Lowerer {
|
|
|
3383
3509
|
for (const [symbol, decl] of functionDeclBySymbol)
|
|
3384
3510
|
if (scanReturns(symbol, decl))
|
|
3385
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
|
+
}
|
|
3386
3529
|
// Every implementation of a virtual slot must retain the same ABI,
|
|
3387
3530
|
// including when just one body forwards an omitted parameter.
|
|
3388
3531
|
for (const family of optionalMethodFamilies) {
|
|
@@ -3427,6 +3570,14 @@ export class Lowerer {
|
|
|
3427
3570
|
this.runtimeOptionalFunctionReturns.set(decl, arithmetic);
|
|
3428
3571
|
}
|
|
3429
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
|
+
}
|
|
3430
3581
|
for (const sf of sourceFiles) {
|
|
3431
3582
|
ts.walkPreorder(sf, (node) => {
|
|
3432
3583
|
if (!ts.isVariableDeclaration(node) || !ts.isIdentifier(node.name))
|
|
@@ -3434,6 +3585,23 @@ export class Lowerer {
|
|
|
3434
3585
|
const symbol = symbolOf(node.name);
|
|
3435
3586
|
if (!symbol)
|
|
3436
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
|
+
}
|
|
3437
3605
|
const fields = optionalFields.get(symbol);
|
|
3438
3606
|
if (!dynamicObjectEntryRows.has(symbol) && !optionalSymbols.has(symbol) && !fields)
|
|
3439
3607
|
return;
|
|
@@ -3444,7 +3612,7 @@ export class Lowerer {
|
|
|
3444
3612
|
if (!dynamicObjectEntryRows.has(symbol) && optionalSymbols.has(symbol))
|
|
3445
3613
|
promoted = addUndefined(promoted);
|
|
3446
3614
|
if (promoted.kind === "func" && node.initializer && ts.isIdentifier(node.initializer)) {
|
|
3447
|
-
const sourceSig =
|
|
3615
|
+
const sourceSig = signatureOf(node.initializer);
|
|
3448
3616
|
if (sourceSig) {
|
|
3449
3617
|
promoted = {
|
|
3450
3618
|
...promoted,
|
|
@@ -3644,6 +3812,7 @@ export class Lowerer {
|
|
|
3644
3812
|
* and the retained reachability worklist. */
|
|
3645
3813
|
finishModule(functions) {
|
|
3646
3814
|
finalizeClassMethodValues(this, functions);
|
|
3815
|
+
trackClassFieldCreation(this, functions);
|
|
3647
3816
|
// Globals typed by a class that never REGISTERED (a JS class whose
|
|
3648
3817
|
// collection fenced — Symbol-keyed fields, an unsupported base): the
|
|
3649
3818
|
// declaration statement and every use compiled to runtime fences, but
|
|
@@ -3814,6 +3983,7 @@ export class Lowerer {
|
|
|
3814
3983
|
* body; both fire edges through the same hooks and are not units
|
|
3815
3984
|
* themselves. */
|
|
3816
3985
|
emitReachable(extraRoots) {
|
|
3986
|
+
this.deferredModuleInitializers = new DeferredModuleInitializers();
|
|
3817
3987
|
const parts = this.splitFiles();
|
|
3818
3988
|
// Direct lowering callers do not necessarily run program preflight.
|
|
3819
3989
|
// Establish the same managed header/top-level batch here before
|
|
@@ -3832,6 +4002,8 @@ export class Lowerer {
|
|
|
3832
4002
|
// before collectProgram visits them one by one; reached body lowering
|
|
3833
4003
|
// will reuse the same answers later.
|
|
3834
4004
|
this.prefetchClassCollection(parts.flatMap((fp) => fp.classDecls));
|
|
4005
|
+
const collectionEdges = new Set();
|
|
4006
|
+
this.onEdge = (name) => { collectionEdges.add(name); };
|
|
3835
4007
|
this.collectProgram(parts);
|
|
3836
4008
|
this.analyzeRuntimeOptionalArrayReads(parts);
|
|
3837
4009
|
// Decorated classes analyze post-collection here too: the %init seeds
|
|
@@ -3894,13 +4066,13 @@ export class Lowerer {
|
|
|
3894
4066
|
units.set(`%${cName}.constructor`, {
|
|
3895
4067
|
order: unitOrder++,
|
|
3896
4068
|
roots: classCtorRoots(info),
|
|
3897
|
-
lower: () => this.lowerClassCtor(info),
|
|
4069
|
+
lower: () => info.localClass && !info.localClass.ready ? null : this.lowerClassCtor(info),
|
|
3898
4070
|
});
|
|
3899
4071
|
for (const { mName, member } of this.classMethodMembers(info)) {
|
|
3900
4072
|
units.set(`%${cName}.${mName}`, {
|
|
3901
4073
|
order: unitOrder++,
|
|
3902
4074
|
roots: functionRoots(member),
|
|
3903
|
-
lower: () => this.lowerClassMethodMember(info, member),
|
|
4075
|
+
lower: () => info.localClass && !info.localClass.ready ? null : this.lowerClassMethodMember(info, member),
|
|
3904
4076
|
});
|
|
3905
4077
|
}
|
|
3906
4078
|
for (const prop of info.throwingSetters) {
|
|
@@ -3978,6 +4150,7 @@ export class Lowerer {
|
|
|
3978
4150
|
return owner;
|
|
3979
4151
|
};
|
|
3980
4152
|
const reachable = new Set();
|
|
4153
|
+
this.constructedClasses = new Set();
|
|
3981
4154
|
const queue = [];
|
|
3982
4155
|
const loweredUnits = new Map();
|
|
3983
4156
|
const initFunctions = [];
|
|
@@ -3988,6 +4161,12 @@ export class Lowerer {
|
|
|
3988
4161
|
reachable.add(name);
|
|
3989
4162
|
if (units.has(name))
|
|
3990
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
|
+
}
|
|
3991
4170
|
};
|
|
3992
4171
|
// Class EXPRESSIONS collect while init bodies lower (below): their
|
|
3993
4172
|
// member units register the moment collection finishes — before any
|
|
@@ -3996,11 +4175,13 @@ export class Lowerer {
|
|
|
3996
4175
|
const cName = info.def.name;
|
|
3997
4176
|
const register = (name, roots, lower) => {
|
|
3998
4177
|
units.set(name, { order: unitOrder++, roots, lower });
|
|
4178
|
+
if (reachable.has(name))
|
|
4179
|
+
queue.push(name);
|
|
3999
4180
|
metadataPriority.set(name, [3, expressionMetadataOrder++]);
|
|
4000
4181
|
};
|
|
4001
|
-
register(`%${cName}.constructor`, classCtorRoots(info), () => this.lowerClassCtor(info));
|
|
4182
|
+
register(`%${cName}.constructor`, classCtorRoots(info), () => info.localClass && !info.localClass.ready ? null : this.lowerClassCtor(info));
|
|
4002
4183
|
for (const { mName, member } of this.classMethodMembers(info)) {
|
|
4003
|
-
register(`%${cName}.${mName}`, functionRoots(member), () => this.lowerClassMethodMember(info, member));
|
|
4184
|
+
register(`%${cName}.${mName}`, functionRoots(member), () => info.localClass && !info.localClass.ready ? null : this.lowerClassMethodMember(info, member));
|
|
4004
4185
|
}
|
|
4005
4186
|
if (info.staticMethods)
|
|
4006
4187
|
for (const [name, entry] of info.staticMethods) {
|
|
@@ -4010,6 +4191,8 @@ export class Lowerer {
|
|
|
4010
4191
|
register(`%${cName}.set:${prop}`, [], () => this.throwingSetterFn(info, prop));
|
|
4011
4192
|
}
|
|
4012
4193
|
};
|
|
4194
|
+
for (const name of collectionEdges)
|
|
4195
|
+
this.onEdge(name);
|
|
4013
4196
|
// Generic instances queued by the bodies above lower here (an instance
|
|
4014
4197
|
// body fires edges of its own and can queue further instances of
|
|
4015
4198
|
// either kind — function instances and class instantiations drain to
|
|
@@ -4134,10 +4317,13 @@ export class Lowerer {
|
|
|
4134
4317
|
const classDispatch = new ClassDynamicDispatch(extraRoots !== undefined);
|
|
4135
4318
|
for (;;) {
|
|
4136
4319
|
drainInstances();
|
|
4320
|
+
const initializerChanged = this.deferredModuleInitializers.process(this, [
|
|
4321
|
+
...loweredUnits.values(), ...initFunctions, ...instanceFunctions, ...this.liftedFns, ...this.implicitFns,
|
|
4322
|
+
]);
|
|
4137
4323
|
const dispatchChanged = classDispatch.process(this, [
|
|
4138
4324
|
...loweredUnits.values(), ...initFunctions, ...instanceFunctions, ...this.liftedFns, ...this.implicitFns,
|
|
4139
4325
|
]);
|
|
4140
|
-
if (queue.length === 0 && !dispatchChanged)
|
|
4326
|
+
if (queue.length === 0 && !dispatchChanged && !initializerChanged)
|
|
4141
4327
|
break;
|
|
4142
4328
|
drainUnits();
|
|
4143
4329
|
this.restoreGenericInstanceOrder(instLowered);
|
|
@@ -4160,6 +4346,20 @@ export class Lowerer {
|
|
|
4160
4346
|
...this.liftedFns,
|
|
4161
4347
|
...this.implicitFns,
|
|
4162
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
|
+
} });
|
|
4163
4363
|
this.reachableForArtifacts = reachable;
|
|
4164
4364
|
return { reachable, result: this.finishModule(functions) };
|
|
4165
4365
|
}
|
|
@@ -4177,12 +4377,17 @@ export class Lowerer {
|
|
|
4177
4377
|
noteVirtualEdge(info, method) {
|
|
4178
4378
|
if (!this.onEdge)
|
|
4179
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
|
+
}
|
|
4180
4385
|
const above = this.findMethodOn(info, method);
|
|
4181
4386
|
if (above)
|
|
4182
4387
|
this.noteEdge(`%${above.declarer.def.name}.${method}`);
|
|
4183
4388
|
const below = (c) => {
|
|
4184
4389
|
for (const s of c.subclasses) {
|
|
4185
|
-
if (s.methods.has(method))
|
|
4390
|
+
if (this.classCanBeConstructed(s) && s.methods.has(method))
|
|
4186
4391
|
this.noteEdge(`%${s.def.name}.${method}`);
|
|
4187
4392
|
below(s);
|
|
4188
4393
|
}
|
|
@@ -4477,7 +4682,7 @@ export class Lowerer {
|
|
|
4477
4682
|
Segmenter: intlHint,
|
|
4478
4683
|
DisplayNames: intlHint,
|
|
4479
4684
|
TextEncoder: "TextEncoder instances support encode(string) and encode(); other codec operations require a dedicated lowering",
|
|
4480
|
-
TextDecoder: "TextDecoder instances support recognized
|
|
4685
|
+
TextDecoder: "TextDecoder instances support recognized labels, fatal/ignoreBOM option literals, and streaming UTF-8/UTF-16/single-byte decode; runtime option objects remain unsupported",
|
|
4481
4686
|
};
|
|
4482
4687
|
this.pushDiag(noLoweringDiag(this.checker.typeToString(type), locOf(node), typeHints[stdlibOwnSym?.name ?? ""]));
|
|
4483
4688
|
throw new PoisonError();
|
|
@@ -4533,6 +4738,22 @@ export class Lowerer {
|
|
|
4533
4738
|
return fenceStaticReadableStreamMember(this, access, use);
|
|
4534
4739
|
}
|
|
4535
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
|
+
}
|
|
4751
|
+
// A checked JS method receives its actual call-site receiver. Its
|
|
4752
|
+
// declaration's inferred class type must not turn property reads back
|
|
4753
|
+
// into native field loads when the method is borrowed by another object.
|
|
4754
|
+
if (node.kind === ts.SyntaxKind.ThisKeyword && isJsSourceFile(node.getSourceFile()) &&
|
|
4755
|
+
this.fnStack.length > 0 && this.resolveThis()?.type.kind === "dyn")
|
|
4756
|
+
return this.checker.getUnknownType();
|
|
4536
4757
|
// Inside an optional-chain body the guarded receiver is typed by its
|
|
4537
4758
|
// NON-NULLISH type (the chain's tag test proved it), so every
|
|
4538
4759
|
// receiver-kind check downstream sees the narrowed arm.
|
|
@@ -4577,8 +4798,15 @@ export class Lowerer {
|
|
|
4577
4798
|
// A checked value can contain any runtime kind. A checker-proven
|
|
4578
4799
|
// branch narrow therefore cannot contradict this specialization;
|
|
4579
4800
|
// reads still validate the payload through maybeNarrow.
|
|
4580
|
-
if (boundIr.kind === "dyn")
|
|
4581
|
-
|
|
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
|
+
}
|
|
4582
4810
|
// A union binding narrowed to one of its arms (typeof/equality
|
|
4583
4811
|
// guards over string|number bindings) — the narrow is truth.
|
|
4584
4812
|
if (boundIr.kind === "union") {
|
|
@@ -4887,8 +5115,20 @@ export class Lowerer {
|
|
|
4887
5115
|
* this is THE tag for that (union, arm) pair program-wide — every wrap,
|
|
4888
5116
|
* narrow, and tag test agrees by construction. */
|
|
4889
5117
|
armTag(unionId, arm) {
|
|
5118
|
+
return this.unions.armTag(unionId, arm);
|
|
5119
|
+
}
|
|
5120
|
+
/** Literal ownership depends only on the union contract and record layouts.
|
|
5121
|
+
* Recheck it when recursive placeholders close, not for every literal. */
|
|
5122
|
+
literalUnionArm(unionId, values) {
|
|
4890
5123
|
const def = this.unions.get(unionId);
|
|
4891
|
-
|
|
5124
|
+
if (!def || values.length === 0)
|
|
5125
|
+
return null;
|
|
5126
|
+
let cached = this.unionLiteralOwners.get(unionId);
|
|
5127
|
+
if (!cached || cached.shapes !== this.shapes.revision || cached.unions !== this.unions.revision) {
|
|
5128
|
+
cached = { owners: discriminantOwners(def, (id) => this.shapes.get(id)), shapes: this.shapes.revision, unions: this.unions.revision };
|
|
5129
|
+
this.unionLiteralOwners.set(unionId, cached);
|
|
5130
|
+
}
|
|
5131
|
+
return literalUnionArm(def, values, (id) => this.shapes.get(id), cached.owners);
|
|
4892
5132
|
}
|
|
4893
5133
|
/** Implicit union construction. Wherever a value flows into a typed slot
|
|
4894
5134
|
* (initializer, assignment, call argument, return, field write, record
|
|
@@ -4991,7 +5231,14 @@ export class Lowerer {
|
|
|
4991
5231
|
// undefined/null literals store the dyn unit values. Types outside the
|
|
4992
5232
|
// dyn's domain (bytes, classes, Maps, ...) fall through to
|
|
4993
5233
|
// requireExactShape's SC1101 fence.
|
|
4994
|
-
//
|
|
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
|
+
}
|
|
4995
5242
|
// Promise<never> return holding a `return Promise.reject(value)` the
|
|
4996
5243
|
// dyn arm typed promise<dyn>): awaiting through the slot ignores the
|
|
4997
5244
|
// fulfillment payload (scr_await_void) and rejections flow untyped,
|
|
@@ -5009,23 +5256,22 @@ export class Lowerer {
|
|
|
5009
5256
|
return { kind: "seqExpr", stmts: [{ kind: "exprStmt", expr, loc: expr.loc }],
|
|
5010
5257
|
result: dynUndefinedExpr(expr.loc), type: DYN, loc: expr.loc };
|
|
5011
5258
|
}
|
|
5012
|
-
//
|
|
5013
|
-
//
|
|
5014
|
-
//
|
|
5015
|
-
// runtime CACHES the identity edge, so `instanceof TypeError` on
|
|
5016
|
-
// the dyn side still answers exactly (dyn.errInstanceof). Only the
|
|
5017
|
-
// root spelling was convertible before; the harness passes typed
|
|
5018
|
-
// errors into untyped helpers constantly.
|
|
5259
|
+
// Preserve the concrete class so checked property/method dispatch
|
|
5260
|
+
// discovers user Error subclasses. Runtime boxing selects the live
|
|
5261
|
+
// view by vtable even when an error first crosses through its base.
|
|
5019
5262
|
if (expr.type.kind === "object" && this.errorHierarchyClassOf(expr.type.className)) {
|
|
5020
5263
|
return {
|
|
5021
5264
|
kind: "dynFrom",
|
|
5022
|
-
value:
|
|
5265
|
+
value: expr,
|
|
5023
5266
|
type: DYN,
|
|
5024
5267
|
loc: expr.loc,
|
|
5025
5268
|
};
|
|
5026
5269
|
}
|
|
5027
5270
|
if (expr.kind === "unitLit" || this.dynConvertible(expr.type)) {
|
|
5028
|
-
|
|
5271
|
+
const shape = expr.type.kind === "record" ? this.shapes.get(expr.type.shapeId) : undefined;
|
|
5272
|
+
const liveRef = expr.type.kind === "array" || !!shape && (shape.fields.length > 0 || shape.indexValue !== undefined);
|
|
5273
|
+
return { kind: "dynFrom", value: expr, type: DYN, loc: expr.loc,
|
|
5274
|
+
...(liveRef ? { liveRef: true } : {}) };
|
|
5029
5275
|
}
|
|
5030
5276
|
return expr;
|
|
5031
5277
|
}
|
|
@@ -5447,6 +5693,7 @@ export class Lowerer {
|
|
|
5447
5693
|
return;
|
|
5448
5694
|
const sameFamily = (src.kind === "record" && arm.kind === "record") ||
|
|
5449
5695
|
(src.kind === "array" && arm.kind === "array") ||
|
|
5696
|
+
(src.kind === "func" && arm.kind === "func") ||
|
|
5450
5697
|
(src.kind === "object" && arm.kind === "object") ||
|
|
5451
5698
|
// Tuples already lift into ordinary array slots. Consider that
|
|
5452
5699
|
// same conversion when the array is an arm of a union too.
|
|
@@ -5456,9 +5703,30 @@ export class Lowerer {
|
|
|
5456
5703
|
if (sameFamily && this.widthLiftPlan(src, arm) !== null)
|
|
5457
5704
|
candidates.push({ tag: i, arm });
|
|
5458
5705
|
});
|
|
5459
|
-
|
|
5706
|
+
let selected = candidates;
|
|
5707
|
+
if (selected.length > 1 && src.kind === "record") {
|
|
5708
|
+
const source = this.shapes.get(src.shapeId);
|
|
5709
|
+
// An inferred JS union may widen its tag while retaining variants
|
|
5710
|
+
// with and without a value. Prefer the unique layout whose omitted
|
|
5711
|
+
// fields are explicitly undefined, rather than filling an optional
|
|
5712
|
+
// unknown slot and making both variants look equally compatible.
|
|
5713
|
+
const absentOnly = selected.filter(({ arm }) => {
|
|
5714
|
+
if (!source || arm.kind !== "record")
|
|
5715
|
+
return false;
|
|
5716
|
+
const target = this.shapes.get(arm.shapeId);
|
|
5717
|
+
return target !== undefined && target.fields.every((field) => {
|
|
5718
|
+
if (source.fields.some((present) => present.name === field.name))
|
|
5719
|
+
return true;
|
|
5720
|
+
return isUnitType(field.type) || field.type.kind === "union" &&
|
|
5721
|
+
this.unions.get(field.type.unionId)?.arms.every(isUnitType) === true;
|
|
5722
|
+
});
|
|
5723
|
+
});
|
|
5724
|
+
if (absentOnly.length === 1)
|
|
5725
|
+
selected = absentOnly;
|
|
5726
|
+
}
|
|
5727
|
+
if (selected.length !== 1)
|
|
5460
5728
|
return null;
|
|
5461
|
-
return { how: "liftWrap", tag:
|
|
5729
|
+
return { how: "liftWrap", tag: selected[0].tag, arm: selected[0].arm };
|
|
5462
5730
|
}
|
|
5463
5731
|
// A UNION source into a slot that is ONE of its arms (a width copy
|
|
5464
5732
|
// whose target field narrowed — the option-table choices shape:
|
|
@@ -7100,6 +7368,10 @@ export class Lowerer {
|
|
|
7100
7368
|
const to = this.unions.get(toId);
|
|
7101
7369
|
if (!from || !to)
|
|
7102
7370
|
return null;
|
|
7371
|
+
const request = `${fromId}:${toId}:${trappable === undefined ? "" : [...trappable].sort((a, b) => a - b).join(".")}`;
|
|
7372
|
+
const cached = this.copyRetagHelpers.get(request);
|
|
7373
|
+
if (cached && cached.shapes === this.shapes.revision && cached.unions === this.unions.revision)
|
|
7374
|
+
return cached.name;
|
|
7103
7375
|
const plan = planUnionRetag(from, to, (id) => this.shapes.get(id), (src, dst) => this.widthLiftPlan(src, dst), trappable);
|
|
7104
7376
|
if (plan === null)
|
|
7105
7377
|
return null;
|
|
@@ -7111,11 +7383,17 @@ export class Lowerer {
|
|
|
7111
7383
|
stranded.push(tag); });
|
|
7112
7384
|
const key = `${fromId}:${toId}:${stranded.join(".")}`;
|
|
7113
7385
|
const existing = this.retagHelpers.get(key);
|
|
7114
|
-
|
|
7115
|
-
|
|
7116
|
-
|
|
7117
|
-
|
|
7118
|
-
|
|
7386
|
+
const name = existing ?? `%union.retag.${this.retagHelpers.size}`;
|
|
7387
|
+
if (!existing) {
|
|
7388
|
+
this.retagHelpers.set(key, name);
|
|
7389
|
+
this.liftedFns.push(buildUnionRetag(name, from, to, plan, loc, (lift, value, dst) => this.applyWidthLift(lift, value, dst, loc), (type) => this.fmt(type)));
|
|
7390
|
+
}
|
|
7391
|
+
// Width routes still revalidate on every request. Only a complete plan
|
|
7392
|
+
// of exact payload copies and site-proven traps can bypass planning.
|
|
7393
|
+
if (plan.every((arm) => arm.kind === "trap" || (arm.kind === "direct"
|
|
7394
|
+
? arm.route.lift.how === "copy" : arm.routes.every((route) => route.lift.how === "copy")))) {
|
|
7395
|
+
this.copyRetagHelpers.set(request, { name, shapes: this.shapes.revision, unions: this.unions.revision });
|
|
7396
|
+
}
|
|
7119
7397
|
return name;
|
|
7120
7398
|
}
|
|
7121
7399
|
/** Interned `%union.narrow.<n>(u)` — the CHECKED single-arm extraction
|
|
@@ -7588,7 +7866,7 @@ export class Lowerer {
|
|
|
7588
7866
|
const property = this.checker.getPropertyOfType(this.typeOf(literal), def.discriminant.field);
|
|
7589
7867
|
if (property && !(property.flags & (ts.SymbolFlags.Optional | ts.SymbolFlags.GetAccessor | ts.SymbolFlags.SetAccessor))) {
|
|
7590
7868
|
const values = literalValues(this.checker.getTypeOfSymbol(property));
|
|
7591
|
-
const arm = values && literalUnionArm(def, values
|
|
7869
|
+
const arm = values && this.literalUnionArm(def.id, values);
|
|
7592
7870
|
if (arm)
|
|
7593
7871
|
expr = this.coerceInto(node, expr, arm);
|
|
7594
7872
|
}
|
|
@@ -7611,7 +7889,9 @@ export class Lowerer {
|
|
|
7611
7889
|
}
|
|
7612
7890
|
}
|
|
7613
7891
|
}
|
|
7614
|
-
let e = this.
|
|
7892
|
+
let e = this.dynamic && expr.type.kind === "dyn" && expected.kind === "array" && expected.elem.kind === "jsval"
|
|
7893
|
+
? { kind: "jsExit", value: this.jsvalIn(expr, node), type: expected, loc: expr.loc }
|
|
7894
|
+
: this.coerceToExpected(expr, expected);
|
|
7615
7895
|
// Existing JavaScript arrays retain mutations and identity across checked
|
|
7616
7896
|
// slots. Fresh literals have no prior identity and use checked storage
|
|
7617
7897
|
// directly, so later writes can change their inferred element type.
|
|
@@ -7644,7 +7924,7 @@ export class Lowerer {
|
|
|
7644
7924
|
// NamedEvaluation through a variable initializer) — inspect prints
|
|
7645
7925
|
// [Function: name] and call errors spell it, like Node.
|
|
7646
7926
|
if (e.kind === "dynFrom" && e.value.type.kind === "func" && e.fnName === undefined) {
|
|
7647
|
-
const name = jsFuncNameOf(node);
|
|
7927
|
+
const name = jsFuncNameOf(node, this);
|
|
7648
7928
|
if (name !== null)
|
|
7649
7929
|
e = { ...e, fnName: name };
|
|
7650
7930
|
}
|
|
@@ -7857,7 +8137,7 @@ export class Lowerer {
|
|
|
7857
8137
|
const property = this.checker.getPropertyOfType(this.typeOf(node), def.discriminant.field);
|
|
7858
8138
|
if (property && !(property.flags & (ts.SymbolFlags.Optional | ts.SymbolFlags.GetAccessor | ts.SymbolFlags.SetAccessor))) {
|
|
7859
8139
|
const values = literalValues(this.checker.getTypeOfSymbol(property));
|
|
7860
|
-
const arm = values && literalUnionArm(def, values
|
|
8140
|
+
const arm = values && this.literalUnionArm(def.id, values);
|
|
7861
8141
|
if (arm)
|
|
7862
8142
|
return this.coerceInto(node, this.lowerObjectLiteral(node, arm), expected);
|
|
7863
8143
|
}
|
|
@@ -7865,7 +8145,7 @@ export class Lowerer {
|
|
|
7865
8145
|
}
|
|
7866
8146
|
// An OBJECT LITERAL against a checked-dynamic slot in a JS file (the
|
|
7867
8147
|
// getSupportInfo options argument — a dyn-ABI param), or against the
|
|
7868
|
-
// standard
|
|
8148
|
+
// standard native option-bag types in TypeScript: the value's world IS the
|
|
7869
8149
|
// checked-dynamic tree — build the dyn literal directly.
|
|
7870
8150
|
if (expected?.kind === "dyn") {
|
|
7871
8151
|
let x = node;
|
|
@@ -7885,7 +8165,8 @@ export class Lowerer {
|
|
|
7885
8165
|
return sym?.name === name && this.isStdlibSymbol(sym);
|
|
7886
8166
|
});
|
|
7887
8167
|
if (ts.isObjectLiteralExpression(x)) {
|
|
7888
|
-
if (isJsSourceFile(x.getSourceFile()) || builtinOption("RequestInit") || builtinOption("ErrorOptions"))
|
|
8168
|
+
if (isJsSourceFile(x.getSourceFile()) || builtinOption("RequestInit") || builtinOption("ErrorOptions") || builtinOption("SpawnOptions") ||
|
|
8169
|
+
!this.mapTypeOf(this.typeOf(x))) {
|
|
7889
8170
|
return lowerDynObjectLiteral(this, x);
|
|
7890
8171
|
}
|
|
7891
8172
|
}
|
|
@@ -7933,7 +8214,7 @@ export class Lowerer {
|
|
|
7933
8214
|
}
|
|
7934
8215
|
}
|
|
7935
8216
|
let e = this.lowerExpr(node);
|
|
7936
|
-
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())) {
|
|
7937
8218
|
// A destination that accepts undefined must retain an unchecked
|
|
7938
8219
|
// read's storage value even when the checker still calls it present.
|
|
7939
8220
|
e = this.runtimeOptionalSourceValue(node, e) ?? e;
|
|
@@ -7994,7 +8275,19 @@ export class Lowerer {
|
|
|
7994
8275
|
* declared result type of an index-signature read under
|
|
7995
8276
|
* noUncheckedIndexedAccess. Null when the type cannot take the arm. */
|
|
7996
8277
|
withUndefinedArmOf(t) {
|
|
7997
|
-
|
|
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;
|
|
7998
8291
|
}
|
|
7999
8292
|
/** True when a static type converts to a dyn value (the dynFrom
|
|
8000
8293
|
* walker's domain): JSON-safe, bytes<u8> (Uint8Array/Buffer — the checked-dynamic tree's
|
|
@@ -8096,14 +8389,17 @@ export class Lowerer {
|
|
|
8096
8389
|
stripUndefinedArm(t) {
|
|
8097
8390
|
if (t.kind !== "union")
|
|
8098
8391
|
return t;
|
|
8392
|
+
const cached = this.strippedUndefinedArms.get(t.unionId);
|
|
8393
|
+
if (cached && cached.unions === this.unions.revision)
|
|
8394
|
+
return cached.type;
|
|
8099
8395
|
const def = this.unions.get(t.unionId);
|
|
8100
|
-
if (!def ||
|
|
8396
|
+
if (!def || this.armTag(t.unionId, UNDEFINED_T) < 0)
|
|
8101
8397
|
return t;
|
|
8102
8398
|
const rest = def.arms.filter((a) => a.kind !== "undefinedT");
|
|
8103
|
-
if (rest.length === 1)
|
|
8104
|
-
return rest[0];
|
|
8105
8399
|
// Removing an arm keeps canonical (typeKey-sorted) order.
|
|
8106
|
-
|
|
8400
|
+
const type = rest.length === 1 ? rest[0] : { kind: "union", unionId: this.unions.transform(def, rest) };
|
|
8401
|
+
this.strippedUndefinedArms.set(t.unionId, { type, unions: this.unions.revision });
|
|
8402
|
+
return type;
|
|
8107
8403
|
}
|
|
8108
8404
|
/** The interned `T | undefined` union over a non-union arm type — the ABI
|
|
8109
8405
|
* type of a defaulted parameter, and the result type of lookups that may
|
|
@@ -8164,13 +8460,14 @@ export class Lowerer {
|
|
|
8164
8460
|
* symbol reports eagerly (nothing could ever reference it). */
|
|
8165
8461
|
collectDeferring(symbolOf, collect) {
|
|
8166
8462
|
const sink = [];
|
|
8463
|
+
const previousSink = this.diagSink;
|
|
8167
8464
|
this.diagSink = sink;
|
|
8168
8465
|
try {
|
|
8169
8466
|
collect();
|
|
8170
8467
|
return null;
|
|
8171
8468
|
}
|
|
8172
8469
|
catch (e) {
|
|
8173
|
-
this.diagSink =
|
|
8470
|
+
this.diagSink = previousSink;
|
|
8174
8471
|
const symbol = (() => {
|
|
8175
8472
|
// symbolOf queries the checker too — a second panic must not
|
|
8176
8473
|
// escape the fence that is handling the first.
|
|
@@ -8203,7 +8500,7 @@ export class Lowerer {
|
|
|
8203
8500
|
return symbol;
|
|
8204
8501
|
}
|
|
8205
8502
|
finally {
|
|
8206
|
-
this.diagSink =
|
|
8503
|
+
this.diagSink = previousSink;
|
|
8207
8504
|
}
|
|
8208
8505
|
}
|
|
8209
8506
|
/** Pushes a symbol's deferred collection diagnostics: lowering resolved
|
|
@@ -8384,6 +8681,8 @@ export class Lowerer {
|
|
|
8384
8681
|
* BEFORE that statement (JS's order for the supported whole-initializer
|
|
8385
8682
|
* positions). */
|
|
8386
8683
|
pendingClassExprInits = [];
|
|
8684
|
+
computedClassBases = new Map();
|
|
8685
|
+
computedCallableBases = new Map();
|
|
8387
8686
|
/** Discovery hook: registers a just-collected expression class's member
|
|
8388
8687
|
* bodies as worklist units (the units map is otherwise built before
|
|
8389
8688
|
* lowering starts). Null in the emit pass. */
|
|
@@ -8472,11 +8771,7 @@ export class Lowerer {
|
|
|
8472
8771
|
// Computed method names resolve exactly like collection did
|
|
8473
8772
|
// (classMemberNameOf — folded keys and the sym:iterator slot);
|
|
8474
8773
|
// unresolvable ones never collected, so they skip here too.
|
|
8475
|
-
const baseName =
|
|
8476
|
-
? classMemberNameOf(this, fnLike.name)
|
|
8477
|
-
: ts.isIdentifier(fnLike.name) || ts.isPrivateIdentifier(fnLike.name)
|
|
8478
|
-
? fnLike.name.text
|
|
8479
|
-
: null;
|
|
8774
|
+
const baseName = classMemberNameOf(this, fnLike.name);
|
|
8480
8775
|
if (baseName === null)
|
|
8481
8776
|
continue;
|
|
8482
8777
|
const mName = ts.isMethodDeclaration(fnLike) ? baseName : `${ts.isGetAccessor(fnLike) ? "get" : "set"}:${baseName}`;
|
|
@@ -8847,9 +9142,7 @@ export class Lowerer {
|
|
|
8847
9142
|
});
|
|
8848
9143
|
if (resolved.error !== null) {
|
|
8849
9144
|
const location = blame ?? (symbol === undefined ? undefined : this.checker.declarationsOf(symbol)[0]) ?? this.entry;
|
|
8850
|
-
const message = resolved.
|
|
8851
|
-
? "closures capturing catch bindings (narrow into a typed local first)"
|
|
8852
|
-
: `the binding '${resolved.origin.name}' captured through a plain nested function (the declaration has no static storage a capture can thread — bind the value through a typed const, or read it in the declaring scope)`;
|
|
9145
|
+
const message = `the binding '${resolved.origin.name}' captured through a plain nested function (the declaration has no static storage a capture can thread — bind the value through a typed const, or read it in the declaring scope)`;
|
|
8853
9146
|
this.unsupported("SC1090", location, message);
|
|
8854
9147
|
}
|
|
8855
9148
|
if (resolved.local !== null)
|
|
@@ -9238,7 +9531,16 @@ export class Lowerer {
|
|
|
9238
9531
|
return isStdlibMember(this, access);
|
|
9239
9532
|
}
|
|
9240
9533
|
isStdlibSymbol(symbol) {
|
|
9241
|
-
|
|
9534
|
+
if (!symbol)
|
|
9535
|
+
return false;
|
|
9536
|
+
const cached = this.stdlibSymbols.get(symbol);
|
|
9537
|
+
if (cached !== undefined)
|
|
9538
|
+
return cached;
|
|
9539
|
+
// A compilation's checker declarations and library provenance are fixed.
|
|
9540
|
+
// Global alias and narrowing state remain outside this symbol-only cache.
|
|
9541
|
+
const result = isStdlibSymbol(this, symbol);
|
|
9542
|
+
this.stdlibSymbols.set(symbol, result);
|
|
9543
|
+
return result;
|
|
9242
9544
|
}
|
|
9243
9545
|
isStdlibGlobal(expr, name) {
|
|
9244
9546
|
return isStdlibGlobal(this, expr, name);
|
|
@@ -9580,7 +9882,7 @@ export class Lowerer {
|
|
|
9580
9882
|
const arg = this.lowerExpr(expr.arguments[0]);
|
|
9581
9883
|
return { kind: "jsOp", op: "construct", args: [ctor, arg], type: JSVAL, loc };
|
|
9582
9884
|
}
|
|
9583
|
-
const builtin = lowerAbortControllerNew(this, expr) ?? lowerResponseNew(this, expr) ?? lowerStaticReadableStreamNew(this, expr);
|
|
9885
|
+
const builtin = lowerAbortControllerNew(this, expr) ?? lowerFetchWebNew(this, expr) ?? lowerResponseNew(this, expr) ?? lowerStaticReadableStreamNew(this, expr);
|
|
9584
9886
|
return builtin ?? this.withRuntimeOptionalClassValue(expr.expression, () => lowerNew(this, expr));
|
|
9585
9887
|
}
|
|
9586
9888
|
lowerFieldRead(expr) {
|
|
@@ -9640,6 +9942,10 @@ export class Lowerer {
|
|
|
9640
9942
|
* member access that IS a module in its own right (`fs.promises` — the
|
|
9641
9943
|
* same object as node:fs/promises, Node's rule). Null otherwise. */
|
|
9642
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;
|
|
9643
9949
|
const stored = ts.isIdentifier(expr)
|
|
9644
9950
|
? (this.peekLocal(expr)?.type ?? this.globalOf(expr)?.type)
|
|
9645
9951
|
: undefined;
|
|
@@ -9862,10 +10168,10 @@ export class Lowerer {
|
|
|
9862
10168
|
if (!expr.questionDotToken && ts.isPropertyAccessExpression(expr.expression)) {
|
|
9863
10169
|
const inner = this.builtinMemberOf(expr.expression);
|
|
9864
10170
|
if (inner && inner.module === "fs" && inner.member === "constants") {
|
|
9865
|
-
const MODES = { F_OK: 0, X_OK: 1, W_OK: 2, R_OK: 4 };
|
|
10171
|
+
const MODES = { F_OK: 0, X_OK: 1, W_OK: 2, R_OK: 4, COPYFILE_EXCL: 1, COPYFILE_FICLONE: 2, COPYFILE_FICLONE_FORCE: 4 };
|
|
9866
10172
|
const value = own(MODES, expr.name.text);
|
|
9867
10173
|
if (value === undefined) {
|
|
9868
|
-
this.noLowering(`fs.constants.${expr.name.text}`, expr, "F_OK, R_OK, W_OK, and
|
|
10174
|
+
this.noLowering(`fs.constants.${expr.name.text}`, expr, "F_OK, R_OK, W_OK, X_OK, and COPYFILE_* are the lowered constants");
|
|
9869
10175
|
}
|
|
9870
10176
|
return { kind: "numLit", value, type: F64, loc };
|
|
9871
10177
|
}
|
|
@@ -9873,6 +10179,10 @@ export class Lowerer {
|
|
|
9873
10179
|
const bi = this.builtinMemberOf(expr);
|
|
9874
10180
|
if (!bi)
|
|
9875
10181
|
return null;
|
|
10182
|
+
if ((bi.module === "path" || bi.module === "path/posix" || bi.module === "path/win32") &&
|
|
10183
|
+
(bi.member === "posix" || bi.member === "win32")) {
|
|
10184
|
+
return pathModuleValue(this, `path/${bi.member}`, loc);
|
|
10185
|
+
}
|
|
9876
10186
|
// events.defaultMaxListeners READS the process-wide default (its
|
|
9877
10187
|
// write twin routes through emitter.setDefaultMaxChk).
|
|
9878
10188
|
if (bi.module === "events" && bi.member === "defaultMaxListeners") {
|
|
@@ -9908,7 +10218,7 @@ export class Lowerer {
|
|
|
9908
10218
|
}
|
|
9909
10219
|
if (bi.member === "constants" && bi.module === "fs") {
|
|
9910
10220
|
// A bare `fs.constants` read (not one of the baked bits above).
|
|
9911
|
-
this.noLowering(`fs.constants`, expr, "F_OK, R_OK, W_OK, and
|
|
10221
|
+
this.noLowering(`fs.constants`, expr, "F_OK, R_OK, W_OK, X_OK, and COPYFILE_* are the lowered constants");
|
|
9912
10222
|
}
|
|
9913
10223
|
if (builtinModuleFnOf(this, bi.module, bi.member)) {
|
|
9914
10224
|
this.unsupported("SC1090", expr, `library functions as values (call '${expr.getText()}' directly)`);
|
|
@@ -9921,6 +10231,9 @@ export class Lowerer {
|
|
|
9921
10231
|
* deliberately narrower than table membership because many table rows
|
|
9922
10232
|
* are only dispatch sentinels for call-site-specific lowering. */
|
|
9923
10233
|
lowerBuiltinCallableValue(bi, loc) {
|
|
10234
|
+
if (bi.module === "fs" && builtinModuleFnOf(this, bi.module, bi.member)?.fn === "fs.callbackCall") {
|
|
10235
|
+
return { kind: "libCall", fn: "fs.callbackValue", args: [{ kind: "strLit", value: bi.member, type: STRING, loc }], type: DYN, loc };
|
|
10236
|
+
}
|
|
9924
10237
|
const fn = builtinModuleFnOf(this, bi.module, bi.member);
|
|
9925
10238
|
return fn ? this.lowerNativeCallableValue(fn, `${bi.module}.${bi.member}`, loc) : null;
|
|
9926
10239
|
}
|