@scriptc/compiler 0.0.9 → 0.0.11
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 +54 -9
- package/dist/backend/emission/emit-exprs.js +170 -14
- package/dist/backend/emission/emit-exprs.js.map +1 -1
- package/dist/backend/emission/emit-walkers.js +29 -2
- package/dist/backend/emission/emit-walkers.js.map +1 -1
- package/dist/backend/emission/emitter.js +25 -1
- package/dist/backend/emission/emitter.js.map +1 -1
- package/dist/backend/llvm/dyn.d.ts +1 -0
- package/dist/backend/llvm/dyn.js +83 -1
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.js +210 -13
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/coverage/surface-manifest.js +16 -2
- package/dist/coverage/surface-manifest.js.map +1 -1
- package/dist/diagnostics/diagnostic.d.ts +41 -14
- package/dist/diagnostics/diagnostic.js +79 -27
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/diagnostics/render.js +8 -0
- package/dist/diagnostics/render.js.map +1 -1
- package/dist/frontend/lowering/lib-boundary.js +11 -1
- package/dist/frontend/lowering/lib-boundary.js.map +1 -1
- package/dist/frontend/lowering/lower-builtins.d.ts +69 -0
- package/dist/frontend/lowering/lower-builtins.js +380 -4
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +41 -0
- package/dist/frontend/lowering/lower-calls.js +559 -11
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +7 -0
- package/dist/frontend/lowering/lower-classes.js +51 -1
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.d.ts +21 -0
- package/dist/frontend/lowering/lower-containers.js +262 -17
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-dgram.js +92 -17
- package/dist/frontend/lowering/lower-dgram.js.map +1 -1
- package/dist/frontend/lowering/lower-emitter.d.ts +70 -3
- package/dist/frontend/lowering/lower-emitter.js +436 -29
- package/dist/frontend/lowering/lower-emitter.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +80 -5
- package/dist/frontend/lowering/lower-exprs.js +651 -23
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.d.ts +8 -5
- package/dist/frontend/lowering/lower-modules.js +144 -19
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-namespaces.d.ts +39 -11
- package/dist/frontend/lowering/lower-namespaces.js +166 -24
- package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
- package/dist/frontend/lowering/lower-server.js +211 -4
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.d.ts +1 -5
- package/dist/frontend/lowering/lower-stmts.js +293 -10
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.js +178 -10
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +53 -1
- package/dist/frontend/lowering/lowerer.js +210 -19
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/surfaces.d.ts +44 -0
- package/dist/frontend/lowering/surfaces.js +234 -3
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/npm.d.ts +12 -0
- package/dist/frontend/npm.js +30 -0
- package/dist/frontend/npm.js.map +1 -1
- package/dist/frontend/program.d.ts +25 -0
- package/dist/frontend/program.js +144 -135
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/shared.d.ts +1 -1
- package/dist/frontend/shared.js +1 -1
- package/dist/frontend/shared.js.map +1 -1
- package/dist/frontend/types.d.ts +13 -0
- package/dist/frontend/types.js +84 -7
- package/dist/frontend/types.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +157 -12
- package/dist/index.js.map +1 -1
- package/dist/ir/nodes.d.ts +163 -13
- package/dist/ir/nodes.js +65 -6
- package/dist/ir/nodes.js.map +1 -1
- package/dist/ir/validate.js +64 -5
- package/dist/ir/validate.js.map +1 -1
- package/dist/library/fence-eval.d.ts +77 -0
- package/dist/library/fence-eval.js +395 -0
- package/dist/library/fence-eval.js.map +1 -0
- package/dist/library/int-infer.d.ts +119 -0
- package/dist/library/int-infer.js +1301 -0
- package/dist/library/int-infer.js.map +1 -0
- package/dist/library/int-infer.test.d.ts +1 -0
- package/dist/library/int-infer.test.js +279 -0
- package/dist/library/int-infer.test.js.map +1 -0
- package/dist/library/profile.d.ts +43 -6
- package/dist/library/profile.js +179 -31
- package/dist/library/profile.js.map +1 -1
- package/dist/library/sidecar.d.ts +23 -0
- package/dist/library/sidecar.js +150 -16
- package/dist/library/sidecar.js.map +1 -1
- package/package.json +2 -2
- package/surface-manifest.json +208 -10
|
@@ -10,6 +10,7 @@ import { FileParts } from "./lower-modules.js";
|
|
|
10
10
|
import { ClassInfo, ClassIteratorInfo, GenericClassInfo, findStaticOn } from "./lower-classes.js";
|
|
11
11
|
import { MixinFnShape } from "./lower-mixins.js";
|
|
12
12
|
import { ParamShape, FnSig, GenericFnInfo, GenericInstance } from "./lower-calls.js";
|
|
13
|
+
import { type EmitSpecCtx, type EmitSpecRequest } from "./lower-emitter.js";
|
|
13
14
|
import { FieldTarget } from "./lower-exprs.js";
|
|
14
15
|
import type { ExpandoMember } from "./lower-expando.js";
|
|
15
16
|
/** Entry function name. '%' cannot appear in a TS identifier, so a user
|
|
@@ -301,6 +302,14 @@ export declare function dynUndefinedExpr(loc: SrcLoc): IrExpr;
|
|
|
301
302
|
* an empty code means no code slot. `type` is the replaced expression's
|
|
302
303
|
* own (never materialized — the global.undefRead pattern). */
|
|
303
304
|
export declare function nodeThrowExpr(kind: 0 | 1 | 2, code: string, message: string, type: IrType, loc: SrcLoc): IrExpr;
|
|
305
|
+
/** The post-validation fence STRING a validation-ladder Chk libCall
|
|
306
|
+
* throws after its Node-order checks pass: the same SC2020 text the
|
|
307
|
+
* per-statement runtime fence would have thrown (message + "[code at
|
|
308
|
+
* file:line]"), rendered eagerly so the runtime can throw it verbatim
|
|
309
|
+
* (scr_throw_lowering_fence). The diagnostic joins the runtime-fence
|
|
310
|
+
* ledger exactly like a deferred statement fence — nothing silently
|
|
311
|
+
* drops off the coverage report. */
|
|
312
|
+
export declare function ladderFenceExpr(L: Lowerer, surface: string, node: ts.Node, hint?: string): IrExpr;
|
|
304
313
|
/** The checked-dynamic declaration fallback for unmappable binding types
|
|
305
314
|
* (see irTypeOf), two gates over one story:
|
|
306
315
|
*
|
|
@@ -357,6 +366,29 @@ export declare class Lowerer {
|
|
|
357
366
|
/** Per-symbol result of the never-reassigned file scan
|
|
358
367
|
* (bindingNeverReassigned — object-literal generic-method receivers). */
|
|
359
368
|
readonly neverReassignedCache: Map<ts.Symbol, boolean>;
|
|
369
|
+
/** TRAP bindings: declarations whose initializer provably throws before
|
|
370
|
+
* producing a value (its chain roots at an ambient-undefined name —
|
|
371
|
+
* ambientUndefVarRootOf). Module init unwinds at the declaration, so no
|
|
372
|
+
* reference to the binding can ever execute; the statement lowers to the
|
|
373
|
+
* root's throw, no storage exists, and references lower to the same
|
|
374
|
+
* trap shape (never reached — sound whatever the type). */
|
|
375
|
+
readonly trapBindings: Set<ts.Symbol>;
|
|
376
|
+
/** NULLISH bindings of unmappable (generic-signature) types: `const i:
|
|
377
|
+
* I<A & B> = null as any` — the binding provably holds null/undefined
|
|
378
|
+
* forever (every write's RHS is nullish too), so no storage exists and
|
|
379
|
+
* each READ knows the value. Member reads and method calls through one
|
|
380
|
+
* lower to Node's exact TypeError ("Cannot read properties of null
|
|
381
|
+
* (reading 'fn')"); nullish-to-nullish flows lower to nothing. The map
|
|
382
|
+
* answers which unit the binding holds (the TypeError names it). Null
|
|
383
|
+
* entries cache probed non-qualifiers. */
|
|
384
|
+
readonly nullishBindings: Map<ts.Symbol, "undefined" | "null" | null>;
|
|
385
|
+
/** DEAD bindings of unmappable types: never READ anywhere in the
|
|
386
|
+
* program, declared with no initializer or a value-only one (a function
|
|
387
|
+
* literal), every write's RHS side-effect-free. Node materializes the
|
|
388
|
+
* value and drops it — zero observable effect — so the declaration and
|
|
389
|
+
* its writes lower to nothing, and no type fence fires for a value the
|
|
390
|
+
* program never consumes. */
|
|
391
|
+
readonly deadBindings: Set<ts.Symbol>;
|
|
360
392
|
/** IMPLICIT-ANY function-value bindings (npm-static JS — `const knownBy
|
|
361
393
|
* = (cmd) => ...`), by their VariableDeclaration: the registered info,
|
|
362
394
|
* or null for probed non-qualifiers (implicitLocalFnNodeOf). */
|
|
@@ -409,6 +441,13 @@ export declare class Lowerer {
|
|
|
409
441
|
/** Synthetic array-HOF loop functions (map/filter/forEach desugar),
|
|
410
442
|
* interned per method + element/callback-result type: key → fn name. */
|
|
411
443
|
readonly arrHofHelpers: Map<string, string>;
|
|
444
|
+
/** Emit-override specializations (`%C.emit:<event>` — lower-emitter.ts's
|
|
445
|
+
* emit-overrides block): interned names, the drive-loop queue, and the
|
|
446
|
+
* currently-lowering specialization's context (the super-forward
|
|
447
|
+
* interception reads it). */
|
|
448
|
+
readonly emitSpecDone: Set<string>;
|
|
449
|
+
readonly emitSpecQueue: EmitSpecRequest[];
|
|
450
|
+
emitSpecCtx: EmitSpecCtx | null;
|
|
412
451
|
/** Width-coercion helpers (%rec.width.N / %arr.width.N), interned per
|
|
413
452
|
* (from, to) shape pair — see widthCoerce. */
|
|
414
453
|
readonly widthHelpers: Map<string, string>;
|
|
@@ -541,6 +580,15 @@ export declare class Lowerer {
|
|
|
541
580
|
* `fileName\u0000specifier` (collectDynamicImports fills it during npm
|
|
542
581
|
* collection; lowerDynamicImportCall reads it per site). */
|
|
543
582
|
readonly dynImports: Map<string, DynamicImportResolution>;
|
|
583
|
+
/** createRequire-require resolutions of BARE npm specifiers, keyed
|
|
584
|
+
* `fileName\u0000specifier` (collectCreateRequires fills it during npm
|
|
585
|
+
* collection under --dynamic — the require-condition entry key plus its
|
|
586
|
+
* embedded format; lowerCreateRequireCall reads it per site; "" marks a
|
|
587
|
+
* failed resolution already reported at collection). */
|
|
588
|
+
readonly createRequireImports: Map<string, "" | {
|
|
589
|
+
entryKey: string;
|
|
590
|
+
format: "esm" | "cjs" | "json";
|
|
591
|
+
}>;
|
|
544
592
|
/** Module → the name of its synthesized namespace-BUILDER function
|
|
545
593
|
* (lowerOwnModuleImport): every `import()` of the same program module
|
|
546
594
|
* shares one builder. */
|
|
@@ -1631,7 +1679,7 @@ export declare class Lowerer {
|
|
|
1631
1679
|
stmts: IrStmt[];
|
|
1632
1680
|
value: IrExpr;
|
|
1633
1681
|
};
|
|
1634
|
-
lowerBindingPattern(pattern: ts.ArrayBindingPattern | ts.ObjectBindingPattern, srcRef: () => IrExpr, srcType: IrType, isLet: boolean, out: IrStmt[]): void;
|
|
1682
|
+
lowerBindingPattern(pattern: ts.ArrayBindingPattern | ts.ObjectBindingPattern, srcRef: () => IrExpr, srcType: IrType, isLet: boolean, out: IrStmt[], dynSpell?: string): void;
|
|
1635
1683
|
checkBindingElement(el: ts.BindingElement, allowDefault?: boolean): void;
|
|
1636
1684
|
bindPatternTarget(name: ts.BindingName, value: IrExpr, isLet: boolean, out: IrStmt[]): void;
|
|
1637
1685
|
lowerVarDeclList(list: ts.VariableDeclarationList): IrStmt | null;
|
|
@@ -1799,6 +1847,10 @@ export declare class Lowerer {
|
|
|
1799
1847
|
module: string;
|
|
1800
1848
|
member: string;
|
|
1801
1849
|
}, loc: SrcLoc): IrExpr | null;
|
|
1850
|
+
lowerFsLadderCall(expr: ts.CallExpression, bi: {
|
|
1851
|
+
module: string;
|
|
1852
|
+
member: string;
|
|
1853
|
+
}, loc: SrcLoc): IrExpr | null;
|
|
1802
1854
|
lowerChildArgsArg(node: ts.Expression | undefined, loc: SrcLoc): IrExpr;
|
|
1803
1855
|
lowerSpawnSyncCall(expr: ts.CallExpression, loc: SrcLoc): IrExpr;
|
|
1804
1856
|
lowerSpawnCall(expr: ts.CallExpression, loc: SrcLoc): IrExpr;
|
|
@@ -19,14 +19,15 @@ import { arrayOf, BOOL, canAdaptDynFuncTo, canConvertToDyn, canCrossIslandBounda
|
|
|
19
19
|
import { provenanceActive } from "../provenance-registry.js";
|
|
20
20
|
import { ambientDtsPath, canonicalBuiltinModule, cjsExportAssignmentOf, cjsExportDiscardReason, fallbackDtsPath, isCjsExportTableLiteral, isJsSourceFile, isNodeEsmFile, isNodeTypesPath, locOf, overridesDtsPath, npmStaticDepSf7, requireSpecOf, resolveImport, workspacePackageOfPath, } from "../program.js";
|
|
21
21
|
import { containsRecord, containsUnion, describeComponentBlocker, describeRecordMemberBlocker, formatIrType, ISLAND_AMBIENT_TYPES, isUnitOnlyTsType, mapType, ShapeRegistry, typeKey, UnionRegistry, withUndefinedArm as withUndefinedArmCanonical, } from "../types.js";
|
|
22
|
-
import { boundaryIntoIslandMsg, boundaryOutOfIslandMsg, builtinConstLit, builtinModuleConstOf, builtinFenceHintOf, builtinModuleFnOf, stdlibMemberFence, isStdlibMember, isStdlibSymbol, isStdlibGlobal, stdlibGlobalMember, nodeTypesOnlySymbol } from "./surfaces.js";
|
|
22
|
+
import { boundaryIntoIslandMsg, boundaryOutOfIslandMsg, builtinConstLit, builtinModuleConstOf, builtinModulesArrayLit, builtinFenceHintOf, builtinModuleFnOf, stdlibMemberFence, isStdlibMember, isStdlibSymbol, isStdlibGlobal, stdlibGlobalMember, nodeTypesOnlySymbol } from "./surfaces.js";
|
|
23
23
|
import { splitFiles, collectProgram, collectNpmImports, collectJsonImports, moduleArtifacts, collectGlobals, declSymbolOf, defaultExportSymbolOf, lowerFileInit, lowerDefaultExport, buildMain, appendDynamicImportModules } from "./lower-modules.js";
|
|
24
24
|
import { registerBuiltinErrorClasses, registerBuiltinEmitterClass, registerBuiltinStreamClasses, builtinErrorInfoOf, builtinEmitterInfoOf, builtinStreamInfoOf, analyzeClassDecoration, classIteratorDrainCall, classIteratorNextCall, classIteratorOf, classIteratorOpenCall, classIteratorRestDrainCall, classMemberNameOf, classValueRef, collectClassShape, exactClassOfReceiver, collectClassShapeInner, ctorAbiEquals, findMethodOn, findStaticOn, findGenericMethodOn, findGenericStaticOn, genericClassInstanceType, isSubclassOf, inHierarchy, overrideBelow, staticShadowBelow, upcastTo, lowerClassMembers, lowerClassCtor, lowerClassExpression, lowerClassExpressionInfo, lowerClassMethodMember, lowerClassValueProperty, lowerStaticMethod, throwingSetterFn, fieldInitStmts, lowerStaticFieldInits, lowerStaticFieldRead, lowerDerivedCtorBody, superCallStmt, lowerSuperMethodCall, superThisRef, lowerSuperAccessorRead, lowerSuperAccessorWrite, inheritsBuiltinErrorCtor, inheritsBuiltinEmitterCtor, errorMessageArg, lowerNew, accessorCall } from "./lower-classes.js";
|
|
25
25
|
import { mixinCallClassInfoOf, mixinIntersectionInstanceType } from "./lower-mixins.js";
|
|
26
26
|
import { bindingNeverReassigned, bodyReadsArguments, isThisParameter, paramShape, paramShapes, checkDefaultParamBodyType, completeArgs, wrappedUndefined, undefinedArgFor, requireExactArityValue, bodyReturnType, declaredReturnType, collectSignature, collectSignatureInner, collectGenericSignature, genericFnOf, lowerGenericCall, lowerGenericFnValue, inferTypeParamBindings, lowerGenericInstance, lowerCall, lowerTimersMemberCall, lowerPromiseMethodCall, lowerFilterNarrowCall, isTopLevelFnSymbol, lowerNestedFunctionDecl, lambdaSignature, lowerLambda, lowerFunction } from "./lower-calls.js";
|
|
27
27
|
import { lowerArrayMethodCall, lowerBufferStaticCall, lowerBytesMethodCall, lowerBytesNew, lowerMapMethodCall, lowerMapForEachCall, buildMapForEachFn, lowerRecordOvfCaptureHelper, lowerEnvToPairsHelper, lowerSetMethodCall, lowerSetForEachCall, buildSetForEachFn, lowerRegexMethodCall, lowerStringMethodCall } from "./lower-containers.js";
|
|
28
28
|
import { lowerStreamModuleCall } from "./lower-stream.js";
|
|
29
|
-
import {
|
|
29
|
+
import { lowerEmitOverrideSpec } from "./lower-emitter.js";
|
|
30
|
+
import { builtinImportOf, createRequireBindingDecl, createRequireNamespaceDecl, createRequireSpecOf, stripTypeCasts, lowerBuiltinModuleCall, lowerFsToUnixTimestampCall, lowerFsLadderCall, lowerChildArgsArg, lowerSpawnSyncCall, lowerSpawnCall, lowerExecSyncCall, recordToEnvPairs, lowerJsonMethodCall, fencedBuiltinImportOf, lowerCryptoComposedCall, lowerUrlMethodCall, lowerSearchParamsMethodCall, lowerStatsMethodCall, lowerChildMethodCall, lowerAtomicsCall, lowerBuiltinExtraProperty, promisifiedExecFileDecl, lowerExecFileAsyncCall, execFileAsyncHelper, lowerStringDecoderMethodCall, strdecHelper, lowerReadlineMethodCall, lowerDcChannelMethodCall, lowerDcChannelProperty, lowerAlsMethodCall, lowerDcTracingChannelMethodCall, lowerDcTracingChannelProperty, lowerJsonProperty, lowerErrorCodeProperty, lowerProcessProperty, isProcessEnv, envValueType, lowerProcessEnvGet, lowerProcessMethodCall, lowerProcessOptionalMethodCall, lowerTimeoutMethodCall, envSnapshotHelper, isConsoleLog, consoleCallMember, lowerNumberStaticCall, lowerNumberStaticProperty, lowerDateCall, lowerTextCodecCall, lowerFsConstantsProperty, lowerHttp2ConstantsProperty, http2ConstantBindingOf, http2ConstantsDestructureDecl, lowerProcessStreamProperty, lowerStringStaticCall, lowerStringLastIndexOfCall, lowerPromiseStaticCall } from "./lower-builtins.js";
|
|
30
31
|
import { isIslandExpr, islandFuncValueFence, islandRegexpOf, jsvalIn, requireDynamicApi, islandGlobalFnOf, lowerDynamicImportCall, lowerFetchCall, lowerIslandMethodCall, lowerMathProperty, npmPackageOf, npmMemberFence, npmPackageOfSymbol } from "./lower-island.js";
|
|
31
32
|
import { lowerHttpHeadersElement, lowerNetModuleCall, lowerServerMethodCall, lowerServerProperty } from "./lower-server.js";
|
|
32
33
|
import { lowerDgramDnsModuleCall, lowerDgramMethodCall } from "./lower-dgram.js";
|
|
@@ -148,8 +149,24 @@ export function lowerToIr(program, entry, moduleOrder, options = {}) {
|
|
|
148
149
|
const dynamic = options.dynamic ?? false;
|
|
149
150
|
const targetPlatform = options.targetPlatform ?? process.platform;
|
|
150
151
|
const startupCrash = options.startupCrash ?? null;
|
|
152
|
+
// --dynamic: modules reachable only through dynamic import() of the
|
|
153
|
+
// program's own files join the compiled graph here, ONCE, before any
|
|
154
|
+
// pass constructs (nothing calls their %init at startup — the import()
|
|
155
|
+
// site's namespace builder does, on the engine microtask, Node's
|
|
156
|
+
// evaluation point for them). Inadmissible static cycles inside the
|
|
157
|
+
// added subgraph are minted here and handed to the EMIT pass: the
|
|
158
|
+
// discovery pass's diagnostics are discarded by design, and after this
|
|
159
|
+
// extension of the shared array no later pass re-walks the subgraph.
|
|
160
|
+
const dynamicCycleDiags = [];
|
|
161
|
+
if (dynamic) {
|
|
162
|
+
appendDynamicImportModules(program, moduleOrder, (cycle, reason) => {
|
|
163
|
+
dynamicCycleDiags.push(unsupportedDiag("SC1016", { file: entry.fileName, start: 0, end: 0 }, `circular imports (${cycle}; ${reason})`));
|
|
164
|
+
});
|
|
165
|
+
}
|
|
151
166
|
const reachable = new Lowerer(program, entry, moduleOrder, dynamic, { targetPlatform }).discover(options.libRoots);
|
|
152
167
|
const emit = new Lowerer(program, entry, moduleOrder, dynamic, { reachable, targetPlatform, startupCrash });
|
|
168
|
+
for (const d of dynamicCycleDiags)
|
|
169
|
+
emit.pushDiag(d);
|
|
153
170
|
const result = emit.run();
|
|
154
171
|
if (options.coverage !== true)
|
|
155
172
|
return result;
|
|
@@ -299,6 +316,26 @@ export function nodeThrowExpr(kind, code, message, type, loc) {
|
|
|
299
316
|
loc,
|
|
300
317
|
};
|
|
301
318
|
}
|
|
319
|
+
/** The post-validation fence STRING a validation-ladder Chk libCall
|
|
320
|
+
* throws after its Node-order checks pass: the same SC2020 text the
|
|
321
|
+
* per-statement runtime fence would have thrown (message + "[code at
|
|
322
|
+
* file:line]"), rendered eagerly so the runtime can throw it verbatim
|
|
323
|
+
* (scr_throw_lowering_fence). The diagnostic joins the runtime-fence
|
|
324
|
+
* ledger exactly like a deferred statement fence — nothing silently
|
|
325
|
+
* drops off the coverage report. */
|
|
326
|
+
export function ladderFenceExpr(L, surface, node, hint) {
|
|
327
|
+
const loc = locOf(node);
|
|
328
|
+
const d = noLoweringDiag(surface, loc, hint);
|
|
329
|
+
L.runtimeFences.push(d);
|
|
330
|
+
const sf = node.getSourceFile();
|
|
331
|
+
const pos = ts.getLineAndCharacterOfPosition(sf, loc.start);
|
|
332
|
+
return {
|
|
333
|
+
kind: "strLit",
|
|
334
|
+
value: `${d.message} [${d.code} at ${loc.file}:${pos.line + 1}]`,
|
|
335
|
+
type: STRING,
|
|
336
|
+
loc,
|
|
337
|
+
};
|
|
338
|
+
}
|
|
302
339
|
/** The checked-dynamic declaration fallback for unmappable binding types
|
|
303
340
|
* (see irTypeOf), two gates over one story:
|
|
304
341
|
*
|
|
@@ -477,6 +514,29 @@ export class Lowerer {
|
|
|
477
514
|
/** Per-symbol result of the never-reassigned file scan
|
|
478
515
|
* (bindingNeverReassigned — object-literal generic-method receivers). */
|
|
479
516
|
neverReassignedCache = new Map();
|
|
517
|
+
/** TRAP bindings: declarations whose initializer provably throws before
|
|
518
|
+
* producing a value (its chain roots at an ambient-undefined name —
|
|
519
|
+
* ambientUndefVarRootOf). Module init unwinds at the declaration, so no
|
|
520
|
+
* reference to the binding can ever execute; the statement lowers to the
|
|
521
|
+
* root's throw, no storage exists, and references lower to the same
|
|
522
|
+
* trap shape (never reached — sound whatever the type). */
|
|
523
|
+
trapBindings = new Set();
|
|
524
|
+
/** NULLISH bindings of unmappable (generic-signature) types: `const i:
|
|
525
|
+
* I<A & B> = null as any` — the binding provably holds null/undefined
|
|
526
|
+
* forever (every write's RHS is nullish too), so no storage exists and
|
|
527
|
+
* each READ knows the value. Member reads and method calls through one
|
|
528
|
+
* lower to Node's exact TypeError ("Cannot read properties of null
|
|
529
|
+
* (reading 'fn')"); nullish-to-nullish flows lower to nothing. The map
|
|
530
|
+
* answers which unit the binding holds (the TypeError names it). Null
|
|
531
|
+
* entries cache probed non-qualifiers. */
|
|
532
|
+
nullishBindings = new Map();
|
|
533
|
+
/** DEAD bindings of unmappable types: never READ anywhere in the
|
|
534
|
+
* program, declared with no initializer or a value-only one (a function
|
|
535
|
+
* literal), every write's RHS side-effect-free. Node materializes the
|
|
536
|
+
* value and drops it — zero observable effect — so the declaration and
|
|
537
|
+
* its writes lower to nothing, and no type fence fires for a value the
|
|
538
|
+
* program never consumes. */
|
|
539
|
+
deadBindings = new Set();
|
|
480
540
|
/** IMPLICIT-ANY function-value bindings (npm-static JS — `const knownBy
|
|
481
541
|
* = (cmd) => ...`), by their VariableDeclaration: the registered info,
|
|
482
542
|
* or null for probed non-qualifiers (implicitLocalFnNodeOf). */
|
|
@@ -540,6 +600,13 @@ export class Lowerer {
|
|
|
540
600
|
/** Synthetic array-HOF loop functions (map/filter/forEach desugar),
|
|
541
601
|
* interned per method + element/callback-result type: key → fn name. */
|
|
542
602
|
arrHofHelpers = new Map();
|
|
603
|
+
/** Emit-override specializations (`%C.emit:<event>` — lower-emitter.ts's
|
|
604
|
+
* emit-overrides block): interned names, the drive-loop queue, and the
|
|
605
|
+
* currently-lowering specialization's context (the super-forward
|
|
606
|
+
* interception reads it). */
|
|
607
|
+
emitSpecDone = new Set();
|
|
608
|
+
emitSpecQueue = [];
|
|
609
|
+
emitSpecCtx = null;
|
|
543
610
|
/** Width-coercion helpers (%rec.width.N / %arr.width.N), interned per
|
|
544
611
|
* (from, to) shape pair — see widthCoerce. */
|
|
545
612
|
widthHelpers = new Map();
|
|
@@ -661,6 +728,12 @@ export class Lowerer {
|
|
|
661
728
|
* `fileName\u0000specifier` (collectDynamicImports fills it during npm
|
|
662
729
|
* collection; lowerDynamicImportCall reads it per site). */
|
|
663
730
|
dynImports = new Map();
|
|
731
|
+
/** createRequire-require resolutions of BARE npm specifiers, keyed
|
|
732
|
+
* `fileName\u0000specifier` (collectCreateRequires fills it during npm
|
|
733
|
+
* collection under --dynamic — the require-condition entry key plus its
|
|
734
|
+
* embedded format; lowerCreateRequireCall reads it per site; "" marks a
|
|
735
|
+
* failed resolution already reported at collection). */
|
|
736
|
+
createRequireImports = new Map();
|
|
664
737
|
/** Module → the name of its synthesized namespace-BUILDER function
|
|
665
738
|
* (lowerOwnModuleImport): every `import()` of the same program module
|
|
666
739
|
* shares one builder. */
|
|
@@ -849,16 +922,12 @@ export class Lowerer {
|
|
|
849
922
|
// lowering, long after the constructor completes.
|
|
850
923
|
isProgramFile: (sf) => this.fileTag.has(sf),
|
|
851
924
|
};
|
|
852
|
-
// --dynamic: modules reachable only through dynamic import()
|
|
853
|
-
//
|
|
854
|
-
//
|
|
855
|
-
//
|
|
856
|
-
//
|
|
857
|
-
|
|
858
|
-
appendDynamicImportModules(program, this.moduleOrder, (cycle) => {
|
|
859
|
-
this.pushDiag(unsupportedDiag("SC1016", { file: entry.fileName, start: 0, end: 0 }, `circular imports (${cycle})`));
|
|
860
|
-
});
|
|
861
|
-
}
|
|
925
|
+
// --dynamic: modules reachable only through dynamic import() joined
|
|
926
|
+
// moduleOrder BEFORE any pass constructed — lowerToIr runs
|
|
927
|
+
// appendDynamicImportModules once on the shared array (a per-pass run
|
|
928
|
+
// here minted cycle refusals into the DISCOVERY pass, whose
|
|
929
|
+
// diagnostics are discarded by design, and the extended order left
|
|
930
|
+
// nothing for the emit pass to re-detect).
|
|
862
931
|
this.moduleOrder.forEach((sf, i) => {
|
|
863
932
|
this.fileTag.set(sf, sf === entry ? "" : `%m${i}.`);
|
|
864
933
|
});
|
|
@@ -1367,9 +1436,11 @@ export class Lowerer {
|
|
|
1367
1436
|
let ec = 0;
|
|
1368
1437
|
let gc = 0;
|
|
1369
1438
|
let gi = 0;
|
|
1439
|
+
let es = 0;
|
|
1370
1440
|
while (ec < this.exprClasses.length ||
|
|
1371
1441
|
gc < this.genericClassInstances.length ||
|
|
1372
|
-
gi < this.instantiationQueue.length
|
|
1442
|
+
gi < this.instantiationQueue.length ||
|
|
1443
|
+
es < this.emitSpecQueue.length) {
|
|
1373
1444
|
while (ec < this.exprClasses.length) {
|
|
1374
1445
|
functions.push(...this.lowerClassMembers(this.exprClasses[ec++]));
|
|
1375
1446
|
}
|
|
@@ -1390,6 +1461,20 @@ export class Lowerer {
|
|
|
1390
1461
|
throw e;
|
|
1391
1462
|
}
|
|
1392
1463
|
}
|
|
1464
|
+
// Emit-override specializations queued by the emit sites above (a
|
|
1465
|
+
// body can queue more — the super-forward chain — and generic
|
|
1466
|
+
// instances of its own; the joint fixpoint covers both).
|
|
1467
|
+
while (es < this.emitSpecQueue.length) {
|
|
1468
|
+
try {
|
|
1469
|
+
const fn = lowerEmitOverrideSpec(this, this.emitSpecQueue[es++]);
|
|
1470
|
+
if (fn)
|
|
1471
|
+
functions.push(fn);
|
|
1472
|
+
}
|
|
1473
|
+
catch (e) {
|
|
1474
|
+
if (!(e instanceof PoisonError))
|
|
1475
|
+
throw e;
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1393
1478
|
}
|
|
1394
1479
|
}
|
|
1395
1480
|
// Lambdas lifted while lowering any of the above (plus synthetic
|
|
@@ -1707,9 +1792,11 @@ export class Lowerer {
|
|
|
1707
1792
|
// the joint fixpoint).
|
|
1708
1793
|
let instLowered = 0;
|
|
1709
1794
|
let clsInstLowered = 0;
|
|
1795
|
+
let specLowered = 0;
|
|
1710
1796
|
const drainInstances = () => {
|
|
1711
1797
|
while (instLowered < this.instantiationQueue.length ||
|
|
1712
|
-
clsInstLowered < this.genericClassInstances.length
|
|
1798
|
+
clsInstLowered < this.genericClassInstances.length ||
|
|
1799
|
+
specLowered < this.emitSpecQueue.length) {
|
|
1713
1800
|
while (instLowered < this.instantiationQueue.length) {
|
|
1714
1801
|
const { info, inst } = this.instantiationQueue[instLowered++];
|
|
1715
1802
|
// Body-level poisons skip the instance here too (the emit pass
|
|
@@ -1726,6 +1813,18 @@ export class Lowerer {
|
|
|
1726
1813
|
while (clsInstLowered < this.genericClassInstances.length) {
|
|
1727
1814
|
this.lowerClassMembers(this.genericClassInstances[clsInstLowered++]);
|
|
1728
1815
|
}
|
|
1816
|
+
// Emit-override specialization bodies fire edges of their own
|
|
1817
|
+
// (the super-forward chain, closures, generic calls) — lower them
|
|
1818
|
+
// for discovery exactly like generic instances.
|
|
1819
|
+
while (specLowered < this.emitSpecQueue.length) {
|
|
1820
|
+
try {
|
|
1821
|
+
lowerEmitOverrideSpec(this, this.emitSpecQueue[specLowered++]);
|
|
1822
|
+
}
|
|
1823
|
+
catch (e) {
|
|
1824
|
+
if (!(e instanceof PoisonError))
|
|
1825
|
+
throw e;
|
|
1826
|
+
}
|
|
1827
|
+
}
|
|
1729
1828
|
}
|
|
1730
1829
|
};
|
|
1731
1830
|
parts.forEach((fp) => {
|
|
@@ -2361,6 +2460,21 @@ export class Lowerer {
|
|
|
2361
2460
|
return expr;
|
|
2362
2461
|
}
|
|
2363
2462
|
if (expr.type.kind === "jsval" && expected.kind !== "jsval") {
|
|
2463
|
+
// The jsval→DOM crossing (the world unification's engine-handle
|
|
2464
|
+
// kind): an 'any'-typed engine value flowing into an 'unknown'/
|
|
2465
|
+
// 'object'/JS-residue slot wraps BY REFERENCE as the DOM's island
|
|
2466
|
+
// kind — engine scalars normalize to native DOM kinds at wrap time,
|
|
2467
|
+
// typeof/truthiness/String()/=== route to the engine, un-armed DOM
|
|
2468
|
+
// walks fence loudly, and the value unwraps back identity-preserved
|
|
2469
|
+
// (scr_jsval_from_dyn). Monotone under evolution/widening: a value
|
|
2470
|
+
// wraps once at its first dyn edge and stays valid through every
|
|
2471
|
+
// subsequent dyn slot; narrowing never changes representation.
|
|
2472
|
+
// This wrap RETIRES the silent-wrong-answer fence-closure box for
|
|
2473
|
+
// jsval members of DOM object literals (lowerDynObjectLiteral's
|
|
2474
|
+
// coercion lands here first).
|
|
2475
|
+
if (expected.kind === "dyn") {
|
|
2476
|
+
return { kind: "dynFromJsval", value: expr, type: DYN, loc: expr.loc };
|
|
2477
|
+
}
|
|
2364
2478
|
// The exit set: everything round-trippable, plus bare undefined-armed
|
|
2365
2479
|
// unions of JSON-safe data arms (the engine's undefined takes the
|
|
2366
2480
|
// undefined arm before the JSON detour) — canExitIslandToType.
|
|
@@ -5161,6 +5275,11 @@ export class Lowerer {
|
|
|
5161
5275
|
if (value.kind === "unitLit") {
|
|
5162
5276
|
return { kind: "dynFrom", value, type: DYN, loc: value.loc };
|
|
5163
5277
|
}
|
|
5278
|
+
// An ISLAND ('any') value: the by-reference jsval→DOM wrap — the same
|
|
5279
|
+
// edge coerceToExpected converts (dyn slots accept engine values).
|
|
5280
|
+
if (value.type.kind === "jsval") {
|
|
5281
|
+
return { kind: "dynFromJsval", value, type: DYN, loc: value.loc };
|
|
5282
|
+
}
|
|
5164
5283
|
if (!this.dynConvertible(value.type)) {
|
|
5165
5284
|
this.unsupported("SC1100", node, `storing '${this.fmt(value.type)}' values under an 'unknown'-valued index signature (only numbers, strings, booleans, and JSON-safe records/arrays/unions convert)`);
|
|
5166
5285
|
}
|
|
@@ -6116,7 +6235,7 @@ export class Lowerer {
|
|
|
6116
6235
|
lowerDestructuringAssignParts(target, rhs, loc) {
|
|
6117
6236
|
return lowerDestructuringAssignParts(this, target, rhs, loc);
|
|
6118
6237
|
}
|
|
6119
|
-
lowerBindingPattern(pattern, srcRef, srcType, isLet, out) {
|
|
6238
|
+
lowerBindingPattern(pattern, srcRef, srcType, isLet, out, dynSpell) {
|
|
6120
6239
|
// An ISLAND source (`const { readFileSync } = await import("fs")` —
|
|
6121
6240
|
// a namespace handle, or any 'any'-typed object): each bound name is
|
|
6122
6241
|
// an engine property read, mirroring the island property-read rule —
|
|
@@ -6180,7 +6299,7 @@ export class Lowerer {
|
|
|
6180
6299
|
}
|
|
6181
6300
|
return;
|
|
6182
6301
|
}
|
|
6183
|
-
return lowerBindingPattern(this, pattern, srcRef, srcType, isLet, out);
|
|
6302
|
+
return lowerBindingPattern(this, pattern, srcRef, srcType, isLet, out, dynSpell);
|
|
6184
6303
|
}
|
|
6185
6304
|
checkBindingElement(el, allowDefault = false) {
|
|
6186
6305
|
return checkBindingElement(this, el, allowDefault);
|
|
@@ -6248,7 +6367,12 @@ export class Lowerer {
|
|
|
6248
6367
|
// out-of-block read would split the variable in two) — vars take the
|
|
6249
6368
|
// standard path and its own fences.
|
|
6250
6369
|
(ts.getCombinedNodeFlags(decl) & ts.NodeFlags.BlockScoped) !== 0 &&
|
|
6251
|
-
islandCandidate(decl.initializer)
|
|
6370
|
+
islandCandidate(decl.initializer) &&
|
|
6371
|
+
// createRequire's plumbing decls are COMPILE-TIME erasures (the
|
|
6372
|
+
// require binding and its builtin-namespace bindings) — never
|
|
6373
|
+
// island values; the standard path's skips own them.
|
|
6374
|
+
!createRequireBindingDecl(this, decl.name, decl.initializer) &&
|
|
6375
|
+
!createRequireNamespaceDecl(this, decl.name, decl.initializer)) {
|
|
6252
6376
|
const mapped = this.mapTypeOf(this.typeOf(decl.name));
|
|
6253
6377
|
const handleOnly = mapped === null ||
|
|
6254
6378
|
(mapped.kind !== "jsval" &&
|
|
@@ -6261,6 +6385,16 @@ export class Lowerer {
|
|
|
6261
6385
|
const local = this.declareLocal(decl.name, decl.name.text, JSVAL, isLet);
|
|
6262
6386
|
return { kind: "varDecl", localId: local.id, init, loc: locOf(decl) };
|
|
6263
6387
|
}
|
|
6388
|
+
// The CHECKED-DYNAMIC twin of the handle rescue (the runtime-world
|
|
6389
|
+
// local rule): an unmappable declared type over a dyn initializer
|
|
6390
|
+
// (`const first = plugins[0]` — the checker spells 'string |
|
|
6391
|
+
// object' while the read is a DOM keyed read) keeps the binding
|
|
6392
|
+
// dyn; typed use sites ride validated extractions and the routed
|
|
6393
|
+
// engine ops, exactly the JSON.parse-binding story.
|
|
6394
|
+
if (mapped === null && init.type.kind === "dyn") {
|
|
6395
|
+
const local = this.declareLocal(decl.name, decl.name.text, DYN, isLet);
|
|
6396
|
+
return { kind: "varDecl", localId: local.id, init, loc: locOf(decl) };
|
|
6397
|
+
}
|
|
6264
6398
|
if (mapped === null)
|
|
6265
6399
|
this.badType(decl.name, this.typeOf(decl.name));
|
|
6266
6400
|
// A mappable declared type with a non-island initializer: the
|
|
@@ -6629,10 +6763,42 @@ export class Lowerer {
|
|
|
6629
6763
|
if (!decl)
|
|
6630
6764
|
return null;
|
|
6631
6765
|
// The CommonJS twin: `const fs = require("fs")` binds the same
|
|
6632
|
-
// namespace surface as `import * as fs from "node:fs"
|
|
6766
|
+
// namespace surface as `import * as fs from "node:fs"` — and the
|
|
6767
|
+
// createRequire spelling (`const fs = require("node:fs")` through a
|
|
6768
|
+
// createRequire binding, the fallback-typed cast idiom stripped)
|
|
6769
|
+
// binds it too.
|
|
6633
6770
|
if (ts.isVariableDeclaration(decl) && ts.isIdentifier(decl.name) && decl.initializer) {
|
|
6634
6771
|
const spec = requireSpecOf(decl.initializer);
|
|
6635
|
-
|
|
6772
|
+
if (spec !== null)
|
|
6773
|
+
return canonicalBuiltinModule(spec);
|
|
6774
|
+
const init = stripTypeCasts(decl.initializer);
|
|
6775
|
+
if (ts.isCallExpression(init)) {
|
|
6776
|
+
const cr = createRequireSpecOf(this, init);
|
|
6777
|
+
if (cr !== null && cr.spec !== null)
|
|
6778
|
+
return canonicalBuiltinModule(cr.spec);
|
|
6779
|
+
}
|
|
6780
|
+
return null;
|
|
6781
|
+
}
|
|
6782
|
+
// A DESTRUCTURED sub-namespace binding — `const { promises } =
|
|
6783
|
+
// fs` / `= require('fs')`: the member is itself a supported module
|
|
6784
|
+
// ("fs/promises"), so the binding carries that module's namespace
|
|
6785
|
+
// surface. canonicalBuiltinModule gates the composition (an
|
|
6786
|
+
// ordinary destructured FUNCTION binding composes to an unknown
|
|
6787
|
+
// name and answers null — builtinImportOf owns those).
|
|
6788
|
+
if (ts.isBindingElement(decl) && ts.isObjectBindingPattern(decl.parent) &&
|
|
6789
|
+
ts.isVariableDeclaration(decl.parent.parent) && decl.parent.parent.initializer !== undefined &&
|
|
6790
|
+
decl.propertyName === undefined && decl.initializer === undefined) {
|
|
6791
|
+
const name = decl.name;
|
|
6792
|
+
if (name === undefined || !ts.isIdentifier(name))
|
|
6793
|
+
return null;
|
|
6794
|
+
const init = decl.parent.parent.initializer;
|
|
6795
|
+
const spec = requireSpecOf(init);
|
|
6796
|
+
const outer = spec !== null
|
|
6797
|
+
? canonicalBuiltinModule(spec)
|
|
6798
|
+
: ts.isIdentifier(init) ? this.builtinNamespaceModuleOf(init) : null;
|
|
6799
|
+
if (outer !== null)
|
|
6800
|
+
return canonicalBuiltinModule(`${outer}/${name.text}`);
|
|
6801
|
+
return null;
|
|
6636
6802
|
}
|
|
6637
6803
|
}
|
|
6638
6804
|
// The INLINE CommonJS spelling: `require("cluster").isPrimary` — the
|
|
@@ -6644,6 +6810,17 @@ export class Lowerer {
|
|
|
6644
6810
|
if (spec !== null)
|
|
6645
6811
|
return canonicalBuiltinModule(spec);
|
|
6646
6812
|
}
|
|
6813
|
+
// The createRequire spelling of the same inline form:
|
|
6814
|
+
// `require("node:path").join(...)` through a createRequire binding
|
|
6815
|
+
// (the fallback-typed cast idiom strips: `(require("x") as T).m`).
|
|
6816
|
+
{
|
|
6817
|
+
const inner = stripTypeCasts(expr);
|
|
6818
|
+
if (ts.isCallExpression(inner)) {
|
|
6819
|
+
const cr = createRequireSpecOf(this, inner);
|
|
6820
|
+
if (cr !== null && cr.spec !== null)
|
|
6821
|
+
return canonicalBuiltinModule(cr.spec);
|
|
6822
|
+
}
|
|
6823
|
+
}
|
|
6647
6824
|
if (ts.isIdentifier(expr)) {
|
|
6648
6825
|
const symbol = this.checker.getSymbolAtLocation(expr);
|
|
6649
6826
|
const decl = symbol ? this.checker.declarationsOf(symbol)[0] : undefined;
|
|
@@ -6746,6 +6923,12 @@ export class Lowerer {
|
|
|
6746
6923
|
const fsTs = this.lowerFsToUnixTimestampCall(call, bi, locOf(access));
|
|
6747
6924
|
if (fsTs)
|
|
6748
6925
|
return fsTs;
|
|
6926
|
+
// The fs validation-ladder spoke (checked-dynamic lane): misuse of
|
|
6927
|
+
// implemented-namespace members throws Node's typed errors instead
|
|
6928
|
+
// of meeting the table fence.
|
|
6929
|
+
const fsLadder = this.lowerFsLadderCall(call, bi, locOf(access));
|
|
6930
|
+
if (fsLadder)
|
|
6931
|
+
return fsLadder;
|
|
6749
6932
|
const builtinFn = builtinModuleFnOf(this, bi.module, bi.member);
|
|
6750
6933
|
if (!builtinFn) {
|
|
6751
6934
|
this.noLowering(`${bi.module}.${bi.member}`, call, builtinFenceHintOf(bi.module, bi.member), this.checker.getSymbolAtLocation(access.name));
|
|
@@ -6784,6 +6967,11 @@ export class Lowerer {
|
|
|
6784
6967
|
const c = builtinModuleConstOf(this, bi.module, bi.member);
|
|
6785
6968
|
if (c !== undefined)
|
|
6786
6969
|
return builtinConstLit(c, loc);
|
|
6970
|
+
// module.builtinModules through a namespace binding — the baked
|
|
6971
|
+
// Node v24 list, a fresh string[] per read.
|
|
6972
|
+
if (bi.module === "module" && bi.member === "builtinModules") {
|
|
6973
|
+
return builtinModulesArrayLit(loc);
|
|
6974
|
+
}
|
|
6787
6975
|
if (bi.member === "constants" && bi.module === "fs") {
|
|
6788
6976
|
// A bare `fs.constants` read (not one of the baked bits above).
|
|
6789
6977
|
this.noLowering(`fs.constants`, expr, "F_OK, R_OK, W_OK, and X_OK are the lowered constants");
|
|
@@ -6799,6 +6987,9 @@ export class Lowerer {
|
|
|
6799
6987
|
lowerFsToUnixTimestampCall(expr, bi, loc) {
|
|
6800
6988
|
return lowerFsToUnixTimestampCall(this, expr, bi, loc);
|
|
6801
6989
|
}
|
|
6990
|
+
lowerFsLadderCall(expr, bi, loc) {
|
|
6991
|
+
return lowerFsLadderCall(this, expr, bi, loc);
|
|
6992
|
+
}
|
|
6802
6993
|
lowerChildArgsArg(node, loc) {
|
|
6803
6994
|
return lowerChildArgsArg(this, node, loc);
|
|
6804
6995
|
}
|