@scriptc/compiler 0.1.1 → 0.1.3
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 +104 -31
- package/ambient/scriptc.d.ts +2 -1
- package/dist/backend/build-cache.js.map +1 -1
- package/dist/backend/c/async.d.ts +5 -0
- package/dist/backend/c/async.js +81 -2
- package/dist/backend/c/async.js.map +1 -1
- package/dist/backend/c/c-emitter.d.ts +25 -10
- package/dist/backend/c/c-emitter.js +74 -22
- package/dist/backend/c/c-emitter.js.map +1 -1
- package/dist/backend/c/exprs.d.ts +8 -1
- package/dist/backend/c/exprs.js +371 -18
- 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/shapes.js +15 -13
- package/dist/backend/c/shapes.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.d.ts +4 -0
- package/dist/backend/c/types.js +18 -1
- package/dist/backend/c/types.js.map +1 -1
- package/dist/backend/c/types.test.js +8 -1
- package/dist/backend/c/types.test.js.map +1 -1
- package/dist/backend/c/walkers.js +63 -16
- package/dist/backend/c/walkers.js.map +1 -1
- package/dist/backend/external-c.js.map +1 -1
- package/dist/backend/json-literal.d.ts +7 -0
- package/dist/backend/json-literal.js +17 -0
- package/dist/backend/json-literal.js.map +1 -0
- package/dist/backend/json-literal.test.d.ts +1 -0
- package/dist/backend/json-literal.test.js +17 -0
- package/dist/backend/json-literal.test.js.map +1 -0
- package/dist/backend/link-plan.d.ts +1 -1
- package/dist/backend/link-plan.js +5 -1
- package/dist/backend/link-plan.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/classes.js +8 -7
- package/dist/backend/llvm/classes.js.map +1 -1
- package/dist/backend/llvm/common.d.ts +4 -0
- package/dist/backend/llvm/common.js +6 -0
- package/dist/backend/llvm/common.js.map +1 -1
- package/dist/backend/llvm/common.test.d.ts +1 -0
- package/dist/backend/llvm/common.test.js +9 -0
- package/dist/backend/llvm/common.test.js.map +1 -0
- package/dist/backend/llvm/dyn.d.ts +4 -0
- package/dist/backend/llvm/dyn.js +80 -16
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.js +132 -25
- 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 +5 -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 +15 -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 +8 -0
- package/dist/backend/llvm/expr-primitives.js.map +1 -1
- package/dist/backend/llvm/expr-records.js +3 -3
- package/dist/backend/llvm/expr-records.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.js +222 -10
- package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
- package/dist/backend/llvm/expr-stream-callbacks.d.ts +3 -0
- package/dist/backend/llvm/expr-stream-callbacks.js +53 -0
- package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
- package/dist/backend/llvm/lib-dispatch.js +24 -0
- package/dist/backend/llvm/lib-dispatch.js.map +1 -1
- package/dist/backend/llvm/lib-process.js +50 -5
- package/dist/backend/llvm/lib-process.js.map +1 -1
- package/dist/backend/llvm/lib-shared.js +64 -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/shapes.js +10 -8
- package/dist/backend/llvm/shapes.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 +7 -5
- 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-link-info.d.ts +2 -1
- package/dist/backend/native-link-info.js +4 -0
- package/dist/backend/native-link-info.js.map +1 -1
- package/dist/backend/native-link-info.test.js +24 -1
- package/dist/backend/native-link-info.test.js.map +1 -1
- package/dist/backend/native-toolchain.d.ts +8 -6
- package/dist/backend/native-toolchain.js +28 -13
- package/dist/backend/native-toolchain.js.map +1 -1
- package/dist/backend/native-toolchain.test.js +36 -1
- package/dist/backend/native-toolchain.test.js.map +1 -1
- package/dist/backend/runtime-pack-targets.test.js +1 -1
- package/dist/backend/runtime-pack-targets.test.js.map +1 -1
- package/dist/backend/runtime-pack.js.map +1 -1
- package/dist/backend/runtime-pack.test.js +1 -0
- package/dist/backend/runtime-pack.test.js.map +1 -1
- package/dist/backend/targets.d.ts +5 -0
- package/dist/backend/targets.js +9 -0
- package/dist/backend/targets.js.map +1 -1
- package/dist/backend/targets.test.js +6 -1
- package/dist/backend/targets.test.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 +13 -0
- package/dist/coverage/surface-manifest.js.map +1 -1
- package/dist/diagnostics/diagnostic.d.ts +6 -5
- package/dist/diagnostics/diagnostic.js +10 -9
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/diagnostics/render.js.map +1 -1
- package/dist/executable/executable-cache.d.ts +1 -0
- package/dist/executable/executable-cache.js +1 -0
- package/dist/executable/executable-cache.js.map +1 -1
- package/dist/executable/executable-cache.test.js +1 -0
- package/dist/executable/executable-cache.test.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 +31 -0
- package/dist/frontend/lowering/containers/bytes.js +1105 -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 +16 -10
- 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 +40 -21
- package/dist/frontend/lowering/lower-builtins.js +611 -115
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +21 -10
- package/dist/frontend/lowering/lower-calls.js +516 -75
- 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 +147 -1475
- 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 +503 -2353
- 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 +10 -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 +60 -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 +10 -28
- package/dist/frontend/lowering/lower-stmts.js +542 -259
- 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 +41 -38
- package/dist/frontend/lowering/lowerer.js +148 -62
- 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/lowering/surfaces.d.ts +5 -3
- package/dist/frontend/lowering/surfaces.js +33 -13
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/npm-static-declarations.d.ts +35 -0
- package/dist/frontend/npm-static-declarations.js +519 -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 +132 -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 +513 -70
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/resolve.d.ts +26 -3
- package/dist/frontend/resolve.js +166 -29
- package/dist/frontend/resolve.js.map +1 -1
- package/dist/frontend/resolve.test.js +24 -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 +171 -16
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/index.js +11 -5
- package/dist/index.js.map +1 -1
- package/dist/ir/analysis.js +1 -0
- package/dist/ir/analysis.js.map +1 -1
- package/dist/ir/ir.d.ts +125 -52
- package/dist/ir/ir.js +136 -7
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/serialize.d.ts +1 -1
- package/dist/ir/serialize.js +1 -1
- package/dist/ir/validate.js +120 -63
- 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 +4 -4
- package/dist/library/int-infer.test.js.map +1 -1
- package/dist/library/library-cache.d.ts +1 -0
- package/dist/library/library-cache.js +1 -0
- package/dist/library/library-cache.js.map +1 -1
- package/dist/library/library-cache.test.js +18 -5
- package/dist/library/library-cache.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 +91 -20
|
@@ -1,20 +1,25 @@
|
|
|
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
|
|
4
5
|
* generic instantiation (bounded by MAX_GENERIC_INSTANCES). */
|
|
5
6
|
import * as ts from "../ts7/adapter.js";
|
|
6
7
|
import { lowerGenMethodCall } from "./lower-generators.js";
|
|
7
|
-
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
|
+
import { BIGINT_T, 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, lowerChildWriterMethodCall, lowerCreateRequireCall, lowerCryptoHashMethodCall, 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
|
|
@@ -3022,6 +3149,34 @@ export function lowerCall(lowerer, expr) {
|
|
|
3022
3149
|
// Provenance-checked like setTimeout; zero-arg forms are the JS
|
|
3023
3150
|
// constants ("", false, 0). `new String(...)` (wrapper objects) stays
|
|
3024
3151
|
// on the SC2020 fence.
|
|
3152
|
+
if (ts.isIdentifier(expr.expression) &&
|
|
3153
|
+
expr.expression.text === "BigInt" &&
|
|
3154
|
+
lowerer.isStdlibSymbol(lowerer.resolveValueSymbol(expr.expression) ?? undefined)) {
|
|
3155
|
+
if (expr.arguments.length !== 1) {
|
|
3156
|
+
lowerer.noLowering(`BigInt with ${expr.arguments.length} arguments`, expr);
|
|
3157
|
+
}
|
|
3158
|
+
const argNode = expr.arguments[0];
|
|
3159
|
+
const arg = lowerer.lowerExpr(argNode);
|
|
3160
|
+
if (arg.type.kind === "bigint")
|
|
3161
|
+
return arg;
|
|
3162
|
+
if (arg.type.kind === "string") {
|
|
3163
|
+
return { kind: "libCall", fn: "bigint.parse", args: [arg], type: BIGINT_T, loc };
|
|
3164
|
+
}
|
|
3165
|
+
if (arg.type.kind === "f64") {
|
|
3166
|
+
return { kind: "libCall", fn: "bigint.fromF64", args: [arg], type: BIGINT_T, loc };
|
|
3167
|
+
}
|
|
3168
|
+
if (arg.type.kind === "bool") {
|
|
3169
|
+
return {
|
|
3170
|
+
kind: "ternary",
|
|
3171
|
+
cond: arg,
|
|
3172
|
+
then: { kind: "libCall", fn: "bigint.parse", args: [{ kind: "strLit", value: "1", type: STRING, loc }], type: BIGINT_T, loc },
|
|
3173
|
+
else_: { kind: "libCall", fn: "bigint.parse", args: [{ kind: "strLit", value: "0", type: STRING, loc }], type: BIGINT_T, loc },
|
|
3174
|
+
type: BIGINT_T,
|
|
3175
|
+
loc,
|
|
3176
|
+
};
|
|
3177
|
+
}
|
|
3178
|
+
lowerer.noLowering(`BigInt of ${lowerer.fmt(arg.type)} values`, argNode, "string, number, boolean, and bigint arguments are supported");
|
|
3179
|
+
}
|
|
3025
3180
|
if (ts.isIdentifier(expr.expression) &&
|
|
3026
3181
|
(expr.expression.text === "String" ||
|
|
3027
3182
|
expr.expression.text === "Boolean" ||
|
|
@@ -3057,6 +3212,9 @@ export function lowerCall(lowerer, expr) {
|
|
|
3057
3212
|
const arg = lowerer.lowerExpr(argNode);
|
|
3058
3213
|
if (name === "String")
|
|
3059
3214
|
return lowerer.ensureString(arg, argNode);
|
|
3215
|
+
if (name === "Number" && arg.type.kind === "bigint") {
|
|
3216
|
+
return { kind: "libCall", fn: "bigint.toF64", args: [arg], type: F64, loc };
|
|
3217
|
+
}
|
|
3060
3218
|
if (arg.type.kind === "f64")
|
|
3061
3219
|
return arg;
|
|
3062
3220
|
if (arg.type.kind === "bool") {
|
|
@@ -3141,7 +3299,7 @@ export function lowerCall(lowerer, expr) {
|
|
|
3141
3299
|
!expr.expression.questionDotToken &&
|
|
3142
3300
|
!expr.questionDotToken &&
|
|
3143
3301
|
!expr.arguments.some((a) => ts.isSpreadElement(a))) {
|
|
3144
|
-
const recvProbe =
|
|
3302
|
+
const recvProbe = tryLowerExpression(lowerer, expr.expression.expression);
|
|
3145
3303
|
if (recvProbe?.type.kind === "dyn") {
|
|
3146
3304
|
const args = expr.arguments.map((a) => lowerer.lowerExprExpecting(a, DYN));
|
|
3147
3305
|
return {
|
|
@@ -3287,6 +3445,9 @@ export function lowerCall(lowerer, expr) {
|
|
|
3287
3445
|
const cryptoServed = lowerer.lowerCryptoModuleCall(expr, bi, loc);
|
|
3288
3446
|
if (cryptoServed)
|
|
3289
3447
|
return cryptoServed;
|
|
3448
|
+
const timersInterval = lowerer.lowerTimersPromisesSetInterval(expr, bi, loc);
|
|
3449
|
+
if (timersInterval)
|
|
3450
|
+
return timersInterval;
|
|
3290
3451
|
const builtinFn = builtinModuleFnOf(lowerer, bi.module, bi.member);
|
|
3291
3452
|
if (!builtinFn) {
|
|
3292
3453
|
// Typed by @types/node (the fallback declarations only declare
|
|
@@ -3442,7 +3603,7 @@ export function lowerCall(lowerer, expr) {
|
|
|
3442
3603
|
return parsed;
|
|
3443
3604
|
}
|
|
3444
3605
|
}
|
|
3445
|
-
const probed =
|
|
3606
|
+
const probed = tryLowerExpression(lowerer, expr.arguments[0]);
|
|
3446
3607
|
if (name === "parseFloat" && probed?.type.kind === "string") {
|
|
3447
3608
|
return { kind: "libCall", fn: "num.parseFloat", args: [probed], type: F64, loc };
|
|
3448
3609
|
}
|
|
@@ -3756,12 +3917,12 @@ export function lowerCall(lowerer, expr) {
|
|
|
3756
3917
|
return { kind: "callValue", callee, args, type: callee.type.ret, loc };
|
|
3757
3918
|
}
|
|
3758
3919
|
if (ts.isPropertyAccessExpression(expr.expression)) {
|
|
3759
|
-
const intrinsic =
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3920
|
+
const intrinsic = fenceNodeModuleMutationCall(lowerer, expr, expr.expression) ??
|
|
3921
|
+
// Builtin namespace imports first (`fs.readFileSync(...)` where fs
|
|
3922
|
+
// is `import * as fs from "node:fs"`): the same tables and fences
|
|
3923
|
+
// as named builtin imports — before anything below tries to lower
|
|
3924
|
+
// the namespace object itself as a receiver.
|
|
3925
|
+
lowerer.lowerNamespaceBuiltinCall(expr, expr.expression) ??
|
|
3765
3926
|
// The node:perf_hooks spoke: performance.now() and its
|
|
3766
3927
|
// .bind(performance) function value over the runtime's
|
|
3767
3928
|
// process-start-anchored monotonic clock.
|
|
@@ -3792,10 +3953,12 @@ export function lowerCall(lowerer, expr) {
|
|
|
3792
3953
|
lowerer.lowerUrlMethodCall(expr, expr.expression) ??
|
|
3793
3954
|
lowerer.lowerSearchParamsMethodCall(expr, expr.expression) ??
|
|
3794
3955
|
lowerer.lowerStatsMethodCall(expr, expr.expression) ??
|
|
3956
|
+
lowerCryptoHashMethodCall(lowerer, expr, expr.expression) ??
|
|
3795
3957
|
lowerFileHandleMethodCall(lowerer, expr, expr.expression) ??
|
|
3796
3958
|
lowerer.lowerChildMethodCall(expr, expr.expression) ??
|
|
3797
3959
|
// Piped child-output stream receivers — on/once("data" | "end").
|
|
3798
3960
|
lowerChildStreamMethodCall(lowerer, expr, expr.expression) ??
|
|
3961
|
+
lowerChildWriterMethodCall(lowerer, expr, expr.expression) ??
|
|
3799
3962
|
// First-class process-stream receivers — write(data).
|
|
3800
3963
|
lowerProcStreamMethodCall(lowerer, expr, expr.expression) ??
|
|
3801
3964
|
// FSWatcher receivers — close() (fs.watch's handle).
|
|
@@ -3878,6 +4041,8 @@ export function lowerCall(lowerer, expr) {
|
|
|
3878
4041
|
// by the receiver's own element.
|
|
3879
4042
|
lowerer.lowerFilterNarrowCall(expr, expr.expression) ??
|
|
3880
4043
|
lowerArrayIsArrayCall(lowerer, expr, expr.expression) ??
|
|
4044
|
+
lowerBigIntStaticCall(lowerer, expr, expr.expression) ??
|
|
4045
|
+
lowerBigIntMethodCall(lowerer, expr, expr.expression) ??
|
|
3881
4046
|
lowerSymbolStaticCall(lowerer, expr, expr.expression) ??
|
|
3882
4047
|
lowerSymbolMethodCall(lowerer, expr, expr.expression) ??
|
|
3883
4048
|
lowerRegExpStaticCall(lowerer, expr, expr.expression) ??
|
|
@@ -4379,7 +4544,7 @@ function lowerDynReceiverMethodCall(lowerer, call, access) {
|
|
|
4379
4544
|
// evolving `let h = {}` object flowing back out of a JS helper —
|
|
4380
4545
|
// tsc types the return by the evolved shape, the binding lowered
|
|
4381
4546
|
// dyn): probe the lowering and claim exactly the dyn results.
|
|
4382
|
-
const probed =
|
|
4547
|
+
const probed = tryLowerExpression(lowerer, access.expression);
|
|
4383
4548
|
if (probed?.type.kind !== "dyn")
|
|
4384
4549
|
return null;
|
|
4385
4550
|
recv = probed;
|
|
@@ -4572,6 +4737,71 @@ export function lowerDynDispatchMethodCall(lowerer, call, access, recv, arrayRec
|
|
|
4572
4737
|
if (arrayReceiver && predicate?.type.kind === "func" && predicate.type.ret.kind === "void") {
|
|
4573
4738
|
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
4739
|
}
|
|
4740
|
+
// A dynamic argument array consumed immediately by the fixed-arity arrow
|
|
4741
|
+
// apply lowering below never exposes its surplus tail. Keep a pushed
|
|
4742
|
+
// static-only value's evaluation and the array length mutation, but store
|
|
4743
|
+
// undefined in that unobserved slot so no impossible dyn conversion is
|
|
4744
|
+
// invented. If the slot falls inside the typed prefix, its dynCheck fails
|
|
4745
|
+
// at the callback boundary; valid callers preserve the original prefix.
|
|
4746
|
+
if (method === "push" &&
|
|
4747
|
+
call.arguments.length === 1 &&
|
|
4748
|
+
ts.isIdentifier(access.expression) &&
|
|
4749
|
+
ts.isExpressionStatement(call.parent) &&
|
|
4750
|
+
ts.isBlock(call.parent.parent)) {
|
|
4751
|
+
const receiverSymbol = lowerer.checker.getSymbolAtLocation(access.expression);
|
|
4752
|
+
const block = call.parent.parent;
|
|
4753
|
+
const statementIndex = block.statements.indexOf(call.parent);
|
|
4754
|
+
const next = statementIndex >= 0 ? block.statements[statementIndex + 1] : undefined;
|
|
4755
|
+
let returned = next && ts.isReturnStatement(next) ? next.expression : undefined;
|
|
4756
|
+
while (returned && ts.isParenthesizedExpression(returned))
|
|
4757
|
+
returned = returned.expression;
|
|
4758
|
+
const apply = returned && ts.isCallExpression(returned) &&
|
|
4759
|
+
ts.isPropertyAccessExpression(returned.expression) &&
|
|
4760
|
+
returned.expression.name.text === "apply"
|
|
4761
|
+
? returned
|
|
4762
|
+
: null;
|
|
4763
|
+
const argsNode = apply?.arguments[1];
|
|
4764
|
+
const sameArgs = receiverSymbol !== undefined &&
|
|
4765
|
+
argsNode !== undefined &&
|
|
4766
|
+
ts.isIdentifier(argsNode) &&
|
|
4767
|
+
lowerer.checker.getSymbolAtLocation(argsNode) === receiverSymbol;
|
|
4768
|
+
const applyAccess = apply && ts.isPropertyAccessExpression(apply.expression)
|
|
4769
|
+
? apply.expression
|
|
4770
|
+
: null;
|
|
4771
|
+
const applyTarget = applyAccess?.expression;
|
|
4772
|
+
const arrow = applyTarget ? arrowSignatureOf(lowerer, applyTarget) : null;
|
|
4773
|
+
const target = applyTarget && ts.isIdentifier(applyTarget)
|
|
4774
|
+
? lowerer.peekLocal(applyTarget)
|
|
4775
|
+
: null;
|
|
4776
|
+
const targetParams = target?.type.kind === "func" && target.type.rest !== true
|
|
4777
|
+
? target.type.params
|
|
4778
|
+
: null;
|
|
4779
|
+
if (sameArgs && arrow !== null && targetParams !== null &&
|
|
4780
|
+
targetParams.every((param) => canDynCheckTo(param, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id)))) {
|
|
4781
|
+
const value = lowerer.lowerExpr(call.arguments[0]);
|
|
4782
|
+
if (value.type.kind !== "dyn" && !lowerer.dynConvertible(value.type)) {
|
|
4783
|
+
const saved = lowerer.declareHiddenLocal("%applyTail", DYN);
|
|
4784
|
+
return {
|
|
4785
|
+
kind: "seqExpr",
|
|
4786
|
+
stmts: [
|
|
4787
|
+
{ kind: "varDecl", localId: saved.id, init: recv, loc: locOf(access.expression) },
|
|
4788
|
+
{ kind: "exprStmt", expr: value, loc: value.loc },
|
|
4789
|
+
],
|
|
4790
|
+
result: {
|
|
4791
|
+
kind: "dynInvoke",
|
|
4792
|
+
recv: { kind: "varRef", localId: saved.id, type: DYN, loc: locOf(access.expression) },
|
|
4793
|
+
method,
|
|
4794
|
+
calleeName: access.getText(),
|
|
4795
|
+
args: [dynUndefinedExpr(locOf(call.arguments[0]))],
|
|
4796
|
+
type: DYN,
|
|
4797
|
+
loc: locOf(call),
|
|
4798
|
+
},
|
|
4799
|
+
type: DYN,
|
|
4800
|
+
loc: locOf(call),
|
|
4801
|
+
};
|
|
4802
|
+
}
|
|
4803
|
+
}
|
|
4804
|
+
}
|
|
4575
4805
|
const args = call.arguments.map((arg, i) => i === 0 && predicate ? lowerer.coerceInto(arg, predicate, DYN) : lowerer.lowerExprExpecting(arg, DYN));
|
|
4576
4806
|
return {
|
|
4577
4807
|
kind: "dynInvoke",
|
|
@@ -4924,7 +5154,7 @@ function lowerPrimitiveProtoCall(lowerer, call, recv, name, memberSym) {
|
|
|
4924
5154
|
// optional number selects 0 at runtime through the same narrowed
|
|
4925
5155
|
// nullish IR used by `digits ?? 0`.
|
|
4926
5156
|
const zero = { kind: "numLit", value: 0, type: F64, loc: digits.loc };
|
|
4927
|
-
const defaultUnitDigits = (value) =>
|
|
5157
|
+
const defaultUnitDigits = (value) => isSafeToDiscard(value)
|
|
4928
5158
|
? zero
|
|
4929
5159
|
: {
|
|
4930
5160
|
kind: "seqExpr",
|
|
@@ -5010,6 +5240,46 @@ function lowerPrimitiveProtoCall(lowerer, call, recv, name, memberSym) {
|
|
|
5010
5240
|
return null;
|
|
5011
5241
|
return { kind: "boolLit", value: false, type: BOOL, loc };
|
|
5012
5242
|
}
|
|
5243
|
+
/** The uniquely arity-selected overload on an implicit-any receiver whose
|
|
5244
|
+
* active monomorphization supplies a concrete type. The checker resolved
|
|
5245
|
+
* the original call through `any`, so getResolvedSignature cannot name
|
|
5246
|
+
* the declaration-authored overload; typeOf carries the instance's real
|
|
5247
|
+
* receiver type. Restricting the fallback to exactly one bodyless
|
|
5248
|
+
* signature at this arity avoids recreating TypeScript's overload
|
|
5249
|
+
* resolution for same-arity type distinctions. */
|
|
5250
|
+
function implicitReceiverOverloadReturn(lowerer, expr) {
|
|
5251
|
+
if (!ts.isCallExpression(expr) ||
|
|
5252
|
+
!ts.isPropertyAccessExpression(expr.expression) ||
|
|
5253
|
+
expr.arguments.some(ts.isSpreadElement)) {
|
|
5254
|
+
return null;
|
|
5255
|
+
}
|
|
5256
|
+
const access = expr.expression;
|
|
5257
|
+
const original = lowerer.checker.getTypeAtLocation(access.expression);
|
|
5258
|
+
if ((original.flags & ts.TypeFlags.Any) === 0)
|
|
5259
|
+
return null;
|
|
5260
|
+
const effective = lowerer.typeOf(access.expression);
|
|
5261
|
+
if ((effective.flags & ts.TypeFlags.Any) !== 0)
|
|
5262
|
+
return null;
|
|
5263
|
+
const member = lowerer.checker.getPropertyOfType(effective, access.name.text);
|
|
5264
|
+
if (!member)
|
|
5265
|
+
return null;
|
|
5266
|
+
const signatures = lowerer.checker.getCallSignatures(lowerer.checker.getTypeOfSymbol(member));
|
|
5267
|
+
const matches = signatures.filter((signature) => {
|
|
5268
|
+
const decl = lowerer.checker.signatureDeclaration(signature);
|
|
5269
|
+
if (!decl ||
|
|
5270
|
+
!(ts.isFunctionDeclaration(decl) || ts.isMethodDeclaration(decl)) ||
|
|
5271
|
+
decl.body) {
|
|
5272
|
+
return false;
|
|
5273
|
+
}
|
|
5274
|
+
const params = decl.parameters.filter((param) => !isThisParameter(param));
|
|
5275
|
+
const required = params.filter((param) => !param.questionToken && !param.initializer && !param.dotDotDotToken).length;
|
|
5276
|
+
const maximum = params.some((param) => param.dotDotDotToken) ? Infinity : params.length;
|
|
5277
|
+
return expr.arguments.length >= required && expr.arguments.length <= maximum;
|
|
5278
|
+
});
|
|
5279
|
+
if (matches.length !== 1)
|
|
5280
|
+
return null;
|
|
5281
|
+
return lowerer.mapTypeOf(lowerer.checker.getReturnTypeOfSignature(matches[0]));
|
|
5282
|
+
}
|
|
5013
5283
|
/** Reconciles a direct call's recorded type with the checker's answer at
|
|
5014
5284
|
* the site when the callee is OVERLOADED: tsc resolved the call against
|
|
5015
5285
|
* one overload SIGNATURE, so every downstream lowering sees that
|
|
@@ -5029,10 +5299,12 @@ function lowerPrimitiveProtoCall(lowerer, call, recv, name, memberSym) {
|
|
|
5029
5299
|
function reconcileOverloadReturn(lowerer, expr, call) {
|
|
5030
5300
|
const rsig = lowerer.checker.getResolvedSignature(expr);
|
|
5031
5301
|
const rdecl = rsig ? lowerer.checker.signatureDeclaration(rsig) : undefined;
|
|
5032
|
-
|
|
5033
|
-
|
|
5034
|
-
|
|
5035
|
-
|
|
5302
|
+
const resolvedOverload = rsig && rdecl &&
|
|
5303
|
+
(ts.isFunctionDeclaration(rdecl) || ts.isMethodDeclaration(rdecl)) &&
|
|
5304
|
+
!rdecl.body
|
|
5305
|
+
? lowerer.mapTypeOf(lowerer.checker.getReturnTypeOfSignature(rsig))
|
|
5306
|
+
: null;
|
|
5307
|
+
const rt = resolvedOverload ?? implicitReceiverOverloadReturn(lowerer, expr);
|
|
5036
5308
|
// Unmappable, void, or unit resolved returns keep the implementation's
|
|
5037
5309
|
// type: a discarded result never looks, a USED one meets its use
|
|
5038
5310
|
// site's own mapping (and that site's honest fences). Unit narrowing
|
|
@@ -5290,19 +5562,38 @@ export function isTopLevelFnSymbol(lowerer, ident) {
|
|
|
5290
5562
|
ts.isFunctionDeclaration(decl) &&
|
|
5291
5563
|
(ts.isSourceFile(decl.parent) || lowerer.nsBlocks.get(decl.parent) === "flattened"));
|
|
5292
5564
|
}
|
|
5293
|
-
/** Nested `function name(...) {...}`:
|
|
5294
|
-
*
|
|
5295
|
-
*
|
|
5296
|
-
*
|
|
5297
|
-
*
|
|
5298
|
-
*
|
|
5565
|
+
/** Nested `function name(...) {...}`: declare the mutable function binding
|
|
5566
|
+
* before lowering its body, then initialize it with the lifted closure.
|
|
5567
|
+
* The early declaration is observable only when another nested closure
|
|
5568
|
+
* captures the binding: its box must exist before either side of a mutual
|
|
5569
|
+
* recursion cycle builds its closure. Forward source references use the
|
|
5570
|
+
* same split declaration/assignment through predeclareForwardFnDecl.
|
|
5571
|
+
* Self-references inside the body lower to `selfRef`, not a capture: a box
|
|
5572
|
+
* holding its own closure would be an RC cycle. */
|
|
5299
5573
|
export function lowerNestedFunctionDecl(lowerer, stmt) {
|
|
5300
5574
|
if (!stmt.name)
|
|
5301
5575
|
lowerer.unsupported("SC1090", stmt, "anonymous function declarations");
|
|
5302
5576
|
const { funcType } = lowerer.lambdaSignature(stmt);
|
|
5303
|
-
|
|
5577
|
+
// Function declaration bindings are mutable in JavaScript. More
|
|
5578
|
+
// importantly, putting the empty slot into the owning statement list
|
|
5579
|
+
// BEFORE lowerLambda lets a sibling lowered from that body capture this
|
|
5580
|
+
// local's eventual box. The local object may become boxed while either
|
|
5581
|
+
// body lowers; backends inspect its final shape when emitting varDecl.
|
|
5582
|
+
const local = lowerer.declareLocal(stmt.name, stmt.name.text, funcType, true);
|
|
5583
|
+
let declared = false;
|
|
5584
|
+
for (let i = lowerer.activeStmtLists.length - 1; i >= 0; i--) {
|
|
5585
|
+
const entry = lowerer.activeStmtLists[i];
|
|
5586
|
+
if (entry.ctx !== lowerer.ctx || !entry.stmts.includes(stmt))
|
|
5587
|
+
continue;
|
|
5588
|
+
entry.out.push({ kind: "varDecl", localId: local.id, init: null, loc: locOf(stmt) });
|
|
5589
|
+
declared = true;
|
|
5590
|
+
break;
|
|
5591
|
+
}
|
|
5592
|
+
if (!declared) {
|
|
5593
|
+
throw new InternalCompilerError("lowerer bug: nested function declaration has no active statement list");
|
|
5594
|
+
}
|
|
5304
5595
|
const init = lowerer.lowerLambda(stmt);
|
|
5305
|
-
return { kind: "
|
|
5596
|
+
return { kind: "assign", localId: local.id, value: init, loc: locOf(stmt) };
|
|
5306
5597
|
}
|
|
5307
5598
|
/** Signature checks + param shapes + IR func type for any lambda-like
|
|
5308
5599
|
* node. The func type's params are the ABI types, so a lambda with
|
|
@@ -5312,10 +5603,6 @@ export function lowerNestedFunctionDecl(lowerer, stmt) {
|
|
|
5312
5603
|
export function lambdaSignature(lowerer, node) {
|
|
5313
5604
|
if (!node.body)
|
|
5314
5605
|
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
5606
|
if (node.typeParameters) {
|
|
5320
5607
|
// Generic function-like forms monomorphize only where a static home
|
|
5321
5608
|
// exists: top-level generic function declarations, generic methods
|
|
@@ -5486,13 +5773,14 @@ export function lowerLambda(lowerer, node) {
|
|
|
5486
5773
|
// the lifted body returns the inner T (a `return v` fulfills with v).
|
|
5487
5774
|
const isAsync = !ts.isAccessor(node) &&
|
|
5488
5775
|
node.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword) === true;
|
|
5489
|
-
|
|
5776
|
+
const isGenerator = node.asteriskToken !== undefined;
|
|
5777
|
+
if (isAsync && !isGenerator && funcType.ret.kind !== "promise")
|
|
5490
5778
|
lowerer.badType(node, lowerer.typeOf(node));
|
|
5491
5779
|
// Generator lambdas (function* expressions and object-literal
|
|
5492
5780
|
// *methods): the VALUE's type returns the generator; the lifted body
|
|
5493
5781
|
// returns the TReturn channel (a `return v` is the done-value).
|
|
5494
|
-
|
|
5495
|
-
|
|
5782
|
+
if (isGenerator &&
|
|
5783
|
+
(funcType.ret.kind !== "generator" || (funcType.ret.async === true) !== isAsync))
|
|
5496
5784
|
lowerer.badType(node, lowerer.typeOf(node));
|
|
5497
5785
|
const bodyReturn = isGenerator
|
|
5498
5786
|
? lowerer.genBodyReturnType(funcType.ret)
|
|
@@ -5500,7 +5788,7 @@ export function lowerLambda(lowerer, node) {
|
|
|
5500
5788
|
const fnCtx = newFnCtx(true, selfSymbol, funcType, bodyReturn);
|
|
5501
5789
|
fnCtx.isAsync = isAsync;
|
|
5502
5790
|
if (isGenerator && funcType.ret.kind === "generator") {
|
|
5503
|
-
fnCtx.generator =
|
|
5791
|
+
fnCtx.generator = generatorMeta(lowerer, funcType.ret);
|
|
5504
5792
|
}
|
|
5505
5793
|
const diagsBefore = lowerer.diags.length;
|
|
5506
5794
|
lowerer.fnStack.push(fnCtx);
|
|
@@ -5531,11 +5819,13 @@ export function lowerLambda(lowerer, node) {
|
|
|
5531
5819
|
// the validator's bare-unitLit rule (typeCheckReturnExpression).
|
|
5532
5820
|
// A `void e` body rides the statement lowering (the value is
|
|
5533
5821
|
// discarded here, so the operand evaluates for effect alone —
|
|
5534
|
-
// `(name) => void doThing(name)`, the fire-and-forget arrow).
|
|
5822
|
+
// `(name) => void doThing(name)`, the fire-and-forget arrow). A
|
|
5823
|
+
// conditional body does the same so its void arms become lazy
|
|
5824
|
+
// statement branches instead of a forbidden void-valued ternary.
|
|
5535
5825
|
let stripped = bodyExpr;
|
|
5536
5826
|
while (ts.isParenthesizedExpression(stripped))
|
|
5537
5827
|
stripped = stripped.expression;
|
|
5538
|
-
if (ts.isVoidExpression(stripped)) {
|
|
5828
|
+
if (ts.isVoidExpression(stripped) || ts.isConditionalExpression(stripped)) {
|
|
5539
5829
|
body = [lowerer.lowerExprStatement(stripped)];
|
|
5540
5830
|
}
|
|
5541
5831
|
else {
|
|
@@ -6535,6 +6825,48 @@ function lowerSymbolStaticCall(lowerer, call, access) {
|
|
|
6535
6825
|
}
|
|
6536
6826
|
lowerer.unsupported("SC1090", call, `well-known symbols as values (Symbol.${member} — for-of, iteration protocols, and template literals compile through their language constructs; the reified symbol has no static lowering)`);
|
|
6537
6827
|
}
|
|
6828
|
+
function lowerBigIntStaticCall(lowerer, call, access) {
|
|
6829
|
+
if (call.questionDotToken || access.questionDotToken)
|
|
6830
|
+
return null;
|
|
6831
|
+
if (!lowerer.isStdlibGlobal(access.expression, "BigInt"))
|
|
6832
|
+
return null;
|
|
6833
|
+
const name = access.name.text;
|
|
6834
|
+
if (name !== "asUintN" && name !== "asIntN")
|
|
6835
|
+
return null;
|
|
6836
|
+
if (call.arguments.length !== 2) {
|
|
6837
|
+
lowerer.noLowering(`BigInt.${name} with ${call.arguments.length} arguments`, call);
|
|
6838
|
+
}
|
|
6839
|
+
const loc = locOf(call);
|
|
6840
|
+
const bits = lowerer.lowerExprExpecting(call.arguments[0], F64);
|
|
6841
|
+
const value = lowerer.lowerExprExpecting(call.arguments[1], BIGINT_T);
|
|
6842
|
+
return {
|
|
6843
|
+
kind: "libCall",
|
|
6844
|
+
fn: name === "asUintN" ? "bigint.asUintN" : "bigint.asIntN",
|
|
6845
|
+
args: [bits, value],
|
|
6846
|
+
type: BIGINT_T,
|
|
6847
|
+
loc,
|
|
6848
|
+
};
|
|
6849
|
+
}
|
|
6850
|
+
function lowerBigIntMethodCall(lowerer, call, access) {
|
|
6851
|
+
if (lowerer.mapTypeOf(lowerer.typeOf(access.expression))?.kind !== "bigint")
|
|
6852
|
+
return null;
|
|
6853
|
+
if (!lowerer.isStdlibMember(access))
|
|
6854
|
+
return null;
|
|
6855
|
+
const name = access.name.text;
|
|
6856
|
+
const loc = locOf(call);
|
|
6857
|
+
const receiver = lowerer.lowerExpr(access.expression);
|
|
6858
|
+
if (receiver.type.kind !== "bigint")
|
|
6859
|
+
return null;
|
|
6860
|
+
if (name === "valueOf" && call.arguments.length === 0)
|
|
6861
|
+
return receiver;
|
|
6862
|
+
if (name === "toString" && call.arguments.length <= 1) {
|
|
6863
|
+
const radix = call.arguments[0]
|
|
6864
|
+
? lowerer.lowerExprExpecting(call.arguments[0], F64)
|
|
6865
|
+
: { kind: "numLit", value: 10, type: F64, loc };
|
|
6866
|
+
return { kind: "libCall", fn: "bigint.toString", args: [receiver, radix], type: STRING, loc };
|
|
6867
|
+
}
|
|
6868
|
+
return null;
|
|
6869
|
+
}
|
|
6538
6870
|
/** Method calls on symbol-typed receivers: `.toString()` is the
|
|
6539
6871
|
* "Symbol(desc)" text (Node's Symbol.prototype.toString — note that
|
|
6540
6872
|
* template literals and concatenation THROW in JS and stay fenced;
|
|
@@ -6842,7 +7174,7 @@ function lowerIntlNumberFormatCall(lowerer, call, access) {
|
|
|
6842
7174
|
function objectIsDisjointFalse(left, right, loc) {
|
|
6843
7175
|
const stmts = [];
|
|
6844
7176
|
for (const e of [left, right]) {
|
|
6845
|
-
if (!
|
|
7177
|
+
if (!isSafeToDiscard(e))
|
|
6846
7178
|
stmts.push({ kind: "exprStmt", expr: e, loc });
|
|
6847
7179
|
}
|
|
6848
7180
|
const answer = { kind: "boolLit", value: false, type: BOOL, loc };
|
|
@@ -6856,6 +7188,9 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
6856
7188
|
if (!lowerer.isStdlibGlobal(access.expression, "Object"))
|
|
6857
7189
|
return null;
|
|
6858
7190
|
const member = access.name.text;
|
|
7191
|
+
const cacheKeys = lowerRequireCacheKeys(lowerer, call, member);
|
|
7192
|
+
if (cacheKeys)
|
|
7193
|
+
return cacheKeys;
|
|
6859
7194
|
// Object.is — the spec's SameValue over the static kinds. Number
|
|
6860
7195
|
// pairs take the runtime SameValue (NaN equals NaN, +0 differs from
|
|
6861
7196
|
// -0 — the two divergences from ===); every other supported pair
|
|
@@ -7046,8 +7381,8 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
7046
7381
|
// the explicit-undefined-is-absent stance). Everything else keeps
|
|
7047
7382
|
// the spread hint.
|
|
7048
7383
|
if (call.arguments.length === 2 && !call.arguments.some((a) => ts.isSpreadElement(a))) {
|
|
7049
|
-
const tProbe =
|
|
7050
|
-
const sProbe =
|
|
7384
|
+
const tProbe = tryLowerExpression(lowerer, call.arguments[0]);
|
|
7385
|
+
const sProbe = tryLowerExpression(lowerer, call.arguments[1]);
|
|
7051
7386
|
// CHECKED-DYNAMIC target and source (the JS file-scope
|
|
7052
7387
|
// object-literal identity story): the runtime dyn copy — own
|
|
7053
7388
|
// members of the source land on the target, which returns.
|
|
@@ -7105,7 +7440,7 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
7105
7440
|
while (ts.isParenthesizedExpression(targetNode))
|
|
7106
7441
|
targetNode = targetNode.expression;
|
|
7107
7442
|
const freshLiteralTarget = ts.isObjectLiteralExpression(targetNode);
|
|
7108
|
-
const tProbe = freshLiteralTarget ? null :
|
|
7443
|
+
const tProbe = freshLiteralTarget ? null : tryLowerExpression(lowerer, call.arguments[0]);
|
|
7109
7444
|
const tKind = tProbe?.type.kind;
|
|
7110
7445
|
if (freshLiteralTarget || tKind === "dyn" || tKind === "nullT" || tKind === "undefinedT") {
|
|
7111
7446
|
const loc = locOf(call);
|
|
@@ -7177,7 +7512,7 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
7177
7512
|
// static shapes have no property table to extend.
|
|
7178
7513
|
if (member === "defineProperties" && call.arguments.length === 2 &&
|
|
7179
7514
|
!call.arguments.some((a) => ts.isSpreadElement(a))) {
|
|
7180
|
-
let target =
|
|
7515
|
+
let target = tryLowerExpression(lowerer, call.arguments[0]);
|
|
7181
7516
|
// A FUNCTION-typed target boxes through the dyn boundary: the
|
|
7182
7517
|
// property table lives on the CLOSURE (shared by every box of this
|
|
7183
7518
|
// function value), so defining through a fresh box sticks — the
|
|
@@ -7232,7 +7567,7 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
7232
7567
|
if (member === "hasOwn" && call.arguments.length === 2 && !call.arguments.some((a) => ts.isSpreadElement(a))) {
|
|
7233
7568
|
const recvNode = call.arguments[0];
|
|
7234
7569
|
const keyNode = call.arguments[1];
|
|
7235
|
-
const probed =
|
|
7570
|
+
const probed = tryLowerExpression(lowerer, recvNode);
|
|
7236
7571
|
// A CHECKED-DYNAMIC receiver (the JS file-scope object-literal
|
|
7237
7572
|
// identity story): the runtime dyn probe — OBJ member presence, ARR
|
|
7238
7573
|
// index bounds, Node's ToObject TypeError on nullish.
|
|
@@ -7278,7 +7613,7 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
7278
7613
|
// runtime walks the dyn node's own keys (integer-like keys first,
|
|
7279
7614
|
// JS's own-key order) and answers a dyn array.
|
|
7280
7615
|
{
|
|
7281
|
-
const probed =
|
|
7616
|
+
const probed = tryLowerExpression(lowerer, argNode);
|
|
7282
7617
|
const isDyn = probed?.type.kind === "dyn";
|
|
7283
7618
|
// Unit-typed arguments (Object.keys(null)) ride the same runtime
|
|
7284
7619
|
// walk: it throws Node's catchable TypeError.
|
|
@@ -7296,7 +7631,7 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
7296
7631
|
// record (the narrowed export-table literal) — the lowered value's
|
|
7297
7632
|
// shape is the honest dispatch key, exactly the identity-Set stance.
|
|
7298
7633
|
if (argIr === null && isJsSourceFile(argNode.getSourceFile())) {
|
|
7299
|
-
const probed =
|
|
7634
|
+
const probed = tryLowerExpression(lowerer, argNode);
|
|
7300
7635
|
if (probed?.type.kind === "record")
|
|
7301
7636
|
argIr = probed.type;
|
|
7302
7637
|
}
|
|
@@ -8337,6 +8672,69 @@ const SP_BRAND_METHODS = new Set([
|
|
|
8337
8672
|
"append", "delete", "get", "getAll", "has", "set", "sort",
|
|
8338
8673
|
"forEach", "keys", "values", "entries", "toString",
|
|
8339
8674
|
]);
|
|
8675
|
+
function arrowSignatureOf(lowerer, node) {
|
|
8676
|
+
const signatures = lowerer.checker.getCallSignatures(lowerer.typeOf(node));
|
|
8677
|
+
if (signatures.length !== 1)
|
|
8678
|
+
return null;
|
|
8679
|
+
const declaration = lowerer.checker.signatureDeclaration(signatures[0]);
|
|
8680
|
+
return declaration !== undefined && ts.isArrowFunction(declaration) ? signatures[0] : null;
|
|
8681
|
+
}
|
|
8682
|
+
/** `arrow.apply(thisArg, dynArgs)` for a fixed-arity compiled arrow. Arrows
|
|
8683
|
+
* ignore `thisArg` and surplus arguments by language definition; declared
|
|
8684
|
+
* parameters validate from the dynamic array in order. */
|
|
8685
|
+
function lowerArrowFunctionApply(lowerer, call, access) {
|
|
8686
|
+
if (access.name.text !== "apply" ||
|
|
8687
|
+
call.arguments.length !== 2 ||
|
|
8688
|
+
call.arguments.some(ts.isSpreadElement) ||
|
|
8689
|
+
arrowSignatureOf(lowerer, access.expression) === null) {
|
|
8690
|
+
return null;
|
|
8691
|
+
}
|
|
8692
|
+
const callee = lowerer.lowerExpr(access.expression);
|
|
8693
|
+
if (callee.type.kind !== "func" || callee.type.rest === true)
|
|
8694
|
+
return null;
|
|
8695
|
+
if (!callee.type.params.every((param) => canDynCheckTo(param, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id)))) {
|
|
8696
|
+
return null;
|
|
8697
|
+
}
|
|
8698
|
+
const argsList = lowerer.lowerExpr(call.arguments[1]);
|
|
8699
|
+
if (argsList.type.kind !== "dyn")
|
|
8700
|
+
return null;
|
|
8701
|
+
const loc = locOf(call);
|
|
8702
|
+
const savedCallee = lowerer.declareHiddenLocal("%applyFn", callee.type);
|
|
8703
|
+
const savedArgs = lowerer.declareHiddenLocal("%applyArgs", DYN);
|
|
8704
|
+
const stmts = [
|
|
8705
|
+
{ kind: "varDecl", localId: savedCallee.id, init: callee, loc },
|
|
8706
|
+
{ kind: "exprStmt", expr: lowerer.lowerExpr(call.arguments[0]), loc },
|
|
8707
|
+
{ kind: "varDecl", localId: savedArgs.id, init: argsList, loc },
|
|
8708
|
+
];
|
|
8709
|
+
const args = callee.type.params.map((param, index) => {
|
|
8710
|
+
const read = {
|
|
8711
|
+
kind: "dynKeyGet",
|
|
8712
|
+
key: { kind: "strLit", value: String(index), type: STRING, loc },
|
|
8713
|
+
value: { kind: "varRef", localId: savedArgs.id, type: DYN, loc },
|
|
8714
|
+
type: DYN,
|
|
8715
|
+
loc,
|
|
8716
|
+
};
|
|
8717
|
+
return lowerer.coerceInto(call.arguments[1], read, param);
|
|
8718
|
+
});
|
|
8719
|
+
const invoked = {
|
|
8720
|
+
kind: "callValue",
|
|
8721
|
+
callee: { kind: "varRef", localId: savedCallee.id, type: callee.type, loc },
|
|
8722
|
+
args,
|
|
8723
|
+
type: callee.type.ret,
|
|
8724
|
+
loc,
|
|
8725
|
+
};
|
|
8726
|
+
let result;
|
|
8727
|
+
if (invoked.type.kind === "void") {
|
|
8728
|
+
stmts.push({ kind: "exprStmt", expr: invoked, loc });
|
|
8729
|
+
result = dynUndefinedExpr(loc);
|
|
8730
|
+
}
|
|
8731
|
+
else {
|
|
8732
|
+
result = lowerer.coerceInto(call, invoked, DYN);
|
|
8733
|
+
if (result.type.kind !== "dyn")
|
|
8734
|
+
return null;
|
|
8735
|
+
}
|
|
8736
|
+
return { kind: "seqExpr", stmts, result, type: DYN, loc };
|
|
8737
|
+
}
|
|
8340
8738
|
function lowerObjLitGenericMethodCall(lowerer, call, access) {
|
|
8341
8739
|
if (lowerer.chainBlocked(access, call))
|
|
8342
8740
|
return null;
|
|
@@ -8398,6 +8796,9 @@ function lowerObjLitGenericMethodCall(lowerer, call, access) {
|
|
|
8398
8796
|
}
|
|
8399
8797
|
const found = objLitGenericFnNodeOf(lowerer, propSym);
|
|
8400
8798
|
if (!found) {
|
|
8799
|
+
const arrowApply = lowerArrowFunctionApply(lowerer, call, access);
|
|
8800
|
+
if (arrowApply !== null)
|
|
8801
|
+
return arrowApply;
|
|
8401
8802
|
// Function.prototype.apply/call/bind spelled through a FUNCTION
|
|
8402
8803
|
// receiver: compiled functions are direct calls with no runtime
|
|
8403
8804
|
// `this`/arguments object to re-route — name the working spelling
|
|
@@ -8444,9 +8845,32 @@ function lowerObjLitGenericMethodCall(lowerer, call, access) {
|
|
|
8444
8845
|
export function lowerObjectMethodCall(lowerer, call, access) {
|
|
8445
8846
|
if (lowerer.chainBlocked(access, call))
|
|
8446
8847
|
return null;
|
|
8447
|
-
const
|
|
8448
|
-
|
|
8848
|
+
const mappedReceiver = lowerer.mapTypeOf(lowerer.typeOf(access.expression));
|
|
8849
|
+
const receiverIr = mappedReceiver?.kind === "object"
|
|
8850
|
+
? mappedReceiver
|
|
8851
|
+
: mappedReceiver?.kind === "union"
|
|
8852
|
+
? (() => {
|
|
8853
|
+
const arms = lowerer.unions.get(mappedReceiver.unionId)?.arms ?? [];
|
|
8854
|
+
const objects = arms.filter((arm) => arm.kind === "object");
|
|
8855
|
+
return objects.length === 1 && arms.every((arm) => arm.kind === "object" || isUnitType(arm))
|
|
8856
|
+
? objects[0]
|
|
8857
|
+
: null;
|
|
8858
|
+
})()
|
|
8859
|
+
: null;
|
|
8860
|
+
if (receiverIr === null)
|
|
8449
8861
|
return null;
|
|
8862
|
+
const lowerReceiver = () => {
|
|
8863
|
+
const receiver = lowerer.lowerExpr(access.expression);
|
|
8864
|
+
const optional = lowerer.runtimeOptionalPropertyReceiver(access.expression, receiver, receiverIr, access.name.text);
|
|
8865
|
+
if (optional !== null)
|
|
8866
|
+
return optional;
|
|
8867
|
+
if (receiver.type.kind === "union") {
|
|
8868
|
+
const helper = lowerer.narrowedArmHelper(receiver.type.unionId, receiverIr, locOf(access.expression));
|
|
8869
|
+
if (helper !== null)
|
|
8870
|
+
return { kind: "call", callee: helper, args: [receiver], type: receiverIr, loc: locOf(access.expression) };
|
|
8871
|
+
}
|
|
8872
|
+
return receiver;
|
|
8873
|
+
};
|
|
8450
8874
|
const info = lowerer.classes.get(receiverIr.className);
|
|
8451
8875
|
if (!info)
|
|
8452
8876
|
lowerer.flushDeferredClass(receiverIr.className);
|
|
@@ -8474,17 +8898,34 @@ export function lowerObjectMethodCall(lowerer, call, access) {
|
|
|
8474
8898
|
if (gfound)
|
|
8475
8899
|
return lowerClassGenericMethodCall(lowerer, call, access, info, gfound);
|
|
8476
8900
|
}
|
|
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
|
-
//
|
|
8901
|
+
// A FUNC-, nullable-FUNC-, or DYN-typed FIELD in call position:
|
|
8902
|
+
// `this.cb()` — the ctor-assigned callback field (countdown.js's
|
|
8903
|
+
// shape). The call is an ordinary call through the field's VALUE —
|
|
8904
|
+
// read and, when necessary, check-narrow the callable arm, then
|
|
8905
|
+
// callValue; checked-dynamic fields use the dynCall boundary. Every
|
|
8906
|
+
// other field type falls through to the fences.
|
|
8483
8907
|
if (info && !found) {
|
|
8484
8908
|
const fieldType = info.fields.get(access.name.text);
|
|
8485
|
-
|
|
8909
|
+
const callableType = fieldType?.kind === "func"
|
|
8910
|
+
? fieldType
|
|
8911
|
+
: fieldType?.kind === "union"
|
|
8912
|
+
? (() => {
|
|
8913
|
+
const arms = lowerer.unions.get(fieldType.unionId)?.arms ?? [];
|
|
8914
|
+
const funcs = arms.filter((arm) => arm.kind === "func");
|
|
8915
|
+
return funcs.length === 1 && arms.every((arm) => arm.kind === "func" || isUnitType(arm))
|
|
8916
|
+
? funcs[0]
|
|
8917
|
+
: null;
|
|
8918
|
+
})()
|
|
8919
|
+
: null;
|
|
8920
|
+
if (fieldType && (callableType !== null || fieldType.kind === "dyn")) {
|
|
8486
8921
|
const target = lowerer.fieldTarget(access);
|
|
8487
|
-
|
|
8922
|
+
let callee = target ? lowerer.fieldGetExpr(target, locOf(access), access) : null;
|
|
8923
|
+
if (callee?.type.kind === "union" && callableType !== null) {
|
|
8924
|
+
const helper = lowerer.narrowedArmHelper(callee.type.unionId, callableType, locOf(access));
|
|
8925
|
+
if (helper !== null) {
|
|
8926
|
+
callee = { kind: "call", callee: helper, args: [callee], type: callableType, loc: locOf(access) };
|
|
8927
|
+
}
|
|
8928
|
+
}
|
|
8488
8929
|
if (callee?.type.kind === "func") {
|
|
8489
8930
|
const params = callee.type.params;
|
|
8490
8931
|
const args = call.arguments.map((a, i) => lowerer.lowerExprExpecting(a, params[i]));
|
|
@@ -8514,7 +8955,7 @@ export function lowerObjectMethodCall(lowerer, call, access) {
|
|
|
8514
8955
|
// The one builtin method: Error.prototype.toString, a runtime
|
|
8515
8956
|
// implementation called directly (overriding it is fenced, so no
|
|
8516
8957
|
// dispatch can ever be needed). Receiver BORROWED by the libCall.
|
|
8517
|
-
const receiver =
|
|
8958
|
+
const receiver = lowerReceiver();
|
|
8518
8959
|
return {
|
|
8519
8960
|
kind: "libCall",
|
|
8520
8961
|
fn: "error.toString",
|
|
@@ -8536,7 +8977,7 @@ export function lowerObjectMethodCall(lowerer, call, access) {
|
|
|
8536
8977
|
lowerer.noteVirtualEdge(info, method);
|
|
8537
8978
|
else
|
|
8538
8979
|
lowerer.noteEdge(`%${found.declarer.def.name}.${method}`);
|
|
8539
|
-
const receiver =
|
|
8980
|
+
const receiver = lowerReceiver();
|
|
8540
8981
|
const args = lowerer.completeArgs(call.arguments, found.sig.params, locOf(call), call);
|
|
8541
8982
|
if (lowerer.overrideBelow(info, method)) {
|
|
8542
8983
|
return reconcileOverloadReturn(lowerer, call, {
|