@nudojs/core 1.3.0 → 1.5.0
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/{check-report-BWmfy810.d.ts → check-report-Ci1dDysO.d.ts} +52 -27
- package/dist/{chunk-CKH6GQAI.js → chunk-W2MP6REI.js} +2351 -1896
- package/dist/{chunk-5YNR4Q7E.js → chunk-YO4GKCNE.js} +817 -169
- package/dist/exec.d.ts +8 -16
- package/dist/exec.js +9 -1
- package/dist/index.d.ts +125 -110
- package/dist/index.js +174 -94
- package/dist/internal.d.ts +4 -4
- package/dist/internal.js +39 -27
- package/dist/{run-Dk08Q5zl.d.ts → run-WJfj477N.d.ts} +186 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import "./chunk-US532PZA.js";
|
|
2
2
|
import {
|
|
3
|
+
CONSTRAINT_BUILDERS,
|
|
4
|
+
CONSTRAINT_BUILDER_NAMES,
|
|
5
|
+
CONSTRAINT_EXPR_RE,
|
|
3
6
|
NudoSidecarError,
|
|
4
7
|
SELF,
|
|
5
8
|
andC,
|
|
@@ -14,14 +17,20 @@ import {
|
|
|
14
17
|
effectiveInterface,
|
|
15
18
|
evictGeneralizeMemoForPaths,
|
|
16
19
|
execNudoModule,
|
|
20
|
+
extractBalancedParens,
|
|
17
21
|
extractDeclaredThrows,
|
|
22
|
+
extractFileEnvNames,
|
|
18
23
|
extractFn,
|
|
19
24
|
extractFnBudget,
|
|
25
|
+
extractMockModuleRecords,
|
|
26
|
+
extractNudoImportRecords,
|
|
20
27
|
extractNudoImports,
|
|
21
28
|
extractRefineReturnFromSource,
|
|
22
29
|
extractRefinesFromSource,
|
|
30
|
+
findFnDirectiveScope,
|
|
23
31
|
fn,
|
|
24
32
|
fnConstraintToEntryReqs,
|
|
33
|
+
fnDirectiveCommentLines,
|
|
25
34
|
formatConstraint,
|
|
26
35
|
formatEffectiveInterfaceDisplay,
|
|
27
36
|
formatInterfaceTierLine,
|
|
@@ -40,6 +49,7 @@ import {
|
|
|
40
49
|
isNodeModulesPath,
|
|
41
50
|
isNudoConstraint,
|
|
42
51
|
lenTerm,
|
|
52
|
+
listFnDirectiveScopes,
|
|
43
53
|
listFunctionNames,
|
|
44
54
|
listTopFunctions,
|
|
45
55
|
litC,
|
|
@@ -50,6 +60,9 @@ import {
|
|
|
50
60
|
nullable,
|
|
51
61
|
number,
|
|
52
62
|
omit,
|
|
63
|
+
parseEnvPayload,
|
|
64
|
+
parseMockModulePayload,
|
|
65
|
+
parseNudoImportPayload,
|
|
53
66
|
partial,
|
|
54
67
|
pick,
|
|
55
68
|
refineDiagCount,
|
|
@@ -58,13 +71,19 @@ import {
|
|
|
58
71
|
resetHashSourceCache,
|
|
59
72
|
resetNudoModuleExecCache,
|
|
60
73
|
resetSidecarLoadFailureCache,
|
|
74
|
+
scanBudgetDecl,
|
|
75
|
+
scanCaseArgSpans,
|
|
76
|
+
scanCaseTags,
|
|
77
|
+
scanContractSegments,
|
|
61
78
|
scanLiteralCalls,
|
|
79
|
+
scanThrowsDecl,
|
|
62
80
|
setInterfaceDiagCollector,
|
|
63
81
|
setRefineDiagCollector,
|
|
64
82
|
shape,
|
|
65
83
|
sidecarClosureFingerprint,
|
|
66
84
|
sidecarPathOf,
|
|
67
85
|
stableAnalyzeKeySource,
|
|
86
|
+
stablePathKey,
|
|
68
87
|
string,
|
|
69
88
|
takeInterfaceDiags,
|
|
70
89
|
takeInterfaceDiagsSince,
|
|
@@ -72,7 +91,7 @@ import {
|
|
|
72
91
|
takeRefineDiagsSince,
|
|
73
92
|
throwConstraintToKinds,
|
|
74
93
|
union
|
|
75
|
-
} from "./chunk-
|
|
94
|
+
} from "./chunk-YO4GKCNE.js";
|
|
76
95
|
import {
|
|
77
96
|
$add,
|
|
78
97
|
$arguments,
|
|
@@ -200,6 +219,7 @@ import {
|
|
|
200
219
|
TYPEOF_NAMES,
|
|
201
220
|
abs,
|
|
202
221
|
absFunction,
|
|
222
|
+
absOnly,
|
|
203
223
|
absShapeKey,
|
|
204
224
|
absToString,
|
|
205
225
|
add,
|
|
@@ -231,6 +251,7 @@ import {
|
|
|
231
251
|
callAbsMethod,
|
|
232
252
|
callAtFunctionBoundary,
|
|
233
253
|
callTranspiledExport,
|
|
254
|
+
callTranspiledExportApply,
|
|
234
255
|
callTranspiledExportFull,
|
|
235
256
|
canonicalArrayIndex,
|
|
236
257
|
clearBClasses,
|
|
@@ -309,6 +330,7 @@ import {
|
|
|
309
330
|
identBoundaryRegex,
|
|
310
331
|
implies,
|
|
311
332
|
instantiateReturn,
|
|
333
|
+
isAbsApplyResult,
|
|
312
334
|
isArrMutator,
|
|
313
335
|
isBigPrim,
|
|
314
336
|
isDefinitelyFalse,
|
|
@@ -345,6 +367,7 @@ import {
|
|
|
345
367
|
looseEqAbs,
|
|
346
368
|
lt,
|
|
347
369
|
ltNum,
|
|
370
|
+
makeAbsApplyResult,
|
|
348
371
|
makeArrayCtorAbs,
|
|
349
372
|
makeMapAbs,
|
|
350
373
|
makeSetAbs,
|
|
@@ -484,7 +507,7 @@ import {
|
|
|
484
507
|
v,
|
|
485
508
|
withExecPhi,
|
|
486
509
|
withVar
|
|
487
|
-
} from "./chunk-
|
|
510
|
+
} from "./chunk-W2MP6REI.js";
|
|
488
511
|
|
|
489
512
|
// src/environment.ts
|
|
490
513
|
function createEnvironment(parent, bindings = /* @__PURE__ */ new Map()) {
|
|
@@ -613,15 +636,15 @@ function checkArg(arg, expect, phi = pTrue) {
|
|
|
613
636
|
}
|
|
614
637
|
const combined = arg.pred && arg.pred.op !== "true" ? phi.op === "true" ? arg.pred : { op: "and", args: [phi, arg.pred] } : phi;
|
|
615
638
|
if (implies(combined, expect)) return void 0;
|
|
616
|
-
const
|
|
617
|
-
if (
|
|
618
|
-
const ok = decideLitCmp(
|
|
639
|
+
const lvR = litValue(arg);
|
|
640
|
+
if (lvR.ok && (expect.op === "gt" || expect.op === "ge" || expect.op === "lt" || expect.op === "le")) {
|
|
641
|
+
const ok = decideLitCmp(lvR.value, expect);
|
|
619
642
|
if (ok === true) return void 0;
|
|
620
643
|
if (ok === false) {
|
|
621
644
|
return {
|
|
622
645
|
severity: "error",
|
|
623
646
|
code: "nudo:constraint-violated",
|
|
624
|
-
message: `argument ${JSON.stringify(
|
|
647
|
+
message: `argument ${JSON.stringify(lvR.value)} does not satisfy ${predToString(expect)}`,
|
|
625
648
|
suggestion: `use a value satisfying the constraint, or relax the function precondition`
|
|
626
649
|
};
|
|
627
650
|
}
|
|
@@ -745,60 +768,92 @@ function isBoundedEvidenceMissing(ret, constraint) {
|
|
|
745
768
|
if (ret.pred && ret.pred.op !== "true") return false;
|
|
746
769
|
return true;
|
|
747
770
|
}
|
|
771
|
+
function flattenSumArms(ret) {
|
|
772
|
+
if (ret.shape.k !== "sum") return [ret];
|
|
773
|
+
const out = [];
|
|
774
|
+
for (const m of ret.shape.members) {
|
|
775
|
+
if (m.shape.k === "sum") out.push(...flattenSumArms(m));
|
|
776
|
+
else out.push(m);
|
|
777
|
+
}
|
|
778
|
+
return out;
|
|
779
|
+
}
|
|
780
|
+
function isWidenedSumArm(m, parent) {
|
|
781
|
+
return parent.conf === "partial" && m.shape.k === "prim" && !m.term && (!m.pred || m.pred.op === "true");
|
|
782
|
+
}
|
|
748
783
|
function assertImplies(ret, constraint, opts) {
|
|
749
784
|
const phi = opts?.phi ?? pTrue;
|
|
750
785
|
if (ret.shape.k === "never") return proved();
|
|
751
786
|
if (isAnyConstraint(constraint)) return proved();
|
|
752
|
-
const nullishOk = constraintAdmitsNullish(constraint);
|
|
753
|
-
if (isNullishLitAbs(ret)) {
|
|
754
|
-
return nullishOk ? proved() : disproved(`nullish return \u22AD ${formatConstraint(constraint)}`);
|
|
755
|
-
}
|
|
756
|
-
let sumMembers;
|
|
757
|
-
if (ret.shape.k === "sum") {
|
|
758
|
-
const members = ret.shape.members;
|
|
759
|
-
const nullishMembers = members.filter((m) => isNullishLitAbs(m));
|
|
760
|
-
if (nullishMembers.length > 0 && !nullishOk) {
|
|
761
|
-
return disproved(
|
|
762
|
-
`nullish return arm \u22AD ${formatConstraint(constraint)} (contract does not admit nullish)`
|
|
763
|
-
);
|
|
764
|
-
}
|
|
765
|
-
sumMembers = members.filter((m) => !isNullishLitAbs(m));
|
|
766
|
-
}
|
|
767
787
|
if (isValueSetUnknown(ret)) {
|
|
768
788
|
return unprovable(
|
|
769
789
|
ret.shape.k === "any" ? "any does not establish the return contract" : "inference failure (unknown/opaque) \u2014 cannot prove the return contract"
|
|
770
790
|
);
|
|
771
791
|
}
|
|
792
|
+
const arms = flattenSumArms(ret);
|
|
793
|
+
if (arms.length > 1) {
|
|
794
|
+
return assertSumArms(arms, ret, constraint, opts, phi);
|
|
795
|
+
}
|
|
796
|
+
return assertImpliesSingle(arms[0], constraint, opts, phi);
|
|
797
|
+
}
|
|
798
|
+
function assertSumArms(arms, parent, constraint, opts, phi) {
|
|
799
|
+
const hasWidenedArm = arms.some(
|
|
800
|
+
(a) => isValueSetUnknown(a) || isWidenedSumArm(a, parent)
|
|
801
|
+
);
|
|
802
|
+
let sawUnprovable = false;
|
|
803
|
+
for (const arm of arms) {
|
|
804
|
+
if (isNullishLitAbs(arm)) {
|
|
805
|
+
if (!constraintAdmitsNullish(constraint)) {
|
|
806
|
+
return disproved(
|
|
807
|
+
`nullish return arm \u22AD ${formatConstraint(constraint)} (contract does not admit nullish)`
|
|
808
|
+
);
|
|
809
|
+
}
|
|
810
|
+
continue;
|
|
811
|
+
}
|
|
812
|
+
if (isValueSetUnknown(arm) || isWidenedSumArm(arm, parent)) {
|
|
813
|
+
sawUnprovable = true;
|
|
814
|
+
continue;
|
|
815
|
+
}
|
|
816
|
+
const r = assertImpliesSingle(arm, constraint, opts, phi);
|
|
817
|
+
if (r.status === "disproved") {
|
|
818
|
+
if (hasWidenedArm) {
|
|
819
|
+
sawUnprovable = true;
|
|
820
|
+
continue;
|
|
821
|
+
}
|
|
822
|
+
return r;
|
|
823
|
+
}
|
|
824
|
+
if (r.status === "unprovable") sawUnprovable = true;
|
|
825
|
+
}
|
|
826
|
+
return sawUnprovable ? unprovable("sum: some arms unprovable") : proved();
|
|
827
|
+
}
|
|
828
|
+
function assertImpliesSingle(arm, constraint, opts, phi) {
|
|
829
|
+
if (isNullishLitAbs(arm)) {
|
|
830
|
+
return constraintAdmitsNullish(constraint) ? proved() : disproved(`nullish return \u22AD ${formatConstraint(constraint)}`);
|
|
831
|
+
}
|
|
832
|
+
if (isValueSetUnknown(arm)) {
|
|
833
|
+
return unprovable(
|
|
834
|
+
arm.shape.k === "any" ? "any does not establish the return contract" : "inference failure (unknown/opaque) \u2014 cannot prove the return contract"
|
|
835
|
+
);
|
|
836
|
+
}
|
|
772
837
|
if (constraint.members && constraint.members.length > 0) {
|
|
773
838
|
let sawUnprovable = false;
|
|
774
839
|
for (const m of constraint.members) {
|
|
775
|
-
const r = assertImplies(
|
|
840
|
+
const r = assertImplies(arm, m, opts);
|
|
776
841
|
if (r.status === "proved") return proved();
|
|
777
842
|
if (r.status === "unprovable") sawUnprovable = true;
|
|
778
843
|
}
|
|
779
844
|
return sawUnprovable ? unprovable("union: no member proved the return contract") : disproved(`return \u22AD union(${constraint.members.map((m) => formatConstraint(m)).join(", ")})`);
|
|
780
845
|
}
|
|
781
|
-
if (sumMembers && constraint.fields) {
|
|
782
|
-
let sawUnprovable = false;
|
|
783
|
-
for (const m of sumMembers) {
|
|
784
|
-
if (isValueSetUnknown(m)) continue;
|
|
785
|
-
const r = assertImplies(m, constraint, opts);
|
|
786
|
-
if (r.status === "disproved") return r;
|
|
787
|
-
if (r.status === "unprovable") sawUnprovable = true;
|
|
788
|
-
}
|
|
789
|
-
return sawUnprovable ? unprovable("sum: some arms unprovable") : proved();
|
|
790
|
-
}
|
|
791
846
|
if (constraint.fields) {
|
|
792
|
-
return assertShapeFields(
|
|
847
|
+
return assertShapeFields(arm, constraint, opts);
|
|
793
848
|
}
|
|
794
849
|
if (constraint.element) {
|
|
795
|
-
if (
|
|
796
|
-
return disproved(`return shape ${
|
|
850
|
+
if (arm.shape.k !== "arr" && arm.shape.k !== "tuple") {
|
|
851
|
+
return disproved(`return shape ${arm.shape.k} \u22AD array(...)`);
|
|
797
852
|
}
|
|
798
853
|
return proved();
|
|
799
854
|
}
|
|
800
855
|
if (constraint.fn) return proved();
|
|
801
|
-
return assertScalar(
|
|
856
|
+
return assertScalar(arm, constraint, phi);
|
|
802
857
|
}
|
|
803
858
|
function isAnyConstraint(c) {
|
|
804
859
|
return !c.prim && c.preds.length === 0 && !c.fields && !c.element && !c.members && !c.fn && !isIntFlag(c);
|
|
@@ -838,13 +893,18 @@ function assertScalar(ret, constraint, phi) {
|
|
|
838
893
|
if (retPrim && retPrim !== constraint.prim) {
|
|
839
894
|
return disproved(`typeof return = "${retPrim}" \u22AD "${constraint.prim}"`);
|
|
840
895
|
}
|
|
841
|
-
if (!retPrim
|
|
896
|
+
if (!retPrim) {
|
|
897
|
+
const k = ret.shape.k;
|
|
898
|
+
if (k === "obj" || k === "arr" || k === "tuple" || k === "fn" || k === "brand" || k === "eff") {
|
|
899
|
+
return disproved(`return shape ${k} \u22AD prim "${constraint.prim}"`);
|
|
900
|
+
}
|
|
842
901
|
}
|
|
843
902
|
}
|
|
844
903
|
if (isIntFlag(constraint) && constraint.prim === "number") {
|
|
845
|
-
const
|
|
846
|
-
|
|
847
|
-
|
|
904
|
+
const lvR = litValue(ret);
|
|
905
|
+
const lv = lvR.ok ? lvR.value : void 0;
|
|
906
|
+
if (typeof lv === "number" && !Number.isInteger(lv)) {
|
|
907
|
+
return disproved(`return ${lv} \u22AD int`);
|
|
848
908
|
}
|
|
849
909
|
}
|
|
850
910
|
const t = retAnchorTerm(ret);
|
|
@@ -867,18 +927,17 @@ function assertScalar(ret, constraint, phi) {
|
|
|
867
927
|
);
|
|
868
928
|
}
|
|
869
929
|
}
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
if (
|
|
873
|
-
|
|
930
|
+
if (ret.term?.op === "lit") {
|
|
931
|
+
const lv = ret.term.value;
|
|
932
|
+
if (typeof lv === "number" || typeof lv === "string" || typeof lv === "boolean" || lv === null || lv === void 0) {
|
|
933
|
+
if (literalMeetsConstraint(lv, constraint)) {
|
|
934
|
+
return proved();
|
|
935
|
+
}
|
|
936
|
+
const boundDesc = describeBoundViolation(lv, constraint);
|
|
937
|
+
return disproved(
|
|
938
|
+
boundDesc ?? `return ${JSON.stringify(lv)} \u22AD ${formatConstraint(constraint)}`
|
|
939
|
+
);
|
|
874
940
|
}
|
|
875
|
-
const boundDesc = describeBoundViolation(lv, constraint);
|
|
876
|
-
return disproved(
|
|
877
|
-
boundDesc ?? `return ${JSON.stringify(lv)} \u22AD ${formatConstraint(constraint)}`
|
|
878
|
-
);
|
|
879
|
-
}
|
|
880
|
-
if (ret.term?.op === "lit" && ret.term.value === void 0) {
|
|
881
|
-
return proved();
|
|
882
941
|
}
|
|
883
942
|
if (constraintPred.op !== "true" || constraint.preds.length > 0) {
|
|
884
943
|
if (isBoundedEvidenceMissing(ret, constraint)) {
|
|
@@ -924,7 +983,8 @@ function litLE(a, b) {
|
|
|
924
983
|
}
|
|
925
984
|
function primOfAbs(a) {
|
|
926
985
|
if (a.shape.k === "prim") return a.shape.type;
|
|
927
|
-
const
|
|
986
|
+
const lvR = litValue(a);
|
|
987
|
+
const lv = lvR.ok ? lvR.value : void 0;
|
|
928
988
|
if (typeof lv === "number") return "number";
|
|
929
989
|
if (typeof lv === "string") return "string";
|
|
930
990
|
if (typeof lv === "boolean") return "boolean";
|
|
@@ -1513,7 +1573,7 @@ function unindexCheckKey(key) {
|
|
|
1513
1573
|
function evictCheckSourceMemoForPaths(paths) {
|
|
1514
1574
|
let n = 0;
|
|
1515
1575
|
for (const raw of paths) {
|
|
1516
|
-
const p =
|
|
1576
|
+
const p = stablePathKey(raw);
|
|
1517
1577
|
const keys = checkDepIndex.get(p);
|
|
1518
1578
|
if (!keys) continue;
|
|
1519
1579
|
for (const key of [...keys]) {
|
|
@@ -1589,8 +1649,9 @@ function checkMemoSet(key, value, depPaths) {
|
|
|
1589
1649
|
}
|
|
1590
1650
|
checkReportMemo.set(key, value);
|
|
1591
1651
|
if (depPaths.length > 0) {
|
|
1592
|
-
|
|
1593
|
-
|
|
1652
|
+
const normDeps = [...new Set(depPaths.map(stablePathKey))];
|
|
1653
|
+
checkKeyDeps.set(key, normDeps);
|
|
1654
|
+
for (const p of normDeps) {
|
|
1594
1655
|
let set = checkDepIndex.get(p);
|
|
1595
1656
|
if (!set) {
|
|
1596
1657
|
set = /* @__PURE__ */ new Set();
|
|
@@ -1915,13 +1976,14 @@ function scanCaseInconsistency(source, knownFns, opts) {
|
|
|
1915
1976
|
}
|
|
1916
1977
|
arg = projected;
|
|
1917
1978
|
}
|
|
1918
|
-
const
|
|
1919
|
-
|
|
1979
|
+
const argLit = arg.term?.op === "lit" ? arg.term.value : void 0;
|
|
1980
|
+
const argIsLit = arg.term?.op === "lit";
|
|
1981
|
+
if (!argIsLit || typeof argLit !== "number" && typeof argLit !== "string" && typeof argLit !== "boolean" && argLit !== null && argLit !== void 0) {
|
|
1920
1982
|
continue;
|
|
1921
1983
|
}
|
|
1922
1984
|
const hasEqOr = (entry.constraint.members?.length ?? 0) > 0 || entry.constraint.preds.some((p) => p.op === "eq");
|
|
1923
1985
|
if (hasEqOr) {
|
|
1924
|
-
if (!literalMeetsConstraint(
|
|
1986
|
+
if (!literalMeetsConstraint(argLit, entry.constraint)) {
|
|
1925
1987
|
const paramName = entry.param || paramNames[idx] || `arg${idx}`;
|
|
1926
1988
|
out.push({
|
|
1927
1989
|
severity: "error",
|
|
@@ -1936,16 +1998,16 @@ function scanCaseInconsistency(source, knownFns, opts) {
|
|
|
1936
1998
|
}
|
|
1937
1999
|
continue;
|
|
1938
2000
|
}
|
|
1939
|
-
if (typeof
|
|
2001
|
+
if (typeof argLit !== "number") continue;
|
|
1940
2002
|
const flatten = (p) => p.op === "and" ? p.args.flatMap(flatten) : p.op === "true" ? [] : [p];
|
|
1941
2003
|
for (const p of flatten(entry.pred)) {
|
|
1942
2004
|
if ((p.op === "gt" || p.op === "ge" || p.op === "lt" || p.op === "le") && p.b.op === "lit" && typeof p.b.value === "number") {
|
|
1943
2005
|
const n = p.b.value;
|
|
1944
2006
|
let ok = true;
|
|
1945
|
-
if (p.op === "gt") ok =
|
|
1946
|
-
if (p.op === "ge") ok =
|
|
1947
|
-
if (p.op === "lt") ok =
|
|
1948
|
-
if (p.op === "le") ok =
|
|
2007
|
+
if (p.op === "gt") ok = argLit > n;
|
|
2008
|
+
if (p.op === "ge") ok = argLit >= n;
|
|
2009
|
+
if (p.op === "lt") ok = argLit < n;
|
|
2010
|
+
if (p.op === "le") ok = argLit <= n;
|
|
1949
2011
|
if (!ok) {
|
|
1950
2012
|
const paramName = entry.param || paramNames[idx] || `arg${idx}`;
|
|
1951
2013
|
out.push({
|
|
@@ -1963,36 +2025,18 @@ function scanCaseInconsistency(source, knownFns, opts) {
|
|
|
1963
2025
|
}
|
|
1964
2026
|
}
|
|
1965
2027
|
};
|
|
1966
|
-
const
|
|
1967
|
-
if (!
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
decl.declarations[0].init.type
|
|
1976
|
-
)
|
|
1977
|
-
))) {
|
|
1978
|
-
const id = decl.type === "FunctionDeclaration" ? decl.id?.name : decl.declarations[0]?.id?.name;
|
|
1979
|
-
if (id && knownFns.includes(id)) {
|
|
1980
|
-
for (const c of obj2.leadingComments ?? []) {
|
|
1981
|
-
const caseArgs = parseCaseArgs(c.value);
|
|
1982
|
-
if (!caseArgs) continue;
|
|
1983
|
-
const caseName = /@nudo:case\s+"([^"]+)"/.exec(c.value)?.[1] ?? "?";
|
|
1984
|
-
checkCaseAgainstReqs(id, caseName, caseArgs, c.loc?.start.line);
|
|
1985
|
-
}
|
|
2028
|
+
for (const scope of listFnDirectiveScopes(file)) {
|
|
2029
|
+
if (!knownFns.includes(scope.name)) continue;
|
|
2030
|
+
for (let ci = 0; ci < scope.commentTexts.length; ci++) {
|
|
2031
|
+
const text = scope.commentTexts[ci];
|
|
2032
|
+
const startLine = scope.commentStartLines[ci] ?? 0;
|
|
2033
|
+
for (const tag of scanCaseTags(text)) {
|
|
2034
|
+
const caseArgs = parseCaseArgs(`@nudo:case "${tag.name}" (${tag.argsText})`);
|
|
2035
|
+
if (!caseArgs) continue;
|
|
2036
|
+
checkCaseAgainstReqs(scope.name, tag.name, caseArgs, startLine);
|
|
1986
2037
|
}
|
|
1987
2038
|
}
|
|
1988
|
-
|
|
1989
|
-
if (key === "loc" || key === "start" || key === "end" || key === "leadingComments") continue;
|
|
1990
|
-
const val = obj2[key];
|
|
1991
|
-
if (Array.isArray(val)) val.forEach(visit);
|
|
1992
|
-
else if (val && typeof val === "object") visit(val);
|
|
1993
|
-
}
|
|
1994
|
-
};
|
|
1995
|
-
visit(file);
|
|
2039
|
+
}
|
|
1996
2040
|
return out;
|
|
1997
2041
|
}
|
|
1998
2042
|
|
|
@@ -2085,7 +2129,8 @@ function sidecarDiagIssues(diags) {
|
|
|
2085
2129
|
const k = `${d.code}\0${d.message}`;
|
|
2086
2130
|
if (seen.has(k)) continue;
|
|
2087
2131
|
seen.add(k);
|
|
2088
|
-
|
|
2132
|
+
const severity = d.code === "nudo:contract-syntax" || d.code === "nudo:directive-syntax" ? "warning" : "error";
|
|
2133
|
+
out.push({ severity, code: d.code, message: d.message });
|
|
2089
2134
|
}
|
|
2090
2135
|
return out;
|
|
2091
2136
|
}
|
|
@@ -2201,7 +2246,7 @@ function checkSourceInner(filePath, source, file, phi, opts, issues, signatures,
|
|
|
2201
2246
|
message: `${name} (export): may throw ${gateDisplay}`,
|
|
2202
2247
|
actual: `${name}(\u2026) throws ${gateDisplay}`,
|
|
2203
2248
|
expected: "entry total, or @nudo:throws / try-catch",
|
|
2204
|
-
suggestion: first.cause ? `${first.cause} \u2192 ${first.kind === "ReferenceError" ? "re-export `export { x } from` \u4E0D\u662F\u5C40\u90E8\u7ED1\u5B9A\u2014\u2014\u6539 `import { x }` / @nudo:throws ReferenceError" : `@nudo:throws ${first.kind}
|
|
2249
|
+
suggestion: first.cause ? `${first.cause} \u2192 ${first.kind === "ReferenceError" ? "re-export `export { x } from` \u4E0D\u662F\u5C40\u90E8\u7ED1\u5B9A\u2014\u2014\u6539 `import { x }` / @nudo:throws ReferenceError" : `@nudo:throws ${first.kind} | sidecar: fn({ \u2026 }): shape({ <body-read fields> }) | refine / guard / try-catch`}` : first.kind === "ReferenceError" ? "re-export `export { x } from` \u4E0D\u662F\u5C40\u90E8\u7ED1\u5B9A\u2014\u2014\u6539 `import { x }` / @nudo:throws ReferenceError" : `@nudo:throws ${first.kind} | sidecar: fn({ \u2026 }): shape({ <body-read fields> }) | refine / guard / try-catch`,
|
|
2205
2250
|
fn: name,
|
|
2206
2251
|
...loc.line !== void 0 ? { line: loc.line } : {},
|
|
2207
2252
|
...loc.column !== void 0 ? { column: loc.column } : {}
|
|
@@ -2246,7 +2291,7 @@ function checkSourceInner(filePath, source, file, phi, opts, issues, signatures,
|
|
|
2246
2291
|
message: `${name} (export): may throw ${gateDisplay}`,
|
|
2247
2292
|
actual: `${formatEntrySigLine(name, g, gateDisplay)}`,
|
|
2248
2293
|
expected: "entry total, or @nudo:throws / try-catch",
|
|
2249
|
-
suggestion: first.cause ? `${first.cause} \u2192 ${first.kind === "ReferenceError" ? "re-export `export { x } from` \u4E0D\u662F\u5C40\u90E8\u7ED1\u5B9A\u2014\u2014\u6539 `import { x }` / @nudo:throws ReferenceError" : `@nudo:throws ${first.kind}
|
|
2294
|
+
suggestion: first.cause ? `${first.cause} \u2192 ${first.kind === "ReferenceError" ? "re-export `export { x } from` \u4E0D\u662F\u5C40\u90E8\u7ED1\u5B9A\u2014\u2014\u6539 `import { x }` / @nudo:throws ReferenceError" : `@nudo:throws ${first.kind} | sidecar: fn({ \u2026 }): shape({ <body-read fields> }) | refine / guard / try-catch`}` : first.kind === "ReferenceError" ? "re-export `export { x } from` \u4E0D\u662F\u5C40\u90E8\u7ED1\u5B9A\u2014\u2014\u6539 `import { x }` / @nudo:throws ReferenceError" : `@nudo:throws ${first.kind} | sidecar: fn({ \u2026 }): shape({ <body-read fields> }) | refine / guard / try-catch`,
|
|
2250
2295
|
fn: name,
|
|
2251
2296
|
...loc.line !== void 0 ? { line: loc.line } : {},
|
|
2252
2297
|
...loc.column !== void 0 ? { column: loc.column } : {}
|
|
@@ -2614,6 +2659,19 @@ function actionsForIssue(i) {
|
|
|
2614
2659
|
label: "migration switch: ignore this throw class on L2"
|
|
2615
2660
|
}
|
|
2616
2661
|
];
|
|
2662
|
+
case "nudo:unproven-return":
|
|
2663
|
+
return [
|
|
2664
|
+
{
|
|
2665
|
+
kind: "relax",
|
|
2666
|
+
label: `relax the return contract${i.fn ? ` of ${i.fn}` : ""} to the inferred surface (review the diff \u2014 not a silent green)`,
|
|
2667
|
+
...i.expected ? { hint: i.expected } : {}
|
|
2668
|
+
},
|
|
2669
|
+
draft,
|
|
2670
|
+
{
|
|
2671
|
+
kind: "info",
|
|
2672
|
+
label: "or narrow the return expression / add a precondition so the bound is implied"
|
|
2673
|
+
}
|
|
2674
|
+
];
|
|
2617
2675
|
case "nudo:unknown-inference":
|
|
2618
2676
|
case "nudo:opaque-result":
|
|
2619
2677
|
return [
|
|
@@ -2979,6 +3037,9 @@ export {
|
|
|
2979
3037
|
$while,
|
|
2980
3038
|
$whileSeq,
|
|
2981
3039
|
$yield,
|
|
3040
|
+
CONSTRAINT_BUILDERS,
|
|
3041
|
+
CONSTRAINT_BUILDER_NAMES,
|
|
3042
|
+
CONSTRAINT_EXPR_RE,
|
|
2982
3043
|
DEFAULT_MAX_LOOP_ITERS,
|
|
2983
3044
|
MAX_EVAL_CALL_DEPTH,
|
|
2984
3045
|
MAX_EVAL_TOTAL_CALLS,
|
|
@@ -2993,6 +3054,7 @@ export {
|
|
|
2993
3054
|
TYPEOF_NAMES,
|
|
2994
3055
|
abs,
|
|
2995
3056
|
absFunction,
|
|
3057
|
+
absOnly,
|
|
2996
3058
|
absShapeKey,
|
|
2997
3059
|
absToConstraint,
|
|
2998
3060
|
absToString,
|
|
@@ -3031,6 +3093,7 @@ export {
|
|
|
3031
3093
|
callAbsMethod,
|
|
3032
3094
|
callAtFunctionBoundary,
|
|
3033
3095
|
callTranspiledExport,
|
|
3096
|
+
callTranspiledExportApply,
|
|
3034
3097
|
callTranspiledExportFull,
|
|
3035
3098
|
canonicalArrayIndex,
|
|
3036
3099
|
checkArg,
|
|
@@ -3090,16 +3153,22 @@ export {
|
|
|
3090
3153
|
evictGeneralizeMemoForPaths,
|
|
3091
3154
|
execNudoModule,
|
|
3092
3155
|
extStateOf,
|
|
3156
|
+
extractBalancedParens,
|
|
3093
3157
|
extractDeclaredThrows,
|
|
3158
|
+
extractFileEnvNames,
|
|
3094
3159
|
extractFn,
|
|
3095
3160
|
extractFnBudget,
|
|
3161
|
+
extractMockModuleRecords,
|
|
3162
|
+
extractNudoImportRecords,
|
|
3096
3163
|
extractNudoImports,
|
|
3097
3164
|
extractRefineReturnFromSource,
|
|
3098
3165
|
extractRefinesFromSource,
|
|
3099
3166
|
falseConstraint,
|
|
3100
3167
|
fillTuple,
|
|
3168
|
+
findFnDirectiveScope,
|
|
3101
3169
|
fn,
|
|
3102
3170
|
fnConstraintToEntryReqs,
|
|
3171
|
+
fnDirectiveCommentLines,
|
|
3103
3172
|
fnOf,
|
|
3104
3173
|
foldRequireSpecArg,
|
|
3105
3174
|
foldStaticStringExpr,
|
|
@@ -3141,6 +3210,7 @@ export {
|
|
|
3141
3210
|
interfaceDiagCount,
|
|
3142
3211
|
interfaceSourceOf,
|
|
3143
3212
|
interfaceTierOf,
|
|
3213
|
+
isAbsApplyResult,
|
|
3144
3214
|
isArrMutator,
|
|
3145
3215
|
isBigPrim,
|
|
3146
3216
|
isDefinitelyFalse,
|
|
@@ -3174,6 +3244,7 @@ export {
|
|
|
3174
3244
|
leavePromiseExecutorScope,
|
|
3175
3245
|
lenTerm,
|
|
3176
3246
|
leqAbs,
|
|
3247
|
+
listFnDirectiveScopes,
|
|
3177
3248
|
listFunctionNames,
|
|
3178
3249
|
lit,
|
|
3179
3250
|
litC,
|
|
@@ -3186,6 +3257,7 @@ export {
|
|
|
3186
3257
|
looseEqAbs,
|
|
3187
3258
|
lt,
|
|
3188
3259
|
ltNum,
|
|
3260
|
+
makeAbsApplyResult,
|
|
3189
3261
|
makeArrayCtorAbs,
|
|
3190
3262
|
makeMapAbs,
|
|
3191
3263
|
makeSetAbs,
|
|
@@ -3235,6 +3307,9 @@ export {
|
|
|
3235
3307
|
or,
|
|
3236
3308
|
pFalse,
|
|
3237
3309
|
pTrue,
|
|
3310
|
+
parseEnvPayload,
|
|
3311
|
+
parseMockModulePayload,
|
|
3312
|
+
parseNudoImportPayload,
|
|
3238
3313
|
parseSource,
|
|
3239
3314
|
partial,
|
|
3240
3315
|
phiAnd,
|
|
@@ -3277,6 +3352,11 @@ export {
|
|
|
3277
3352
|
runTranspiledOptionsMemoKey,
|
|
3278
3353
|
runWithLoopExits,
|
|
3279
3354
|
runtimeImportOf,
|
|
3355
|
+
scanBudgetDecl,
|
|
3356
|
+
scanCaseArgSpans,
|
|
3357
|
+
scanCaseTags,
|
|
3358
|
+
scanContractSegments,
|
|
3359
|
+
scanThrowsDecl,
|
|
3280
3360
|
serializeCheckJson,
|
|
3281
3361
|
serializeCheckJsonMulti,
|
|
3282
3362
|
setAddEntry,
|
package/dist/internal.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { I as InterfaceSource, a as InterfaceTierOpts, p as parseSource, C as CheckIssue } from './check-report-
|
|
2
|
-
export { L as LeakBudget, b as LoadDepsFingerprint, M as MAX_PROMISE_MICROS, d as defaultLeakBudget, e as exceedsBudget, c as extractAllLoadSpecs, g as getPromiseMicrosLength, l as leakIfNeeded, f as loadModuleDepsFingerprint, m as maybeLeak, n as normPath, r as resetLeakCounter, h as resolveDepPath, s as sidecarSpecsOf, t as termDepth,
|
|
3
|
-
import { A as Abs, T as Term, c as AstEnv } from './run-
|
|
4
|
-
export { $ as $tryDigestSoft, d as $tryMarkSoft, e as $tryReleaseSoft, E as ERROR_FAMILY, f as EvalFallbackStats, M as MayThrowEffect, g as
|
|
1
|
+
import { I as InterfaceSource, a as InterfaceTierOpts, p as parseSource, C as CheckIssue } from './check-report-Ci1dDysO.js';
|
|
2
|
+
export { L as LeakBudget, b as LoadDepsFingerprint, M as MAX_PROMISE_MICROS, d as defaultLeakBudget, e as exceedsBudget, c as extractAllLoadSpecs, g as getPromiseMicrosLength, l as leakIfNeeded, f as loadModuleDepsFingerprint, m as maybeLeak, n as normPath, r as resetLeakCounter, h as resolveDepPath, s as sidecarSpecsOf, i as stablePathKey, j as stablePathKeyGraph, t as termDepth, k as termNodes } from './check-report-Ci1dDysO.js';
|
|
3
|
+
import { A as Abs, T as Term, c as AstEnv } from './run-WJfj477N.js';
|
|
4
|
+
export { $ as $tryDigestSoft, d as $tryMarkSoft, e as $tryReleaseSoft, E as ERROR_FAMILY, f as EvalFallbackStats, M as MayThrowEffect, g as clearPureCallMemo, h as clearPureMemo, i as enterEvalCallBudgetSession, j as errorTypeAbs, k as exitEvalCallBudgetSession, l as filterDeclaredThrows, m as filterGateThrows, n as filterIgnoredThrows, o as flushMayThrowEffects, p as formatThrowsAbs, q as getEvalCallBudgetState, r as getEvalFallbackStats, s as getMayThrowCollector, t as isThrowsIgnored, u as mayThrowEffectsToAbs, v as orphanMayThrowEffects, w as popMayThrowFrame, x as pushMayThrowFrame, y as recordMayThrow, z as resetEvalFallbackStats, B as runWithMayThrowSession, D as setMayThrowCollector, F as throwAbsToKinds, G as throwsKindCovered, H as withEvalBudgetOverride } from './run-WJfj477N.js';
|
|
5
5
|
import { File, Node } from '@babel/types';
|
|
6
6
|
|
|
7
7
|
/**
|