@wairon/cli 5.1.1-dev.45 → 5.1.1-dev.47
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/dist/cli/index.js +69 -32
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +71 -32
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -65,7 +65,7 @@ var init_defaults = __esm({
|
|
|
65
65
|
copilot: ".github/prompts",
|
|
66
66
|
codex: ".codex/agents"
|
|
67
67
|
};
|
|
68
|
-
WAIRON_VERSION = "5.1.1-dev.
|
|
68
|
+
WAIRON_VERSION = "5.1.1-dev.47";
|
|
69
69
|
GITHUB_REPO = "SYW-Apps/Waffle-AIron";
|
|
70
70
|
SUPPORTED_ALIASES = ["wai"];
|
|
71
71
|
SCAN_EXCLUDE_DIRS = /* @__PURE__ */ new Set([
|
|
@@ -1943,8 +1943,12 @@ var init_specs = __esm({
|
|
|
1943
1943
|
* so a lower detail dial no longer vouches for everything the component
|
|
1944
1944
|
* declares. Each entry gets the same target validation a `call` step gets
|
|
1945
1945
|
* (the component resolves, the caller declares it, the method is on its
|
|
1946
|
-
* contract)
|
|
1947
|
-
*
|
|
1946
|
+
* contract) AND the same code↔spec reading (call-conformance, both
|
|
1947
|
+
* directions): an entry asserts the same call a step does, minus the
|
|
1948
|
+
* position in the flow that check never reads, so it can no more buy
|
|
1949
|
+
* reachability without the code than a step can. Refused beside a non-empty
|
|
1950
|
+
* narrative, where the steps already say what is called and a second
|
|
1951
|
+
* spelling could only disagree.
|
|
1948
1952
|
*/
|
|
1949
1953
|
calls: import_zod7.z.array(import_zod7.z.string().min(1)).optional(),
|
|
1950
1954
|
/**
|
|
@@ -2667,7 +2671,10 @@ function importBindingOf(facts, name) {
|
|
|
2667
2671
|
return ownEntry(facts.importBindings, name);
|
|
2668
2672
|
}
|
|
2669
2673
|
function fieldTypesOf(facts, field) {
|
|
2670
|
-
return ownEntry(facts.fieldTypes, field) ??
|
|
2674
|
+
return ownEntry(facts.fieldTypes, field) ?? NO_DECLARED_TYPES;
|
|
2675
|
+
}
|
|
2676
|
+
function localTypesOf(facts, name) {
|
|
2677
|
+
return ownEntry(facts.localTypes, name) ?? NO_DECLARED_TYPES;
|
|
2671
2678
|
}
|
|
2672
2679
|
function typeBindingOf(facts, name) {
|
|
2673
2680
|
return ownEntry(facts.typeOnlyBindings, name) ?? ownEntry(facts.importBindings, name)?.from;
|
|
@@ -2696,12 +2703,12 @@ function resolveImport(fromFile, specifier, knownPaths) {
|
|
|
2696
2703
|
}
|
|
2697
2704
|
return void 0;
|
|
2698
2705
|
}
|
|
2699
|
-
var path6,
|
|
2706
|
+
var path6, NO_DECLARED_TYPES;
|
|
2700
2707
|
var init_code_model = __esm({
|
|
2701
2708
|
"src/models/code-model.ts"() {
|
|
2702
2709
|
"use strict";
|
|
2703
2710
|
path6 = __toESM(require("path"));
|
|
2704
|
-
|
|
2711
|
+
NO_DECLARED_TYPES = [];
|
|
2705
2712
|
}
|
|
2706
2713
|
});
|
|
2707
2714
|
|
|
@@ -9151,7 +9158,7 @@ function buildCodeIndex(model) {
|
|
|
9151
9158
|
};
|
|
9152
9159
|
const possibleOriginsOf = (site, from) => {
|
|
9153
9160
|
const proven = originOf(site, from);
|
|
9154
|
-
if (!site.field && !site.constructed) return proven;
|
|
9161
|
+
if (!site.field && !site.constructed && !site.via) return proven;
|
|
9155
9162
|
const resolved = scopeOf2(site, from);
|
|
9156
9163
|
if (!resolved) return proven;
|
|
9157
9164
|
const { path: scope, facts: f } = resolved;
|
|
@@ -9160,10 +9167,10 @@ function buildCodeIndex(model) {
|
|
|
9160
9167
|
const landings = specifier !== void 0 ? landingFrom(scope, specifier) : declarationsAt(scope).has(name) ? republishedFrom(scope) : NO_ORIGIN;
|
|
9161
9168
|
for (const candidate of landings) out.add(candidate);
|
|
9162
9169
|
};
|
|
9163
|
-
|
|
9164
|
-
|
|
9165
|
-
}
|
|
9170
|
+
const widenThroughType = (typeName) => widenThrough(typeName, typeBindingOf(f, typeName));
|
|
9171
|
+
if (site.field) for (const typeName of fieldTypesOf(f, site.field)) widenThroughType(typeName);
|
|
9166
9172
|
if (site.constructed) widenThrough(site.constructed, importBindingOf(f, site.constructed)?.from);
|
|
9173
|
+
if (site.via) for (const typeName of localTypesOf(f, site.via)) widenThroughType(typeName);
|
|
9167
9174
|
return out;
|
|
9168
9175
|
};
|
|
9169
9176
|
const declarationsAt = (path70) => namesAt(declarations, pathKey(path70), (f) => /* @__PURE__ */ new Set([...f.declaredNames, ...f.exportedNames]));
|
|
@@ -13613,6 +13620,18 @@ function resolveCallTarget(ctx, componentId, methodName) {
|
|
|
13613
13620
|
}
|
|
13614
13621
|
return { accepted, files };
|
|
13615
13622
|
}
|
|
13623
|
+
function claimsOf(implMethod) {
|
|
13624
|
+
const claims = [];
|
|
13625
|
+
for (const step of implMethod.narrative) {
|
|
13626
|
+
if (step.type !== "call" || !step.targetComponent || !step.targetMethod) continue;
|
|
13627
|
+
claims.push({ step: step.stepNumber, component: step.targetComponent, method: step.targetMethod });
|
|
13628
|
+
}
|
|
13629
|
+
for (const ref of implMethod.calls ?? []) {
|
|
13630
|
+
const parsed = parseDeclaredCall(ref);
|
|
13631
|
+
if (parsed) claims.push({ component: parsed.compId, method: parsed.methodName });
|
|
13632
|
+
}
|
|
13633
|
+
return claims;
|
|
13634
|
+
}
|
|
13616
13635
|
function describeSite(site) {
|
|
13617
13636
|
if (!site.member) return `${site.name}(\u2026)`;
|
|
13618
13637
|
if (site.via) return `${site.via}.${site.name}(\u2026)`;
|
|
@@ -13621,23 +13640,26 @@ function describeSite(site) {
|
|
|
13621
13640
|
return `<receiver>.${site.name}(\u2026)`;
|
|
13622
13641
|
}
|
|
13623
13642
|
function describeMiss(m) {
|
|
13624
|
-
const
|
|
13643
|
+
const where = m.step === void 0 ? "declared call" : `step ${m.step}`;
|
|
13644
|
+
const head = `${where} \u2192 ${m.target} (looked for ${m.accepted.map((a) => `"${a}"`).join(" / ")}`;
|
|
13625
13645
|
if (m.miss.kind === "elsewhere") return `${head}, called but resolved to ${m.miss.landed.map((p) => `"${p}"`).join(", ")})`;
|
|
13626
13646
|
if (m.miss.kind === "unresolved") return `${head}, written as ${m.miss.shapes.map((s) => `\`${s}\``).join(" / ")})`;
|
|
13627
13647
|
return `${head})`;
|
|
13628
13648
|
}
|
|
13629
|
-
var callConformanceRule;
|
|
13649
|
+
var unitOf, claimNoun, callConformanceRule;
|
|
13630
13650
|
var init_call_conformance = __esm({
|
|
13631
13651
|
"src/core/rules/conformance/call-conformance.ts"() {
|
|
13632
13652
|
"use strict";
|
|
13633
13653
|
init_models();
|
|
13654
|
+
unitOf = (m) => m.step === void 0 ? m.target : `${m.step}:${m.target}`;
|
|
13655
|
+
claimNoun = (implMethod) => implMethod.narrative.length ? "narrative call step(s)" : "declared call(s)";
|
|
13634
13656
|
callConformanceRule = {
|
|
13635
13657
|
name: "call-conformance",
|
|
13636
|
-
description: "Code\u2194spec Level 3: the
|
|
13658
|
+
description: "Code\u2194spec Level 3: the CLAIMED call \u2194 realized call relation, judged both ways against the method's own source file (its sourcePath, else the implementation's), at exact analysis grade only. A method claims a call two ways and they face one check: a narrative `call` step, and an entry of the declared `calls` a narrative-less method reaches its collaborators through. They assert the same thing, and the step number is no part of the claim \u2014 this check never reads order, so it is only how a finding points at one. Forward: every claim must be realized by a call whose callee RESOLVES TO one of the target method's own source files \u2014 the target's contract name or a per-method `symbol` override, closed transitively over the named helpers the realized function calls, and resolved against every file the call CAN have reached: a `this.<field>.<method>()` receiver followed through the field's DECLARED TYPE, a `new Class(...).<method>()` receiver through the module its CLASS NAME came from, and a plain `<name>.<method>()` receiver through the type the file ANNOTATES that name with \u2014 a parameter's, or an annotated variable's, which is how a module that wires its collaborators as closures writes every one of its calls. A matching call whose origin a pure model cannot resolve is reported apart as CALL_ORIGIN_UNRESOLVED, which NAMES the shape it could not follow and asks for nothing \u2014 a coverage hole in the reader, reported for the reason CONFORMANCE_DEGRADED is: a silently degraded gate is worse than a degraded one. A finding names a landing only from the PROVEN tier so that widening what a call reached can accept a claim but never accuse one, and a target that names no file of its own falls back to name membership. Converse: a call that resolves to a modelled method of ANOTHER component in the SAME file crosses a component boundary while looking local, so the method must claim it \u2014 in a step or in `calls` (UNDECLARED_COLOCATED_CALL) \u2014 judged on the proven tier alone, and a same-file private helper is no modelled method and is never reported. A method that claims nothing at all is judged in neither direction: what it leaves unsaid is UNUSED_*'s subject. Order, arguments and conditions stay unverified, dispatch steps (runtime-table routed) are no claim about a call site, a malformed declared reference is MALFORMED_DECLARED_CALL's finding and names no target here, the conformance dial (off) skips, and weaker analysis grades never guess.",
|
|
13637
13659
|
codes: [
|
|
13638
|
-
{ code: "CALL_STEP_UNREALIZED", defaultSeverity: "warning", summary: "Narrative call step realized by no call that resolves to the target method's own source file \u2014 the call is absent, or it lands in another module", carryable: true },
|
|
13639
|
-
{ code: "CALL_ORIGIN_UNRESOLVED", defaultSeverity: "warning", summary: "Narrative call step whose target name IS called, but only from call sites written in a shape this analysis cannot resolve to a file \u2014 the
|
|
13640
|
-
{ code: "UNDECLARED_COLOCATED_CALL", defaultSeverity: "warning", summary: "The realized function calls a modelled method of another component living in the same source file, and
|
|
13660
|
+
{ code: "CALL_STEP_UNREALIZED", defaultSeverity: "warning", summary: "Narrative call step or declared call realized by no call that resolves to the target method's own source file \u2014 the call is absent, or it lands in another module", carryable: true },
|
|
13661
|
+
{ code: "CALL_ORIGIN_UNRESOLVED", defaultSeverity: "warning", summary: "Narrative call step or declared call whose target name IS called, but only from call sites written in a shape this analysis cannot resolve to a file \u2014 the claim was not checked, and is neither proven realized nor accused", carryable: true },
|
|
13662
|
+
{ code: "UNDECLARED_COLOCATED_CALL", defaultSeverity: "warning", summary: "The realized function calls a modelled method of another component living in the same source file, and neither a narrative step nor a declared call names it", carryable: true }
|
|
13641
13663
|
],
|
|
13642
13664
|
check(ctx) {
|
|
13643
13665
|
const code = ctx.codeIndex();
|
|
@@ -13654,7 +13676,7 @@ var init_call_conformance = __esm({
|
|
|
13654
13676
|
const { implementation: impl, method: implMethod, component, sourceFile: file } = entry;
|
|
13655
13677
|
const tier = implMethod.conformance ?? impl.conformance ?? defaultConformanceTier(component);
|
|
13656
13678
|
if (tier === "off") continue;
|
|
13657
|
-
if (!implMethod.narrative.length) continue;
|
|
13679
|
+
if (!implMethod.narrative.length && !implMethod.calls?.length) continue;
|
|
13658
13680
|
if (!file) continue;
|
|
13659
13681
|
const facts = code.factsAt(file);
|
|
13660
13682
|
if (!facts || facts.status !== "analyzed" || facts.analysisGrade !== "exact") continue;
|
|
@@ -13664,16 +13686,15 @@ var init_call_conformance = __esm({
|
|
|
13664
13686
|
const sites = closedCallSites(code, file, fnSymbol);
|
|
13665
13687
|
if (!sites) continue;
|
|
13666
13688
|
const missed = [];
|
|
13667
|
-
for (const
|
|
13668
|
-
if (
|
|
13669
|
-
|
|
13670
|
-
const target = resolveCallTarget(ctx, step.targetComponent, step.targetMethod);
|
|
13689
|
+
for (const claim of claimsOf(implMethod)) {
|
|
13690
|
+
if (!ctx.componentMap.has(claim.component)) continue;
|
|
13691
|
+
const target = resolveCallTarget(ctx, claim.component, claim.method);
|
|
13671
13692
|
if (target.accepted.has(fnSymbol)) continue;
|
|
13672
13693
|
const matching = sites.filter((s) => target.accepted.has(s.name));
|
|
13673
|
-
const ref = `${
|
|
13694
|
+
const ref = `${claim.component}.${claim.method}`;
|
|
13674
13695
|
if (target.files.size === 0) {
|
|
13675
13696
|
if (matching.length === 0) {
|
|
13676
|
-
missed.push({ step: step
|
|
13697
|
+
missed.push({ step: claim.step, target: ref, accepted: [...target.accepted], miss: { kind: "absent" } });
|
|
13677
13698
|
}
|
|
13678
13699
|
continue;
|
|
13679
13700
|
}
|
|
@@ -13687,7 +13708,7 @@ var init_call_conformance = __esm({
|
|
|
13687
13708
|
}
|
|
13688
13709
|
if (realized) continue;
|
|
13689
13710
|
const miss = matching.length === 0 ? { kind: "absent" } : landed.size === 0 ? { kind: "unresolved", shapes: [...new Set(matching.map(describeSite))].sort() } : { kind: "elsewhere", landed: [...landed].sort() };
|
|
13690
|
-
missed.push({ step: step
|
|
13711
|
+
missed.push({ step: claim.step, target: ref, accepted: [...target.accepted], miss });
|
|
13691
13712
|
}
|
|
13692
13713
|
const unrealized = missed.filter((m) => m.miss.kind !== "unresolved");
|
|
13693
13714
|
const unresolved = missed.filter((m) => m.miss.kind === "unresolved");
|
|
@@ -13695,30 +13716,36 @@ var init_call_conformance = __esm({
|
|
|
13695
13716
|
ctx.addIssue(
|
|
13696
13717
|
"warning",
|
|
13697
13718
|
"CALL_STEP_UNREALIZED",
|
|
13698
|
-
`Method "${implMethod.name}" in implementation "${impl.id}": ${unrealized.length}
|
|
13719
|
+
`Method "${implMethod.name}" in implementation "${impl.id}": ${unrealized.length} ${claimNoun(implMethod)} are realized by no call of the function "${fnSymbol}" in "${file}" that resolves to the target's own source file \u2014 ${unrealized.map(describeMiss).join("; ")}. Callees are closed over the named helpers the function calls, and each call site is resolved through this file's import bindings (order, arguments and conditions are not checked). Realize the calls, fix what the method claims, or map code names via per-method symbols on the targets.`,
|
|
13699
13720
|
impl.id,
|
|
13700
13721
|
entry.draftContext,
|
|
13701
13722
|
void 0,
|
|
13702
|
-
//
|
|
13703
|
-
//
|
|
13704
|
-
|
|
13723
|
+
// One claim, named the way the register names a unit: a step by its
|
|
13724
|
+
// number and target, a declaration by its target alone. What the
|
|
13725
|
+
// register carries is ONE unrealized claim, never "this method's
|
|
13726
|
+
// calls".
|
|
13727
|
+
{ at: implMethod.name, covers: unrealized.map(unitOf) }
|
|
13705
13728
|
);
|
|
13706
13729
|
}
|
|
13707
13730
|
if (unresolved.length) {
|
|
13708
13731
|
ctx.addIssue(
|
|
13709
13732
|
"warning",
|
|
13710
13733
|
"CALL_ORIGIN_UNRESOLVED",
|
|
13711
|
-
`Method "${implMethod.name}" in implementation "${impl.id}": ${unresolved.length}
|
|
13734
|
+
`Method "${implMethod.name}" in implementation "${impl.id}": ${unresolved.length} ${claimNoun(implMethod)} ARE called by name inside the function "${fnSymbol}" in "${file}", but every site calling them is written in a shape this analysis cannot resolve to a file \u2014 ${unresolved.map(describeMiss).join("; ")}. What resolves is a name bound to a module of THIS project: a bare or namespaced call through such an import binding, a \`this.<field>\` receiver whose declared type names one, a \`new Class(\u2026)\` receiver whose class does, and a receiver NAME the file annotates with a type that does. What does not: an import from a PACKAGE specifier, a receiver holding a value the module assembled, a receiver this model records no name for, and one the file annotates with nothing. This reports what was not checked, not what is wrong \u2014 the claim is neither proven realized nor accused of being missing, and no working call is asked to be rewritten to suit the reader.`,
|
|
13712
13735
|
impl.id,
|
|
13713
13736
|
entry.draftContext,
|
|
13714
13737
|
void 0,
|
|
13715
|
-
{ at: implMethod.name, covers: unresolved.map(
|
|
13738
|
+
{ at: implMethod.name, covers: unresolved.map(unitOf) }
|
|
13716
13739
|
);
|
|
13717
13740
|
}
|
|
13718
13741
|
const declared = /* @__PURE__ */ new Set();
|
|
13719
13742
|
for (const step of implMethod.narrative) {
|
|
13720
13743
|
if (step.targetComponent && step.targetMethod) declared.add(`${step.targetComponent}.${step.targetMethod}`);
|
|
13721
13744
|
}
|
|
13745
|
+
for (const ref of implMethod.calls ?? []) {
|
|
13746
|
+
const parsed = parseDeclaredCall(ref);
|
|
13747
|
+
if (parsed) declared.add(`${parsed.compId}.${parsed.methodName}`);
|
|
13748
|
+
}
|
|
13722
13749
|
const crossings = /* @__PURE__ */ new Map();
|
|
13723
13750
|
for (const site of closedCallSites(code, file, fnSymbol, new Set(colocated.keys())) ?? []) {
|
|
13724
13751
|
const owner = colocated.get(site.name);
|
|
@@ -13733,7 +13760,7 @@ var init_call_conformance = __esm({
|
|
|
13733
13760
|
ctx.addIssue(
|
|
13734
13761
|
"warning",
|
|
13735
13762
|
"UNDECLARED_COLOCATED_CALL",
|
|
13736
|
-
`Method "${implMethod.name}" in implementation "${impl.id}": the function "${fnSymbol}" in "${file}" calls ${crossings.size} modelled method(s) of OTHER components living in that same file, and
|
|
13763
|
+
`Method "${implMethod.name}" in implementation "${impl.id}": the function "${fnSymbol}" in "${file}" calls ${crossings.size} modelled method(s) of OTHER components living in that same file, and neither a narrative step nor a declared call names it \u2014 ${detail}. Sharing a file does not make the hop internal: it crosses a component boundary nothing imports, so no file-level check can see it. Narrate the call, declare it in \`calls\`, or move the code so the boundary is real.`,
|
|
13737
13764
|
impl.id,
|
|
13738
13765
|
entry.draftContext,
|
|
13739
13766
|
void 0,
|
|
@@ -15896,6 +15923,7 @@ function walkExact(ts, sourceText, fileName) {
|
|
|
15896
15923
|
const importBindings = /* @__PURE__ */ new Map();
|
|
15897
15924
|
const typeOnlyBindings = /* @__PURE__ */ new Map();
|
|
15898
15925
|
const fieldTypes = /* @__PURE__ */ new Map();
|
|
15926
|
+
const localTypes = /* @__PURE__ */ new Map();
|
|
15899
15927
|
const mutableBindings = /* @__PURE__ */ new Set();
|
|
15900
15928
|
const receiverKey = (site) => site.via ?? (site.field ? `this.${site.field}` : site.constructed ? `new ${site.constructed}` : "");
|
|
15901
15929
|
const siteKey = (site) => `${site.member ? "m" : "b"}:${receiverKey(site)}:${site.name}`;
|
|
@@ -15923,6 +15951,13 @@ function walkExact(ts, sourceText, fileName) {
|
|
|
15923
15951
|
named.add(typeName);
|
|
15924
15952
|
fieldTypes.set(field, named);
|
|
15925
15953
|
};
|
|
15954
|
+
const recordLocalType = (name, type) => {
|
|
15955
|
+
const typeName = typeReferenceName(type);
|
|
15956
|
+
if (!typeName || !ts.isIdentifier(name)) return;
|
|
15957
|
+
const named = localTypes.get(name.text) ?? /* @__PURE__ */ new Set();
|
|
15958
|
+
named.add(typeName);
|
|
15959
|
+
localTypes.set(name.text, named);
|
|
15960
|
+
};
|
|
15926
15961
|
const hasExportModifier = (node) => {
|
|
15927
15962
|
const mods = node.modifiers;
|
|
15928
15963
|
return !!mods?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword);
|
|
@@ -15990,6 +16025,7 @@ function walkExact(ts, sourceText, fileName) {
|
|
|
15990
16025
|
else if (ts.isParameter(node) && node.parent && ts.isConstructorDeclaration(node.parent) && isParameterProperty(node)) {
|
|
15991
16026
|
recordFieldType(node.name, node.type);
|
|
15992
16027
|
}
|
|
16028
|
+
if (ts.isParameter(node) || ts.isVariableDeclaration(node)) recordLocalType(node.name, node.type);
|
|
15993
16029
|
if (ts.isFunctionDeclaration(node) || ts.isClassDeclaration(node) || ts.isInterfaceDeclaration(node) || ts.isTypeAliasDeclaration(node) || ts.isEnumDeclaration(node) || ts.isModuleDeclaration(node)) {
|
|
15994
16030
|
const name = node.name && ts.isIdentifier(node.name) ? node.name.text : void 0;
|
|
15995
16031
|
if (name) {
|
|
@@ -16066,7 +16102,7 @@ function walkExact(ts, sourceText, fileName) {
|
|
|
16066
16102
|
};
|
|
16067
16103
|
visit(sf);
|
|
16068
16104
|
const reexportOnly = sf.statements.length > 0 && sf.statements.every((st) => ts.isExportDeclaration(st) && !!st.moduleSpecifier);
|
|
16069
|
-
return { declared, anchors, exported, imports, reexports, starExports, namedReexports, complexity, calls, importBindings, typeOnlyBindings, fieldTypes, mutableBindings, reexportOnly };
|
|
16105
|
+
return { declared, anchors, exported, imports, reexports, starExports, namedReexports, complexity, calls, importBindings, typeOnlyBindings, fieldTypes, localTypes, mutableBindings, reexportOnly };
|
|
16070
16106
|
}
|
|
16071
16107
|
function resolveRelativeModule(fromFile, specifier) {
|
|
16072
16108
|
if (!specifier.startsWith(".")) return null;
|
|
@@ -16247,6 +16283,7 @@ function buildCodeModel(implementations, types, projectRoot2, sourceRoots = [],
|
|
|
16247
16283
|
importBindings: Object.fromEntries(facts.importBindings),
|
|
16248
16284
|
typeOnlyBindings: Object.fromEntries(facts.typeOnlyBindings),
|
|
16249
16285
|
fieldTypes: Object.fromEntries([...facts.fieldTypes].map(([k, v]) => [k, [...v]])),
|
|
16286
|
+
localTypes: Object.fromEntries([...facts.localTypes].map(([k, v]) => [k, [...v]])),
|
|
16250
16287
|
topLevelMutableBindings: [...facts.mutableBindings],
|
|
16251
16288
|
reexportOnly: facts.reexportOnly
|
|
16252
16289
|
};
|