@scriptc/compiler 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ambient/scriptc-node-fallback.d.ts +84 -19
- package/dist/backend/cycle-analysis.js +1 -0
- package/dist/backend/cycle-analysis.js.map +1 -1
- package/dist/backend/llvm/classes.js +21 -5
- package/dist/backend/llvm/classes.js.map +1 -1
- package/dist/backend/llvm/dyn.d.ts +8 -0
- package/dist/backend/llvm/dyn.js +247 -108
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.d.ts +6 -3
- package/dist/backend/llvm/emitter.js +99 -25
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/emitter.test.js +9 -1
- package/dist/backend/llvm/emitter.test.js.map +1 -1
- package/dist/backend/llvm/expr-bytes.d.ts +1 -1
- package/dist/backend/llvm/expr-bytes.js +28 -17
- package/dist/backend/llvm/expr-bytes.js.map +1 -1
- package/dist/backend/llvm/expr-containers.js +5 -0
- package/dist/backend/llvm/expr-containers.js.map +1 -1
- package/dist/backend/llvm/expr-control.js +1 -1
- package/dist/backend/llvm/expr-control.js.map +1 -1
- package/dist/backend/llvm/expr-dynamic.js +47 -13
- package/dist/backend/llvm/expr-dynamic.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.js +11 -1
- package/dist/backend/llvm/expr-primitives.js.map +1 -1
- package/dist/backend/llvm/expr-records.js +11 -3
- package/dist/backend/llvm/expr-records.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.js +187 -18
- 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-process.js +23 -3
- package/dist/backend/llvm/lib-process.js.map +1 -1
- package/dist/backend/llvm/lib-shared.js +80 -3
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/llvm/shapes.js +8 -2
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/may-throw.js +4 -0
- package/dist/backend/may-throw.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 +3 -6
- package/dist/backend/native-toolchain.js +53 -23
- package/dist/backend/native-toolchain.js.map +1 -1
- package/dist/backend/native-toolchain.test.js +72 -0
- package/dist/backend/native-toolchain.test.js.map +1 -1
- package/dist/backend/runtime-abi.d.ts +2 -2
- package/dist/backend/runtime-abi.js +2 -2
- package/dist/backend/runtime-pack-native.js +4 -1
- package/dist/backend/runtime-pack-native.js.map +1 -1
- package/dist/backend/runtime-pack-targets.test.js +1 -1
- package/dist/backend/runtime-pack.test.js +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/backend/targets.js +10 -6
- package/dist/backend/targets.js.map +1 -1
- package/dist/backend/targets.test.js +7 -0
- package/dist/backend/targets.test.js.map +1 -1
- package/dist/compat/fetch-profile.js +34 -4
- package/dist/compat/fetch-profile.js.map +1 -1
- package/dist/coverage/surface-manifest.js +5 -3
- package/dist/coverage/surface-manifest.js.map +1 -1
- package/dist/diagnostics/diagnostic.js +2 -7
- package/dist/diagnostics/diagnostic.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/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 +4 -4
- package/dist/frontend/lowering/class-callbacks.js +29 -17
- package/dist/frontend/lowering/class-callbacks.js.map +1 -1
- package/dist/frontend/lowering/class-construction.d.ts +14 -0
- package/dist/frontend/lowering/class-construction.js +185 -0
- package/dist/frontend/lowering/class-construction.js.map +1 -0
- package/dist/frontend/lowering/class-descriptors.d.ts +2 -1
- package/dist/frontend/lowering/class-descriptors.js +58 -10
- package/dist/frontend/lowering/class-descriptors.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +36 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.js +965 -91
- package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js +66 -3
- 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 +15 -42
- package/dist/frontend/lowering/class-instance-constructor.js.map +1 -1
- package/dist/frontend/lowering/class-method-values.d.ts +20 -1
- package/dist/frontend/lowering/class-method-values.js +120 -24
- package/dist/frontend/lowering/class-method-values.js.map +1 -1
- package/dist/frontend/lowering/class-prototypes.d.ts +10 -3
- package/dist/frontend/lowering/class-prototypes.js +188 -21
- package/dist/frontend/lowering/class-prototypes.js.map +1 -1
- package/dist/frontend/lowering/class-runtime-statics.d.ts +8 -0
- package/dist/frontend/lowering/class-runtime-statics.js +84 -0
- package/dist/frontend/lowering/class-runtime-statics.js.map +1 -0
- package/dist/frontend/lowering/class-static-data.d.ts +1 -0
- package/dist/frontend/lowering/class-static-data.js +6 -4
- package/dist/frontend/lowering/class-static-data.js.map +1 -1
- package/dist/frontend/lowering/containers/bytes.js +66 -17
- package/dist/frontend/lowering/containers/bytes.js.map +1 -1
- package/dist/frontend/lowering/containers/string-and-regexp.js +24 -47
- 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/error-methods.d.ts +4 -1
- package/dist/frontend/lowering/error-methods.js +100 -1
- package/dist/frontend/lowering/error-methods.js.map +1 -1
- package/dist/frontend/lowering/expressions/native-proxy.js +3 -1
- package/dist/frontend/lowering/expressions/native-proxy.js.map +1 -1
- package/dist/frontend/lowering/expressions/nullish-assignment.js +19 -11
- package/dist/frontend/lowering/expressions/nullish-assignment.js.map +1 -1
- package/dist/frontend/lowering/expressions/object-literals.js +68 -7
- package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
- package/dist/frontend/lowering/expressions/optional-chains.d.ts +3 -4
- package/dist/frontend/lowering/expressions/optional-chains.js +72 -20
- package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
- package/dist/frontend/lowering/function-context.d.ts +11 -3
- package/dist/frontend/lowering/function-context.js +11 -5
- package/dist/frontend/lowering/function-context.js.map +1 -1
- package/dist/frontend/lowering/generator-dynamic-dispatch.d.ts +1 -0
- package/dist/frontend/lowering/generator-dynamic-dispatch.js +39 -1
- package/dist/frontend/lowering/generator-dynamic-dispatch.js.map +1 -1
- package/dist/frontend/lowering/lib-boundary.d.ts +2 -0
- package/dist/frontend/lowering/lib-boundary.js +54 -1
- package/dist/frontend/lowering/lib-boundary.js.map +1 -1
- package/dist/frontend/lowering/lower-builtin-values.d.ts +7 -1
- package/dist/frontend/lowering/lower-builtin-values.js +113 -3
- package/dist/frontend/lowering/lower-builtin-values.js.map +1 -1
- package/dist/frontend/lowering/lower-builtins.d.ts +10 -14
- package/dist/frontend/lowering/lower-builtins.js +443 -88
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +8 -5
- package/dist/frontend/lowering/lower-calls.js +717 -142
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +18 -13
- package/dist/frontend/lowering/lower-classes.js +1076 -188
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.d.ts +9 -0
- package/dist/frontend/lowering/lower-containers.js +172 -51
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-dgram.js +3 -2
- package/dist/frontend/lowering/lower-dgram.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +12 -8
- package/dist/frontend/lowering/lower-exprs.js +802 -232
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-generators.js +17 -2
- package/dist/frontend/lowering/lower-generators.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.js +15 -1
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-island.d.ts +2 -0
- package/dist/frontend/lowering/lower-island.js +36 -10
- 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 +380 -73
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.test.d.ts +1 -0
- package/dist/frontend/lowering/lower-modules.test.js +107 -0
- package/dist/frontend/lowering/lower-modules.test.js.map +1 -0
- package/dist/frontend/lowering/lower-stmts.d.ts +7 -3
- package/dist/frontend/lowering/lower-stmts.js +221 -47
- 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 +3 -1
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- 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 +53 -10
- package/dist/frontend/lowering/lowerer.js +390 -77
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/lowerer.test.js +187 -3
- 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 -0
- package/dist/frontend/lowering/surfaces.js +48 -19
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/lowering/text-decoder-encoding.d.ts +2 -0
- package/dist/frontend/lowering/text-decoder-encoding.js +8 -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/lowering/unregistered-class-types.test.js +3 -3
- package/dist/frontend/lowering/unregistered-class-types.test.js.map +1 -1
- package/dist/frontend/npm-static-prune.js +116 -34
- package/dist/frontend/npm-static-prune.js.map +1 -1
- package/dist/frontend/npm-static-prune.test.js +8 -0
- package/dist/frontend/npm-static-prune.test.js.map +1 -1
- package/dist/frontend/program.d.ts +1 -1
- package/dist/frontend/program.js +57 -26
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/program.test.js +18 -0
- package/dist/frontend/program.test.js.map +1 -1
- package/dist/frontend/ts7/ast.js +4 -3
- package/dist/frontend/ts7/ast.js.map +1 -1
- package/dist/frontend/ts7/semantic-json.js +5 -10
- package/dist/frontend/ts7/semantic-json.js.map +1 -1
- package/dist/frontend/type-mapper.d.ts +9 -1
- package/dist/frontend/type-mapper.js +169 -23
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/frontend/type-mapper.test.js +23 -0
- package/dist/frontend/type-mapper.test.js.map +1 -1
- package/dist/frontend/union-discriminants.d.ts +1 -1
- package/dist/frontend/union-discriminants.js +24 -9
- package/dist/frontend/union-discriminants.js.map +1 -1
- package/dist/index.js +16 -10
- package/dist/index.js.map +1 -1
- package/dist/ir/analysis.js +2 -0
- package/dist/ir/analysis.js.map +1 -1
- package/dist/ir/ir.d.ts +74 -41
- package/dist/ir/ir.js +167 -43
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/ir.test.js +35 -0
- package/dist/ir/ir.test.js.map +1 -1
- package/dist/ir/serialize.js +35 -3
- package/dist/ir/serialize.js.map +1 -1
- package/dist/ir/serialize.test.js +26 -1
- 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 +136 -16
- package/dist/ir/validate.js.map +1 -1
- package/dist/ir/validate.test.js +77 -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/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/sanitizer.js +3 -1
- package/dist/native/sanitizer.js.map +1 -1
- package/dist/native/toolchain.d.ts +1 -1
- package/dist/native/toolchain.js +26 -6
- package/dist/native/toolchain.js.map +1 -1
- package/dist/native/toolchain.test.js +53 -1
- package/dist/native/toolchain.test.js.map +1 -1
- package/package.json +20 -20
- package/surface-manifest.json +170 -93
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { everyStmtList, everyTypeChild } from "../../ir/traverse.js";
|
|
1
2
|
import { InternalCompilerError } from "../../errors.js";
|
|
2
3
|
/* Module-graph lowering: splitting each source file into its parts, the
|
|
3
4
|
* program-collection pass (signatures, classes, globals — reachability
|
|
@@ -16,16 +17,16 @@ import { BOOL, DYN, F64, JSVAL, RUNTIME_ERROR_CLASSES, STRING, VOID, arrayOf, ca
|
|
|
16
17
|
import { ENTRY_NAME, PoisonError, boundIdentifiersOf, dynFallbackType, dynUndefinedExpr, importCallHandleType, newFnCtx, staticImportNamespaceType, uncheckedOverloadHandleCall } from "./lowerer.js";
|
|
17
18
|
import { isNativeFfiRequire, builtinMemberRequireDecl, builtinNamespaceDestructureModuleOf, createRequireBindingDecl, createRequireNamespaceDecl, createRequireProgramModuleDecl, createRequireSpecOf, isPromisifyCall, registerBuiltinCallableAlias, stripTypeCasts } from "./lower-builtins.js";
|
|
18
19
|
import { bindingContextualGenericFnNodeOf, bindingGenericFnAliasInfoOf, bindingGenericFnInfoOf, bindingGenericFnNodeOf, bindingNeverReassigned, deadUnmappableBinding, funcTypeFromParamShapes, implicitLocalFnInfoOf, implicitLocalFnNodeOf, nullishGenericBindingUnitOf, registerOverloadedCallableAlias } from "./lower-calls.js";
|
|
19
|
-
import { hasJsTypeAnnotation, isVarDeclared, numericIteratorSourceOf, provenanceElidedConstDecl } from "./lower-stmts.js";
|
|
20
|
-
import {
|
|
20
|
+
import { jsBindingHasOpenWrites, hasJsTypeAnnotation, isVarDeclared, numericIteratorSourceOf, provenanceElidedConstDecl } from "./lower-stmts.js";
|
|
21
|
+
import { objectFactoryGlobalType } from "./object-factory-new.js";
|
|
21
22
|
import { streamClassAliasDecl } from "./lower-stream.js";
|
|
22
23
|
import { stdlibGlobalAliasDecl, stdlibGlobalAliasNameOf, stdlibGlobalNameOf } from "./surfaces.js";
|
|
23
24
|
import { isNativeBuiltinValueInitializer } from "./lower-builtin-values.js";
|
|
24
|
-
import { collectNamespaceStmt, nsPathPrefix, trapDeclRootOf } from "./lower-namespaces.js";
|
|
25
|
+
import { collectNamespaceStmt, nsMemberIdentOf, nsPathPrefix, trapDeclRootOf } from "./lower-namespaces.js";
|
|
25
26
|
import { collectExpandoMembers } from "./lower-expando.js";
|
|
26
27
|
import { recordTextCodecClass } from "../../ir/ir.js";
|
|
27
28
|
import { isUnitOnlyTsType, unitOnlyUnion } from "../type-mapper.js";
|
|
28
|
-
import { collectVirtualJsMethods, decoratorNodesOf, genericIfaceBindingKeepsClass, guaranteedDecorationThrow } from "./lower-classes.js";
|
|
29
|
+
import { collectInheritedJsFieldWrites, collectVirtualJsMethods, decoratorNodesOf, genericIfaceBindingKeepsClass, guaranteedDecorationThrow, storedClassValueType } from "./lower-classes.js";
|
|
29
30
|
import { isMixinFnBinding, mixinResultBindingClassOf } from "./lower-mixins.js";
|
|
30
31
|
import { cjsModuleRef, cjsModuleRegistryPrelude } from "./lower-node-module.js";
|
|
31
32
|
import { forkTargetPaths } from "../fork-target.js";
|
|
@@ -228,12 +229,42 @@ export function appendDynamicImportModules(program, order, onCycle) {
|
|
|
228
229
|
* signatures are cheap and calls resolve against them; only BODY lowering
|
|
229
230
|
* is reachability-gated. */
|
|
230
231
|
export function collectProgram(lowerer, parts) {
|
|
232
|
+
const computed = new Set();
|
|
233
|
+
for (const fp of parts)
|
|
234
|
+
for (const decl of fp.classDecls) {
|
|
235
|
+
const heritage = decl.heritageClauses?.find((clause) => clause.token === ts.SyntaxKind.ExtendsKeyword)?.types[0]?.expression;
|
|
236
|
+
if (heritage && ts.isCallExpression(heritage))
|
|
237
|
+
computed.add(decl);
|
|
238
|
+
}
|
|
239
|
+
// Descendants need the computed ancestor's completed layout before
|
|
240
|
+
// their own fields and inherited methods can be collected.
|
|
241
|
+
const computedSymbols = new Set([...computed].map((decl) => declSymbolOf(lowerer, decl)).filter((symbol) => symbol !== undefined));
|
|
242
|
+
let expanded = true;
|
|
243
|
+
while (expanded) {
|
|
244
|
+
expanded = false;
|
|
245
|
+
for (const fp of parts)
|
|
246
|
+
for (const decl of fp.classDecls) {
|
|
247
|
+
if (computed.has(decl))
|
|
248
|
+
continue;
|
|
249
|
+
const heritage = decl.heritageClauses?.find((clause) => clause.token === ts.SyntaxKind.ExtendsKeyword)?.types[0]?.expression;
|
|
250
|
+
const base = heritage && ts.isIdentifier(heritage) ? lowerer.resolveValueSymbol(heritage) : undefined;
|
|
251
|
+
if (!base || !computedSymbols.has(base))
|
|
252
|
+
continue;
|
|
253
|
+
computed.add(decl);
|
|
254
|
+
const symbol = declSymbolOf(lowerer, decl);
|
|
255
|
+
if (symbol)
|
|
256
|
+
computedSymbols.add(symbol);
|
|
257
|
+
expanded = true;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
231
260
|
lowerer.collecting = true;
|
|
232
261
|
try {
|
|
233
262
|
collectVirtualJsMethods(lowerer, parts.map((part) => part.sf));
|
|
263
|
+
collectInheritedJsFieldWrites(lowerer, parts.map((part) => part.sf));
|
|
234
264
|
for (const fp of parts)
|
|
235
265
|
for (const decl of fp.classDecls)
|
|
236
|
-
|
|
266
|
+
if (!computed.has(decl))
|
|
267
|
+
lowerer.collectClassShape(decl);
|
|
237
268
|
for (const fp of parts)
|
|
238
269
|
for (const decl of fp.fnDecls)
|
|
239
270
|
lowerer.collectSignature(decl);
|
|
@@ -263,6 +294,60 @@ export function collectProgram(lowerer, parts) {
|
|
|
263
294
|
lowerer.collectNpmImports(parts);
|
|
264
295
|
lowerer.collectJsonImports(parts);
|
|
265
296
|
}
|
|
297
|
+
for (const decl of computed) {
|
|
298
|
+
const symbol = declSymbolOf(lowerer, decl);
|
|
299
|
+
const wasCollecting = lowerer.collecting;
|
|
300
|
+
lowerer.collecting = true;
|
|
301
|
+
const previousSink = lowerer.diagSink;
|
|
302
|
+
const deferred = [];
|
|
303
|
+
lowerer.diagSink = deferred;
|
|
304
|
+
const expression = decl.heritageClauses.find((clause) => clause.token === ts.SyntaxKind.ExtendsKeyword).types[0].expression;
|
|
305
|
+
const context = newFnCtx(false, null, null, DYN);
|
|
306
|
+
lowerer.fnStack.push(context);
|
|
307
|
+
try {
|
|
308
|
+
let value = lowerer.lowerExpr(expression);
|
|
309
|
+
const known = value.type.kind === "dyn" ? storedClassValueType(lowerer, expression) : null;
|
|
310
|
+
if (known?.kind === "classval")
|
|
311
|
+
value = lowerer.coerceToExpected(value, known);
|
|
312
|
+
if (value.type.kind === "dyn" || value.type.kind === "func") {
|
|
313
|
+
const name = `%class.base.${lowerer.classNamer(decl)}`;
|
|
314
|
+
const loc = locOf(expression);
|
|
315
|
+
lowerer.liftedFns.push({ name, params: [], returnType: value.type, locals: context.locals,
|
|
316
|
+
body: [{ kind: "return", value, loc }], loc });
|
|
317
|
+
lowerer.computedCallableBases.set(decl, { kind: "call", callee: name, args: [], type: value.type, loc });
|
|
318
|
+
}
|
|
319
|
+
if (value.type.kind === "classval") {
|
|
320
|
+
const classInfo = lowerer.classes.get(value.type.className);
|
|
321
|
+
if (classInfo) {
|
|
322
|
+
const name = `%class.base.${lowerer.classNamer(decl)}`;
|
|
323
|
+
const loc = locOf(expression);
|
|
324
|
+
lowerer.liftedFns.push({ name, params: [], returnType: value.type, locals: context.locals,
|
|
325
|
+
body: [{ kind: "return", value, loc }], loc });
|
|
326
|
+
lowerer.computedClassBases.set(lowerer.classNamer(decl), { value: { kind: "call", callee: name, args: [], type: value.type, loc }, classInfo });
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
catch (error) {
|
|
331
|
+
if (!(error instanceof PoisonError))
|
|
332
|
+
throw error;
|
|
333
|
+
}
|
|
334
|
+
finally {
|
|
335
|
+
lowerer.fnStack.pop();
|
|
336
|
+
lowerer.diagSink = previousSink;
|
|
337
|
+
}
|
|
338
|
+
lowerer.diagSink = deferred;
|
|
339
|
+
try {
|
|
340
|
+
lowerer.collectClassShape(decl);
|
|
341
|
+
}
|
|
342
|
+
finally {
|
|
343
|
+
lowerer.diagSink = previousSink;
|
|
344
|
+
}
|
|
345
|
+
if (symbol && deferred.length) {
|
|
346
|
+
lowerer.deferredDiags.set(symbol, [...(lowerer.deferredDiags.get(symbol) ?? []), ...deferred]);
|
|
347
|
+
lowerer.deferredClassByName.set(lowerer.classNamer(decl), symbol);
|
|
348
|
+
}
|
|
349
|
+
lowerer.collecting = wasCollecting;
|
|
350
|
+
}
|
|
266
351
|
}
|
|
267
352
|
/** The npm-import chokepoint, run once per pass during collection (so
|
|
268
353
|
* bodies lowered in ANY pass resolve the bindings). In a static build
|
|
@@ -640,49 +725,172 @@ export function collectJsonImports(lowerer, parts) {
|
|
|
640
725
|
/** The classes, records, and unions the emitted module carries: exactly
|
|
641
726
|
* what the lowered functions and globals reference, closed transitively
|
|
642
727
|
* over record fields, union arms, class field types, base chains, and
|
|
643
|
-
*
|
|
644
|
-
* dropping an unused subclass must not turn its base into a standalone
|
|
645
|
-
* class at emit time). Registry entries interned while collecting
|
|
728
|
+
* constructible descendants and their base chains. Registry entries interned while collecting
|
|
646
729
|
* signatures nothing reaches stay out — an unreached type leaves no
|
|
647
730
|
* trace. A referenced class with no registration had its collection
|
|
648
731
|
* deferred: the reference flushes those diagnostics. Methods whose
|
|
649
732
|
* bodies were not lowered leave the def's method list, so vtable slots
|
|
650
733
|
* exist exactly for emitted overrides. */
|
|
651
734
|
export function moduleArtifacts(lowerer, functions) {
|
|
735
|
+
const valueInstanceOfRoots = new Set();
|
|
652
736
|
const classNames = new Set();
|
|
653
737
|
const shapeIds = new Set();
|
|
654
738
|
const unionIds = new Set();
|
|
655
739
|
const pendingClasses = [];
|
|
656
740
|
const pendingShapes = [];
|
|
657
741
|
const pendingUnions = [];
|
|
658
|
-
const
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
return;
|
|
742
|
+
const boxedChild = (type, seen = new Set()) => {
|
|
743
|
+
switch (type.kind) {
|
|
744
|
+
case "child": return true;
|
|
745
|
+
case "array":
|
|
746
|
+
case "set": return boxedChild(type.elem, seen);
|
|
747
|
+
case "promise": return boxedChild(type.inner, seen);
|
|
748
|
+
case "map": return boxedChild(type.key, seen) || boxedChild(type.value, seen);
|
|
749
|
+
case "func": return boxedChild(type.ret, seen);
|
|
750
|
+
case "record":
|
|
751
|
+
if (seen.has(type.shapeId))
|
|
752
|
+
return false;
|
|
753
|
+
seen.add(type.shapeId);
|
|
754
|
+
return lowerer.shapes.get(type.shapeId)?.fields.some((field) => boxedChild(field.type, seen)) ?? false;
|
|
755
|
+
case "union":
|
|
756
|
+
if (seen.has(type.unionId))
|
|
757
|
+
return false;
|
|
758
|
+
seen.add(type.unionId);
|
|
759
|
+
return lowerer.unions.get(type.unionId)?.arms.some((arm) => boxedChild(arm, seen)) ?? false;
|
|
760
|
+
default: return false;
|
|
663
761
|
}
|
|
664
|
-
|
|
762
|
+
};
|
|
763
|
+
const visitClass = (name) => {
|
|
764
|
+
if (classNames.has(name))
|
|
665
765
|
return;
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
766
|
+
classNames.add(name);
|
|
767
|
+
pendingClasses.push(name);
|
|
768
|
+
};
|
|
769
|
+
const visitShape = (id) => {
|
|
770
|
+
if (shapeIds.has(id))
|
|
771
|
+
return;
|
|
772
|
+
shapeIds.add(id);
|
|
773
|
+
pendingShapes.push(id);
|
|
774
|
+
};
|
|
775
|
+
const visitUnion = (id) => {
|
|
776
|
+
if (unionIds.has(id))
|
|
777
|
+
return;
|
|
778
|
+
unionIds.add(id);
|
|
779
|
+
pendingUnions.push(id);
|
|
780
|
+
};
|
|
781
|
+
const visitType = (type) => {
|
|
782
|
+
switch (type.kind) {
|
|
783
|
+
case "object":
|
|
784
|
+
case "classval":
|
|
785
|
+
visitClass(type.className);
|
|
786
|
+
break;
|
|
787
|
+
case "record":
|
|
788
|
+
visitShape(type.shapeId);
|
|
789
|
+
break;
|
|
790
|
+
case "union":
|
|
791
|
+
visitUnion(type.unionId);
|
|
792
|
+
break;
|
|
682
793
|
}
|
|
794
|
+
return everyTypeChild(type, visitType);
|
|
795
|
+
};
|
|
796
|
+
const visitor = {
|
|
797
|
+
expr: (node) => {
|
|
798
|
+
visitType(node.type);
|
|
799
|
+
switch (node.kind) {
|
|
800
|
+
case "fieldIncDec":
|
|
801
|
+
case "new":
|
|
802
|
+
case "classRef":
|
|
803
|
+
case "instanceOf":
|
|
804
|
+
case "virtualCall":
|
|
805
|
+
case "fieldGet":
|
|
806
|
+
case "caughtCheck":
|
|
807
|
+
visitClass(node.className);
|
|
808
|
+
break;
|
|
809
|
+
case "caughtTest":
|
|
810
|
+
if (node.className !== undefined)
|
|
811
|
+
visitClass(node.className);
|
|
812
|
+
break;
|
|
813
|
+
case "recordGet":
|
|
814
|
+
case "recordKeyGet":
|
|
815
|
+
case "recordOvfKeys":
|
|
816
|
+
case "recordOvfHas":
|
|
817
|
+
visitShape(node.shapeId);
|
|
818
|
+
break;
|
|
819
|
+
case "unionWrap":
|
|
820
|
+
case "unionFuncEq":
|
|
821
|
+
case "unionNarrow":
|
|
822
|
+
case "unionDisc":
|
|
823
|
+
case "unionKeyGet":
|
|
824
|
+
case "unionIsTag":
|
|
825
|
+
case "unionEq":
|
|
826
|
+
visitUnion(node.unionId);
|
|
827
|
+
break;
|
|
828
|
+
case "yieldExpr":
|
|
829
|
+
if (node.captureCompletion !== undefined)
|
|
830
|
+
visitType(node.captureCompletion.returnType);
|
|
831
|
+
break;
|
|
832
|
+
case "instanceOfValue":
|
|
833
|
+
for (const type of [node.value.type, node.classValue.type]) {
|
|
834
|
+
if (type.kind !== "object" && type.kind !== "classval")
|
|
835
|
+
continue;
|
|
836
|
+
let root = lowerer.classes.get(type.className);
|
|
837
|
+
if (!root)
|
|
838
|
+
continue;
|
|
839
|
+
while (root.base)
|
|
840
|
+
root = root.base;
|
|
841
|
+
valueInstanceOfRoots.add(root.def.name);
|
|
842
|
+
}
|
|
843
|
+
break;
|
|
844
|
+
case "dynFrom":
|
|
845
|
+
if (boxedChild(node.value.type)) {
|
|
846
|
+
// A generic child can expose native stdio without importing stream.
|
|
847
|
+
visitClass("%Readable");
|
|
848
|
+
visitClass("%Writable");
|
|
849
|
+
}
|
|
850
|
+
break;
|
|
851
|
+
default:
|
|
852
|
+
// A new node with a named artifact reference must join this switch.
|
|
853
|
+
node;
|
|
854
|
+
}
|
|
855
|
+
return true;
|
|
856
|
+
},
|
|
857
|
+
stmt: (node) => {
|
|
858
|
+
switch (node.kind) {
|
|
859
|
+
case "fieldSet":
|
|
860
|
+
visitClass(node.className);
|
|
861
|
+
break;
|
|
862
|
+
case "recordSet":
|
|
863
|
+
case "recordKeySet":
|
|
864
|
+
case "recordKeyDelete":
|
|
865
|
+
visitShape(node.shapeId);
|
|
866
|
+
break;
|
|
867
|
+
default:
|
|
868
|
+
node;
|
|
869
|
+
}
|
|
870
|
+
return true;
|
|
871
|
+
},
|
|
683
872
|
};
|
|
684
|
-
|
|
685
|
-
|
|
873
|
+
// Visit compiler-owned typed storage and executable trees directly, without
|
|
874
|
+
// creating dynamic snapshots of every node's properties and metadata.
|
|
875
|
+
for (const fn of functions) {
|
|
876
|
+
for (const param of fn.params)
|
|
877
|
+
visitType(param.type);
|
|
878
|
+
visitType(fn.returnType);
|
|
879
|
+
for (const local of fn.locals)
|
|
880
|
+
visitType(local.type);
|
|
881
|
+
for (const capture of fn.captures ?? [])
|
|
882
|
+
visitType(capture.type);
|
|
883
|
+
for (const capture of fn.classCaptures ?? [])
|
|
884
|
+
visitType(capture.type);
|
|
885
|
+
if (fn.generator !== undefined) {
|
|
886
|
+
visitType(fn.generator.yieldT);
|
|
887
|
+
visitType(fn.generator.nextT);
|
|
888
|
+
visitType(fn.generator.resultType);
|
|
889
|
+
}
|
|
890
|
+
everyStmtList(fn.body, visitor);
|
|
891
|
+
}
|
|
892
|
+
for (const global of lowerer.globalsList)
|
|
893
|
+
visitType(global.type);
|
|
686
894
|
// The builtin error classes ride EVERY module: the runtime's own throws
|
|
687
895
|
// (JSON/dynCheck/regex failures) mint instances of them whether or not
|
|
688
896
|
// user code mentions Error, and the uncaught printer tells Error
|
|
@@ -703,12 +911,19 @@ export function moduleArtifacts(lowerer, functions) {
|
|
|
703
911
|
// overflow-valued shape (`{ [key: string]: {script?: string} }`)
|
|
704
912
|
// references its value shape through indexValue alone.
|
|
705
913
|
const shape = lowerer.shapes.get(pendingShapes.pop());
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
914
|
+
if (shape !== undefined) {
|
|
915
|
+
for (const field of shape.fields)
|
|
916
|
+
visitType(field.type);
|
|
917
|
+
if (shape.indexValue !== undefined)
|
|
918
|
+
visitType(shape.indexValue);
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
while (pendingUnions.length > 0) {
|
|
922
|
+
const union = lowerer.unions.get(pendingUnions.pop());
|
|
923
|
+
if (union !== undefined)
|
|
924
|
+
for (const arm of union.arms)
|
|
925
|
+
visitType(arm);
|
|
709
926
|
}
|
|
710
|
-
while (pendingUnions.length > 0)
|
|
711
|
-
visit(lowerer.unions.get(pendingUnions.pop())?.arms);
|
|
712
927
|
while (pendingClasses.length > 0) {
|
|
713
928
|
const name = pendingClasses.pop();
|
|
714
929
|
const info = lowerer.classes.get(name);
|
|
@@ -718,15 +933,17 @@ export function moduleArtifacts(lowerer, functions) {
|
|
|
718
933
|
lowerer.flushDeferredClass(name);
|
|
719
934
|
continue;
|
|
720
935
|
}
|
|
721
|
-
|
|
936
|
+
for (const field of info.def.fields)
|
|
937
|
+
visitType(field.type);
|
|
722
938
|
if (info.base)
|
|
723
|
-
|
|
939
|
+
visitClass(info.base.def.name);
|
|
724
940
|
if (lowerer.inHierarchy(info)) {
|
|
725
941
|
let root = info;
|
|
726
942
|
while (root.base)
|
|
727
943
|
root = root.base;
|
|
728
944
|
const wholeTree = (c) => {
|
|
729
|
-
|
|
945
|
+
if (valueInstanceOfRoots.has(root.def.name) || lowerer.classCanBeConstructed(c))
|
|
946
|
+
visitClass(c.def.name);
|
|
730
947
|
for (const s of c.subclasses)
|
|
731
948
|
wholeTree(s);
|
|
732
949
|
};
|
|
@@ -803,7 +1020,7 @@ function cjsScalarLiteral(e) {
|
|
|
803
1020
|
* a checked-dynamic (or unit) value, so a DYN module global can hold it:
|
|
804
1021
|
* no initializer, a unit literal, or a checker-`any` call/member/
|
|
805
1022
|
* identifier read (any-typed operations lower through the checked-dynamic tree in JS).
|
|
806
|
-
* `new` expressions stay OUT even when checker-any (`new Anon.Sub()` over
|
|
1023
|
+
* User-class `new` expressions stay OUT even when checker-any (`new Anon.Sub()` over
|
|
807
1024
|
* an expando class member constructs a TYPED instance — corpus 2032), as
|
|
808
1025
|
* does everything else (object/array literals have their own rules;
|
|
809
1026
|
* typed-but-unmappable initializers keep the %init-local adoption). */
|
|
@@ -827,6 +1044,16 @@ function jsDynHoldableInitializer(lowerer, init) {
|
|
|
827
1044
|
e = e.expression;
|
|
828
1045
|
if (checkedGlobalReference(lowerer, e))
|
|
829
1046
|
return true;
|
|
1047
|
+
if (ts.isCallExpression(e) && ts.isPropertyAccessExpression(e.expression) &&
|
|
1048
|
+
["freeze", "seal", "preventExtensions"].includes(e.expression.name.text) &&
|
|
1049
|
+
lowerer.stdlibGlobalMember(e.expression, "Object") !== null && e.arguments[0] &&
|
|
1050
|
+
ts.isArrayLiteralExpression(e.arguments[0]))
|
|
1051
|
+
return true;
|
|
1052
|
+
// The built-in Array constructor can create an evolving array whose
|
|
1053
|
+
// inferred element type has no native mapping. Its checked reference
|
|
1054
|
+
// must remain shared with separately declared functions and aliases.
|
|
1055
|
+
if ((ts.isCallExpression(e) || ts.isNewExpression(e)) && lowerer.isStdlibGlobal(e.expression, "Array"))
|
|
1056
|
+
return true;
|
|
830
1057
|
// JavaScript process streams lower to native checked handles even when
|
|
831
1058
|
// their declared method overloads prevent a structural type mapping.
|
|
832
1059
|
// Register the shared slot before separately declared functions lower.
|
|
@@ -834,6 +1061,8 @@ function jsDynHoldableInitializer(lowerer, init) {
|
|
|
834
1061
|
const member = lowerer.stdlibGlobalMember(e, "process");
|
|
835
1062
|
if (member === "stdin" || member === "stdout" || member === "stderr")
|
|
836
1063
|
return true;
|
|
1064
|
+
if (e.name.text === "constructor" && lowerer.checker.getCallSignatures(lowerer.typeOf(e.expression)).length > 0)
|
|
1065
|
+
return true;
|
|
837
1066
|
}
|
|
838
1067
|
if (e.kind === ts.SyntaxKind.NullKeyword)
|
|
839
1068
|
return true;
|
|
@@ -851,6 +1080,11 @@ function jsDynHoldableInitializer(lowerer, init) {
|
|
|
851
1080
|
if ((ts.isPropertyAccessExpression(e) || ts.isElementAccessExpression(e)) &&
|
|
852
1081
|
ts.isIdentifier(e.expression) && lowerer.globalOf(e.expression)?.type.kind === "dyn")
|
|
853
1082
|
return true;
|
|
1083
|
+
if (ts.isPropertyAccessExpression(e)) {
|
|
1084
|
+
const member = nsMemberIdentOf(lowerer, e);
|
|
1085
|
+
if (member && (lowerer.globalOf(member)?.type.kind === "dyn" || lowerer.genericFnOf(member)?.implicitParams))
|
|
1086
|
+
return true;
|
|
1087
|
+
}
|
|
854
1088
|
// Optional callable reads (for example descriptor?.get) can be held in
|
|
855
1089
|
// the same checked slot as a callable. Their nullish arm must remain
|
|
856
1090
|
// observable by functions declared outside the module initializer.
|
|
@@ -862,6 +1096,8 @@ function jsDynHoldableInitializer(lowerer, init) {
|
|
|
862
1096
|
if (arms?.some(arm => arm.kind === "func") && arms.every(arm => isUnitType(arm) || (arm.kind === "func" && canBoxFuncIntoDyn(arm, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id)))))
|
|
863
1097
|
return true;
|
|
864
1098
|
}
|
|
1099
|
+
if ((ts.isFunctionExpression(e) || ts.isArrowFunction(e)) && !e.typeParameters?.length && isJsSourceFile(e.getSourceFile()))
|
|
1100
|
+
return true;
|
|
865
1101
|
if (ts.isIdentifier(e) || ts.isArrowFunction(e) || ts.isFunctionExpression(e)) {
|
|
866
1102
|
if (ts.isIdentifier(e)) {
|
|
867
1103
|
if (lowerer.globalOf(e)?.type.kind === "dyn")
|
|
@@ -976,6 +1212,10 @@ export function collectGlobals(lowerer, sf, topStmts) {
|
|
|
976
1212
|
let type = lowerer.mapTypeOf(tsType) ?? dynFallbackType(lowerer, stmt.expression, tsType);
|
|
977
1213
|
if (type === null)
|
|
978
1214
|
lowerer.badType(stmt.expression, tsType);
|
|
1215
|
+
// Inferred JavaScript factory exports keep their original value,
|
|
1216
|
+
// including callable objects decorated with Object.assign.
|
|
1217
|
+
if (isJsSourceFile(sf) && ts.isCallExpression(stmt.expression) && type.kind === "record" && lowerer.dynConvertible(type))
|
|
1218
|
+
type = DYN;
|
|
979
1219
|
// `export default undefined` — the unit-only union, like any
|
|
980
1220
|
// unit-only binding (`export default null` maps via mapType).
|
|
981
1221
|
if (type.kind === "void" && isUnitOnlyTsType(tsType)) {
|
|
@@ -1024,16 +1264,9 @@ export function collectGlobals(lowerer, sf, topStmts) {
|
|
|
1024
1264
|
const t = lowerer.mapTypeOf(strict) ?? dynFallbackType(lowerer, nameNode, strict);
|
|
1025
1265
|
if (!t || t.kind === "void")
|
|
1026
1266
|
lowerer.badType(typeNode, strict);
|
|
1027
|
-
//
|
|
1028
|
-
//
|
|
1029
|
-
//
|
|
1030
|
-
// owner, identity by construction (a record-typed second slot
|
|
1031
|
-
// would either copy or mismatch the dyn value — that mismatch
|
|
1032
|
-
// was an ICE; a second same-named global double-released at
|
|
1033
|
-
// teardown). The statement's assign degenerates to a harmless
|
|
1034
|
-
// self-assign. Mutable (`let`) sources keep the registration
|
|
1035
|
-
// below: Node copies the VALUE at this statement, and separate
|
|
1036
|
-
// storage is exactly that copy.
|
|
1267
|
+
// An immutable export source shares its live storage and native
|
|
1268
|
+
// callable ABI. Mutable sources need a separate snapshot slot:
|
|
1269
|
+
// later writes to the binding do not change the exported value.
|
|
1037
1270
|
{
|
|
1038
1271
|
let rhs = typeNode;
|
|
1039
1272
|
while (ts.isParenthesizedExpression(rhs))
|
|
@@ -1041,19 +1274,14 @@ export function collectGlobals(lowerer, sf, topStmts) {
|
|
|
1041
1274
|
if (ts.isIdentifier(rhs)) {
|
|
1042
1275
|
const vSym = lowerer.checker.getSymbolAtLocation(rhs);
|
|
1043
1276
|
const vG = vSym && lowerer.globalsBySymbol.get(vSym);
|
|
1044
|
-
if (vG
|
|
1277
|
+
if (vG) {
|
|
1045
1278
|
if (!vG.mutable) {
|
|
1046
1279
|
lowerer.globalsBySymbol.set(symbol, vG);
|
|
1047
1280
|
for (const d of lowerer.checker.declarationsOf(symbol))
|
|
1048
1281
|
lowerer.globalsByDeclNode.set(d, vG);
|
|
1049
1282
|
return;
|
|
1050
1283
|
}
|
|
1051
|
-
|
|
1052
|
-
// Node's copy-of-the-reference at this statement (later
|
|
1053
|
-
// reassignments of the let stay invisible through the
|
|
1054
|
-
// export). The id must not collide with the let's own
|
|
1055
|
-
// `%g.<tag><name>` global.
|
|
1056
|
-
const g = { id: `%g.${tag}%export.${name}`, name, type: DYN, mutable: false };
|
|
1284
|
+
const g = { id: `%g.${tag}%export.${name}`, name, type: vG.type, mutable: false };
|
|
1057
1285
|
lowerer.globalsBySymbol.set(symbol, g);
|
|
1058
1286
|
for (const d of lowerer.checker.declarationsOf(symbol))
|
|
1059
1287
|
lowerer.globalsByDeclNode.set(d, g);
|
|
@@ -1062,7 +1290,7 @@ export function collectGlobals(lowerer, sf, topStmts) {
|
|
|
1062
1290
|
}
|
|
1063
1291
|
}
|
|
1064
1292
|
}
|
|
1065
|
-
const g = { id: `%g.${tag}
|
|
1293
|
+
const g = { id: `%g.${tag}%export.${name}`, name, type: t, mutable: false };
|
|
1066
1294
|
lowerer.globalsBySymbol.set(symbol, g);
|
|
1067
1295
|
// Importer aliases resolve to a DISTINCT late-bound symbol with
|
|
1068
1296
|
// the same declaration — key the node too (globalOf's fallback).
|
|
@@ -1123,8 +1351,12 @@ export function collectGlobals(lowerer, sf, topStmts) {
|
|
|
1123
1351
|
const diagsBefore = lowerer.diags.length;
|
|
1124
1352
|
try {
|
|
1125
1353
|
const strict = lowerer.typeOf(rhs);
|
|
1126
|
-
|
|
1354
|
+
let t = lowerer.mapTypeOf(strict) ??
|
|
1127
1355
|
(fnValued || factoryValued ? dynFallbackType(lowerer, rhs, strict) : null);
|
|
1356
|
+
// A returned object remains the live CommonJS root; later
|
|
1357
|
+
// exports.member writes must update that same open object.
|
|
1358
|
+
if (factoryValued && t?.kind === "record" && lowerer.dynConvertible(t))
|
|
1359
|
+
t = DYN;
|
|
1128
1360
|
if (t && t.kind !== "void") {
|
|
1129
1361
|
const g = { id: `%g.${tag}exports`, name: "exports", type: t, mutable: false };
|
|
1130
1362
|
lowerer.globalsByDeclNode.set(cjs.expr, g);
|
|
@@ -1493,6 +1725,23 @@ export function collectGlobals(lowerer, sf, topStmts) {
|
|
|
1493
1725
|
for (const nameNode of boundIdentifiersOf(decl.name)) {
|
|
1494
1726
|
const diagsBefore = lowerer.diags.length;
|
|
1495
1727
|
try {
|
|
1728
|
+
// Checked JavaScript factories can expose inferred callables by
|
|
1729
|
+
// destructuring. Keep each exported binding in module storage so
|
|
1730
|
+
// separately lowered functions see the initialized value.
|
|
1731
|
+
if (isJsSourceFile(sf) && !ts.isIdentifier(decl.name) && decl.initializer &&
|
|
1732
|
+
!decl.type && !hasJsTypeAnnotation(decl) && !lowerer.mapTypeOf(lowerer.typeOf(nameNode))) {
|
|
1733
|
+
const symbol = lowerer.checker.getSymbolAtLocation(nameNode);
|
|
1734
|
+
if (symbol && !lowerer.globalsBySymbol.has(symbol)) {
|
|
1735
|
+
const g = { id: `%g.${tag}${nsPrefix}${nameNode.text}`, name: nameNode.text,
|
|
1736
|
+
type: DYN, mutable: isLet, source: bindingSource(nameNode),
|
|
1737
|
+
...(!isVarDeclared(decl) ? { tdz: true } : {}) };
|
|
1738
|
+
lowerer.globalsBySymbol.set(symbol, g);
|
|
1739
|
+
lowerer.globalsList.push(g);
|
|
1740
|
+
if (isVarDeclared(decl))
|
|
1741
|
+
noteVarGlobalEntryInit(lowerer, sf, g);
|
|
1742
|
+
}
|
|
1743
|
+
continue;
|
|
1744
|
+
}
|
|
1496
1745
|
// Builtin declarations do not always describe the concrete native
|
|
1497
1746
|
// callable ABI. Preserve checked-native values in shared storage;
|
|
1498
1747
|
// adapting the loader to (string) would replace its validation.
|
|
@@ -1543,7 +1792,8 @@ export function collectGlobals(lowerer, sf, topStmts) {
|
|
|
1543
1792
|
if (isJsSourceFile(sf) && ts.isIdentifier(decl.name) && nameNode === decl.name &&
|
|
1544
1793
|
decl.initializer && ts.isObjectLiteralExpression(decl.initializer) &&
|
|
1545
1794
|
decl.initializer.properties.some((p) => !ts.isSpreadAssignment(p) &&
|
|
1546
|
-
(ts.isMethodDeclaration(p) || ts.isAccessor(p) || ts.isComputedPropertyName(p.name)
|
|
1795
|
+
(ts.isMethodDeclaration(p) || ts.isAccessor(p) || ts.isComputedPropertyName(p.name) ||
|
|
1796
|
+
ts.isShorthandPropertyAssignment(p) && lowerer.checker.getCallSignatures(lowerer.typeOf(p.name)).length > 0))) {
|
|
1547
1797
|
const symbol = lowerer.checker.getSymbolAtLocation(nameNode);
|
|
1548
1798
|
if (symbol && !lowerer.globalsBySymbol.has(symbol)) {
|
|
1549
1799
|
const g = { id: `%g.${tag}${nsPrefix}${nameNode.text}`, name: nameNode.text, type: DYN, mutable: isLet, source: bindingSource(nameNode) };
|
|
@@ -1649,9 +1899,16 @@ export function collectGlobals(lowerer, sf, topStmts) {
|
|
|
1649
1899
|
if (isJsSourceFile(sf) && !lowerer.mapTypeOf(lowerer.typeOf(nameNode)) &&
|
|
1650
1900
|
ts.isIdentifier(decl.name) && nameNode === decl.name && decl.initializer &&
|
|
1651
1901
|
jsDynHoldableInitializer(lowerer, decl.initializer)) {
|
|
1652
|
-
const
|
|
1902
|
+
const initializer = decl.initializer;
|
|
1903
|
+
const member = ts.isPropertyAccessExpression(initializer) ? nsMemberIdentOf(lowerer, initializer) : null;
|
|
1904
|
+
const generic = member && lowerer.genericFnOf(member);
|
|
1905
|
+
const fallback = (ts.isArrowFunction(initializer) || ts.isFunctionExpression(initializer)) && !initializer.typeParameters?.length
|
|
1906
|
+
? lowerer.lambdaSignature(initializer).funcType
|
|
1907
|
+
: member && lowerer.globalOf(member)?.type.kind === "dyn" ? DYN
|
|
1908
|
+
: member && generic?.implicitParams ? lowerer.lowerGenericFnValue(member, generic).type
|
|
1909
|
+
: dynFallbackType(lowerer, nameNode, lowerer.typeOf(nameNode));
|
|
1653
1910
|
const symbol = lowerer.checker.getSymbolAtLocation(nameNode);
|
|
1654
|
-
if (symbol && fallback && (fallback.kind === "func" || fallback.kind === "union") && lowerer.dynConvertible(fallback)) {
|
|
1911
|
+
if (symbol && fallback && (fallback.kind === "dyn" || fallback.kind === "func" || fallback.kind === "union") && lowerer.dynConvertible(fallback)) {
|
|
1655
1912
|
if (!lowerer.globalsBySymbol.has(symbol)) {
|
|
1656
1913
|
const g = {
|
|
1657
1914
|
id: `%g.${tag}${nsPrefix}${nameNode.text}`, name: nameNode.text,
|
|
@@ -1675,9 +1932,7 @@ export function collectGlobals(lowerer, sf, topStmts) {
|
|
|
1675
1932
|
// their own per-site runtime fences.
|
|
1676
1933
|
const factoryType = !isLet && isJsSourceFile(sf) && !decl.type && !hasJsTypeAnnotation(decl) &&
|
|
1677
1934
|
ts.isIdentifier(decl.name) && nameNode === decl.name && decl.initializer && ts.isNewExpression(decl.initializer)
|
|
1678
|
-
?
|
|
1679
|
-
if (!factoryType && isJsSourceFile(sf) && !lowerer.mapTypeOf(lowerer.typeOf(nameNode)))
|
|
1680
|
-
continue;
|
|
1935
|
+
? objectFactoryGlobalType(lowerer, decl.initializer) ?? undefined : undefined;
|
|
1681
1936
|
// `var p1 = import("./m")` at file scope: the global holds the
|
|
1682
1937
|
// island promise/handle — the import expression's only
|
|
1683
1938
|
// production — whatever the checker's namespace type mapped to
|
|
@@ -1691,12 +1946,53 @@ export function collectGlobals(lowerer, sf, topStmts) {
|
|
|
1691
1946
|
// exactly the local rule (uncheckedOverloadHandleCall).
|
|
1692
1947
|
(uncheckedOverloadHandleCall(lowerer, decl.initializer) ? JSVAL : null) : null)
|
|
1693
1948
|
: null;
|
|
1694
|
-
|
|
1949
|
+
// JavaScript factory results with unmappable annotations still
|
|
1950
|
+
// need shared storage. Unannotated callable unions also use a
|
|
1951
|
+
// checked slot; mappable authored annotations keep their layout.
|
|
1952
|
+
const unannotatedCall = !decl.type && !hasJsTypeAnnotation(decl);
|
|
1953
|
+
const callSignature = (isJsSourceFile(sf) || unannotatedCall) && decl.initializer && ts.isCallExpression(decl.initializer)
|
|
1954
|
+
? lowerer.checker.getResolvedSignature(decl.initializer) : undefined;
|
|
1955
|
+
const callDeclaration = callSignature && lowerer.checker.signatureDeclaration(callSignature);
|
|
1956
|
+
const callType = callDeclaration && isJsSourceFile(callDeclaration.getSourceFile())
|
|
1957
|
+
? lowerer.mapTypeOf(lowerer.typeOf(nameNode)) : null;
|
|
1958
|
+
const inferredJsCall = callDeclaration && isJsSourceFile(callDeclaration.getSourceFile()) &&
|
|
1959
|
+
(!callType || unannotatedCall && callType.kind === "union" && lowerer.unions.get(callType.unionId)?.arms.some((arm) => arm.kind === "func"));
|
|
1960
|
+
if (!factoryType && !inferredJsCall && isJsSourceFile(sf) && !lowerer.mapTypeOf(lowerer.typeOf(nameNode)))
|
|
1961
|
+
continue;
|
|
1962
|
+
let type = handleT ?? factoryType ?? (inferredJsCall ? DYN : lowerer.irTypeOf(nameNode));
|
|
1963
|
+
if (isJsSourceFile(sf) && !decl.type && !hasJsTypeAnnotation(decl) && decl.initializer &&
|
|
1964
|
+
(ts.isArrowFunction(decl.initializer) || ts.isFunctionExpression(decl.initializer)) &&
|
|
1965
|
+
!decl.initializer.typeParameters?.length) {
|
|
1966
|
+
type = lowerer.lambdaSignature(decl.initializer).funcType;
|
|
1967
|
+
}
|
|
1968
|
+
// Namespace aliases of inferred helpers carry the helper's
|
|
1969
|
+
// settled callable, whose return can differ from checker inference.
|
|
1970
|
+
// Keep a shared checked slot before any consumer specializes it.
|
|
1971
|
+
if (isJsSourceFile(sf) && !decl.type && !hasJsTypeAnnotation(decl) && type.kind === "func" &&
|
|
1972
|
+
decl.initializer && ts.isPropertyAccessExpression(decl.initializer)) {
|
|
1973
|
+
const member = nsMemberIdentOf(lowerer, decl.initializer);
|
|
1974
|
+
if (member && lowerer.genericFnOf(member)?.implicitParams)
|
|
1975
|
+
type = DYN;
|
|
1976
|
+
else if (member) {
|
|
1977
|
+
const source = lowerer.globalOf(member);
|
|
1978
|
+
if (source?.type.kind === "func")
|
|
1979
|
+
type = source.type;
|
|
1980
|
+
}
|
|
1981
|
+
}
|
|
1982
|
+
if (isJsSourceFile(sf) && !decl.type && !hasJsTypeAnnotation(decl) &&
|
|
1983
|
+
decl.initializer && ts.isCallExpression(decl.initializer) && type.kind === "union") {
|
|
1984
|
+
const arms = lowerer.unions.get(type.unionId)?.arms;
|
|
1985
|
+
if (arms?.some((arm) => arm.kind === "record") && arms.every((arm) => isUnitType(arm) || arm.kind === "record"))
|
|
1986
|
+
type = DYN;
|
|
1987
|
+
}
|
|
1988
|
+
if (isJsSourceFile(sf) && !decl.type && !hasJsTypeAnnotation(decl) && decl.initializer &&
|
|
1989
|
+
ts.isNewExpression(decl.initializer) && lowerer.mapTypeOf(lowerer.typeOf(decl.initializer.expression))?.kind === "dyn" &&
|
|
1990
|
+
!(ts.isIdentifier(decl.initializer.expression) && lowerer.isStdlibSymbol(lowerer.checker.getSymbolAtLocation(decl.initializer.expression))))
|
|
1991
|
+
type = DYN;
|
|
1695
1992
|
// Calls through checked function values retain their object
|
|
1696
1993
|
// identity, including symbol keys absent from inferred records.
|
|
1697
1994
|
if (isJsSourceFile(sf) && !decl.type && !hasJsTypeAnnotation(decl) && type.kind === "record" &&
|
|
1698
|
-
decl.initializer && ts.isCallExpression(decl.initializer) &&
|
|
1699
|
-
ts.isIdentifier(decl.initializer.expression) && lowerer.globalOf(decl.initializer.expression)?.type.kind === "dyn") {
|
|
1995
|
+
decl.initializer && ts.isCallExpression(decl.initializer) && lowerer.dynConvertible(type)) {
|
|
1700
1996
|
type = DYN;
|
|
1701
1997
|
}
|
|
1702
1998
|
if (isJsSourceFile(sf) && !decl.type && !hasJsTypeAnnotation(decl) && type.kind === "record" &&
|
|
@@ -1711,11 +2007,18 @@ export function collectGlobals(lowerer, sf, topStmts) {
|
|
|
1711
2007
|
// a fixed-signature adapter to reconstruct its hidden rest ABI.
|
|
1712
2008
|
if (!decl.type && !hasJsTypeAnnotation(decl) && type.kind === "func" && type.rest === true && type.restAbi === undefined)
|
|
1713
2009
|
type = DYN;
|
|
2010
|
+
if (isJsSourceFile(sf) && isLet && !decl.type && !hasJsTypeAnnotation(decl) &&
|
|
2011
|
+
(type.kind === "object" || jsBindingHasOpenWrites(lowerer, decl)))
|
|
2012
|
+
type = DYN;
|
|
1714
2013
|
// JavaScript call results may retain a checked array supplied by
|
|
1715
2014
|
// the caller. A typed global here would copy it on extraction.
|
|
1716
2015
|
if (isJsSourceFile(sf) && !decl.type && !hasJsTypeAnnotation(decl) && type.kind === "array" &&
|
|
1717
2016
|
decl.initializer && ts.isCallExpression(decl.initializer))
|
|
1718
2017
|
type = DYN;
|
|
2018
|
+
if (!lowerer.dynamic && isJsSourceFile(sf) && !decl.type && !hasJsTypeAnnotation(decl) &&
|
|
2019
|
+
decl.initializer && ts.isNewExpression(decl.initializer) && lowerer.isStdlibGlobal(decl.initializer.expression, "Array") &&
|
|
2020
|
+
(type.kind !== "array" || type.elem.kind === "dyn"))
|
|
2021
|
+
type = DYN;
|
|
1719
2022
|
// Unannotated JavaScript aliases retain an existing native
|
|
1720
2023
|
// checked object instead of copying it into an inferred record.
|
|
1721
2024
|
if (isJsSourceFile(sf) && !decl.type && !hasJsTypeAnnotation(decl) &&
|
|
@@ -1793,8 +2096,7 @@ export function collectGlobals(lowerer, sf, topStmts) {
|
|
|
1793
2096
|
// adapter would re-copy at the assignment.
|
|
1794
2097
|
if (isJsSourceFile(sf) &&
|
|
1795
2098
|
type.kind === "func" &&
|
|
1796
|
-
type.ret.kind === "record" &&
|
|
1797
|
-
lowerer.dynConvertible(type.ret) &&
|
|
2099
|
+
(type.ret.kind === "date" || type.ret.kind === "record" && lowerer.dynConvertible(type.ret)) &&
|
|
1798
2100
|
decl.initializer !== undefined &&
|
|
1799
2101
|
(ts.isFunctionExpression(decl.initializer) || ts.isArrowFunction(decl.initializer)) &&
|
|
1800
2102
|
decl.initializer.type === undefined &&
|
|
@@ -1811,6 +2113,10 @@ export function collectGlobals(lowerer, sf, topStmts) {
|
|
|
1811
2113
|
type = DYN;
|
|
1812
2114
|
}
|
|
1813
2115
|
// Module vars hold real undefined until their declaration runs.
|
|
2116
|
+
// Unannotated JS function values need that state too: callers
|
|
2117
|
+
// before the initializer must see undefined and a TypeError.
|
|
2118
|
+
if (isJsSourceFile(sf) && isVarDeclared(decl) && type.kind === "func" && lowerer.dynConvertible(type))
|
|
2119
|
+
type = DYN;
|
|
1814
2120
|
// Codec records keep that state in the ordinary optional union;
|
|
1815
2121
|
// lexical codec declarations retain their separate TDZ guard.
|
|
1816
2122
|
const codec = type.kind === "record" && recordTextCodecClass(lowerer.shapes.get(type.shapeId)) !== null;
|
|
@@ -2214,7 +2520,7 @@ export function lowerFileInit(lowerer, sf, stmts, name) {
|
|
|
2214
2520
|
// SITE's position instead (below) — their inner class node may
|
|
2215
2521
|
// even live in another file.
|
|
2216
2522
|
c.decl && ts.isClassDeclaration(c.decl) && !c.mixinInstance && c.decl.getSourceFile() === sf &&
|
|
2217
|
-
(c.callableBase !== undefined || c.staticFields.length > 0 || (c.staticBlocks?.length ?? 0) > 0 || c.classDecorators !== undefined))
|
|
2523
|
+
(c.callableBase !== undefined || c.def.baseValueGlobal !== undefined || c.runtimeStatics !== undefined || c.staticFields.length > 0 || (c.staticBlocks?.length ?? 0) > 0 || c.classDecorators !== undefined))
|
|
2218
2524
|
.map((c) => ({ pos: c.decl.getStart(), info: c }));
|
|
2219
2525
|
// Statics-bearing MIXIN instantiations whose call evaluates in THIS
|
|
2220
2526
|
// file: their declaration-time code runs when the call does — the
|
|
@@ -2240,7 +2546,8 @@ export function lowerFileInit(lowerer, sf, stmts, name) {
|
|
|
2240
2546
|
body.push(...lowerer.lowerStaticFieldInits(statics[at].info));
|
|
2241
2547
|
at++;
|
|
2242
2548
|
}
|
|
2243
|
-
const
|
|
2549
|
+
const deferred = lowerer.deferredModuleInitializers?.defer(lowerer, stmt);
|
|
2550
|
+
const stmtIr = deferred ? [deferred] : lowerer.lowerStmts([stmt]);
|
|
2244
2551
|
// Class EXPRESSIONS inside this statement queued their static
|
|
2245
2552
|
// inits while it lowered: they land immediately before it — JS's
|
|
2246
2553
|
// order for the supported whole-initializer positions.
|