@scriptc/compiler 0.2.1 → 0.2.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 +158 -31
- package/dist/backend/cycle-analysis.js +63 -50
- package/dist/backend/cycle-analysis.js.map +1 -1
- package/dist/backend/cycle-analysis.test.js +51 -0
- package/dist/backend/cycle-analysis.test.js.map +1 -1
- package/dist/backend/llvm/borrowed-receivers.d.ts +9 -0
- package/dist/backend/llvm/borrowed-receivers.js +58 -0
- package/dist/backend/llvm/borrowed-receivers.js.map +1 -0
- package/dist/backend/llvm/call-lifetimes.d.ts +20 -0
- package/dist/backend/llvm/call-lifetimes.js +179 -0
- package/dist/backend/llvm/call-lifetimes.js.map +1 -0
- package/dist/backend/llvm/call-lifetimes.test.d.ts +1 -0
- package/dist/backend/llvm/call-lifetimes.test.js +205 -0
- package/dist/backend/llvm/call-lifetimes.test.js.map +1 -0
- package/dist/backend/llvm/dyn.d.ts +5 -2
- package/dist/backend/llvm/dyn.js +163 -47
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.d.ts +37 -1
- package/dist/backend/llvm/emitter.js +209 -21
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/emitter.test.js +29 -2
- package/dist/backend/llvm/emitter.test.js.map +1 -1
- package/dist/backend/llvm/expr-async.js +1 -1
- package/dist/backend/llvm/expr-async.js.map +1 -1
- package/dist/backend/llvm/expr-calls.js +42 -5
- package/dist/backend/llvm/expr-calls.js.map +1 -1
- package/dist/backend/llvm/expr-containers.js +75 -13
- package/dist/backend/llvm/expr-containers.js.map +1 -1
- package/dist/backend/llvm/expr-dynamic.js +31 -6
- package/dist/backend/llvm/expr-dynamic.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.js +6 -5
- package/dist/backend/llvm/expr-primitives.js.map +1 -1
- package/dist/backend/llvm/expr-records.js +1 -1
- package/dist/backend/llvm/expr-records.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.js +75 -19
- package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
- package/dist/backend/llvm/expr-stream-callbacks.d.ts +2 -2
- package/dist/backend/llvm/expr-stream-callbacks.js +7 -57
- package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
- package/dist/backend/llvm/lib-dispatch.js +41 -3
- package/dist/backend/llvm/lib-dispatch.js.map +1 -1
- package/dist/backend/llvm/lib-filesystem.js +12 -9
- package/dist/backend/llvm/lib-filesystem.js.map +1 -1
- package/dist/backend/llvm/lib-shared.js +70 -2
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/llvm/local-array-reads.d.ts +44 -0
- package/dist/backend/llvm/local-array-reads.js +313 -0
- package/dist/backend/llvm/local-array-reads.js.map +1 -0
- package/dist/backend/llvm/local-array-reads.test.d.ts +1 -0
- package/dist/backend/llvm/local-array-reads.test.js +446 -0
- package/dist/backend/llvm/local-array-reads.test.js.map +1 -0
- package/dist/backend/llvm/map-read-lifetimes.d.ts +36 -0
- package/dist/backend/llvm/map-read-lifetimes.js +128 -0
- package/dist/backend/llvm/map-read-lifetimes.js.map +1 -0
- package/dist/backend/llvm/map-read-lifetimes.test.d.ts +1 -0
- package/dist/backend/llvm/map-read-lifetimes.test.js +123 -0
- package/dist/backend/llvm/map-read-lifetimes.test.js.map +1 -0
- package/dist/backend/llvm/shapes.js +1 -0
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/llvm/split.js +15 -5
- package/dist/backend/llvm/split.js.map +1 -1
- package/dist/backend/llvm/split.test.js +17 -0
- package/dist/backend/llvm/split.test.js.map +1 -1
- package/dist/backend/llvm/stack-unions.d.ts +20 -0
- package/dist/backend/llvm/stack-unions.js +61 -0
- package/dist/backend/llvm/stack-unions.js.map +1 -0
- package/dist/backend/llvm/stack-unions.test.d.ts +1 -0
- package/dist/backend/llvm/stack-unions.test.js +241 -0
- package/dist/backend/llvm/stack-unions.test.js.map +1 -0
- package/dist/backend/llvm/string-lifetimes.d.ts +12 -0
- package/dist/backend/llvm/string-lifetimes.js +70 -0
- package/dist/backend/llvm/string-lifetimes.js.map +1 -0
- package/dist/backend/llvm/string-lifetimes.test.d.ts +1 -0
- package/dist/backend/llvm/string-lifetimes.test.js +230 -0
- package/dist/backend/llvm/string-lifetimes.test.js.map +1 -0
- package/dist/backend/mangle.d.ts +2 -0
- package/dist/backend/mangle.js +4 -0
- package/dist/backend/mangle.js.map +1 -1
- package/dist/backend/may-throw.js +71 -29
- package/dist/backend/may-throw.js.map +1 -1
- package/dist/backend/may-throw.test.js +104 -1
- package/dist/backend/may-throw.test.js.map +1 -1
- package/dist/backend/native-codegen.d.ts +1 -1
- package/dist/backend/native-codegen.js +4 -3
- package/dist/backend/native-codegen.js.map +1 -1
- package/dist/backend/native-codegen.test.js +11 -0
- package/dist/backend/native-codegen.test.js.map +1 -1
- package/dist/backend/native-toolchain.d.ts +2 -2
- package/dist/backend/native-toolchain.js +2 -0
- package/dist/backend/native-toolchain.js.map +1 -1
- package/dist/backend/target-diagnostics.d.ts +5 -0
- package/dist/backend/target-diagnostics.js +72 -1
- package/dist/backend/target-diagnostics.js.map +1 -1
- package/dist/backend/target-diagnostics.test.d.ts +1 -0
- package/dist/backend/target-diagnostics.test.js +68 -0
- package/dist/backend/target-diagnostics.test.js.map +1 -0
- package/dist/coverage/surface-manifest.js +5 -3
- package/dist/coverage/surface-manifest.js.map +1 -1
- package/dist/executable/executable-cache.d.ts +7 -3
- package/dist/executable/executable-cache.js +47 -11
- package/dist/executable/executable-cache.js.map +1 -1
- package/dist/executable/executable-cache.test.js +109 -2
- package/dist/executable/executable-cache.test.js.map +1 -1
- package/dist/executable/prepare.js +2 -1
- package/dist/executable/prepare.js.map +1 -1
- package/dist/frontend/builtin-modules.d.ts +1 -1
- package/dist/frontend/builtin-modules.js +1 -1
- package/dist/frontend/builtin-modules.js.map +1 -1
- package/dist/frontend/function-completion.d.ts +6 -0
- package/dist/frontend/function-completion.js +50 -0
- package/dist/frontend/function-completion.js.map +1 -0
- package/dist/frontend/input-tracker.js +3 -3
- package/dist/frontend/input-tracker.js.map +1 -1
- package/dist/frontend/input-tracker.test.js +38 -2
- package/dist/frontend/input-tracker.test.js.map +1 -1
- package/dist/frontend/lowering/abstract-equality.js +5 -1
- package/dist/frontend/lowering/abstract-equality.js.map +1 -1
- package/dist/frontend/lowering/checked-iterable-spread.d.ts +4 -0
- package/dist/frontend/lowering/checked-iterable-spread.js +30 -0
- package/dist/frontend/lowering/checked-iterable-spread.js.map +1 -0
- package/dist/frontend/lowering/checked-promise-all.d.ts +5 -0
- package/dist/frontend/lowering/checked-promise-all.js +31 -0
- package/dist/frontend/lowering/checked-promise-all.js.map +1 -0
- package/dist/frontend/lowering/class-callbacks.d.ts +1 -1
- package/dist/frontend/lowering/class-callbacks.js +7 -6
- package/dist/frontend/lowering/class-callbacks.js.map +1 -1
- package/dist/frontend/lowering/class-construction.d.ts +2 -0
- package/dist/frontend/lowering/class-construction.js +34 -5
- package/dist/frontend/lowering/class-construction.js.map +1 -1
- package/dist/frontend/lowering/class-descriptors.d.ts +1 -1
- package/dist/frontend/lowering/class-descriptors.js +12 -5
- package/dist/frontend/lowering/class-descriptors.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +25 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.js +597 -78
- package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js +64 -2
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js.map +1 -1
- package/dist/frontend/lowering/class-instance-constructor.d.ts +1 -1
- package/dist/frontend/lowering/class-instance-constructor.js +11 -41
- package/dist/frontend/lowering/class-instance-constructor.js.map +1 -1
- package/dist/frontend/lowering/class-method-values.d.ts +16 -0
- package/dist/frontend/lowering/class-method-values.js +60 -29
- package/dist/frontend/lowering/class-method-values.js.map +1 -1
- package/dist/frontend/lowering/class-prototypes.d.ts +5 -1
- package/dist/frontend/lowering/class-prototypes.js +69 -10
- package/dist/frontend/lowering/class-prototypes.js.map +1 -1
- package/dist/frontend/lowering/class-runtime-statics.d.ts +4 -4
- package/dist/frontend/lowering/class-runtime-statics.js +26 -8
- package/dist/frontend/lowering/class-runtime-statics.js.map +1 -1
- package/dist/frontend/lowering/class-static-data.d.ts +1 -0
- package/dist/frontend/lowering/class-static-data.js +4 -2
- package/dist/frontend/lowering/class-static-data.js.map +1 -1
- package/dist/frontend/lowering/collection-ingestion.d.ts +31 -0
- package/dist/frontend/lowering/collection-ingestion.js +215 -0
- package/dist/frontend/lowering/collection-ingestion.js.map +1 -0
- package/dist/frontend/lowering/containers/bytes.js +19 -4
- package/dist/frontend/lowering/containers/bytes.js.map +1 -1
- package/dist/frontend/lowering/containers/string-and-regexp.js +6 -1
- package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
- package/dist/frontend/lowering/deferred-module-initializers.d.ts +13 -0
- package/dist/frontend/lowering/deferred-module-initializers.js +410 -0
- package/dist/frontend/lowering/deferred-module-initializers.js.map +1 -0
- package/dist/frontend/lowering/deferred-module-initializers.test.d.ts +1 -0
- package/dist/frontend/lowering/deferred-module-initializers.test.js +92 -0
- package/dist/frontend/lowering/deferred-module-initializers.test.js.map +1 -0
- package/dist/frontend/lowering/expressions/object-literals.js +31 -1
- package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
- package/dist/frontend/lowering/expressions/optional-chains.js +3 -3
- package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
- package/dist/frontend/lowering/import-meta.d.ts +10 -0
- package/dist/frontend/lowering/import-meta.js +52 -0
- package/dist/frontend/lowering/import-meta.js.map +1 -0
- package/dist/frontend/lowering/lower-assert.js +105 -41
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-builtin-values.d.ts +2 -0
- package/dist/frontend/lowering/lower-builtin-values.js +22 -1
- package/dist/frontend/lowering/lower-builtin-values.js.map +1 -1
- package/dist/frontend/lowering/lower-builtins.d.ts +7 -22
- package/dist/frontend/lowering/lower-builtins.js +439 -95
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.js +289 -76
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +5 -0
- package/dist/frontend/lowering/lower-classes.js +443 -29
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.d.ts +6 -2
- package/dist/frontend/lowering/lower-containers.js +79 -20
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +10 -6
- package/dist/frontend/lowering/lower-exprs.js +329 -170
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-generators.js +5 -1
- package/dist/frontend/lowering/lower-generators.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.js +58 -1
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-island.js +4 -0
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-island.test.d.ts +1 -0
- package/dist/frontend/lowering/lower-island.test.js +51 -0
- package/dist/frontend/lowering/lower-island.test.js.map +1 -0
- package/dist/frontend/lowering/lower-modules.d.ts +1 -3
- package/dist/frontend/lowering/lower-modules.js +186 -82
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.test.js +69 -1
- package/dist/frontend/lowering/lower-modules.test.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.js +172 -103
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.test.d.ts +1 -0
- package/dist/frontend/lowering/lower-stmts.test.js +77 -0
- package/dist/frontend/lowering/lower-stmts.test.js.map +1 -0
- package/dist/frontend/lowering/lower-stream.js +2 -0
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lower-system-errors.d.ts +6 -0
- package/dist/frontend/lowering/lower-system-errors.js +29 -0
- package/dist/frontend/lowering/lower-system-errors.js.map +1 -0
- package/dist/frontend/lowering/lower-url.d.ts +2 -1
- package/dist/frontend/lowering/lower-url.js +32 -9
- package/dist/frontend/lowering/lower-url.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +30 -12
- package/dist/frontend/lowering/lowerer.js +268 -49
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/lowerer.test.js +38 -0
- package/dist/frontend/lowering/lowerer.test.js.map +1 -1
- package/dist/frontend/lowering/module-namespace-elements.d.ts +7 -0
- package/dist/frontend/lowering/module-namespace-elements.js +54 -0
- package/dist/frontend/lowering/module-namespace-elements.js.map +1 -0
- package/dist/frontend/lowering/object-factory-new.d.ts +4 -3
- package/dist/frontend/lowering/object-factory-new.js +27 -14
- package/dist/frontend/lowering/object-factory-new.js.map +1 -1
- package/dist/frontend/lowering/surfaces.d.ts +3 -2
- package/dist/frontend/lowering/surfaces.js +93 -33
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/lowering/text-decoder-encoding.js +3 -0
- package/dist/frontend/lowering/text-decoder-encoding.js.map +1 -1
- package/dist/frontend/lowering/text-decoder-encoding.test.js +2 -1
- package/dist/frontend/lowering/text-decoder-encoding.test.js.map +1 -1
- package/dist/frontend/module-syntax.d.ts +1 -1
- package/dist/frontend/module-syntax.js +8 -1
- package/dist/frontend/module-syntax.js.map +1 -1
- package/dist/frontend/module-syntax.test.js +10 -0
- package/dist/frontend/module-syntax.test.js.map +1 -1
- package/dist/frontend/npm.d.ts +4 -0
- package/dist/frontend/npm.js +86 -33
- package/dist/frontend/npm.js.map +1 -1
- package/dist/frontend/npm.test.js +103 -0
- package/dist/frontend/npm.test.js.map +1 -1
- package/dist/frontend/pipeline-native.js +2 -1
- package/dist/frontend/pipeline-native.js.map +1 -1
- package/dist/frontend/program.js +4 -2
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/services-node.js +3 -2
- package/dist/frontend/services-node.js.map +1 -1
- package/dist/frontend/services.d.ts +5 -1
- package/dist/frontend/services.js +9 -1
- package/dist/frontend/services.js.map +1 -1
- package/dist/frontend/services.test.js +21 -0
- package/dist/frontend/services.test.js.map +1 -1
- package/dist/frontend/ts7/ast-node.d.ts +2 -0
- package/dist/frontend/ts7/ast-node.js +30 -4
- package/dist/frontend/ts7/ast-node.js.map +1 -1
- package/dist/frontend/ts7/ast-node.test.js +60 -1
- package/dist/frontend/ts7/ast-node.test.js.map +1 -1
- package/dist/frontend/type-mapper.js +89 -14
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/frontend/union-discriminants.js +22 -7
- package/dist/frontend/union-discriminants.js.map +1 -1
- package/dist/index.js +19 -12
- 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/integer-loops.d.ts +7 -0
- package/dist/ir/integer-loops.js +23 -0
- package/dist/ir/integer-loops.js.map +1 -1
- package/dist/ir/integer-loops.test.d.ts +1 -0
- package/dist/ir/integer-loops.test.js +41 -0
- package/dist/ir/integer-loops.test.js.map +1 -0
- package/dist/ir/ir.d.ts +44 -26
- package/dist/ir/ir.js +69 -11
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/ir.test.js +18 -0
- package/dist/ir/ir.test.js.map +1 -1
- package/dist/ir/serialize.js +21 -1
- package/dist/ir/serialize.js.map +1 -1
- package/dist/ir/serialize.test.js +21 -0
- package/dist/ir/serialize.test.js.map +1 -1
- package/dist/ir/traverse.d.ts +0 -3
- package/dist/ir/traverse.js +33 -20
- package/dist/ir/traverse.js.map +1 -1
- package/dist/ir/validate.js +216 -80
- package/dist/ir/validate.js.map +1 -1
- package/dist/ir/validate.test.js +244 -1
- package/dist/ir/validate.test.js.map +1 -1
- package/dist/library/compiler-self-identity.js +1 -1
- package/dist/library/compiler-self-identity.test.js +2 -2
- package/dist/library/compiler-self-identity.test.js.map +1 -1
- package/dist/library/fence-eval.js +9 -2
- package/dist/library/fence-eval.js.map +1 -1
- package/dist/library/fence-eval.test.d.ts +1 -0
- package/dist/library/fence-eval.test.js +21 -0
- package/dist/library/fence-eval.test.js.map +1 -0
- package/dist/library/int-infer.d.ts +2 -2
- package/dist/library/int-infer.js +10 -7
- package/dist/library/int-infer.js.map +1 -1
- package/dist/library/int-infer.test.js +44 -0
- package/dist/library/int-infer.test.js.map +1 -1
- package/dist/library/prepare.js +2 -1
- package/dist/library/prepare.js.map +1 -1
- package/dist/native/runtime-typescript.d.ts +4 -0
- package/dist/native/runtime-typescript.js +61 -0
- package/dist/native/runtime-typescript.js.map +1 -0
- package/dist/native/runtime-typescript.test.d.ts +1 -0
- package/dist/native/runtime-typescript.test.js +41 -0
- package/dist/native/runtime-typescript.test.js.map +1 -0
- package/package.json +20 -20
- package/surface-manifest.json +385 -29
|
@@ -10,7 +10,7 @@ import { bodyReadsArguments } from "../arguments-usage.js";
|
|
|
10
10
|
import { lowerGenMethodCall } from "./lower-generators.js";
|
|
11
11
|
import { lowerClassSymbolMethodCall } from "./symbol-methods.js";
|
|
12
12
|
import { errorToStringCall } from "./error-methods.js";
|
|
13
|
-
import { lowerClassPrototypeAssign } from "./class-prototypes.js";
|
|
13
|
+
import { lowerClassPrototypeAssign, lowerClassPrototypeDescriptors } from "./class-prototypes.js";
|
|
14
14
|
import { BYTES_ELEMENT_NAME, BIGINT_T, BOOL, CAUGHT, DYN, F64, JSVAL, NULL_T, STRING, SYMBOL_T, UNDEFINED_T, VOID, arrayOf, canBoxFuncIntoDyn, canConvertToDyn, canDynCheckTo, canMarshalTypedFuncIntoIsland, ffiClassType, ffiSourceParamTypes, funcOf, isDynTypedRefType, isFfiCallbackParam, isFfiContextParam, isFfiReleaseParam, isUnitType, shapeHasAccessorSlots, typeEquals } from "../../ir/ir.js";
|
|
15
15
|
import { isJsSourceFile, isNodeEsmFile, locOf, requireSpecOf } from "../program.js";
|
|
16
16
|
import { genResultRecord, isGenericCallableMemberType, jsOpenObjectType, typeKey } from "../type-mapper.js";
|
|
@@ -45,6 +45,9 @@ import { fenceSymbolFieldCopy } from "./symbol-fields.js";
|
|
|
45
45
|
import { lowerClassDataDescriptor, lowerClassDescriptorRead } from "./class-descriptors.js";
|
|
46
46
|
import { classStaticDataFor } from "./class-static-data.js";
|
|
47
47
|
import { jsBindingHasOpenWrites } from "./lower-stmts.js";
|
|
48
|
+
import { functionCanReturnUndefined } from "../function-completion.js";
|
|
49
|
+
import { checkedIterableSpread } from "./checked-iterable-spread.js";
|
|
50
|
+
import { lowerUrlFactory } from "./lower-url.js";
|
|
48
51
|
export { bodyReadsArguments };
|
|
49
52
|
/** The one func-type projection of completed parameter shapes. Typed rest
|
|
50
53
|
* parameters keep their packed array as the trailing native ABI slot and
|
|
@@ -125,6 +128,23 @@ export const MAX_GENERIC_INSTANCES = 100;
|
|
|
125
128
|
* - `...xs: T[]`: the ABI type is the array; call sites pack the surplus.
|
|
126
129
|
*/
|
|
127
130
|
export function paramShape(lowerer, param) {
|
|
131
|
+
if (isJsSourceFile(param.getSourceFile()) && ts.isSetAccessorDeclaration(param.parent))
|
|
132
|
+
return { type: DYN, mode: "required" };
|
|
133
|
+
if (isJsSourceFile(param.getSourceFile()) && ts.isConstructorDeclaration(param.parent) && !param.dotDotDotToken) {
|
|
134
|
+
// Reflective JavaScript construction can supply values outside the
|
|
135
|
+
// constructor's documented usual types. Retain the actual arguments
|
|
136
|
+
// and apply checked conversions only at operations that need them.
|
|
137
|
+
return param.initializer ? { type: DYN, mode: "omittable", bodyType: DYN }
|
|
138
|
+
: { type: DYN, mode: param.questionToken ? "omittable" : "required" };
|
|
139
|
+
}
|
|
140
|
+
const executor = param.parent;
|
|
141
|
+
const construction = executor?.parent;
|
|
142
|
+
const nativeExecutor = executor && (ts.isArrowFunction(executor) || ts.isFunctionExpression(executor)) && ts.isNewExpression(construction) &&
|
|
143
|
+
construction.arguments?.[0] === executor && lowerer.isStdlibGlobal(construction.expression, "Promise");
|
|
144
|
+
if (!nativeExecutor && isJsSourceFile(param.getSourceFile()) && !param.type && !param.dotDotDotToken && !ts.isSetAccessorDeclaration(param.parent) &&
|
|
145
|
+
!/@(?:param|type)\b/.test(param.getSourceFile().text.slice(param.parent?.pos ?? param.pos, param.getStart()))) {
|
|
146
|
+
return param.initializer ? { type: DYN, mode: "omittable", bodyType: DYN } : { type: DYN, mode: "required" };
|
|
147
|
+
}
|
|
128
148
|
if (param.initializer && isJsSourceFile(param.getSourceFile()) && !param.type &&
|
|
129
149
|
!/@(?:param|type)\b/.test(param.getSourceFile().text.slice(param.parent?.pos ?? param.pos, param.getStart()))) {
|
|
130
150
|
return { type: DYN, mode: "omittable", bodyType: DYN };
|
|
@@ -219,9 +239,39 @@ export function paramShape(lowerer, param) {
|
|
|
219
239
|
}
|
|
220
240
|
if (param.initializer) {
|
|
221
241
|
const raw = lowerer.irTypeOf(param.name);
|
|
242
|
+
// An optional JS array parameter is a live caller-owned buffer,
|
|
243
|
+
// including typed arrays passed through checked callbacks. Extracting
|
|
244
|
+
// a native array here would copy it and discard element writes.
|
|
245
|
+
if (isJsSourceFile(param.getSourceFile()) && !param.type &&
|
|
246
|
+
(raw.kind === "array" || raw.kind === "union" && lowerer.unions.get(raw.unionId)?.arms.some((arm) => arm.kind === "array"))) {
|
|
247
|
+
return { type: DYN, mode: "omittable", bodyType: DYN };
|
|
248
|
+
}
|
|
222
249
|
return defaultParameterShape(lowerer, param, raw);
|
|
223
250
|
}
|
|
224
|
-
|
|
251
|
+
let type = lowerer.runtimeOptionalBindingType(param.name, lowerer.irTypeOf(param.name));
|
|
252
|
+
const body = param.parent?.body;
|
|
253
|
+
if (isJsSourceFile(param.getSourceFile()) && body &&
|
|
254
|
+
type.kind !== "dyn" && type.kind !== "jsval") {
|
|
255
|
+
const symbol = lowerer.checker.getSymbolAtLocation(param.name);
|
|
256
|
+
let acceptsUndefined = false;
|
|
257
|
+
ts.walkPreorder(body, (node) => {
|
|
258
|
+
if (acceptsUndefined || !ts.isBinaryExpression(node))
|
|
259
|
+
return;
|
|
260
|
+
const op = node.operatorToken.kind;
|
|
261
|
+
if (op !== ts.SyntaxKind.EqualsEqualsEqualsToken && op !== ts.SyntaxKind.ExclamationEqualsEqualsToken &&
|
|
262
|
+
op !== ts.SyntaxKind.EqualsEqualsToken && op !== ts.SyntaxKind.ExclamationEqualsToken)
|
|
263
|
+
return;
|
|
264
|
+
const checks = (value, absent) => ts.isIdentifier(value) && ts.isIdentifier(absent) && absent.text === "undefined" &&
|
|
265
|
+
(lowerer.typeOf(absent).flags & ts.TypeFlags.Undefined) !== 0 &&
|
|
266
|
+
lowerer.checker.getSymbolAtLocation(value) === symbol;
|
|
267
|
+
acceptsUndefined = checks(node.left, node.right) || checks(node.right, node.left);
|
|
268
|
+
});
|
|
269
|
+
// A JavaScript body that handles an absent argument defines a wider
|
|
270
|
+
// contract than its JSDoc's usual value. Checked callers must deliver
|
|
271
|
+
// undefined to that branch rather than reject it at the ABI boundary.
|
|
272
|
+
if (acceptsUndefined)
|
|
273
|
+
type = lowerer.promoteRuntimeOptionalParameter(param.name, type);
|
|
274
|
+
}
|
|
225
275
|
if (type.kind === "void") {
|
|
226
276
|
return { type: DYN, mode: param.questionToken ? "omittable" : "required" };
|
|
227
277
|
}
|
|
@@ -249,8 +299,9 @@ export function isThisParameter(param) {
|
|
|
249
299
|
export function paramShapes(lowerer, params, signature, blameOf) {
|
|
250
300
|
if (!signature)
|
|
251
301
|
return params.filter((p) => !isThisParameter(p)).map((param) => lowerer.paramShape(param));
|
|
302
|
+
const symbols = signature.getParameters();
|
|
252
303
|
return params.map((declParam, i) => {
|
|
253
|
-
const symbol =
|
|
304
|
+
const symbol = symbols[i];
|
|
254
305
|
const tsType = symbol ? lowerer.checker.getTypeOfSymbol(symbol) : lowerer.typeOf(declParam.name);
|
|
255
306
|
const mapped = jsOpenObjectType(declParam, lowerer.runtimeOptionalBindingType(declParam.name, lowerer.mapTypeOf(tsType) ?? lowerer.irTypeOf(declParam.name)), lowerer.shapes, lowerer.unions);
|
|
256
307
|
if (!mapped || mapped.kind === "void")
|
|
@@ -368,7 +419,7 @@ leading) {
|
|
|
368
419
|
// before conversion to the dense checked-dynamic argument pack.
|
|
369
420
|
value = { kind: "arrayLit", elems: [value], spreads: [0], type: value.type, loc: value.loc };
|
|
370
421
|
}
|
|
371
|
-
value = lowerer
|
|
422
|
+
value = checkedIterableSpread(lowerer, value, arg.expression.getText(), loc);
|
|
372
423
|
if (spreads === 1 && index === argNodes.length - 1) {
|
|
373
424
|
stmts.push({ kind: "exprStmt", expr: {
|
|
374
425
|
kind: "libCall", fn: "dyn.packPushSpread", args: [ref(), value, { kind: "strLit", value: arg.expression.getText(), type: STRING, loc }], type: VOID, loc,
|
|
@@ -892,6 +943,8 @@ function producesConstructor(lowerer, type) {
|
|
|
892
943
|
return false;
|
|
893
944
|
}
|
|
894
945
|
export function declaredReturnType(lowerer, decl, blame) {
|
|
946
|
+
if (isJsSourceFile(decl.getSourceFile()) && ts.isGetAccessorDeclaration(decl))
|
|
947
|
+
return DYN;
|
|
895
948
|
const sig = lowerer.checker.getSignatureFromDeclaration(decl);
|
|
896
949
|
if (!sig)
|
|
897
950
|
lowerer.unsupported("SC1090", decl, "this function form");
|
|
@@ -906,11 +959,36 @@ export function declaredReturnType(lowerer, decl, blame) {
|
|
|
906
959
|
// (`.action(() => { throw ... })`). `never` VALUES stay unmapped.
|
|
907
960
|
if (retTsType.flags & ts.TypeFlags.Never)
|
|
908
961
|
return VOID;
|
|
909
|
-
|
|
910
|
-
if (isJsSourceFile(decl.getSourceFile()) &&
|
|
962
|
+
let mappedReturn = lowerer.mapTypeOf(retTsType);
|
|
963
|
+
if (isJsSourceFile(decl.getSourceFile()) && decl.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.AsyncKeyword) &&
|
|
964
|
+
!decl.asteriskToken && mappedReturn?.kind !== "promise") {
|
|
965
|
+
const fallback = dynFallbackType(lowerer, decl, retTsType);
|
|
966
|
+
return fallback?.kind === "promise" ? fallback : { kind: "promise", inner: DYN };
|
|
967
|
+
}
|
|
968
|
+
if (mappedReturn && isJsSourceFile(decl.getSourceFile()) && functionCanReturnUndefined(decl))
|
|
969
|
+
mappedReturn = lowerer.withUndefinedArmOf(mappedReturn) ?? mappedReturn;
|
|
970
|
+
if (isJsSourceFile(decl.getSourceFile()) && mappedReturn?.kind === "void") {
|
|
971
|
+
let returnsValue = false;
|
|
972
|
+
const scan = (node) => {
|
|
973
|
+
if (node !== decl && ts.isFunctionLike(node))
|
|
974
|
+
return;
|
|
975
|
+
if (ts.isReturnStatement(node) && node.expression)
|
|
976
|
+
returnsValue = true;
|
|
977
|
+
node.forEachChild(scan);
|
|
978
|
+
};
|
|
979
|
+
scan(decl);
|
|
980
|
+
if (returnsValue)
|
|
981
|
+
return DYN;
|
|
982
|
+
}
|
|
983
|
+
if (isJsSourceFile(decl.getSourceFile()) && mappedReturn?.kind === "array")
|
|
984
|
+
return DYN;
|
|
985
|
+
if (isJsSourceFile(decl.getSourceFile()) && !decl.type && !hasExplicitJsDocReturn(decl) && mappedReturn?.kind === "record")
|
|
911
986
|
return DYN;
|
|
912
987
|
if (isJsSourceFile(decl.getSourceFile()) && !decl.type && !hasExplicitJsDocReturn(decl) && mappedReturn?.kind === "date")
|
|
913
988
|
return DYN;
|
|
989
|
+
if (isJsSourceFile(decl.getSourceFile()) && !decl.type && !hasExplicitJsDocReturn(decl) &&
|
|
990
|
+
mappedReturn?.kind === "union" && lowerer.unions.get(mappedReturn.unionId)?.arms.some((arm) => arm.kind === "func"))
|
|
991
|
+
return DYN;
|
|
914
992
|
// JS inference assigns Number to arithmetic over any, although the
|
|
915
993
|
// runtime operands can both be BigInts. Preserve that native result.
|
|
916
994
|
if (isJsSourceFile(decl.getSourceFile()) && !decl.type && !hasExplicitJsDocReturn(decl) &&
|
|
@@ -971,7 +1049,7 @@ export function declaredReturnType(lowerer, decl, blame) {
|
|
|
971
1049
|
// Native-only members (such as Int32Array layout offsets) cannot cross
|
|
972
1050
|
// that boundary; their factories keep the native record ABI.
|
|
973
1051
|
const asyncReturn = decl.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.AsyncKeyword) && mappedReturn?.kind === "promise";
|
|
974
|
-
const recordReturn = asyncReturn ? mappedReturn.inner : mappedReturn;
|
|
1052
|
+
const recordReturn = asyncReturn && mappedReturn?.kind === "promise" ? mappedReturn.inner : mappedReturn;
|
|
975
1053
|
const recordArms = recordReturn?.kind === "union" ? lowerer.unions.get(recordReturn.unionId)?.arms : recordReturn ? [recordReturn] : undefined;
|
|
976
1054
|
const inferredRecordReturn = recordArms?.some((arm) => arm.kind === "record" || arm.kind === "object") &&
|
|
977
1055
|
recordArms.every((arm) => isUnitType(arm) || arm.kind === "record" || arm.kind === "object" && !hasExplicitJsDocReturn(decl));
|
|
@@ -985,7 +1063,7 @@ export function declaredReturnType(lowerer, decl, blame) {
|
|
|
985
1063
|
})) {
|
|
986
1064
|
return asyncReturn ? { kind: "promise", inner: DYN } : DYN;
|
|
987
1065
|
}
|
|
988
|
-
const returnType =
|
|
1066
|
+
const returnType = mappedReturn;
|
|
989
1067
|
if (!returnType) {
|
|
990
1068
|
// JS inference residue (an `any` return, an unmappable union): the
|
|
991
1069
|
// checked-dynamic fallback, exactly the declaration story in
|
|
@@ -1466,8 +1544,9 @@ function unifySignatureBindings(lowerer, info, rsig, bindings, tsBindings) {
|
|
|
1466
1544
|
if (dSigs.length === 1 && iSigs.length === 1) {
|
|
1467
1545
|
const ds = dSigs[0];
|
|
1468
1546
|
const is = iSigs[0];
|
|
1547
|
+
const instanceParams = is.getParameters();
|
|
1469
1548
|
ds.getParameters().forEach((dp, i) => {
|
|
1470
|
-
const ip =
|
|
1549
|
+
const ip = instanceParams[i];
|
|
1471
1550
|
if (ip)
|
|
1472
1551
|
unify(lowerer.checker.getTypeOfSymbol(dp), lowerer.checker.getTypeOfSymbol(ip), depth + 1);
|
|
1473
1552
|
});
|
|
@@ -1484,8 +1563,9 @@ function unifySignatureBindings(lowerer, info, rsig, bindings, tsBindings) {
|
|
|
1484
1563
|
};
|
|
1485
1564
|
const declSig = lowerer.checker.getSignatureFromDeclaration(info.decl);
|
|
1486
1565
|
if (declSig) {
|
|
1566
|
+
const instanceParams = rsig.getParameters();
|
|
1487
1567
|
declSig.getParameters().forEach((dp, i) => {
|
|
1488
|
-
const ip =
|
|
1568
|
+
const ip = instanceParams[i];
|
|
1489
1569
|
if (ip)
|
|
1490
1570
|
unify(lowerer.checker.getTypeOfSymbol(dp), lowerer.checker.getTypeOfSymbol(ip));
|
|
1491
1571
|
});
|
|
@@ -2097,6 +2177,12 @@ function implicitDeclaredReturn(lowerer, info) {
|
|
|
2097
2177
|
if (retTs.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined))
|
|
2098
2178
|
return DYN;
|
|
2099
2179
|
if (lowerer.checker.isArrayType(retTs)) {
|
|
2180
|
+
// Inferred JavaScript arrays can hold values selected through a
|
|
2181
|
+
// mutable constructor registry. The checker may retain only one
|
|
2182
|
+
// constructor's element type; settle the result from the lowered
|
|
2183
|
+
// container instead of checking every element against that guess.
|
|
2184
|
+
if (!hasExplicitJsDocReturn(info.decl))
|
|
2185
|
+
return null;
|
|
2100
2186
|
if (info.decl.parameters.some((param, index) => info.implicitParams?.[index] &&
|
|
2101
2187
|
lowerer.mapTypeOf(lowerer.typeOf(param.name))?.kind === "array"))
|
|
2102
2188
|
return null;
|
|
@@ -2110,6 +2196,12 @@ function implicitDeclaredReturn(lowerer, info) {
|
|
|
2110
2196
|
return null;
|
|
2111
2197
|
}
|
|
2112
2198
|
const mapped = lowerer.mapTypeOf(retTs);
|
|
2199
|
+
// Mixed inferred results can select a closure or a class instance.
|
|
2200
|
+
// Their callable ABI is settled by the lowered body, including native
|
|
2201
|
+
// classes whose reflected calls return checked values.
|
|
2202
|
+
if (mapped?.kind === "union" && !hasExplicitJsDocReturn(info.decl) &&
|
|
2203
|
+
lowerer.unions.get(mapped.unionId)?.arms.some((arm) => arm.kind === "func"))
|
|
2204
|
+
return null;
|
|
2113
2205
|
if (mapped?.kind === "symbol" && !hasExplicitJsDocReturn(info.decl))
|
|
2114
2206
|
return null;
|
|
2115
2207
|
if (mapped?.kind === "date" && !hasExplicitJsDocReturn(info.decl))
|
|
@@ -2206,12 +2298,25 @@ function storedImplicitArgumentType(lowerer, arg) {
|
|
|
2206
2298
|
return DYN;
|
|
2207
2299
|
if (ts.isIdentifier(arg))
|
|
2208
2300
|
return lowerer.peekLocal(arg)?.type ?? lowerer.globalOf(arg)?.type ?? null;
|
|
2301
|
+
if (isJsSourceFile(arg.getSourceFile()) &&
|
|
2302
|
+
(ts.isPropertyAccessExpression(arg) || ts.isElementAccessExpression(arg))) {
|
|
2303
|
+
// Mutable JS members can retain an initializer-only checker type (for
|
|
2304
|
+
// example a linked-list slot initially null). Specialize to the value
|
|
2305
|
+
// we actually represent, rather than checking it back into that type.
|
|
2306
|
+
const represented = tryLowerExpression(lowerer, arg);
|
|
2307
|
+
if (represented)
|
|
2308
|
+
return represented.type;
|
|
2309
|
+
}
|
|
2310
|
+
if (isJsSourceFile(arg.getSourceFile()) && (ts.isCallExpression(arg) || ts.isConditionalExpression(arg) ||
|
|
2311
|
+
ts.isBinaryExpression(arg) && (arg.operatorToken.kind === ts.SyntaxKind.BarBarToken ||
|
|
2312
|
+
arg.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken || arg.operatorToken.kind === ts.SyntaxKind.QuestionQuestionToken))) {
|
|
2313
|
+
// Calls and fallback expressions can retain checked storage wider than
|
|
2314
|
+
// the checker's inference (for example Object.assign on a JS instance).
|
|
2315
|
+
const represented = tryLowerExpression(lowerer, arg);
|
|
2316
|
+
if (represented?.type.kind === "dyn" || represented?.type.kind === "func")
|
|
2317
|
+
return represented.type;
|
|
2318
|
+
}
|
|
2209
2319
|
if (ts.isCallExpression(arg) && ts.isIdentifier(arg.expression)) {
|
|
2210
|
-
if (isJsSourceFile(arg.getSourceFile())) {
|
|
2211
|
-
const represented = tryLowerExpression(lowerer, arg);
|
|
2212
|
-
if (represented?.type.kind === "dyn" || represented?.type.kind === "func")
|
|
2213
|
-
return represented.type;
|
|
2214
|
-
}
|
|
2215
2320
|
const callee = storedImplicitArgumentType(lowerer, arg.expression);
|
|
2216
2321
|
if (callee?.kind === "dyn")
|
|
2217
2322
|
return DYN;
|
|
@@ -3852,6 +3957,7 @@ export function lowerCall(lowerer, expr) {
|
|
|
3852
3957
|
lowerer.fenceStaticReadableStreamMember(access, "call");
|
|
3853
3958
|
const source = tryLowerExpression(lowerer, access.expression);
|
|
3854
3959
|
if (source && (source.type.kind === "dyn" || source.type.kind === "func" ||
|
|
3960
|
+
source.type.kind === "union" && isJsSourceFile(expr.getSourceFile()) && lowerer.dynConvertible(source.type) ||
|
|
3855
3961
|
(source.type.kind === "map" || source.type.kind === "set") && lowerer.dynConvertible(source.type) || isDynTypedRefType(source.type) &&
|
|
3856
3962
|
lowerer.foldedStringKeyOf(access.argumentExpression) === null &&
|
|
3857
3963
|
lowerer.mapTypeOf(lowerer.typeOf(access.argumentExpression))?.kind !== "symbol")) {
|
|
@@ -4238,6 +4344,9 @@ export function lowerCall(lowerer, expr) {
|
|
|
4238
4344
|
if (name === "parseFloat" && probed?.type.kind === "string") {
|
|
4239
4345
|
return { kind: "libCall", fn: "num.parseFloat", args: [probed], type: F64, loc };
|
|
4240
4346
|
}
|
|
4347
|
+
if (name === "parseFloat" && probed?.type.kind === "dyn") {
|
|
4348
|
+
return { kind: "libCall", fn: "num.parseFloat", args: [{ kind: "libCall", fn: "dyn.toStringCoerce", args: [probed], type: STRING, loc }], type: F64, loc };
|
|
4349
|
+
}
|
|
4241
4350
|
if (name === "isFinite" && probed?.type.kind === "f64") {
|
|
4242
4351
|
return { kind: "libCall", fn: "number.isFinite", args: [probed], type: BOOL, loc };
|
|
4243
4352
|
}
|
|
@@ -4565,6 +4674,7 @@ export function lowerCall(lowerer, expr) {
|
|
|
4565
4674
|
// Before the island path: regex-argument replace/replaceAll/split
|
|
4566
4675
|
// lower STATICALLY; only the string-pattern overloads are island.
|
|
4567
4676
|
lowerRegexMethodCallWithOptionalArg(lowerer, expr, expr.expression) ??
|
|
4677
|
+
lowerUrlStaticCall(lowerer, expr, expr.expression) ??
|
|
4568
4678
|
lowerer.lowerUrlMethodCall(expr, expr.expression) ??
|
|
4569
4679
|
lowerer.lowerSearchParamsMethodCall(expr, expr.expression) ??
|
|
4570
4680
|
lowerer.lowerStatsMethodCall(expr, expr.expression) ??
|
|
@@ -4615,9 +4725,6 @@ export function lowerCall(lowerer, expr) {
|
|
|
4615
4725
|
lowerer.lowerBytesMethodCall(expr, expr.expression) ??
|
|
4616
4726
|
lowerBytesStaticCall(lowerer, expr, expr.expression) ??
|
|
4617
4727
|
lowerBufferStaticCallWithNarrowedArg(lowerer, expr, expr.expression) ??
|
|
4618
|
-
// URL.revokeObjectURL's zero-argument contract (the one-argument
|
|
4619
|
-
// form keeps the fence — createObjectURL does too).
|
|
4620
|
-
lowerUrlStaticCall(lowerer, expr, expr.expression) ??
|
|
4621
4728
|
// Readable.from — the stream classes' one static (before the
|
|
4622
4729
|
// stdlib chokepoint claims the member).
|
|
4623
4730
|
lowerStreamStaticCall(lowerer, expr, expr.expression) ??
|
|
@@ -5760,7 +5867,7 @@ function lowerSpreadArgsCall(lowerer, expr, callee, loc) {
|
|
|
5760
5867
|
// The spelling rides along for V8's nullish spread-call
|
|
5761
5868
|
// TypeError ("v is not iterable (cannot read property ...)").
|
|
5762
5869
|
spreads.push({ arg: args.length, what: p.spreadOf.getText() });
|
|
5763
|
-
args.push(lowerer
|
|
5870
|
+
args.push(checkedIterableSpread(lowerer, p.v, p.spreadOf.getText(), loc));
|
|
5764
5871
|
}
|
|
5765
5872
|
else {
|
|
5766
5873
|
args.push(lowerer.coerceInto(p.node, p.v, DYN));
|
|
@@ -5770,7 +5877,7 @@ function lowerSpreadArgsCall(lowerer, expr, callee, loc) {
|
|
|
5770
5877
|
return { kind: "dynCall", callee: boxed, calleeName, args, spreads, type: DYN, loc };
|
|
5771
5878
|
}
|
|
5772
5879
|
if (spreadParts.length > 0 &&
|
|
5773
|
-
spreadParts.every((p) => p.v.type.kind === "jsval") &&
|
|
5880
|
+
(spreadParts.every((p) => p.v.type.kind === "jsval") || callee.type.kind === "func" && callee.type.restAbi === "jsval") &&
|
|
5774
5881
|
(callee.type.kind === "jsval" || callee.type.kind === "func")) {
|
|
5775
5882
|
if (spreadParts.length !== 1 || parts[parts.length - 1].spreadOf === null) {
|
|
5776
5883
|
lowerer.unsupported("SC1090", expr, "spread arguments before positional arguments in island calls (one trailing spread after the fixed arguments is the supported form)");
|
|
@@ -5783,7 +5890,7 @@ function lowerSpreadArgsCall(lowerer, expr, callee, loc) {
|
|
|
5783
5890
|
const last = parts[parts.length - 1];
|
|
5784
5891
|
// The spelling rides in `name` for V8's nullish spread-call
|
|
5785
5892
|
// TypeError ("v is not iterable (cannot read property ...)").
|
|
5786
|
-
return { kind: "jsOp", op: "callSpread", name: last.spreadOf.getText(), args: [f, preArr, last.v], type: JSVAL, loc };
|
|
5893
|
+
return { kind: "jsOp", op: "callSpread", name: last.spreadOf.getText(), args: [f, preArr, lowerer.coerceInto(last.spreadOf, last.v, JSVAL)], type: JSVAL, loc };
|
|
5787
5894
|
}
|
|
5788
5895
|
// No lane fits (a spread source outside both tiers, a callee neither
|
|
5789
5896
|
// boxable nor marshalable, mixed dyn/jsval spreads): fence HERE — the
|
|
@@ -5835,12 +5942,21 @@ function canCompleteRuntimeSpread(lowerer, shapes) {
|
|
|
5835
5942
|
function lowerDynReceiverMethodCall(lowerer, call, access) {
|
|
5836
5943
|
if (lowerer.chainBlocked(call, access))
|
|
5837
5944
|
return null;
|
|
5945
|
+
if (stdlibGlobalNameOf(lowerer, access.expression) !== null)
|
|
5946
|
+
return null;
|
|
5838
5947
|
// Only checker-untyped receivers: `any`/`unknown`, or the `any[]` an
|
|
5839
5948
|
// Array.isArray guard narrows them to (the value is STILL the checked-dynamic tree
|
|
5840
5949
|
// array — scalar narrowings bridge through maybeNarrow's dynCheck and
|
|
5841
5950
|
// take the ordinary typed paths, but there is no static home for an
|
|
5842
5951
|
// any-elemented array). Typed receivers keep their own lowerings.
|
|
5843
5952
|
const recvTs = lowerer.typeOf(access.expression);
|
|
5953
|
+
const recvSymbol = recvTs.getSymbol();
|
|
5954
|
+
if (recvSymbol && ["MapIterator", "SetIterator"].includes(recvSymbol.name) &&
|
|
5955
|
+
lowerer.isStdlibSymbol(recvSymbol) &&
|
|
5956
|
+
["map", "filter", "take", "drop", "flatMap", "toArray", "forEach", "reduce", "some", "every", "find"].includes(access.name.text) &&
|
|
5957
|
+
lowerer.isStdlibMember(access)) {
|
|
5958
|
+
lowerer.noLowering(`collection iterator .${access.name.text}()`, call, "stored Map/Set iterators support .next() and iteration; iterator helper methods have no lowering");
|
|
5959
|
+
}
|
|
5844
5960
|
const arrayReceiver = lowerer.checker.isArrayType(recvTs);
|
|
5845
5961
|
const anyArray = arrayReceiver &&
|
|
5846
5962
|
((lowerer.checker.getTypeArguments(recvTs)[0]?.flags ?? 0) &
|
|
@@ -5860,7 +5976,7 @@ function lowerDynReceiverMethodCall(lowerer, call, access) {
|
|
|
5860
5976
|
!["call", "apply", "bind", "toString", "valueOf", "constructor"].includes(access.name.text) &&
|
|
5861
5977
|
canBoxFuncIntoDyn(probed.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) {
|
|
5862
5978
|
const loc = locOf(call);
|
|
5863
|
-
const fnName = jsFuncNameOf(access.expression);
|
|
5979
|
+
const fnName = jsFuncNameOf(access.expression, lowerer);
|
|
5864
5980
|
const boxed = { kind: "dynFrom", value: probed, type: DYN, loc, ...(fnName !== null ? { fnName } : {}) };
|
|
5865
5981
|
const local = lowerer.declareHiddenLocal("%callableReceiver", DYN);
|
|
5866
5982
|
const receiver = { kind: "varRef", localId: local.id, type: DYN, loc };
|
|
@@ -5879,18 +5995,24 @@ function lowerDynReceiverMethodCall(lowerer, call, access) {
|
|
|
5879
5995
|
}
|
|
5880
5996
|
if (probed?.type.kind === "classval") {
|
|
5881
5997
|
const info = lowerer.classes.get(probed.type.className);
|
|
5882
|
-
if (info
|
|
5998
|
+
if (info)
|
|
5883
5999
|
return lowerStaticMethodCall(lowerer, call, access);
|
|
5884
6000
|
}
|
|
5885
|
-
if (probed?.type.kind
|
|
5886
|
-
|
|
5887
|
-
|
|
6001
|
+
if (probed?.type.kind === "union" && isJsSourceFile(call.getSourceFile()) &&
|
|
6002
|
+
lowerer.unions.get(probed.type.unionId)?.arms.every((arm) => isUnitType(arm) || arm.kind === "object" || arm.kind === "record" || arm.kind === "func") && lowerer.dynConvertible(probed.type)) {
|
|
6003
|
+
recv = lowerer.coerceToExpected(probed, DYN);
|
|
6004
|
+
}
|
|
6005
|
+
else {
|
|
6006
|
+
if (probed?.type.kind !== "dyn")
|
|
6007
|
+
return null;
|
|
6008
|
+
recv = probed;
|
|
6009
|
+
}
|
|
5888
6010
|
}
|
|
5889
6011
|
// A factory may return a constructor more precise than its inferred
|
|
5890
6012
|
// checker result. Runtime static members live on that constructor.
|
|
5891
6013
|
if (recv.type.kind === "classval") {
|
|
5892
6014
|
const info = lowerer.classes.get(recv.type.className);
|
|
5893
|
-
if (info
|
|
6015
|
+
if (info)
|
|
5894
6016
|
return lowerStaticMethodCall(lowerer, call, access);
|
|
5895
6017
|
}
|
|
5896
6018
|
// A checker-`any` receiver that already lowered to a real STRING (the
|
|
@@ -5906,6 +6028,25 @@ function lowerDynReceiverMethodCall(lowerer, call, access) {
|
|
|
5906
6028
|
}
|
|
5907
6029
|
if (recv.type.kind !== "dyn")
|
|
5908
6030
|
return null;
|
|
6031
|
+
if (access.name.text === "normalize" && call.arguments.length <= 1 && !call.arguments.some(ts.isSpreadElement)) {
|
|
6032
|
+
const loc = locOf(call);
|
|
6033
|
+
const hasArgument = call.arguments.length === 1;
|
|
6034
|
+
const name = `%dyn.string.normalize:${hasArgument ? 1 : 0}`;
|
|
6035
|
+
if (!lowerer.liftedFns.some((fn) => fn.name === name)) {
|
|
6036
|
+
const value = varRef("receiver", DYN, loc);
|
|
6037
|
+
const argument = varRef("form", DYN, loc);
|
|
6038
|
+
const form = { kind: "ternary", cond: { kind: "dynTest", value: argument, test: "undefined", type: BOOL, loc },
|
|
6039
|
+
then: { kind: "strLit", value: "NFC", type: STRING, loc },
|
|
6040
|
+
else_: { kind: "libCall", fn: "dyn.toStringCoerce", args: [argument], type: STRING, loc }, type: STRING, loc };
|
|
6041
|
+
const result = { kind: "strIntrinsic", method: "normalize", receiver: { kind: "dynCheck", value, type: STRING, loc }, args: [form], type: STRING, loc };
|
|
6042
|
+
lowerer.liftedFns.push({ name, params: [{ localId: "receiver", name: "receiver", type: DYN }, { localId: "form", name: "form", type: DYN }],
|
|
6043
|
+
locals: [{ id: "receiver", name: "receiver", type: DYN, mutable: false }, { id: "form", name: "form", type: DYN, mutable: false }], returnType: DYN, loc,
|
|
6044
|
+
body: [{ kind: "if", cond: { kind: "dynTest", value, test: "string", type: BOOL, loc }, then: [
|
|
6045
|
+
{ kind: "return", value: { kind: "dynFrom", value: result, type: DYN, loc }, loc },
|
|
6046
|
+
], else_: null, loc }, { kind: "return", value: { kind: "dynInvoke", recv: value, method: "normalize", calleeName: access.getText(), args: hasArgument ? [argument] : [], type: DYN, loc }, loc }] });
|
|
6047
|
+
}
|
|
6048
|
+
return { kind: "call", callee: name, args: [recv, call.arguments[0] ? lowerer.lowerExprExpecting(call.arguments[0], DYN) : dynUndefinedExpr(loc)], type: DYN, loc };
|
|
6049
|
+
}
|
|
5909
6050
|
if (lowerer.mapTypeOf(recvTs)?.kind === "classval") {
|
|
5910
6051
|
return lowerStaticMethodCall(lowerer, call, access);
|
|
5911
6052
|
}
|
|
@@ -5965,6 +6106,9 @@ function lowerDynReceiverMethodCall(lowerer, call, access) {
|
|
|
5965
6106
|
// with the original receiver rather than a materialized property view.
|
|
5966
6107
|
const callbackProperty = (() => {
|
|
5967
6108
|
const prop = lowerer.checker.getPropertyOfType(recvTs, access.name.text);
|
|
6109
|
+
const mapped = lowerer.mapTypeOf(recvTs);
|
|
6110
|
+
if (mapped?.kind === "union" && lowerer.unions.get(mapped.unionId)?.arms.every((arm) => arm.kind === "object" && lowerer.classes.get(arm.className)?.fields.has(access.name.text)))
|
|
6111
|
+
return true;
|
|
5968
6112
|
return prop !== undefined && lowerer.checker.declarationsOf(prop).some((decl) => ts.isPropertyDeclaration(decl) || ts.isPropertySignature(decl));
|
|
5969
6113
|
})();
|
|
5970
6114
|
const dispatched = callbackProperty ? null : lowerDynDispatchMethodCall(lowerer, call, access, recv, arrayReceiver);
|
|
@@ -6002,18 +6146,24 @@ function lowerDynReceiverMethodCall(lowerer, call, access) {
|
|
|
6002
6146
|
type: DYN,
|
|
6003
6147
|
loc: locOf(access),
|
|
6004
6148
|
};
|
|
6149
|
+
const calleeLocal = lowerer.declareHiddenLocal("%dynCallCallee", DYN);
|
|
6150
|
+
const callee = varRef(calleeLocal.id, DYN, loc);
|
|
6151
|
+
const stmts = [
|
|
6152
|
+
{ kind: "varDecl", localId: receiverLocal.id, init: recv, loc },
|
|
6153
|
+
{ kind: "varDecl", localId: calleeLocal.id, init: member, loc },
|
|
6154
|
+
];
|
|
6005
6155
|
if (call.arguments.some(ts.isSpreadElement)) {
|
|
6006
|
-
const spread = lowerSpreadArgsCall(lowerer, call,
|
|
6156
|
+
const spread = lowerSpreadArgsCall(lowerer, call, callee, loc);
|
|
6007
6157
|
if (spread?.kind === "dynCall")
|
|
6008
6158
|
return { kind: "seqExpr",
|
|
6009
|
-
stmts
|
|
6159
|
+
stmts,
|
|
6010
6160
|
result: { ...spread, receiver }, type: DYN, loc };
|
|
6011
6161
|
lowerer.unsupported("SC1090", call, "spread arguments in calls through 'unknown' values");
|
|
6012
6162
|
}
|
|
6013
6163
|
const args = call.arguments.map((a) => lowerer.lowerExprExpecting(a, DYN));
|
|
6014
6164
|
return {
|
|
6015
|
-
kind: "seqExpr", stmts
|
|
6016
|
-
result: { kind: "dynCall", callee
|
|
6165
|
+
kind: "seqExpr", stmts,
|
|
6166
|
+
result: { kind: "dynCall", callee, receiver, calleeName: access.getText(), args, type: DYN, loc }, type: DYN, loc,
|
|
6017
6167
|
};
|
|
6018
6168
|
}
|
|
6019
6169
|
/** Prototype method names of the checked-dynamic tree-representable kinds (String, Array,
|
|
@@ -6041,6 +6191,7 @@ const DYN_PROTO_METHOD_NAMES = new Set([
|
|
|
6041
6191
|
* is-not-a-function where the kind's prototype lacks the name, and
|
|
6042
6192
|
* fences LOUDLY on real-but-unimplemented pairs. */
|
|
6043
6193
|
const DYN_DISPATCH_METHODS = new Set([
|
|
6194
|
+
"toFixed", "toExponential",
|
|
6044
6195
|
"segment", "containing", "resolvedOptions", "test", "exec",
|
|
6045
6196
|
"apply", "bind", "call",
|
|
6046
6197
|
"push", "pop", "shift", "unshift", "slice", "at",
|
|
@@ -6539,6 +6690,15 @@ function lowerPrimitiveProtoCall(lowerer, call, recv, name, memberSym) {
|
|
|
6539
6690
|
if (!lowerer.isStdlibSymbol(memberSym))
|
|
6540
6691
|
return null;
|
|
6541
6692
|
const recvKind = lowerer.mapTypeOf(lowerer.typeOf(recv))?.kind;
|
|
6693
|
+
if ((name === "toFixed" || name === "toExponential") && call.arguments.length <= 1 &&
|
|
6694
|
+
!call.arguments.some(ts.isSpreadElement) && isJsSourceFile(call.getSourceFile())) {
|
|
6695
|
+
const operand = lowerer.lowerExpr(recv);
|
|
6696
|
+
if (operand.type.kind === "dyn" || operand.type.kind === "union" && lowerer.dynConvertible(operand.type))
|
|
6697
|
+
return {
|
|
6698
|
+
kind: "dynInvoke", recv: lowerer.coerceToExpected(operand, DYN), method: name, calleeName: `${recv.getText()}.${name}`,
|
|
6699
|
+
args: call.arguments.map((argument) => lowerer.lowerExprExpecting(argument, DYN)), type: DYN, loc: locOf(call),
|
|
6700
|
+
};
|
|
6701
|
+
}
|
|
6542
6702
|
if (recvKind !== "f64" && recvKind !== "bool" && recvKind !== "string")
|
|
6543
6703
|
return null;
|
|
6544
6704
|
const loc = locOf(call);
|
|
@@ -7019,6 +7179,17 @@ export function lowerNestedFunctionDecl(lowerer, stmt) {
|
|
|
7019
7179
|
throw new InternalCompilerError("lowerer bug: nested function declaration has no active statement list");
|
|
7020
7180
|
}
|
|
7021
7181
|
const init = lowerer.lowerLambda(stmt);
|
|
7182
|
+
// Body inference may settle a JS return differently from the initial
|
|
7183
|
+
// checker signature. Publish that same ABI on the hoisted binding and
|
|
7184
|
+
// every mutable capture of it before callers are lowered.
|
|
7185
|
+
if (init.type.kind === "func" && !typeEquals(local.type, init.type)) {
|
|
7186
|
+
local.type = init.type;
|
|
7187
|
+
for (const fn of lowerer.liftedFns)
|
|
7188
|
+
for (const capture of fn.captures ?? []) {
|
|
7189
|
+
if (capture.localId === local.id)
|
|
7190
|
+
capture.type = init.type;
|
|
7191
|
+
}
|
|
7192
|
+
}
|
|
7022
7193
|
return { kind: "assign", localId: local.id, value: init, loc: locOf(stmt) };
|
|
7023
7194
|
}
|
|
7024
7195
|
/** Signature checks + param shapes + IR func type for any lambda-like
|
|
@@ -7183,6 +7354,13 @@ export function lowerLambda(lowerer, node) {
|
|
|
7183
7354
|
const signature = lowerer.lambdaSignature(node);
|
|
7184
7355
|
const { shapes } = signature;
|
|
7185
7356
|
let { funcType } = signature;
|
|
7357
|
+
// Reflected JS methods receive the caller's actual `this`, which may
|
|
7358
|
+
// be a Proxy or a descriptor-created object rather than the class.
|
|
7359
|
+
// Fluent methods must return that receiver without a class cast.
|
|
7360
|
+
if (ts.isMethodDeclaration(node) && isJsSourceFile(node.getSourceFile()) &&
|
|
7361
|
+
!node.type && !node.asteriskToken && !hasExplicitJsDocReturn(node) && returnsOnlyThis(node)) {
|
|
7362
|
+
funcType = { ...funcType, ret: funcType.ret.kind === "promise" ? { ...funcType.ret, inner: DYN } : DYN };
|
|
7363
|
+
}
|
|
7186
7364
|
// A lambda IS a value: the completed-ABI rule applies at birth. The
|
|
7187
7365
|
// contextual (target) type decides — `(x?: number) => void` may flow
|
|
7188
7366
|
// into a slot annotated `(x: number | undefined) => void` (same ABI
|
|
@@ -7792,7 +7970,7 @@ export function lowerPromiseMethodCall(lowerer, call, access) {
|
|
|
7792
7970
|
value: {
|
|
7793
7971
|
kind: "dynCall",
|
|
7794
7972
|
callee: { kind: "varRef", localId: cbLocal.id, type: DYN, loc },
|
|
7795
|
-
calleeName: jsFuncNameOf(call.arguments[0]) ?? "onFulfilled",
|
|
7973
|
+
calleeName: jsFuncNameOf(call.arguments[0], lowerer) ?? "onFulfilled",
|
|
7796
7974
|
args: handlerArgs,
|
|
7797
7975
|
type: DYN,
|
|
7798
7976
|
loc,
|
|
@@ -7825,7 +8003,8 @@ export function lowerPromiseMethodCall(lowerer, call, access) {
|
|
|
7825
8003
|
lowerer.unsupported("SC1090", call.arguments[0], "then handlers with more than one parameter (the two-argument onRejected form has no lowering — chain .catch(...) instead)");
|
|
7826
8004
|
}
|
|
7827
8005
|
const param = cb.type.params[0];
|
|
7828
|
-
if (param !== undefined && !typeEquals(param, inner) &&
|
|
8006
|
+
if (param !== undefined && !typeEquals(param, inner) &&
|
|
8007
|
+
!(param.kind === "dyn" && (inner.kind === "void" || lowerer.dynConvertible(inner)))) {
|
|
7829
8008
|
lowerer.unsupported("SC1090", call.arguments[0], `then handlers whose parameter is not the settled value's type (expected '${lowerer.fmt(inner)}', got '${lowerer.fmt(param)}')`);
|
|
7830
8009
|
}
|
|
7831
8010
|
const resultT = lowerer.mapTypeOf(lowerer.typeOf(call));
|
|
@@ -7855,7 +8034,7 @@ export function lowerPromiseMethodCall(lowerer, call, access) {
|
|
|
7855
8034
|
if (param !== undefined && inner.kind !== "void") {
|
|
7856
8035
|
const vLocal = lowerer.declareHiddenLocal("v", inner);
|
|
7857
8036
|
body.push({ kind: "varDecl", localId: vLocal.id, init: awaitE, loc });
|
|
7858
|
-
handlerArgs = [{ kind: "varRef", localId: vLocal.id, type: inner, loc }];
|
|
8037
|
+
handlerArgs = [lowerer.coerceToExpected({ kind: "varRef", localId: vLocal.id, type: inner, loc }, param)];
|
|
7859
8038
|
}
|
|
7860
8039
|
else {
|
|
7861
8040
|
body.push({ kind: "exprStmt", expr: awaitE, loc });
|
|
@@ -7916,6 +8095,14 @@ export function lowerPromiseMethodCall(lowerer, call, access) {
|
|
|
7916
8095
|
}
|
|
7917
8096
|
if (member === "finally") {
|
|
7918
8097
|
const cb = lowerer.lowerExpr(call.arguments[0]);
|
|
8098
|
+
if (lowerer.dynConvertible(promT) && lowerer.dynConvertible(cb.type)) {
|
|
8099
|
+
const result = {
|
|
8100
|
+
kind: "dynInvoke", recv: lowerer.coerceToExpected(receiver, DYN),
|
|
8101
|
+
method: "finally", calleeName: access.getText(),
|
|
8102
|
+
args: [lowerer.coerceToExpected(cb, DYN)], type: DYN, loc,
|
|
8103
|
+
};
|
|
8104
|
+
return lowerer.coerceToExpected(result, promT);
|
|
8105
|
+
}
|
|
7919
8106
|
if (cb.type.kind !== "func" || cb.type.params.length !== 0 || cb.type.ret.kind !== "void") {
|
|
7920
8107
|
lowerer.unsupported("SC1090", call.arguments[0], "finally callbacks with parameters or a return value (use () => { ... })");
|
|
7921
8108
|
}
|
|
@@ -7992,7 +8179,8 @@ export function lowerPromiseMethodCall(lowerer, call, access) {
|
|
|
7992
8179
|
// receiver, passes fulfillments through as dyn, and on rejection
|
|
7993
8180
|
// calls the boxed handler with caughtToDyn's identity-preserving
|
|
7994
8181
|
// snapshot (the dyn-then desugar's catch twin).
|
|
7995
|
-
if (member === "catch" && inner.kind === "dyn")
|
|
8182
|
+
if (member === "catch" && (inner.kind === "dyn" || isJsSourceFile(call.getSourceFile()) &&
|
|
8183
|
+
(inner.kind === "void" || lowerer.dynConvertible(inner)))) {
|
|
7996
8184
|
let cb = lowerer.lowerExpr(call.arguments[0]);
|
|
7997
8185
|
if (cb.type.kind === "func" &&
|
|
7998
8186
|
canBoxFuncIntoDyn(cb.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) {
|
|
@@ -8009,20 +8197,11 @@ export function lowerPromiseMethodCall(lowerer, call, access) {
|
|
|
8009
8197
|
const pLocal = lowerer.declareHiddenLocal("p", promT);
|
|
8010
8198
|
const cbLocal = lowerer.declareHiddenLocal("cb", DYN);
|
|
8011
8199
|
const eLocal = lowerer.declareHiddenLocal("e", CAUGHT);
|
|
8012
|
-
const vLocal = lowerer.declareHiddenLocal("v",
|
|
8200
|
+
const vLocal = inner.kind === "void" ? null : lowerer.declareHiddenLocal("v", inner);
|
|
8201
|
+
const awaited = { kind: "awaitExpr", value: { kind: "varRef", localId: pLocal.id, type: promT, loc }, type: inner, loc };
|
|
8013
8202
|
const tryBody = [
|
|
8014
|
-
{
|
|
8015
|
-
|
|
8016
|
-
localId: vLocal.id,
|
|
8017
|
-
init: {
|
|
8018
|
-
kind: "awaitExpr",
|
|
8019
|
-
value: { kind: "varRef", localId: pLocal.id, type: promT, loc },
|
|
8020
|
-
type: DYN,
|
|
8021
|
-
loc,
|
|
8022
|
-
},
|
|
8023
|
-
loc,
|
|
8024
|
-
},
|
|
8025
|
-
{ kind: "return", value: { kind: "varRef", localId: vLocal.id, type: DYN, loc }, loc },
|
|
8203
|
+
vLocal ? { kind: "varDecl", localId: vLocal.id, init: awaited, loc } : { kind: "exprStmt", expr: awaited, loc },
|
|
8204
|
+
{ kind: "return", value: vLocal ? lowerer.coerceToExpected(varRef(vLocal.id, inner, loc), DYN) : dynUndefinedExpr(loc), loc },
|
|
8026
8205
|
];
|
|
8027
8206
|
const catchBody = [
|
|
8028
8207
|
{
|
|
@@ -8030,7 +8209,7 @@ export function lowerPromiseMethodCall(lowerer, call, access) {
|
|
|
8030
8209
|
value: {
|
|
8031
8210
|
kind: "dynCall",
|
|
8032
8211
|
callee: { kind: "varRef", localId: cbLocal.id, type: DYN, loc },
|
|
8033
|
-
calleeName: jsFuncNameOf(call.arguments[0]) ?? "onRejected",
|
|
8212
|
+
calleeName: jsFuncNameOf(call.arguments[0], lowerer) ?? "onRejected",
|
|
8034
8213
|
args: [
|
|
8035
8214
|
{
|
|
8036
8215
|
kind: "caughtToDyn",
|
|
@@ -8833,7 +9012,7 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
8833
9012
|
!call.arguments.some(ts.isSpreadElement) && !lowerer.dynamic) {
|
|
8834
9013
|
let object = lowerer.lowerExpr(call.arguments[0]);
|
|
8835
9014
|
if (object.type.kind === "func") {
|
|
8836
|
-
const fnName = jsFuncNameOf(call.arguments[0]);
|
|
9015
|
+
const fnName = jsFuncNameOf(call.arguments[0], lowerer);
|
|
8837
9016
|
object = { kind: "dynFrom", value: object, type: DYN, loc: locOf(call),
|
|
8838
9017
|
...(fnName !== null ? { fnName } : {}) };
|
|
8839
9018
|
}
|
|
@@ -8841,8 +9020,15 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
8841
9020
|
object = lowerer.coerceInto(call.arguments[0], object, DYN);
|
|
8842
9021
|
if (object.type.kind === "dyn") {
|
|
8843
9022
|
const loc = locOf(call);
|
|
8844
|
-
if (member === "getPrototypeOf")
|
|
8845
|
-
|
|
9023
|
+
if (member === "getPrototypeOf") {
|
|
9024
|
+
let parent = call.parent;
|
|
9025
|
+
while (parent && ts.isParenthesizedExpression(parent))
|
|
9026
|
+
parent = parent.parent;
|
|
9027
|
+
const identityOnly = !!parent && ts.isBinaryExpression(parent) &&
|
|
9028
|
+
[ts.SyntaxKind.EqualsEqualsEqualsToken, ts.SyntaxKind.ExclamationEqualsEqualsToken].includes(parent.operatorToken.kind);
|
|
9029
|
+
return { kind: "libCall", fn: "dyn.getPrototype", args: [object], type: DYN, loc,
|
|
9030
|
+
...(identityOnly ? { prototypeIdentityOnly: true } : {}) };
|
|
9031
|
+
}
|
|
8846
9032
|
const prototype = lowerer.lowerExprExpecting(call.arguments[1], DYN);
|
|
8847
9033
|
if (prototype.type.kind === "dyn")
|
|
8848
9034
|
return { kind: "libCall", fn: "dyn.setPrototype", args: [object, prototype], type: DYN, loc };
|
|
@@ -9024,7 +9210,7 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
9024
9210
|
if (isJsSourceFile(call.getSourceFile()) && call.arguments.length > 0 && !call.arguments.some(ts.isSpreadElement)) {
|
|
9025
9211
|
const target = tryLowerExpression(lowerer, call.arguments[0]);
|
|
9026
9212
|
if (target && ((target.type.kind === "func" && lowerer.dynConvertible(target.type)) ||
|
|
9027
|
-
(target.type.kind === "object" && lowerer.
|
|
9213
|
+
(target.type.kind === "object" && lowerer.dynConvertible(target.type)))) {
|
|
9028
9214
|
const loc = locOf(call);
|
|
9029
9215
|
return { kind: "libCall", fn: "dyn.assignAll", args: [lowerer.coerceToExpected(target, DYN),
|
|
9030
9216
|
{ kind: "dynArrLit", elems: call.arguments.slice(1).map((arg) => lowerer.lowerExprExpecting(arg, DYN)), type: DYN, loc },
|
|
@@ -9226,7 +9412,7 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
9226
9412
|
target = lowerer.coerceToExpected(target, DYN);
|
|
9227
9413
|
}
|
|
9228
9414
|
if (target?.type.kind === "func" && lowerer.dynConvertible(target.type)) {
|
|
9229
|
-
const fnName = jsFuncNameOf(call.arguments[0]);
|
|
9415
|
+
const fnName = jsFuncNameOf(call.arguments[0], lowerer);
|
|
9230
9416
|
target = { kind: "dynFrom", value: target, type: DYN, loc: locOf(call.arguments[0]), ...(fnName !== null ? { fnName } : {}) };
|
|
9231
9417
|
}
|
|
9232
9418
|
const descriptorPrimitive = member === "getOwnPropertyDescriptor" && target &&
|
|
@@ -9255,6 +9441,9 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
9255
9441
|
// static shapes have no property table to extend.
|
|
9256
9442
|
if (member === "defineProperties" && call.arguments.length === 2 &&
|
|
9257
9443
|
!call.arguments.some((a) => ts.isSpreadElement(a))) {
|
|
9444
|
+
const prototype = lowerClassPrototypeDescriptors(lowerer, call, member);
|
|
9445
|
+
if (prototype)
|
|
9446
|
+
return prototype;
|
|
9258
9447
|
let target = tryLowerExpression(lowerer, call.arguments[0]);
|
|
9259
9448
|
if (target) {
|
|
9260
9449
|
const native = lowerClassDataDescriptor(lowerer, call, member, target);
|
|
@@ -9267,7 +9456,7 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
9267
9456
|
// wrapper returned later reads the same table.
|
|
9268
9457
|
if (target && target.type.kind === "func" &&
|
|
9269
9458
|
canBoxFuncIntoDyn(target.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) {
|
|
9270
|
-
const fnName = jsFuncNameOf(call.arguments[0]);
|
|
9459
|
+
const fnName = jsFuncNameOf(call.arguments[0], lowerer);
|
|
9271
9460
|
target = { kind: "dynFrom", value: target, type: DYN, loc: locOf(call.arguments[0]), ...(fnName !== null ? { fnName } : {}) };
|
|
9272
9461
|
}
|
|
9273
9462
|
if (target && isUnitType(target.type)) {
|
|
@@ -9322,7 +9511,8 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
9322
9511
|
let inner = argNode;
|
|
9323
9512
|
while (ts.isParenthesizedExpression(inner) || ts.isAsExpression(inner))
|
|
9324
9513
|
inner = inner.expression;
|
|
9325
|
-
const value =
|
|
9514
|
+
const value = isJsSourceFile(call.getSourceFile()) && (ts.isObjectLiteralExpression(inner) || ts.isArrayLiteralExpression(inner))
|
|
9515
|
+
? lowerer.lowerExprExpecting(argNode, DYN) : lowerer.lowerExpr(argNode);
|
|
9326
9516
|
if (value.type.kind === "dyn")
|
|
9327
9517
|
return { kind: "libCall", fn: "dyn.freeze", args: [value], type: DYN, loc: locOf(call) };
|
|
9328
9518
|
if (ts.isObjectLiteralExpression(inner) || ts.isArrayLiteralExpression(inner)) {
|
|
@@ -9458,14 +9648,11 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
9458
9648
|
}
|
|
9459
9649
|
}
|
|
9460
9650
|
let argIr = lowerer.mapTypeOf(lowerer.typeOf(argNode));
|
|
9461
|
-
//
|
|
9462
|
-
//
|
|
9463
|
-
|
|
9464
|
-
if (
|
|
9465
|
-
|
|
9466
|
-
if (probed?.type.kind === "record")
|
|
9467
|
-
argIr = probed.type;
|
|
9468
|
-
}
|
|
9651
|
+
// Inferred records can carry runtime-optional index values that the
|
|
9652
|
+
// checker omits (named regex captures). Enumerate the represented shape.
|
|
9653
|
+
const represented = tryLowerExpression(lowerer, argNode);
|
|
9654
|
+
if (represented?.type.kind === "record")
|
|
9655
|
+
argIr = represented.type;
|
|
9469
9656
|
if (argIr?.kind !== "record")
|
|
9470
9657
|
return null; // Maps, classes, arrays → the SC2020 fence
|
|
9471
9658
|
const shape = lowerer.shapes.get(argIr.shapeId);
|
|
@@ -9857,6 +10044,13 @@ export function lowerRecordFieldCall(lowerer, call, access) {
|
|
|
9857
10044
|
return { kind: "callValue", callee, args, type: callee.type.ret, loc: locOf(call) };
|
|
9858
10045
|
}
|
|
9859
10046
|
const target = lowerer.fieldTarget(access);
|
|
10047
|
+
const loc = locOf(call);
|
|
10048
|
+
const receiverLocal = target && isJsSourceFile(call.getSourceFile())
|
|
10049
|
+
? lowerer.declareHiddenLocal("%callReceiver", target.obj.type) : null;
|
|
10050
|
+
const init = target && receiverLocal
|
|
10051
|
+
? { kind: "varDecl", localId: receiverLocal.id, init: target.obj, loc } : null;
|
|
10052
|
+
if (target && receiverLocal)
|
|
10053
|
+
target.obj = varRef(receiverLocal.id, receiverLocal.type, loc);
|
|
9860
10054
|
let callee = target ? lowerer.fieldGetExpr(target, locOf(access), access) : null;
|
|
9861
10055
|
if (!callee)
|
|
9862
10056
|
return null;
|
|
@@ -9865,10 +10059,24 @@ export function lowerRecordFieldCall(lowerer, call, access) {
|
|
|
9865
10059
|
// `.bold` (the chalk shape).
|
|
9866
10060
|
if (callee.type.kind === "record")
|
|
9867
10061
|
callee = lowerer.hybridCallUnwrap(callee);
|
|
10062
|
+
// Inferred JavaScript option records can retain checked callables in
|
|
10063
|
+
// fields even when the checker only describes those members as any.
|
|
10064
|
+
if (callee.type.kind === "dyn" && isJsSourceFile(call.getSourceFile())) {
|
|
10065
|
+
const receiver = target && receiverLocal ? lowerer.coerceToExpected(target.obj, DYN) : undefined;
|
|
10066
|
+
const spread = call.arguments.some(ts.isSpreadElement) ? lowerSpreadArgsCall(lowerer, call, callee, loc) : null;
|
|
10067
|
+
if (spread && spread.kind !== "dynCall")
|
|
10068
|
+
lowerer.unsupported("SC1090", call, "checked record property call spread arguments");
|
|
10069
|
+
const result = spread ? (receiver ? { ...spread, receiver } : spread) : {
|
|
10070
|
+
kind: "dynCall", callee, ...(receiver ? { receiver } : {}), calleeName: access.getText(),
|
|
10071
|
+
args: call.arguments.map((arg) => lowerer.lowerExprExpecting(arg, DYN)), type: DYN, loc,
|
|
10072
|
+
};
|
|
10073
|
+
return init ? { kind: "seqExpr", stmts: [init], result, type: result.type, loc } : result;
|
|
10074
|
+
}
|
|
9868
10075
|
if (callee.type.kind !== "func")
|
|
9869
10076
|
lowerer.badType(access, lowerer.typeOf(access));
|
|
9870
10077
|
const args = completeFuncValueArgs(lowerer, call, callee.type, locOf(call));
|
|
9871
|
-
|
|
10078
|
+
const result = { kind: "callValue", callee, ...(target && receiverLocal ? { receiver: lowerer.coerceToExpected(target.obj, DYN) } : {}), args, type: callee.type.ret, loc };
|
|
10079
|
+
return init ? { kind: "seqExpr", stmts: [init], result, type: result.type, loc } : result;
|
|
9872
10080
|
}
|
|
9873
10081
|
/** The function-like node behind an object-literal generic-method member:
|
|
9874
10082
|
* the MethodDeclaration itself (`{ m<T>(x: T) {...} }`) or a generic
|
|
@@ -10526,7 +10734,8 @@ export function requireObjLitGenericReceiver(lowerer, blame, recvExpr, literal,
|
|
|
10526
10734
|
* direct `call` of the instance with the receiver unevaluated. Claims
|
|
10527
10735
|
* every call whose member is generic-callable — lowering it or fencing
|
|
10528
10736
|
* with a named message. */
|
|
10529
|
-
/** URL
|
|
10737
|
+
/** The URL factories use the constructor's conversion order and parser.
|
|
10738
|
+
* URL.revokeObjectURL() with NO argument: Node's ERR_MISSING_ARGS
|
|
10530
10739
|
* throws before the registry lookup, so the zero-argument contract is
|
|
10531
10740
|
* exact without any blob machinery. The one-argument form (Node's
|
|
10532
10741
|
* silent no-op for unregistered ids) and createObjectURL keep their
|
|
@@ -10534,12 +10743,15 @@ export function requireObjLitGenericReceiver(lowerer, blame, recvExpr, literal,
|
|
|
10534
10743
|
function lowerUrlStaticCall(lowerer, call, callee) {
|
|
10535
10744
|
if (!ts.isPropertyAccessExpression(callee) || callee.questionDotToken !== undefined)
|
|
10536
10745
|
return null;
|
|
10537
|
-
if (!ts.isIdentifier(callee.expression)
|
|
10538
|
-
return null;
|
|
10539
|
-
if (callee.name.text !== "revokeObjectURL" || call.arguments.length !== 0)
|
|
10746
|
+
if (!ts.isIdentifier(callee.expression))
|
|
10540
10747
|
return null;
|
|
10541
10748
|
const sym = lowerer.resolveValueSymbol(callee.expression);
|
|
10542
|
-
if (!sym || !lowerer.isStdlibSymbol(sym))
|
|
10749
|
+
if (!sym || !lowerer.isStdlibSymbol(sym) || sym.name !== "URL")
|
|
10750
|
+
return null;
|
|
10751
|
+
if (callee.name.text === "canParse" || callee.name.text === "parse") {
|
|
10752
|
+
return lowerUrlFactory(lowerer, call, callee.name.text);
|
|
10753
|
+
}
|
|
10754
|
+
if (callee.name.text !== "revokeObjectURL" || call.arguments.length !== 0)
|
|
10543
10755
|
return null;
|
|
10544
10756
|
return nodeThrowExpr(1, "ERR_MISSING_ARGS", 'The "url" argument must be specified', VOID, locOf(call));
|
|
10545
10757
|
}
|
|
@@ -10820,9 +11032,11 @@ export function lowerObjectMethodCall(lowerer, call, access) {
|
|
|
10820
11032
|
// type still belongs to the unspecialized body (plane.normal.dot()).
|
|
10821
11033
|
// Use the lowered receiver's representation and retain its evaluation.
|
|
10822
11034
|
const probe = mappedReceiver?.kind !== "object" && (lowerer.implicitParamTypes !== null || ts.isNewExpression(access.expression) ||
|
|
10823
|
-
isJsSourceFile(call.getSourceFile())
|
|
10824
|
-
? tryLowerExpression(lowerer, access.expression)
|
|
10825
|
-
|
|
11035
|
+
isJsSourceFile(call.getSourceFile()))
|
|
11036
|
+
? ts.isNewExpression(access.expression) ? lowerer.lowerExpr(access.expression) : tryLowerExpression(lowerer, access.expression)
|
|
11037
|
+
: null;
|
|
11038
|
+
const specializedReceiver = probe?.type.kind === "object" || probe?.type.kind === "union" &&
|
|
11039
|
+
lowerer.unions.get(probe.type.unionId)?.arms.some((arm) => arm.kind === "object") ? probe : null;
|
|
10826
11040
|
if (specializedReceiver)
|
|
10827
11041
|
mappedReceiver = specializedReceiver.type;
|
|
10828
11042
|
if (mappedReceiver?.kind === "union") {
|
|
@@ -10833,8 +11047,7 @@ export function lowerObjectMethodCall(lowerer, call, access) {
|
|
|
10833
11047
|
const arms = lowerer.unions.get(mappedReceiver.unionId)?.arms;
|
|
10834
11048
|
if (isJsSourceFile(call.getSourceFile()) && arms?.every((arm) => arm.kind === "object" &&
|
|
10835
11049
|
!lowerer.classes.get(arm.className)?.def.runtime) && lowerer.dynConvertible(mappedReceiver)) {
|
|
10836
|
-
|
|
10837
|
-
return lowerDynDispatchMethodCall(lowerer, call, access, receiver, false);
|
|
11050
|
+
return lowerDynReceiverMethodCall(lowerer, call, access);
|
|
10838
11051
|
}
|
|
10839
11052
|
}
|
|
10840
11053
|
const receiverIr = mappedReceiver?.kind === "object"
|
|
@@ -10982,7 +11195,7 @@ export function lowerObjectMethodCall(lowerer, call, access) {
|
|
|
10982
11195
|
const fallback = virtual
|
|
10983
11196
|
? { kind: "virtualCall", className: info.def.name, method, args: [lowerer.upcastTo(value, info.def.name), ...args], type: found.sig.ret, loc }
|
|
10984
11197
|
: { kind: "call", callee: `%${found.declarer.def.name}.${method}`, args: [lowerer.upcastTo(value, found.declarer.def.name), ...args], type: found.sig.ret, loc };
|
|
10985
|
-
const result = classCallbackCall(lowerer, value, method, call.arguments.map((arg) => lowerer.lowerExprExpecting(arg, DYN)), fallback, loc);
|
|
11198
|
+
const result = classCallbackCall(lowerer, value, method, call.arguments.map((arg) => lowerer.lowerExprExpecting(arg, DYN)), fallback, loc, access.getText());
|
|
10986
11199
|
return { kind: "seqExpr", stmts: [{ kind: "varDecl", localId: local.id, init: receiver, loc }], result, type: result.type, loc };
|
|
10987
11200
|
}
|
|
10988
11201
|
if (found.declarer.builtinError) {
|