@scriptc/compiler 0.0.10 → 0.0.12
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 +63 -15
- package/ambient/scriptc.d.ts +2 -2
- package/dist/backend/cc.d.ts +2 -2
- package/dist/backend/emission/emit-async.js +1 -1
- package/dist/backend/emission/emit-exprs.js +131 -54
- package/dist/backend/emission/emit-exprs.js.map +1 -1
- package/dist/backend/emission/emit-island.js +1 -1
- package/dist/backend/emission/emit-shapes.js +1 -1
- package/dist/backend/emission/emit-walkers.d.ts +14 -14
- package/dist/backend/emission/emit-walkers.js +44 -44
- package/dist/backend/emission/emit-walkers.js.map +1 -1
- package/dist/backend/emission/emitter.d.ts +3 -3
- package/dist/backend/emission/emitter.js +33 -9
- package/dist/backend/emission/emitter.js.map +1 -1
- package/dist/backend/emission/may-throw.js +1 -1
- package/dist/backend/llvm/dyn.d.ts +10 -10
- package/dist/backend/llvm/dyn.js +26 -26
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.js +156 -47
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/shapes.js +1 -1
- package/dist/backend/llvm/walkers.js +2 -2
- package/dist/backend/llvm/walkers.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 +21 -8
- package/dist/diagnostics/diagnostic.js +48 -14
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/frontend/lowering/lib-boundary.js +5 -5
- package/dist/frontend/lowering/lib-boundary.js.map +1 -1
- package/dist/frontend/lowering/lower-assert.js +12 -12
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-builtins.d.ts +63 -7
- package/dist/frontend/lowering/lower-builtins.js +327 -35
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +4 -4
- package/dist/frontend/lowering/lower-calls.js +104 -70
- 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 +82 -6
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.d.ts +9 -5
- package/dist/frontend/lowering/lower-containers.js +88 -26
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-emitter.d.ts +70 -3
- package/dist/frontend/lowering/lower-emitter.js +438 -31
- package/dist/frontend/lowering/lower-emitter.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +87 -12
- package/dist/frontend/lowering/lower-exprs.js +630 -125
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.js +5 -5
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-island.js +12 -3
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.d.ts +8 -5
- package/dist/frontend/lowering/lower-modules.js +157 -63
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-namespaces.d.ts +24 -0
- package/dist/frontend/lowering/lower-namespaces.js +158 -16
- package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
- package/dist/frontend/lowering/lower-server.js +11 -11
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.d.ts +1 -1
- package/dist/frontend/lowering/lower-stmts.js +271 -36
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.js +171 -20
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +27 -10
- package/dist/frontend/lowering/lowerer.js +156 -54
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/surfaces.d.ts +44 -0
- package/dist/frontend/lowering/surfaces.js +236 -5
- 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 +145 -136
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/shared.d.ts +1 -1
- package/dist/frontend/shared.js +8 -8
- package/dist/frontend/shared.js.map +1 -1
- package/dist/frontend/types.d.ts +2 -2
- package/dist/frontend/types.js +15 -15
- package/dist/frontend/types.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +169 -5
- package/dist/index.js.map +1 -1
- package/dist/ir/nodes.d.ts +174 -106
- package/dist/ir/nodes.js +69 -24
- package/dist/ir/nodes.js.map +1 -1
- package/dist/ir/validate.js +55 -36
- package/dist/ir/validate.js.map +1 -1
- package/dist/library/fence-eval.js +12 -2
- package/dist/library/fence-eval.js.map +1 -1
- package/dist/library/int-infer.d.ts +119 -0
- package/dist/library/int-infer.js +1314 -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 +34 -5
- package/dist/library/profile.js +77 -13
- package/dist/library/profile.js.map +1 -1
- package/dist/library/sidecar-validate.js +1 -1
- package/dist/library/sidecar-validate.js.map +1 -1
- package/dist/library/sidecar.d.ts +24 -1
- package/dist/library/sidecar.js +163 -16
- package/dist/library/sidecar.js.map +1 -1
- package/package.json +2 -2
- package/surface-manifest.json +210 -12
|
@@ -98,7 +98,7 @@ export declare function hoistVarBinding(L: Lowerer, symbol: ts.Symbol, nameNode:
|
|
|
98
98
|
* such reads `undefined`, never a TDZ error, so the hoisted slot must
|
|
99
99
|
* hold `undefined` from function entry — which is only honest for
|
|
100
100
|
* undefined-armed union types (the interned arm) and checked-dynamic
|
|
101
|
-
* bindings (the
|
|
101
|
+
* bindings (the dyn undefined). Everything else returns false
|
|
102
102
|
* and the reference lands on the named fence in rejectUnresolvedSymbol:
|
|
103
103
|
* a slot of a narrower type has no bit pattern for the `undefined` Node
|
|
104
104
|
* would yield if the capture ran early, and guessing "it won't" is the
|
|
@@ -10,7 +10,7 @@ import { enforceLibBoundary } from "./lib-boundary.js";
|
|
|
10
10
|
import { cjsExportAssignmentOf, cjsExportDiscardReason, cjsExportTargetLiteral, isCjsJsFile, isJsSourceFile, locOf, requireSpecOf } from "../program.js";
|
|
11
11
|
import { COMPOUND_ASSIGN_OPS, STR_METHODS, UNSUPPORTED_STMT, isStdlibMember, sideEffectFreeOptionValue, stdlibGlobalAliasDecl, stdlibGlobalNameOf } from "./surfaces.js";
|
|
12
12
|
import { isProvenanceSourceFile } from "../provenance-registry.js";
|
|
13
|
-
import { ambientUndefVarRootOf, lowerImportEquals, nsUndefRead, nsWritableTarget } from "./lower-namespaces.js";
|
|
13
|
+
import { ambientUndefVarRootOf, lowerImportEquals, nsUndefRead, nsWritableTarget, trapDeclRootOf } from "./lower-namespaces.js";
|
|
14
14
|
import { expandoWritableTarget, lowerExpandoAssignStmt } from "./lower-expando.js";
|
|
15
15
|
import { lowerForOfArrayIter, lowerForOfMap, lowerForOfSearchParams, lowerForOfSet, objectIterOverIndexShape, strCharsCall } from "./lower-containers.js";
|
|
16
16
|
import { bindingContextualGenericFnNodeOf, bindingGenericFnAliasInfoOf, bindingGenericFnInfoOf, bindingGenericFnNodeOf, deadUnmappableBinding, implicitLocalFnInfoOf, implicitLocalFnNodeOf, nullishExprUnitOf, nullishGenericBindingUnitOf, recordKeysArrayCall } from "./lower-calls.js";
|
|
@@ -18,9 +18,9 @@ import { isMixinFnBinding, mixinResultBindingClassOf } from "./lower-mixins.js";
|
|
|
18
18
|
import { genericIfaceBindingKeepsClass } from "./lower-classes.js";
|
|
19
19
|
import { lowerStreamUnderscoreAssign, streamClassAliasDecl, streamSidesOf } from "./lower-stream.js";
|
|
20
20
|
import { lowerHttpResPropertyAssignment, lowerServerCloseOverrideAssignment } from "./lower-server.js";
|
|
21
|
-
import { builtinMemberRequireDecl, builtinNamespaceDestructureModuleOf } from "./lower-builtins.js";
|
|
21
|
+
import { builtinMemberRequireDecl, builtinNamespaceDestructureModuleOf, createRequireBindingDecl, createRequireCalleeFileOf, createRequireNamespaceDecl } from "./lower-builtins.js";
|
|
22
22
|
import { lowerEnumDeclaration } from "./lower-enums.js";
|
|
23
|
-
import { abstractPropertyDeclOf, aliasTypeofNarrows, probeLower, pureReemittable, symbolFieldInfo } from "./lower-exprs.js";
|
|
23
|
+
import { abstractPropertyDeclOf, aliasTypeofNarrows, isMatchSliceType, lowerGroupsProjection, matchResultNamedGroupsOf, probeLower, pureReemittable, symbolFieldInfo } from "./lower-exprs.js";
|
|
24
24
|
import { checkerPanicDiag, isCheckerPanic, requiresDynamicDiag } from "../../diagnostics/diagnostic.js";
|
|
25
25
|
import { isUnitOnlyTsType, unitOnlyUnion } from "../types.js";
|
|
26
26
|
import { canonicalBuiltinModule, isRelativeSpecifier } from "../shared.js";
|
|
@@ -486,7 +486,7 @@ export function hoistVarBinding(L, symbol, nameNode) {
|
|
|
486
486
|
const local = { id: `${name}.${count}`, name, type, mutable: true };
|
|
487
487
|
L.ctx.locals.push(local);
|
|
488
488
|
L.ctx.scopes[0].set(symbol, local);
|
|
489
|
-
// A checked-dynamic slot holds the
|
|
489
|
+
// A checked-dynamic slot holds the dyn undefined (a NULL dyn is a
|
|
490
490
|
// trap); everything else rides unassignedSlotInit (interned union arm,
|
|
491
491
|
// engine undefined for jsval).
|
|
492
492
|
const wrapped = type.kind === "dyn" ? dynUndefinedExpr(locOf(nameNode)) : L.unassignedSlotInit(type, locOf(nameNode));
|
|
@@ -502,7 +502,7 @@ export function hoistVarBinding(L, symbol, nameNode) {
|
|
|
502
502
|
* such reads `undefined`, never a TDZ error, so the hoisted slot must
|
|
503
503
|
* hold `undefined` from function entry — which is only honest for
|
|
504
504
|
* undefined-armed union types (the interned arm) and checked-dynamic
|
|
505
|
-
* bindings (the
|
|
505
|
+
* bindings (the dyn undefined). Everything else returns false
|
|
506
506
|
* and the reference lands on the named fence in rejectUnresolvedSymbol:
|
|
507
507
|
* a slot of a narrower type has no bit pattern for the `undefined` Node
|
|
508
508
|
* would yield if the capture ran early, and guessing "it won't" is the
|
|
@@ -536,7 +536,7 @@ export function predeclareForwardVar(L, symbol) {
|
|
|
536
536
|
const ctx = owner.ctx;
|
|
537
537
|
// Only a slot that can hold `undefined` can carry the pre-
|
|
538
538
|
// initialization reads: an undefined-armed union (the interned arm),
|
|
539
|
-
// a checked-dynamic binding (the
|
|
539
|
+
// a checked-dynamic binding (the dyn undefined), or a jsval 'any'
|
|
540
540
|
// binding (the engine's undefined).
|
|
541
541
|
const type = varBindingType(L, nameNode);
|
|
542
542
|
if (!type)
|
|
@@ -757,7 +757,7 @@ export function lowerStmt(L, stmt) {
|
|
|
757
757
|
// A bare `return;` in a union-returning function yields undefined
|
|
758
758
|
// (JS), which the undefined arm carries — tsc only allows the bare
|
|
759
759
|
// form when the return type includes undefined/void. A CHECKED-
|
|
760
|
-
// DYNAMIC return slot holds the
|
|
760
|
+
// DYNAMIC return slot holds the dyn undefined directly (the
|
|
761
761
|
// appendImplicitUndefinedReturn rule). What remains is JS-only —
|
|
762
762
|
// a JSDoc return claim the body contradicts (ms's parse: `@return
|
|
763
763
|
// {Number}` with a bare early `return;`): no undefined fits the
|
|
@@ -819,11 +819,11 @@ export function lowerStmt(L, stmt) {
|
|
|
819
819
|
const value = L.lowerExpr(stmt.expression);
|
|
820
820
|
if (value.type.kind === "void")
|
|
821
821
|
L.badType(stmt.expression, L.typeOf(stmt.expression));
|
|
822
|
-
// A dyn throw rides the REF cell arm (scr_throw_ref over the
|
|
822
|
+
// A dyn throw rides the REF cell arm (scr_throw_ref over the checked-dynamic tree
|
|
823
823
|
// node — identity preserved through catch bindings, caughtToDyn
|
|
824
824
|
// passes it back by reference). The JS-lane traced-call shape:
|
|
825
|
-
// `throw err` where err arrived as a
|
|
826
|
-
// narrowing over the payload stays false (the
|
|
825
|
+
// `throw err` where err arrived as a dyn argument. instanceof
|
|
826
|
+
// narrowing over the payload stays false (the checked-dynamic tree's %error encoding
|
|
827
827
|
// is not a hierarchy object — SEMANTICS.md).
|
|
828
828
|
return { kind: "throw", value, loc: locOf(stmt) };
|
|
829
829
|
}
|
|
@@ -1018,7 +1018,7 @@ export function lowerDestructuringDecl(L, decl, isLet) {
|
|
|
1018
1018
|
let init = L.lowerExpr(decl.initializer);
|
|
1019
1019
|
// A TS `any`-origin source whose lowered value is NOT a destructurable
|
|
1020
1020
|
// shape (`var { x } = <any>0` — the cast erases to the f64; a dyn
|
|
1021
|
-
// value — the
|
|
1021
|
+
// value — the checked-dynamic tree has no destructure): JS reads the properties off
|
|
1022
1022
|
// whatever the value is (a number answers undefined) — engine
|
|
1023
1023
|
// semantics, the dynamic-family fence. Record and array sources fall
|
|
1024
1024
|
// through to their lowerings, island handles to theirs (--dynamic
|
|
@@ -1103,6 +1103,39 @@ export function lowerDestructuringDecl(L, decl, isLet) {
|
|
|
1103
1103
|
init = { kind: "unionNarrow", unionId: init.type.unionId, tag, value: uref, type: arm, loc };
|
|
1104
1104
|
}
|
|
1105
1105
|
}
|
|
1106
|
+
// `const { groups } = re.exec(s)!` / `const { groups: { year } } = m`
|
|
1107
|
+
// — every pattern element binds `groups` off a MATCH SLICE whose
|
|
1108
|
+
// regex is statically known: the slice has no record shape of its
|
|
1109
|
+
// own, so the groups projection (lowerGroupsProjection — the same
|
|
1110
|
+
// record `m.groups` reads produce) wraps one level in a synthesized
|
|
1111
|
+
// `{ groups: ... }` record and the ordinary record destructure below
|
|
1112
|
+
// serves the pattern — aliases and nested patterns included. Only
|
|
1113
|
+
// named-group regexes take the wrap: a group-less regex destructures
|
|
1114
|
+
// `groups: undefined` in Node (a nested pattern then throws), which
|
|
1115
|
+
// the fence reports honestly instead.
|
|
1116
|
+
if (ts.isObjectBindingPattern(decl.name) &&
|
|
1117
|
+
decl.name.elements.length > 0 &&
|
|
1118
|
+
isMatchSliceType(L, init.type) &&
|
|
1119
|
+
decl.name.elements.every((el) => {
|
|
1120
|
+
if (el.dotDotDotToken !== undefined || el.name === undefined)
|
|
1121
|
+
return false;
|
|
1122
|
+
const prop = el.propertyName;
|
|
1123
|
+
if (prop === undefined)
|
|
1124
|
+
return ts.isIdentifier(el.name) && el.name.text === "groups";
|
|
1125
|
+
return (ts.isIdentifier(prop) || ts.isStringLiteral(prop)) && prop.text === "groups";
|
|
1126
|
+
})) {
|
|
1127
|
+
const groups = matchResultNamedGroupsOf(L, decl.initializer);
|
|
1128
|
+
if (groups !== null && groups.length > 0) {
|
|
1129
|
+
const proj = lowerGroupsProjection(L, init, groups, loc);
|
|
1130
|
+
const outerShape = L.shapes.intern([{ name: "groups", type: proj.type }], false, undefined, ["groups"]);
|
|
1131
|
+
init = {
|
|
1132
|
+
kind: "recordLit",
|
|
1133
|
+
fields: [{ name: "groups", value: proj }],
|
|
1134
|
+
type: { kind: "record", shapeId: outerShape },
|
|
1135
|
+
loc,
|
|
1136
|
+
};
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1106
1139
|
const tmp = L.declareHiddenLocal("%destr", init.type);
|
|
1107
1140
|
out.push({ kind: "varDecl", localId: tmp.id, init, loc });
|
|
1108
1141
|
// V8's destructuring TypeError spells STATIC sources: an identifier
|
|
@@ -1243,16 +1276,16 @@ export function lowerBindingPattern(L, pattern, srcRef, srcType, isLet, out, dyn
|
|
|
1243
1276
|
L.lowerBindingPattern(pattern, () => ({ kind: "varRef", localId: chars.id, type: charsT, loc }), charsT, isLet, out);
|
|
1244
1277
|
return;
|
|
1245
1278
|
}
|
|
1246
|
-
// DYN sources (`const [a, b] = d` over a
|
|
1279
|
+
// DYN sources (`const [a, b] = d` over a dyn value, `([_, code]) =>`
|
|
1247
1280
|
// params destructuring dyn callback arguments — the suite harness's
|
|
1248
1281
|
// _expectWarning shapes): the source packs ONCE through the spread
|
|
1249
1282
|
// walk (dyn.iterPack — arrays element-by-element, strings by code
|
|
1250
1283
|
// point, bytes by byte; every other kind throws V8's destructuring
|
|
1251
1284
|
// TypeError, the compile-time spelling when the source has one),
|
|
1252
1285
|
// then positions bind the pack's index keys as dyn values — reads
|
|
1253
|
-
// past the end bind undefined, exactly JS. Defaults fire on the
|
|
1286
|
+
// past the end bind undefined, exactly JS. Defaults fire on the checked-dynamic tree
|
|
1254
1287
|
// undefined (JS's rule); rest elements keep the fence (surplus
|
|
1255
|
-
// packing over the
|
|
1288
|
+
// packing over the checked-dynamic tree needs a slice the IR does not spell yet).
|
|
1256
1289
|
if (srcType.kind === "dyn") {
|
|
1257
1290
|
const loc = locOf(pattern);
|
|
1258
1291
|
const pack = L.declareHiddenLocal("%dpack", DYN);
|
|
@@ -1283,14 +1316,14 @@ export function lowerBindingPattern(L, pattern, srcRef, srcType, isLet, out, dyn
|
|
|
1283
1316
|
loc: elLoc,
|
|
1284
1317
|
};
|
|
1285
1318
|
if (el.initializer) {
|
|
1286
|
-
// The default fires exactly on the
|
|
1287
|
-
// its value converting into the
|
|
1319
|
+
// The default fires exactly on the dyn undefined (JS's rule),
|
|
1320
|
+
// its value converting into the checked-dynamic tree like any dyn-slot value.
|
|
1288
1321
|
const rl = L.declareHiddenLocal("%delem", DYN);
|
|
1289
1322
|
out.push({ kind: "varDecl", localId: rl.id, init: value, loc: elLoc });
|
|
1290
1323
|
const ref = () => ({ kind: "varRef", localId: rl.id, type: DYN, loc: elLoc });
|
|
1291
1324
|
const dflt = L.coerceToExpected(L.lowerExpr(el.initializer), DYN);
|
|
1292
1325
|
if (dflt.type.kind !== "dyn") {
|
|
1293
|
-
L.unsupported("SC1031", el.initializer, `defaults of '${L.fmt(dflt.type)}' type over checked-dynamic sources (the value cannot convert into the
|
|
1326
|
+
L.unsupported("SC1031", el.initializer, `defaults of '${L.fmt(dflt.type)}' type over checked-dynamic sources (the value cannot convert into the checked-dynamic tree)`);
|
|
1294
1327
|
}
|
|
1295
1328
|
value = {
|
|
1296
1329
|
kind: "ternary",
|
|
@@ -1586,6 +1619,29 @@ export function lowerBindingPattern(L, pattern, srcRef, srcType, isLet, out, dyn
|
|
|
1586
1619
|
continue;
|
|
1587
1620
|
}
|
|
1588
1621
|
const fieldType = shape.fields.find((f) => f.name === propName)?.type;
|
|
1622
|
+
if (!fieldType && shape.indexValue !== undefined && !shape.tuple) {
|
|
1623
|
+
// An UNDECLARED key of an INDEX-SIGNATURE shape (`const { m, n, p }
|
|
1624
|
+
// = ....groups` over `{ [key: string]: string }` — the groups
|
|
1625
|
+
// record, `Record<string, T>` tables generally): the overflow-map
|
|
1626
|
+
// read, exactly the dot access's recordKeyGet — a missing key
|
|
1627
|
+
// traps when the value type carries no undefined arm (the checker
|
|
1628
|
+
// claimed V), or binds the undefined arm (where a default applies
|
|
1629
|
+
// like any field's).
|
|
1630
|
+
const loc = locOf(el);
|
|
1631
|
+
let value = {
|
|
1632
|
+
kind: "recordKeyGet",
|
|
1633
|
+
obj: srcRef(),
|
|
1634
|
+
shapeId: srcType.shapeId,
|
|
1635
|
+
key: { kind: "strLit", value: propName, type: STRING, loc },
|
|
1636
|
+
overflowOnly: true,
|
|
1637
|
+
type: shape.indexValue,
|
|
1638
|
+
loc,
|
|
1639
|
+
};
|
|
1640
|
+
if (el.initializer)
|
|
1641
|
+
value = applyBindingDefault(L, el, value);
|
|
1642
|
+
L.bindPatternTarget(el.name, value, isLet, out);
|
|
1643
|
+
continue;
|
|
1644
|
+
}
|
|
1589
1645
|
if (!fieldType) {
|
|
1590
1646
|
// The pattern names a field the source SHAPE does not carry —
|
|
1591
1647
|
// `for (let {x = 1} of [{}])` (signature 08): tsc types the binding
|
|
@@ -2481,7 +2537,7 @@ export function bindPatternTarget(L, name, value, isLet, out) {
|
|
|
2481
2537
|
// a pattern binding whose VALUE lowered checked-dynamic stays dyn
|
|
2482
2538
|
// where the checker spells an island-world type (`function f({
|
|
2483
2539
|
// plugins = [] } = {})` over a JSDoc '(string | object)[]=' member —
|
|
2484
|
-
// the read is a
|
|
2540
|
+
// the read is a dyn keyed read whose members may be wrapped island
|
|
2485
2541
|
// values) or a type with no mapping at all (the varDecl rule's
|
|
2486
2542
|
// unmappable-declared-type stance, `string | object` bindings
|
|
2487
2543
|
// included). Marshaling here would fence or deep-copy; the value's
|
|
@@ -2566,8 +2622,10 @@ export function lowerVarDecl(L, decl, isLet) {
|
|
|
2566
2622
|
// statement lowers to exactly that throw; the binding registers as a
|
|
2567
2623
|
// trap (references lower to the same never-reached shape), and no
|
|
2568
2624
|
// storage or type mapping is needed for a value that never exists.
|
|
2569
|
-
|
|
2570
|
-
|
|
2625
|
+
// Written bindings keep ordinary storage (trapDeclRootOf) — the
|
|
2626
|
+
// initializer read still lowers to the root's throw below.
|
|
2627
|
+
{
|
|
2628
|
+
const root = trapDeclRootOf(L, decl);
|
|
2571
2629
|
if (root !== null) {
|
|
2572
2630
|
for (const nameNode of boundIdentifiersOf(decl.name)) {
|
|
2573
2631
|
const sym = L.checker.getSymbolAtLocation(nameNode);
|
|
@@ -2631,6 +2689,17 @@ export function lowerVarDecl(L, decl, isLet) {
|
|
|
2631
2689
|
// skipped its global by the same test).
|
|
2632
2690
|
if (builtinMemberRequireDecl(decl.name, decl.initializer))
|
|
2633
2691
|
return null;
|
|
2692
|
+
// `const require = createRequire(import.meta.url)` — compile-time
|
|
2693
|
+
// plumbing: each call through the binding resolves per site
|
|
2694
|
+
// (lowerCreateRequireCall); no storage, no code (collectGlobals
|
|
2695
|
+
// skipped its global by the same test).
|
|
2696
|
+
if (!isLet && createRequireBindingDecl(L, decl.name, decl.initializer))
|
|
2697
|
+
return null;
|
|
2698
|
+
// `const fs = require("node:fs")` through that binding — a builtin
|
|
2699
|
+
// namespace import in const clothing: alias plumbing, no storage
|
|
2700
|
+
// (builtinNamespaceModuleOf resolves member uses).
|
|
2701
|
+
if (!isLet && createRequireNamespaceDecl(L, decl.name, decl.initializer))
|
|
2702
|
+
return null;
|
|
2634
2703
|
// `const { NGHTTP2_CANCEL } = http2.constants` — a destructure over
|
|
2635
2704
|
// the baked constants table: alias plumbing, no storage (uses read
|
|
2636
2705
|
// their literals via http2ConstantBindingOf; collectGlobals skipped
|
|
@@ -2721,7 +2790,7 @@ export function lowerVarDecl(L, decl, isLet) {
|
|
|
2721
2790
|
// a loop — must NOT reset the persisting binding.
|
|
2722
2791
|
if (isVarDeclared(decl))
|
|
2723
2792
|
return null;
|
|
2724
|
-
// Checked-dynamic globals hold the
|
|
2793
|
+
// Checked-dynamic globals hold the dyn undefined from their
|
|
2725
2794
|
// declaration statement on; unions and jsval ride
|
|
2726
2795
|
// unassignedSlotInit's arms.
|
|
2727
2796
|
const wrapped = g.type.kind === "dyn" ? dynUndefinedExpr(locOf(decl)) : L.unassignedSlotInit(g.type, locOf(decl));
|
|
@@ -2776,7 +2845,7 @@ export function lowerVarDecl(L, decl, isLet) {
|
|
|
2776
2845
|
const local = L.declareLocal(decl.name, decl.name.text, type, isLet);
|
|
2777
2846
|
// tsc's definite-assignment analysis never guards `any` reads, so
|
|
2778
2847
|
// uninitialized bindings must hold their world's undefined, never
|
|
2779
|
-
// NULL: unions the interned arm, dyn the
|
|
2848
|
+
// NULL: unions the interned arm, dyn the dyn undefined, jsval the
|
|
2780
2849
|
// engine's — all readable immediately, exactly Node.
|
|
2781
2850
|
const init = type.kind === "dyn" ? dynUndefinedExpr(locOf(decl)) : L.unassignedSlotInit(type, locOf(decl));
|
|
2782
2851
|
return { kind: "varDecl", localId: local.id, init, loc: locOf(decl) };
|
|
@@ -2800,7 +2869,7 @@ export function lowerVarDecl(L, decl, isLet) {
|
|
|
2800
2869
|
}
|
|
2801
2870
|
// A dyn initializer under an unmappable declared type (`const ws =
|
|
2802
2871
|
// pkg.workspaces` — the lowering world types the unknown-receiver read
|
|
2803
|
-
// `any`, which a static build cannot hold): the VALUE is a
|
|
2872
|
+
// `any`, which a static build cannot hold): the VALUE is a dyn
|
|
2804
2873
|
// subtree, so the local stays dyn — later narrowing tests and checked
|
|
2805
2874
|
// casts read it like any JSON.parse result.
|
|
2806
2875
|
// `const p = import("./m")` / `const ns = await import("./m")`: the
|
|
@@ -2825,7 +2894,7 @@ export function lowerVarDecl(L, decl, isLet) {
|
|
|
2825
2894
|
// the island-HANDLE local rule's mirror): a binding whose
|
|
2826
2895
|
// INITIALIZER lowered checked-dynamic stays dyn even where the
|
|
2827
2896
|
// checker spells 'any' (`const parsers = options.parsers ?? {}` over
|
|
2828
|
-
// an 'object'-typed bag — the read is a
|
|
2897
|
+
// an 'object'-typed bag — the read is a dyn keyed read). Marshaling
|
|
2829
2898
|
// into the engine here would deep-copy data and sever aliasing; the
|
|
2830
2899
|
// value's world is the honest dispatch, and every use site already
|
|
2831
2900
|
// handles dyn (validated exits, routed engine ops for wrapped
|
|
@@ -2852,7 +2921,7 @@ export function lowerVarDecl(L, decl, isLet) {
|
|
|
2852
2921
|
// pushes of anything non-numeric would fence and typed exits would
|
|
2853
2922
|
// mismatch the checker's evolved reads downstream. The binding is
|
|
2854
2923
|
// checked-dynamic instead (the `let x = {}` stance, and lower-modules'
|
|
2855
|
-
// file-scope evolving-array rule): pushes ride the
|
|
2924
|
+
// file-scope evolving-array rule): pushes ride the dyn array, typed
|
|
2856
2925
|
// exits dynCheck.
|
|
2857
2926
|
if ((type === null || type.kind === "array") && isJsSourceFile(decl.getSourceFile())) {
|
|
2858
2927
|
let initExpr = decl.initializer;
|
|
@@ -2931,6 +3000,15 @@ export function lowerVarDecl(L, decl, isLet) {
|
|
|
2931
3000
|
// bridge is an independent observer of the same settlement).
|
|
2932
3001
|
if (init.type.kind === "jsval" && type.kind === "promise")
|
|
2933
3002
|
type = JSVAL;
|
|
3003
|
+
// An island value under an `any[]`-declared LOCAL spelling stays an
|
|
3004
|
+
// island HANDLE too (the runtime-world rule): the jsval-element-array
|
|
3005
|
+
// exit is a CALL-boundary conversion (the loadPlugins param ABI) —
|
|
3006
|
+
// converting a local would strand the engine's own prototypes
|
|
3007
|
+
// (join/map/... on a native handle-element array), where the handle
|
|
3008
|
+
// routes every use engine-side.
|
|
3009
|
+
if (init.type.kind === "jsval" && type.kind === "array" && type.elem.kind === "jsval") {
|
|
3010
|
+
type = JSVAL;
|
|
3011
|
+
}
|
|
2934
3012
|
// A STATIC array of island HANDLES under an unannotated declared type
|
|
2935
3013
|
// spelling evolved elements (`const kept = fns.filter(...)` over an
|
|
2936
3014
|
// evolving-`any` receiver — the handle-element lowering keeps the
|
|
@@ -3647,7 +3725,12 @@ export function lowerExprStatement(L, expr) {
|
|
|
3647
3725
|
ts.isExpressionStatement(stmtNode) &&
|
|
3648
3726
|
ts.isSourceFile(stmtNode.parent) &&
|
|
3649
3727
|
isJsSourceFile(stmtNode.parent);
|
|
3650
|
-
if (requireSpecOf(expr) !== null &&
|
|
3728
|
+
if (requireSpecOf(expr) !== null &&
|
|
3729
|
+
ts.isCallExpression(expr) &&
|
|
3730
|
+
ts.isIdentifier(expr.expression) &&
|
|
3731
|
+
// A binding NAMED require made by createRequire is not the CJS
|
|
3732
|
+
// global — the expression path owns it (lowerCreateRequireCall).
|
|
3733
|
+
createRequireCalleeFileOf(L, expr.expression) === null) {
|
|
3651
3734
|
const sf = expr.getSourceFile();
|
|
3652
3735
|
// A bare require of a package NOTHING INSTALLED resolves, in ANY
|
|
3653
3736
|
// CommonJS JS file (the export-assignment spellings tsgo marks
|
|
@@ -3773,7 +3856,7 @@ export function lowerExprStatement(L, expr) {
|
|
|
3773
3856
|
const loc = locOf(expr);
|
|
3774
3857
|
// Dispatch follows the RUNTIME world (383(d)): a checker-'any'
|
|
3775
3858
|
// receiver whose value LOWERED checked-dynamic (`bag.nested.x
|
|
3776
|
-
// = v` behind an 'object'-typed bag) takes the
|
|
3859
|
+
// = v` behind an 'object'-typed bag) takes the dyn keyed
|
|
3777
3860
|
// write — the routed JSVAL arm lands it on the real engine
|
|
3778
3861
|
// object.
|
|
3779
3862
|
if (obj.type.kind === "dyn") {
|
|
@@ -3870,7 +3953,7 @@ export function lowerExprStatement(L, expr) {
|
|
|
3870
3953
|
}
|
|
3871
3954
|
// `h.onDone = cb` on a CHECKED-DYNAMIC receiver (a JS `let h =
|
|
3872
3955
|
// {}` evolving object, an implicit-any param, a dyn member
|
|
3873
|
-
// chain): the
|
|
3956
|
+
// chain): the dyn keyed write — the value converts INTO dyn
|
|
3874
3957
|
// (closures box), the runtime sets the member on OBJ receivers
|
|
3875
3958
|
// and throws Node's TypeErrors on the rest. The receiver is
|
|
3876
3959
|
// PROBED (probeLower) and claimed exactly when it lowers to
|
|
@@ -3890,7 +3973,7 @@ export function lowerExprStatement(L, expr) {
|
|
|
3890
3973
|
}
|
|
3891
3974
|
// `events.defaultMaxListeners = v` in STATEMENT position — the
|
|
3892
3975
|
// module-property write Node validates (the lowerBinary
|
|
3893
|
-
// expression twin): the value crosses into the
|
|
3976
|
+
// expression twin): the value crosses into the checked-dynamic tree, the runtime
|
|
3894
3977
|
// ladder throws Node's exact errors, valid numbers apply.
|
|
3895
3978
|
if (!expr.left.questionDotToken && expr.left.name.text === "defaultMaxListeners") {
|
|
3896
3979
|
const bi = L.builtinMemberOf(expr.left);
|
|
@@ -4194,7 +4277,7 @@ function lowerCompoundToTarget(L, expr, compound, target) {
|
|
|
4194
4277
|
isJsSourceFile(expr.getSourceFile())) {
|
|
4195
4278
|
// JS any-origin operands: check to number and compute natively
|
|
4196
4279
|
// (the binary-operator stance) — the dyn target takes the result
|
|
4197
|
-
// back through the usual
|
|
4280
|
+
// back through the usual dyn conversion.
|
|
4198
4281
|
const checkNum = (e) => e.type.kind === "dyn" ? { kind: "dynCheck", value: e, type: F64, loc: e.loc } : e;
|
|
4199
4282
|
const computed = { kind: "bin", op: compound, left: checkNum(read), right: checkNum(rhs), type: F64, loc };
|
|
4200
4283
|
value = target.type.kind === "dyn" ? { kind: "dynFrom", value: computed, type: DYN, loc } : computed;
|
|
@@ -5026,7 +5109,7 @@ function destructAssignPiece(L, prop, islandSource) {
|
|
|
5026
5109
|
// keys resolve statically (the record path's rule) — the keyed read
|
|
5027
5110
|
// below takes the folded name. A RUNTIME-valued key over an ISLAND
|
|
5028
5111
|
// source reads through the engine's own indexing at the element's
|
|
5029
|
-
// pattern position (`({ [key]: w } = src)`); over the
|
|
5112
|
+
// pattern position (`({ [key]: w } = src)`); over the checked-dynamic tree the fence
|
|
5030
5113
|
// stays.
|
|
5031
5114
|
const folded = patternKeyNameOf(L, prop.name);
|
|
5032
5115
|
if (folded === null) {
|
|
@@ -5476,12 +5559,12 @@ export function lowerForOf(L, stmt) {
|
|
|
5476
5559
|
if (iterable.type.kind === "jsval") {
|
|
5477
5560
|
return lowerForOfIsland(L, stmt, iterable, labels);
|
|
5478
5561
|
}
|
|
5479
|
-
// A CHECKED-DYNAMIC iterable (`unknown[]
|
|
5480
|
-
// `(string | object)[]
|
|
5481
|
-
//
|
|
5482
|
-
//
|
|
5562
|
+
// A CHECKED-DYNAMIC iterable (`unknown[]`, the collapsed
|
|
5563
|
+
// `(string | object)[]`, JSON-parsed values, wrapped engine
|
|
5564
|
+
// values): the source packs ONCE through the spread walk and a
|
|
5565
|
+
// hidden index loop binds each element as a dyn value.
|
|
5483
5566
|
if (iterable.type.kind === "dyn") {
|
|
5484
|
-
L
|
|
5567
|
+
return lowerForOfDyn(L, stmt, iterable, labels);
|
|
5485
5568
|
}
|
|
5486
5569
|
if (iterable.type.kind !== "array") {
|
|
5487
5570
|
L.badType(stmt.expression, L.typeOf(stmt.expression));
|
|
@@ -5854,6 +5937,158 @@ function lowerForOfClassIterator(L, stmt, iterable, cit, labels) {
|
|
|
5854
5937
|
* (break/return out of a partial iteration calling it.return()) is NOT
|
|
5855
5938
|
* run — a divergence only a custom island iterator with a return()
|
|
5856
5939
|
* method can observe. */
|
|
5940
|
+
/** For-of over a CHECKED-DYNAMIC iterable: the source packs ONCE
|
|
5941
|
+
* through the spread walk (dyn.iterPack — dyn arrays element-by-
|
|
5942
|
+
* element, strings by code point, bytes by byte; a WRAPPED engine
|
|
5943
|
+
* value drains through the ENGINE's own iterator protocol via the
|
|
5944
|
+
* iter_drain arm; every other kind throws V8's not-iterable
|
|
5945
|
+
* TypeError, the identifier spelling when the head has one), then a
|
|
5946
|
+
* hidden index loop binds each element as a dyn value. The pack is an
|
|
5947
|
+
* eager SNAPSHOT (the matchAll stance): body mutations of a dyn-array
|
|
5948
|
+
* source don't extend the iteration where JS's live array iterator
|
|
5949
|
+
* would — documented divergence; engine sources drain through their
|
|
5950
|
+
* own protocol, so generators/Maps/Sets step exactly once like Node. */
|
|
5951
|
+
function lowerForOfDyn(L, stmt, iterable, labels) {
|
|
5952
|
+
const loc = locOf(stmt);
|
|
5953
|
+
const head = stmt.expression;
|
|
5954
|
+
// V8's for-of CallPrinter spellings: named sources (identifiers and
|
|
5955
|
+
// plain property chains) read "<src> is not iterable", call heads
|
|
5956
|
+
// with a nameable callee "<callee> is not a function or its return
|
|
5957
|
+
// value is not iterable"; everything else keeps the runtime kind
|
|
5958
|
+
// wording. The runtime uses the spelling VERBATIM when non-empty.
|
|
5959
|
+
const headText = (e) => {
|
|
5960
|
+
if (ts.isIdentifier(e))
|
|
5961
|
+
return e.text;
|
|
5962
|
+
if (ts.isPropertyAccessExpression(e) && !e.questionDotToken && ts.isIdentifier(e.name)) {
|
|
5963
|
+
const base = headText(e.expression);
|
|
5964
|
+
return base !== null ? `${base}.${e.name.text}` : null;
|
|
5965
|
+
}
|
|
5966
|
+
return null;
|
|
5967
|
+
};
|
|
5968
|
+
const headName = headText(head);
|
|
5969
|
+
const calleeName = ts.isCallExpression(head) ? headText(head.expression) : null;
|
|
5970
|
+
const spell = headName !== null
|
|
5971
|
+
? `${headName} is not iterable`
|
|
5972
|
+
: calleeName !== null
|
|
5973
|
+
? `${calleeName} is not a function or its return value is not iterable`
|
|
5974
|
+
: "";
|
|
5975
|
+
const pack = L.declareHiddenLocal("%dofpack", DYN);
|
|
5976
|
+
const idx = L.declareHiddenLocal("%dofi", F64);
|
|
5977
|
+
idx.mutable = true;
|
|
5978
|
+
const packRef = () => ({ kind: "varRef", localId: pack.id, type: DYN, loc });
|
|
5979
|
+
const iRef = () => ({ kind: "varRef", localId: idx.id, type: F64, loc });
|
|
5980
|
+
const elemInit = () => ({ kind: "libCall", fn: "dyn.arrAt", args: [packRef(), iRef()], type: DYN, loc });
|
|
5981
|
+
L.scopes.push(new Map());
|
|
5982
|
+
try {
|
|
5983
|
+
const binds = [];
|
|
5984
|
+
if (!ts.isVariableDeclarationList(stmt.initializer)) {
|
|
5985
|
+
// Pre-declared heads: identifier targets assign the existing
|
|
5986
|
+
// binding once per pass (JS's shared-binding rule); literal
|
|
5987
|
+
// patterns run the destructuring-assignment machinery over the
|
|
5988
|
+
// dyn element; member targets keep the fence.
|
|
5989
|
+
let target = stmt.initializer;
|
|
5990
|
+
while (ts.isParenthesizedExpression(target))
|
|
5991
|
+
target = target.expression;
|
|
5992
|
+
const tmp = L.declareHiddenLocal("%vof", DYN);
|
|
5993
|
+
binds.push({ kind: "varDecl", localId: tmp.id, init: elemInit(), loc });
|
|
5994
|
+
const elemRef = { kind: "varRef", localId: tmp.id, type: DYN, loc };
|
|
5995
|
+
if (ts.isArrayLiteralExpression(target) || ts.isObjectLiteralExpression(target)) {
|
|
5996
|
+
binds.push(lowerDestructuringAssign(L, target, elemRef, target, loc));
|
|
5997
|
+
}
|
|
5998
|
+
else if (ts.isIdentifier(target) && L.resolveWritable(target)) {
|
|
5999
|
+
const writable = L.resolveWritable(target);
|
|
6000
|
+
binds.push({
|
|
6001
|
+
kind: "assign",
|
|
6002
|
+
localId: writable.id,
|
|
6003
|
+
value: L.coerceInto(target, elemRef, writable.type),
|
|
6004
|
+
loc,
|
|
6005
|
+
});
|
|
6006
|
+
}
|
|
6007
|
+
else {
|
|
6008
|
+
L.unsupported("SC1090", stmt.initializer, "for-of over a pre-declared variable (declare the loop variable in the loop: for (const x of ...))");
|
|
6009
|
+
}
|
|
6010
|
+
}
|
|
6011
|
+
else {
|
|
6012
|
+
const list = stmt.initializer;
|
|
6013
|
+
if ((list.flags & ts.NodeFlags.Using) !== 0) {
|
|
6014
|
+
L.unsupported("SC1090", list, "'using' declarations (dispose-at-scope-exit semantics)");
|
|
6015
|
+
}
|
|
6016
|
+
const isLet = (list.flags & ts.NodeFlags.Let) !== 0 || (list.flags & ts.NodeFlags.BlockScoped) === 0;
|
|
6017
|
+
const decl = list.declarations[0];
|
|
6018
|
+
if (ts.isArrayBindingPattern(decl.name) || ts.isObjectBindingPattern(decl.name)) {
|
|
6019
|
+
const tmp = L.declareHiddenLocal("%destr", DYN);
|
|
6020
|
+
binds.push({ kind: "varDecl", localId: tmp.id, init: elemInit(), loc });
|
|
6021
|
+
L.lowerBindingPattern(decl.name, () => ({ kind: "varRef", localId: tmp.id, type: DYN, loc }), DYN, isLet, binds);
|
|
6022
|
+
}
|
|
6023
|
+
else if (ts.isIdentifier(decl.name)) {
|
|
6024
|
+
const varTarget = forOfVarTarget(L, decl);
|
|
6025
|
+
if (varTarget) {
|
|
6026
|
+
// `for (var x of d)`: the element mechanics stay on a hidden
|
|
6027
|
+
// per-iteration local; the body opens by assigning the ONE
|
|
6028
|
+
// hoisted var binding (the array head's rule).
|
|
6029
|
+
const tmp = L.declareHiddenLocal("%vof", DYN);
|
|
6030
|
+
binds.push({ kind: "varDecl", localId: tmp.id, init: elemInit(), loc });
|
|
6031
|
+
binds.push({
|
|
6032
|
+
kind: "assign",
|
|
6033
|
+
localId: varTarget.id,
|
|
6034
|
+
value: L.coerceInto(decl.name, { kind: "varRef", localId: tmp.id, type: DYN, loc }, varTarget.type),
|
|
6035
|
+
loc,
|
|
6036
|
+
});
|
|
6037
|
+
}
|
|
6038
|
+
else {
|
|
6039
|
+
const local = L.declareLocal(decl.name, decl.name.text, DYN, isLet);
|
|
6040
|
+
binds.push({ kind: "varDecl", localId: local.id, init: elemInit(), loc });
|
|
6041
|
+
}
|
|
6042
|
+
}
|
|
6043
|
+
else {
|
|
6044
|
+
L.unsupported("SC1031", decl.name);
|
|
6045
|
+
}
|
|
6046
|
+
}
|
|
6047
|
+
const body = L.inCtl("loop", () => L.lowerScopedBlock(stmt.statement), labels);
|
|
6048
|
+
return {
|
|
6049
|
+
kind: "block",
|
|
6050
|
+
body: [
|
|
6051
|
+
{
|
|
6052
|
+
kind: "varDecl",
|
|
6053
|
+
localId: pack.id,
|
|
6054
|
+
init: {
|
|
6055
|
+
kind: "libCall",
|
|
6056
|
+
fn: "dyn.iterPack",
|
|
6057
|
+
args: [iterable, { kind: "strLit", value: spell, type: STRING, loc }],
|
|
6058
|
+
type: DYN,
|
|
6059
|
+
loc,
|
|
6060
|
+
},
|
|
6061
|
+
loc,
|
|
6062
|
+
},
|
|
6063
|
+
{
|
|
6064
|
+
kind: "for",
|
|
6065
|
+
init: { kind: "varDecl", localId: idx.id, init: { kind: "numLit", value: 0, type: F64, loc }, loc },
|
|
6066
|
+
cond: {
|
|
6067
|
+
kind: "bin",
|
|
6068
|
+
op: "<",
|
|
6069
|
+
left: iRef(),
|
|
6070
|
+
right: { kind: "libCall", fn: "dyn.arrLen", args: [packRef()], type: F64, loc },
|
|
6071
|
+
type: BOOL,
|
|
6072
|
+
loc,
|
|
6073
|
+
},
|
|
6074
|
+
update: {
|
|
6075
|
+
kind: "assign",
|
|
6076
|
+
localId: idx.id,
|
|
6077
|
+
value: { kind: "bin", op: "+", left: iRef(), right: { kind: "numLit", value: 1, type: F64, loc }, type: F64, loc },
|
|
6078
|
+
loc,
|
|
6079
|
+
},
|
|
6080
|
+
body: [...binds, ...body],
|
|
6081
|
+
...(labels && { labels }),
|
|
6082
|
+
loc,
|
|
6083
|
+
},
|
|
6084
|
+
],
|
|
6085
|
+
loc,
|
|
6086
|
+
};
|
|
6087
|
+
}
|
|
6088
|
+
finally {
|
|
6089
|
+
L.scopes.pop();
|
|
6090
|
+
}
|
|
6091
|
+
}
|
|
5857
6092
|
function lowerForOfIsland(L, stmt, iterable, labels) {
|
|
5858
6093
|
const loc = locOf(stmt);
|
|
5859
6094
|
if (!ts.isVariableDeclarationList(stmt.initializer)) {
|