@scriptc/compiler 0.2.0 → 0.2.1
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 +25 -15
- 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 +5 -0
- package/dist/backend/llvm/dyn.js +166 -99
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.d.ts +2 -2
- package/dist/backend/llvm/emitter.js +79 -20
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/expr-bytes.d.ts +1 -1
- package/dist/backend/llvm/expr-bytes.js +28 -17
- package/dist/backend/llvm/expr-bytes.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 +18 -9
- 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 +125 -17
- package/dist/backend/llvm/expr-stream-bridges.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 +45 -2
- 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/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/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/diagnostics/diagnostic.js +2 -7
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/frontend/lowering/class-callbacks.d.ts +3 -3
- package/dist/frontend/lowering/class-callbacks.js +26 -15
- package/dist/frontend/lowering/class-callbacks.js.map +1 -1
- package/dist/frontend/lowering/class-construction.d.ts +12 -0
- package/dist/frontend/lowering/class-construction.js +156 -0
- package/dist/frontend/lowering/class-construction.js.map +1 -0
- package/dist/frontend/lowering/class-descriptors.d.ts +1 -0
- package/dist/frontend/lowering/class-descriptors.js +46 -5
- package/dist/frontend/lowering/class-descriptors.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +11 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.js +403 -48
- package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js +2 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js.map +1 -1
- package/dist/frontend/lowering/class-instance-constructor.js +4 -1
- package/dist/frontend/lowering/class-instance-constructor.js.map +1 -1
- package/dist/frontend/lowering/class-method-values.d.ts +4 -1
- package/dist/frontend/lowering/class-method-values.js +72 -7
- package/dist/frontend/lowering/class-method-values.js.map +1 -1
- package/dist/frontend/lowering/class-prototypes.d.ts +5 -2
- package/dist/frontend/lowering/class-prototypes.js +121 -13
- 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 +66 -0
- package/dist/frontend/lowering/class-runtime-statics.js.map +1 -0
- package/dist/frontend/lowering/class-static-data.js +2 -2
- package/dist/frontend/lowering/class-static-data.js.map +1 -1
- package/dist/frontend/lowering/containers/bytes.js +49 -13
- package/dist/frontend/lowering/containers/bytes.js.map +1 -1
- package/dist/frontend/lowering/containers/string-and-regexp.js +19 -47
- package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
- 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 +38 -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 +69 -17
- 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 +6 -5
- package/dist/frontend/lowering/lower-builtins.js +156 -41
- 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 +448 -83
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +13 -13
- package/dist/frontend/lowering/lower-classes.js +650 -176
- 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 +135 -36
- 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 +2 -2
- package/dist/frontend/lowering/lower-exprs.js +531 -126
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-generators.js +12 -1
- package/dist/frontend/lowering/lower-generators.js.map +1 -1
- package/dist/frontend/lowering/lower-island.d.ts +2 -0
- package/dist/frontend/lowering/lower-island.js +32 -10
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.js +220 -17
- 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 +39 -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 +135 -26
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.js +1 -1
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +27 -1
- package/dist/frontend/lowering/lowerer.js +172 -50
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/lowerer.test.js +149 -3
- package/dist/frontend/lowering/lowerer.test.js.map +1 -1
- package/dist/frontend/lowering/surfaces.d.ts +2 -0
- package/dist/frontend/lowering/surfaces.js +25 -8
- 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 +5 -0
- package/dist/frontend/lowering/text-decoder-encoding.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 +53 -24
- 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 +90 -13
- 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 +2 -2
- package/dist/frontend/union-discriminants.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 +52 -33
- package/dist/ir/ir.js +142 -42
- 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 +15 -3
- package/dist/ir/serialize.js.map +1 -1
- package/dist/ir/serialize.test.js +5 -1
- package/dist/ir/serialize.test.js.map +1 -1
- package/dist/ir/validate.js +80 -11
- package/dist/ir/validate.js.map +1 -1
- package/dist/ir/validate.test.js +61 -1
- package/dist/ir/validate.test.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 +56 -81
|
@@ -16,16 +16,16 @@ import { BOOL, DYN, F64, JSVAL, RUNTIME_ERROR_CLASSES, STRING, VOID, arrayOf, ca
|
|
|
16
16
|
import { ENTRY_NAME, PoisonError, boundIdentifiersOf, dynFallbackType, dynUndefinedExpr, importCallHandleType, newFnCtx, staticImportNamespaceType, uncheckedOverloadHandleCall } from "./lowerer.js";
|
|
17
17
|
import { isNativeFfiRequire, builtinMemberRequireDecl, builtinNamespaceDestructureModuleOf, createRequireBindingDecl, createRequireNamespaceDecl, createRequireProgramModuleDecl, createRequireSpecOf, isPromisifyCall, registerBuiltinCallableAlias, stripTypeCasts } from "./lower-builtins.js";
|
|
18
18
|
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";
|
|
19
|
+
import { jsBindingHasOpenWrites, hasJsTypeAnnotation, isVarDeclared, numericIteratorSourceOf, provenanceElidedConstDecl } from "./lower-stmts.js";
|
|
20
20
|
import { objectFactorySignature } from "./object-factory-new.js";
|
|
21
21
|
import { streamClassAliasDecl } from "./lower-stream.js";
|
|
22
22
|
import { stdlibGlobalAliasDecl, stdlibGlobalAliasNameOf, stdlibGlobalNameOf } from "./surfaces.js";
|
|
23
23
|
import { isNativeBuiltinValueInitializer } from "./lower-builtin-values.js";
|
|
24
|
-
import { collectNamespaceStmt, nsPathPrefix, trapDeclRootOf } from "./lower-namespaces.js";
|
|
24
|
+
import { collectNamespaceStmt, nsMemberIdentOf, nsPathPrefix, trapDeclRootOf } from "./lower-namespaces.js";
|
|
25
25
|
import { collectExpandoMembers } from "./lower-expando.js";
|
|
26
26
|
import { recordTextCodecClass } from "../../ir/ir.js";
|
|
27
27
|
import { isUnitOnlyTsType, unitOnlyUnion } from "../type-mapper.js";
|
|
28
|
-
import { collectVirtualJsMethods, decoratorNodesOf, genericIfaceBindingKeepsClass, guaranteedDecorationThrow } from "./lower-classes.js";
|
|
28
|
+
import { collectVirtualJsMethods, decoratorNodesOf, genericIfaceBindingKeepsClass, guaranteedDecorationThrow, storedClassValueType } from "./lower-classes.js";
|
|
29
29
|
import { isMixinFnBinding, mixinResultBindingClassOf } from "./lower-mixins.js";
|
|
30
30
|
import { cjsModuleRef, cjsModuleRegistryPrelude } from "./lower-node-module.js";
|
|
31
31
|
import { forkTargetPaths } from "../fork-target.js";
|
|
@@ -228,12 +228,41 @@ export function appendDynamicImportModules(program, order, onCycle) {
|
|
|
228
228
|
* signatures are cheap and calls resolve against them; only BODY lowering
|
|
229
229
|
* is reachability-gated. */
|
|
230
230
|
export function collectProgram(lowerer, parts) {
|
|
231
|
+
const computed = new Set();
|
|
232
|
+
for (const fp of parts)
|
|
233
|
+
for (const decl of fp.classDecls) {
|
|
234
|
+
const heritage = decl.heritageClauses?.find((clause) => clause.token === ts.SyntaxKind.ExtendsKeyword)?.types[0]?.expression;
|
|
235
|
+
if (heritage && ts.isCallExpression(heritage))
|
|
236
|
+
computed.add(decl);
|
|
237
|
+
}
|
|
238
|
+
// Descendants need the computed ancestor's completed layout before
|
|
239
|
+
// their own fields and inherited methods can be collected.
|
|
240
|
+
const computedSymbols = new Set([...computed].map((decl) => declSymbolOf(lowerer, decl)).filter((symbol) => symbol !== undefined));
|
|
241
|
+
let expanded = true;
|
|
242
|
+
while (expanded) {
|
|
243
|
+
expanded = false;
|
|
244
|
+
for (const fp of parts)
|
|
245
|
+
for (const decl of fp.classDecls) {
|
|
246
|
+
if (computed.has(decl))
|
|
247
|
+
continue;
|
|
248
|
+
const heritage = decl.heritageClauses?.find((clause) => clause.token === ts.SyntaxKind.ExtendsKeyword)?.types[0]?.expression;
|
|
249
|
+
const base = heritage && ts.isIdentifier(heritage) ? lowerer.resolveValueSymbol(heritage) : undefined;
|
|
250
|
+
if (!base || !computedSymbols.has(base))
|
|
251
|
+
continue;
|
|
252
|
+
computed.add(decl);
|
|
253
|
+
const symbol = declSymbolOf(lowerer, decl);
|
|
254
|
+
if (symbol)
|
|
255
|
+
computedSymbols.add(symbol);
|
|
256
|
+
expanded = true;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
231
259
|
lowerer.collecting = true;
|
|
232
260
|
try {
|
|
233
261
|
collectVirtualJsMethods(lowerer, parts.map((part) => part.sf));
|
|
234
262
|
for (const fp of parts)
|
|
235
263
|
for (const decl of fp.classDecls)
|
|
236
|
-
|
|
264
|
+
if (!computed.has(decl))
|
|
265
|
+
lowerer.collectClassShape(decl);
|
|
237
266
|
for (const fp of parts)
|
|
238
267
|
for (const decl of fp.fnDecls)
|
|
239
268
|
lowerer.collectSignature(decl);
|
|
@@ -263,6 +292,60 @@ export function collectProgram(lowerer, parts) {
|
|
|
263
292
|
lowerer.collectNpmImports(parts);
|
|
264
293
|
lowerer.collectJsonImports(parts);
|
|
265
294
|
}
|
|
295
|
+
for (const decl of computed) {
|
|
296
|
+
const symbol = declSymbolOf(lowerer, decl);
|
|
297
|
+
const wasCollecting = lowerer.collecting;
|
|
298
|
+
lowerer.collecting = true;
|
|
299
|
+
const previousSink = lowerer.diagSink;
|
|
300
|
+
const deferred = [];
|
|
301
|
+
lowerer.diagSink = deferred;
|
|
302
|
+
const expression = decl.heritageClauses.find((clause) => clause.token === ts.SyntaxKind.ExtendsKeyword).types[0].expression;
|
|
303
|
+
const context = newFnCtx(false, null, null, DYN);
|
|
304
|
+
lowerer.fnStack.push(context);
|
|
305
|
+
try {
|
|
306
|
+
let value = lowerer.lowerExpr(expression);
|
|
307
|
+
const known = value.type.kind === "dyn" ? storedClassValueType(lowerer, expression) : null;
|
|
308
|
+
if (known?.kind === "classval")
|
|
309
|
+
value = lowerer.coerceToExpected(value, known);
|
|
310
|
+
if (value.type.kind === "dyn" || value.type.kind === "func") {
|
|
311
|
+
const name = `%class.base.${lowerer.classNamer(decl)}`;
|
|
312
|
+
const loc = locOf(expression);
|
|
313
|
+
lowerer.liftedFns.push({ name, params: [], returnType: value.type, locals: context.locals,
|
|
314
|
+
body: [{ kind: "return", value, loc }], loc });
|
|
315
|
+
lowerer.computedCallableBases.set(decl, { kind: "call", callee: name, args: [], type: value.type, loc });
|
|
316
|
+
}
|
|
317
|
+
if (value.type.kind === "classval") {
|
|
318
|
+
const classInfo = lowerer.classes.get(value.type.className);
|
|
319
|
+
if (classInfo) {
|
|
320
|
+
const name = `%class.base.${lowerer.classNamer(decl)}`;
|
|
321
|
+
const loc = locOf(expression);
|
|
322
|
+
lowerer.liftedFns.push({ name, params: [], returnType: value.type, locals: context.locals,
|
|
323
|
+
body: [{ kind: "return", value, loc }], loc });
|
|
324
|
+
lowerer.computedClassBases.set(lowerer.classNamer(decl), { value: { kind: "call", callee: name, args: [], type: value.type, loc }, classInfo });
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
catch (error) {
|
|
329
|
+
if (!(error instanceof PoisonError))
|
|
330
|
+
throw error;
|
|
331
|
+
}
|
|
332
|
+
finally {
|
|
333
|
+
lowerer.fnStack.pop();
|
|
334
|
+
lowerer.diagSink = previousSink;
|
|
335
|
+
}
|
|
336
|
+
lowerer.diagSink = deferred;
|
|
337
|
+
try {
|
|
338
|
+
lowerer.collectClassShape(decl);
|
|
339
|
+
}
|
|
340
|
+
finally {
|
|
341
|
+
lowerer.diagSink = previousSink;
|
|
342
|
+
}
|
|
343
|
+
if (symbol && deferred.length) {
|
|
344
|
+
lowerer.deferredDiags.set(symbol, [...(lowerer.deferredDiags.get(symbol) ?? []), ...deferred]);
|
|
345
|
+
lowerer.deferredClassByName.set(lowerer.classNamer(decl), symbol);
|
|
346
|
+
}
|
|
347
|
+
lowerer.collecting = wasCollecting;
|
|
348
|
+
}
|
|
266
349
|
}
|
|
267
350
|
/** The npm-import chokepoint, run once per pass during collection (so
|
|
268
351
|
* bodies lowered in ANY pass resolve the bindings). In a static build
|
|
@@ -655,15 +738,41 @@ export function moduleArtifacts(lowerer, functions) {
|
|
|
655
738
|
const pendingClasses = [];
|
|
656
739
|
const pendingShapes = [];
|
|
657
740
|
const pendingUnions = [];
|
|
741
|
+
const boxedChild = (type, seen = new Set()) => {
|
|
742
|
+
switch (type.kind) {
|
|
743
|
+
case "child": return true;
|
|
744
|
+
case "array":
|
|
745
|
+
case "set": return boxedChild(type.elem, seen);
|
|
746
|
+
case "promise": return boxedChild(type.inner, seen);
|
|
747
|
+
case "map": return boxedChild(type.key, seen) || boxedChild(type.value, seen);
|
|
748
|
+
case "func": return boxedChild(type.ret, seen);
|
|
749
|
+
case "record":
|
|
750
|
+
if (seen.has(type.shapeId))
|
|
751
|
+
return false;
|
|
752
|
+
seen.add(type.shapeId);
|
|
753
|
+
return lowerer.shapes.get(type.shapeId)?.fields.some((field) => boxedChild(field.type, seen)) ?? false;
|
|
754
|
+
case "union":
|
|
755
|
+
if (seen.has(type.unionId))
|
|
756
|
+
return false;
|
|
757
|
+
seen.add(type.unionId);
|
|
758
|
+
return lowerer.unions.get(type.unionId)?.arms.some((arm) => boxedChild(arm, seen)) ?? false;
|
|
759
|
+
default: return false;
|
|
760
|
+
}
|
|
761
|
+
};
|
|
658
762
|
const visit = (node) => {
|
|
659
763
|
if (Array.isArray(node)) {
|
|
660
|
-
|
|
661
|
-
|
|
764
|
+
// This walk only reads compiler-owned arrays. A callback traversal
|
|
765
|
+
// reuses one checked view instead of refreshing it at each step.
|
|
766
|
+
node.forEach(visit);
|
|
662
767
|
return;
|
|
663
768
|
}
|
|
664
769
|
if (node === null || typeof node !== "object")
|
|
665
770
|
return;
|
|
666
771
|
const rec = node;
|
|
772
|
+
if (rec["kind"] === "dynFrom" && boxedChild(rec["value"].type)) {
|
|
773
|
+
// A generic child can expose native stdio without importing stream.
|
|
774
|
+
visit([{ className: "%Readable" }, { className: "%Writable" }]);
|
|
775
|
+
}
|
|
667
776
|
if (typeof rec["className"] === "string" && !classNames.has(rec["className"])) {
|
|
668
777
|
classNames.add(rec["className"]);
|
|
669
778
|
pendingClasses.push(rec["className"]);
|
|
@@ -681,8 +790,25 @@ export function moduleArtifacts(lowerer, functions) {
|
|
|
681
790
|
visit(rec[key]);
|
|
682
791
|
}
|
|
683
792
|
};
|
|
684
|
-
|
|
685
|
-
|
|
793
|
+
// Keep function lists and their typed slots in native storage. Reflective
|
|
794
|
+
// array iteration refreshes a complete view at each step; only executable
|
|
795
|
+
// nodes and individual types need the general dependency walk.
|
|
796
|
+
for (const fn of functions) {
|
|
797
|
+
for (const param of fn.params)
|
|
798
|
+
visit(param.type);
|
|
799
|
+
visit(fn.returnType);
|
|
800
|
+
for (const local of fn.locals)
|
|
801
|
+
visit(local.type);
|
|
802
|
+
for (const capture of fn.captures ?? [])
|
|
803
|
+
visit(capture.type);
|
|
804
|
+
for (const capture of fn.classCaptures ?? [])
|
|
805
|
+
visit(capture.type);
|
|
806
|
+
visit(fn.generator);
|
|
807
|
+
for (const stmt of fn.body)
|
|
808
|
+
visit(stmt);
|
|
809
|
+
}
|
|
810
|
+
for (const global of lowerer.globalsList)
|
|
811
|
+
visit(global.type);
|
|
686
812
|
// The builtin error classes ride EVERY module: the runtime's own throws
|
|
687
813
|
// (JSON/dynCheck/regex failures) mint instances of them whether or not
|
|
688
814
|
// user code mentions Error, and the uncaught printer tells Error
|
|
@@ -803,7 +929,7 @@ function cjsScalarLiteral(e) {
|
|
|
803
929
|
* a checked-dynamic (or unit) value, so a DYN module global can hold it:
|
|
804
930
|
* no initializer, a unit literal, or a checker-`any` call/member/
|
|
805
931
|
* 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
|
|
932
|
+
* User-class `new` expressions stay OUT even when checker-any (`new Anon.Sub()` over
|
|
807
933
|
* an expando class member constructs a TYPED instance — corpus 2032), as
|
|
808
934
|
* does everything else (object/array literals have their own rules;
|
|
809
935
|
* typed-but-unmappable initializers keep the %init-local adoption). */
|
|
@@ -827,6 +953,16 @@ function jsDynHoldableInitializer(lowerer, init) {
|
|
|
827
953
|
e = e.expression;
|
|
828
954
|
if (checkedGlobalReference(lowerer, e))
|
|
829
955
|
return true;
|
|
956
|
+
if (ts.isCallExpression(e) && ts.isPropertyAccessExpression(e.expression) &&
|
|
957
|
+
["freeze", "seal", "preventExtensions"].includes(e.expression.name.text) &&
|
|
958
|
+
lowerer.stdlibGlobalMember(e.expression, "Object") !== null && e.arguments[0] &&
|
|
959
|
+
ts.isArrayLiteralExpression(e.arguments[0]))
|
|
960
|
+
return true;
|
|
961
|
+
// The built-in Array constructor can create an evolving array whose
|
|
962
|
+
// inferred element type has no native mapping. Its checked reference
|
|
963
|
+
// must remain shared with separately declared functions and aliases.
|
|
964
|
+
if ((ts.isCallExpression(e) || ts.isNewExpression(e)) && lowerer.isStdlibGlobal(e.expression, "Array"))
|
|
965
|
+
return true;
|
|
830
966
|
// JavaScript process streams lower to native checked handles even when
|
|
831
967
|
// their declared method overloads prevent a structural type mapping.
|
|
832
968
|
// Register the shared slot before separately declared functions lower.
|
|
@@ -834,6 +970,8 @@ function jsDynHoldableInitializer(lowerer, init) {
|
|
|
834
970
|
const member = lowerer.stdlibGlobalMember(e, "process");
|
|
835
971
|
if (member === "stdin" || member === "stdout" || member === "stderr")
|
|
836
972
|
return true;
|
|
973
|
+
if (e.name.text === "constructor" && lowerer.checker.getCallSignatures(lowerer.typeOf(e.expression)).length > 0)
|
|
974
|
+
return true;
|
|
837
975
|
}
|
|
838
976
|
if (e.kind === ts.SyntaxKind.NullKeyword)
|
|
839
977
|
return true;
|
|
@@ -851,6 +989,11 @@ function jsDynHoldableInitializer(lowerer, init) {
|
|
|
851
989
|
if ((ts.isPropertyAccessExpression(e) || ts.isElementAccessExpression(e)) &&
|
|
852
990
|
ts.isIdentifier(e.expression) && lowerer.globalOf(e.expression)?.type.kind === "dyn")
|
|
853
991
|
return true;
|
|
992
|
+
if (ts.isPropertyAccessExpression(e)) {
|
|
993
|
+
const member = nsMemberIdentOf(lowerer, e);
|
|
994
|
+
if (member && (lowerer.globalOf(member)?.type.kind === "dyn" || lowerer.genericFnOf(member)?.implicitParams))
|
|
995
|
+
return true;
|
|
996
|
+
}
|
|
854
997
|
// Optional callable reads (for example descriptor?.get) can be held in
|
|
855
998
|
// the same checked slot as a callable. Their nullish arm must remain
|
|
856
999
|
// observable by functions declared outside the module initializer.
|
|
@@ -862,6 +1005,8 @@ function jsDynHoldableInitializer(lowerer, init) {
|
|
|
862
1005
|
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
1006
|
return true;
|
|
864
1007
|
}
|
|
1008
|
+
if ((ts.isFunctionExpression(e) || ts.isArrowFunction(e)) && !e.typeParameters?.length && isJsSourceFile(e.getSourceFile()))
|
|
1009
|
+
return true;
|
|
865
1010
|
if (ts.isIdentifier(e) || ts.isArrowFunction(e) || ts.isFunctionExpression(e)) {
|
|
866
1011
|
if (ts.isIdentifier(e)) {
|
|
867
1012
|
if (lowerer.globalOf(e)?.type.kind === "dyn")
|
|
@@ -1123,8 +1268,12 @@ export function collectGlobals(lowerer, sf, topStmts) {
|
|
|
1123
1268
|
const diagsBefore = lowerer.diags.length;
|
|
1124
1269
|
try {
|
|
1125
1270
|
const strict = lowerer.typeOf(rhs);
|
|
1126
|
-
|
|
1271
|
+
let t = lowerer.mapTypeOf(strict) ??
|
|
1127
1272
|
(fnValued || factoryValued ? dynFallbackType(lowerer, rhs, strict) : null);
|
|
1273
|
+
// A returned object remains the live CommonJS root; later
|
|
1274
|
+
// exports.member writes must update that same open object.
|
|
1275
|
+
if (factoryValued && t?.kind === "record" && lowerer.dynConvertible(t))
|
|
1276
|
+
t = DYN;
|
|
1128
1277
|
if (t && t.kind !== "void") {
|
|
1129
1278
|
const g = { id: `%g.${tag}exports`, name: "exports", type: t, mutable: false };
|
|
1130
1279
|
lowerer.globalsByDeclNode.set(cjs.expr, g);
|
|
@@ -1493,6 +1642,23 @@ export function collectGlobals(lowerer, sf, topStmts) {
|
|
|
1493
1642
|
for (const nameNode of boundIdentifiersOf(decl.name)) {
|
|
1494
1643
|
const diagsBefore = lowerer.diags.length;
|
|
1495
1644
|
try {
|
|
1645
|
+
// Checked JavaScript factories can expose inferred callables by
|
|
1646
|
+
// destructuring. Keep each exported binding in module storage so
|
|
1647
|
+
// separately lowered functions see the initialized value.
|
|
1648
|
+
if (isJsSourceFile(sf) && !ts.isIdentifier(decl.name) && decl.initializer &&
|
|
1649
|
+
!decl.type && !hasJsTypeAnnotation(decl) && !lowerer.mapTypeOf(lowerer.typeOf(nameNode))) {
|
|
1650
|
+
const symbol = lowerer.checker.getSymbolAtLocation(nameNode);
|
|
1651
|
+
if (symbol && !lowerer.globalsBySymbol.has(symbol)) {
|
|
1652
|
+
const g = { id: `%g.${tag}${nsPrefix}${nameNode.text}`, name: nameNode.text,
|
|
1653
|
+
type: DYN, mutable: isLet, source: bindingSource(nameNode),
|
|
1654
|
+
...(!isVarDeclared(decl) ? { tdz: true } : {}) };
|
|
1655
|
+
lowerer.globalsBySymbol.set(symbol, g);
|
|
1656
|
+
lowerer.globalsList.push(g);
|
|
1657
|
+
if (isVarDeclared(decl))
|
|
1658
|
+
noteVarGlobalEntryInit(lowerer, sf, g);
|
|
1659
|
+
}
|
|
1660
|
+
continue;
|
|
1661
|
+
}
|
|
1496
1662
|
// Builtin declarations do not always describe the concrete native
|
|
1497
1663
|
// callable ABI. Preserve checked-native values in shared storage;
|
|
1498
1664
|
// adapting the loader to (string) would replace its validation.
|
|
@@ -1543,7 +1709,8 @@ export function collectGlobals(lowerer, sf, topStmts) {
|
|
|
1543
1709
|
if (isJsSourceFile(sf) && ts.isIdentifier(decl.name) && nameNode === decl.name &&
|
|
1544
1710
|
decl.initializer && ts.isObjectLiteralExpression(decl.initializer) &&
|
|
1545
1711
|
decl.initializer.properties.some((p) => !ts.isSpreadAssignment(p) &&
|
|
1546
|
-
(ts.isMethodDeclaration(p) || ts.isAccessor(p) || ts.isComputedPropertyName(p.name)
|
|
1712
|
+
(ts.isMethodDeclaration(p) || ts.isAccessor(p) || ts.isComputedPropertyName(p.name) ||
|
|
1713
|
+
ts.isShorthandPropertyAssignment(p) && lowerer.checker.getCallSignatures(lowerer.typeOf(p.name)).length > 0))) {
|
|
1547
1714
|
const symbol = lowerer.checker.getSymbolAtLocation(nameNode);
|
|
1548
1715
|
if (symbol && !lowerer.globalsBySymbol.has(symbol)) {
|
|
1549
1716
|
const g = { id: `%g.${tag}${nsPrefix}${nameNode.text}`, name: nameNode.text, type: DYN, mutable: isLet, source: bindingSource(nameNode) };
|
|
@@ -1649,9 +1816,16 @@ export function collectGlobals(lowerer, sf, topStmts) {
|
|
|
1649
1816
|
if (isJsSourceFile(sf) && !lowerer.mapTypeOf(lowerer.typeOf(nameNode)) &&
|
|
1650
1817
|
ts.isIdentifier(decl.name) && nameNode === decl.name && decl.initializer &&
|
|
1651
1818
|
jsDynHoldableInitializer(lowerer, decl.initializer)) {
|
|
1652
|
-
const
|
|
1819
|
+
const initializer = decl.initializer;
|
|
1820
|
+
const member = ts.isPropertyAccessExpression(initializer) ? nsMemberIdentOf(lowerer, initializer) : null;
|
|
1821
|
+
const generic = member && lowerer.genericFnOf(member);
|
|
1822
|
+
const fallback = (ts.isArrowFunction(initializer) || ts.isFunctionExpression(initializer)) && !initializer.typeParameters?.length
|
|
1823
|
+
? lowerer.lambdaSignature(initializer).funcType
|
|
1824
|
+
: member && lowerer.globalOf(member)?.type.kind === "dyn" ? DYN
|
|
1825
|
+
: member && generic?.implicitParams ? lowerer.lowerGenericFnValue(member, generic).type
|
|
1826
|
+
: dynFallbackType(lowerer, nameNode, lowerer.typeOf(nameNode));
|
|
1653
1827
|
const symbol = lowerer.checker.getSymbolAtLocation(nameNode);
|
|
1654
|
-
if (symbol && fallback && (fallback.kind === "func" || fallback.kind === "union") && lowerer.dynConvertible(fallback)) {
|
|
1828
|
+
if (symbol && fallback && (fallback.kind === "dyn" || fallback.kind === "func" || fallback.kind === "union") && lowerer.dynConvertible(fallback)) {
|
|
1655
1829
|
if (!lowerer.globalsBySymbol.has(symbol)) {
|
|
1656
1830
|
const g = {
|
|
1657
1831
|
id: `%g.${tag}${nsPrefix}${nameNode.text}`, name: nameNode.text,
|
|
@@ -1691,7 +1865,30 @@ export function collectGlobals(lowerer, sf, topStmts) {
|
|
|
1691
1865
|
// exactly the local rule (uncheckedOverloadHandleCall).
|
|
1692
1866
|
(uncheckedOverloadHandleCall(lowerer, decl.initializer) ? JSVAL : null) : null)
|
|
1693
1867
|
: null;
|
|
1694
|
-
|
|
1868
|
+
// Unannotated results of JavaScript calls can carry callable
|
|
1869
|
+
// objects or heterogeneous unions absent from the native type
|
|
1870
|
+
// map. Their compiled initializer still validates every crossing.
|
|
1871
|
+
const callSignature = !decl.type && !hasJsTypeAnnotation(decl) && decl.initializer && ts.isCallExpression(decl.initializer)
|
|
1872
|
+
? lowerer.checker.getResolvedSignature(decl.initializer) : undefined;
|
|
1873
|
+
const callDeclaration = callSignature && lowerer.checker.signatureDeclaration(callSignature);
|
|
1874
|
+
const inferredJsCall = callDeclaration && isJsSourceFile(callDeclaration.getSourceFile()) &&
|
|
1875
|
+
!lowerer.mapTypeOf(lowerer.typeOf(nameNode));
|
|
1876
|
+
let type = handleT ?? factoryType ?? (inferredJsCall ? DYN : lowerer.irTypeOf(nameNode));
|
|
1877
|
+
if (isJsSourceFile(sf) && !decl.type && !hasJsTypeAnnotation(decl) && decl.initializer &&
|
|
1878
|
+
(ts.isArrowFunction(decl.initializer) || ts.isFunctionExpression(decl.initializer)) &&
|
|
1879
|
+
!decl.initializer.typeParameters?.length) {
|
|
1880
|
+
type = lowerer.lambdaSignature(decl.initializer).funcType;
|
|
1881
|
+
}
|
|
1882
|
+
if (isJsSourceFile(sf) && !decl.type && !hasJsTypeAnnotation(decl) &&
|
|
1883
|
+
decl.initializer && ts.isCallExpression(decl.initializer) && type.kind === "union") {
|
|
1884
|
+
const arms = lowerer.unions.get(type.unionId)?.arms;
|
|
1885
|
+
if (arms?.some((arm) => arm.kind === "record") && arms.every((arm) => isUnitType(arm) || arm.kind === "record"))
|
|
1886
|
+
type = DYN;
|
|
1887
|
+
}
|
|
1888
|
+
if (isJsSourceFile(sf) && !decl.type && !hasJsTypeAnnotation(decl) && decl.initializer &&
|
|
1889
|
+
ts.isNewExpression(decl.initializer) && lowerer.mapTypeOf(lowerer.typeOf(decl.initializer.expression))?.kind === "dyn" &&
|
|
1890
|
+
!(ts.isIdentifier(decl.initializer.expression) && lowerer.isStdlibSymbol(lowerer.checker.getSymbolAtLocation(decl.initializer.expression))))
|
|
1891
|
+
type = DYN;
|
|
1695
1892
|
// Calls through checked function values retain their object
|
|
1696
1893
|
// identity, including symbol keys absent from inferred records.
|
|
1697
1894
|
if (isJsSourceFile(sf) && !decl.type && !hasJsTypeAnnotation(decl) && type.kind === "record" &&
|
|
@@ -1711,6 +1908,9 @@ export function collectGlobals(lowerer, sf, topStmts) {
|
|
|
1711
1908
|
// a fixed-signature adapter to reconstruct its hidden rest ABI.
|
|
1712
1909
|
if (!decl.type && !hasJsTypeAnnotation(decl) && type.kind === "func" && type.rest === true && type.restAbi === undefined)
|
|
1713
1910
|
type = DYN;
|
|
1911
|
+
if (isJsSourceFile(sf) && isLet && !decl.type && !hasJsTypeAnnotation(decl) &&
|
|
1912
|
+
(type.kind === "object" || jsBindingHasOpenWrites(lowerer, decl)))
|
|
1913
|
+
type = DYN;
|
|
1714
1914
|
// JavaScript call results may retain a checked array supplied by
|
|
1715
1915
|
// the caller. A typed global here would copy it on extraction.
|
|
1716
1916
|
if (isJsSourceFile(sf) && !decl.type && !hasJsTypeAnnotation(decl) && type.kind === "array" &&
|
|
@@ -1793,8 +1993,7 @@ export function collectGlobals(lowerer, sf, topStmts) {
|
|
|
1793
1993
|
// adapter would re-copy at the assignment.
|
|
1794
1994
|
if (isJsSourceFile(sf) &&
|
|
1795
1995
|
type.kind === "func" &&
|
|
1796
|
-
type.ret.kind === "record" &&
|
|
1797
|
-
lowerer.dynConvertible(type.ret) &&
|
|
1996
|
+
(type.ret.kind === "date" || type.ret.kind === "record" && lowerer.dynConvertible(type.ret)) &&
|
|
1798
1997
|
decl.initializer !== undefined &&
|
|
1799
1998
|
(ts.isFunctionExpression(decl.initializer) || ts.isArrowFunction(decl.initializer)) &&
|
|
1800
1999
|
decl.initializer.type === undefined &&
|
|
@@ -1811,6 +2010,10 @@ export function collectGlobals(lowerer, sf, topStmts) {
|
|
|
1811
2010
|
type = DYN;
|
|
1812
2011
|
}
|
|
1813
2012
|
// Module vars hold real undefined until their declaration runs.
|
|
2013
|
+
// Unannotated JS function values need that state too: callers
|
|
2014
|
+
// before the initializer must see undefined and a TypeError.
|
|
2015
|
+
if (isJsSourceFile(sf) && isVarDeclared(decl) && type.kind === "func" && lowerer.dynConvertible(type))
|
|
2016
|
+
type = DYN;
|
|
1814
2017
|
// Codec records keep that state in the ordinary optional union;
|
|
1815
2018
|
// lexical codec declarations retain their separate TDZ guard.
|
|
1816
2019
|
const codec = type.kind === "record" && recordTextCodecClass(lowerer.shapes.get(type.shapeId)) !== null;
|
|
@@ -2214,7 +2417,7 @@ export function lowerFileInit(lowerer, sf, stmts, name) {
|
|
|
2214
2417
|
// SITE's position instead (below) — their inner class node may
|
|
2215
2418
|
// even live in another file.
|
|
2216
2419
|
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))
|
|
2420
|
+
(c.callableBase !== undefined || c.def.baseValueGlobal !== undefined || c.staticFields.length > 0 || (c.staticBlocks?.length ?? 0) > 0 || c.classDecorators !== undefined))
|
|
2218
2421
|
.map((c) => ({ pos: c.decl.getStart(), info: c }));
|
|
2219
2422
|
// Statics-bearing MIXIN instantiations whose call evaluates in THIS
|
|
2220
2423
|
// file: their declaration-time code runs when the call does — the
|