@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
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { InternalCompilerError } from "../../errors.js";
|
|
2
|
+
import { SYMBOL_T } from "../../ir/ir.js";
|
|
2
3
|
import { literalValues } from "../literal-values.js";
|
|
3
4
|
import { literalUnionArm } from "../union-discriminants.js";
|
|
4
5
|
/* Expression lowering: the expression dispatch (lowerExpr), literals
|
|
@@ -10,7 +11,6 @@ import { literalUnionArm } from "../union-discriminants.js";
|
|
|
10
11
|
import * as ts from "../ts7/adapter.js";
|
|
11
12
|
import { dirname } from "node:path";
|
|
12
13
|
import * as posix from "node:path/posix";
|
|
13
|
-
import { pathToFileURL } from "node:url";
|
|
14
14
|
import { captureContextArguments } from "./function-context.js";
|
|
15
15
|
import { OBJECT_CALLABLE_VALUES } from "./surfaces.js";
|
|
16
16
|
import { wasiGuestPath } from "../../wasi-paths.js";
|
|
@@ -53,13 +53,15 @@ import { classSymbolKeyOf } from "./symbol-fields.js";
|
|
|
53
53
|
import { lowerClassMethodValue } from "./class-method-values.js";
|
|
54
54
|
import { classInstanceOf } from "./class-dynamic-dispatch.js";
|
|
55
55
|
import { lowerGlobalValue } from "./lower-global-value.js";
|
|
56
|
-
import {
|
|
56
|
+
import { importMetaField, isImportMeta } from "./import-meta.js";
|
|
57
|
+
import { lowerClassPrototypeData, lowerClassPrototypeComputedAssignment } from "./class-prototypes.js";
|
|
57
58
|
import { isClassCallback } from "./class-callbacks.js";
|
|
58
59
|
import { builtinPrototypeMethod, lowerArrayIsArrayValue, lowerCheckedPredicateValue, lowerNumberParserValue, lowerObjectAssignValue, lowerStringCodesValue } from "./lower-builtin-values.js";
|
|
59
60
|
import { lowerArrayFromValue } from "./lower-containers.js";
|
|
60
|
-
import { lowerPerfHooksTypeof } from "./lower-builtins.js";
|
|
61
|
+
import { lowerPerfHooksTypeof, lowerUrlAssignment } from "./lower-builtins.js";
|
|
61
62
|
import { jsBindingHasOpenWrites } from "./lower-stmts.js";
|
|
62
63
|
import { checkedClassInstanceOf } from "./class-construction.js";
|
|
64
|
+
import { lowerModuleNamespaceElement } from "./module-namespace-elements.js";
|
|
63
65
|
/** A template piece's RAW text (String.raw's contract: escapes stay
|
|
64
66
|
* characters). 7's client AST ships no rawText at runtime (the typing
|
|
65
67
|
* declares it; the serialized node data omits it), so the raw span comes
|
|
@@ -123,6 +125,25 @@ function isParseArgsDynProperty(lowerer, expr) {
|
|
|
123
125
|
return false;
|
|
124
126
|
});
|
|
125
127
|
}
|
|
128
|
+
function isStatFsDynProperty(lowerer, expr) {
|
|
129
|
+
if (!["type", "bsize", "blocks", "bfree", "bavail", "files", "ffree", "bigint"].includes(expr.name.text))
|
|
130
|
+
return false;
|
|
131
|
+
const symbol = lowerer.checker.getSymbolAtLocation(expr.name);
|
|
132
|
+
return !!symbol && lowerer.checker.declarationsOf(symbol).some((declaration) => {
|
|
133
|
+
if (!lowerer.isStdlibFile(declaration.getSourceFile()))
|
|
134
|
+
return false;
|
|
135
|
+
const parent = declaration.parent;
|
|
136
|
+
if (!ts.isInterfaceDeclaration(parent))
|
|
137
|
+
return false;
|
|
138
|
+
if (expr.name.text === "bigint" ? parent.name.text !== "StatFsOptions" : !["StatsFsBase", "StatsFs", "BigIntStatsFs"].includes(parent.name.text))
|
|
139
|
+
return false;
|
|
140
|
+
for (let node = parent.parent; node; node = node.parent) {
|
|
141
|
+
if (ts.isModuleDeclaration(node) && ts.isStringLiteral(node.name))
|
|
142
|
+
return node.name.text === "fs" || node.name.text === "node:fs";
|
|
143
|
+
}
|
|
144
|
+
return false;
|
|
145
|
+
});
|
|
146
|
+
}
|
|
126
147
|
export function lowerExpr(lowerer, expr) {
|
|
127
148
|
if (lowerExprDepth >= LOWER_EXPR_MAX_DEPTH) {
|
|
128
149
|
lowerer.unsupported("SC1090", expr, `expressions nested deeper than ${LOWER_EXPR_MAX_DEPTH} levels`);
|
|
@@ -586,6 +607,8 @@ function lowerExprInner(lowerer, expr) {
|
|
|
586
607
|
if (ts.isTypeOfExpression(expr)) {
|
|
587
608
|
if (lowerer.isStdlibGlobal(expr.expression, "process"))
|
|
588
609
|
return { kind: "strLit", value: "object", type: STRING, loc };
|
|
610
|
+
if (lowerer.isStdlibGlobal(expr.expression, "fetch"))
|
|
611
|
+
return { kind: "strLit", value: "function", type: STRING, loc };
|
|
589
612
|
const performance = lowerPerfHooksTypeof(lowerer, expr.expression);
|
|
590
613
|
if (performance)
|
|
591
614
|
return performance;
|
|
@@ -777,7 +800,7 @@ function lowerExprInner(lowerer, expr) {
|
|
|
777
800
|
if (use?.kind === "element") {
|
|
778
801
|
const key = runtimeOptionalElementKey(use.access.argumentExpression);
|
|
779
802
|
if (key === null) {
|
|
780
|
-
|
|
803
|
+
return varRef(local.id, local.type, loc);
|
|
781
804
|
}
|
|
782
805
|
return runtimeOptionalReceiverRead(lowerer, expr, local, key, loc);
|
|
783
806
|
}
|
|
@@ -1067,6 +1090,8 @@ function lowerExprInner(lowerer, expr) {
|
|
|
1067
1090
|
}
|
|
1068
1091
|
if (lowerer.isStdlibGlobal(expr, "ArrayBuffer"))
|
|
1069
1092
|
return { kind: "libCall", fn: "arrayBuffer.constructor", args: [], type: DYN, loc };
|
|
1093
|
+
if (isJsSourceFile(expr.getSourceFile()) && lowerer.isStdlibGlobal(expr, "Array"))
|
|
1094
|
+
return { kind: "libCall", fn: "dyn.arrayConstructor", args: [], type: DYN, loc };
|
|
1070
1095
|
if (Object.values(BYTES_ELEMENT_NAME).includes(expr.text) && lowerer.isStdlibSymbol(lowerer.checker.getSymbolAtLocation(expr))) {
|
|
1071
1096
|
return { kind: "libCall", fn: "bytes.constructor", args: [{ kind: "strLit", value: expr.text, type: STRING, loc }], type: DYN, loc };
|
|
1072
1097
|
}
|
|
@@ -1941,6 +1966,13 @@ function lowerExprInner(lowerer, expr) {
|
|
|
1941
1966
|
: { kind: "strIntrinsic", method: "length", receiver: recv, args: [], type: F64, loc };
|
|
1942
1967
|
}
|
|
1943
1968
|
}
|
|
1969
|
+
if (isJsSourceFile(expr.getSourceFile()) && expr.name.text === "constructor") {
|
|
1970
|
+
const receiver = tryLowerExpression(lowerer, expr.expression);
|
|
1971
|
+
if (receiver?.type.kind === "dyn" || receiver?.type.kind === "object" && !lowerer.classes.get(receiver.type.className)?.fields.has("constructor")) {
|
|
1972
|
+
return { kind: "dynKeyGet", value: lowerer.coerceToExpected(receiver, DYN),
|
|
1973
|
+
key: { kind: "strLit", value: "constructor", type: STRING, loc }, type: DYN, loc };
|
|
1974
|
+
}
|
|
1975
|
+
}
|
|
1944
1976
|
// `f.name` / `f.length` / own properties on a FUNCTION-typed JS
|
|
1945
1977
|
// value (the mustCall wrapper's function-instance members): read
|
|
1946
1978
|
// through the dyn box — the closure's own-property table answers
|
|
@@ -2018,16 +2050,13 @@ function lowerExprInner(lowerer, expr) {
|
|
|
2018
2050
|
return nsUndefRead(lowerer, ambientRoot.text, expr, t);
|
|
2019
2051
|
}
|
|
2020
2052
|
}
|
|
2021
|
-
//
|
|
2022
|
-
//
|
|
2023
|
-
//
|
|
2024
|
-
// the generic dyn receiver path below. Provenance is limited to the
|
|
2025
|
-
// node:util parseArgs family; every other stdlib member keeps its
|
|
2026
|
-
// ordinary surface fence.
|
|
2053
|
+
// Checked-dynamic stdlib results retain ambient property symbols,
|
|
2054
|
+
// including parseArgs tokens narrowed to anonymous union arms. Only
|
|
2055
|
+
// members owned by these implemented families bypass the stdlib fence.
|
|
2027
2056
|
const segmentDataSymbol = lowerer.typeOf(expr.expression).getSymbol();
|
|
2028
2057
|
const segmentDataProperty = segmentDataSymbol?.name === "SegmentData" && lowerer.isStdlibSymbol(segmentDataSymbol) &&
|
|
2029
2058
|
["segment", "index", "input", "isWordLike"].includes(expr.name.text);
|
|
2030
|
-
if (isParseArgsDynProperty(lowerer, expr) || segmentDataProperty) {
|
|
2059
|
+
if (isParseArgsDynProperty(lowerer, expr) || isStatFsDynProperty(lowerer, expr) || segmentDataProperty) {
|
|
2031
2060
|
const recv = lowerer.lowerExpr(expr.expression);
|
|
2032
2061
|
if (recv.type.kind === "dyn") {
|
|
2033
2062
|
const key = {
|
|
@@ -2091,7 +2120,8 @@ function lowerExprInner(lowerer, expr) {
|
|
|
2091
2120
|
// chain. Scalar-narrowed occurrences bridge via maybeNarrow's
|
|
2092
2121
|
// validated dynCheck as usual.
|
|
2093
2122
|
if (recvLowered.type.kind === "dyn" || isJsSourceFile(expr.getSourceFile()) &&
|
|
2094
|
-
["f64", "bool", "bigint", "string", "symbol"].includes(recvLowered.type.kind)
|
|
2123
|
+
(["f64", "bool", "bigint", "string", "symbol"].includes(recvLowered.type.kind) ||
|
|
2124
|
+
recvLowered.type.kind === "union" && lowerer.dynConvertible(recvLowered.type))) {
|
|
2095
2125
|
const key = { kind: "strLit", value: expr.name.text, type: STRING, loc: locOf(expr.name) };
|
|
2096
2126
|
const opt = hasOptionalChainGuard(expr.expression);
|
|
2097
2127
|
return lowerer.maybeNarrow({ kind: "dynKeyGet", key, ...(opt ? { optional: true } : {}), value: lowerer.coerceToExpected(recvLowered, DYN), type: DYN, loc }, expr);
|
|
@@ -2187,38 +2217,7 @@ function moduleFileName(lowerer, sf) {
|
|
|
2187
2217
|
: sf.fileName;
|
|
2188
2218
|
}
|
|
2189
2219
|
function importMetaProperty(lowerer, expr) {
|
|
2190
|
-
|
|
2191
|
-
return null;
|
|
2192
|
-
const meta = expr.expression;
|
|
2193
|
-
if (meta.keywordToken !== ts.SyntaxKind.ImportKeyword || meta.name.text !== "meta")
|
|
2194
|
-
return null;
|
|
2195
|
-
const sf = expr.getSourceFile();
|
|
2196
|
-
const fileName = moduleFileName(lowerer, sf);
|
|
2197
|
-
switch (expr.name.text) {
|
|
2198
|
-
case "env":
|
|
2199
|
-
return dynUndefinedExpr(locOf(expr));
|
|
2200
|
-
case "url":
|
|
2201
|
-
return {
|
|
2202
|
-
kind: "strLit",
|
|
2203
|
-
value: pathToFileURL(fileName, { windows: lowerer.targetPlatform === "win32" }).href,
|
|
2204
|
-
type: STRING,
|
|
2205
|
-
loc: locOf(expr),
|
|
2206
|
-
};
|
|
2207
|
-
case "filename":
|
|
2208
|
-
return { kind: "strLit", value: fileName, type: STRING, loc: locOf(expr) };
|
|
2209
|
-
case "dirname":
|
|
2210
|
-
return {
|
|
2211
|
-
kind: "strLit",
|
|
2212
|
-
value: lowerer.targetPlatform === "wasi" ? posix.dirname(fileName) : dirname(fileName),
|
|
2213
|
-
type: STRING,
|
|
2214
|
-
loc: locOf(expr),
|
|
2215
|
-
};
|
|
2216
|
-
case "main":
|
|
2217
|
-
return { kind: "boolLit", value: sf === lowerer.entry, type: BOOL, loc: locOf(expr) };
|
|
2218
|
-
default:
|
|
2219
|
-
lowerer.unsupported("SC1090", expr, `'import.meta.${expr.name.text}' (only url, filename, dirname, and main are supported in static ESM)`);
|
|
2220
|
-
return null;
|
|
2221
|
-
}
|
|
2220
|
+
return isImportMeta(expr.expression) ? importMetaField(lowerer, expr, expr.name.text) : null;
|
|
2222
2221
|
}
|
|
2223
2222
|
/** `c ? a : b`. An explicit destination constructs each branch at that
|
|
2224
2223
|
* layout before joining it. Without one, retain the expression's inferred
|
|
@@ -2540,8 +2539,52 @@ export function maybeNarrow(lowerer, expr, node) {
|
|
|
2540
2539
|
// instead of misreading the payload (the dyn boundary's usual stance).
|
|
2541
2540
|
// Object/array narrowings stay dyn-typed and keep their fences.
|
|
2542
2541
|
if (expr.type.kind === "dyn") {
|
|
2542
|
+
// An inferred JS member's storage may be deliberately wider than its
|
|
2543
|
+
// declaration (prototype-selected buffers, null-initialized scratch
|
|
2544
|
+
// objects). Extract at the consuming operation, not at the read.
|
|
2545
|
+
if (isJsSourceFile(node.getSourceFile()) && ts.isPropertyAccessExpression(node)) {
|
|
2546
|
+
const receiver = lowerer.mapTypeOf(lowerer.typeOf(node.expression));
|
|
2547
|
+
if (receiver?.kind === "object") {
|
|
2548
|
+
const info = lowerer.classes.get(receiver.className);
|
|
2549
|
+
if (info?.fields.get(node.name.text)?.kind === "dyn" || lowerer.findMethodOn(info ?? null, `get:${node.name.text}`)?.sig.ret.kind === "dyn")
|
|
2550
|
+
return expr;
|
|
2551
|
+
}
|
|
2552
|
+
if (receiver?.kind === "classval") {
|
|
2553
|
+
const info = lowerer.classes.get(receiver.className);
|
|
2554
|
+
if (info && hasRuntimeStatics(info))
|
|
2555
|
+
return expr;
|
|
2556
|
+
}
|
|
2557
|
+
}
|
|
2558
|
+
if (isJsSourceFile(node.getSourceFile()) &&
|
|
2559
|
+
(ts.isPropertyAccessExpression(node) || ts.isElementAccessExpression(node))) {
|
|
2560
|
+
let receiver = node.expression;
|
|
2561
|
+
while (ts.isPropertyAccessExpression(receiver) || ts.isElementAccessExpression(receiver) || ts.isParenthesizedExpression(receiver)) {
|
|
2562
|
+
if (ts.isPropertyAccessExpression(receiver)) {
|
|
2563
|
+
const owner = lowerer.mapTypeOf(lowerer.typeOf(receiver.expression));
|
|
2564
|
+
if (owner?.kind === "object" && lowerer.classes.get(owner.className)?.fields.get(receiver.name.text)?.kind === "dyn")
|
|
2565
|
+
return expr;
|
|
2566
|
+
}
|
|
2567
|
+
receiver = receiver.expression;
|
|
2568
|
+
}
|
|
2569
|
+
if (receiver.kind === ts.SyntaxKind.ThisKeyword && lowerer.resolveThis()?.type.kind === "dyn")
|
|
2570
|
+
return expr;
|
|
2571
|
+
if (ts.isIdentifier(receiver)) {
|
|
2572
|
+
const stored = lowerer.peekLocal(receiver)?.type ?? lowerer.globalOf(receiver)?.type;
|
|
2573
|
+
if (stored?.kind === "dyn")
|
|
2574
|
+
return expr;
|
|
2575
|
+
const symbol = lowerer.resolveValueSymbol(receiver);
|
|
2576
|
+
const bound = symbol && lowerer.implicitParamTypes?.get(symbol);
|
|
2577
|
+
if (bound && lowerer.mapTypeOf(bound)?.kind === "dyn")
|
|
2578
|
+
return expr;
|
|
2579
|
+
}
|
|
2580
|
+
}
|
|
2543
2581
|
if (isJsSourceFile(node.getSourceFile()) && ts.isIdentifier(node)) {
|
|
2544
2582
|
const symbol = lowerer.resolveValueSymbol(node);
|
|
2583
|
+
if (symbol && lowerer.checker.declarationsOf(symbol).some((decl) => ts.isParameter(decl) &&
|
|
2584
|
+
ts.isMethodDeclaration(decl.parent) && lowerer.checkedVirtualJsMethods.has(decl.parent)))
|
|
2585
|
+
return expr;
|
|
2586
|
+
if (symbol && lowerer.checker.declarationsOf(symbol).some((decl) => ts.isParameter(decl) && ts.isConstructorDeclaration(decl.parent)))
|
|
2587
|
+
return expr;
|
|
2545
2588
|
if (symbol && lowerer.checker.declarationsOf(symbol).some((decl) => ts.isVariableDeclaration(decl) && jsBindingHasOpenWrites(lowerer, decl)))
|
|
2546
2589
|
return expr;
|
|
2547
2590
|
if (symbol && lowerer.checker.declarationsOf(symbol).some((decl) => ts.isParameter(decl) && decl.initializer && !decl.type &&
|
|
@@ -2605,6 +2648,19 @@ export function maybeNarrow(lowerer, expr, node) {
|
|
|
2605
2648
|
}
|
|
2606
2649
|
if (expr.type.kind !== "union")
|
|
2607
2650
|
return expr;
|
|
2651
|
+
// Represented fields and index values can include undefined even when
|
|
2652
|
+
// checker inference or lib.d.ts declares strings (RegExp captures).
|
|
2653
|
+
// Only a declaration that represents the optional arm can provide a
|
|
2654
|
+
// trustworthy flow narrowing; otherwise consumers must check it.
|
|
2655
|
+
if ((expr.kind === "recordGet" || expr.kind === "recordKeyGet") &&
|
|
2656
|
+
(ts.isPropertyAccessExpression(node) || ts.isElementAccessExpression(node))) {
|
|
2657
|
+
const receiver = lowerer.mapTypeOf(lowerer.typeOf(node.expression));
|
|
2658
|
+
const shape = receiver?.kind === "record" ? lowerer.shapes.get(receiver.shapeId) : undefined;
|
|
2659
|
+
const declared = expr.kind === "recordGet" ? shape?.fields.find((field) => field.name === expr.field)?.type : shape?.indexValue;
|
|
2660
|
+
if (lowerer.armTag(expr.type.unionId, UNDEFINED_T) >= 0 &&
|
|
2661
|
+
declared && !(declared.kind === "union" && lowerer.armTag(declared.unionId, UNDEFINED_T) >= 0))
|
|
2662
|
+
return expr;
|
|
2663
|
+
}
|
|
2608
2664
|
if (ts.isIdentifier(node)) {
|
|
2609
2665
|
const symbol = lowerer.resolveValueSymbol(node);
|
|
2610
2666
|
if (symbol && lowerer.unstableSwitchBindings.has(symbol))
|
|
@@ -3559,14 +3615,16 @@ export function lowerIntrinsicProperty(lowerer, expr) {
|
|
|
3559
3615
|
if (receiver.type.kind === "dyn")
|
|
3560
3616
|
return { kind: "dynKeyGet", value: receiver,
|
|
3561
3617
|
key: { kind: "strLit", value: name, type: STRING, loc: locOf(expr) }, type: DYN, loc: locOf(expr) };
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
return { kind: "seqExpr", stmts: [{ kind: "exprStmt", expr: receiver, loc: locOf(expr) }], result, type: STRING, loc: locOf(expr) };
|
|
3618
|
+
const result = { kind: "libCall", fn: "dyn.arrayConstructor", args: [], type: DYN, loc: locOf(expr) };
|
|
3619
|
+
return { kind: "seqExpr", stmts: [{ kind: "exprStmt", expr: receiver, loc: locOf(expr) }], result, type: DYN, loc: locOf(expr) };
|
|
3565
3620
|
}
|
|
3566
3621
|
const strictReceiver = (expected) => {
|
|
3567
3622
|
const value = lowerer.lowerExpr(expr.expression);
|
|
3568
|
-
if (value.type.kind === "dyn")
|
|
3623
|
+
if (value.type.kind === "dyn") {
|
|
3624
|
+
if (isJsSourceFile(expr.getSourceFile()) && name === "length")
|
|
3625
|
+
return value;
|
|
3569
3626
|
return lowerer.coerceInto(expr.expression, value, expected);
|
|
3627
|
+
}
|
|
3570
3628
|
return lowerer.runtimeOptionalPropertyReceiver(expr.expression, value, expected, name) ?? value;
|
|
3571
3629
|
};
|
|
3572
3630
|
if (kind === "child") {
|
|
@@ -3670,7 +3728,7 @@ export function lowerIntrinsicProperty(lowerer, expr) {
|
|
|
3670
3728
|
// (the child.stdout pattern); a checker-narrowed read extracts
|
|
3671
3729
|
// through maybeNarrow like any union member.
|
|
3672
3730
|
if (name === "description") {
|
|
3673
|
-
const receiver = lowerer.lowerExpr(expr.expression);
|
|
3731
|
+
const receiver = lowerer.coerceToExpected(lowerer.lowerExpr(expr.expression), SYMBOL_T);
|
|
3674
3732
|
const type = { kind: "union", unionId: lowerer.unions.intern([STRING, UNDEFINED_T]) };
|
|
3675
3733
|
return { kind: "libCall", fn: "sym.desc", args: [receiver], type, loc };
|
|
3676
3734
|
}
|
|
@@ -3771,6 +3829,9 @@ export function lowerIntrinsicProperty(lowerer, expr) {
|
|
|
3771
3829
|
let receiver = expected?.kind === "bytes"
|
|
3772
3830
|
? strictReceiver(expected)
|
|
3773
3831
|
: lowerer.lowerExpr(expr.expression);
|
|
3832
|
+
if (receiver.type.kind === "dyn")
|
|
3833
|
+
return { kind: "dynCheck", value: { kind: "dynKeyGet", value: receiver,
|
|
3834
|
+
key: { kind: "strLit", value: name, type: STRING, loc: locOf(expr) }, type: DYN, loc: locOf(expr) }, type: F64, loc: locOf(expr) };
|
|
3774
3835
|
if (receiver.type.kind === "union" && lowerer.armTag(receiver.type.unionId, UNDEFINED_T) >= 0) {
|
|
3775
3836
|
const present = lowerer.stripUndefinedArm(receiver.type);
|
|
3776
3837
|
const helper = present.kind === "bytes"
|
|
@@ -4020,6 +4081,8 @@ export function lowerArrayLiteral(lowerer, expr, expected) {
|
|
|
4020
4081
|
if (arms?.length && arms.every((arm) => arm.kind === "classval"))
|
|
4021
4082
|
mapped = DYN;
|
|
4022
4083
|
}
|
|
4084
|
+
if (!expected && isJsSourceFile(expr.getSourceFile()) && expr.elements.some((element) => ts.isSpreadElement(element) && tryLowerExpression(lowerer, element.expression)?.type.kind === "dyn"))
|
|
4085
|
+
mapped = DYN;
|
|
4023
4086
|
// An EMPTY literal under a CONST ASSERTION whose type queries panicked
|
|
4024
4087
|
// (tsgo's readonly-[] TupleType conversion — the facade answers `any`,
|
|
4025
4088
|
// which maps to nothing statically and to an island value under
|
|
@@ -4417,6 +4480,12 @@ export function lowerOptionalNumber(lowerer, operand, loc, narrowedNode) {
|
|
|
4417
4480
|
* string-key element access (`a["length"]`) and string indexing (`s[0]`
|
|
4418
4481
|
* typechecks against the lib's index signature; use .charAt) stay out. */
|
|
4419
4482
|
export function lowerElementAccess(lowerer, expr) {
|
|
4483
|
+
if (isImportMeta(expr.expression)) {
|
|
4484
|
+
const name = lowerer.foldedStringKeyOf(expr.argumentExpression);
|
|
4485
|
+
if (name === null)
|
|
4486
|
+
lowerer.unsupported("SC1090", expr, "import.meta with a runtime-computed key (use a statically-known metadata field)");
|
|
4487
|
+
return importMetaField(lowerer, expr, name);
|
|
4488
|
+
}
|
|
4420
4489
|
// `a?.[i]`: the guard lowers as an optional-chain step around the
|
|
4421
4490
|
// plain element read below.
|
|
4422
4491
|
if (expr.questionDotToken && !lowerer.chainHandled.has(expr)) {
|
|
@@ -4438,6 +4507,9 @@ export function lowerElementAccess(lowerer, expr) {
|
|
|
4438
4507
|
const cachedModule = lowerRequireCacheElement(lowerer, expr);
|
|
4439
4508
|
if (cachedModule)
|
|
4440
4509
|
return cachedModule;
|
|
4510
|
+
const namespaceElement = lowerModuleNamespaceElement(lowerer, expr);
|
|
4511
|
+
if (namespaceElement)
|
|
4512
|
+
return namespaceElement;
|
|
4441
4513
|
// Native Web handles use the same supported surface for bracket and dot
|
|
4442
4514
|
// spellings. Fence a statically-known unsupported key before the generic
|
|
4443
4515
|
// checked-dynamic element-read path can turn it into a runtime missing
|
|
@@ -4540,6 +4612,13 @@ export function lowerElementAccess(lowerer, expr) {
|
|
|
4540
4612
|
const key = lowerer.lowerExprExpecting(expr.argumentExpression, DYN);
|
|
4541
4613
|
return lowerer.maybeNarrow({ kind: "dynKeyGet", key, value: boxed, type: DYN, loc }, expr);
|
|
4542
4614
|
}
|
|
4615
|
+
if (receiver?.type.kind === "array" || receiver?.type.kind === "bytes")
|
|
4616
|
+
receiverIr = receiver.type;
|
|
4617
|
+
if (receiver?.type.kind === "union") {
|
|
4618
|
+
const present = lowerer.stripUndefinedArm(receiver.type);
|
|
4619
|
+
if (present.kind === "array" || present.kind === "bytes")
|
|
4620
|
+
receiverIr = present;
|
|
4621
|
+
}
|
|
4543
4622
|
}
|
|
4544
4623
|
// A readonly tuple union under Array.isArray is checker-typed as an
|
|
4545
4624
|
// intersection with any[], whose structural mapping is not the tuple
|
|
@@ -4774,6 +4853,11 @@ export function lowerElementAccess(lowerer, expr) {
|
|
|
4774
4853
|
if (receiverIr?.kind !== "array") {
|
|
4775
4854
|
{
|
|
4776
4855
|
const receiver = tryLowerExpression(lowerer, expr.expression);
|
|
4856
|
+
if (receiver?.type.kind === "dyn" || receiver && isJsSourceFile(expr.getSourceFile()) &&
|
|
4857
|
+
(receiver.type.kind === "union" || receiver.type.kind === "bytes") && lowerer.dynConvertible(receiver.type)) {
|
|
4858
|
+
const key = lowerRecordPropertyKey(lowerer, lowerer.lowerExpr(expr.argumentExpression), expr.argumentExpression);
|
|
4859
|
+
return lowerer.maybeNarrow({ kind: "dynKeyGet", value: lowerer.coerceInto(expr.expression, receiver, DYN), key, type: DYN, loc: locOf(expr) }, expr);
|
|
4860
|
+
}
|
|
4777
4861
|
if (receiver?.type.kind === "func" &&
|
|
4778
4862
|
canBoxFuncIntoDyn(receiver.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) {
|
|
4779
4863
|
const key = lowerRecordPropertyKey(lowerer, lowerer.lowerExpr(expr.argumentExpression), expr.argumentExpression);
|
|
@@ -5353,7 +5437,9 @@ export function lowerElementCompound(lowerer, expr, op) {
|
|
|
5353
5437
|
const oldLocal = lowerer.declareHiddenLocal("%compoundOld", oldValue.type);
|
|
5354
5438
|
const oldRef = () => varRef(oldLocal.id, oldValue.type, loc);
|
|
5355
5439
|
const rhs = lowerer.lowerExpr(expr.right);
|
|
5356
|
-
const numericRhs =
|
|
5440
|
+
const numericRhs = rhs.type.kind === "dyn" && isJsSourceFile(expr.getSourceFile()) && receiver.type.kind === "bytes"
|
|
5441
|
+
? { kind: "libCall", fn: "dyn.toNumberCoerce", args: [rhs], type: F64, loc }
|
|
5442
|
+
: lowerOptionalNumber(lowerer, rhs, loc);
|
|
5357
5443
|
const elementType = receiver.type.kind === "array" ? receiver.type.elem : F64;
|
|
5358
5444
|
const valueType = elementType.kind === "union" && lowerer.armTag(elementType.unionId, UNDEFINED_T) >= 0
|
|
5359
5445
|
? lowerer.stripUndefinedArm(elementType)
|
|
@@ -5432,6 +5518,18 @@ export function lowerNativeFunctionAssignment(lowerer, expr) {
|
|
|
5432
5518
|
(!ts.isPropertyAccessExpression(target) && !ts.isElementAccessExpression(target)) ||
|
|
5433
5519
|
target.questionDotToken)
|
|
5434
5520
|
return null;
|
|
5521
|
+
// Checked constructors share the callable's live property descriptors.
|
|
5522
|
+
const classType = storedClassValueType(lowerer, target.expression);
|
|
5523
|
+
const staticClass = classType?.kind === "classval" ? lowerer.classes.get(classType.className) : undefined;
|
|
5524
|
+
if (staticClass && hasRuntimeStatics(staticClass)) {
|
|
5525
|
+
return lowerDynMemberAssignment(lowerer, expr, lowerer.lowerExprExpecting(target.expression, DYN));
|
|
5526
|
+
}
|
|
5527
|
+
// Other class statics and prototype tables have their own paths.
|
|
5528
|
+
// Probing them as ordinary functions could materialize unused methods.
|
|
5529
|
+
if (lowerer.exactClassOfReceiver(target.expression) ||
|
|
5530
|
+
ts.isPropertyAccessExpression(target.expression) && target.expression.name.text === "prototype" &&
|
|
5531
|
+
lowerer.exactClassOfReceiver(target.expression.expression))
|
|
5532
|
+
return null;
|
|
5435
5533
|
const receiver = tryLowerExpression(lowerer, target.expression);
|
|
5436
5534
|
if (receiver?.type.kind !== "func" ||
|
|
5437
5535
|
!canBoxFuncIntoDyn(receiver.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id)))
|
|
@@ -5445,6 +5543,9 @@ export function lowerNativeFunctionAssignment(lowerer, expr) {
|
|
|
5445
5543
|
return lowerDynMemberAssignment(lowerer, expr, boxed);
|
|
5446
5544
|
}
|
|
5447
5545
|
export function lowerElementWrite(lowerer, expr) {
|
|
5546
|
+
const prototype = lowerClassPrototypeComputedAssignment(lowerer, expr);
|
|
5547
|
+
if (prototype)
|
|
5548
|
+
return { kind: "exprStmt", expr: prototype, loc: locOf(expr) };
|
|
5448
5549
|
const target = expr.left;
|
|
5449
5550
|
fenceNodeModuleMutation(lowerer, target, "assignment");
|
|
5450
5551
|
const globalKey = globalSymbolKey(lowerer, target.expression, target.argumentExpression);
|
|
@@ -5502,6 +5603,12 @@ export function lowerElementWrite(lowerer, expr) {
|
|
|
5502
5603
|
}
|
|
5503
5604
|
}
|
|
5504
5605
|
let receiverIr = lowerer.mapTypeOf(lowerer.typeOf(target.expression));
|
|
5606
|
+
if (isJsSourceFile(expr.getSourceFile()) && checkedReceiver) {
|
|
5607
|
+
const represented = checkedReceiver.type.kind === "union"
|
|
5608
|
+
? lowerer.stripUndefinedArm(checkedReceiver.type) : checkedReceiver.type;
|
|
5609
|
+
if (represented.kind === "array" || represented.kind === "bytes")
|
|
5610
|
+
receiverIr = represented;
|
|
5611
|
+
}
|
|
5505
5612
|
if (receiverIr === null || receiverIr.kind === "dyn") {
|
|
5506
5613
|
const receiver = tryLowerExpression(lowerer, target.expression);
|
|
5507
5614
|
if (receiver?.type.kind === "array")
|
|
@@ -6278,78 +6385,86 @@ export function lowerPrefixUnary(lowerer, expr) {
|
|
|
6278
6385
|
}
|
|
6279
6386
|
lowerer.unsupported("SC1090", expr, `syntax '${ts.syntaxKindName(expr.kind)}'`);
|
|
6280
6387
|
}
|
|
6281
|
-
/**
|
|
6282
|
-
|
|
6283
|
-
|
|
6284
|
-
* backend reads/writes through the box); record fields and array
|
|
6285
|
-
* elements keep the fence in value position (statement-position `obj.f++`
|
|
6286
|
-
* still desugars through the compound-field path). */
|
|
6287
|
-
function lowerIncDec(lowerer, expr, prefix) {
|
|
6388
|
+
/** Member updates evaluate the reference once, convert its old value with
|
|
6389
|
+
* ToNumeric, store the new value, then yield the old or new numeric value. */
|
|
6390
|
+
export function lowerIncDec(lowerer, expr, prefix) {
|
|
6288
6391
|
const loc = locOf(expr);
|
|
6289
6392
|
const op = expr.operator === ts.SyntaxKind.PlusPlusToken ? "+" : "-";
|
|
6290
6393
|
if (!ts.isIdentifier(expr.operand)) {
|
|
6291
|
-
|
|
6292
|
-
|
|
6394
|
+
const access = expr.operand;
|
|
6395
|
+
if (!ts.isPropertyAccessExpression(access) && !ts.isElementAccessExpression(access) || access.questionDotToken) {
|
|
6396
|
+
lowerer.unsupported("SC1045", expr, "increment/decrement of this target");
|
|
6397
|
+
}
|
|
6398
|
+
fenceNodeModuleMutation(lowerer, access, "assignment");
|
|
6399
|
+
if (ts.isPropertyAccessExpression(access)) {
|
|
6400
|
+
const target = staticFieldWriteTarget(lowerer, access);
|
|
6293
6401
|
if (target) {
|
|
6294
6402
|
if (target.type.kind !== "f64")
|
|
6295
6403
|
lowerer.unsupported("SC1043", expr);
|
|
6296
6404
|
return { kind: "incDec", op, prefix, localId: target.id, type: F64, loc };
|
|
6297
6405
|
}
|
|
6298
6406
|
}
|
|
6299
|
-
|
|
6300
|
-
|
|
6301
|
-
|
|
6302
|
-
|
|
6303
|
-
|
|
6304
|
-
|
|
6305
|
-
|
|
6306
|
-
|
|
6307
|
-
|
|
6308
|
-
|
|
6309
|
-
|
|
6310
|
-
|
|
6311
|
-
|
|
6312
|
-
|
|
6313
|
-
|
|
6314
|
-
|
|
6315
|
-
|
|
6316
|
-
|
|
6317
|
-
|
|
6318
|
-
|
|
6319
|
-
|
|
6320
|
-
|
|
6321
|
-
|
|
6322
|
-
|
|
6323
|
-
|
|
6324
|
-
|
|
6325
|
-
|
|
6326
|
-
|
|
6327
|
-
|
|
6328
|
-
|
|
6329
|
-
const
|
|
6330
|
-
? lowerer.
|
|
6331
|
-
:
|
|
6332
|
-
|
|
6333
|
-
|
|
6334
|
-
|
|
6335
|
-
|
|
6336
|
-
|
|
6337
|
-
|
|
6338
|
-
|
|
6339
|
-
|
|
6340
|
-
|
|
6341
|
-
|
|
6342
|
-
|
|
6343
|
-
|
|
6344
|
-
|
|
6345
|
-
|
|
6346
|
-
|
|
6347
|
-
|
|
6348
|
-
|
|
6349
|
-
|
|
6350
|
-
|
|
6351
|
-
|
|
6352
|
-
|
|
6407
|
+
const stmts = [];
|
|
6408
|
+
const save = (value, name) => {
|
|
6409
|
+
const local = lowerer.declareHiddenLocal(name, value.type);
|
|
6410
|
+
stmts.push({ kind: "varDecl", localId: local.id, init: value, loc });
|
|
6411
|
+
return varRef(local.id, value.type, loc);
|
|
6412
|
+
};
|
|
6413
|
+
const finish = (read, write) => {
|
|
6414
|
+
const old = save(read.type.kind === "f64" ? read : {
|
|
6415
|
+
kind: "libCall", fn: "dyn.toNumeric", args: [lowerer.coerceInto(access, read, DYN)], type: DYN, loc,
|
|
6416
|
+
}, "%incrementOld");
|
|
6417
|
+
const next = save(old.type.kind === "f64" ? {
|
|
6418
|
+
kind: "bin", op, left: old, right: { kind: "numLit", value: 1, type: F64, loc }, type: F64, loc,
|
|
6419
|
+
} : {
|
|
6420
|
+
kind: "libCall", fn: "dyn.increment", args: [old, { kind: "boolLit", value: op === "+", type: BOOL, loc }], type: DYN, loc,
|
|
6421
|
+
}, "%incrementNext");
|
|
6422
|
+
stmts.push(write(next));
|
|
6423
|
+
const result = prefix ? next : old;
|
|
6424
|
+
return { kind: "seqExpr", stmts, result, type: result.type, loc };
|
|
6425
|
+
};
|
|
6426
|
+
const raw = lowerer.lowerExpr(access.expression);
|
|
6427
|
+
// Keep native array/byte storage: boxing a native array can create a
|
|
6428
|
+
// checked view, which is not a substitute for updating its slot.
|
|
6429
|
+
if (ts.isElementAccessExpression(access) && (raw.type.kind === "array" || raw.type.kind === "bytes")) {
|
|
6430
|
+
const receiver = save(raw, "%incrementArray");
|
|
6431
|
+
const rawIndex = lowerer.lowerExpr(access.argumentExpression);
|
|
6432
|
+
const index = save(rawIndex.type.kind === "dyn" && isJsSourceFile(expr.getSourceFile())
|
|
6433
|
+
? { kind: "libCall", fn: "dyn.toNumberCoerce", args: [rawIndex], type: F64, loc } : rawIndex, "%incrementIndex");
|
|
6434
|
+
if (index.type.kind !== "f64")
|
|
6435
|
+
lowerer.unsupported("SC1090", access, "incrementing non-number array keys");
|
|
6436
|
+
const type = raw.type;
|
|
6437
|
+
const read = type.kind === "array"
|
|
6438
|
+
? arrayValueRead(lowerer, receiver, index, type.elem, loc)
|
|
6439
|
+
: { kind: "bytesIntrinsic", method: "get", receiver, args: [index], type: F64, loc };
|
|
6440
|
+
return finish(read, (value) => type.kind === "array"
|
|
6441
|
+
? arrayValueStore(lowerer, receiver, index, lowerer.coerceInto(access, value, type.elem), type.elem, loc)
|
|
6442
|
+
: { kind: "bytesSet", arr: receiver, index, value: lowerer.coerceInto(access, value, F64), loc });
|
|
6443
|
+
}
|
|
6444
|
+
if (isJsSourceFile(expr.getSourceFile()) && raw.type.kind === "dyn") {
|
|
6445
|
+
const receiver = save(raw, "%incrementReceiver");
|
|
6446
|
+
const key = save(ts.isElementAccessExpression(access)
|
|
6447
|
+
? lowerer.lowerExprExpecting(access.argumentExpression, DYN)
|
|
6448
|
+
: lowerer.coerceInto(access, { kind: "strLit", value: access.name.text, type: STRING, loc }, DYN), "%incrementKey");
|
|
6449
|
+
return finish({ kind: "dynKeyGet", value: receiver, key, type: DYN, loc }, (value) => ({
|
|
6450
|
+
kind: "exprStmt", expr: { kind: "libCall", fn: "dyn.keySetComputed", args: [receiver, key, lowerer.coerceInto(access, value, DYN)], type: VOID, loc }, loc,
|
|
6451
|
+
}));
|
|
6452
|
+
}
|
|
6453
|
+
const target = ts.isPropertyAccessExpression(access) ? lowerer.fieldTarget(access) : symbolFieldTarget(lowerer, access);
|
|
6454
|
+
if (target && lowerer.dynConvertible(target.fieldType)) {
|
|
6455
|
+
target.obj = save(target.obj, "%incrementReceiver");
|
|
6456
|
+
return finish(lowerer.fieldGetExpr(target, loc, access), (value) => lowerer.fieldSetStmt(target, lowerer.coerceInto(access, value, target.fieldType), loc, access));
|
|
6457
|
+
}
|
|
6458
|
+
if (isJsSourceFile(expr.getSourceFile()) && lowerer.dynConvertible(raw.type)) {
|
|
6459
|
+
const receiver = save(lowerer.coerceInto(access.expression, raw, DYN), "%incrementReceiver");
|
|
6460
|
+
const key = save(ts.isElementAccessExpression(access)
|
|
6461
|
+
? lowerer.lowerExprExpecting(access.argumentExpression, DYN)
|
|
6462
|
+
: lowerer.coerceInto(access, { kind: "strLit", value: access.name.text, type: STRING, loc }, DYN), "%incrementKey");
|
|
6463
|
+
return finish({ kind: "dynKeyGet", value: receiver, key, type: DYN, loc }, (value) => ({
|
|
6464
|
+
kind: "exprStmt", expr: { kind: "libCall", fn: "dyn.keySetComputed", args: [receiver, key, lowerer.coerceInto(access, value, DYN)], type: VOID, loc }, loc,
|
|
6465
|
+
}));
|
|
6466
|
+
}
|
|
6467
|
+
lowerer.unsupported("SC1045", expr, "increment/decrement of this member target");
|
|
6353
6468
|
}
|
|
6354
6469
|
const target = lowerer.resolveWritable(expr.operand);
|
|
6355
6470
|
if (!target) {
|
|
@@ -6429,6 +6544,7 @@ export function lowerCompoundValueToTarget(lowerer, expr, compound, target) {
|
|
|
6429
6544
|
const loc = locOf(expr);
|
|
6430
6545
|
const read = { kind: "varRef", localId: target.id, type: target.type, loc: locOf(expr.left) };
|
|
6431
6546
|
const rhs = lowerer.lowerExpr(expr.right);
|
|
6547
|
+
const numericRead = lowerOptionalNumber(lowerer, read, loc);
|
|
6432
6548
|
const numericRhs = lowerOptionalNumber(lowerer, rhs, loc);
|
|
6433
6549
|
if (target.type.kind === "jsval" || rhs.type.kind === "jsval") {
|
|
6434
6550
|
const JS_COMPOUND = { "+": "add", "-": "sub", "*": "mul", "/": "div", "%": "mod", "**": "pow" };
|
|
@@ -6445,8 +6561,8 @@ export function lowerCompoundValueToTarget(lowerer, expr, compound, target) {
|
|
|
6445
6561
|
if (compound === "+" && target.type.kind === "string") {
|
|
6446
6562
|
return { kind: "strConcat", left: read, right: lowerer.ensureString(rhs, expr.right), type: STRING, loc };
|
|
6447
6563
|
}
|
|
6448
|
-
if (
|
|
6449
|
-
return { kind: "bin", op: compound, left:
|
|
6564
|
+
if (numericRead.type.kind === "f64" && numericRhs.type.kind === "f64") {
|
|
6565
|
+
return lowerer.coerceInto(expr, { kind: "bin", op: compound, left: numericRead, right: numericRhs, type: F64, loc }, target.type);
|
|
6450
6566
|
}
|
|
6451
6567
|
if ((target.type.kind === "dyn" || rhs.type.kind === "dyn") &&
|
|
6452
6568
|
isJsSourceFile(expr.getSourceFile())) {
|
|
@@ -6466,7 +6582,13 @@ export function lowerBinary(lowerer, expr) {
|
|
|
6466
6582
|
if (cacheHas)
|
|
6467
6583
|
return cacheHas;
|
|
6468
6584
|
if (op === ts.SyntaxKind.EqualsToken || (op >= ts.SyntaxKind.FirstCompoundAssignment && op <= ts.SyntaxKind.LastCompoundAssignment)) {
|
|
6585
|
+
const urlWrite = lowerUrlAssignment(lowerer, expr);
|
|
6586
|
+
if (urlWrite)
|
|
6587
|
+
return urlWrite;
|
|
6469
6588
|
if (op === ts.SyntaxKind.EqualsToken) {
|
|
6589
|
+
const prototypeWrite = lowerClassPrototypeComputedAssignment(lowerer, expr);
|
|
6590
|
+
if (prototypeWrite)
|
|
6591
|
+
return prototypeWrite;
|
|
6470
6592
|
const callableWrite = lowerNativeFunctionAssignment(lowerer, expr);
|
|
6471
6593
|
if (callableWrite)
|
|
6472
6594
|
return callableWrite;
|
|
@@ -6731,8 +6853,14 @@ export function lowerBinary(lowerer, expr) {
|
|
|
6731
6853
|
}
|
|
6732
6854
|
const strictEquality = op === ts.SyntaxKind.EqualsEqualsEqualsToken ||
|
|
6733
6855
|
op === ts.SyntaxKind.ExclamationEqualsEqualsToken;
|
|
6734
|
-
|
|
6735
|
-
|
|
6856
|
+
let left = strictEquality ? lowerAbsenceProbe(lowerer, expr.left) ?? lowerer.lowerExpr(expr.left) : lowerer.lowerExpr(expr.left);
|
|
6857
|
+
let right = strictEquality ? lowerAbsenceProbe(lowerer, expr.right) ?? lowerer.lowerExpr(expr.right) : lowerer.lowerExpr(expr.right);
|
|
6858
|
+
if (strictEquality && (left.type.kind === "caught" || right.type.kind === "caught")) {
|
|
6859
|
+
if (left.type.kind === "caught")
|
|
6860
|
+
left = { kind: "caughtToDyn", value: left, type: DYN, loc: left.loc };
|
|
6861
|
+
if (right.type.kind === "caught")
|
|
6862
|
+
right = { kind: "caughtToDyn", value: right, type: DYN, loc: right.loc };
|
|
6863
|
+
}
|
|
6736
6864
|
if (left.type.kind === "dyn" || right.type.kind === "dyn") {
|
|
6737
6865
|
// The narrowing unit comparisons ARE answerable on unknown: `v ===
|
|
6738
6866
|
// undefined` / `v !== null` test the dyn node's kind directly, and
|
|
@@ -6760,7 +6888,7 @@ export function lowerBinary(lowerer, expr) {
|
|
|
6760
6888
|
const dynSide = left.type.kind === "dyn" ? left : right;
|
|
6761
6889
|
const scalarSide = dynSide === left ? right : left;
|
|
6762
6890
|
const reference = scalarSide.type;
|
|
6763
|
-
if ((
|
|
6891
|
+
if ((reference.kind === "object" || reference.kind === "record" || reference.kind === "array" ||
|
|
6764
6892
|
reference.kind === "bytes" || reference.kind === "func" || reference.kind === "classval" || reference.kind === "regex" || reference.kind === "url" ||
|
|
6765
6893
|
reference.kind === "bigint" || reference.kind === "symbol" || reference.kind === "map" || reference.kind === "set" || reference.kind === "union" || DYN_HANDLE_KINDS.has(reference.kind)) &&
|
|
6766
6894
|
lowerer.dynConvertible(reference)) {
|
|
@@ -7976,6 +8104,8 @@ function lowerDynTypeofTest(lowerer, expr, loc) {
|
|
|
7976
8104
|
for (const [a, b] of operandPairs(expr)) {
|
|
7977
8105
|
if (!ts.isTypeOfExpression(a))
|
|
7978
8106
|
continue;
|
|
8107
|
+
if (lowerer.isStdlibGlobal(a.expression, "fetch"))
|
|
8108
|
+
continue;
|
|
7979
8109
|
// Non-literal comparisons use the ordinary typeof string value,
|
|
7980
8110
|
// preserving both operands' evaluation order without a narrowing test.
|
|
7981
8111
|
if (!ts.isStringLiteral(b))
|
|
@@ -9338,11 +9468,10 @@ function matchAllRegexOf(lowerer, e) {
|
|
|
9338
9468
|
* member fence);
|
|
9339
9469
|
* - a nullable receiver (the JS `s.match(re).groups` idiom) throws
|
|
9340
9470
|
* Node's exact TypeError on the unit arms;
|
|
9341
|
-
* - every declared name is a key (nonparticipating groups hold
|
|
9342
|
-
*
|
|
9471
|
+
* - every declared name is a key (nonparticipating groups hold undefined,
|
|
9472
|
+
* exactly the slice elements they project);
|
|
9343
9473
|
* - ES2025 duplicate names (distinct alternatives) project the first
|
|
9344
|
-
* participating occurrence
|
|
9345
|
-
* participating-empty "" falls through to slots that are "" anyway;
|
|
9474
|
+
* participating occurrence, including a participating empty string;
|
|
9346
9475
|
* - key order is group declaration order (declaredOrder), Node's own.
|
|
9347
9476
|
* The record has no prototype — Node's groups object is null-prototype,
|
|
9348
9477
|
* observable only through util.inspect's "[Object: null prototype]"
|
|
@@ -9419,12 +9548,8 @@ function matchSliceUnionArms(lowerer, unionId) {
|
|
|
9419
9548
|
}
|
|
9420
9549
|
return { arrTag, units };
|
|
9421
9550
|
}
|
|
9422
|
-
/** The groups-record projection
|
|
9423
|
-
*
|
|
9424
|
-
* record with no declared fields — holding one OVERFLOW entry per
|
|
9425
|
-
* group name in declaration order, so every downstream consumer
|
|
9426
|
-
* (recordKeyGet reads, Object.keys, JSON, the `| undefined` union
|
|
9427
|
-
* wrap) meets exactly the type tsc reported. One lifted helper per
|
|
9551
|
+
/** The groups-record projection holds string | undefined values, including
|
|
9552
|
+
* an own overflow entry for every nonparticipating capture. One lifted helper per
|
|
9428
9553
|
* (index list, receiver representation) builds it; see
|
|
9429
9554
|
* lowerMatchGroupsRead for the semantics the body encodes. */
|
|
9430
9555
|
export function lowerGroupsProjection(lowerer, recv, groups, loc) {
|
|
@@ -9442,7 +9567,8 @@ export function lowerGroupsProjection(lowerer, recv, groups, loc) {
|
|
|
9442
9567
|
order.push(g.name);
|
|
9443
9568
|
}
|
|
9444
9569
|
}
|
|
9445
|
-
const
|
|
9570
|
+
const valueType = arrayValueType(lowerer, STRING);
|
|
9571
|
+
const shapeId = lowerer.shapes.intern([], false, valueType);
|
|
9446
9572
|
const recordT = { kind: "record", shapeId };
|
|
9447
9573
|
const recvKey = recv.type.kind === "union" ? recv.type.unionId : "arr";
|
|
9448
9574
|
const key = `regexgroups:${shapeId}:${groups.map((g) => `${g.name}=${g.index}`).join(",")}:${recvKey}`;
|
|
@@ -9484,7 +9610,7 @@ export function lowerGroupsProjection(lowerer, recv, groups, loc) {
|
|
|
9484
9610
|
body.push({ kind: "varDecl", localId: "arr.0", init: narrowed, loc });
|
|
9485
9611
|
mRef = { kind: "varRef", localId: "arr.0", type: arrayOf(STRING), loc };
|
|
9486
9612
|
}
|
|
9487
|
-
const elem = (index) => (
|
|
9613
|
+
const elem = (index) => arrayValueRead(lowerer, mRef, numLit(index, loc), STRING, loc);
|
|
9488
9614
|
const values = new Map();
|
|
9489
9615
|
order.forEach((name, i) => {
|
|
9490
9616
|
const idxs = indicesByName.get(name);
|
|
@@ -9492,16 +9618,16 @@ export function lowerGroupsProjection(lowerer, recv, groups, loc) {
|
|
|
9492
9618
|
values.set(name, elem(idxs[0]));
|
|
9493
9619
|
return;
|
|
9494
9620
|
}
|
|
9495
|
-
// Duplicates: the first
|
|
9496
|
-
//
|
|
9621
|
+
// Duplicates: the first participating occurrence. Empty strings
|
|
9622
|
+
// participate; undefined means this alternative did not match.
|
|
9497
9623
|
const id = `g${i}.0`;
|
|
9498
|
-
locals.push({ id, name: `g${i}`, type:
|
|
9624
|
+
locals.push({ id, name: `g${i}`, type: valueType, mutable: true });
|
|
9499
9625
|
body.push({ kind: "varDecl", localId: id, init: elem(idxs[0]), loc });
|
|
9500
|
-
const gRef = { kind: "varRef", localId: id, type:
|
|
9626
|
+
const gRef = { kind: "varRef", localId: id, type: valueType, loc };
|
|
9501
9627
|
for (const idx of idxs.slice(1)) {
|
|
9502
9628
|
body.push({
|
|
9503
9629
|
kind: "if",
|
|
9504
|
-
cond: { kind: "
|
|
9630
|
+
cond: { kind: "unionIsTag", unionId: valueType.kind === "union" ? valueType.unionId : "", tag: valueType.kind === "union" ? lowerer.armTag(valueType.unionId, UNDEFINED_T) : -1, negated: false, value: gRef, type: BOOL, loc },
|
|
9505
9631
|
then: [{ kind: "assign", localId: id, value: elem(idx), loc }],
|
|
9506
9632
|
else_: null,
|
|
9507
9633
|
loc,
|
|
@@ -9595,6 +9721,15 @@ export function lowerFieldRead(lowerer, expr) {
|
|
|
9595
9721
|
if (receiverIr?.kind === "record") {
|
|
9596
9722
|
const shape = lowerer.shapes.get(receiverIr.shapeId);
|
|
9597
9723
|
if (shape?.indexValue && !shape.fields.some((f) => f.name === expr.name.text)) {
|
|
9724
|
+
const actual = tryLowerExpression(lowerer, expr.expression);
|
|
9725
|
+
if (actual?.type.kind === "dyn")
|
|
9726
|
+
return { kind: "dynKeyGet", value: actual,
|
|
9727
|
+
key: { kind: "strLit", value: expr.name.text, type: STRING, loc: locOf(expr.name) }, type: DYN, loc: locOf(expr) };
|
|
9728
|
+
if (actual?.type.kind === "record") {
|
|
9729
|
+
const field = lowerer.shapes.get(actual.type.shapeId)?.fields.find((field) => field.name === expr.name.text);
|
|
9730
|
+
if (field)
|
|
9731
|
+
return { kind: "recordGet", obj: actual, shapeId: actual.type.shapeId, field: field.name, type: field.type, loc: locOf(expr) };
|
|
9732
|
+
}
|
|
9598
9733
|
lowerer.unsupported("SC1090", expr, `dot access to index-signature keys (spell it r["${expr.name.text}"] — brackets are the index-signature form)`);
|
|
9599
9734
|
}
|
|
9600
9735
|
}
|
|
@@ -9875,6 +10010,10 @@ function lowerUnionKeyedRead(lowerer, expr, unionId, value, key, literalField) {
|
|
|
9875
10010
|
* or accessor dispatch. Resolve the property from the represented class;
|
|
9876
10011
|
* the optional checker view must not turn its getter into a record read. */
|
|
9877
10012
|
function classFieldTarget(lowerer, receiverNode, receiverType, fieldName, saved) {
|
|
10013
|
+
const represented = saved ?? lowerer.lowerExpr(receiverNode);
|
|
10014
|
+
if (represented.type.kind === "dyn" && isJsSourceFile(receiverNode.getSourceFile()) && !fieldName.startsWith("#")) {
|
|
10015
|
+
return { container: "dynamic", obj: represented, field: fieldName, fieldType: DYN };
|
|
10016
|
+
}
|
|
9878
10017
|
const info = lowerer.classes.get(receiverType.className);
|
|
9879
10018
|
if (!info) {
|
|
9880
10019
|
// A receiver typed as a class whose collection deferred: the
|
|
@@ -9884,14 +10023,14 @@ function classFieldTarget(lowerer, receiverNode, receiverType, fieldName, saved)
|
|
|
9884
10023
|
}
|
|
9885
10024
|
const fieldType = info.fields.get(fieldName);
|
|
9886
10025
|
const lowerObjectReceiver = () => {
|
|
9887
|
-
let obj =
|
|
10026
|
+
let obj = represented;
|
|
9888
10027
|
if (obj.type.kind === "union") {
|
|
9889
10028
|
const helper = lowerer.narrowedArmHelper(obj.type.unionId, receiverType, locOf(receiverNode));
|
|
9890
10029
|
obj = helper
|
|
9891
10030
|
? { kind: "call", callee: helper, args: [obj], type: receiverType, loc: locOf(receiverNode) }
|
|
9892
10031
|
: lowerer.maybeNarrow(obj, receiverNode);
|
|
9893
10032
|
}
|
|
9894
|
-
return
|
|
10033
|
+
return lowerer.coerceInto(receiverNode, obj, receiverType);
|
|
9895
10034
|
};
|
|
9896
10035
|
if (fieldName === "cause" && receiverType.className !== "%DOMException") {
|
|
9897
10036
|
let root = info;
|
|
@@ -9903,6 +10042,11 @@ function classFieldTarget(lowerer, receiverNode, receiverType, fieldName, saved)
|
|
|
9903
10042
|
}
|
|
9904
10043
|
if (fieldType) {
|
|
9905
10044
|
const obj = lowerObjectReceiver();
|
|
10045
|
+
if (isJsSourceFile(receiverNode.getSourceFile()) && !fieldName.startsWith("#") &&
|
|
10046
|
+
[...lowerer.classes.values()].some((candidate) => lowerer.isSubclassOf(candidate.def.name, receiverType.className) &&
|
|
10047
|
+
(candidate.methods.has(`get:${fieldName}`) || candidate.methods.has(`set:${fieldName}`)))) {
|
|
10048
|
+
return { container: "dynamic", obj: lowerer.coerceToExpected(obj, DYN), field: fieldName, fieldType: DYN };
|
|
10049
|
+
}
|
|
9906
10050
|
return { container: "class", obj, className: receiverType.className, field: fieldName, fieldType };
|
|
9907
10051
|
}
|
|
9908
10052
|
// Accessor property: either half declared anywhere on the chain
|
|
@@ -9920,6 +10064,12 @@ function classFieldTarget(lowerer, receiverNode, receiverType, fieldName, saved)
|
|
|
9920
10064
|
fieldType: getF ? getF.sig.ret : setF.sig.params[0].type,
|
|
9921
10065
|
};
|
|
9922
10066
|
}
|
|
10067
|
+
if (info.decl && isJsSourceFile(info.decl.getSourceFile())) {
|
|
10068
|
+
const property = lowerer.checker.getPropertyOfType(lowerer.checker.getTypeAtLocation(receiverNode), fieldName);
|
|
10069
|
+
if (property && lowerer.checker.declarationsOf(property).some((declaration) => ts.isPropertyAccessExpression(declaration) || ts.isBinaryExpression(declaration) || ts.isElementAccessExpression(declaration))) {
|
|
10070
|
+
return { container: "dynamic", obj: lowerer.coerceToExpected(lowerObjectReceiver(), DYN), field: fieldName, fieldType: DYN };
|
|
10071
|
+
}
|
|
10072
|
+
}
|
|
9923
10073
|
return null;
|
|
9924
10074
|
}
|
|
9925
10075
|
/** A structural assertion can leave the value in its original class
|
|
@@ -9945,6 +10095,8 @@ function representedClassFieldTarget(lowerer, receiverNode, fieldName, value) {
|
|
|
9945
10095
|
* receivers) a declared accessor property. Returns the pieces of a
|
|
9946
10096
|
* fieldSet/recordSet/accessor-call (minus value/kind) or null. */
|
|
9947
10097
|
export function fieldTarget(lowerer, access) {
|
|
10098
|
+
if (lowerer.cjsLocalModuleBindingOf(access.expression))
|
|
10099
|
+
return null;
|
|
9948
10100
|
if (lowerer.chainBlocked(access))
|
|
9949
10101
|
return null;
|
|
9950
10102
|
if (access.name.text === "stackTraceLimit" && lowerer.isStdlibGlobal(access.expression, "Error")) {
|
|
@@ -10059,8 +10211,17 @@ export function fieldTarget(lowerer, access) {
|
|
|
10059
10211
|
return declaredArms.every((a) => ivArms.some((b) => typeEquals(a, b)));
|
|
10060
10212
|
};
|
|
10061
10213
|
if (!nameSym || nameSym.name === ts.InternalSymbolName.Index || canonicalized()) {
|
|
10062
|
-
|
|
10063
|
-
|
|
10214
|
+
let obj = lowerer.lowerExpr(access.expression);
|
|
10215
|
+
if (obj.type.kind === "union" && lowerer.armTag(obj.type.unionId, UNDEFINED_T) >= 0) {
|
|
10216
|
+
const present = lowerer.stripUndefinedArm(obj.type);
|
|
10217
|
+
obj = present.kind === "record" ? lowerer.runtimeOptionalPropertyReceiver(access.expression, obj, present, access.name.text) ?? obj : lowerer.maybeNarrow(obj, access.expression);
|
|
10218
|
+
}
|
|
10219
|
+
if (obj.type.kind !== "record")
|
|
10220
|
+
return null;
|
|
10221
|
+
const actualShape = lowerer.shapes.get(obj.type.shapeId);
|
|
10222
|
+
if (!actualShape?.indexValue)
|
|
10223
|
+
return null;
|
|
10224
|
+
return { container: "recordOvf", obj, shapeId: obj.type.shapeId, field: access.name.text, fieldType: actualShape.indexValue };
|
|
10064
10225
|
}
|
|
10065
10226
|
}
|
|
10066
10227
|
return null;
|
|
@@ -10158,6 +10319,11 @@ function symbolFieldTarget(lowerer, expr) {
|
|
|
10158
10319
|
* tsc-clean (the property types as the setter's param), but Node yields
|
|
10159
10320
|
* undefined, which these property types cannot represent. */
|
|
10160
10321
|
export function fieldGetExpr(lowerer, target, loc, blame) {
|
|
10322
|
+
if (target.container === "dynamic")
|
|
10323
|
+
return {
|
|
10324
|
+
kind: "dynKeyGet", value: target.obj,
|
|
10325
|
+
key: { kind: "strLit", value: target.field, type: STRING, loc }, type: DYN, loc,
|
|
10326
|
+
};
|
|
10161
10327
|
if (target.container === "class" && (target.field === "message" || target.field === "name") && (target.className === "%Error" || lowerer.isSubclassOf(target.className, "%Error")))
|
|
10162
10328
|
return errorPropertyRead(lowerer, target.obj, target.field);
|
|
10163
10329
|
if (target.container === "errorStackLimit") {
|
|
@@ -10267,6 +10433,11 @@ export function fieldGetExpr(lowerer, target, loc, blame) {
|
|
|
10267
10433
|
* call). A write to a getter-only property never gets here in a clean
|
|
10268
10434
|
* program (tsc's TS2540 is the fence); the rejection is the backstop. */
|
|
10269
10435
|
export function fieldSetStmt(lowerer, target, value, loc, blame) {
|
|
10436
|
+
if (target.container === "dynamic")
|
|
10437
|
+
return {
|
|
10438
|
+
kind: "exprStmt", expr: { kind: "libCall", fn: "dyn.keySet",
|
|
10439
|
+
args: [target.obj, { kind: "strLit", value: target.field, type: STRING, loc }, lowerer.coerceToExpected(value, DYN)], type: VOID, loc }, loc,
|
|
10440
|
+
};
|
|
10270
10441
|
if (target.container === "class" && (target.field === "message" || target.field === "name") && (target.className === "%Error" || lowerer.isSubclassOf(target.className, "%Error")))
|
|
10271
10442
|
return errorPropertyWrite(lowerer, target.obj, value, target.field);
|
|
10272
10443
|
if (target.container === "errorStackLimit") {
|
|
@@ -10434,7 +10605,7 @@ export function lowerPromiseAllTupleCall(lowerer, call, access) {
|
|
|
10434
10605
|
const loc = locOf(call);
|
|
10435
10606
|
const inner = first.inner;
|
|
10436
10607
|
const entryT = { kind: "promise", inner };
|
|
10437
|
-
const elems = argNode.elements.map((el) => lowerer.
|
|
10608
|
+
const elems = argNode.elements.map((el) => lowerer.lowerExprExpecting(el, entryT));
|
|
10438
10609
|
const entries = { kind: "arrayLit", elems, type: arrayOf(entryT), loc };
|
|
10439
10610
|
const type = inner.kind === "void"
|
|
10440
10611
|
? { kind: "promise", inner: VOID }
|
|
@@ -10466,7 +10637,10 @@ function lowerFieldCompoundValue(lowerer, access, op, rhsNode, loc) {
|
|
|
10466
10637
|
// NaN — SEMANTICS.md), combine, write back (dyn.keySet). The
|
|
10467
10638
|
// receiver and member read are saved before evaluating the RHS.
|
|
10468
10639
|
if (ts.isPropertyAccessExpression(access)) {
|
|
10469
|
-
|
|
10640
|
+
let probed = tryLowerExpression(lowerer, access.expression);
|
|
10641
|
+
const staticClass = probed?.type.kind === "classval" ? lowerer.classes.get(probed.type.className) : undefined;
|
|
10642
|
+
if (probed && staticClass && hasRuntimeStatics(staticClass))
|
|
10643
|
+
probed = lowerer.coerceToExpected(probed, DYN);
|
|
10470
10644
|
if (probed?.type.kind === "dyn") {
|
|
10471
10645
|
const receiver = save(probed, "%compoundReceiver");
|
|
10472
10646
|
const key = { kind: "strLit", value: access.name.text, type: STRING, loc: locOf(access.name) };
|
|
@@ -10475,6 +10649,14 @@ function lowerFieldCompoundValue(lowerer, access, op, rhsNode, loc) {
|
|
|
10475
10649
|
const rhs = save(rhsNode
|
|
10476
10650
|
? lowerer.lowerExpr(rhsNode)
|
|
10477
10651
|
: { kind: "numLit", value: 1, type: F64, loc }, "%compoundRhs");
|
|
10652
|
+
if (isJsSourceFile(access.getSourceFile()) && lowerer.dynConvertible(rhs.type)) {
|
|
10653
|
+
const numeric = ["-", "*", "/", "%", "**"].includes(op);
|
|
10654
|
+
const right = lowerer.coerceToExpected(rhs, DYN);
|
|
10655
|
+
const value = save({ kind: "libCall", fn: op === "+" ? "dyn.add" : numeric ? "dyn.arithmetic" : "dyn.bitwise",
|
|
10656
|
+
args: op === "+" ? [read, right] : [read, right, { kind: "strLit", value: op, type: STRING, loc }], type: DYN, loc }, "%compoundResult");
|
|
10657
|
+
body.push({ kind: "exprStmt", expr: { kind: "libCall", fn: "dyn.keySet", args: [receiver, key, value], type: VOID, loc }, loc });
|
|
10658
|
+
return { kind: "seqExpr", stmts: body, result: value, type: DYN, loc };
|
|
10659
|
+
}
|
|
10478
10660
|
const numericRhs = rhs.type.kind === "dyn"
|
|
10479
10661
|
? { kind: "dynCheck", value: rhs, type: F64, loc: rhs.loc }
|
|
10480
10662
|
: lowerOptionalNumber(lowerer, rhs, loc);
|
|
@@ -10512,35 +10694,12 @@ function lowerFieldCompoundValue(lowerer, access, op, rhsNode, loc) {
|
|
|
10512
10694
|
value = { kind: "bin", op, left: read, right: numericRhs, type: F64, loc };
|
|
10513
10695
|
}
|
|
10514
10696
|
else if (target.fieldType.kind === "dyn" &&
|
|
10515
|
-
isJsSourceFile(access.getSourceFile())
|
|
10516
|
-
|
|
10517
|
-
|
|
10518
|
-
|
|
10519
|
-
|
|
10520
|
-
|
|
10521
|
-
// ToNumber; SEMANTICS.md) and computes natively; the result boxes
|
|
10522
|
-
// back into the field's dyn slot. `+=` with a string RHS is the
|
|
10523
|
-
// string-context read: check to string, concat, box back.
|
|
10524
|
-
const checkNum = (e) => e.type.kind === "dyn" ? { kind: "dynCheck", value: e, type: F64, loc: e.loc } : e;
|
|
10525
|
-
if (op === "+" && rhs.type.kind === "string") {
|
|
10526
|
-
const concat = {
|
|
10527
|
-
kind: "strConcat",
|
|
10528
|
-
// String-context read: JS's String(unknown) over the field —
|
|
10529
|
-
// the JS-exact dyn walker, never a checked cast.
|
|
10530
|
-
left: { kind: "toString", operand: read, type: STRING, loc },
|
|
10531
|
-
right: rhs,
|
|
10532
|
-
type: STRING,
|
|
10533
|
-
loc,
|
|
10534
|
-
};
|
|
10535
|
-
value = { kind: "dynFrom", value: concat, type: DYN, loc };
|
|
10536
|
-
}
|
|
10537
|
-
else if (rhs.type.kind === "f64" || rhs.type.kind === "dyn") {
|
|
10538
|
-
const bin = { kind: "bin", op, left: checkNum(read), right: checkNum(rhs), type: F64, loc };
|
|
10539
|
-
value = { kind: "dynFrom", value: bin, type: DYN, loc };
|
|
10540
|
-
}
|
|
10541
|
-
else {
|
|
10542
|
-
lowerer.unsupported("SC1043", access);
|
|
10543
|
-
}
|
|
10697
|
+
isJsSourceFile(access.getSourceFile())) {
|
|
10698
|
+
const numeric = ["-", "*", "/", "%", "**"].includes(op);
|
|
10699
|
+
const left = lowerer.coerceToExpected(read, DYN);
|
|
10700
|
+
const right = lowerer.coerceToExpected(rhs, DYN);
|
|
10701
|
+
value = { kind: "libCall", fn: op === "+" ? "dyn.add" : numeric ? "dyn.arithmetic" : "dyn.bitwise",
|
|
10702
|
+
args: op === "+" ? [left, right] : [left, right, { kind: "strLit", value: op, type: STRING, loc }], type: DYN, loc };
|
|
10544
10703
|
}
|
|
10545
10704
|
else {
|
|
10546
10705
|
lowerer.unsupported("SC1043", access);
|