@scriptc/compiler 0.1.2 → 0.1.4
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 +258 -64
- package/dist/backend/c/async.d.ts +30 -0
- package/dist/backend/c/async.js +224 -0
- package/dist/backend/c/async.js.map +1 -1
- package/dist/backend/c/c-emitter.d.ts +13 -0
- package/dist/backend/c/c-emitter.js +28 -9
- 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 +445 -60
- package/dist/backend/c/exprs.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/types.d.ts +4 -0
- package/dist/backend/c/types.js +20 -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 +32 -11
- package/dist/backend/c/walkers.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 +2 -1
- package/dist/backend/link-plan.js +6 -1
- package/dist/backend/link-plan.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 +24 -13
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.js +54 -12
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/expr-bytes.d.ts +1 -1
- package/dist/backend/llvm/expr-bytes.js +8 -8
- package/dist/backend/llvm/expr-bytes.js.map +1 -1
- package/dist/backend/llvm/expr-callbacks.d.ts +9 -0
- package/dist/backend/llvm/expr-callbacks.js +125 -0
- package/dist/backend/llvm/expr-callbacks.js.map +1 -1
- package/dist/backend/llvm/expr-context.d.ts +18 -2
- package/dist/backend/llvm/expr-dispatch.js +1 -0
- package/dist/backend/llvm/expr-dispatch.js.map +1 -1
- package/dist/backend/llvm/expr-dynamic.js +9 -0
- package/dist/backend/llvm/expr-dynamic.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.d.ts +1 -1
- package/dist/backend/llvm/expr-primitives.js +38 -9
- package/dist/backend/llvm/expr-primitives.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.test.d.ts +1 -0
- package/dist/backend/llvm/expr-primitives.test.js +38 -0
- package/dist/backend/llvm/expr-primitives.test.js.map +1 -0
- 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 +2 -1
- package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
- package/dist/backend/llvm/expr-stream-callbacks.d.ts +6 -0
- package/dist/backend/llvm/expr-stream-callbacks.js +122 -0
- package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
- package/dist/backend/llvm/lib-dispatch.js +22 -0
- package/dist/backend/llvm/lib-dispatch.js.map +1 -1
- package/dist/backend/llvm/lib-filesystem.js +68 -10
- package/dist/backend/llvm/lib-filesystem.js.map +1 -1
- package/dist/backend/llvm/lib-network.js +18 -2
- package/dist/backend/llvm/lib-network.js.map +1 -1
- package/dist/backend/llvm/lib-process.js +206 -11
- package/dist/backend/llvm/lib-process.js.map +1 -1
- package/dist/backend/llvm/lib-shared.js +82 -0
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/llvm/lib-stream.js +23 -0
- 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/walkers.js +7 -5
- package/dist/backend/llvm/walkers.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 +11 -6
- package/dist/backend/native-toolchain.js +30 -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.test.js +29 -10
- package/dist/backend/runtime-pack.test.js.map +1 -1
- package/dist/backend/targets.d.ts +9 -0
- package/dist/backend/targets.js +22 -0
- package/dist/backend/targets.js.map +1 -1
- package/dist/backend/targets.test.js +13 -1
- package/dist/backend/targets.test.js.map +1 -1
- package/dist/coverage/surface-manifest.js +9 -0
- package/dist/coverage/surface-manifest.js.map +1 -1
- package/dist/diagnostics/diagnostic.js +4 -4
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/executable/executable-cache.d.ts +3 -0
- package/dist/executable/executable-cache.js +4 -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/frontend/fork-target.d.ts +17 -0
- package/dist/frontend/fork-target.js +256 -0
- package/dist/frontend/fork-target.js.map +1 -0
- package/dist/frontend/lowering/abstract-equality.d.ts +6 -0
- package/dist/frontend/lowering/abstract-equality.js +250 -0
- package/dist/frontend/lowering/abstract-equality.js.map +1 -0
- package/dist/frontend/lowering/containers/bytes.d.ts +0 -4
- package/dist/frontend/lowering/containers/bytes.js +112 -28
- package/dist/frontend/lowering/containers/bytes.js.map +1 -1
- package/dist/frontend/lowering/lower-assert.js +87 -12
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-builtins.d.ts +72 -44
- package/dist/frontend/lowering/lower-builtins.js +1323 -165
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +37 -27
- package/dist/frontend/lowering/lower-calls.js +682 -132
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.js +39 -8
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.js +162 -8
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-event-emitter.js +212 -21
- package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.js +238 -87
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.d.ts +4 -0
- package/dist/frontend/lowering/lower-inspect.js +8 -1
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-island.d.ts +6 -3
- package/dist/frontend/lowering/lower-island.js +165 -6
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.d.ts +6 -0
- package/dist/frontend/lowering/lower-modules.js +192 -38
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-namespaces.js +7 -0
- package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
- package/dist/frontend/lowering/lower-server.d.ts +1 -1
- package/dist/frontend/lowering/lower-server.js +130 -27
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.d.ts +5 -4
- package/dist/frontend/lowering/lower-stmts.js +141 -21
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.d.ts +3 -0
- package/dist/frontend/lowering/lower-stream.js +7 -0
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +90 -13
- package/dist/frontend/lowering/lowerer.js +416 -76
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/surfaces.d.ts +31 -3
- package/dist/frontend/lowering/surfaces.js +173 -90
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/npm-static-declarations.d.ts +4 -0
- package/dist/frontend/npm-static-declarations.js +83 -14
- package/dist/frontend/npm-static-declarations.js.map +1 -1
- package/dist/frontend/npm-static-declarations.test.js +33 -2
- package/dist/frontend/npm-static-declarations.test.js.map +1 -1
- package/dist/frontend/npm-static.js +6 -5
- package/dist/frontend/npm-static.js.map +1 -1
- package/dist/frontend/npm.d.ts +15 -3
- package/dist/frontend/npm.js +80 -8
- package/dist/frontend/npm.js.map +1 -1
- package/dist/frontend/npm.test.js +76 -9
- package/dist/frontend/npm.test.js.map +1 -1
- package/dist/frontend/program.js +110 -12
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/resolve.d.ts +28 -7
- package/dist/frontend/resolve.js +90 -26
- package/dist/frontend/resolve.js.map +1 -1
- package/dist/frontend/resolve.test.js +21 -1
- package/dist/frontend/resolve.test.js.map +1 -1
- package/dist/frontend/type-mapper.d.ts +5 -0
- package/dist/frontend/type-mapper.js +115 -33
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.js +30 -3
- 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 +155 -66
- package/dist/ir/ir.js +143 -6
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/ir.test.js +14 -1
- package/dist/ir/ir.test.js.map +1 -1
- package/dist/ir/serialize.d.ts +1 -1
- package/dist/ir/serialize.js +1 -1
- package/dist/ir/serialize.js.map +1 -1
- package/dist/ir/validate.js +242 -18
- package/dist/ir/validate.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/package.json +17 -17
- package/surface-manifest.json +163 -54
|
@@ -5,10 +5,10 @@ import { InternalCompilerError } from "../../errors.js";
|
|
|
5
5
|
* generic instantiation (bounded by MAX_GENERIC_INSTANCES). */
|
|
6
6
|
import * as ts from "../ts7/adapter.js";
|
|
7
7
|
import { lowerGenMethodCall } from "./lower-generators.js";
|
|
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
|
+
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";
|
|
9
9
|
import { isJsSourceFile, locOf } from "../program.js";
|
|
10
10
|
import { genResultRecord, isGenericCallableMemberType, typeKey } from "../type-mapper.js";
|
|
11
|
-
import { PoisonError, dynFallbackType, dynUndefinedExpr, importCallHandleType, jsFuncNameOf, newFnCtx, nodeThrowExpr } from "./lowerer.js";
|
|
11
|
+
import { PoisonError, dynFallbackType, dynUndefinedExpr, importCallHandleType, jsFuncNameOf, newFnCtx, nodeThrowExpr, staticImportNamespaceType } from "./lowerer.js";
|
|
12
12
|
import { enforceLibBoundary } from "./lib-boundary.js";
|
|
13
13
|
import { NARROW_FIRST, builtinFenceHintOf, builtinModuleFnOf } from "./surfaces.js";
|
|
14
14
|
import { ffiBindingDiag, ffiSignatureDiag, libCallbackDiag, requiresDynamicDiag } from "../../diagnostics/diagnostic.js";
|
|
@@ -16,7 +16,7 @@ import { mixinFnShapeOf } from "./lower-mixins.js";
|
|
|
16
16
|
import { dynStringReceiver, lowerArrayFromCall, lowerDynArrayFilterCall, lowerDynArrayFlatMapCall, lowerGroupByStaticCall, lowerIteratorHelperCall, lowerObjectAssignIndexShape, lowerObjectFromEntriesCall, lowerObjectIterOverIndexShape, lowerTupleReadMethodCall } from "./lower-containers.js";
|
|
17
17
|
import { bufEncoding } from "./containers/bytes.js";
|
|
18
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";
|
|
19
|
+
import { lowerChildStreamMethodCall, lowerChildWriterMethodCall, lowerCreateRequireCall, lowerCryptoHashMethodCall, lowerDirentMethodCall, lowerFileHandleMethodCall, lowerImportMetaResolveCall, lowerNodeModuleCall, lowerPerfHooksCall, lowerProcStreamMethodCall, lowerReflectApplyCall, lowerRequireResolveCall, lowerWatcherMethodCall } from "./lower-builtins.js";
|
|
20
20
|
import { lowerAbsenceProbe, lowerPromiseAllTupleCall, lowerPromiseRejectCall, templateRawTextOf } from "./lower-exprs.js";
|
|
21
21
|
import { isSafeToDiscard } from "./expressions/evaluation-safety.js";
|
|
22
22
|
import { tryLowerExpression } from "./expressions/try-lower-expression.js";
|
|
@@ -32,6 +32,58 @@ import { npmStaticPackageOfPath } from "../npm-static.js";
|
|
|
32
32
|
import { countedFor, varRef } from "../../ir/build.js";
|
|
33
33
|
import { rejectStaticThis } from "./static-this.js";
|
|
34
34
|
import { fenceNodeModuleMutationCall, lowerRequireCacheKeys } from "./lower-node-module.js";
|
|
35
|
+
/** The one func-type projection of completed parameter shapes. Typed rest
|
|
36
|
+
* parameters keep their packed array as the trailing native ABI slot and
|
|
37
|
+
* mark the value variadic so indirect call sites run completeArgs before
|
|
38
|
+
* callValue. Dynamic rest remains the historical hidden ScrDyn slot, while
|
|
39
|
+
* island rest spells its engine-array slot directly. */
|
|
40
|
+
export function funcTypeFromParamShapes(shapes, ret) {
|
|
41
|
+
const typedRest = shapes.some((shape) => shape.mode === "rest");
|
|
42
|
+
const dynRest = shapes.some((shape) => shape.mode === "dynRest");
|
|
43
|
+
const islandRest = shapes.some((shape) => shape.mode === "islandRest");
|
|
44
|
+
return {
|
|
45
|
+
kind: "func",
|
|
46
|
+
params: shapes.filter((shape) => shape.mode !== "dynRest").map((shape) => shape.type),
|
|
47
|
+
ret,
|
|
48
|
+
...(typedRest || dynRest || islandRest ? { rest: true } : {}),
|
|
49
|
+
...(typedRest
|
|
50
|
+
? { restAbi: "typed" }
|
|
51
|
+
: islandRest
|
|
52
|
+
? { restAbi: "jsval" }
|
|
53
|
+
: {}),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/** Registers `const alias = overloadedDeclaration` as a compile-time
|
|
57
|
+
* callable projection. The source function's one implementation ABI is
|
|
58
|
+
* already collected in fnSigsBySymbol; each direct call still uses the
|
|
59
|
+
* TS7-resolved overload result bridge. The alias owns no storage, and a
|
|
60
|
+
* value read materializes the source function's interned closure, so JS
|
|
61
|
+
* identity (`alias === source`) is preserved. */
|
|
62
|
+
export function registerOverloadedCallableAlias(lowerer, decl) {
|
|
63
|
+
if (!ts.isIdentifier(decl.name) || !decl.initializer)
|
|
64
|
+
return false;
|
|
65
|
+
let init = decl.initializer;
|
|
66
|
+
while (ts.isParenthesizedExpression(init))
|
|
67
|
+
init = init.expression;
|
|
68
|
+
if (!ts.isIdentifier(init))
|
|
69
|
+
return false;
|
|
70
|
+
const aliasType = lowerer.typeOf(decl.name);
|
|
71
|
+
if (lowerer.checker.getCallSignatures(aliasType).length < 2)
|
|
72
|
+
return false;
|
|
73
|
+
const sourceSymbol = lowerer.resolveValueSymbol(init);
|
|
74
|
+
if (!sourceSymbol)
|
|
75
|
+
return false;
|
|
76
|
+
const sourceProjection = lowerer.staticCallables.get(sourceSymbol);
|
|
77
|
+
const signature = lowerer.fnSigsBySymbol.get(sourceSymbol) ??
|
|
78
|
+
(sourceProjection?.kind === "declared-function" ? sourceProjection.signature : undefined);
|
|
79
|
+
if (!signature)
|
|
80
|
+
return false;
|
|
81
|
+
const aliasSymbol = lowerer.checker.getSymbolAtLocation(decl.name);
|
|
82
|
+
if (!aliasSymbol)
|
|
83
|
+
return false;
|
|
84
|
+
lowerer.staticCallables.set(aliasSymbol, { kind: "declared-function", signature });
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
35
87
|
export function generatorMeta(lowerer, type) {
|
|
36
88
|
const resultType = genResultRecord(type.yieldT, type.retT, lowerer.shapes, lowerer.unions);
|
|
37
89
|
if (resultType === null) {
|
|
@@ -61,6 +113,10 @@ export const MAX_GENERIC_INSTANCES = 100;
|
|
|
61
113
|
* - `...xs: T[]`: the ABI type is the array; call sites pack the surplus.
|
|
62
114
|
*/
|
|
63
115
|
export function paramShape(lowerer, param) {
|
|
116
|
+
const moduleNs = lowerer.moduleNsParamOverrides.get(param);
|
|
117
|
+
if (moduleNs !== undefined) {
|
|
118
|
+
return { type: moduleNs, mode: param.questionToken ? "omittable" : "required" };
|
|
119
|
+
}
|
|
64
120
|
// Island-handle params (a then-handler receiving a dynamic import's
|
|
65
121
|
// namespace handle — markJsvalHandlerParams): jsval, whatever the
|
|
66
122
|
// contextual type spelled.
|
|
@@ -256,6 +312,18 @@ export function checkDefaultParamBodyType(lowerer, param, bodyType) {
|
|
|
256
312
|
* explicitly-passed `undefined` wraps to — both trigger a default, JS-
|
|
257
313
|
* exact); a rest param packs the surplus args (possibly zero) into one
|
|
258
314
|
* array literal, evaluated in source order at the call site. */
|
|
315
|
+
function fixedTupleSpreadInfo(lowerer, node) {
|
|
316
|
+
const type = lowerer.mapTypeOf(lowerer.typeOf(node));
|
|
317
|
+
if (type?.kind !== "record")
|
|
318
|
+
return null;
|
|
319
|
+
const shape = lowerer.shapes.get(type.shapeId);
|
|
320
|
+
if (!shape?.tuple || shape.fields.length === 0)
|
|
321
|
+
return null;
|
|
322
|
+
return {
|
|
323
|
+
type,
|
|
324
|
+
fields: [...shape.fields].sort((a, b) => Number(a.name) - Number(b.name)),
|
|
325
|
+
};
|
|
326
|
+
}
|
|
259
327
|
export function completeArgs(lowerer, argNodes, shapes, loc, blame,
|
|
260
328
|
/** Pre-lowered values virtually PREPENDED to the argument list — the
|
|
261
329
|
* tagged-template strings object, which has no ts.Expression to lower
|
|
@@ -264,7 +332,56 @@ export function completeArgs(lowerer, argNodes, shapes, loc, blame,
|
|
|
264
332
|
* DYN conversion in a dyn rest, element coercion in a typed rest). */
|
|
265
333
|
leading) {
|
|
266
334
|
const isIr = (s) => s !== undefined && !("kind" in s);
|
|
267
|
-
const sources = leading
|
|
335
|
+
const sources = leading?.map((ir) => ({ ir })) ?? [];
|
|
336
|
+
for (const arg of argNodes) {
|
|
337
|
+
if (!ts.isSpreadElement(arg)) {
|
|
338
|
+
sources.push(arg);
|
|
339
|
+
continue;
|
|
340
|
+
}
|
|
341
|
+
const tuple = fixedTupleSpreadInfo(lowerer, arg.expression);
|
|
342
|
+
if (!tuple) {
|
|
343
|
+
sources.push(arg);
|
|
344
|
+
continue;
|
|
345
|
+
}
|
|
346
|
+
// A fixed tuple has a compile-time argument count, so flatten it into
|
|
347
|
+
// the callee's ordinary positional ABI. The operand itself still
|
|
348
|
+
// evaluates exactly once and at the spread's source-order position:
|
|
349
|
+
// the first extracted field carries a seqExpr that initializes one
|
|
350
|
+
// hidden tuple local, and every later field reads that same local.
|
|
351
|
+
// Tuple fields are owned reads, so the call receives the same +1
|
|
352
|
+
// values as separately written arguments while the saved tuple stays
|
|
353
|
+
// alive through the call.
|
|
354
|
+
const spreadLoc = locOf(arg);
|
|
355
|
+
const value = lowerer.coerceInto(arg.expression, lowerer.lowerExpr(arg.expression), tuple.type);
|
|
356
|
+
const saved = lowerer.declareHiddenLocal("%callSpread", tuple.type);
|
|
357
|
+
const savedRef = () => ({
|
|
358
|
+
kind: "varRef",
|
|
359
|
+
localId: saved.id,
|
|
360
|
+
type: tuple.type,
|
|
361
|
+
loc: spreadLoc,
|
|
362
|
+
});
|
|
363
|
+
tuple.fields.forEach((field, i) => {
|
|
364
|
+
const read = {
|
|
365
|
+
kind: "recordGet",
|
|
366
|
+
obj: savedRef(),
|
|
367
|
+
shapeId: tuple.type.shapeId,
|
|
368
|
+
field: field.name,
|
|
369
|
+
type: field.type,
|
|
370
|
+
loc: spreadLoc,
|
|
371
|
+
};
|
|
372
|
+
sources.push({
|
|
373
|
+
ir: i === 0
|
|
374
|
+
? {
|
|
375
|
+
kind: "seqExpr",
|
|
376
|
+
stmts: [{ kind: "varDecl", localId: saved.id, init: value, loc: spreadLoc }],
|
|
377
|
+
result: read,
|
|
378
|
+
type: field.type,
|
|
379
|
+
loc: spreadLoc,
|
|
380
|
+
}
|
|
381
|
+
: read,
|
|
382
|
+
});
|
|
383
|
+
});
|
|
384
|
+
}
|
|
268
385
|
const restAt = shapes.findIndex((s) => s.mode === "rest" || s.mode === "dynRest" || s.mode === "islandRest");
|
|
269
386
|
const positional = restAt >= 0 ? shapes.slice(0, restAt) : [...shapes];
|
|
270
387
|
const out = positional.map((shape, i) => {
|
|
@@ -293,6 +410,8 @@ leading) {
|
|
|
293
410
|
// reaching here means a call form we don't model — defensive.
|
|
294
411
|
lowerer.unsupported("SC1090", blame, "this call form");
|
|
295
412
|
}
|
|
413
|
+
if (shape.callDefault)
|
|
414
|
+
return shape.callDefault;
|
|
296
415
|
return lowerer.undefinedArgFor(shape.type, loc, blame);
|
|
297
416
|
});
|
|
298
417
|
if (restAt >= 0 && shapes[restAt].mode === "islandRest") {
|
|
@@ -439,6 +558,34 @@ export function omittedArgFor(lowerer, type, loc) {
|
|
|
439
558
|
return { kind: "jsOp", op: "undefLit", args: [], type: JSVAL, loc };
|
|
440
559
|
return lowerer.wrappedUndefined(type, loc);
|
|
441
560
|
}
|
|
561
|
+
/** Complete an indirect static call against its func value ABI. Ordinary
|
|
562
|
+
* fixed-width values retain the historical optional-suffix completion.
|
|
563
|
+
* Typed-rest values reinterpret their final array slot as a rest ParamShape
|
|
564
|
+
* and reuse completeArgs, including fixed-tuple and same-element array
|
|
565
|
+
* spreads with source-order/evaluate-once semantics. */
|
|
566
|
+
function completeFuncValueArgs(lowerer, call, funcType, loc) {
|
|
567
|
+
if (funcType.rest === true && funcType.restAbi === "typed") {
|
|
568
|
+
const rest = funcType.params[funcType.params.length - 1];
|
|
569
|
+
if (!rest || rest.kind !== "array") {
|
|
570
|
+
throw new InternalCompilerError("typed-rest function value has no trailing array ABI slot");
|
|
571
|
+
}
|
|
572
|
+
const shapes = funcType.params.slice(0, -1).map((type) => ({
|
|
573
|
+
type,
|
|
574
|
+
mode: omittedArgFor(lowerer, type, loc) ? "omittable" : "required",
|
|
575
|
+
}));
|
|
576
|
+
shapes.push({ type: rest, mode: "rest" });
|
|
577
|
+
return completeArgs(lowerer, call.arguments, shapes, loc, call);
|
|
578
|
+
}
|
|
579
|
+
const args = call.arguments.map((arg, index) => lowerer.lowerExprExpecting(arg, funcType.params[index]));
|
|
580
|
+
for (let i = args.length; i < funcType.params.length; i++) {
|
|
581
|
+
const absent = omittedArgFor(lowerer, funcType.params[i], loc);
|
|
582
|
+
if (!absent) {
|
|
583
|
+
lowerer.unsupported("SC1090", call, "calls omitting a non-optional parameter of the callee's type");
|
|
584
|
+
}
|
|
585
|
+
args.push(absent);
|
|
586
|
+
}
|
|
587
|
+
return args;
|
|
588
|
+
}
|
|
442
589
|
export function undefinedArgFor(lowerer, type, loc, blame) {
|
|
443
590
|
if (type.kind === "dyn")
|
|
444
591
|
return dynUndefinedExpr(loc);
|
|
@@ -454,13 +601,12 @@ export function undefinedArgFor(lowerer, type, loc, blame) {
|
|
|
454
601
|
}
|
|
455
602
|
return wrapped;
|
|
456
603
|
}
|
|
457
|
-
/** DECISION (docs/ir.md): function VALUES
|
|
458
|
-
*
|
|
459
|
-
*
|
|
460
|
-
*
|
|
461
|
-
*
|
|
462
|
-
*
|
|
463
|
-
* types reject). Direct calls get the full feature. */
|
|
604
|
+
/** DECISION (docs/ir.md): function VALUES carry one completed native ABI.
|
|
605
|
+
* Optional/default parameters appear as literal `T | undefined` slots;
|
|
606
|
+
* typed rest parameters appear as one trailing typed-array slot plus the
|
|
607
|
+
* typed-rest marker that makes indirect call sites pack source arguments.
|
|
608
|
+
* A value is admitted only where its target type projects to that same
|
|
609
|
+
* completed signature. */
|
|
464
610
|
export function requireExactArityValue(lowerer, blame, contextual, shapes, funcType) {
|
|
465
611
|
// dynRest params ride the boxed thunk (JS arity — no completed-ABI
|
|
466
612
|
// spelling exists or is needed); they don't gate the value form.
|
|
@@ -475,9 +621,6 @@ export function requireExactArityValue(lowerer, blame, contextual, shapes, funcT
|
|
|
475
621
|
(s.mode === "omittable" && (s.type.kind === "dyn" || s.type.kind === "jsval")))) {
|
|
476
622
|
return;
|
|
477
623
|
}
|
|
478
|
-
if (shapes.some((s) => s.mode === "rest")) {
|
|
479
|
-
lowerer.unsupported("SC1090", blame, "functions with rest parameters as values (call them directly)");
|
|
480
|
-
}
|
|
481
624
|
// The type the value FLOWS under must spell the completed ABI: the
|
|
482
625
|
// contextual (target) type when one exists, otherwise the expression's
|
|
483
626
|
// OWN inferred type — the unannotated-const case (`const f = (x = 5) =>
|
|
@@ -520,6 +663,20 @@ export function requireExactArityValue(lowerer, blame, contextual, shapes, funcT
|
|
|
520
663
|
lowerer.spawnResFnAdapterPlan(funcType, mappedFn) !== null) {
|
|
521
664
|
return;
|
|
522
665
|
}
|
|
666
|
+
// An uncontextualized npm-static implementation function can still
|
|
667
|
+
// have a declaration-backed completed ABI: the package's .d.ts
|
|
668
|
+
// projection supplies the body-facing parameter/return types while
|
|
669
|
+
// the shipped JavaScript's own inferred type remains wider (`any`
|
|
670
|
+
// callback fields are the common case). lambdaSignature has already
|
|
671
|
+
// constructed and validated that concrete ABI, and every eventual
|
|
672
|
+
// storage/call site independently checks it. Admit the value at birth;
|
|
673
|
+
// do not make the unprojected JS inference veto its authored surface.
|
|
674
|
+
if (target === undefined &&
|
|
675
|
+
contextual !== null &&
|
|
676
|
+
(ts.isArrowFunction(contextual) || ts.isFunctionExpression(contextual)) &&
|
|
677
|
+
npmStaticPackageOfPath(contextual.getSourceFile().fileName) !== null) {
|
|
678
|
+
return;
|
|
679
|
+
}
|
|
523
680
|
// An 'any'-typed slot is the ISLAND boundary: the host-function
|
|
524
681
|
// trampoline already implements JS call semantics over the completed
|
|
525
682
|
// signature — a missing engine argument arrives as undefined and takes
|
|
@@ -1426,12 +1583,7 @@ export function lowerGenericFnValue(lowerer, ref, info) {
|
|
|
1426
1583
|
// closure per function, so `f === f` holds like any declaration).
|
|
1427
1584
|
if (info.implicitParams) {
|
|
1428
1585
|
const inst = implicitDefaultInstance(lowerer, ref, info);
|
|
1429
|
-
const funcType =
|
|
1430
|
-
kind: "func",
|
|
1431
|
-
params: inst.params.filter((p) => p.mode !== "dynRest").map((p) => p.type),
|
|
1432
|
-
ret: inst.returnType,
|
|
1433
|
-
...(inst.params.some((p) => p.mode === "dynRest") ? { rest: true } : {}),
|
|
1434
|
-
};
|
|
1586
|
+
const funcType = funcTypeFromParamShapes(inst.params, inst.returnType);
|
|
1435
1587
|
lowerer.requireExactArityValue(ref, ref, inst.params, funcType);
|
|
1436
1588
|
lowerer.noteEdge(inst.name);
|
|
1437
1589
|
return { kind: "closure", fnName: inst.name, captures: [], type: funcType, loc };
|
|
@@ -1477,15 +1629,9 @@ export function lowerGenericFnValue(lowerer, ref, info) {
|
|
|
1477
1629
|
if (info.typeParams.some((tp) => !bindings.get(tp)))
|
|
1478
1630
|
fenceUnpinned();
|
|
1479
1631
|
const inst = genericValueInstance(lowerer, ref, info, bindings);
|
|
1480
|
-
// The value's type is the completed ABI signature
|
|
1481
|
-
//
|
|
1482
|
-
|
|
1483
|
-
const funcType = {
|
|
1484
|
-
kind: "func",
|
|
1485
|
-
params: inst.params.filter((p) => p.mode !== "dynRest").map((p) => p.type),
|
|
1486
|
-
ret: inst.returnType,
|
|
1487
|
-
...(inst.params.some((p) => p.mode === "dynRest") ? { rest: true } : {}),
|
|
1488
|
-
};
|
|
1632
|
+
// The value's type is the completed ABI signature. Typed rest keeps its
|
|
1633
|
+
// packed-array slot; dynRest stays hidden behind the rest marker.
|
|
1634
|
+
const funcType = funcTypeFromParamShapes(inst.params, inst.returnType);
|
|
1489
1635
|
lowerer.requireExactArityValue(ref, ref, inst.params, funcType);
|
|
1490
1636
|
lowerer.noteEdge(inst.name);
|
|
1491
1637
|
return { kind: "closure", fnName: inst.name, captures: [], type: funcType, loc };
|
|
@@ -2780,6 +2926,57 @@ export function lowerFfiCall(lowerer, expr) {
|
|
|
2780
2926
|
loc,
|
|
2781
2927
|
};
|
|
2782
2928
|
}
|
|
2929
|
+
/** Full builtin dispatch for compile-time callable projections. A projected
|
|
2930
|
+
* alias must traverse the same spoke/validation ladder as its direct import;
|
|
2931
|
+
* jumping to the table tail would bypass checked-dynamic argument errors. */
|
|
2932
|
+
function lowerProjectedBuiltinCall(lowerer, expr, bi, loc) {
|
|
2933
|
+
if (bi.module === "child_process" && bi.member === "execFile") {
|
|
2934
|
+
return lowerer.lowerExecFileCall(expr, loc);
|
|
2935
|
+
}
|
|
2936
|
+
if (bi.module === "timers") {
|
|
2937
|
+
const timersServed = lowerTimersMemberCall(lowerer, expr, bi.member, loc);
|
|
2938
|
+
if (timersServed)
|
|
2939
|
+
return timersServed;
|
|
2940
|
+
}
|
|
2941
|
+
const served = lowerer.lowerNetModuleCall(expr, bi, loc);
|
|
2942
|
+
if (served)
|
|
2943
|
+
return served;
|
|
2944
|
+
const dgramServed = lowerer.lowerDgramDnsModuleCall(expr, bi, loc);
|
|
2945
|
+
if (dgramServed)
|
|
2946
|
+
return dgramServed;
|
|
2947
|
+
const assertServed = lowerer.lowerAssertModuleCall(expr, bi, loc);
|
|
2948
|
+
if (assertServed)
|
|
2949
|
+
return assertServed;
|
|
2950
|
+
const testServed = lowerer.lowerNodeTestModuleCall(expr, bi, loc);
|
|
2951
|
+
if (testServed)
|
|
2952
|
+
return testServed;
|
|
2953
|
+
const utilServed = lowerer.lowerUtilModuleCall(expr, bi, loc);
|
|
2954
|
+
if (utilServed)
|
|
2955
|
+
return utilServed;
|
|
2956
|
+
const streamServed = lowerStreamModuleCall(lowerer, expr, bi, loc);
|
|
2957
|
+
if (streamServed)
|
|
2958
|
+
return streamServed;
|
|
2959
|
+
const fsTs = lowerer.lowerFsToUnixTimestampCall(expr, bi, loc);
|
|
2960
|
+
if (fsTs)
|
|
2961
|
+
return fsTs;
|
|
2962
|
+
const fsLadder = lowerer.lowerFsLadderCall(expr, bi, loc);
|
|
2963
|
+
if (fsLadder)
|
|
2964
|
+
return fsLadder;
|
|
2965
|
+
const cryptoServed = lowerer.lowerCryptoModuleCall(expr, bi, loc);
|
|
2966
|
+
if (cryptoServed)
|
|
2967
|
+
return cryptoServed;
|
|
2968
|
+
const timersInterval = lowerer.lowerTimersPromisesSetInterval(expr, bi, loc);
|
|
2969
|
+
if (timersInterval)
|
|
2970
|
+
return timersInterval;
|
|
2971
|
+
const nodeModuleServed = lowerNodeModuleCall(lowerer, expr, bi, loc);
|
|
2972
|
+
if (nodeModuleServed)
|
|
2973
|
+
return nodeModuleServed;
|
|
2974
|
+
const builtinFn = builtinModuleFnOf(lowerer, bi.module, bi.member);
|
|
2975
|
+
if (!builtinFn) {
|
|
2976
|
+
lowerer.noLowering(`${bi.module}.${bi.member}`, expr, builtinFenceHintOf(bi.module, bi.member), ts.isIdentifier(expr.expression) ? lowerer.resolveValueSymbol(expr.expression) : undefined);
|
|
2977
|
+
}
|
|
2978
|
+
return lowerer.lowerBuiltinModuleCall(expr, bi, builtinFn, loc);
|
|
2979
|
+
}
|
|
2783
2980
|
export function lowerCall(lowerer, expr) {
|
|
2784
2981
|
const loc = locOf(expr);
|
|
2785
2982
|
// A call whose chain ROOTS at an ambient-undefined name (`declare
|
|
@@ -3149,6 +3346,34 @@ export function lowerCall(lowerer, expr) {
|
|
|
3149
3346
|
// Provenance-checked like setTimeout; zero-arg forms are the JS
|
|
3150
3347
|
// constants ("", false, 0). `new String(...)` (wrapper objects) stays
|
|
3151
3348
|
// on the SC2020 fence.
|
|
3349
|
+
if (ts.isIdentifier(expr.expression) &&
|
|
3350
|
+
expr.expression.text === "BigInt" &&
|
|
3351
|
+
lowerer.isStdlibSymbol(lowerer.resolveValueSymbol(expr.expression) ?? undefined)) {
|
|
3352
|
+
if (expr.arguments.length !== 1) {
|
|
3353
|
+
lowerer.noLowering(`BigInt with ${expr.arguments.length} arguments`, expr);
|
|
3354
|
+
}
|
|
3355
|
+
const argNode = expr.arguments[0];
|
|
3356
|
+
const arg = lowerer.lowerExpr(argNode);
|
|
3357
|
+
if (arg.type.kind === "bigint")
|
|
3358
|
+
return arg;
|
|
3359
|
+
if (arg.type.kind === "string") {
|
|
3360
|
+
return { kind: "libCall", fn: "bigint.parse", args: [arg], type: BIGINT_T, loc };
|
|
3361
|
+
}
|
|
3362
|
+
if (arg.type.kind === "f64") {
|
|
3363
|
+
return { kind: "libCall", fn: "bigint.fromF64", args: [arg], type: BIGINT_T, loc };
|
|
3364
|
+
}
|
|
3365
|
+
if (arg.type.kind === "bool") {
|
|
3366
|
+
return {
|
|
3367
|
+
kind: "ternary",
|
|
3368
|
+
cond: arg,
|
|
3369
|
+
then: { kind: "libCall", fn: "bigint.parse", args: [{ kind: "strLit", value: "1", type: STRING, loc }], type: BIGINT_T, loc },
|
|
3370
|
+
else_: { kind: "libCall", fn: "bigint.parse", args: [{ kind: "strLit", value: "0", type: STRING, loc }], type: BIGINT_T, loc },
|
|
3371
|
+
type: BIGINT_T,
|
|
3372
|
+
loc,
|
|
3373
|
+
};
|
|
3374
|
+
}
|
|
3375
|
+
lowerer.noLowering(`BigInt of ${lowerer.fmt(arg.type)} values`, argNode, "string, number, boolean, and bigint arguments are supported");
|
|
3376
|
+
}
|
|
3152
3377
|
if (ts.isIdentifier(expr.expression) &&
|
|
3153
3378
|
(expr.expression.text === "String" ||
|
|
3154
3379
|
expr.expression.text === "Boolean" ||
|
|
@@ -3184,6 +3409,9 @@ export function lowerCall(lowerer, expr) {
|
|
|
3184
3409
|
const arg = lowerer.lowerExpr(argNode);
|
|
3185
3410
|
if (name === "String")
|
|
3186
3411
|
return lowerer.ensureString(arg, argNode);
|
|
3412
|
+
if (name === "Number" && arg.type.kind === "bigint") {
|
|
3413
|
+
return { kind: "libCall", fn: "bigint.toF64", args: [arg], type: F64, loc };
|
|
3414
|
+
}
|
|
3187
3415
|
if (arg.type.kind === "f64")
|
|
3188
3416
|
return arg;
|
|
3189
3417
|
if (arg.type.kind === "bool") {
|
|
@@ -3340,15 +3568,21 @@ export function lowerCall(lowerer, expr) {
|
|
|
3340
3568
|
// supported form is fenced here per site. Members with no lowering at
|
|
3341
3569
|
// all (fs.watch, os.cpus, ...) fence with the module-qualified name.
|
|
3342
3570
|
if (ts.isIdentifier(expr.expression)) {
|
|
3343
|
-
// A call through a
|
|
3344
|
-
//
|
|
3345
|
-
//
|
|
3346
|
-
// already-settled promise).
|
|
3571
|
+
// A call through a compile-time util.promisify projection. execFile
|
|
3572
|
+
// keeps its custom result helper; ordinary builtins route through
|
|
3573
|
+
// their existing promise-module lowering.
|
|
3347
3574
|
{
|
|
3348
3575
|
const sym = lowerer.resolveValueSymbol(expr.expression);
|
|
3349
|
-
|
|
3576
|
+
const projection = sym ? lowerer.staticCallables.get(sym) : undefined;
|
|
3577
|
+
if (projection?.kind === "promisified-exec-file") {
|
|
3350
3578
|
return lowerer.lowerExecFileAsyncCall(expr, loc);
|
|
3351
3579
|
}
|
|
3580
|
+
if (projection?.kind === "promisified-builtin") {
|
|
3581
|
+
return lowerProjectedBuiltinCall(lowerer, expr, { module: projection.module, member: projection.member }, loc);
|
|
3582
|
+
}
|
|
3583
|
+
if (projection?.kind === "builtin-function") {
|
|
3584
|
+
return lowerProjectedBuiltinCall(lowerer, expr, { module: projection.module, member: projection.member }, loc);
|
|
3585
|
+
}
|
|
3352
3586
|
// A call through a `const requestFn = tls ? https.request :
|
|
3353
3587
|
// http.request` binding (the client-function ternary): the http
|
|
3354
3588
|
// client lowering with the RUNTIME-secure dial.
|
|
@@ -3358,6 +3592,9 @@ export function lowerCall(lowerer, expr) {
|
|
|
3358
3592
|
}
|
|
3359
3593
|
const bi = lowerer.builtinImportOf(expr.expression);
|
|
3360
3594
|
if (bi) {
|
|
3595
|
+
if (bi.module === "child_process" && bi.member === "execFile") {
|
|
3596
|
+
return lowerer.lowerExecFileCall(expr, loc);
|
|
3597
|
+
}
|
|
3361
3598
|
// The timers spoke: the node:timers module's exports ARE the
|
|
3362
3599
|
// timer globals (Node re-exports them), so a named/destructured
|
|
3363
3600
|
// import lands on the same shared lowering. Unknown members fall
|
|
@@ -3417,6 +3654,9 @@ export function lowerCall(lowerer, expr) {
|
|
|
3417
3654
|
const timersInterval = lowerer.lowerTimersPromisesSetInterval(expr, bi, loc);
|
|
3418
3655
|
if (timersInterval)
|
|
3419
3656
|
return timersInterval;
|
|
3657
|
+
const nodeModuleServed = lowerNodeModuleCall(lowerer, expr, bi, loc);
|
|
3658
|
+
if (nodeModuleServed)
|
|
3659
|
+
return nodeModuleServed;
|
|
3420
3660
|
const builtinFn = builtinModuleFnOf(lowerer, bi.module, bi.member);
|
|
3421
3661
|
if (!builtinFn) {
|
|
3422
3662
|
// Typed by @types/node (the fallback declarations only declare
|
|
@@ -3723,7 +3963,7 @@ export function lowerCall(lowerer, expr) {
|
|
|
3723
3963
|
if (generic && !(jsSpreadArgs && generic.implicitParams))
|
|
3724
3964
|
return lowerer.lowerGenericCall(expr, generic);
|
|
3725
3965
|
const sig = generic ? null : lowerer.fnSigOf(expr.expression);
|
|
3726
|
-
if (sig && !(jsSpreadArgs && spreadNeedsRuntimeArity(sig.params, expr.arguments))) {
|
|
3966
|
+
if (sig && !(jsSpreadArgs && spreadNeedsRuntimeArity(lowerer, sig.params, expr.arguments))) {
|
|
3727
3967
|
lowerer.noteEdge(sig.name);
|
|
3728
3968
|
const args = lowerer.completeArgs(expr.arguments, sig.params, loc, expr);
|
|
3729
3969
|
return reconcileOverloadReturn(lowerer, expr, { kind: "call", callee: sig.name, args, type: sig.returnType, loc });
|
|
@@ -3765,15 +4005,7 @@ export function lowerCall(lowerer, expr) {
|
|
|
3765
4005
|
if (callee) {
|
|
3766
4006
|
if (callee.type.kind !== "func")
|
|
3767
4007
|
lowerer.badType(expr.expression, lowerer.typeOf(expr.expression));
|
|
3768
|
-
const
|
|
3769
|
-
const args = expr.arguments.map((a, i) => lowerer.lowerExprExpecting(a, params[i]));
|
|
3770
|
-
for (let i = args.length; i < params.length; i++) {
|
|
3771
|
-
const absent = omittedArgFor(lowerer, params[i], loc);
|
|
3772
|
-
if (!absent) {
|
|
3773
|
-
lowerer.unsupported("SC1090", expr, "calls omitting a non-optional parameter of the callee's type");
|
|
3774
|
-
}
|
|
3775
|
-
args.push(absent);
|
|
3776
|
-
}
|
|
4008
|
+
const args = completeFuncValueArgs(lowerer, expr, callee.type, loc);
|
|
3777
4009
|
return { kind: "callValue", callee, args, type: callee.type.ret, loc };
|
|
3778
4010
|
}
|
|
3779
4011
|
}
|
|
@@ -3813,15 +4045,7 @@ export function lowerCall(lowerer, expr) {
|
|
|
3813
4045
|
callee = lowerer.hybridCallUnwrap(callee);
|
|
3814
4046
|
if (callee.type.kind !== "func")
|
|
3815
4047
|
lowerer.badType(expr.expression, lowerer.typeOf(expr.expression));
|
|
3816
|
-
const
|
|
3817
|
-
const args = expr.arguments.map((a, i) => lowerer.lowerExprExpecting(a, params[i]));
|
|
3818
|
-
for (let i = args.length; i < params.length; i++) {
|
|
3819
|
-
const absent = omittedArgFor(lowerer, params[i], loc);
|
|
3820
|
-
if (!absent) {
|
|
3821
|
-
lowerer.unsupported("SC1090", expr, "calls omitting a non-optional parameter of the callee's type");
|
|
3822
|
-
}
|
|
3823
|
-
args.push(absent);
|
|
3824
|
-
}
|
|
4048
|
+
const args = completeFuncValueArgs(lowerer, expr, callee.type, loc);
|
|
3825
4049
|
return { kind: "callValue", callee, args, type: callee.type.ret, loc };
|
|
3826
4050
|
}
|
|
3827
4051
|
// An AMBIENT namespace callee (`M.f()` where only `declare
|
|
@@ -3874,15 +4098,7 @@ export function lowerCall(lowerer, expr) {
|
|
|
3874
4098
|
callee = lowerer.hybridCallUnwrap(callee);
|
|
3875
4099
|
if (callee.type.kind !== "func")
|
|
3876
4100
|
lowerer.badType(expr.expression, lowerer.typeOf(expr.expression));
|
|
3877
|
-
const
|
|
3878
|
-
const args = expr.arguments.map((a, i) => lowerer.lowerExprExpecting(a, params[i]));
|
|
3879
|
-
for (let i = args.length; i < params.length; i++) {
|
|
3880
|
-
const absent = omittedArgFor(lowerer, params[i], loc);
|
|
3881
|
-
if (!absent) {
|
|
3882
|
-
lowerer.unsupported("SC1090", expr, "calls omitting a non-optional parameter of the callee's type");
|
|
3883
|
-
}
|
|
3884
|
-
args.push(absent);
|
|
3885
|
-
}
|
|
4101
|
+
const args = completeFuncValueArgs(lowerer, expr, callee.type, loc);
|
|
3886
4102
|
return { kind: "callValue", callee, args, type: callee.type.ret, loc };
|
|
3887
4103
|
}
|
|
3888
4104
|
if (ts.isPropertyAccessExpression(expr.expression)) {
|
|
@@ -3922,10 +4138,12 @@ export function lowerCall(lowerer, expr) {
|
|
|
3922
4138
|
lowerer.lowerUrlMethodCall(expr, expr.expression) ??
|
|
3923
4139
|
lowerer.lowerSearchParamsMethodCall(expr, expr.expression) ??
|
|
3924
4140
|
lowerer.lowerStatsMethodCall(expr, expr.expression) ??
|
|
4141
|
+
lowerCryptoHashMethodCall(lowerer, expr, expr.expression) ??
|
|
3925
4142
|
lowerFileHandleMethodCall(lowerer, expr, expr.expression) ??
|
|
3926
4143
|
lowerer.lowerChildMethodCall(expr, expr.expression) ??
|
|
3927
4144
|
// Piped child-output stream receivers — on/once("data" | "end").
|
|
3928
4145
|
lowerChildStreamMethodCall(lowerer, expr, expr.expression) ??
|
|
4146
|
+
lowerChildWriterMethodCall(lowerer, expr, expr.expression) ??
|
|
3929
4147
|
// First-class process-stream receivers — write(data).
|
|
3930
4148
|
lowerProcStreamMethodCall(lowerer, expr, expr.expression) ??
|
|
3931
4149
|
// FSWatcher receivers — close() (fs.watch's handle).
|
|
@@ -4008,6 +4226,8 @@ export function lowerCall(lowerer, expr) {
|
|
|
4008
4226
|
// by the receiver's own element.
|
|
4009
4227
|
lowerer.lowerFilterNarrowCall(expr, expr.expression) ??
|
|
4010
4228
|
lowerArrayIsArrayCall(lowerer, expr, expr.expression) ??
|
|
4229
|
+
lowerBigIntStaticCall(lowerer, expr, expr.expression) ??
|
|
4230
|
+
lowerBigIntMethodCall(lowerer, expr, expr.expression) ??
|
|
4011
4231
|
lowerSymbolStaticCall(lowerer, expr, expr.expression) ??
|
|
4012
4232
|
lowerSymbolMethodCall(lowerer, expr, expr.expression) ??
|
|
4013
4233
|
lowerRegExpStaticCall(lowerer, expr, expr.expression) ??
|
|
@@ -4152,6 +4372,14 @@ export function lowerCall(lowerer, expr) {
|
|
|
4152
4372
|
if (callee.type.kind !== "func") {
|
|
4153
4373
|
lowerer.badType(expr.expression, lowerer.typeOf(expr.expression));
|
|
4154
4374
|
}
|
|
4375
|
+
// Typed-rest closures already have a fixed native ABI: complete the
|
|
4376
|
+
// source-level variadic call into their trailing typed-array slot.
|
|
4377
|
+
// Claim before the runtime-arity spread lane; completeArgs handles
|
|
4378
|
+
// typed spreads without boxing the function.
|
|
4379
|
+
if (callee.type.rest === true && callee.type.restAbi === "typed") {
|
|
4380
|
+
const args = completeFuncValueArgs(lowerer, expr, callee.type, loc);
|
|
4381
|
+
return { kind: "callValue", callee, args, type: callee.type.ret, loc };
|
|
4382
|
+
}
|
|
4155
4383
|
// A SPREAD argument on a func-typed callee — the rest-forwarding
|
|
4156
4384
|
// idiom (`(...args) => from(...args)`): the runtime-arity lane boxes
|
|
4157
4385
|
// or marshals the callee and applies through a runtime-built argument
|
|
@@ -4203,26 +4431,7 @@ export function lowerCall(lowerer, expr) {
|
|
|
4203
4431
|
const boxed = { kind: "dynFrom", value: callee, type: DYN, loc };
|
|
4204
4432
|
return { kind: "dynCall", callee: boxed, calleeName, args, type: DYN, loc };
|
|
4205
4433
|
}
|
|
4206
|
-
const
|
|
4207
|
-
const args = expr.arguments.map((a, i) => lowerer.lowerExprExpecting(a, params[i]));
|
|
4208
|
-
// Optional-param func TYPES map their `x?: T` slots as `T | undefined`
|
|
4209
|
-
// ABI unions, and tsc admits calls that omit the optional suffix —
|
|
4210
|
-
// complete the missing trailing args with the interned undefined arm,
|
|
4211
|
-
// exactly what completeArgs does for direct calls (the ABI stays
|
|
4212
|
-
// count-exact). A missing arg whose param has no undefined arm means
|
|
4213
|
-
// the callee value's type spelled a required param tsc let the caller
|
|
4214
|
-
// skip — not a shape this surface models; fence.
|
|
4215
|
-
for (let i = args.length; i < params.length; i++) {
|
|
4216
|
-
// A missing argument completes with the slot's absent value — the
|
|
4217
|
-
// interned undefined arm, the dyn undefined for checked-dynamic
|
|
4218
|
-
// slots (a JS-inferred wrapper like mustCall's, called short), or
|
|
4219
|
-
// the engine undefined for island slots.
|
|
4220
|
-
const absent = omittedArgFor(lowerer, params[i], loc);
|
|
4221
|
-
if (!absent) {
|
|
4222
|
-
lowerer.unsupported("SC1090", expr, "calls omitting a non-optional parameter of the callee's type");
|
|
4223
|
-
}
|
|
4224
|
-
args.push(absent);
|
|
4225
|
-
}
|
|
4434
|
+
const args = completeFuncValueArgs(lowerer, expr, callee.type, loc);
|
|
4226
4435
|
return { kind: "callValue", callee, args, type: callee.type.ret, loc };
|
|
4227
4436
|
}
|
|
4228
4437
|
function lowerRegexMethodCallWithOptionalArg(lowerer, call, access) {
|
|
@@ -4470,9 +4679,22 @@ function lowerSpreadArgsCall(lowerer, expr, callee, loc) {
|
|
|
4470
4679
|
* (dynRest/islandRest, whose packs are built per-argument): the shapes
|
|
4471
4680
|
* the runtime-arity lane (lowerSpreadArgsCall) serves. Typed `rest`
|
|
4472
4681
|
* slots keep completeArgs' same-element spread packing. */
|
|
4473
|
-
function spreadNeedsRuntimeArity(shapes, argNodes) {
|
|
4682
|
+
function spreadNeedsRuntimeArity(lowerer, shapes, argNodes) {
|
|
4474
4683
|
const restAt = shapes.findIndex((s) => s.mode === "rest" || s.mode === "dynRest" || s.mode === "islandRest");
|
|
4475
|
-
|
|
4684
|
+
let position = 0;
|
|
4685
|
+
for (const arg of argNodes) {
|
|
4686
|
+
if (ts.isSpreadElement(arg)) {
|
|
4687
|
+
const tuple = fixedTupleSpreadInfo(lowerer, arg.expression);
|
|
4688
|
+
if (tuple) {
|
|
4689
|
+
position += tuple.fields.length;
|
|
4690
|
+
continue;
|
|
4691
|
+
}
|
|
4692
|
+
if (restAt < 0 || position < restAt || shapes[restAt].mode !== "rest")
|
|
4693
|
+
return true;
|
|
4694
|
+
}
|
|
4695
|
+
position++;
|
|
4696
|
+
}
|
|
4697
|
+
return false;
|
|
4476
4698
|
}
|
|
4477
4699
|
/** METHOD calls on dyn receivers (`pkg.name.replace(...)`, `rawName.split`,
|
|
4478
4700
|
* `ws.packages.filter(...)` — JSON.parse-derived values): validate the
|
|
@@ -4500,8 +4722,9 @@ function lowerDynReceiverMethodCall(lowerer, call, access) {
|
|
|
4500
4722
|
const anyArray = arrayReceiver &&
|
|
4501
4723
|
((lowerer.checker.getTypeArguments(recvTs)[0]?.flags ?? 0) &
|
|
4502
4724
|
(ts.TypeFlags.Any | ts.TypeFlags.Unknown)) !== 0;
|
|
4725
|
+
const checkerUntyped = (recvTs.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) !== 0 || anyArray;
|
|
4503
4726
|
let recv;
|
|
4504
|
-
if (
|
|
4727
|
+
if (checkerUntyped) {
|
|
4505
4728
|
recv = lowerer.lowerExpr(access.expression);
|
|
4506
4729
|
}
|
|
4507
4730
|
else {
|
|
@@ -4590,7 +4813,23 @@ function lowerDynReceiverMethodCall(lowerer, call, access) {
|
|
|
4590
4813
|
// member models. Order note: JS reads the callee before evaluating
|
|
4591
4814
|
// arguments — dynKeyGet's undefined-receiver TypeError fires first,
|
|
4592
4815
|
// exactly Node.
|
|
4593
|
-
|
|
4816
|
+
// A checker-typed object whose represented value remains dyn still
|
|
4817
|
+
// has an authored own-member contract. Let that member win even when
|
|
4818
|
+
// its name overlaps a primitive prototype (`colors.bold(...)`): the
|
|
4819
|
+
// source value was compiled from that object shape, while genuinely
|
|
4820
|
+
// untyped/any receivers retain the runtime-kind ambiguity and fence.
|
|
4821
|
+
const ownCallable = !checkerUntyped && (() => {
|
|
4822
|
+
const prop = lowerer.checker.getPropertyOfType(recvTs, access.name.text);
|
|
4823
|
+
if (prop === undefined)
|
|
4824
|
+
return false;
|
|
4825
|
+
// getPropertyOfType includes inherited Object.prototype members.
|
|
4826
|
+
// Those are not stored members of a checked-dynamic object, so
|
|
4827
|
+
// dynKeyGet cannot stand in for JavaScript's prototype lookup. Only
|
|
4828
|
+
// an authored declaration can justify the own-member path.
|
|
4829
|
+
const authored = lowerer.checker.declarationsOf(prop).some((decl) => !lowerer.isStdlibFile(decl.getSourceFile()));
|
|
4830
|
+
return authored && lowerer.checker.getCallSignatures(lowerer.checker.getTypeOfSymbol(prop)).length > 0;
|
|
4831
|
+
})();
|
|
4832
|
+
if (DYN_PROTO_METHOD_NAMES.has(access.name.text) && !ownCallable)
|
|
4594
4833
|
return null;
|
|
4595
4834
|
// Optional forms (`obj.cb?.()`, `obj?.cb()`) belong to the chain
|
|
4596
4835
|
// machinery's short-circuit semantics — not modeled here yet.
|
|
@@ -5522,30 +5761,50 @@ function loweredTemplateStrings(lowerer, expr, cooked, loc) {
|
|
|
5522
5761
|
* same collection lists top-level declarations ride. */
|
|
5523
5762
|
export function isTopLevelFnSymbol(lowerer, ident) {
|
|
5524
5763
|
const symbol = lowerer.resolveValueSymbol(ident);
|
|
5764
|
+
if (symbol && lowerer.staticCallables.get(symbol)?.kind === "declared-function")
|
|
5765
|
+
return true;
|
|
5525
5766
|
const decl = symbol ? lowerer.checker.declarationsOf(symbol)[0] : undefined;
|
|
5526
5767
|
return (!!decl &&
|
|
5527
5768
|
ts.isFunctionDeclaration(decl) &&
|
|
5528
5769
|
(ts.isSourceFile(decl.parent) || lowerer.nsBlocks.get(decl.parent) === "flattened"));
|
|
5529
5770
|
}
|
|
5530
|
-
/** Nested `function name(...) {...}`:
|
|
5531
|
-
*
|
|
5532
|
-
*
|
|
5533
|
-
*
|
|
5534
|
-
*
|
|
5535
|
-
*
|
|
5771
|
+
/** Nested `function name(...) {...}`: declare the mutable function binding
|
|
5772
|
+
* before lowering its body, then initialize it with the lifted closure.
|
|
5773
|
+
* The early declaration is observable only when another nested closure
|
|
5774
|
+
* captures the binding: its box must exist before either side of a mutual
|
|
5775
|
+
* recursion cycle builds its closure. Forward source references use the
|
|
5776
|
+
* same split declaration/assignment through predeclareForwardFnDecl.
|
|
5777
|
+
* Self-references inside the body lower to `selfRef`, not a capture: a box
|
|
5778
|
+
* holding its own closure would be an RC cycle. */
|
|
5536
5779
|
export function lowerNestedFunctionDecl(lowerer, stmt) {
|
|
5537
5780
|
if (!stmt.name)
|
|
5538
5781
|
lowerer.unsupported("SC1090", stmt, "anonymous function declarations");
|
|
5539
5782
|
const { funcType } = lowerer.lambdaSignature(stmt);
|
|
5540
|
-
|
|
5783
|
+
// Function declaration bindings are mutable in JavaScript. More
|
|
5784
|
+
// importantly, putting the empty slot into the owning statement list
|
|
5785
|
+
// BEFORE lowerLambda lets a sibling lowered from that body capture this
|
|
5786
|
+
// local's eventual box. The local object may become boxed while either
|
|
5787
|
+
// body lowers; backends inspect its final shape when emitting varDecl.
|
|
5788
|
+
const local = lowerer.declareLocal(stmt.name, stmt.name.text, funcType, true);
|
|
5789
|
+
let declared = false;
|
|
5790
|
+
for (let i = lowerer.activeStmtLists.length - 1; i >= 0; i--) {
|
|
5791
|
+
const entry = lowerer.activeStmtLists[i];
|
|
5792
|
+
if (entry.ctx !== lowerer.ctx || !entry.stmts.includes(stmt))
|
|
5793
|
+
continue;
|
|
5794
|
+
entry.out.push({ kind: "varDecl", localId: local.id, init: null, loc: locOf(stmt) });
|
|
5795
|
+
declared = true;
|
|
5796
|
+
break;
|
|
5797
|
+
}
|
|
5798
|
+
if (!declared) {
|
|
5799
|
+
throw new InternalCompilerError("lowerer bug: nested function declaration has no active statement list");
|
|
5800
|
+
}
|
|
5541
5801
|
const init = lowerer.lowerLambda(stmt);
|
|
5542
|
-
return { kind: "
|
|
5802
|
+
return { kind: "assign", localId: local.id, value: init, loc: locOf(stmt) };
|
|
5543
5803
|
}
|
|
5544
5804
|
/** Signature checks + param shapes + IR func type for any lambda-like
|
|
5545
|
-
* node. The func type's params are the ABI types
|
|
5546
|
-
*
|
|
5547
|
-
*
|
|
5548
|
-
* value rule (requireExactArityValue decides who may become a value). */
|
|
5805
|
+
* node. The func type's params are the ABI types: optional/default params
|
|
5806
|
+
* become `T | undefined`, and typed rest becomes one packed-array slot.
|
|
5807
|
+
* requireExactArityValue decides whether that completed ABI may escape. */
|
|
5549
5808
|
export function lambdaSignature(lowerer, node) {
|
|
5550
5809
|
if (!node.body)
|
|
5551
5810
|
lowerer.unsupported("SC1090", node, "function overload signatures");
|
|
@@ -5645,7 +5904,6 @@ export function lambdaSignature(lowerer, node) {
|
|
|
5645
5904
|
// use a rest parameter. Arrows never claim it (JS: an arrow's
|
|
5646
5905
|
// `arguments` is the enclosing function's).
|
|
5647
5906
|
const hasDynRest = shapes.some((s) => s.mode === "dynRest");
|
|
5648
|
-
const hasIslandRest = shapes.some((s) => s.mode === "islandRest");
|
|
5649
5907
|
const usesArguments = !hasDynRest &&
|
|
5650
5908
|
!ts.isArrowFunction(node) &&
|
|
5651
5909
|
isJsSourceFile(node.getSourceFile()) &&
|
|
@@ -5653,20 +5911,10 @@ export function lambdaSignature(lowerer, node) {
|
|
|
5653
5911
|
if (usesArguments && node.parameters.length > 0) {
|
|
5654
5912
|
lowerer.unsupported("SC1090", node, "'arguments' in functions with declared parameters (use a rest parameter: (...args))");
|
|
5655
5913
|
}
|
|
5656
|
-
|
|
5657
|
-
|
|
5658
|
-
funcType
|
|
5659
|
-
|
|
5660
|
-
// dynRest is EXCLUDED (the boxed thunk fills the trailing dyn
|
|
5661
|
-
// array — no spelled slot); islandRest is INCLUDED (the trailing
|
|
5662
|
-
// jsval param IS the engine arguments array, the REST host-call
|
|
5663
|
-
// adapter's one uniform shape).
|
|
5664
|
-
params: shapes.filter((s) => s.mode !== "dynRest").map((s) => s.type),
|
|
5665
|
-
ret,
|
|
5666
|
-
...(hasDynRest || usesArguments || hasIslandRest ? { rest: true } : {}),
|
|
5667
|
-
...(hasIslandRest ? { restAbi: "jsval" } : {}),
|
|
5668
|
-
},
|
|
5669
|
-
};
|
|
5914
|
+
const funcType = funcTypeFromParamShapes(shapes, ret);
|
|
5915
|
+
if (usesArguments && !hasDynRest)
|
|
5916
|
+
funcType.rest = true;
|
|
5917
|
+
return { shapes, funcType };
|
|
5670
5918
|
}
|
|
5671
5919
|
/** Does this function's OWN body read `arguments`? Nested plain functions
|
|
5672
5920
|
* and methods have their own `arguments` (the walk skips them); arrows
|
|
@@ -5699,7 +5947,7 @@ export function bodyReadsArguments(fn) {
|
|
|
5699
5947
|
export function lowerLambda(lowerer, node) {
|
|
5700
5948
|
const loc = locOf(node);
|
|
5701
5949
|
const { shapes, funcType } = lowerer.lambdaSignature(node);
|
|
5702
|
-
// A lambda IS a value: the
|
|
5950
|
+
// A lambda IS a value: the completed-ABI rule applies at birth. The
|
|
5703
5951
|
// contextual (target) type decides — `(x?: number) => void` may flow
|
|
5704
5952
|
// into a slot annotated `(x: number | undefined) => void` (same ABI
|
|
5705
5953
|
// signature), anything else is fenced. Nested function declarations and
|
|
@@ -5765,11 +6013,13 @@ export function lowerLambda(lowerer, node) {
|
|
|
5765
6013
|
// the validator's bare-unitLit rule (typeCheckReturnExpression).
|
|
5766
6014
|
// A `void e` body rides the statement lowering (the value is
|
|
5767
6015
|
// discarded here, so the operand evaluates for effect alone —
|
|
5768
|
-
// `(name) => void doThing(name)`, the fire-and-forget arrow).
|
|
6016
|
+
// `(name) => void doThing(name)`, the fire-and-forget arrow). A
|
|
6017
|
+
// conditional body does the same so its void arms become lazy
|
|
6018
|
+
// statement branches instead of a forbidden void-valued ternary.
|
|
5769
6019
|
let stripped = bodyExpr;
|
|
5770
6020
|
while (ts.isParenthesizedExpression(stripped))
|
|
5771
6021
|
stripped = stripped.expression;
|
|
5772
|
-
if (ts.isVoidExpression(stripped)) {
|
|
6022
|
+
if (ts.isVoidExpression(stripped) || ts.isConditionalExpression(stripped)) {
|
|
5773
6023
|
body = [lowerer.lowerExprStatement(stripped)];
|
|
5774
6024
|
}
|
|
5775
6025
|
else {
|
|
@@ -5844,7 +6094,7 @@ export function lowerLambda(lowerer, node) {
|
|
|
5844
6094
|
// closure-signature check trips (SC9001). Island rest types SPELL
|
|
5845
6095
|
// their trailing engine-array param, so funcType.params already
|
|
5846
6096
|
// covers those.
|
|
5847
|
-
if (funcType.rest === true && funcType.restAbi
|
|
6097
|
+
if (funcType.rest === true && funcType.restAbi === undefined) {
|
|
5848
6098
|
params.push({ localId: "%pfrest", name: "%pfrest", type: DYN });
|
|
5849
6099
|
}
|
|
5850
6100
|
const fence = lowerer.deferToRuntimeFence(diagsBefore, node, {
|
|
@@ -5899,13 +6149,16 @@ export function lowerLambda(lowerer, node) {
|
|
|
5899
6149
|
* to a promise-of-jsval local or module global answers the binding's
|
|
5900
6150
|
* type. Null everywhere else. */
|
|
5901
6151
|
function islandPromiseStorageTypeOf(lowerer, e) {
|
|
5902
|
-
const direct =
|
|
6152
|
+
const direct = lowerer.dynamic
|
|
6153
|
+
? importCallHandleType(e)
|
|
6154
|
+
: staticImportNamespaceType(lowerer, e);
|
|
5903
6155
|
if (direct?.kind === "promise")
|
|
5904
6156
|
return direct;
|
|
5905
6157
|
if (!ts.isIdentifier(e))
|
|
5906
6158
|
return null;
|
|
5907
6159
|
const local = lowerer.resolveLocal(e);
|
|
5908
|
-
if (local?.type.kind === "promise" &&
|
|
6160
|
+
if (local?.type.kind === "promise" &&
|
|
6161
|
+
(local.type.inner.kind === "jsval" || local.type.inner.kind === "moduleNs"))
|
|
5909
6162
|
return local.type;
|
|
5910
6163
|
if (local)
|
|
5911
6164
|
return null;
|
|
@@ -5913,7 +6166,8 @@ function islandPromiseStorageTypeOf(lowerer, e) {
|
|
|
5913
6166
|
if (sym && sym.flags & ts.SymbolFlags.Alias)
|
|
5914
6167
|
sym = lowerer.checker.getAliasedSymbol(sym);
|
|
5915
6168
|
const g = sym ? lowerer.globalsBySymbol.get(sym) : undefined;
|
|
5916
|
-
if (g?.type.kind === "promise" &&
|
|
6169
|
+
if (g?.type.kind === "promise" &&
|
|
6170
|
+
(g.type.inner.kind === "jsval" || g.type.inner.kind === "moduleNs"))
|
|
5917
6171
|
return g.type;
|
|
5918
6172
|
return null;
|
|
5919
6173
|
}
|
|
@@ -5933,6 +6187,18 @@ function markJsvalHandlerParams(lowerer, handler) {
|
|
|
5933
6187
|
}
|
|
5934
6188
|
}
|
|
5935
6189
|
}
|
|
6190
|
+
function markModuleNsHandlerParams(lowerer, handler, type) {
|
|
6191
|
+
let e = handler;
|
|
6192
|
+
while (ts.isParenthesizedExpression(e))
|
|
6193
|
+
e = e.expression;
|
|
6194
|
+
if (!ts.isArrowFunction(e) && !ts.isFunctionExpression(e))
|
|
6195
|
+
return;
|
|
6196
|
+
for (const p of e.parameters) {
|
|
6197
|
+
if (ts.isIdentifier(p.name) && !p.dotDotDotToken && !p.initializer) {
|
|
6198
|
+
lowerer.moduleNsParamOverrides.set(p, type);
|
|
6199
|
+
}
|
|
6200
|
+
}
|
|
6201
|
+
}
|
|
5936
6202
|
export function lowerPromiseMethodCall(lowerer, call, access) {
|
|
5937
6203
|
if (call.questionDotToken || access.questionDotToken)
|
|
5938
6204
|
return null;
|
|
@@ -5946,7 +6212,7 @@ export function lowerPromiseMethodCall(lowerer, call, access) {
|
|
|
5946
6212
|
// (importCallHandleType / the island-HANDLE var rules), so the storage
|
|
5947
6213
|
// type is the receiver's truth. Direct `import("./m").then(...)`
|
|
5948
6214
|
// spells the same promise with no binding at all.
|
|
5949
|
-
if (!recvT
|
|
6215
|
+
if (!recvT)
|
|
5950
6216
|
recvT = islandPromiseStorageTypeOf(lowerer, access.expression);
|
|
5951
6217
|
if (recvT?.kind !== "promise")
|
|
5952
6218
|
return null;
|
|
@@ -6051,6 +6317,8 @@ export function lowerPromiseMethodCall(lowerer, call, access) {
|
|
|
6051
6317
|
// the handle is the value's only story, isIslandExpr's local rule).
|
|
6052
6318
|
if (inner.kind === "jsval")
|
|
6053
6319
|
markJsvalHandlerParams(lowerer, call.arguments[0]);
|
|
6320
|
+
if (inner.kind === "moduleNs")
|
|
6321
|
+
markModuleNsHandlerParams(lowerer, call.arguments[0], inner);
|
|
6054
6322
|
let cb = lowerer.lowerExpr(call.arguments[0]);
|
|
6055
6323
|
// A TYPED handler on a DYN-settling promise (the tracePromise
|
|
6056
6324
|
// result's `.then((value) => ...)` — the checker's generic
|
|
@@ -6769,6 +7037,48 @@ function lowerSymbolStaticCall(lowerer, call, access) {
|
|
|
6769
7037
|
}
|
|
6770
7038
|
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)`);
|
|
6771
7039
|
}
|
|
7040
|
+
function lowerBigIntStaticCall(lowerer, call, access) {
|
|
7041
|
+
if (call.questionDotToken || access.questionDotToken)
|
|
7042
|
+
return null;
|
|
7043
|
+
if (!lowerer.isStdlibGlobal(access.expression, "BigInt"))
|
|
7044
|
+
return null;
|
|
7045
|
+
const name = access.name.text;
|
|
7046
|
+
if (name !== "asUintN" && name !== "asIntN")
|
|
7047
|
+
return null;
|
|
7048
|
+
if (call.arguments.length !== 2) {
|
|
7049
|
+
lowerer.noLowering(`BigInt.${name} with ${call.arguments.length} arguments`, call);
|
|
7050
|
+
}
|
|
7051
|
+
const loc = locOf(call);
|
|
7052
|
+
const bits = lowerer.lowerExprExpecting(call.arguments[0], F64);
|
|
7053
|
+
const value = lowerer.lowerExprExpecting(call.arguments[1], BIGINT_T);
|
|
7054
|
+
return {
|
|
7055
|
+
kind: "libCall",
|
|
7056
|
+
fn: name === "asUintN" ? "bigint.asUintN" : "bigint.asIntN",
|
|
7057
|
+
args: [bits, value],
|
|
7058
|
+
type: BIGINT_T,
|
|
7059
|
+
loc,
|
|
7060
|
+
};
|
|
7061
|
+
}
|
|
7062
|
+
function lowerBigIntMethodCall(lowerer, call, access) {
|
|
7063
|
+
if (lowerer.mapTypeOf(lowerer.typeOf(access.expression))?.kind !== "bigint")
|
|
7064
|
+
return null;
|
|
7065
|
+
if (!lowerer.isStdlibMember(access))
|
|
7066
|
+
return null;
|
|
7067
|
+
const name = access.name.text;
|
|
7068
|
+
const loc = locOf(call);
|
|
7069
|
+
const receiver = lowerer.lowerExpr(access.expression);
|
|
7070
|
+
if (receiver.type.kind !== "bigint")
|
|
7071
|
+
return null;
|
|
7072
|
+
if (name === "valueOf" && call.arguments.length === 0)
|
|
7073
|
+
return receiver;
|
|
7074
|
+
if (name === "toString" && call.arguments.length <= 1) {
|
|
7075
|
+
const radix = call.arguments[0]
|
|
7076
|
+
? lowerer.lowerExprExpecting(call.arguments[0], F64)
|
|
7077
|
+
: { kind: "numLit", value: 10, type: F64, loc };
|
|
7078
|
+
return { kind: "libCall", fn: "bigint.toString", args: [receiver, radix], type: STRING, loc };
|
|
7079
|
+
}
|
|
7080
|
+
return null;
|
|
7081
|
+
}
|
|
6772
7082
|
/** Method calls on symbol-typed receivers: `.toString()` is the
|
|
6773
7083
|
* "Symbol(desc)" text (Node's Symbol.prototype.toString — note that
|
|
6774
7084
|
* template literals and concatenation THROW in JS and stay fenced;
|
|
@@ -7509,6 +7819,48 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
7509
7819
|
if (call.arguments.length !== 1 || ts.isSpreadElement(call.arguments[0]))
|
|
7510
7820
|
return null;
|
|
7511
7821
|
const argNode = call.arguments[0];
|
|
7822
|
+
// A compiled PROGRAM module namespace is a nominal token whose members
|
|
7823
|
+
// remain live bindings, but its enumerable key set is static and Node
|
|
7824
|
+
// sorts it in code-unit order. Materialize exactly those value-export
|
|
7825
|
+
// names for Object.keys; values/entries would need a heterogeneous live
|
|
7826
|
+
// view and stay explicitly fenced. Builtin namespaces also stay fenced:
|
|
7827
|
+
// their exact runtime export set is Node-owned, not the ambient subset.
|
|
7828
|
+
{
|
|
7829
|
+
const probed = tryLowerExpression(lowerer, argNode);
|
|
7830
|
+
if (probed?.type.kind === "moduleNs") {
|
|
7831
|
+
if (member !== "keys") {
|
|
7832
|
+
lowerer.noLowering(`Object.${member} over a module namespace`, call, "read the named exports directly (module namespace values are live and may have heterogeneous representations)");
|
|
7833
|
+
}
|
|
7834
|
+
const source = lowerer.sourceFileOfModuleNamespace(probed.type);
|
|
7835
|
+
if (source === null) {
|
|
7836
|
+
lowerer.noLowering("Object.keys over a builtin module namespace", call, "access the builtin's named exports directly (the exact runtime key census is Node-owned)");
|
|
7837
|
+
}
|
|
7838
|
+
const moduleSymbol = source ? lowerer.checker.getSymbolAtLocation(source) : undefined;
|
|
7839
|
+
const names = [];
|
|
7840
|
+
moduleSymbol?.getExports().forEach((symbol, key) => {
|
|
7841
|
+
const name = String(key);
|
|
7842
|
+
if (name.startsWith("__") || name === "export=")
|
|
7843
|
+
return;
|
|
7844
|
+
const target = symbol.flags & ts.SymbolFlags.Alias
|
|
7845
|
+
? lowerer.checker.getAliasedSymbol(symbol)
|
|
7846
|
+
: symbol;
|
|
7847
|
+
if (target.flags & ts.SymbolFlags.Value)
|
|
7848
|
+
names.push(name);
|
|
7849
|
+
});
|
|
7850
|
+
names.sort();
|
|
7851
|
+
const loc = locOf(call);
|
|
7852
|
+
const result = {
|
|
7853
|
+
kind: "arrayLit",
|
|
7854
|
+
elems: names.map((name) => ({ kind: "strLit", value: name, type: STRING, loc })),
|
|
7855
|
+
type: arrayOf(STRING),
|
|
7856
|
+
loc,
|
|
7857
|
+
};
|
|
7858
|
+
const receiver = lowerer.lowerExpr(argNode);
|
|
7859
|
+
return isSafeToDiscard(receiver)
|
|
7860
|
+
? result
|
|
7861
|
+
: { kind: "seqExpr", stmts: [{ kind: "exprStmt", expr: receiver, loc }], result, type: result.type, loc };
|
|
7862
|
+
}
|
|
7863
|
+
}
|
|
7512
7864
|
// A CHECKED-DYNAMIC argument — the checker may still spell a record
|
|
7513
7865
|
// type (the JS file-scope object-literal identity story stores the
|
|
7514
7866
|
// dyn object), so the LOWERED value's kind is the dispatch: the
|
|
@@ -7893,8 +8245,7 @@ export function lowerRecordFieldCall(lowerer, call, access) {
|
|
|
7893
8245
|
callee = lowerer.hybridCallUnwrap(callee);
|
|
7894
8246
|
if (callee.type.kind !== "func")
|
|
7895
8247
|
lowerer.badType(access, lowerer.typeOf(access));
|
|
7896
|
-
const
|
|
7897
|
-
const args = call.arguments.map((a, i) => lowerer.lowerExprExpecting(a, params[i]));
|
|
8248
|
+
const args = completeFuncValueArgs(lowerer, call, callee.type, locOf(call));
|
|
7898
8249
|
return { kind: "callValue", callee, args, type: callee.type.ret, loc: locOf(call) };
|
|
7899
8250
|
}
|
|
7900
8251
|
/** The function-like node behind an object-literal generic-method member:
|
|
@@ -8748,6 +9099,12 @@ export function lowerObjectMethodCall(lowerer, call, access) {
|
|
|
8748
9099
|
if (lowerer.chainBlocked(access, call))
|
|
8749
9100
|
return null;
|
|
8750
9101
|
const mappedReceiver = lowerer.mapTypeOf(lowerer.typeOf(access.expression));
|
|
9102
|
+
if (mappedReceiver?.kind === "union") {
|
|
9103
|
+
const dispatched = lowerUnionObjectMethodCall(lowerer, call, access, mappedReceiver) ??
|
|
9104
|
+
lowerUnionObjectDynFieldCall(lowerer, call, access, mappedReceiver);
|
|
9105
|
+
if (dispatched)
|
|
9106
|
+
return dispatched;
|
|
9107
|
+
}
|
|
8751
9108
|
const receiverIr = mappedReceiver?.kind === "object"
|
|
8752
9109
|
? mappedReceiver
|
|
8753
9110
|
: mappedReceiver?.kind === "union"
|
|
@@ -8829,15 +9186,7 @@ export function lowerObjectMethodCall(lowerer, call, access) {
|
|
|
8829
9186
|
}
|
|
8830
9187
|
}
|
|
8831
9188
|
if (callee?.type.kind === "func") {
|
|
8832
|
-
const
|
|
8833
|
-
const args = call.arguments.map((a, i) => lowerer.lowerExprExpecting(a, params[i]));
|
|
8834
|
-
for (let i = args.length; i < params.length; i++) {
|
|
8835
|
-
const absent = omittedArgFor(lowerer, params[i], locOf(call));
|
|
8836
|
-
if (!absent) {
|
|
8837
|
-
lowerer.unsupported("SC1090", call, "calls omitting a non-optional parameter of the callee's type");
|
|
8838
|
-
}
|
|
8839
|
-
args.push(absent);
|
|
8840
|
-
}
|
|
9189
|
+
const args = completeFuncValueArgs(lowerer, call, callee.type, locOf(call));
|
|
8841
9190
|
return { kind: "callValue", callee, args, type: callee.type.ret, loc: locOf(call) };
|
|
8842
9191
|
}
|
|
8843
9192
|
if (callee?.type.kind === "dyn") {
|
|
@@ -8899,4 +9248,205 @@ export function lowerObjectMethodCall(lowerer, call, access) {
|
|
|
8899
9248
|
loc: locOf(call),
|
|
8900
9249
|
});
|
|
8901
9250
|
}
|
|
9251
|
+
/** A method TypeScript proves callable on every arm of an unrelated class
|
|
9252
|
+
* union. Each runtime tag keeps its own direct/virtual dispatch; only the
|
|
9253
|
+
* completed argument ABI must agree. Results flow into the checker-selected
|
|
9254
|
+
* call type through the ordinary wrap/retag/width machinery. */
|
|
9255
|
+
function lowerUnionObjectMethodCall(lowerer, call, access, receiverT) {
|
|
9256
|
+
const def = lowerer.unions.get(receiverT.unionId);
|
|
9257
|
+
if (!def || def.arms.length < 2 || !def.arms.every((arm) => arm.kind === "object"))
|
|
9258
|
+
return null;
|
|
9259
|
+
const method = access.name.text;
|
|
9260
|
+
const plans = [];
|
|
9261
|
+
for (const arm of def.arms) {
|
|
9262
|
+
const info = lowerer.classes.get(arm.className);
|
|
9263
|
+
if (!info) {
|
|
9264
|
+
lowerer.flushDeferredClass(arm.className);
|
|
9265
|
+
return null;
|
|
9266
|
+
}
|
|
9267
|
+
const found = lowerer.findMethodOn(info, method);
|
|
9268
|
+
if (!found)
|
|
9269
|
+
return null;
|
|
9270
|
+
if (found.sig.abstract === true && !lowerer.overrideBelow(info, method))
|
|
9271
|
+
return null;
|
|
9272
|
+
plans.push({ arm, info, found });
|
|
9273
|
+
}
|
|
9274
|
+
const shapes = plans[0].found.sig.params;
|
|
9275
|
+
if (!plans.every((plan) => paramAbisEqual(shapes, plan.found.sig.params)))
|
|
9276
|
+
return null;
|
|
9277
|
+
const resultT = lowerer.mapTypeOf(lowerer.typeOf(call));
|
|
9278
|
+
if (!resultT || isUnitType(resultT))
|
|
9279
|
+
return null;
|
|
9280
|
+
const loc = locOf(call);
|
|
9281
|
+
const receiver = lowerer.coerceInto(access.expression, lowerer.lowerExpr(access.expression), receiverT);
|
|
9282
|
+
const args = lowerer.completeArgs(call.arguments, shapes, loc, call);
|
|
9283
|
+
const helper = unionObjectMethodHelper(lowerer, call, receiverT, method, plans, shapes, resultT, loc);
|
|
9284
|
+
return { kind: "call", callee: helper, args: [receiver, ...args], type: resultT, loc };
|
|
9285
|
+
}
|
|
9286
|
+
function paramAbisEqual(left, right) {
|
|
9287
|
+
return left.length === right.length && left.every((shape, i) => {
|
|
9288
|
+
const other = right[i];
|
|
9289
|
+
return other !== undefined && shape.mode === other.mode && typeEquals(shape.type, other.type);
|
|
9290
|
+
});
|
|
9291
|
+
}
|
|
9292
|
+
/** The JS-class sibling of union method dispatch: every arm stores the
|
|
9293
|
+
* named callable in a checked-dynamic field. A helper selects and retains
|
|
9294
|
+
* the field value before the dynCall evaluates its source arguments, so an
|
|
9295
|
+
* argument that overwrites the field cannot change this invocation. */
|
|
9296
|
+
function lowerUnionObjectDynFieldCall(lowerer, call, access, receiverT) {
|
|
9297
|
+
const def = lowerer.unions.get(receiverT.unionId);
|
|
9298
|
+
if (!def || def.arms.length < 2 || !def.arms.every((arm) => arm.kind === "object"))
|
|
9299
|
+
return null;
|
|
9300
|
+
const field = access.name.text;
|
|
9301
|
+
const plans = [];
|
|
9302
|
+
for (const arm of def.arms) {
|
|
9303
|
+
const info = lowerer.classes.get(arm.className);
|
|
9304
|
+
if (!info || info.fields.get(field)?.kind !== "dyn")
|
|
9305
|
+
return null;
|
|
9306
|
+
plans.push({ arm, info });
|
|
9307
|
+
}
|
|
9308
|
+
if (call.arguments.some(ts.isSpreadElement)) {
|
|
9309
|
+
lowerer.unsupported("SC1090", call, "spread arguments in calls through 'unknown' values");
|
|
9310
|
+
}
|
|
9311
|
+
const loc = locOf(call);
|
|
9312
|
+
const receiver = lowerer.coerceInto(access.expression, lowerer.lowerExpr(access.expression), receiverT);
|
|
9313
|
+
const key = `${receiverT.unionId}:dyn-field:${field}`;
|
|
9314
|
+
let helper = lowerer.unionCallHelpers.get(key);
|
|
9315
|
+
if (!helper) {
|
|
9316
|
+
helper = `%union.call.${lowerer.unionCallHelpers.size}`;
|
|
9317
|
+
lowerer.unionCallHelpers.set(key, helper);
|
|
9318
|
+
const receiverRef = varRef("this.0", receiverT, loc);
|
|
9319
|
+
const branch = (plan) => {
|
|
9320
|
+
const concrete = {
|
|
9321
|
+
kind: "unionNarrow",
|
|
9322
|
+
unionId: receiverT.unionId,
|
|
9323
|
+
tag: lowerer.armTag(receiverT.unionId, plan.arm),
|
|
9324
|
+
value: receiverRef,
|
|
9325
|
+
type: plan.arm,
|
|
9326
|
+
loc,
|
|
9327
|
+
};
|
|
9328
|
+
return [{
|
|
9329
|
+
kind: "return",
|
|
9330
|
+
value: {
|
|
9331
|
+
kind: "fieldGet",
|
|
9332
|
+
obj: concrete,
|
|
9333
|
+
className: plan.info.def.name,
|
|
9334
|
+
field,
|
|
9335
|
+
type: DYN,
|
|
9336
|
+
loc,
|
|
9337
|
+
},
|
|
9338
|
+
loc,
|
|
9339
|
+
}];
|
|
9340
|
+
};
|
|
9341
|
+
let body = branch(plans[plans.length - 1]);
|
|
9342
|
+
for (let i = plans.length - 2; i >= 0; i--) {
|
|
9343
|
+
const plan = plans[i];
|
|
9344
|
+
body = [{
|
|
9345
|
+
kind: "if",
|
|
9346
|
+
cond: {
|
|
9347
|
+
kind: "unionIsTag",
|
|
9348
|
+
unionId: receiverT.unionId,
|
|
9349
|
+
tag: lowerer.armTag(receiverT.unionId, plan.arm),
|
|
9350
|
+
negated: false,
|
|
9351
|
+
value: receiverRef,
|
|
9352
|
+
type: BOOL,
|
|
9353
|
+
loc,
|
|
9354
|
+
},
|
|
9355
|
+
then: branch(plan),
|
|
9356
|
+
else_: body,
|
|
9357
|
+
loc,
|
|
9358
|
+
}];
|
|
9359
|
+
}
|
|
9360
|
+
const params = [
|
|
9361
|
+
{ localId: "this.0", name: "this", type: receiverT },
|
|
9362
|
+
];
|
|
9363
|
+
const locals = params.map((param) => ({ id: param.localId, name: param.name, type: param.type, mutable: false }));
|
|
9364
|
+
lowerer.liftedFns.push({ name: helper, params, returnType: DYN, locals, body, loc });
|
|
9365
|
+
}
|
|
9366
|
+
const callee = { kind: "call", callee: helper, args: [receiver], type: DYN, loc };
|
|
9367
|
+
const args = call.arguments.map((arg) => lowerer.lowerExprExpecting(arg, DYN));
|
|
9368
|
+
return { kind: "dynCall", callee, calleeName: access.getText(), args, type: DYN, loc };
|
|
9369
|
+
}
|
|
9370
|
+
function unionObjectMethodHelper(lowerer, sourceCall, receiverT, method, plans, shapes, resultT, loc) {
|
|
9371
|
+
const key = `${receiverT.unionId}:${method}:${shapes.map((shape) => `${shape.mode}:${typeKey(shape.type)}`).join(",")}:${typeKey(resultT)}`;
|
|
9372
|
+
const existing = lowerer.unionCallHelpers.get(key);
|
|
9373
|
+
if (existing)
|
|
9374
|
+
return existing;
|
|
9375
|
+
const name = `%union.call.${lowerer.unionCallHelpers.size}`;
|
|
9376
|
+
lowerer.unionCallHelpers.set(key, name);
|
|
9377
|
+
const receiver = varRef("this.0", receiverT, loc);
|
|
9378
|
+
const argRefs = shapes.map((shape, i) => varRef(`a.${i}`, shape.type, loc));
|
|
9379
|
+
const branch = (plan) => {
|
|
9380
|
+
const concrete = {
|
|
9381
|
+
kind: "unionNarrow",
|
|
9382
|
+
unionId: receiverT.unionId,
|
|
9383
|
+
tag: lowerer.armTag(receiverT.unionId, plan.arm),
|
|
9384
|
+
value: receiver,
|
|
9385
|
+
type: plan.arm,
|
|
9386
|
+
loc,
|
|
9387
|
+
};
|
|
9388
|
+
let invoke;
|
|
9389
|
+
if (plan.found.declarer.builtinError) {
|
|
9390
|
+
invoke = {
|
|
9391
|
+
kind: "libCall",
|
|
9392
|
+
fn: "error.toString",
|
|
9393
|
+
args: [lowerer.upcastTo(concrete, plan.found.declarer.def.name)],
|
|
9394
|
+
type: STRING,
|
|
9395
|
+
loc,
|
|
9396
|
+
};
|
|
9397
|
+
}
|
|
9398
|
+
else if (lowerer.overrideBelow(plan.info, method)) {
|
|
9399
|
+
lowerer.noteVirtualEdge(plan.info, method);
|
|
9400
|
+
invoke = {
|
|
9401
|
+
kind: "virtualCall",
|
|
9402
|
+
className: plan.info.def.name,
|
|
9403
|
+
method,
|
|
9404
|
+
args: [lowerer.upcastTo(concrete, plan.info.def.name), ...argRefs],
|
|
9405
|
+
type: plan.found.sig.ret,
|
|
9406
|
+
loc,
|
|
9407
|
+
};
|
|
9408
|
+
}
|
|
9409
|
+
else {
|
|
9410
|
+
lowerer.noteEdge(`%${plan.found.declarer.def.name}.${method}`);
|
|
9411
|
+
invoke = {
|
|
9412
|
+
kind: "call",
|
|
9413
|
+
callee: `%${plan.found.declarer.def.name}.${method}`,
|
|
9414
|
+
args: [lowerer.upcastTo(concrete, plan.found.declarer.def.name), ...argRefs],
|
|
9415
|
+
type: plan.found.sig.ret,
|
|
9416
|
+
loc,
|
|
9417
|
+
};
|
|
9418
|
+
}
|
|
9419
|
+
invoke = reconcileOverloadReturn(lowerer, sourceCall, invoke);
|
|
9420
|
+
const result = lowerer.coerceInto(sourceCall, invoke, resultT);
|
|
9421
|
+
return resultT.kind === "void"
|
|
9422
|
+
? [{ kind: "exprStmt", expr: result, loc }, { kind: "return", value: null, loc }]
|
|
9423
|
+
: [{ kind: "return", value: result, loc }];
|
|
9424
|
+
};
|
|
9425
|
+
let body = branch(plans[plans.length - 1]);
|
|
9426
|
+
for (let i = plans.length - 2; i >= 0; i--) {
|
|
9427
|
+
const plan = plans[i];
|
|
9428
|
+
body = [{
|
|
9429
|
+
kind: "if",
|
|
9430
|
+
cond: {
|
|
9431
|
+
kind: "unionIsTag",
|
|
9432
|
+
unionId: receiverT.unionId,
|
|
9433
|
+
tag: lowerer.armTag(receiverT.unionId, plan.arm),
|
|
9434
|
+
negated: false,
|
|
9435
|
+
value: receiver,
|
|
9436
|
+
type: BOOL,
|
|
9437
|
+
loc,
|
|
9438
|
+
},
|
|
9439
|
+
then: branch(plan),
|
|
9440
|
+
else_: body,
|
|
9441
|
+
loc,
|
|
9442
|
+
}];
|
|
9443
|
+
}
|
|
9444
|
+
const params = [
|
|
9445
|
+
{ localId: "this.0", name: "this", type: receiverT },
|
|
9446
|
+
...shapes.map((shape, i) => ({ localId: `a.${i}`, name: `a${i}`, type: shape.type })),
|
|
9447
|
+
];
|
|
9448
|
+
const locals = params.map((param) => ({ id: param.localId, name: param.name, type: param.type, mutable: false }));
|
|
9449
|
+
lowerer.liftedFns.push({ name, params, returnType: resultT, locals, body, loc });
|
|
9450
|
+
return name;
|
|
9451
|
+
}
|
|
8902
9452
|
//# sourceMappingURL=lower-calls.js.map
|