@scriptc/compiler 0.1.1 → 0.1.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 +45 -17
- package/ambient/scriptc.d.ts +2 -1
- package/dist/backend/build-cache.js.map +1 -1
- package/dist/backend/c/async.js +24 -2
- package/dist/backend/c/async.js.map +1 -1
- package/dist/backend/c/c-emitter.d.ts +22 -10
- package/dist/backend/c/c-emitter.js +60 -15
- package/dist/backend/c/c-emitter.js.map +1 -1
- package/dist/backend/c/exprs.js +220 -10
- package/dist/backend/c/exprs.js.map +1 -1
- package/dist/backend/c/island.js.map +1 -1
- package/dist/backend/c/may-throw.js.map +1 -1
- package/dist/backend/c/stmts.d.ts +3 -5
- package/dist/backend/c/stmts.js +58 -17
- package/dist/backend/c/stmts.js.map +1 -1
- package/dist/backend/c/types.js.map +1 -1
- package/dist/backend/c/walkers.js +31 -5
- package/dist/backend/c/walkers.js.map +1 -1
- package/dist/backend/external-c.js.map +1 -1
- package/dist/backend/linker.js.map +1 -1
- package/dist/backend/llvm/blocks.js.map +1 -1
- package/dist/backend/llvm/dyn.js +56 -3
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.js +98 -19
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/expr-async.js +85 -3
- package/dist/backend/llvm/expr-async.js.map +1 -1
- package/dist/backend/llvm/expr-bytes.js.map +1 -1
- package/dist/backend/llvm/expr-calls.js.map +1 -1
- package/dist/backend/llvm/expr-containers.js.map +1 -1
- package/dist/backend/llvm/expr-context.d.ts +1 -0
- package/dist/backend/llvm/expr-control.js.map +1 -1
- package/dist/backend/llvm/expr-dispatch.js.map +1 -1
- package/dist/backend/llvm/expr-dynamic.js +6 -3
- package/dist/backend/llvm/expr-dynamic.js.map +1 -1
- package/dist/backend/llvm/expr-island.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.js.map +1 -1
- package/dist/backend/llvm/expr-records.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.js +220 -9
- package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
- package/dist/backend/llvm/lib-dispatch.js +2 -0
- package/dist/backend/llvm/lib-dispatch.js.map +1 -1
- package/dist/backend/llvm/lib-shared.js +18 -0
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/llvm/lib-stream.js +6 -3
- package/dist/backend/llvm/lib-stream.js.map +1 -1
- package/dist/backend/llvm/split.js.map +1 -1
- package/dist/backend/llvm/unsupported.js.map +1 -1
- package/dist/backend/llvm/walkers.js.map +1 -1
- package/dist/backend/native-codegen.js.map +1 -1
- package/dist/backend/native-codegen.test.js +2 -0
- package/dist/backend/native-codegen.test.js.map +1 -1
- package/dist/backend/native-toolchain.js.map +1 -1
- package/dist/backend/native-toolchain.test.js.map +1 -1
- package/dist/backend/runtime-pack.js.map +1 -1
- package/dist/backend/targets.js.map +1 -1
- package/dist/backend/vendor-archives.js.map +1 -1
- package/dist/compat/fetch-profile.js +4 -2
- package/dist/compat/fetch-profile.js.map +1 -1
- package/dist/coverage/report.js.map +1 -1
- package/dist/coverage/surface-manifest.js +12 -0
- package/dist/coverage/surface-manifest.js.map +1 -1
- package/dist/diagnostics/diagnostic.d.ts +6 -5
- package/dist/diagnostics/diagnostic.js +7 -6
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/diagnostics/render.js.map +1 -1
- package/dist/ffi/ffi-manifest.js.map +1 -1
- package/dist/frontend/cjs-lexer.js.map +1 -1
- package/dist/frontend/dts-paths.js.map +1 -1
- package/dist/frontend/input-tracker.d.ts +10 -0
- package/dist/frontend/input-tracker.js +26 -3
- package/dist/frontend/input-tracker.js.map +1 -1
- package/dist/frontend/input-tracker.test.js +8 -1
- package/dist/frontend/input-tracker.test.js.map +1 -1
- package/dist/frontend/lib-contract.js.map +1 -1
- package/dist/frontend/lowering/array-values.d.ts +4 -0
- package/dist/frontend/lowering/array-values.js +18 -2
- package/dist/frontend/lowering/array-values.js.map +1 -1
- package/dist/frontend/lowering/callback-arg.js.map +1 -1
- package/dist/frontend/lowering/containers/bytes.d.ts +35 -0
- package/dist/frontend/lowering/containers/bytes.js +1021 -0
- package/dist/frontend/lowering/containers/bytes.js.map +1 -0
- package/dist/frontend/lowering/containers/string-and-regexp.d.ts +17 -0
- package/dist/frontend/lowering/containers/string-and-regexp.js +345 -0
- package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -0
- package/dist/frontend/lowering/expressions/evaluation-safety.d.ts +13 -0
- package/dist/frontend/lowering/expressions/evaluation-safety.js +76 -0
- package/dist/frontend/lowering/expressions/evaluation-safety.js.map +1 -0
- package/dist/frontend/lowering/expressions/object-literals.d.ts +44 -0
- package/dist/frontend/lowering/expressions/object-literals.js +1815 -0
- package/dist/frontend/lowering/expressions/object-literals.js.map +1 -0
- package/dist/frontend/lowering/expressions/optional-chains.d.ts +31 -0
- package/dist/frontend/lowering/expressions/optional-chains.js +382 -0
- package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -0
- package/dist/frontend/lowering/expressions/try-lower-expression.d.ts +7 -0
- package/dist/frontend/lowering/expressions/try-lower-expression.js +26 -0
- package/dist/frontend/lowering/expressions/try-lower-expression.js.map +1 -0
- package/dist/frontend/lowering/lib-boundary.js +7 -2
- package/dist/frontend/lowering/lib-boundary.js.map +1 -1
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-async-iteration.d.ts +7 -0
- package/dist/frontend/lowering/lower-async-iteration.js +657 -0
- package/dist/frontend/lowering/lower-async-iteration.js.map +1 -0
- package/dist/frontend/lowering/lower-builtins.d.ts +18 -0
- package/dist/frontend/lowering/lower-builtins.js +219 -48
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +13 -4
- package/dist/frontend/lowering/lower-calls.js +407 -64
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +7 -13
- package/dist/frontend/lowering/lower-classes.js +128 -35
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-comptime.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.d.ts +1 -47
- package/dist/frontend/lowering/lower-containers.js +135 -1467
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-event-emitter.js +51 -5
- package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +0 -78
- package/dist/frontend/lowering/lower-exprs.js +402 -2351
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-generators.d.ts +18 -3
- package/dist/frontend/lowering/lower-generators.js +145 -9
- package/dist/frontend/lowering/lower-generators.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.js +3 -3
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-island.d.ts +6 -0
- package/dist/frontend/lowering/lower-island.js +37 -5
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.js +52 -15
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-node-module.d.ts +18 -0
- package/dist/frontend/lowering/lower-node-module.js +302 -0
- package/dist/frontend/lowering/lower-node-module.js.map +1 -0
- package/dist/frontend/lowering/lower-server.js +1 -1
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.d.ts +5 -24
- package/dist/frontend/lowering/lower-stmts.js +519 -253
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.js +4 -4
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +37 -34
- package/dist/frontend/lowering/lowerer.js +143 -57
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/optional-arguments.d.ts +9 -0
- package/dist/frontend/lowering/optional-arguments.js +57 -0
- package/dist/frontend/lowering/optional-arguments.js.map +1 -0
- package/dist/frontend/npm-static-declarations.d.ts +35 -0
- package/dist/frontend/npm-static-declarations.js +506 -0
- package/dist/frontend/npm-static-declarations.js.map +1 -0
- package/dist/frontend/npm-static-declarations.test.d.ts +1 -0
- package/dist/frontend/npm-static-declarations.test.js +122 -0
- package/dist/frontend/npm-static-declarations.test.js.map +1 -0
- package/dist/frontend/npm-static.d.ts +2 -0
- package/dist/frontend/npm-static.js +26 -10
- package/dist/frontend/npm-static.js.map +1 -1
- package/dist/frontend/npm.d.ts +60 -0
- package/dist/frontend/npm.js +38 -4
- package/dist/frontend/npm.js.map +1 -1
- package/dist/frontend/npm.test.d.ts +1 -0
- package/dist/frontend/npm.test.js +50 -0
- package/dist/frontend/npm.test.js.map +1 -0
- package/dist/frontend/program.d.ts +3 -2
- package/dist/frontend/program.js +495 -68
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/resolve.d.ts +10 -2
- package/dist/frontend/resolve.js +90 -14
- package/dist/frontend/resolve.js.map +1 -1
- package/dist/frontend/resolve.test.js +4 -1
- package/dist/frontend/resolve.test.js.map +1 -1
- package/dist/frontend/runtime-resolve.d.ts +22 -0
- package/dist/frontend/runtime-resolve.js +101 -0
- package/dist/frontend/runtime-resolve.js.map +1 -0
- package/dist/frontend/runtime-resolve.test.d.ts +1 -0
- package/dist/frontend/runtime-resolve.test.js +18 -0
- package/dist/frontend/runtime-resolve.test.js.map +1 -0
- package/dist/frontend/ts7/adapter.js +12 -13
- package/dist/frontend/ts7/adapter.js.map +1 -1
- package/dist/frontend/ts7/ast.js.map +1 -1
- package/dist/frontend/ts7/census-check.js +3 -3
- package/dist/frontend/ts7/census-check.js.map +1 -1
- package/dist/frontend/ts7/checker.d.ts +3 -0
- package/dist/frontend/ts7/checker.js +12 -3
- package/dist/frontend/ts7/checker.js.map +1 -1
- package/dist/frontend/ts7/enums.js.map +1 -1
- package/dist/frontend/ts7/program-adapter.js +42 -3
- package/dist/frontend/ts7/program-adapter.js.map +1 -1
- package/dist/frontend/type-mapper.js +120 -7
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/index.js +5 -5
- package/dist/index.js.map +1 -1
- package/dist/ir/analysis.js.map +1 -1
- package/dist/ir/ir.d.ts +60 -30
- package/dist/ir/ir.js +57 -6
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/validate.js +44 -59
- package/dist/ir/validate.js.map +1 -1
- package/dist/library/cache-primitives.js.map +1 -1
- package/dist/library/cache-reset.test.js.map +1 -1
- package/dist/library/compiler-self-identity.js.map +1 -1
- package/dist/library/int-infer.js.map +1 -1
- package/dist/library/int-infer.test.js.map +1 -1
- package/dist/library/library-profile.js.map +1 -1
- package/dist/library/sidecar-validate.js.map +1 -1
- package/dist/library/sidecar.js.map +1 -1
- package/dist/startup-cache.js.map +1 -1
- package/dist/wasi-paths.js.map +1 -1
- package/package.json +18 -18
- package/surface-manifest.json +60 -4
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { InternalCompilerError } from "../../errors.js";
|
|
1
2
|
/* Call lowering: the lowerCall dispatch chain, parameter-shape analysis and
|
|
2
3
|
* argument completion (optional/default/rest, explicit-undefined ≡ omission),
|
|
3
4
|
* function/lambda lowering and signature collection, and monomorphizing
|
|
@@ -6,15 +7,19 @@ import * as ts from "../ts7/adapter.js";
|
|
|
6
7
|
import { lowerGenMethodCall } from "./lower-generators.js";
|
|
7
8
|
import { BOOL, CAUGHT, DYN, F64, JSVAL, STRING, SYMBOL_T, UNDEFINED_T, VOID, arrayOf, canBoxFuncIntoDyn, canConvertToDyn, canDynCheckTo, canMarshalTypedFuncIntoIsland, ffiClassType, ffiSourceParamTypes, funcOf, isFfiCallbackParam, isFfiContextParam, isFfiReleaseParam, isUnitType, shapeHasAccessorSlots, typeEquals } from "../../ir/ir.js";
|
|
8
9
|
import { isJsSourceFile, locOf } from "../program.js";
|
|
9
|
-
import { isGenericCallableMemberType, typeKey } from "../type-mapper.js";
|
|
10
|
+
import { genResultRecord, isGenericCallableMemberType, typeKey } from "../type-mapper.js";
|
|
10
11
|
import { PoisonError, dynFallbackType, dynUndefinedExpr, importCallHandleType, jsFuncNameOf, newFnCtx, nodeThrowExpr } from "./lowerer.js";
|
|
11
12
|
import { enforceLibBoundary } from "./lib-boundary.js";
|
|
12
13
|
import { NARROW_FIRST, builtinFenceHintOf, builtinModuleFnOf } from "./surfaces.js";
|
|
13
14
|
import { ffiBindingDiag, ffiSignatureDiag, libCallbackDiag, requiresDynamicDiag } from "../../diagnostics/diagnostic.js";
|
|
14
15
|
import { mixinFnShapeOf } from "./lower-mixins.js";
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
16
|
+
import { dynStringReceiver, lowerArrayFromCall, lowerDynArrayFilterCall, lowerDynArrayFlatMapCall, lowerGroupByStaticCall, lowerIteratorHelperCall, lowerObjectAssignIndexShape, lowerObjectFromEntriesCall, lowerObjectIterOverIndexShape, lowerTupleReadMethodCall } from "./lower-containers.js";
|
|
17
|
+
import { bufEncoding } from "./containers/bytes.js";
|
|
18
|
+
import { lowerRegexMethodCall, lowerStringMethodCall } from "./containers/string-and-regexp.js";
|
|
19
|
+
import { lowerChildStreamMethodCall, lowerCreateRequireCall, lowerDirentMethodCall, lowerFileHandleMethodCall, lowerImportMetaResolveCall, lowerPerfHooksCall, lowerProcStreamMethodCall, lowerReflectApplyCall, lowerRequireResolveCall, lowerWatcherMethodCall } from "./lower-builtins.js";
|
|
20
|
+
import { lowerAbsenceProbe, lowerPromiseAllTupleCall, lowerPromiseRejectCall, templateRawTextOf } from "./lower-exprs.js";
|
|
21
|
+
import { isSafeToDiscard } from "./expressions/evaluation-safety.js";
|
|
22
|
+
import { tryLowerExpression } from "./expressions/try-lower-expression.js";
|
|
18
23
|
import { httpClientFnBindingOf, isStreamUndefCallExpr, lowerCompatReqStreamOptionalCall, lowerHttpClientFnCall } from "./lower-server.js";
|
|
19
24
|
import { EMITTER_API_MEMBERS, exactInstanceClassOf, findGenericMethodOn, lowerClassGenericMethodCall, lowerStaticMethodCall } from "./lower-classes.js";
|
|
20
25
|
import { emitterRooted, lowerEmitterMethodCall } from "./lower-event-emitter.js";
|
|
@@ -26,6 +31,14 @@ import { expandoMemberRead } from "./lower-expando.js";
|
|
|
26
31
|
import { npmStaticPackageOfPath } from "../npm-static.js";
|
|
27
32
|
import { countedFor, varRef } from "../../ir/build.js";
|
|
28
33
|
import { rejectStaticThis } from "./static-this.js";
|
|
34
|
+
import { fenceNodeModuleMutationCall, lowerRequireCacheKeys } from "./lower-node-module.js";
|
|
35
|
+
export function generatorMeta(lowerer, type) {
|
|
36
|
+
const resultType = genResultRecord(type.yieldT, type.retT, lowerer.shapes, lowerer.unions);
|
|
37
|
+
if (resultType === null) {
|
|
38
|
+
throw new InternalCompilerError("lowerer bug: mapped generator without an IteratorResult record");
|
|
39
|
+
}
|
|
40
|
+
return { yieldT: type.yieldT, nextT: type.nextT, resultType };
|
|
41
|
+
}
|
|
29
42
|
/** Instantiation cap per generic function: same-key recursion (`len<T>`
|
|
30
43
|
* calling itself) converges, but POLYMORPHIC recursion (`f<T>` calling
|
|
31
44
|
* `f<T[]>`) would request new instances forever — the cap turns that into a
|
|
@@ -585,6 +598,16 @@ export function appendImplicitUndefinedReturn(lowerer, body, bodyReturn, loc) {
|
|
|
585
598
|
/** A declaration's checker-derived IR return type. The unmappable-type
|
|
586
599
|
* diagnostic points at `blame` (the name for top-level declarations, the
|
|
587
600
|
* whole node for lambda-likes — preserving each caller's historical loc). */
|
|
601
|
+
function hasExplicitJsDocReturn(decl) {
|
|
602
|
+
const sourceFile = decl.getSourceFile();
|
|
603
|
+
return /@returns?\b/.test(sourceFile.text.slice(decl.pos, decl.getStart(sourceFile)));
|
|
604
|
+
}
|
|
605
|
+
function promiseCarriesDyn(lowerer, type) {
|
|
606
|
+
if (type.kind === "promise")
|
|
607
|
+
return type.inner.kind === "dyn";
|
|
608
|
+
return type.kind === "union" &&
|
|
609
|
+
(lowerer.unions.get(type.unionId)?.arms.some((arm) => promiseCarriesDyn(lowerer, arm)) ?? false);
|
|
610
|
+
}
|
|
588
611
|
export function declaredReturnType(lowerer, decl, blame) {
|
|
589
612
|
const sig = lowerer.checker.getSignatureFromDeclaration(decl);
|
|
590
613
|
if (!sig)
|
|
@@ -596,6 +619,17 @@ export function declaredReturnType(lowerer, decl, blame) {
|
|
|
596
619
|
// (`.action(() => { throw ... })`). `never` VALUES stay unmapped.
|
|
597
620
|
if (retTsType.flags & ts.TypeFlags.Never)
|
|
598
621
|
return VOID;
|
|
622
|
+
const mappedReturn = lowerer.mapTypeOf(retTsType);
|
|
623
|
+
if (isJsSourceFile(decl.getSourceFile()) &&
|
|
624
|
+
!hasExplicitJsDocReturn(decl) &&
|
|
625
|
+
mappedReturn !== null &&
|
|
626
|
+
promiseCarriesDyn(lowerer, mappedReturn) &&
|
|
627
|
+
decl.parameters.some((param) => {
|
|
628
|
+
const mapped = lowerer.mapTypeOf(lowerer.typeOf(param.name));
|
|
629
|
+
return mapped === null || mapped.kind === "dyn";
|
|
630
|
+
})) {
|
|
631
|
+
return DYN;
|
|
632
|
+
}
|
|
599
633
|
// A JS function whose UNANNOTATED return infers a FUNCTION type
|
|
600
634
|
// (test/common's mustCall — tsc infers `() => any` from the wrapper
|
|
601
635
|
// it returns): the inferred arity is the wrapper's spelling, not a
|
|
@@ -691,9 +725,6 @@ export function collectSignatureInner(lowerer, decl) {
|
|
|
691
725
|
return;
|
|
692
726
|
const isAsync = decl.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword) === true;
|
|
693
727
|
const isGenerator = decl.asteriskToken !== undefined;
|
|
694
|
-
if (isGenerator && isAsync) {
|
|
695
|
-
lowerer.unsupported("SC1071", decl, "async generators (async function*)");
|
|
696
|
-
}
|
|
697
728
|
if (decl.typeParameters) {
|
|
698
729
|
// Generic async composes: each monomorphized instance is an async
|
|
699
730
|
// IrFunction like any other — its own spawn wrapper, its body
|
|
@@ -742,10 +773,11 @@ export function collectSignatureInner(lowerer, decl) {
|
|
|
742
773
|
}
|
|
743
774
|
const nameBlame = decl.name ?? decl;
|
|
744
775
|
const returnType = lowerer.declaredReturnType(decl, nameBlame);
|
|
745
|
-
if (isAsync && returnType.kind !== "promise") {
|
|
776
|
+
if (isAsync && !isGenerator && returnType.kind !== "promise") {
|
|
746
777
|
lowerer.badType(nameBlame, lowerer.typeOf(nameBlame));
|
|
747
778
|
}
|
|
748
|
-
if (isGenerator &&
|
|
779
|
+
if (isGenerator &&
|
|
780
|
+
(returnType.kind !== "generator" || (returnType.async === true) !== isAsync)) {
|
|
749
781
|
lowerer.badType(nameBlame, lowerer.typeOf(nameBlame));
|
|
750
782
|
}
|
|
751
783
|
const symbol = declSymbolOf(lowerer, decl);
|
|
@@ -761,7 +793,7 @@ export function collectSignatureInner(lowerer, decl) {
|
|
|
761
793
|
returnType,
|
|
762
794
|
isAsync,
|
|
763
795
|
...(isGenerator && returnType.kind === "generator"
|
|
764
|
-
? { generator:
|
|
796
|
+
? { generator: generatorMeta(lowerer, returnType) }
|
|
765
797
|
: {}),
|
|
766
798
|
});
|
|
767
799
|
}
|
|
@@ -1172,17 +1204,15 @@ export function lowerGenericInstance(lowerer, info, inst) {
|
|
|
1172
1204
|
// and awaits park this instance's fibers.
|
|
1173
1205
|
const isAsync = decl.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword) === true;
|
|
1174
1206
|
const nameBlame = (ts.isArrowFunction(decl) ? undefined : decl.name) ?? decl;
|
|
1175
|
-
|
|
1207
|
+
const isGenerator = decl.asteriskToken !== undefined;
|
|
1208
|
+
if (isAsync && !isGenerator && inst.returnType.kind !== "promise") {
|
|
1176
1209
|
lowerer.badType(nameBlame, lowerer.checker.getTypeAtLocation(nameBlame));
|
|
1177
1210
|
}
|
|
1178
1211
|
// A generic GENERATOR instance mirrors async: the body returns the
|
|
1179
1212
|
// resolved TReturn channel, calls enter through the instance's own
|
|
1180
1213
|
// gen-spawn wrapper (the emitter routes by fn.generator).
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
lowerer.unsupported("SC1071", decl, "async generators (async function*)");
|
|
1184
|
-
}
|
|
1185
|
-
if (isGenerator && inst.returnType.kind !== "generator") {
|
|
1214
|
+
if (isGenerator &&
|
|
1215
|
+
(inst.returnType.kind !== "generator" || (inst.returnType.async === true) !== isAsync)) {
|
|
1186
1216
|
lowerer.badType(nameBlame, lowerer.checker.getTypeAtLocation(nameBlame));
|
|
1187
1217
|
}
|
|
1188
1218
|
let bodyReturn = isGenerator
|
|
@@ -1198,7 +1228,7 @@ export function lowerGenericInstance(lowerer, info, inst) {
|
|
|
1198
1228
|
if (cls && info.member.kind === "method")
|
|
1199
1229
|
lowerer.currentClass = cls;
|
|
1200
1230
|
if (isGenerator && inst.returnType.kind === "generator") {
|
|
1201
|
-
fnCtx.generator =
|
|
1231
|
+
fnCtx.generator = generatorMeta(lowerer, inst.returnType);
|
|
1202
1232
|
}
|
|
1203
1233
|
lowerer.fnStack.push(fnCtx);
|
|
1204
1234
|
try {
|
|
@@ -1623,6 +1653,15 @@ function paramWrittenInBody(lowerer, body, sym, name) {
|
|
|
1623
1653
|
walk(body);
|
|
1624
1654
|
return written;
|
|
1625
1655
|
}
|
|
1656
|
+
function broadPromiseParam(lowerer, type) {
|
|
1657
|
+
const mapped = lowerer.mapTypeOf(type);
|
|
1658
|
+
const arms = mapped?.kind === "union"
|
|
1659
|
+
? lowerer.unions.get(mapped.unionId)?.arms
|
|
1660
|
+
: mapped === null ? undefined : [mapped];
|
|
1661
|
+
return !!arms &&
|
|
1662
|
+
arms.some((arm) => arm.kind === "promise" && arm.inner.kind === "dyn") &&
|
|
1663
|
+
arms.every((arm) => isUnitType(arm) || (arm.kind === "promise" && arm.inner.kind === "dyn"));
|
|
1664
|
+
}
|
|
1626
1665
|
/** The implicit-type-parameter slots of a JS function-like: parallel to
|
|
1627
1666
|
* decl.parameters, the param SYMBOL where the slot is a bindable
|
|
1628
1667
|
* implicit-any param (identifier-named, no annotation/JSDoc type, not
|
|
@@ -1651,7 +1690,10 @@ export function implicitAnyParamSymbolsOf(lowerer, decl) {
|
|
|
1651
1690
|
if (param.name.text === "this")
|
|
1652
1691
|
return null;
|
|
1653
1692
|
const t = lowerer.typeOf(param.name);
|
|
1654
|
-
|
|
1693
|
+
const broadFunction = lowerer.checker.typeToString(t) === "Function";
|
|
1694
|
+
const broadArray = lowerer.checkerAnyArrayType(t);
|
|
1695
|
+
const broadPromise = broadPromiseParam(lowerer, t);
|
|
1696
|
+
if ((t.flags & ts.TypeFlags.Any) === 0 && !broadFunction && !broadArray && !broadPromise)
|
|
1655
1697
|
return null;
|
|
1656
1698
|
const sym = lowerer.checker.getSymbolAtLocation(param.name);
|
|
1657
1699
|
if (!sym)
|
|
@@ -1670,13 +1712,54 @@ export function implicitAnyParamSymbolsOf(lowerer, decl) {
|
|
|
1670
1712
|
* selects return INFERENCE with DYN as the recursion pin. */
|
|
1671
1713
|
function implicitDeclaredReturn(lowerer, info) {
|
|
1672
1714
|
try {
|
|
1715
|
+
const broadCallbackSymbols = new Set(info.decl.parameters.flatMap((param, index) => {
|
|
1716
|
+
const symbol = info.implicitParams?.[index];
|
|
1717
|
+
return symbol !== null && symbol !== undefined &&
|
|
1718
|
+
lowerer.checker.typeToString(lowerer.typeOf(param.name)) === "Function"
|
|
1719
|
+
? [symbol]
|
|
1720
|
+
: [];
|
|
1721
|
+
}));
|
|
1722
|
+
let returnsBroadCallback = false;
|
|
1723
|
+
if (broadCallbackSymbols.size > 0 && info.decl.body !== undefined) {
|
|
1724
|
+
ts.walkPreorder(info.decl.body, (node) => {
|
|
1725
|
+
if (node !== info.decl.body && ts.isFunctionLike(node))
|
|
1726
|
+
return "skip";
|
|
1727
|
+
if (!ts.isReturnStatement(node) || node.expression === undefined)
|
|
1728
|
+
return undefined;
|
|
1729
|
+
let expression = node.expression;
|
|
1730
|
+
while (ts.isParenthesizedExpression(expression))
|
|
1731
|
+
expression = expression.expression;
|
|
1732
|
+
if (ts.isCallExpression(expression) &&
|
|
1733
|
+
ts.isIdentifier(expression.expression) &&
|
|
1734
|
+
broadCallbackSymbols.has(lowerer.checker.getSymbolAtLocation(expression.expression) ?? {})) {
|
|
1735
|
+
returnsBroadCallback = true;
|
|
1736
|
+
return "stop";
|
|
1737
|
+
}
|
|
1738
|
+
return undefined;
|
|
1739
|
+
});
|
|
1740
|
+
}
|
|
1741
|
+
if (returnsBroadCallback)
|
|
1742
|
+
return null;
|
|
1673
1743
|
const declSig = lowerer.checker.getSignatureFromDeclaration(info.decl);
|
|
1674
1744
|
if (!declSig)
|
|
1675
1745
|
return null;
|
|
1676
1746
|
const retTs = lowerer.checker.getReturnTypeOfSignature(declSig);
|
|
1677
1747
|
if (retTs.flags & ts.TypeFlags.Any)
|
|
1678
1748
|
return null;
|
|
1679
|
-
|
|
1749
|
+
if (lowerer.checker.isArrayType(retTs)) {
|
|
1750
|
+
const elem = lowerer.checker.getTypeArguments(retTs)[0];
|
|
1751
|
+
// An implicit-any parameter poisons an inferred array result to
|
|
1752
|
+
// any[] even when this instance's body produces one concrete
|
|
1753
|
+
// element type (`knownBy(cmd)` in commander). Let the existing
|
|
1754
|
+
// lowered-return unifier recover that type. Explicit unknown[]
|
|
1755
|
+
// remains a declared checked-dynamic contract and stays pinned.
|
|
1756
|
+
if (elem && (elem.flags & ts.TypeFlags.Any) !== 0)
|
|
1757
|
+
return null;
|
|
1758
|
+
}
|
|
1759
|
+
const mapped = lowerer.mapTypeOf(retTs);
|
|
1760
|
+
if (mapped !== null && promiseCarriesDyn(lowerer, mapped) && !hasExplicitJsDocReturn(info.decl))
|
|
1761
|
+
return null;
|
|
1762
|
+
return mapped;
|
|
1680
1763
|
}
|
|
1681
1764
|
catch (e) {
|
|
1682
1765
|
if (!(e instanceof PoisonError))
|
|
@@ -1684,6 +1767,19 @@ function implicitDeclaredReturn(lowerer, info) {
|
|
|
1684
1767
|
return null;
|
|
1685
1768
|
}
|
|
1686
1769
|
}
|
|
1770
|
+
/** True when a `this.method(...)` call targets an implicit npm-static
|
|
1771
|
+
* method whose result is settled from its lowered body rather than the
|
|
1772
|
+
* checker declaration. Uninitialized-local inference uses this to avoid
|
|
1773
|
+
* freezing an evolving `any` slot to stale JSDoc. */
|
|
1774
|
+
export function implicitMethodCallInfersReturn(lowerer, call) {
|
|
1775
|
+
if (!ts.isPropertyAccessExpression(call.expression) ||
|
|
1776
|
+
call.expression.expression.kind !== ts.SyntaxKind.ThisKeyword ||
|
|
1777
|
+
lowerer.currentClass === null) {
|
|
1778
|
+
return false;
|
|
1779
|
+
}
|
|
1780
|
+
const found = findGenericMethodOn(lowerer, lowerer.currentClass, call.expression.name.text);
|
|
1781
|
+
return found?.info.implicitParams !== undefined && implicitDeclaredReturn(lowerer, found.info) === null;
|
|
1782
|
+
}
|
|
1687
1783
|
/** True when an IR type may BIND an implicit param (a concrete static
|
|
1688
1784
|
* type — the checked-dynamic kinds keep the dyn slot, units have no
|
|
1689
1785
|
* standalone representation). */
|
|
@@ -1709,15 +1805,37 @@ export function implicitCallInstance(lowerer, call, info) {
|
|
|
1709
1805
|
return;
|
|
1710
1806
|
}
|
|
1711
1807
|
let bound = DYN;
|
|
1808
|
+
const declared = lowerer.paramShape(param);
|
|
1809
|
+
if ((lowerer.typeOf(param.name).flags & ts.TypeFlags.Any) === 0)
|
|
1810
|
+
bound = declared.type;
|
|
1712
1811
|
const arg = call.arguments[i];
|
|
1713
1812
|
if (arg && !ts.isSpreadElement(arg)) {
|
|
1813
|
+
const runtimeLocal = ts.isIdentifier(arg) ? lowerer.peekLocal(arg) : null;
|
|
1814
|
+
if (runtimeLocal?.type.kind === "dyn") {
|
|
1815
|
+
bound = DYN;
|
|
1816
|
+
argTypes.set(sym, lowerer.checker.getUnknownType());
|
|
1817
|
+
shapes.push({ type: bound, mode: "required" });
|
|
1818
|
+
return;
|
|
1819
|
+
}
|
|
1714
1820
|
// The argument's own checker type, literal-widened ('add' binds
|
|
1715
1821
|
// string) — typeOf consults the ACTIVE instance's bindings, so a
|
|
1716
1822
|
// bound param forwarded into another implicit call transitively
|
|
1717
1823
|
// instantiates it (this._initCommandGroup(command)).
|
|
1718
1824
|
const t = lowerer.checker.getBaseTypeOfLiteralType(lowerer.typeOf(arg));
|
|
1719
|
-
const mapped = lowerer.mapTypeOf(t);
|
|
1720
|
-
if (
|
|
1825
|
+
const mapped = lowerer.mapTypeOf(t) ?? dynFallbackType(lowerer, arg, t);
|
|
1826
|
+
if (ts.isArrowFunction(arg) &&
|
|
1827
|
+
arg.type === undefined &&
|
|
1828
|
+
mapped?.kind === "func" &&
|
|
1829
|
+
promiseCarriesDyn(lowerer, mapped.ret)) {
|
|
1830
|
+
bound = { ...mapped, ret: DYN };
|
|
1831
|
+
lowerer.runtimeOptionalFunctionReturns.set(arg, DYN);
|
|
1832
|
+
argTypes.set(sym, t);
|
|
1833
|
+
}
|
|
1834
|
+
else if (mapped?.kind === "dyn") {
|
|
1835
|
+
bound = DYN;
|
|
1836
|
+
argTypes.set(sym, t);
|
|
1837
|
+
}
|
|
1838
|
+
else if (bindableImplicitIr(mapped)) {
|
|
1721
1839
|
bound = mapped;
|
|
1722
1840
|
argTypes.set(sym, t);
|
|
1723
1841
|
}
|
|
@@ -1743,7 +1861,11 @@ function internImplicitInstance(lowerer, blame, info, shapes, argTypes) {
|
|
|
1743
1861
|
`${MAX_GENERIC_INSTANCES} instances — polymorphic recursion?)`);
|
|
1744
1862
|
}
|
|
1745
1863
|
const rendered = shapes.map((s) => lowerer.fmt(s.type)).join(", ");
|
|
1746
|
-
const
|
|
1864
|
+
const dynamicBroadPromise = info.decl.parameters.some((param, index) => info.implicitParams?.[index] !== null &&
|
|
1865
|
+
info.implicitParams?.[index] !== undefined &&
|
|
1866
|
+
shapes[index]?.type.kind === "dyn" &&
|
|
1867
|
+
broadPromiseParam(lowerer, lowerer.typeOf(param.name)));
|
|
1868
|
+
const declared = dynamicBroadPromise ? null : implicitDeclaredReturn(lowerer, info);
|
|
1747
1869
|
inst = {
|
|
1748
1870
|
name: `${info.qualifiedName}%${info.instances.size}`,
|
|
1749
1871
|
ordinal: info.instances.size,
|
|
@@ -2712,6 +2834,11 @@ export function lowerCall(lowerer, expr) {
|
|
|
2712
2834
|
if (crServed)
|
|
2713
2835
|
return crServed;
|
|
2714
2836
|
}
|
|
2837
|
+
{
|
|
2838
|
+
const resolved = lowerImportMetaResolveCall(lowerer, expr) ?? lowerRequireResolveCall(lowerer, expr);
|
|
2839
|
+
if (resolved)
|
|
2840
|
+
return resolved;
|
|
2841
|
+
}
|
|
2715
2842
|
// `process.getuid?.()` — intercepted BEFORE the optional-chain
|
|
2716
2843
|
// machinery (the member always exists on a POSIX target, so the
|
|
2717
2844
|
// optional call IS the call; `process.getuid` itself has no value
|
|
@@ -3141,7 +3268,7 @@ export function lowerCall(lowerer, expr) {
|
|
|
3141
3268
|
!expr.expression.questionDotToken &&
|
|
3142
3269
|
!expr.questionDotToken &&
|
|
3143
3270
|
!expr.arguments.some((a) => ts.isSpreadElement(a))) {
|
|
3144
|
-
const recvProbe =
|
|
3271
|
+
const recvProbe = tryLowerExpression(lowerer, expr.expression.expression);
|
|
3145
3272
|
if (recvProbe?.type.kind === "dyn") {
|
|
3146
3273
|
const args = expr.arguments.map((a) => lowerer.lowerExprExpecting(a, DYN));
|
|
3147
3274
|
return {
|
|
@@ -3287,6 +3414,9 @@ export function lowerCall(lowerer, expr) {
|
|
|
3287
3414
|
const cryptoServed = lowerer.lowerCryptoModuleCall(expr, bi, loc);
|
|
3288
3415
|
if (cryptoServed)
|
|
3289
3416
|
return cryptoServed;
|
|
3417
|
+
const timersInterval = lowerer.lowerTimersPromisesSetInterval(expr, bi, loc);
|
|
3418
|
+
if (timersInterval)
|
|
3419
|
+
return timersInterval;
|
|
3290
3420
|
const builtinFn = builtinModuleFnOf(lowerer, bi.module, bi.member);
|
|
3291
3421
|
if (!builtinFn) {
|
|
3292
3422
|
// Typed by @types/node (the fallback declarations only declare
|
|
@@ -3442,7 +3572,7 @@ export function lowerCall(lowerer, expr) {
|
|
|
3442
3572
|
return parsed;
|
|
3443
3573
|
}
|
|
3444
3574
|
}
|
|
3445
|
-
const probed =
|
|
3575
|
+
const probed = tryLowerExpression(lowerer, expr.arguments[0]);
|
|
3446
3576
|
if (name === "parseFloat" && probed?.type.kind === "string") {
|
|
3447
3577
|
return { kind: "libCall", fn: "num.parseFloat", args: [probed], type: F64, loc };
|
|
3448
3578
|
}
|
|
@@ -3756,12 +3886,12 @@ export function lowerCall(lowerer, expr) {
|
|
|
3756
3886
|
return { kind: "callValue", callee, args, type: callee.type.ret, loc };
|
|
3757
3887
|
}
|
|
3758
3888
|
if (ts.isPropertyAccessExpression(expr.expression)) {
|
|
3759
|
-
const intrinsic =
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3889
|
+
const intrinsic = fenceNodeModuleMutationCall(lowerer, expr, expr.expression) ??
|
|
3890
|
+
// Builtin namespace imports first (`fs.readFileSync(...)` where fs
|
|
3891
|
+
// is `import * as fs from "node:fs"`): the same tables and fences
|
|
3892
|
+
// as named builtin imports — before anything below tries to lower
|
|
3893
|
+
// the namespace object itself as a receiver.
|
|
3894
|
+
lowerer.lowerNamespaceBuiltinCall(expr, expr.expression) ??
|
|
3765
3895
|
// The node:perf_hooks spoke: performance.now() and its
|
|
3766
3896
|
// .bind(performance) function value over the runtime's
|
|
3767
3897
|
// process-start-anchored monotonic clock.
|
|
@@ -4379,7 +4509,7 @@ function lowerDynReceiverMethodCall(lowerer, call, access) {
|
|
|
4379
4509
|
// evolving `let h = {}` object flowing back out of a JS helper —
|
|
4380
4510
|
// tsc types the return by the evolved shape, the binding lowered
|
|
4381
4511
|
// dyn): probe the lowering and claim exactly the dyn results.
|
|
4382
|
-
const probed =
|
|
4512
|
+
const probed = tryLowerExpression(lowerer, access.expression);
|
|
4383
4513
|
if (probed?.type.kind !== "dyn")
|
|
4384
4514
|
return null;
|
|
4385
4515
|
recv = probed;
|
|
@@ -4572,6 +4702,71 @@ export function lowerDynDispatchMethodCall(lowerer, call, access, recv, arrayRec
|
|
|
4572
4702
|
if (arrayReceiver && predicate?.type.kind === "func" && predicate.type.ret.kind === "void") {
|
|
4573
4703
|
lowerer.unsupported("SC1090", call.arguments[0], "'.filter()' with a void-returning predicate (the callback return value is erased before its truthiness can be tested)");
|
|
4574
4704
|
}
|
|
4705
|
+
// A dynamic argument array consumed immediately by the fixed-arity arrow
|
|
4706
|
+
// apply lowering below never exposes its surplus tail. Keep a pushed
|
|
4707
|
+
// static-only value's evaluation and the array length mutation, but store
|
|
4708
|
+
// undefined in that unobserved slot so no impossible dyn conversion is
|
|
4709
|
+
// invented. If the slot falls inside the typed prefix, its dynCheck fails
|
|
4710
|
+
// at the callback boundary; valid callers preserve the original prefix.
|
|
4711
|
+
if (method === "push" &&
|
|
4712
|
+
call.arguments.length === 1 &&
|
|
4713
|
+
ts.isIdentifier(access.expression) &&
|
|
4714
|
+
ts.isExpressionStatement(call.parent) &&
|
|
4715
|
+
ts.isBlock(call.parent.parent)) {
|
|
4716
|
+
const receiverSymbol = lowerer.checker.getSymbolAtLocation(access.expression);
|
|
4717
|
+
const block = call.parent.parent;
|
|
4718
|
+
const statementIndex = block.statements.indexOf(call.parent);
|
|
4719
|
+
const next = statementIndex >= 0 ? block.statements[statementIndex + 1] : undefined;
|
|
4720
|
+
let returned = next && ts.isReturnStatement(next) ? next.expression : undefined;
|
|
4721
|
+
while (returned && ts.isParenthesizedExpression(returned))
|
|
4722
|
+
returned = returned.expression;
|
|
4723
|
+
const apply = returned && ts.isCallExpression(returned) &&
|
|
4724
|
+
ts.isPropertyAccessExpression(returned.expression) &&
|
|
4725
|
+
returned.expression.name.text === "apply"
|
|
4726
|
+
? returned
|
|
4727
|
+
: null;
|
|
4728
|
+
const argsNode = apply?.arguments[1];
|
|
4729
|
+
const sameArgs = receiverSymbol !== undefined &&
|
|
4730
|
+
argsNode !== undefined &&
|
|
4731
|
+
ts.isIdentifier(argsNode) &&
|
|
4732
|
+
lowerer.checker.getSymbolAtLocation(argsNode) === receiverSymbol;
|
|
4733
|
+
const applyAccess = apply && ts.isPropertyAccessExpression(apply.expression)
|
|
4734
|
+
? apply.expression
|
|
4735
|
+
: null;
|
|
4736
|
+
const applyTarget = applyAccess?.expression;
|
|
4737
|
+
const arrow = applyTarget ? arrowSignatureOf(lowerer, applyTarget) : null;
|
|
4738
|
+
const target = applyTarget && ts.isIdentifier(applyTarget)
|
|
4739
|
+
? lowerer.peekLocal(applyTarget)
|
|
4740
|
+
: null;
|
|
4741
|
+
const targetParams = target?.type.kind === "func" && target.type.rest !== true
|
|
4742
|
+
? target.type.params
|
|
4743
|
+
: null;
|
|
4744
|
+
if (sameArgs && arrow !== null && targetParams !== null &&
|
|
4745
|
+
targetParams.every((param) => canDynCheckTo(param, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id)))) {
|
|
4746
|
+
const value = lowerer.lowerExpr(call.arguments[0]);
|
|
4747
|
+
if (value.type.kind !== "dyn" && !lowerer.dynConvertible(value.type)) {
|
|
4748
|
+
const saved = lowerer.declareHiddenLocal("%applyTail", DYN);
|
|
4749
|
+
return {
|
|
4750
|
+
kind: "seqExpr",
|
|
4751
|
+
stmts: [
|
|
4752
|
+
{ kind: "varDecl", localId: saved.id, init: recv, loc: locOf(access.expression) },
|
|
4753
|
+
{ kind: "exprStmt", expr: value, loc: value.loc },
|
|
4754
|
+
],
|
|
4755
|
+
result: {
|
|
4756
|
+
kind: "dynInvoke",
|
|
4757
|
+
recv: { kind: "varRef", localId: saved.id, type: DYN, loc: locOf(access.expression) },
|
|
4758
|
+
method,
|
|
4759
|
+
calleeName: access.getText(),
|
|
4760
|
+
args: [dynUndefinedExpr(locOf(call.arguments[0]))],
|
|
4761
|
+
type: DYN,
|
|
4762
|
+
loc: locOf(call),
|
|
4763
|
+
},
|
|
4764
|
+
type: DYN,
|
|
4765
|
+
loc: locOf(call),
|
|
4766
|
+
};
|
|
4767
|
+
}
|
|
4768
|
+
}
|
|
4769
|
+
}
|
|
4575
4770
|
const args = call.arguments.map((arg, i) => i === 0 && predicate ? lowerer.coerceInto(arg, predicate, DYN) : lowerer.lowerExprExpecting(arg, DYN));
|
|
4576
4771
|
return {
|
|
4577
4772
|
kind: "dynInvoke",
|
|
@@ -4924,7 +5119,7 @@ function lowerPrimitiveProtoCall(lowerer, call, recv, name, memberSym) {
|
|
|
4924
5119
|
// optional number selects 0 at runtime through the same narrowed
|
|
4925
5120
|
// nullish IR used by `digits ?? 0`.
|
|
4926
5121
|
const zero = { kind: "numLit", value: 0, type: F64, loc: digits.loc };
|
|
4927
|
-
const defaultUnitDigits = (value) =>
|
|
5122
|
+
const defaultUnitDigits = (value) => isSafeToDiscard(value)
|
|
4928
5123
|
? zero
|
|
4929
5124
|
: {
|
|
4930
5125
|
kind: "seqExpr",
|
|
@@ -5010,6 +5205,46 @@ function lowerPrimitiveProtoCall(lowerer, call, recv, name, memberSym) {
|
|
|
5010
5205
|
return null;
|
|
5011
5206
|
return { kind: "boolLit", value: false, type: BOOL, loc };
|
|
5012
5207
|
}
|
|
5208
|
+
/** The uniquely arity-selected overload on an implicit-any receiver whose
|
|
5209
|
+
* active monomorphization supplies a concrete type. The checker resolved
|
|
5210
|
+
* the original call through `any`, so getResolvedSignature cannot name
|
|
5211
|
+
* the declaration-authored overload; typeOf carries the instance's real
|
|
5212
|
+
* receiver type. Restricting the fallback to exactly one bodyless
|
|
5213
|
+
* signature at this arity avoids recreating TypeScript's overload
|
|
5214
|
+
* resolution for same-arity type distinctions. */
|
|
5215
|
+
function implicitReceiverOverloadReturn(lowerer, expr) {
|
|
5216
|
+
if (!ts.isCallExpression(expr) ||
|
|
5217
|
+
!ts.isPropertyAccessExpression(expr.expression) ||
|
|
5218
|
+
expr.arguments.some(ts.isSpreadElement)) {
|
|
5219
|
+
return null;
|
|
5220
|
+
}
|
|
5221
|
+
const access = expr.expression;
|
|
5222
|
+
const original = lowerer.checker.getTypeAtLocation(access.expression);
|
|
5223
|
+
if ((original.flags & ts.TypeFlags.Any) === 0)
|
|
5224
|
+
return null;
|
|
5225
|
+
const effective = lowerer.typeOf(access.expression);
|
|
5226
|
+
if ((effective.flags & ts.TypeFlags.Any) !== 0)
|
|
5227
|
+
return null;
|
|
5228
|
+
const member = lowerer.checker.getPropertyOfType(effective, access.name.text);
|
|
5229
|
+
if (!member)
|
|
5230
|
+
return null;
|
|
5231
|
+
const signatures = lowerer.checker.getCallSignatures(lowerer.checker.getTypeOfSymbol(member));
|
|
5232
|
+
const matches = signatures.filter((signature) => {
|
|
5233
|
+
const decl = lowerer.checker.signatureDeclaration(signature);
|
|
5234
|
+
if (!decl ||
|
|
5235
|
+
!(ts.isFunctionDeclaration(decl) || ts.isMethodDeclaration(decl)) ||
|
|
5236
|
+
decl.body) {
|
|
5237
|
+
return false;
|
|
5238
|
+
}
|
|
5239
|
+
const params = decl.parameters.filter((param) => !isThisParameter(param));
|
|
5240
|
+
const required = params.filter((param) => !param.questionToken && !param.initializer && !param.dotDotDotToken).length;
|
|
5241
|
+
const maximum = params.some((param) => param.dotDotDotToken) ? Infinity : params.length;
|
|
5242
|
+
return expr.arguments.length >= required && expr.arguments.length <= maximum;
|
|
5243
|
+
});
|
|
5244
|
+
if (matches.length !== 1)
|
|
5245
|
+
return null;
|
|
5246
|
+
return lowerer.mapTypeOf(lowerer.checker.getReturnTypeOfSignature(matches[0]));
|
|
5247
|
+
}
|
|
5013
5248
|
/** Reconciles a direct call's recorded type with the checker's answer at
|
|
5014
5249
|
* the site when the callee is OVERLOADED: tsc resolved the call against
|
|
5015
5250
|
* one overload SIGNATURE, so every downstream lowering sees that
|
|
@@ -5029,10 +5264,12 @@ function lowerPrimitiveProtoCall(lowerer, call, recv, name, memberSym) {
|
|
|
5029
5264
|
function reconcileOverloadReturn(lowerer, expr, call) {
|
|
5030
5265
|
const rsig = lowerer.checker.getResolvedSignature(expr);
|
|
5031
5266
|
const rdecl = rsig ? lowerer.checker.signatureDeclaration(rsig) : undefined;
|
|
5032
|
-
|
|
5033
|
-
|
|
5034
|
-
|
|
5035
|
-
|
|
5267
|
+
const resolvedOverload = rsig && rdecl &&
|
|
5268
|
+
(ts.isFunctionDeclaration(rdecl) || ts.isMethodDeclaration(rdecl)) &&
|
|
5269
|
+
!rdecl.body
|
|
5270
|
+
? lowerer.mapTypeOf(lowerer.checker.getReturnTypeOfSignature(rsig))
|
|
5271
|
+
: null;
|
|
5272
|
+
const rt = resolvedOverload ?? implicitReceiverOverloadReturn(lowerer, expr);
|
|
5036
5273
|
// Unmappable, void, or unit resolved returns keep the implementation's
|
|
5037
5274
|
// type: a discarded result never looks, a USED one meets its use
|
|
5038
5275
|
// site's own mapping (and that site's honest fences). Unit narrowing
|
|
@@ -5312,10 +5549,6 @@ export function lowerNestedFunctionDecl(lowerer, stmt) {
|
|
|
5312
5549
|
export function lambdaSignature(lowerer, node) {
|
|
5313
5550
|
if (!node.body)
|
|
5314
5551
|
lowerer.unsupported("SC1090", node, "function overload signatures");
|
|
5315
|
-
if (node.asteriskToken &&
|
|
5316
|
-
node.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword)) {
|
|
5317
|
-
lowerer.unsupported("SC1071", node, "async generators (async function*)");
|
|
5318
|
-
}
|
|
5319
5552
|
if (node.typeParameters) {
|
|
5320
5553
|
// Generic function-like forms monomorphize only where a static home
|
|
5321
5554
|
// exists: top-level generic function declarations, generic methods
|
|
@@ -5486,13 +5719,14 @@ export function lowerLambda(lowerer, node) {
|
|
|
5486
5719
|
// the lifted body returns the inner T (a `return v` fulfills with v).
|
|
5487
5720
|
const isAsync = !ts.isAccessor(node) &&
|
|
5488
5721
|
node.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword) === true;
|
|
5489
|
-
|
|
5722
|
+
const isGenerator = node.asteriskToken !== undefined;
|
|
5723
|
+
if (isAsync && !isGenerator && funcType.ret.kind !== "promise")
|
|
5490
5724
|
lowerer.badType(node, lowerer.typeOf(node));
|
|
5491
5725
|
// Generator lambdas (function* expressions and object-literal
|
|
5492
5726
|
// *methods): the VALUE's type returns the generator; the lifted body
|
|
5493
5727
|
// returns the TReturn channel (a `return v` is the done-value).
|
|
5494
|
-
|
|
5495
|
-
|
|
5728
|
+
if (isGenerator &&
|
|
5729
|
+
(funcType.ret.kind !== "generator" || (funcType.ret.async === true) !== isAsync))
|
|
5496
5730
|
lowerer.badType(node, lowerer.typeOf(node));
|
|
5497
5731
|
const bodyReturn = isGenerator
|
|
5498
5732
|
? lowerer.genBodyReturnType(funcType.ret)
|
|
@@ -5500,7 +5734,7 @@ export function lowerLambda(lowerer, node) {
|
|
|
5500
5734
|
const fnCtx = newFnCtx(true, selfSymbol, funcType, bodyReturn);
|
|
5501
5735
|
fnCtx.isAsync = isAsync;
|
|
5502
5736
|
if (isGenerator && funcType.ret.kind === "generator") {
|
|
5503
|
-
fnCtx.generator =
|
|
5737
|
+
fnCtx.generator = generatorMeta(lowerer, funcType.ret);
|
|
5504
5738
|
}
|
|
5505
5739
|
const diagsBefore = lowerer.diags.length;
|
|
5506
5740
|
lowerer.fnStack.push(fnCtx);
|
|
@@ -6842,7 +7076,7 @@ function lowerIntlNumberFormatCall(lowerer, call, access) {
|
|
|
6842
7076
|
function objectIsDisjointFalse(left, right, loc) {
|
|
6843
7077
|
const stmts = [];
|
|
6844
7078
|
for (const e of [left, right]) {
|
|
6845
|
-
if (!
|
|
7079
|
+
if (!isSafeToDiscard(e))
|
|
6846
7080
|
stmts.push({ kind: "exprStmt", expr: e, loc });
|
|
6847
7081
|
}
|
|
6848
7082
|
const answer = { kind: "boolLit", value: false, type: BOOL, loc };
|
|
@@ -6856,6 +7090,9 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
6856
7090
|
if (!lowerer.isStdlibGlobal(access.expression, "Object"))
|
|
6857
7091
|
return null;
|
|
6858
7092
|
const member = access.name.text;
|
|
7093
|
+
const cacheKeys = lowerRequireCacheKeys(lowerer, call, member);
|
|
7094
|
+
if (cacheKeys)
|
|
7095
|
+
return cacheKeys;
|
|
6859
7096
|
// Object.is — the spec's SameValue over the static kinds. Number
|
|
6860
7097
|
// pairs take the runtime SameValue (NaN equals NaN, +0 differs from
|
|
6861
7098
|
// -0 — the two divergences from ===); every other supported pair
|
|
@@ -7046,8 +7283,8 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
7046
7283
|
// the explicit-undefined-is-absent stance). Everything else keeps
|
|
7047
7284
|
// the spread hint.
|
|
7048
7285
|
if (call.arguments.length === 2 && !call.arguments.some((a) => ts.isSpreadElement(a))) {
|
|
7049
|
-
const tProbe =
|
|
7050
|
-
const sProbe =
|
|
7286
|
+
const tProbe = tryLowerExpression(lowerer, call.arguments[0]);
|
|
7287
|
+
const sProbe = tryLowerExpression(lowerer, call.arguments[1]);
|
|
7051
7288
|
// CHECKED-DYNAMIC target and source (the JS file-scope
|
|
7052
7289
|
// object-literal identity story): the runtime dyn copy — own
|
|
7053
7290
|
// members of the source land on the target, which returns.
|
|
@@ -7105,7 +7342,7 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
7105
7342
|
while (ts.isParenthesizedExpression(targetNode))
|
|
7106
7343
|
targetNode = targetNode.expression;
|
|
7107
7344
|
const freshLiteralTarget = ts.isObjectLiteralExpression(targetNode);
|
|
7108
|
-
const tProbe = freshLiteralTarget ? null :
|
|
7345
|
+
const tProbe = freshLiteralTarget ? null : tryLowerExpression(lowerer, call.arguments[0]);
|
|
7109
7346
|
const tKind = tProbe?.type.kind;
|
|
7110
7347
|
if (freshLiteralTarget || tKind === "dyn" || tKind === "nullT" || tKind === "undefinedT") {
|
|
7111
7348
|
const loc = locOf(call);
|
|
@@ -7177,7 +7414,7 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
7177
7414
|
// static shapes have no property table to extend.
|
|
7178
7415
|
if (member === "defineProperties" && call.arguments.length === 2 &&
|
|
7179
7416
|
!call.arguments.some((a) => ts.isSpreadElement(a))) {
|
|
7180
|
-
let target =
|
|
7417
|
+
let target = tryLowerExpression(lowerer, call.arguments[0]);
|
|
7181
7418
|
// A FUNCTION-typed target boxes through the dyn boundary: the
|
|
7182
7419
|
// property table lives on the CLOSURE (shared by every box of this
|
|
7183
7420
|
// function value), so defining through a fresh box sticks — the
|
|
@@ -7232,7 +7469,7 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
7232
7469
|
if (member === "hasOwn" && call.arguments.length === 2 && !call.arguments.some((a) => ts.isSpreadElement(a))) {
|
|
7233
7470
|
const recvNode = call.arguments[0];
|
|
7234
7471
|
const keyNode = call.arguments[1];
|
|
7235
|
-
const probed =
|
|
7472
|
+
const probed = tryLowerExpression(lowerer, recvNode);
|
|
7236
7473
|
// A CHECKED-DYNAMIC receiver (the JS file-scope object-literal
|
|
7237
7474
|
// identity story): the runtime dyn probe — OBJ member presence, ARR
|
|
7238
7475
|
// index bounds, Node's ToObject TypeError on nullish.
|
|
@@ -7278,7 +7515,7 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
7278
7515
|
// runtime walks the dyn node's own keys (integer-like keys first,
|
|
7279
7516
|
// JS's own-key order) and answers a dyn array.
|
|
7280
7517
|
{
|
|
7281
|
-
const probed =
|
|
7518
|
+
const probed = tryLowerExpression(lowerer, argNode);
|
|
7282
7519
|
const isDyn = probed?.type.kind === "dyn";
|
|
7283
7520
|
// Unit-typed arguments (Object.keys(null)) ride the same runtime
|
|
7284
7521
|
// walk: it throws Node's catchable TypeError.
|
|
@@ -7296,7 +7533,7 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
7296
7533
|
// record (the narrowed export-table literal) — the lowered value's
|
|
7297
7534
|
// shape is the honest dispatch key, exactly the identity-Set stance.
|
|
7298
7535
|
if (argIr === null && isJsSourceFile(argNode.getSourceFile())) {
|
|
7299
|
-
const probed =
|
|
7536
|
+
const probed = tryLowerExpression(lowerer, argNode);
|
|
7300
7537
|
if (probed?.type.kind === "record")
|
|
7301
7538
|
argIr = probed.type;
|
|
7302
7539
|
}
|
|
@@ -8337,6 +8574,69 @@ const SP_BRAND_METHODS = new Set([
|
|
|
8337
8574
|
"append", "delete", "get", "getAll", "has", "set", "sort",
|
|
8338
8575
|
"forEach", "keys", "values", "entries", "toString",
|
|
8339
8576
|
]);
|
|
8577
|
+
function arrowSignatureOf(lowerer, node) {
|
|
8578
|
+
const signatures = lowerer.checker.getCallSignatures(lowerer.typeOf(node));
|
|
8579
|
+
if (signatures.length !== 1)
|
|
8580
|
+
return null;
|
|
8581
|
+
const declaration = lowerer.checker.signatureDeclaration(signatures[0]);
|
|
8582
|
+
return declaration !== undefined && ts.isArrowFunction(declaration) ? signatures[0] : null;
|
|
8583
|
+
}
|
|
8584
|
+
/** `arrow.apply(thisArg, dynArgs)` for a fixed-arity compiled arrow. Arrows
|
|
8585
|
+
* ignore `thisArg` and surplus arguments by language definition; declared
|
|
8586
|
+
* parameters validate from the dynamic array in order. */
|
|
8587
|
+
function lowerArrowFunctionApply(lowerer, call, access) {
|
|
8588
|
+
if (access.name.text !== "apply" ||
|
|
8589
|
+
call.arguments.length !== 2 ||
|
|
8590
|
+
call.arguments.some(ts.isSpreadElement) ||
|
|
8591
|
+
arrowSignatureOf(lowerer, access.expression) === null) {
|
|
8592
|
+
return null;
|
|
8593
|
+
}
|
|
8594
|
+
const callee = lowerer.lowerExpr(access.expression);
|
|
8595
|
+
if (callee.type.kind !== "func" || callee.type.rest === true)
|
|
8596
|
+
return null;
|
|
8597
|
+
if (!callee.type.params.every((param) => canDynCheckTo(param, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id)))) {
|
|
8598
|
+
return null;
|
|
8599
|
+
}
|
|
8600
|
+
const argsList = lowerer.lowerExpr(call.arguments[1]);
|
|
8601
|
+
if (argsList.type.kind !== "dyn")
|
|
8602
|
+
return null;
|
|
8603
|
+
const loc = locOf(call);
|
|
8604
|
+
const savedCallee = lowerer.declareHiddenLocal("%applyFn", callee.type);
|
|
8605
|
+
const savedArgs = lowerer.declareHiddenLocal("%applyArgs", DYN);
|
|
8606
|
+
const stmts = [
|
|
8607
|
+
{ kind: "varDecl", localId: savedCallee.id, init: callee, loc },
|
|
8608
|
+
{ kind: "exprStmt", expr: lowerer.lowerExpr(call.arguments[0]), loc },
|
|
8609
|
+
{ kind: "varDecl", localId: savedArgs.id, init: argsList, loc },
|
|
8610
|
+
];
|
|
8611
|
+
const args = callee.type.params.map((param, index) => {
|
|
8612
|
+
const read = {
|
|
8613
|
+
kind: "dynKeyGet",
|
|
8614
|
+
key: { kind: "strLit", value: String(index), type: STRING, loc },
|
|
8615
|
+
value: { kind: "varRef", localId: savedArgs.id, type: DYN, loc },
|
|
8616
|
+
type: DYN,
|
|
8617
|
+
loc,
|
|
8618
|
+
};
|
|
8619
|
+
return lowerer.coerceInto(call.arguments[1], read, param);
|
|
8620
|
+
});
|
|
8621
|
+
const invoked = {
|
|
8622
|
+
kind: "callValue",
|
|
8623
|
+
callee: { kind: "varRef", localId: savedCallee.id, type: callee.type, loc },
|
|
8624
|
+
args,
|
|
8625
|
+
type: callee.type.ret,
|
|
8626
|
+
loc,
|
|
8627
|
+
};
|
|
8628
|
+
let result;
|
|
8629
|
+
if (invoked.type.kind === "void") {
|
|
8630
|
+
stmts.push({ kind: "exprStmt", expr: invoked, loc });
|
|
8631
|
+
result = dynUndefinedExpr(loc);
|
|
8632
|
+
}
|
|
8633
|
+
else {
|
|
8634
|
+
result = lowerer.coerceInto(call, invoked, DYN);
|
|
8635
|
+
if (result.type.kind !== "dyn")
|
|
8636
|
+
return null;
|
|
8637
|
+
}
|
|
8638
|
+
return { kind: "seqExpr", stmts, result, type: DYN, loc };
|
|
8639
|
+
}
|
|
8340
8640
|
function lowerObjLitGenericMethodCall(lowerer, call, access) {
|
|
8341
8641
|
if (lowerer.chainBlocked(access, call))
|
|
8342
8642
|
return null;
|
|
@@ -8398,6 +8698,9 @@ function lowerObjLitGenericMethodCall(lowerer, call, access) {
|
|
|
8398
8698
|
}
|
|
8399
8699
|
const found = objLitGenericFnNodeOf(lowerer, propSym);
|
|
8400
8700
|
if (!found) {
|
|
8701
|
+
const arrowApply = lowerArrowFunctionApply(lowerer, call, access);
|
|
8702
|
+
if (arrowApply !== null)
|
|
8703
|
+
return arrowApply;
|
|
8401
8704
|
// Function.prototype.apply/call/bind spelled through a FUNCTION
|
|
8402
8705
|
// receiver: compiled functions are direct calls with no runtime
|
|
8403
8706
|
// `this`/arguments object to re-route — name the working spelling
|
|
@@ -8444,9 +8747,32 @@ function lowerObjLitGenericMethodCall(lowerer, call, access) {
|
|
|
8444
8747
|
export function lowerObjectMethodCall(lowerer, call, access) {
|
|
8445
8748
|
if (lowerer.chainBlocked(access, call))
|
|
8446
8749
|
return null;
|
|
8447
|
-
const
|
|
8448
|
-
|
|
8750
|
+
const mappedReceiver = lowerer.mapTypeOf(lowerer.typeOf(access.expression));
|
|
8751
|
+
const receiverIr = mappedReceiver?.kind === "object"
|
|
8752
|
+
? mappedReceiver
|
|
8753
|
+
: mappedReceiver?.kind === "union"
|
|
8754
|
+
? (() => {
|
|
8755
|
+
const arms = lowerer.unions.get(mappedReceiver.unionId)?.arms ?? [];
|
|
8756
|
+
const objects = arms.filter((arm) => arm.kind === "object");
|
|
8757
|
+
return objects.length === 1 && arms.every((arm) => arm.kind === "object" || isUnitType(arm))
|
|
8758
|
+
? objects[0]
|
|
8759
|
+
: null;
|
|
8760
|
+
})()
|
|
8761
|
+
: null;
|
|
8762
|
+
if (receiverIr === null)
|
|
8449
8763
|
return null;
|
|
8764
|
+
const lowerReceiver = () => {
|
|
8765
|
+
const receiver = lowerer.lowerExpr(access.expression);
|
|
8766
|
+
const optional = lowerer.runtimeOptionalPropertyReceiver(access.expression, receiver, receiverIr, access.name.text);
|
|
8767
|
+
if (optional !== null)
|
|
8768
|
+
return optional;
|
|
8769
|
+
if (receiver.type.kind === "union") {
|
|
8770
|
+
const helper = lowerer.narrowedArmHelper(receiver.type.unionId, receiverIr, locOf(access.expression));
|
|
8771
|
+
if (helper !== null)
|
|
8772
|
+
return { kind: "call", callee: helper, args: [receiver], type: receiverIr, loc: locOf(access.expression) };
|
|
8773
|
+
}
|
|
8774
|
+
return receiver;
|
|
8775
|
+
};
|
|
8450
8776
|
const info = lowerer.classes.get(receiverIr.className);
|
|
8451
8777
|
if (!info)
|
|
8452
8778
|
lowerer.flushDeferredClass(receiverIr.className);
|
|
@@ -8474,17 +8800,34 @@ export function lowerObjectMethodCall(lowerer, call, access) {
|
|
|
8474
8800
|
if (gfound)
|
|
8475
8801
|
return lowerClassGenericMethodCall(lowerer, call, access, info, gfound);
|
|
8476
8802
|
}
|
|
8477
|
-
// A FUNC- or DYN-typed FIELD in call position:
|
|
8478
|
-
// ctor-assigned callback field (countdown.js's
|
|
8479
|
-
// ordinary call through the field's VALUE —
|
|
8480
|
-
//
|
|
8481
|
-
//
|
|
8482
|
-
//
|
|
8803
|
+
// A FUNC-, nullable-FUNC-, or DYN-typed FIELD in call position:
|
|
8804
|
+
// `this.cb()` — the ctor-assigned callback field (countdown.js's
|
|
8805
|
+
// shape). The call is an ordinary call through the field's VALUE —
|
|
8806
|
+
// read and, when necessary, check-narrow the callable arm, then
|
|
8807
|
+
// callValue; checked-dynamic fields use the dynCall boundary. Every
|
|
8808
|
+
// other field type falls through to the fences.
|
|
8483
8809
|
if (info && !found) {
|
|
8484
8810
|
const fieldType = info.fields.get(access.name.text);
|
|
8485
|
-
|
|
8811
|
+
const callableType = fieldType?.kind === "func"
|
|
8812
|
+
? fieldType
|
|
8813
|
+
: fieldType?.kind === "union"
|
|
8814
|
+
? (() => {
|
|
8815
|
+
const arms = lowerer.unions.get(fieldType.unionId)?.arms ?? [];
|
|
8816
|
+
const funcs = arms.filter((arm) => arm.kind === "func");
|
|
8817
|
+
return funcs.length === 1 && arms.every((arm) => arm.kind === "func" || isUnitType(arm))
|
|
8818
|
+
? funcs[0]
|
|
8819
|
+
: null;
|
|
8820
|
+
})()
|
|
8821
|
+
: null;
|
|
8822
|
+
if (fieldType && (callableType !== null || fieldType.kind === "dyn")) {
|
|
8486
8823
|
const target = lowerer.fieldTarget(access);
|
|
8487
|
-
|
|
8824
|
+
let callee = target ? lowerer.fieldGetExpr(target, locOf(access), access) : null;
|
|
8825
|
+
if (callee?.type.kind === "union" && callableType !== null) {
|
|
8826
|
+
const helper = lowerer.narrowedArmHelper(callee.type.unionId, callableType, locOf(access));
|
|
8827
|
+
if (helper !== null) {
|
|
8828
|
+
callee = { kind: "call", callee: helper, args: [callee], type: callableType, loc: locOf(access) };
|
|
8829
|
+
}
|
|
8830
|
+
}
|
|
8488
8831
|
if (callee?.type.kind === "func") {
|
|
8489
8832
|
const params = callee.type.params;
|
|
8490
8833
|
const args = call.arguments.map((a, i) => lowerer.lowerExprExpecting(a, params[i]));
|
|
@@ -8514,7 +8857,7 @@ export function lowerObjectMethodCall(lowerer, call, access) {
|
|
|
8514
8857
|
// The one builtin method: Error.prototype.toString, a runtime
|
|
8515
8858
|
// implementation called directly (overriding it is fenced, so no
|
|
8516
8859
|
// dispatch can ever be needed). Receiver BORROWED by the libCall.
|
|
8517
|
-
const receiver =
|
|
8860
|
+
const receiver = lowerReceiver();
|
|
8518
8861
|
return {
|
|
8519
8862
|
kind: "libCall",
|
|
8520
8863
|
fn: "error.toString",
|
|
@@ -8536,7 +8879,7 @@ export function lowerObjectMethodCall(lowerer, call, access) {
|
|
|
8536
8879
|
lowerer.noteVirtualEdge(info, method);
|
|
8537
8880
|
else
|
|
8538
8881
|
lowerer.noteEdge(`%${found.declarer.def.name}.${method}`);
|
|
8539
|
-
const receiver =
|
|
8882
|
+
const receiver = lowerReceiver();
|
|
8540
8883
|
const args = lowerer.completeArgs(call.arguments, found.sig.params, locOf(call), call);
|
|
8541
8884
|
if (lowerer.overrideBelow(info, method)) {
|
|
8542
8885
|
return reconcileOverloadReturn(lowerer, call, {
|