@scriptc/compiler 0.0.7 → 0.0.9
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 +13 -0
- package/dist/backend/cc.js +14 -0
- package/dist/backend/cc.js.map +1 -1
- package/dist/backend/emission/emit-exprs.js +155 -6
- package/dist/backend/emission/emit-exprs.js.map +1 -1
- package/dist/backend/emission/emit-island.js +9 -1
- package/dist/backend/emission/emit-island.js.map +1 -1
- package/dist/backend/emission/emit-stmts.js +3 -1
- package/dist/backend/emission/emit-stmts.js.map +1 -1
- package/dist/backend/emission/emit-types.d.ts +3 -0
- package/dist/backend/emission/emit-types.js +12 -0
- package/dist/backend/emission/emit-types.js.map +1 -1
- package/dist/backend/emission/emit-walkers.d.ts +7 -5
- package/dist/backend/emission/emit-walkers.js +45 -18
- package/dist/backend/emission/emit-walkers.js.map +1 -1
- package/dist/backend/emission/emitter.d.ts +1 -1
- package/dist/backend/emission/emitter.js +35 -10
- package/dist/backend/emission/emitter.js.map +1 -1
- package/dist/backend/emission/may-throw.js +4 -3
- package/dist/backend/emission/may-throw.js.map +1 -1
- package/dist/backend/llvm/emitter.js +300 -18
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/diagnostics/diagnostic.d.ts +98 -11
- package/dist/diagnostics/diagnostic.js +185 -25
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/frontend/lib-contract.d.ts +24 -6
- package/dist/frontend/lib-contract.js +125 -44
- package/dist/frontend/lib-contract.js.map +1 -1
- package/dist/frontend/lowering/lower-assert.js +16 -0
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-builtins.d.ts +11 -0
- package/dist/frontend/lowering/lower-builtins.js +127 -4
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +77 -18
- package/dist/frontend/lowering/lower-calls.js +978 -44
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +14 -1
- package/dist/frontend/lowering/lower-classes.js +112 -16
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.d.ts +4 -2
- package/dist/frontend/lowering/lower-containers.js +236 -44
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-emitter.js +55 -1
- package/dist/frontend/lowering/lower-emitter.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +26 -3
- package/dist/frontend/lowering/lower-exprs.js +507 -47
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-island.d.ts +7 -0
- package/dist/frontend/lowering/lower-island.js +71 -10
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-mixins.d.ts +1 -1
- package/dist/frontend/lowering/lower-mixins.js +1 -1
- package/dist/frontend/lowering/lower-modules.js +95 -4
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.js +866 -56
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.js +28 -2
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +85 -17
- package/dist/frontend/lowering/lowerer.js +459 -37
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/surfaces.js +20 -3
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/npm-static-rewrite.d.ts +7 -2
- package/dist/frontend/npm-static-rewrite.js +566 -138
- package/dist/frontend/npm-static-rewrite.js.map +1 -1
- package/dist/frontend/npm-static.js +11 -2
- package/dist/frontend/npm-static.js.map +1 -1
- package/dist/frontend/program.js +5 -5
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/shared.d.ts +6 -1
- package/dist/frontend/shared.js +46 -1
- package/dist/frontend/shared.js.map +1 -1
- package/dist/frontend/types.d.ts +28 -1
- package/dist/frontend/types.js +304 -10
- package/dist/frontend/types.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +181 -26
- package/dist/index.js.map +1 -1
- package/dist/ir/nodes.d.ts +159 -9
- package/dist/ir/nodes.js +76 -6
- package/dist/ir/nodes.js.map +1 -1
- package/dist/ir/validate.js +93 -14
- package/dist/ir/validate.js.map +1 -1
- package/dist/library/profile.d.ts +17 -3
- package/dist/library/profile.js +38 -9
- package/dist/library/profile.js.map +1 -1
- package/dist/library/sidecar.js +162 -43
- package/dist/library/sidecar.js.map +1 -1
- package/dist/library/trap-teaching.d.ts +11 -0
- package/dist/library/trap-teaching.js +49 -0
- package/dist/library/trap-teaching.js.map +1 -0
- package/package.json +2 -2
- package/surface-manifest.json +46 -4
|
@@ -14,11 +14,11 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import { isRelativeSpecifier } from "../shared.js";
|
|
16
16
|
import * as ts from "../ts7/adapter.js";
|
|
17
|
-
import { anyOpRequiresDynamicDiag, blockedBindingUseDiag, checkerPanicDiag, isCheckerPanic, genericSignatureTypeDiag, indexSignatureTypeDiag, noLoweringDiag, recordShapeMismatchDiag, requiresDynamicApiDiag, requiresDynamicPackageDiag, requiresDynamicTypeDiag, unionMismatchDiag, unsupportedDiag, unsupportedTypeDiag, } from "../../diagnostics/diagnostic.js";
|
|
17
|
+
import { anyOpRequiresDynamicDiag, blockedBindingUseDiag, checkerPanicDiag, componentTypeDiag, isCheckerPanic, genericSignatureTypeDiag, indexSignatureTypeDiag, intersectionTypeDiag, noLoweringDiag, overloadedSignatureTypeDiag, recordShapeMismatchDiag, requiresDynamicApiDiag, requiresDynamicPackageDiag, requiresDynamicTypeDiag, unionMismatchDiag, unsupportedDiag, unsupportedTypeDiag, } from "../../diagnostics/diagnostic.js";
|
|
18
18
|
import { arrayOf, BOOL, canAdaptDynFuncTo, canConvertToDyn, canCrossIslandBoundary, canExitIslandToType, canMarshalTypedFuncIntoIsland, DYN, F64, isJsonSafeType, isUndefinedArmedUnion, isUnitType, JSVAL, RUNTIME_ERROR_CLASSES, STRING, typeEquals, UNDEFINED_T, VOID } from "../../ir/nodes.js";
|
|
19
19
|
import { provenanceActive } from "../provenance-registry.js";
|
|
20
20
|
import { ambientDtsPath, canonicalBuiltinModule, cjsExportAssignmentOf, cjsExportDiscardReason, fallbackDtsPath, isCjsExportTableLiteral, isJsSourceFile, isNodeEsmFile, isNodeTypesPath, locOf, overridesDtsPath, npmStaticDepSf7, requireSpecOf, resolveImport, workspacePackageOfPath, } from "../program.js";
|
|
21
|
-
import { containsRecord, containsUnion, formatIrType, ISLAND_AMBIENT_TYPES, isUnitOnlyTsType, mapType, ShapeRegistry, typeKey, UnionRegistry, withUndefinedArm as withUndefinedArmCanonical, } from "../types.js";
|
|
21
|
+
import { containsRecord, containsUnion, describeComponentBlocker, describeRecordMemberBlocker, formatIrType, ISLAND_AMBIENT_TYPES, isUnitOnlyTsType, mapType, ShapeRegistry, typeKey, UnionRegistry, withUndefinedArm as withUndefinedArmCanonical, } from "../types.js";
|
|
22
22
|
import { boundaryIntoIslandMsg, boundaryOutOfIslandMsg, builtinConstLit, builtinModuleConstOf, builtinFenceHintOf, builtinModuleFnOf, stdlibMemberFence, isStdlibMember, isStdlibSymbol, isStdlibGlobal, stdlibGlobalMember, nodeTypesOnlySymbol } from "./surfaces.js";
|
|
23
23
|
import { splitFiles, collectProgram, collectNpmImports, collectJsonImports, moduleArtifacts, collectGlobals, declSymbolOf, defaultExportSymbolOf, lowerFileInit, lowerDefaultExport, buildMain, appendDynamicImportModules } from "./lower-modules.js";
|
|
24
24
|
import { registerBuiltinErrorClasses, registerBuiltinEmitterClass, registerBuiltinStreamClasses, builtinErrorInfoOf, builtinEmitterInfoOf, builtinStreamInfoOf, analyzeClassDecoration, classIteratorDrainCall, classIteratorNextCall, classIteratorOf, classIteratorOpenCall, classIteratorRestDrainCall, classMemberNameOf, classValueRef, collectClassShape, exactClassOfReceiver, collectClassShapeInner, ctorAbiEquals, findMethodOn, findStaticOn, findGenericMethodOn, findGenericStaticOn, genericClassInstanceType, isSubclassOf, inHierarchy, overrideBelow, staticShadowBelow, upcastTo, lowerClassMembers, lowerClassCtor, lowerClassExpression, lowerClassExpressionInfo, lowerClassMethodMember, lowerClassValueProperty, lowerStaticMethod, throwingSetterFn, fieldInitStmts, lowerStaticFieldInits, lowerStaticFieldRead, lowerDerivedCtorBody, superCallStmt, lowerSuperMethodCall, superThisRef, lowerSuperAccessorRead, lowerSuperAccessorWrite, inheritsBuiltinErrorCtor, inheritsBuiltinEmitterCtor, errorMessageArg, lowerNew, accessorCall } from "./lower-classes.js";
|
|
@@ -26,8 +26,8 @@ import { mixinCallClassInfoOf, mixinIntersectionInstanceType } from "./lower-mix
|
|
|
26
26
|
import { bindingNeverReassigned, bodyReadsArguments, isThisParameter, paramShape, paramShapes, checkDefaultParamBodyType, completeArgs, wrappedUndefined, undefinedArgFor, requireExactArityValue, bodyReturnType, declaredReturnType, collectSignature, collectSignatureInner, collectGenericSignature, genericFnOf, lowerGenericCall, lowerGenericFnValue, inferTypeParamBindings, lowerGenericInstance, lowerCall, lowerTimersMemberCall, lowerPromiseMethodCall, lowerFilterNarrowCall, isTopLevelFnSymbol, lowerNestedFunctionDecl, lambdaSignature, lowerLambda, lowerFunction } from "./lower-calls.js";
|
|
27
27
|
import { lowerArrayMethodCall, lowerBufferStaticCall, lowerBytesMethodCall, lowerBytesNew, lowerMapMethodCall, lowerMapForEachCall, buildMapForEachFn, lowerRecordOvfCaptureHelper, lowerEnvToPairsHelper, lowerSetMethodCall, lowerSetForEachCall, buildSetForEachFn, lowerRegexMethodCall, lowerStringMethodCall } from "./lower-containers.js";
|
|
28
28
|
import { lowerStreamModuleCall } from "./lower-stream.js";
|
|
29
|
-
import { builtinImportOf, lowerBuiltinModuleCall, lowerChildArgsArg, lowerSpawnSyncCall, lowerSpawnCall, lowerExecSyncCall, recordToEnvPairs, lowerJsonMethodCall, fencedBuiltinImportOf, lowerCryptoComposedCall, lowerUrlMethodCall, lowerSearchParamsMethodCall, lowerStatsMethodCall, lowerChildMethodCall, lowerAtomicsCall, lowerBuiltinExtraProperty, promisifiedExecFileDecl, 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, lowerFsConstantsProperty, lowerHttp2ConstantsProperty, http2ConstantBindingOf, http2ConstantsDestructureDecl, lowerProcessStreamProperty, lowerStringStaticCall, lowerStringLastIndexOfCall, lowerPromiseStaticCall } from "./lower-builtins.js";
|
|
30
|
-
import { isIslandExpr, islandRegexpOf, jsvalIn, requireDynamicApi, islandGlobalFnOf, lowerDynamicImportCall, lowerFetchCall, lowerIslandMethodCall, lowerMathProperty, npmPackageOf, npmMemberFence, npmPackageOfSymbol } from "./lower-island.js";
|
|
29
|
+
import { builtinImportOf, lowerBuiltinModuleCall, lowerFsToUnixTimestampCall, lowerChildArgsArg, lowerSpawnSyncCall, lowerSpawnCall, lowerExecSyncCall, recordToEnvPairs, lowerJsonMethodCall, fencedBuiltinImportOf, lowerCryptoComposedCall, lowerUrlMethodCall, lowerSearchParamsMethodCall, lowerStatsMethodCall, lowerChildMethodCall, lowerAtomicsCall, lowerBuiltinExtraProperty, promisifiedExecFileDecl, 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, lowerFsConstantsProperty, lowerHttp2ConstantsProperty, http2ConstantBindingOf, http2ConstantsDestructureDecl, lowerProcessStreamProperty, lowerStringStaticCall, lowerStringLastIndexOfCall, lowerPromiseStaticCall } from "./lower-builtins.js";
|
|
30
|
+
import { isIslandExpr, islandFuncValueFence, islandRegexpOf, jsvalIn, requireDynamicApi, islandGlobalFnOf, lowerDynamicImportCall, lowerFetchCall, lowerIslandMethodCall, lowerMathProperty, npmPackageOf, npmMemberFence, npmPackageOfSymbol } from "./lower-island.js";
|
|
31
31
|
import { lowerHttpHeadersElement, lowerNetModuleCall, lowerServerMethodCall, lowerServerProperty } from "./lower-server.js";
|
|
32
32
|
import { lowerDgramDnsModuleCall, lowerDgramMethodCall } from "./lower-dgram.js";
|
|
33
33
|
import { lowerNodeTestModuleCall, lowerTestDirectCall, lowerTestMethodCall, lowerTestCtxProperty } from "./lower-test.js";
|
|
@@ -35,7 +35,7 @@ import { lowerAssertModuleCall, lowerAssertDirectCall } from "./lower-assert.js"
|
|
|
35
35
|
import { lowerUtilModuleCall } from "./lower-inspect.js";
|
|
36
36
|
import { lowerComptime, comptimeBakeable, rejectComptimeCaptures, comptimeValueToIr } from "./lower-comptime.js";
|
|
37
37
|
import { lowerStmts, noteBlockedBindings, isBlockedBinding, lowerScopedBlock, predeclareForwardCapture, predeclareForwardFnDecl, predeclareForwardVar, rejectJumpCrossingFinally, lowerStmt, lowerVarStatement, lowerDestructuringDecl, lowerDestructuringAssignParts, lowerBindingPattern, lowerJsvalBindingPattern, checkBindingElement, bindPatternTarget, lowerVarDeclList, lowerVarDecl, lowerSwitch, lowerTry, lowerExprStatement, lowerForOf, lowerForStatement } from "./lower-stmts.js";
|
|
38
|
-
import { lowerExpr, maybeNarrow, lowerUnitComparison, lowerNullishCoalesce, lowerOptionalChain, finishOptionalChain, lowerCondition, ensureBool, requireTruthyUnion, eqComparableUnion, lowerIntrinsicProperty, lowerArrayLiteral, lowerObjectLiteral, lowerShorthandValue, rejectThisInObjectMethod, lowerElementAccess, lowerElementWrite, lowerRecordKeyRead, ensureString, lowerTemplate, lowerAsExpression, lowerPrefixUnary, lowerBinary, lowerCaughtTypeofTest, caughtRead, caughtLocalOf, caughtToString, lowerInstanceOf, lowerRegexLiteral, lowerFieldRead, lowerUnionProperty, fieldTarget, fieldGetExpr, fieldSetStmt, lowerFieldCompound, uniqueSymbolKeyOf, foldedStringKeyOf } from "./lower-exprs.js";
|
|
38
|
+
import { lowerDynObjectLiteral, lowerExpr, maybeNarrow, lowerUnitComparison, lowerNullishCoalesce, lowerOptionalChain, finishOptionalChain, lowerCondition, ensureBool, requireTruthyUnion, eqComparableUnion, lowerIntrinsicProperty, lowerArrayLiteral, lowerObjectLiteral, lowerShorthandValue, rejectThisInObjectMethod, lowerElementAccess, lowerElementWrite, lowerRecordKeyRead, ensureString, lowerTemplate, lowerAsExpression, lowerPrefixUnary, lowerBinary, lowerCaughtTypeofTest, caughtRead, caughtLocalOf, caughtToString, lowerInstanceOf, lowerRegexLiteral, lowerFieldRead, lowerUnionProperty, fieldTarget, fieldGetExpr, fieldSetStmt, lowerFieldCompound, uniqueSymbolKeyOf, foldedStringKeyOf } from "./lower-exprs.js";
|
|
39
39
|
import { lowerRecordFieldCall, lowerObjectMethodCall } from "./lower-calls.js";
|
|
40
40
|
import { fenceCrossBlockNsRef, nsPathPrefix } from "./lower-namespaces.js";
|
|
41
41
|
/** Entry function name. '%' cannot appear in a TS identifier, so a user
|
|
@@ -280,6 +280,25 @@ export function dynUndefinedExpr(loc) {
|
|
|
280
280
|
loc,
|
|
281
281
|
};
|
|
282
282
|
}
|
|
283
|
+
/** An always-throwing Node-parity error expression (the error.nodeThrow
|
|
284
|
+
* libCall — the lowered form of arms Node rejects unconditionally:
|
|
285
|
+
* ERR_INVALID_THIS receivers, ERR_MISSING_ARGS arity ladders, the
|
|
286
|
+
* symbol-to-string TypeError). kind 0 Error / 1 TypeError / 2 RangeError;
|
|
287
|
+
* an empty code means no code slot. `type` is the replaced expression's
|
|
288
|
+
* own (never materialized — the global.undefRead pattern). */
|
|
289
|
+
export function nodeThrowExpr(kind, code, message, type, loc) {
|
|
290
|
+
return {
|
|
291
|
+
kind: "libCall",
|
|
292
|
+
fn: "error.nodeThrow",
|
|
293
|
+
args: [
|
|
294
|
+
{ kind: "numLit", value: kind, type: F64, loc },
|
|
295
|
+
{ kind: "strLit", value: code, type: STRING, loc },
|
|
296
|
+
{ kind: "strLit", value: message, type: STRING, loc },
|
|
297
|
+
],
|
|
298
|
+
type,
|
|
299
|
+
loc,
|
|
300
|
+
};
|
|
301
|
+
}
|
|
283
302
|
/** The checked-dynamic declaration fallback for unmappable binding types
|
|
284
303
|
* (see irTypeOf), two gates over one story:
|
|
285
304
|
*
|
|
@@ -468,6 +487,12 @@ export class Lowerer {
|
|
|
468
487
|
/** Non-null while an instance body lowers: type-parameter symbol →
|
|
469
488
|
* concrete IR type, consulted inside mapType's recursion. */
|
|
470
489
|
typeParamBindings = null;
|
|
490
|
+
/** The ts-level twin of typeParamBindings, non-null while a CALL-keyed
|
|
491
|
+
* instance body lowers: type-parameter symbol → the bound CHECKER type,
|
|
492
|
+
* consulted where the mapped IrType has already widened away information
|
|
493
|
+
* the body needs — indexed accesses (`T[K]` needs K's literal key) and
|
|
494
|
+
* keyed record reads (`o[k]` where k's type is a literal-bound K). */
|
|
495
|
+
typeParamTsBindings = null;
|
|
471
496
|
/** Non-null while an IMPLICIT-ANY instance body lowers (npm-static JS —
|
|
472
497
|
* lower-calls' implicit-monomorphization section): bound param symbol →
|
|
473
498
|
* the call site's checker type, consulted by typeOf for identifier
|
|
@@ -811,6 +836,7 @@ export class Lowerer {
|
|
|
811
836
|
unions: this.unions,
|
|
812
837
|
classNamer: this.classNamer,
|
|
813
838
|
resolveTypeParam: this.typeParamResolver,
|
|
839
|
+
resolveTypeParamTs: this.typeParamTsResolver,
|
|
814
840
|
genericClassInstance: (decl, ref) => this.genericClassInstanceType(decl, ref),
|
|
815
841
|
mixinClassInstance: (decl) => this.mixinTypeContext && this.mixinTypeContext.classNode === decl
|
|
816
842
|
? { kind: "object", className: this.mixinTypeContext.className }
|
|
@@ -895,7 +921,11 @@ export class Lowerer {
|
|
|
895
921
|
const recvDecl = recvDecls.find(ts.isImportClause) ?? recvDecls[0];
|
|
896
922
|
if (recvDecl && ts.isVariableDeclaration(recvDecl) && recvDecl.initializer) {
|
|
897
923
|
const spec = requireSpecOf(recvDecl.initializer);
|
|
898
|
-
const dep = spec
|
|
924
|
+
const dep = spec === null
|
|
925
|
+
? null
|
|
926
|
+
: isRelativeSpecifier(spec)
|
|
927
|
+
? resolveImport(this.program, recvDecl.getSourceFile(), spec)
|
|
928
|
+
: npmStaticDepSf7(this.program, recvDecl.getSourceFile(), spec);
|
|
899
929
|
if (dep)
|
|
900
930
|
symbol = this.cjsModuleExportSymbol(dep, ident.text);
|
|
901
931
|
}
|
|
@@ -1092,12 +1122,14 @@ export class Lowerer {
|
|
|
1092
1122
|
}
|
|
1093
1123
|
/** True when `expr` is an identifier bound by a top-level
|
|
1094
1124
|
* `const x = require("./local")` of a RELATIVE module — the CommonJS
|
|
1095
|
-
* namespace binding — or
|
|
1096
|
-
*
|
|
1097
|
-
* same
|
|
1098
|
-
*
|
|
1099
|
-
*
|
|
1100
|
-
*
|
|
1125
|
+
* namespace binding — or of a bare specifier naming an opted-in
|
|
1126
|
+
* --npm-static package (its CJS entry is a program module, so the
|
|
1127
|
+
* binding is the same namespace over the same export table), or by a
|
|
1128
|
+
* DEFAULT import of a CommonJS JS module (`import d from "./lib.cjs"`:
|
|
1129
|
+
* Node binds d to module.exports, the same value require answers).
|
|
1130
|
+
* Member accesses on it resolve through the export table (property
|
|
1131
|
+
* symbols → resolveValueSymbol); the bare value keeps the
|
|
1132
|
+
* namespace-object fence, like ESM namespace imports of builtins. */
|
|
1101
1133
|
cjsLocalModuleBindingOf(expr) {
|
|
1102
1134
|
if (!ts.isIdentifier(expr))
|
|
1103
1135
|
return false;
|
|
@@ -1115,8 +1147,12 @@ export class Lowerer {
|
|
|
1115
1147
|
return false;
|
|
1116
1148
|
}
|
|
1117
1149
|
const spec = requireSpecOf(decl.initializer);
|
|
1118
|
-
if (spec === null
|
|
1150
|
+
if (spec === null)
|
|
1119
1151
|
return false;
|
|
1152
|
+
if (!isRelativeSpecifier(spec) &&
|
|
1153
|
+
npmStaticDepSf7(this.program, decl.getSourceFile(), spec) === null) {
|
|
1154
|
+
return false;
|
|
1155
|
+
}
|
|
1120
1156
|
}
|
|
1121
1157
|
// SINGLE-VALUE exporters (`module.exports = Countdown` / `= double` /
|
|
1122
1158
|
// `= 42`): the requirer's binding IS the exported value, not a
|
|
@@ -1215,13 +1251,22 @@ export class Lowerer {
|
|
|
1215
1251
|
/** The lowering of a CommonJS `require("./local")` occurrence: a call of
|
|
1216
1252
|
* the required module's run-once %init at exactly this statement's
|
|
1217
1253
|
* position — Node's inline evaluation, with the guard supplying the
|
|
1218
|
-
* cache-hit behavior for every require after the first.
|
|
1219
|
-
*
|
|
1220
|
-
*
|
|
1254
|
+
* cache-hit behavior for every require after the first. Bare specifiers
|
|
1255
|
+
* naming an opted-in --npm-static package resolve to that package's
|
|
1256
|
+
* program entry (the same edge preflight admitted — bundle dists require
|
|
1257
|
+
* their external dependencies by name). Null for everything else
|
|
1258
|
+
* (builtins load nothing; the rest kept its preflight fence). */
|
|
1221
1259
|
requireInitStmt(spec, node) {
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1260
|
+
// Relative requires resolve within the program; a BARE require can be
|
|
1261
|
+
// a program-module edge too when it names an opted-in --npm-static
|
|
1262
|
+
// package (one package requiring another — the resolution answered
|
|
1263
|
+
// its shipped JS, the file is in the module order, and the reads
|
|
1264
|
+
// alias its globals). Without the guarded %init call at this position
|
|
1265
|
+
// those globals stay uninitialized: the dep's module body would never
|
|
1266
|
+
// run.
|
|
1267
|
+
const dep = isRelativeSpecifier(spec)
|
|
1268
|
+
? resolveImport(this.program, node.getSourceFile(), spec)
|
|
1269
|
+
: npmStaticDepSf7(this.program, node.getSourceFile(), spec);
|
|
1225
1270
|
if (!dep || dep.fileName.endsWith(".json"))
|
|
1226
1271
|
return null;
|
|
1227
1272
|
const initName = this.initNameOf.get(dep);
|
|
@@ -1823,8 +1868,8 @@ export class Lowerer {
|
|
|
1823
1868
|
throw new PoisonError();
|
|
1824
1869
|
}
|
|
1825
1870
|
// Would-be records with INDEX SIGNATURES (`Record<string, T>`,
|
|
1826
|
-
// `{ [k: string]: T }`) get
|
|
1827
|
-
//
|
|
1871
|
+
// `{ [k: string]: T }`) get the index-signature fence (SC2006) naming
|
|
1872
|
+
// the supported key/value domain instead of the generic
|
|
1828
1873
|
// supported-types recitation.
|
|
1829
1874
|
if (widened.flags & (ts.TypeFlags.Object | ts.TypeFlags.Intersection) &&
|
|
1830
1875
|
this.checker.getCallSignatures(widened).length === 0 &&
|
|
@@ -1904,6 +1949,77 @@ export class Lowerer {
|
|
|
1904
1949
|
this.pushDiag(requiresDynamicTypeDiag(this.checker.typeToString(type), locOf(node)));
|
|
1905
1950
|
throw new PoisonError();
|
|
1906
1951
|
}
|
|
1952
|
+
// STANDARD-LIBRARY nominal provenance, decided once: interface/class
|
|
1953
|
+
// declarations in the lib's own files (Date, ArrayBuffer, WeakMap, the
|
|
1954
|
+
// iterator/constructor interfaces). Such types report the SC2020 story
|
|
1955
|
+
// below — the same one the index-signature-carrying lib types above
|
|
1956
|
+
// tell — rather than an overload/record claim no user can act on.
|
|
1957
|
+
const stdlibOwnSym = widened.getSymbol();
|
|
1958
|
+
const stdlibNominal = stdlibOwnSym !== undefined &&
|
|
1959
|
+
this.checker.declarationsOf(stdlibOwnSym).some((d) => (ts.isInterfaceDeclaration(d) || ts.isClassDeclaration(d)) &&
|
|
1960
|
+
this.isStdlibFile(d.getSourceFile()));
|
|
1961
|
+
// OVERLOADED call signatures (SC2007) — after the generic branch, so a
|
|
1962
|
+
// generic overload set keeps the monomorphization story: a value of a
|
|
1963
|
+
// multi-signature type has no single compiled signature to hold.
|
|
1964
|
+
if (!stdlibNominal && this.checker.getCallSignatures(widened).length > 1) {
|
|
1965
|
+
this.pushDiag(overloadedSignatureTypeDiag(this.checker.typeToString(type), locOf(node)));
|
|
1966
|
+
throw new PoisonError();
|
|
1967
|
+
}
|
|
1968
|
+
// INTERSECTIONS that resolved to no lowering (SC2008). The ones that
|
|
1969
|
+
// compile never get here: member intersections intern through the
|
|
1970
|
+
// record path, callable hybrids map to '%call' records, and pinned
|
|
1971
|
+
// mixin instantiations resolve by chain structure.
|
|
1972
|
+
if (widened.isIntersectionType()) {
|
|
1973
|
+
this.pushDiag(intersectionTypeDiag(this.checker.typeToString(type), locOf(node)));
|
|
1974
|
+
throw new PoisonError();
|
|
1975
|
+
}
|
|
1976
|
+
// SUPPORTED shapes over a component outside its slot (SC2009): the
|
|
1977
|
+
// Map/Set domains, array/tuple elements, union arms, function
|
|
1978
|
+
// parameters/returns. The container is not the blocker — name the
|
|
1979
|
+
// component instead of reciting the supported set. Checked BEFORE the
|
|
1980
|
+
// lib claim so Map/Set/Promise instantiation failures keep their
|
|
1981
|
+
// component story (describeComponentBlocker always answers for those
|
|
1982
|
+
// heads).
|
|
1983
|
+
{
|
|
1984
|
+
const detail = describeComponentBlocker(widened, this.typeCtx);
|
|
1985
|
+
if (detail !== null) {
|
|
1986
|
+
this.pushDiag(componentTypeDiag(this.checker.typeToString(type), detail, locOf(node)));
|
|
1987
|
+
throw new PoisonError();
|
|
1988
|
+
}
|
|
1989
|
+
}
|
|
1990
|
+
// STANDARD-LIBRARY nominal types with no lowering at all: the SC2020
|
|
1991
|
+
// story, naming the type — and for the families with a WHY, the same
|
|
1992
|
+
// pointed reason the identifier/constructor chokepoints teach.
|
|
1993
|
+
if (stdlibNominal) {
|
|
1994
|
+
const intlHint = "Intl formatter values have no representation — the COMPOSED en-US forms lower: " +
|
|
1995
|
+
'new Intl.NumberFormat("en-US").format(x) and x.toLocaleString("en-US") with default options; ' +
|
|
1996
|
+
"the rest is ICU locale data the binary does not carry";
|
|
1997
|
+
const typeHints = {
|
|
1998
|
+
ArrayBuffer: "no free-standing ArrayBuffer value exists — typed arrays own their storage " +
|
|
1999
|
+
"(new Uint8Array(n) allocates; new Uint8Array(new ArrayBuffer(n)) erases the buffer into the view)",
|
|
2000
|
+
SharedArrayBuffer: "no shared-memory threads exist in a compiled program — Uint8Array is the byte storage",
|
|
2001
|
+
NumberFormat: intlHint,
|
|
2002
|
+
DateTimeFormat: intlHint,
|
|
2003
|
+
DurationFormat: intlHint,
|
|
2004
|
+
PluralRules: intlHint,
|
|
2005
|
+
Collator: intlHint,
|
|
2006
|
+
ListFormat: intlHint,
|
|
2007
|
+
RelativeTimeFormat: intlHint,
|
|
2008
|
+
Segmenter: intlHint,
|
|
2009
|
+
DisplayNames: intlHint,
|
|
2010
|
+
};
|
|
2011
|
+
this.pushDiag(noLoweringDiag(this.checker.typeToString(type), locOf(node), typeHints[stdlibOwnSym?.name ?? ""]));
|
|
2012
|
+
throw new PoisonError();
|
|
2013
|
+
}
|
|
2014
|
+
// USER record shapes blocked by ONE member (SC2009's record arm):
|
|
2015
|
+
// name the member and its type.
|
|
2016
|
+
{
|
|
2017
|
+
const detail = describeRecordMemberBlocker(widened, this.typeCtx);
|
|
2018
|
+
if (detail !== null) {
|
|
2019
|
+
this.pushDiag(componentTypeDiag(this.checker.typeToString(type), detail, locOf(node)));
|
|
2020
|
+
throw new PoisonError();
|
|
2021
|
+
}
|
|
2022
|
+
}
|
|
1907
2023
|
this.pushDiag(unsupportedTypeDiag(this.checker.typeToString(type), locOf(node)));
|
|
1908
2024
|
throw new PoisonError();
|
|
1909
2025
|
}
|
|
@@ -2051,6 +2167,17 @@ export class Lowerer {
|
|
|
2051
2167
|
const sym = t.getSymbol();
|
|
2052
2168
|
return (sym && this.typeParamBindings.get(sym)) ?? null;
|
|
2053
2169
|
};
|
|
2170
|
+
/** The ts-level twin of typeParamResolver: the bound CHECKER type of a
|
|
2171
|
+
* type parameter in the current instantiation (typeParamTsBindings), for
|
|
2172
|
+
* the resolutions where mapType's widening already dropped what the body
|
|
2173
|
+
* needs (indexed accesses over literal-bound keys). Inert outside
|
|
2174
|
+
* call-keyed generic instantiation. */
|
|
2175
|
+
typeParamTsResolver = (t) => {
|
|
2176
|
+
if (!this.typeParamTsBindings || !(t.flags & ts.TypeFlags.TypeParameter))
|
|
2177
|
+
return null;
|
|
2178
|
+
const sym = t.getSymbol();
|
|
2179
|
+
return (sym && this.typeParamTsBindings.get(sym)) ?? null;
|
|
2180
|
+
};
|
|
2054
2181
|
irTypeOf(node) {
|
|
2055
2182
|
const t = this.typeOf(node);
|
|
2056
2183
|
// A never-tainted JS type (neverTaintedJsType) maps — never rides as
|
|
@@ -2076,8 +2203,10 @@ export class Lowerer {
|
|
|
2076
2203
|
}
|
|
2077
2204
|
/** Exact-shape enforcement (SC2002). Records are monomorphic structs, so
|
|
2078
2205
|
* everywhere a value flows into a typed slot (call arg, initializer,
|
|
2079
|
-
* assignment, field, return) the shapes must MATCH —
|
|
2080
|
-
*
|
|
2206
|
+
* assignment, field, return) the shapes must MATCH — or width-coerce:
|
|
2207
|
+
* coerceToExpected already ran widthCoerce (the copy-reshape family),
|
|
2208
|
+
* so what reaches here is the RESIDUE its rules decline, and the
|
|
2209
|
+
* diagnostic names the first blocking rule (describeRecordWidthBlocker).
|
|
2081
2210
|
* Non-record mismatches are not reachable through tsc-clean programs; the
|
|
2082
2211
|
* validator ICEs on them as the usual backstop. */
|
|
2083
2212
|
requireExactShape(node, actual, expected) {
|
|
@@ -2136,7 +2265,13 @@ export class Lowerer {
|
|
|
2136
2265
|
throw new PoisonError();
|
|
2137
2266
|
}
|
|
2138
2267
|
if (containsRecord(actual) || containsRecord(expected)) {
|
|
2139
|
-
|
|
2268
|
+
// A record→record pair gets the pointed story: WHICH width rule
|
|
2269
|
+
// declined (a field that doesn't lift, a required field with no
|
|
2270
|
+
// source, an index signature that could hold the completed key).
|
|
2271
|
+
const detail = actual.kind === "record" && expected.kind === "record"
|
|
2272
|
+
? (this.describeRecordWidthBlocker(actual.shapeId, expected.shapeId) ?? undefined)
|
|
2273
|
+
: undefined;
|
|
2274
|
+
this.pushDiag(recordShapeMismatchDiag(this.fmt(expected), this.fmt(actual), locOf(node), detail));
|
|
2140
2275
|
throw new PoisonError();
|
|
2141
2276
|
}
|
|
2142
2277
|
// Everything else — a plain-kind mismatch like a string flowing into a
|
|
@@ -2634,10 +2769,23 @@ export class Lowerer {
|
|
|
2634
2769
|
* recursively — NESTED width)
|
|
2635
2770
|
* arr — array into array whose element pair lifts (per-element
|
|
2636
2771
|
* copy loop, arrayWidthHelper)
|
|
2772
|
+
* dynIn — a typed value into an 'unknown' (dyn) slot — the same
|
|
2773
|
+
* static→DOM deep copy coerceToExpected applies top-level
|
|
2774
|
+
* upcast — a derived class instance into a base-typed slot (the
|
|
2775
|
+
* prefix-layout pointer reinterpret, no copy)
|
|
2776
|
+
* funcAdapt — a function into a slot whose signature differs only by
|
|
2777
|
+
* CLEAN mechanical conversions (cleanFuncAdaptable); the
|
|
2778
|
+
* stranded (trap-only) dispositions stay out of the plan
|
|
2637
2779
|
* Null when the pair isn't in the relation — callers keep their fences. */
|
|
2638
2780
|
widthLiftPlan(src, dst) {
|
|
2639
2781
|
if (typeEquals(src, dst))
|
|
2640
2782
|
return { how: "copy" };
|
|
2783
|
+
// An 'unknown' (dyn) DESTINATION slot: the static→DOM conversion —
|
|
2784
|
+
// dynFrom, a DEEP COPY (`{ v: 5 }` into `{ v: unknown }`, `number[]`
|
|
2785
|
+
// into `unknown[]` — tsc's top type over the width family's copies).
|
|
2786
|
+
if (dst.kind === "dyn" && src.kind !== "dyn" && this.dynConvertible(src)) {
|
|
2787
|
+
return { how: "dynIn" };
|
|
2788
|
+
}
|
|
2641
2789
|
if (dst.kind === "union") {
|
|
2642
2790
|
if (src.kind === "union") {
|
|
2643
2791
|
return this.unionRetagMappable(src.unionId, dst.unionId) ? { how: "retag" } : null;
|
|
@@ -2667,6 +2815,32 @@ export class Lowerer {
|
|
|
2667
2815
|
return null;
|
|
2668
2816
|
return { how: "liftWrap", tag: candidates[0].tag, arm: candidates[0].arm };
|
|
2669
2817
|
}
|
|
2818
|
+
// A UNION source into a slot that is ONE of its arms (a width copy
|
|
2819
|
+
// whose target field narrowed — the option-table choices shape:
|
|
2820
|
+
// `value: boolean | string` copying into a `value: string` slot the
|
|
2821
|
+
// checker approved): the CHECKED extraction — narrowedArmHelper,
|
|
2822
|
+
// exactly `x!`'s machinery — the proven arm's payload comes out, any
|
|
2823
|
+
// other arm throws the catchable TypeError (divergence 38's stance).
|
|
2824
|
+
if (src.kind === "union" && !isUnitType(dst) && dst.kind !== "void" && this.armTag(src.unionId, dst) >= 0) {
|
|
2825
|
+
return { how: "narrow" };
|
|
2826
|
+
}
|
|
2827
|
+
// A DERIVED instance into a BASE-typed slot (`{ p: Q }` copying into
|
|
2828
|
+
// `{ p: P }`): the same implicit upcast coerceToExpected performs at
|
|
2829
|
+
// top level — prefix layout, a pointer reinterpret, no copy.
|
|
2830
|
+
if (dst.kind === "object" &&
|
|
2831
|
+
src.kind === "object" &&
|
|
2832
|
+
this.isSubclassOf(src.className, dst.className)) {
|
|
2833
|
+
return { how: "upcast" };
|
|
2834
|
+
}
|
|
2835
|
+
// A FUNCTION into a slot whose signature differs only by CLEAN
|
|
2836
|
+
// mechanical conversions (fewer params — JS ignores extras — and
|
|
2837
|
+
// coercibleValue pieces): the general function-value adapter, plan-
|
|
2838
|
+
// gated to the clean subset. The stranded (trap-only) dispositions
|
|
2839
|
+
// funcCoerceAdapter also builds stay TOP-LEVEL only: a width plan
|
|
2840
|
+
// never promises a bridge that can only throw.
|
|
2841
|
+
if (dst.kind === "func" && src.kind === "func" && this.cleanFuncAdaptable(src, dst)) {
|
|
2842
|
+
return { how: "funcAdapt" };
|
|
2843
|
+
}
|
|
2670
2844
|
if (dst.kind === "record" && src.kind === "record") {
|
|
2671
2845
|
return this.recordWidthPlan(src.shapeId, dst.shapeId) !== null ? { how: "width" } : null;
|
|
2672
2846
|
}
|
|
@@ -2786,6 +2960,32 @@ export class Lowerer {
|
|
|
2786
2960
|
throw new Error("lowerer bug: planned clsWidth lift failed to intern");
|
|
2787
2961
|
return { kind: "call", callee: helper, args: [value], type: dst, loc };
|
|
2788
2962
|
}
|
|
2963
|
+
case "narrow": {
|
|
2964
|
+
if (value.type.kind !== "union")
|
|
2965
|
+
throw new Error("lowerer bug: narrow lift on a non-union");
|
|
2966
|
+
const helper = this.narrowedArmHelper(value.type.unionId, dst, loc);
|
|
2967
|
+
if (!helper)
|
|
2968
|
+
throw new Error("lowerer bug: planned narrow lift failed to intern");
|
|
2969
|
+
return { kind: "call", callee: helper, args: [value], type: dst, loc };
|
|
2970
|
+
}
|
|
2971
|
+
case "dynIn": {
|
|
2972
|
+
if (dst.kind !== "dyn")
|
|
2973
|
+
throw new Error("lowerer bug: dynIn lift against a non-dyn slot");
|
|
2974
|
+
return { kind: "dynFrom", value, type: DYN, loc };
|
|
2975
|
+
}
|
|
2976
|
+
case "upcast": {
|
|
2977
|
+
if (dst.kind !== "object" || value.type.kind !== "object")
|
|
2978
|
+
throw new Error("lowerer bug: upcast lift shape");
|
|
2979
|
+
return this.upcastTo(value, dst.className);
|
|
2980
|
+
}
|
|
2981
|
+
case "funcAdapt": {
|
|
2982
|
+
if (dst.kind !== "func" || value.type.kind !== "func")
|
|
2983
|
+
throw new Error("lowerer bug: funcAdapt lift shape");
|
|
2984
|
+
const adapter = this.funcCoerceAdapter(value.type, dst, loc);
|
|
2985
|
+
if (!adapter)
|
|
2986
|
+
throw new Error("lowerer bug: planned funcAdapt lift failed to intern");
|
|
2987
|
+
return { kind: "call", callee: adapter, args: [value], type: dst, loc };
|
|
2988
|
+
}
|
|
2789
2989
|
default: {
|
|
2790
2990
|
const _exhaustive = lift;
|
|
2791
2991
|
void _exhaustive;
|
|
@@ -2803,9 +3003,11 @@ export class Lowerer {
|
|
|
2803
3003
|
* optional-flavored field completes to its undefined arm (the
|
|
2804
3004
|
* literal-completion rule). TUPLES width-coerce too, arity-exact (TS
|
|
2805
3005
|
* permits no other tuple width): per-position lifts, never completion.
|
|
2806
|
-
* Index-signature
|
|
2807
|
-
*
|
|
2808
|
-
*
|
|
3006
|
+
* Index-signature SOURCES narrow here like any wider record — declared
|
|
3007
|
+
* fields copy, the overflow drops with the width (missing target
|
|
3008
|
+
* fields decline: the overflow could hold them). Index-signature
|
|
3009
|
+
* TARGETS keep the overflow CAPTURE helper (widthCoerce's other arm).
|
|
3010
|
+
* Null when the shapes don't relate that way. */
|
|
2809
3011
|
/** The pure planning half of recordWidthHelper — every target field's
|
|
2810
3012
|
* lift, or null when the pair isn't width-coercible. Callers that must
|
|
2811
3013
|
* validate a WHOLE plan before interning anything (the retag helper's
|
|
@@ -2813,7 +3015,13 @@ export class Lowerer {
|
|
|
2813
3015
|
recordWidthPlan(fromId, toId) {
|
|
2814
3016
|
const from = this.shapes.get(fromId);
|
|
2815
3017
|
const to = this.shapes.get(toId);
|
|
2816
|
-
|
|
3018
|
+
// INDEX-SIGNATURE sources narrow like any wider record — the target
|
|
3019
|
+
// fields copy off the declared struct slots and the overflow drops
|
|
3020
|
+
// with the rest of the width (divergence 36's stance; the absent-
|
|
3021
|
+
// completion rule below is the one extra fence). Index-signature
|
|
3022
|
+
// TARGETS keep the overflow CAPTURE helper (widthCoerce's other arm):
|
|
3023
|
+
// a fresh hybrid needs keyed writes, not a field-list literal.
|
|
3024
|
+
if (!from || !to || to.indexValue)
|
|
2817
3025
|
return null;
|
|
2818
3026
|
// Tuple↔record pairs never relate; tuple↔tuple only arity-exact.
|
|
2819
3027
|
if (!!from.tuple !== !!to.tuple)
|
|
@@ -2838,8 +3046,12 @@ export class Lowerer {
|
|
|
2838
3046
|
// the absent-property read: the options-record call shape
|
|
2839
3047
|
// against `{ plugins: unknown, ... }`). Never for tuples: a
|
|
2840
3048
|
// completed position would change .length and JSON where Node
|
|
2841
|
-
// keeps the source arity.
|
|
2842
|
-
|
|
3049
|
+
// keeps the source arity. Never for INDEX-SIGNATURE sources:
|
|
3050
|
+
// the overflow may hold this very key at runtime (tsc lets the
|
|
3051
|
+
// signature satisfy optional target members), so completing to
|
|
3052
|
+
// undefined would drop a value Node keeps — the pair stays
|
|
3053
|
+
// fenced.
|
|
3054
|
+
if (from.tuple || from.indexValue)
|
|
2843
3055
|
return null;
|
|
2844
3056
|
if (tf.type.kind === "dyn") {
|
|
2845
3057
|
plan.set(tf.name, { absentDyn: true });
|
|
@@ -2865,6 +3077,92 @@ export class Lowerer {
|
|
|
2865
3077
|
this.widthPlanning.delete(key);
|
|
2866
3078
|
}
|
|
2867
3079
|
}
|
|
3080
|
+
/** Post-hoc classifier for SC2002's record→record residue: WHY the
|
|
3081
|
+
* width family (recordWidthPlan and the overflow capture — widthCoerce's
|
|
3082
|
+
* two record arms) declined this pair — the FIRST blocking rule, named.
|
|
3083
|
+
* Pure description on the failure path (the site already carries the
|
|
3084
|
+
* rejection): mirrors the planners' gates, never changes what coerces,
|
|
3085
|
+
* and answers null when no pointed story applies (the generic message
|
|
3086
|
+
* stands). */
|
|
3087
|
+
describeRecordWidthBlocker(fromId, toId) {
|
|
3088
|
+
const from = this.shapes.get(fromId);
|
|
3089
|
+
const to = this.shapes.get(toId);
|
|
3090
|
+
if (!from || !to)
|
|
3091
|
+
return null;
|
|
3092
|
+
if (to.indexValue) {
|
|
3093
|
+
// The overflow CAPTURE's gates (lowerRecordOvfCaptureHelper).
|
|
3094
|
+
if (from.tuple || to.tuple)
|
|
3095
|
+
return "a tuple cannot reshape into an index-signature record";
|
|
3096
|
+
const tIv = to.indexValue;
|
|
3097
|
+
const slotOk = (t) => typeEquals(t, tIv) ||
|
|
3098
|
+
(tIv.kind === "dyn" && (t.kind === "dyn" || this.dynConvertible(t))) ||
|
|
3099
|
+
this.widthLiftPlan(t, tIv) !== null;
|
|
3100
|
+
const consumed = new Set();
|
|
3101
|
+
for (const tf of to.fields) {
|
|
3102
|
+
const sf = from.fields.find((f) => f.name === tf.name);
|
|
3103
|
+
if (sf) {
|
|
3104
|
+
if (this.widthLiftPlan(sf.type, tf.type) !== null) {
|
|
3105
|
+
consumed.add(tf.name);
|
|
3106
|
+
continue;
|
|
3107
|
+
}
|
|
3108
|
+
return `field '${tf.name}': '${this.fmt(sf.type)}' does not lift into '${this.fmt(tf.type)}'`;
|
|
3109
|
+
}
|
|
3110
|
+
if (tf.type.kind !== "union" || this.armTag(tf.type.unionId, UNDEFINED_T) < 0) {
|
|
3111
|
+
return `the expected field '${tf.name}' is required and the source has no field to copy into it`;
|
|
3112
|
+
}
|
|
3113
|
+
if (tIv.kind === "dyn" ? !this.dynConvertible(tf.type) : !typeEquals(tf.type, tIv)) {
|
|
3114
|
+
return `the expected field '${tf.name}' ('${this.fmt(tf.type)}') cannot take a runtime key collision from the '${this.fmt(tIv)}' signature slot`;
|
|
3115
|
+
}
|
|
3116
|
+
}
|
|
3117
|
+
for (const ff of from.fields) {
|
|
3118
|
+
if (consumed.has(ff.name))
|
|
3119
|
+
continue;
|
|
3120
|
+
if (!slotOk(ff.type)) {
|
|
3121
|
+
return `the source field '${ff.name}' ('${this.fmt(ff.type)}') cannot enter the expected '[key: string]: ${this.fmt(tIv)}' slot`;
|
|
3122
|
+
}
|
|
3123
|
+
}
|
|
3124
|
+
if (from.indexValue && !slotOk(from.indexValue)) {
|
|
3125
|
+
return `the source's '[key: string]: ${this.fmt(from.indexValue)}' slot cannot enter the expected '[key: string]: ${this.fmt(tIv)}' slot`;
|
|
3126
|
+
}
|
|
3127
|
+
// The dispatch-writes gate: runtime-keyed writes can collide with a
|
|
3128
|
+
// declared field whose type is not the slot's.
|
|
3129
|
+
const dispatchWrites = from.indexValue !== undefined ||
|
|
3130
|
+
from.fields.some((ff) => !consumed.has(ff.name) && to.fields.some((f) => f.name === ff.name));
|
|
3131
|
+
if (dispatchWrites) {
|
|
3132
|
+
const bad = to.fields.find((f) => tIv.kind === "dyn" ? !this.dynConvertible(f.type) : !typeEquals(f.type, tIv));
|
|
3133
|
+
if (bad) {
|
|
3134
|
+
return `runtime-keyed writes can collide with the expected field '${bad.name}' ('${this.fmt(bad.type)}'), which cannot take a '${this.fmt(tIv)}' slot value`;
|
|
3135
|
+
}
|
|
3136
|
+
}
|
|
3137
|
+
return null;
|
|
3138
|
+
}
|
|
3139
|
+
// The field-copy plan's gates (recordWidthPlan).
|
|
3140
|
+
if (!!from.tuple !== !!to.tuple)
|
|
3141
|
+
return null;
|
|
3142
|
+
if (from.tuple && from.fields.length !== to.fields.length) {
|
|
3143
|
+
return `tuple arities differ (${from.fields.length} vs ${to.fields.length}; TS permits no tuple width)`;
|
|
3144
|
+
}
|
|
3145
|
+
for (const tf of to.fields) {
|
|
3146
|
+
const ff = from.fields.find((f) => f.name === tf.name);
|
|
3147
|
+
if (!ff) {
|
|
3148
|
+
if (from.tuple)
|
|
3149
|
+
return null;
|
|
3150
|
+
if (from.indexValue) {
|
|
3151
|
+
return `'${tf.name}' is not a declared field of the source, and the source's index signature could hold it at runtime (a completed undefined would drop that value)`;
|
|
3152
|
+
}
|
|
3153
|
+
if (tf.type.kind === "dyn")
|
|
3154
|
+
continue;
|
|
3155
|
+
if (tf.type.kind !== "union" || this.armTag(tf.type.unionId, UNDEFINED_T) < 0) {
|
|
3156
|
+
return `the expected field '${tf.name}' is missing on the source and is not optional`;
|
|
3157
|
+
}
|
|
3158
|
+
continue;
|
|
3159
|
+
}
|
|
3160
|
+
if (this.widthLiftPlan(ff.type, tf.type) === null) {
|
|
3161
|
+
return `field '${tf.name}': '${this.fmt(ff.type)}' does not lift into '${this.fmt(tf.type)}'`;
|
|
3162
|
+
}
|
|
3163
|
+
}
|
|
3164
|
+
return null;
|
|
3165
|
+
}
|
|
2868
3166
|
recordWidthHelper(fromId, toId, loc) {
|
|
2869
3167
|
const from = this.shapes.get(fromId);
|
|
2870
3168
|
const to = this.shapes.get(toId);
|
|
@@ -3503,8 +3801,14 @@ export class Lowerer {
|
|
|
3503
3801
|
return this.boundaryExitSafe(dst);
|
|
3504
3802
|
if (dst.kind === "dyn")
|
|
3505
3803
|
return src.kind !== "dyn" && this.dynConvertible(src);
|
|
3506
|
-
if (src.kind === "dyn")
|
|
3507
|
-
|
|
3804
|
+
if (src.kind === "dyn") {
|
|
3805
|
+
// The checked-dynamic function boundary's OUT direction joins the
|
|
3806
|
+
// mechanical set: a dyn result landing in an adaptable func slot
|
|
3807
|
+
// takes dynCheck's per-target shim (coerceToExpected's funcOk rule
|
|
3808
|
+
// — the production/development function-choice ternary shape).
|
|
3809
|
+
return (this.jsonSafe(dst) ||
|
|
3810
|
+
(dst.kind === "func" && canAdaptDynFuncTo(dst, (id) => this.shapes.get(id), (id) => this.unions.get(id))));
|
|
3811
|
+
}
|
|
3508
3812
|
if (dst.kind === "union") {
|
|
3509
3813
|
if (src.kind === "union")
|
|
3510
3814
|
return this.unionRetagMappable(src.unionId, dst.unionId);
|
|
@@ -3517,6 +3821,28 @@ export class Lowerer {
|
|
|
3517
3821
|
}
|
|
3518
3822
|
return false;
|
|
3519
3823
|
}
|
|
3824
|
+
/** True when a `src` function value enters a `dst` slot through
|
|
3825
|
+
* funcCoerceAdapter with NO stranded (trap-only) piece: no rest packs,
|
|
3826
|
+
* no surplus source params, every slot parameter converts into the
|
|
3827
|
+
* wrapped function's own type, and the result converts back (a void
|
|
3828
|
+
* slot drops it; a void result answers the exact JS undefined for
|
|
3829
|
+
* dyn/jsval slots). The width family's func gate — widthLiftPlan
|
|
3830
|
+
* bridges only signatures whose every call succeeds by construction. */
|
|
3831
|
+
cleanFuncAdaptable(src, dst) {
|
|
3832
|
+
if (src.rest === true || dst.rest === true)
|
|
3833
|
+
return false;
|
|
3834
|
+
if (src.params.length > dst.params.length)
|
|
3835
|
+
return false;
|
|
3836
|
+
for (let i = 0; i < src.params.length; i++) {
|
|
3837
|
+
if (!this.coercibleValue(dst.params[i], src.params[i]))
|
|
3838
|
+
return false;
|
|
3839
|
+
}
|
|
3840
|
+
if (dst.ret.kind === "void")
|
|
3841
|
+
return src.ret.kind !== "jsval";
|
|
3842
|
+
if (this.coercibleValue(src.ret, dst.ret))
|
|
3843
|
+
return true;
|
|
3844
|
+
return src.ret.kind === "void" && (dst.ret.kind === "dyn" || dst.ret.kind === "jsval");
|
|
3845
|
+
}
|
|
3520
3846
|
/** Interned `%fn.adapt.<n>(f)` — the GENERAL function-value adapter: a
|
|
3521
3847
|
* `fromT` function value flowing into a `toT` slot whose pieces differ
|
|
3522
3848
|
* only by coercibleValue conversions. The slot's callers pass toT's
|
|
@@ -3552,10 +3878,19 @@ export class Lowerer {
|
|
|
3552
3878
|
strandParams = true;
|
|
3553
3879
|
}
|
|
3554
3880
|
let voidRet = null;
|
|
3881
|
+
let strandRet = false;
|
|
3555
3882
|
if (toT.ret.kind !== "void" && !this.coercibleValue(fromT.ret, toT.ret)) {
|
|
3556
|
-
if (fromT.ret.kind !== "void")
|
|
3557
|
-
|
|
3558
|
-
|
|
3883
|
+
if (fromT.ret.kind !== "void") {
|
|
3884
|
+
// A RESULT that cannot convert — the strandParams stance, result
|
|
3885
|
+
// side (the production/development function-choice ternary: the
|
|
3886
|
+
// untaken arm's result shape never lands in the slot's): the
|
|
3887
|
+
// assignment compiles, INVOKING the slot runs the function and
|
|
3888
|
+
// throws the stranded TypeError where its result would convert.
|
|
3889
|
+
strandRet = true;
|
|
3890
|
+
}
|
|
3891
|
+
else {
|
|
3892
|
+
voidRet = toT.ret.kind === "dyn" ? "dyn" : toT.ret.kind === "jsval" ? "jsval" : "strand";
|
|
3893
|
+
}
|
|
3559
3894
|
}
|
|
3560
3895
|
if (toT.ret.kind === "void" && fromT.ret.kind === "jsval")
|
|
3561
3896
|
return null;
|
|
@@ -3623,6 +3958,12 @@ export class Lowerer {
|
|
|
3623
3958
|
strandThrow(`a void result where the '${this.fmt(toT)}' slot promises '${this.fmt(toT.ret)}' (a thrower typed 'never' never reaches this; a genuinely void function has no result to hand over)`),
|
|
3624
3959
|
];
|
|
3625
3960
|
}
|
|
3961
|
+
else if (strandRet) {
|
|
3962
|
+
body = [
|
|
3963
|
+
{ kind: "exprStmt", expr: call, loc },
|
|
3964
|
+
strandThrow(`a '${this.fmt(fromT)}' function invoked through a '${this.fmt(toT)}' slot (the result cannot convert to '${this.fmt(toT.ret)}' — the checker's loose function compatibility admitted the assignment, but the call has no exact lowering)`),
|
|
3965
|
+
];
|
|
3966
|
+
}
|
|
3626
3967
|
else {
|
|
3627
3968
|
const result = this.coerceToExpected(call, toT.ret);
|
|
3628
3969
|
if (!typeEquals(result.type, toT.ret))
|
|
@@ -4646,6 +4987,25 @@ export class Lowerer {
|
|
|
4646
4987
|
e = { kind: "call", callee: helper, args: [e], type: expected, loc: e.loc };
|
|
4647
4988
|
}
|
|
4648
4989
|
}
|
|
4990
|
+
// A JS FUNC value outside the island marshal set flowing into a
|
|
4991
|
+
// jsval slot (`withPlugins(getSupportInfoWithoutPlugins, 0)` — a
|
|
4992
|
+
// wrapper built at module init around a function the run may never
|
|
4993
|
+
// call): the crossing defers to a call-time fence closure instead of
|
|
4994
|
+
// stopping the statement — jsvalIn's deferral, the implicit-coercion
|
|
4995
|
+
// spelling.
|
|
4996
|
+
if (expected.kind === "jsval" && e.type.kind === "func" && !typeEquals(e.type, expected)) {
|
|
4997
|
+
const diagsBefore = this.diags.length;
|
|
4998
|
+
try {
|
|
4999
|
+
this.requireExactShape(node, e.type, expected);
|
|
5000
|
+
}
|
|
5001
|
+
catch (err) {
|
|
5002
|
+
const fence = islandFuncValueFence(this, err, diagsBefore, node);
|
|
5003
|
+
if (fence)
|
|
5004
|
+
return fence;
|
|
5005
|
+
throw err;
|
|
5006
|
+
}
|
|
5007
|
+
return e;
|
|
5008
|
+
}
|
|
4649
5009
|
this.requireExactShape(node, e.type, expected);
|
|
4650
5010
|
return e;
|
|
4651
5011
|
}
|
|
@@ -4732,6 +5092,55 @@ export class Lowerer {
|
|
|
4732
5092
|
return this.coerceInto(node, this.lowerArrayLiteral(x, expected), expected);
|
|
4733
5093
|
}
|
|
4734
5094
|
}
|
|
5095
|
+
// An OBJECT LITERAL against a checked-dynamic slot in a JS file (the
|
|
5096
|
+
// getSupportInfo options argument — a dyn-ABI param): the value's
|
|
5097
|
+
// world IS the DOM — build the DOM literal directly, before the
|
|
5098
|
+
// island gate could claim the checker's `any` context (an island
|
|
5099
|
+
// build could never land in the slot: no engine→DOM crossing).
|
|
5100
|
+
if (expected?.kind === "dyn") {
|
|
5101
|
+
let x = node;
|
|
5102
|
+
while (ts.isParenthesizedExpression(x))
|
|
5103
|
+
x = x.expression;
|
|
5104
|
+
if (ts.isObjectLiteralExpression(x) && isJsSourceFile(x.getSourceFile())) {
|
|
5105
|
+
return lowerDynObjectLiteral(this, x);
|
|
5106
|
+
}
|
|
5107
|
+
}
|
|
5108
|
+
// An ARRAY LITERAL against a UNION slot whose own type has no static
|
|
5109
|
+
// home (the JS dyn fallback — the checker gave no usable context):
|
|
5110
|
+
// when the union has exactly ONE array-family arm — an array, or an
|
|
5111
|
+
// arity-matching tuple (the option-table `default: [{ value: [] }]`
|
|
5112
|
+
// shape) — build AS that arm and wrap; the IR-directed twin of
|
|
5113
|
+
// lowerArrayLiteral's contextual-union rule.
|
|
5114
|
+
if (expected?.kind === "union") {
|
|
5115
|
+
let x = node;
|
|
5116
|
+
while (ts.isParenthesizedExpression(x))
|
|
5117
|
+
x = x.expression;
|
|
5118
|
+
if (ts.isArrayLiteralExpression(x)) {
|
|
5119
|
+
const own = this.mapTypeOf(this.checker.getContextualType(x) ?? this.typeOf(x));
|
|
5120
|
+
// Elements beyond bare null/undefined literals can never live in
|
|
5121
|
+
// a unit-only-element array — a checker type that degraded to one
|
|
5122
|
+
// (`[]`-flavored inference over a populated literal) carries no
|
|
5123
|
+
// element information.
|
|
5124
|
+
const nonUnitElems = x.elements.some((el) => !ts.isOmittedExpression(el) &&
|
|
5125
|
+
el.kind !== ts.SyntaxKind.NullKeyword &&
|
|
5126
|
+
!(ts.isIdentifier(el) && el.text === "undefined"));
|
|
5127
|
+
if (own === null || own.kind === "dyn" || own.kind === "jsval" ||
|
|
5128
|
+
(own.kind === "array" && nonUnitElems && this.unitOnlyElem(own.elem)) ||
|
|
5129
|
+
this.widthLiftPlan(own, expected) === null) {
|
|
5130
|
+
const def = this.unions.get(expected.unionId);
|
|
5131
|
+
const arms = (def?.arms ?? []).filter((a) => (a.kind === "array" && !(nonUnitElems && this.unitOnlyElem(a.elem))) ||
|
|
5132
|
+
(a.kind === "record" &&
|
|
5133
|
+
!!this.shapes.get(a.shapeId)?.tuple &&
|
|
5134
|
+
this.shapes.get(a.shapeId).fields.length === x.elements.length &&
|
|
5135
|
+
!x.elements.some(ts.isSpreadElement)));
|
|
5136
|
+
if (arms.length === 1) {
|
|
5137
|
+
const arm = arms[0];
|
|
5138
|
+
const built = this.lowerArrayLiteral(x, arm);
|
|
5139
|
+
return this.coerceInto(node, built, expected);
|
|
5140
|
+
}
|
|
5141
|
+
}
|
|
5142
|
+
}
|
|
5143
|
+
}
|
|
4735
5144
|
const e = this.lowerExpr(node);
|
|
4736
5145
|
return expected ? this.coerceInto(node, e, expected) : e;
|
|
4737
5146
|
}
|
|
@@ -4999,8 +5408,8 @@ export class Lowerer {
|
|
|
4999
5408
|
lowerGenericFnValue(ref, info) {
|
|
5000
5409
|
return lowerGenericFnValue(this, ref, info);
|
|
5001
5410
|
}
|
|
5002
|
-
inferTypeParamBindings(expr, info, rsig) {
|
|
5003
|
-
return inferTypeParamBindings(this, expr, info, rsig);
|
|
5411
|
+
inferTypeParamBindings(expr, info, rsig, tsBindings) {
|
|
5412
|
+
return inferTypeParamBindings(this, expr, info, rsig, tsBindings);
|
|
5004
5413
|
}
|
|
5005
5414
|
lowerGenericInstance(info, inst) {
|
|
5006
5415
|
return lowerGenericInstance(this, info, inst);
|
|
@@ -6332,6 +6741,11 @@ export class Lowerer {
|
|
|
6332
6741
|
const streamServed = lowerStreamModuleCall(this, call, bi, locOf(access));
|
|
6333
6742
|
if (streamServed)
|
|
6334
6743
|
return streamServed;
|
|
6744
|
+
// fs._toUnixTimestamp — off the param tables (an underscore-stable
|
|
6745
|
+
// internal), served by its own spoke before the table fence.
|
|
6746
|
+
const fsTs = this.lowerFsToUnixTimestampCall(call, bi, locOf(access));
|
|
6747
|
+
if (fsTs)
|
|
6748
|
+
return fsTs;
|
|
6335
6749
|
const builtinFn = builtinModuleFnOf(this, bi.module, bi.member);
|
|
6336
6750
|
if (!builtinFn) {
|
|
6337
6751
|
this.noLowering(`${bi.module}.${bi.member}`, call, builtinFenceHintOf(bi.module, bi.member), this.checker.getSymbolAtLocation(access.name));
|
|
@@ -6362,6 +6776,11 @@ export class Lowerer {
|
|
|
6362
6776
|
const bi = this.builtinMemberOf(expr);
|
|
6363
6777
|
if (!bi)
|
|
6364
6778
|
return null;
|
|
6779
|
+
// events.defaultMaxListeners READS the process-wide default (its
|
|
6780
|
+
// write twin routes through emitter.setDefaultMaxChk).
|
|
6781
|
+
if (bi.module === "events" && bi.member === "defaultMaxListeners") {
|
|
6782
|
+
return { kind: "libCall", fn: "emitter.getDefaultMax", args: [], type: F64, loc };
|
|
6783
|
+
}
|
|
6365
6784
|
const c = builtinModuleConstOf(this, bi.module, bi.member);
|
|
6366
6785
|
if (c !== undefined)
|
|
6367
6786
|
return builtinConstLit(c, loc);
|
|
@@ -6377,6 +6796,9 @@ export class Lowerer {
|
|
|
6377
6796
|
lowerBuiltinModuleCall(expr, bi, fn, loc) {
|
|
6378
6797
|
return lowerBuiltinModuleCall(this, expr, bi, fn, loc);
|
|
6379
6798
|
}
|
|
6799
|
+
lowerFsToUnixTimestampCall(expr, bi, loc) {
|
|
6800
|
+
return lowerFsToUnixTimestampCall(this, expr, bi, loc);
|
|
6801
|
+
}
|
|
6380
6802
|
lowerChildArgsArg(node, loc) {
|
|
6381
6803
|
return lowerChildArgsArg(this, node, loc);
|
|
6382
6804
|
}
|