@nudojs/core 1.2.2 → 1.3.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-0B9Z66n0.d.ts → check-report-BWmfy810.d.ts} +54 -2
- package/dist/{chunk-TOURNNEA.js → chunk-5YNR4Q7E.js} +382 -130
- package/dist/{chunk-4V3CRVSD.js → chunk-CKH6GQAI.js} +3222 -2095
- package/dist/exec.d.ts +598 -3
- package/dist/exec.js +13 -1
- package/dist/index.d.ts +14 -29
- package/dist/index.js +338 -225
- package/dist/internal.d.ts +111 -7
- package/dist/internal.js +65 -3
- package/dist/{hof-types-DqDpAxfh.d.ts → run-Dk08Q5zl.d.ts} +206 -2
- package/package.json +1 -1
- package/dist/index-BNiZvVHw.d.ts +0 -739
package/dist/index.js
CHANGED
|
@@ -9,12 +9,14 @@ import {
|
|
|
9
9
|
buildArgsFromAssume,
|
|
10
10
|
canSkipLiteralCallScan,
|
|
11
11
|
collectAbsFreeVars,
|
|
12
|
+
constraintAdmitsNullish,
|
|
12
13
|
constraintToEntryAbs,
|
|
13
14
|
effectiveInterface,
|
|
14
15
|
evictGeneralizeMemoForPaths,
|
|
15
16
|
execNudoModule,
|
|
16
17
|
extractDeclaredThrows,
|
|
17
18
|
extractFn,
|
|
19
|
+
extractFnBudget,
|
|
18
20
|
extractNudoImports,
|
|
19
21
|
extractRefineReturnFromSource,
|
|
20
22
|
extractRefinesFromSource,
|
|
@@ -30,6 +32,7 @@ import {
|
|
|
30
32
|
getTerm,
|
|
31
33
|
hashSource,
|
|
32
34
|
instantiateConstraint,
|
|
35
|
+
instantiateOnTerm,
|
|
33
36
|
interfaceDiagCount,
|
|
34
37
|
interfaceSourceOf,
|
|
35
38
|
interfaceTierOf,
|
|
@@ -44,6 +47,7 @@ import {
|
|
|
44
47
|
loadModuleDepsFingerprint,
|
|
45
48
|
localNamedExports,
|
|
46
49
|
normPath,
|
|
50
|
+
nullable,
|
|
47
51
|
number,
|
|
48
52
|
omit,
|
|
49
53
|
partial,
|
|
@@ -53,6 +57,7 @@ import {
|
|
|
53
57
|
resetGeneralizeMemo,
|
|
54
58
|
resetHashSourceCache,
|
|
55
59
|
resetNudoModuleExecCache,
|
|
60
|
+
resetSidecarLoadFailureCache,
|
|
56
61
|
scanLiteralCalls,
|
|
57
62
|
setInterfaceDiagCollector,
|
|
58
63
|
setRefineDiagCollector,
|
|
@@ -67,7 +72,7 @@ import {
|
|
|
67
72
|
takeRefineDiagsSince,
|
|
68
73
|
throwConstraintToKinds,
|
|
69
74
|
union
|
|
70
|
-
} from "./chunk-
|
|
75
|
+
} from "./chunk-5YNR4Q7E.js";
|
|
71
76
|
import {
|
|
72
77
|
$add,
|
|
73
78
|
$arguments,
|
|
@@ -189,6 +194,8 @@ import {
|
|
|
189
194
|
NudoThrow,
|
|
190
195
|
NudoUnsupportedError,
|
|
191
196
|
OBJECT_PROTO_METHOD_NAMES,
|
|
197
|
+
PROMISE_MICRO_ERROR_LABEL,
|
|
198
|
+
PROMISE_MICRO_OVERFLOW_LABEL,
|
|
192
199
|
RUNTIME_IMPORT_RE,
|
|
193
200
|
TYPEOF_NAMES,
|
|
194
201
|
abs,
|
|
@@ -206,10 +213,12 @@ import {
|
|
|
206
213
|
asAbs,
|
|
207
214
|
asAbsVal,
|
|
208
215
|
assignSourceSlots,
|
|
216
|
+
assumeFinite,
|
|
209
217
|
attachFnImpl,
|
|
210
218
|
beginCollectionFork,
|
|
211
219
|
betaOf,
|
|
212
220
|
bigintLit,
|
|
221
|
+
bindImports,
|
|
213
222
|
bindingsOf,
|
|
214
223
|
bitandAbs,
|
|
215
224
|
bitnotAbs,
|
|
@@ -228,6 +237,7 @@ import {
|
|
|
228
237
|
clearCollectionTables,
|
|
229
238
|
clearStaleTermPred,
|
|
230
239
|
cmp,
|
|
240
|
+
collectAbsExports,
|
|
231
241
|
collectionElementJoin,
|
|
232
242
|
collectionExactLen,
|
|
233
243
|
confJoin,
|
|
@@ -275,6 +285,7 @@ import {
|
|
|
275
285
|
foldRequireSpecArg,
|
|
276
286
|
foldStaticStringExpr,
|
|
277
287
|
formalParamDisplayNames,
|
|
288
|
+
formalParamSignatureNames,
|
|
278
289
|
formalParamsFromNodes,
|
|
279
290
|
formatAbs,
|
|
280
291
|
formatAbsMultiline,
|
|
@@ -295,6 +306,7 @@ import {
|
|
|
295
306
|
gt,
|
|
296
307
|
gtNum,
|
|
297
308
|
hostBuiltinCtorName,
|
|
309
|
+
identBoundaryRegex,
|
|
298
310
|
implies,
|
|
299
311
|
instantiateReturn,
|
|
300
312
|
isArrMutator,
|
|
@@ -357,6 +369,7 @@ import {
|
|
|
357
369
|
migrateNullProto,
|
|
358
370
|
mod,
|
|
359
371
|
mul,
|
|
372
|
+
namespaceAbsOf,
|
|
360
373
|
namespaceNameOf,
|
|
361
374
|
ne,
|
|
362
375
|
negAbs,
|
|
@@ -438,6 +451,7 @@ import {
|
|
|
438
451
|
strLit,
|
|
439
452
|
strictEqAbs,
|
|
440
453
|
stringOfSymbol,
|
|
454
|
+
stripStringsKeepComments,
|
|
441
455
|
stripTypes,
|
|
442
456
|
sub,
|
|
443
457
|
substAbs,
|
|
@@ -470,7 +484,7 @@ import {
|
|
|
470
484
|
v,
|
|
471
485
|
withExecPhi,
|
|
472
486
|
withVar
|
|
473
|
-
} from "./chunk-
|
|
487
|
+
} from "./chunk-CKH6GQAI.js";
|
|
474
488
|
|
|
475
489
|
// src/environment.ts
|
|
476
490
|
function createEnvironment(parent, bindings = /* @__PURE__ */ new Map()) {
|
|
@@ -703,6 +717,252 @@ function formatDiagnostics(diags) {
|
|
|
703
717
|
}).join("\n");
|
|
704
718
|
}
|
|
705
719
|
|
|
720
|
+
// src/algebra/postcondition.ts
|
|
721
|
+
function proved() {
|
|
722
|
+
return { status: "proved" };
|
|
723
|
+
}
|
|
724
|
+
function disproved(reason) {
|
|
725
|
+
return { status: "disproved", reason };
|
|
726
|
+
}
|
|
727
|
+
function unprovable(reason) {
|
|
728
|
+
return { status: "unprovable", reason };
|
|
729
|
+
}
|
|
730
|
+
var RET_ANCHOR = "__nudo_return__";
|
|
731
|
+
function retAnchorTerm(ret) {
|
|
732
|
+
return ret.term ?? v(RET_ANCHOR);
|
|
733
|
+
}
|
|
734
|
+
function isValueSetUnknown(ret) {
|
|
735
|
+
if (ret.conf === "opaque" || ret.conf === "widened" || ret.conf === "mock") {
|
|
736
|
+
return true;
|
|
737
|
+
}
|
|
738
|
+
if (ret.shape.k === "unknown" && !ret.term) return true;
|
|
739
|
+
if (ret.shape.k === "any") return true;
|
|
740
|
+
return false;
|
|
741
|
+
}
|
|
742
|
+
function isBoundedEvidenceMissing(ret, constraint) {
|
|
743
|
+
if (constraint.preds.length === 0 && !constraint.members) return false;
|
|
744
|
+
if (ret.term?.op === "lit") return false;
|
|
745
|
+
if (ret.pred && ret.pred.op !== "true") return false;
|
|
746
|
+
return true;
|
|
747
|
+
}
|
|
748
|
+
function assertImplies(ret, constraint, opts) {
|
|
749
|
+
const phi = opts?.phi ?? pTrue;
|
|
750
|
+
if (ret.shape.k === "never") return proved();
|
|
751
|
+
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
|
+
if (isValueSetUnknown(ret)) {
|
|
768
|
+
return unprovable(
|
|
769
|
+
ret.shape.k === "any" ? "any does not establish the return contract" : "inference failure (unknown/opaque) \u2014 cannot prove the return contract"
|
|
770
|
+
);
|
|
771
|
+
}
|
|
772
|
+
if (constraint.members && constraint.members.length > 0) {
|
|
773
|
+
let sawUnprovable = false;
|
|
774
|
+
for (const m of constraint.members) {
|
|
775
|
+
const r = assertImplies(ret, m, opts);
|
|
776
|
+
if (r.status === "proved") return proved();
|
|
777
|
+
if (r.status === "unprovable") sawUnprovable = true;
|
|
778
|
+
}
|
|
779
|
+
return sawUnprovable ? unprovable("union: no member proved the return contract") : disproved(`return \u22AD union(${constraint.members.map((m) => formatConstraint(m)).join(", ")})`);
|
|
780
|
+
}
|
|
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
|
+
if (constraint.fields) {
|
|
792
|
+
return assertShapeFields(ret, constraint, opts);
|
|
793
|
+
}
|
|
794
|
+
if (constraint.element) {
|
|
795
|
+
if (ret.shape.k !== "arr" && ret.shape.k !== "tuple") {
|
|
796
|
+
return disproved(`return shape ${ret.shape.k} \u22AD array(...)`);
|
|
797
|
+
}
|
|
798
|
+
return proved();
|
|
799
|
+
}
|
|
800
|
+
if (constraint.fn) return proved();
|
|
801
|
+
return assertScalar(ret, constraint, phi);
|
|
802
|
+
}
|
|
803
|
+
function isAnyConstraint(c) {
|
|
804
|
+
return !c.prim && c.preds.length === 0 && !c.fields && !c.element && !c.members && !c.fn && !isIntFlag(c);
|
|
805
|
+
}
|
|
806
|
+
function assertShapeFields(ret, constraint, opts) {
|
|
807
|
+
let slots;
|
|
808
|
+
if (ret.shape.k === "obj") {
|
|
809
|
+
slots = ret.shape.slots;
|
|
810
|
+
} else if (ret.shape.k === "brand") {
|
|
811
|
+
const inner = ret.shape.shape;
|
|
812
|
+
if (inner.shape.k === "obj") slots = inner.shape.slots;
|
|
813
|
+
}
|
|
814
|
+
if (!slots) {
|
|
815
|
+
return disproved(`return shape ${ret.shape.k} \u22AD object shape`);
|
|
816
|
+
}
|
|
817
|
+
for (const [key, field] of Object.entries(constraint.fields)) {
|
|
818
|
+
const slot = getSlot(slots, key);
|
|
819
|
+
if (!slot) {
|
|
820
|
+
if (!field.optional && !field.constraint.isOptional) {
|
|
821
|
+
return disproved(`missing field ${key}`);
|
|
822
|
+
}
|
|
823
|
+
continue;
|
|
824
|
+
}
|
|
825
|
+
const r = assertImplies(slot.value, field.constraint, opts);
|
|
826
|
+
if (r.status === "disproved") {
|
|
827
|
+
return disproved(`field ${key}: ${r.reason}`);
|
|
828
|
+
}
|
|
829
|
+
if (r.status === "unprovable") {
|
|
830
|
+
return unprovable(`field ${key}: ${r.reason}`);
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
return proved();
|
|
834
|
+
}
|
|
835
|
+
function assertScalar(ret, constraint, phi) {
|
|
836
|
+
if (constraint.prim) {
|
|
837
|
+
const retPrim = primOfAbs(ret);
|
|
838
|
+
if (retPrim && retPrim !== constraint.prim) {
|
|
839
|
+
return disproved(`typeof return = "${retPrim}" \u22AD "${constraint.prim}"`);
|
|
840
|
+
}
|
|
841
|
+
if (!retPrim && ret.shape.k !== "sum" && ret.shape.k !== "never") {
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
if (isIntFlag(constraint) && constraint.prim === "number") {
|
|
845
|
+
const lv2 = litValue(ret);
|
|
846
|
+
if (typeof lv2 === "number" && !Number.isInteger(lv2)) {
|
|
847
|
+
return disproved(`return ${lv2} \u22AD int`);
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
const t = retAnchorTerm(ret);
|
|
851
|
+
const constraintPred = instantiateOnTerm(constraint, t);
|
|
852
|
+
const retPred = ret.pred && ret.pred.op !== "true" ? phi.op === "true" ? ret.pred : and(phi, ret.pred) : phi;
|
|
853
|
+
if (constraint.preds.length === 0 && constraintPred.op === "true") {
|
|
854
|
+
return proved();
|
|
855
|
+
}
|
|
856
|
+
if (constraint.preds.length === 0 && constraintPred.op === "typeof" && constraint.prim) {
|
|
857
|
+
return proved();
|
|
858
|
+
}
|
|
859
|
+
if (constraintPred.op !== "true") {
|
|
860
|
+
if (implies(retPred, constraintPred)) return proved();
|
|
861
|
+
if (ret.pred && ret.pred.op !== "true" && numericBoundsImplyLocal(ret.pred, constraintPred)) {
|
|
862
|
+
return proved();
|
|
863
|
+
}
|
|
864
|
+
if (isBoundedEvidenceMissing(ret, constraint)) {
|
|
865
|
+
return unprovable(
|
|
866
|
+
`cannot prove return satisfies ${formatConstraint(constraint)} (no bound evidence on the return value)`
|
|
867
|
+
);
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
const lv = litValue(ret);
|
|
871
|
+
if (lv !== void 0 && (typeof lv === "number" || typeof lv === "string" || typeof lv === "boolean" || lv === null)) {
|
|
872
|
+
if (literalMeetsConstraint(lv, constraint)) {
|
|
873
|
+
return proved();
|
|
874
|
+
}
|
|
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
|
+
}
|
|
883
|
+
if (constraintPred.op !== "true" || constraint.preds.length > 0) {
|
|
884
|
+
if (isBoundedEvidenceMissing(ret, constraint)) {
|
|
885
|
+
return unprovable(
|
|
886
|
+
`cannot prove return satisfies ${formatConstraint(constraint)} (no bound evidence on the return value)`
|
|
887
|
+
);
|
|
888
|
+
}
|
|
889
|
+
return disproved(
|
|
890
|
+
`return (${formatAbs(ret)}) \u22AD ${formatConstraint(constraint)} (postcondition not implied)`
|
|
891
|
+
);
|
|
892
|
+
}
|
|
893
|
+
return proved();
|
|
894
|
+
}
|
|
895
|
+
function numericBoundsImplyLocal(src, tgt) {
|
|
896
|
+
const one = (p) => p.op === "gt" || p.op === "ge" || p.op === "lt" || p.op === "le";
|
|
897
|
+
if (!one(src) || !one(tgt)) return false;
|
|
898
|
+
if (src.op !== tgt.op) {
|
|
899
|
+
if (src.op === "gt" && tgt.op === "ge") {
|
|
900
|
+
return sameTermSide(src, tgt) && litGE(src.b, tgt.b);
|
|
901
|
+
}
|
|
902
|
+
if (src.op === "lt" && tgt.op === "le") {
|
|
903
|
+
return sameTermSide(src, tgt) && litLE(src.b, tgt.b);
|
|
904
|
+
}
|
|
905
|
+
return false;
|
|
906
|
+
}
|
|
907
|
+
if (!sameTermSide(src, tgt)) return false;
|
|
908
|
+
const sb = src.b.op === "lit" ? src.b.value : void 0;
|
|
909
|
+
const tb = tgt.b.op === "lit" ? tgt.b.value : void 0;
|
|
910
|
+
if (typeof sb !== "number" || typeof tb !== "number") return false;
|
|
911
|
+
if (src.op === "gt" || src.op === "ge") return sb >= tb;
|
|
912
|
+
return sb <= tb;
|
|
913
|
+
}
|
|
914
|
+
function sameTermSide(a, b) {
|
|
915
|
+
return a.a.op === b.a.op && termEquals(a.a, b.a);
|
|
916
|
+
}
|
|
917
|
+
function litGE(a, b) {
|
|
918
|
+
if (a.op !== "lit" || b.op !== "lit") return false;
|
|
919
|
+
return typeof a.value === "number" && typeof b.value === "number" && a.value >= b.value;
|
|
920
|
+
}
|
|
921
|
+
function litLE(a, b) {
|
|
922
|
+
if (a.op !== "lit" || b.op !== "lit") return false;
|
|
923
|
+
return typeof a.value === "number" && typeof b.value === "number" && a.value <= b.value;
|
|
924
|
+
}
|
|
925
|
+
function primOfAbs(a) {
|
|
926
|
+
if (a.shape.k === "prim") return a.shape.type;
|
|
927
|
+
const lv = litValue(a);
|
|
928
|
+
if (typeof lv === "number") return "number";
|
|
929
|
+
if (typeof lv === "string") return "string";
|
|
930
|
+
if (typeof lv === "boolean") return "boolean";
|
|
931
|
+
if (typeof lv === "bigint") return "bigint";
|
|
932
|
+
return void 0;
|
|
933
|
+
}
|
|
934
|
+
function describeBoundViolation(lv, constraint) {
|
|
935
|
+
const opSym = { gt: ">", ge: "\u2265", lt: "<", le: "\u2264" };
|
|
936
|
+
for (const p of constraint.preds) {
|
|
937
|
+
for (const atom of p.op === "and" ? p.args : [p]) {
|
|
938
|
+
if (atom.op !== "gt" && atom.op !== "ge" && atom.op !== "lt" && atom.op !== "le") continue;
|
|
939
|
+
if (atom.b.op !== "lit" || typeof atom.b.value !== "number") continue;
|
|
940
|
+
const n = atom.b.value;
|
|
941
|
+
const sym = opSym[atom.op];
|
|
942
|
+
if (typeof lv === "number") {
|
|
943
|
+
let ok = true;
|
|
944
|
+
if (atom.op === "gt") ok = lv > n;
|
|
945
|
+
if (atom.op === "ge") ok = lv >= n;
|
|
946
|
+
if (atom.op === "lt") ok = lv < n;
|
|
947
|
+
if (atom.op === "le") ok = lv <= n;
|
|
948
|
+
if (!ok) return `return ${sym} ${n}`;
|
|
949
|
+
}
|
|
950
|
+
if (typeof lv === "string" && isLengthSelfTerm(atom.a)) {
|
|
951
|
+
let ok = true;
|
|
952
|
+
if (atom.op === "gt") ok = lv.length > n;
|
|
953
|
+
if (atom.op === "ge") ok = lv.length >= n;
|
|
954
|
+
if (atom.op === "lt") ok = lv.length < n;
|
|
955
|
+
if (atom.op === "le") ok = lv.length <= n;
|
|
956
|
+
if (!ok) return `length(self) ${sym} ${n}`;
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
return void 0;
|
|
961
|
+
}
|
|
962
|
+
function isLengthSelfTerm(t) {
|
|
963
|
+
return t.op === "app" && t.fn === "length" && t.args.length === 1 && t.args[0].op === "var" && t.args[0].id === SELF;
|
|
964
|
+
}
|
|
965
|
+
|
|
706
966
|
// src/algebra/projection.ts
|
|
707
967
|
var PROJECTABLE_CONF = /* @__PURE__ */ new Set(["exact", "path"]);
|
|
708
968
|
var ARR_FALLBACK_CONF = /* @__PURE__ */ new Set([
|
|
@@ -1137,8 +1397,9 @@ function estimateEntryParamCount(source, fnName, file) {
|
|
|
1137
1397
|
}
|
|
1138
1398
|
} catch {
|
|
1139
1399
|
}
|
|
1400
|
+
const name = identBoundaryRegex(fnName);
|
|
1140
1401
|
const re = new RegExp(
|
|
1141
|
-
`(?:function\\s+${
|
|
1402
|
+
`(?:function\\s+${name}\\s*\\(([^)]*)\\)|${name}\\s*=\\s*(?:async\\s*)?function(?:\\s+${name})?\\s*\\(([^)]*)\\)|${name}\\s*=\\s*(?:async\\s*)?\\(([^)]*)\\)\\s*=>)`
|
|
1142
1403
|
);
|
|
1143
1404
|
const m = re.exec(source);
|
|
1144
1405
|
if (m) {
|
|
@@ -1149,13 +1410,15 @@ function estimateEntryParamCount(source, fnName, file) {
|
|
|
1149
1410
|
return 1;
|
|
1150
1411
|
}
|
|
1151
1412
|
function isDefaultExportName(source, fnName) {
|
|
1413
|
+
const name = identBoundaryRegex(fnName);
|
|
1152
1414
|
const re = new RegExp(
|
|
1153
|
-
`export\\s+default\\s+(?:async\\s+)?(?:function\\s+${
|
|
1415
|
+
`export\\s+default\\s+(?:async\\s+)?(?:function\\s+${name}|${name})`
|
|
1154
1416
|
);
|
|
1155
1417
|
return re.test(source);
|
|
1156
1418
|
}
|
|
1157
1419
|
function formatEntrySigLine(name, g, throws) {
|
|
1158
|
-
const
|
|
1420
|
+
const names = g.formals && g.formals.length > 0 ? formalParamSignatureNames(g.formals) : g.params;
|
|
1421
|
+
const ps = names.map((p, i) => {
|
|
1159
1422
|
const t = g.typeParams[i]?.value;
|
|
1160
1423
|
const shown = !t ? "any" : t.shape.k === "unknown" ? "unknown" : formatShape(t);
|
|
1161
1424
|
return `${p}: ${shown}`;
|
|
@@ -1219,6 +1482,7 @@ function resetCheckSourceMemo() {
|
|
|
1219
1482
|
checkKeyDeps.clear();
|
|
1220
1483
|
checkDepIndex.clear();
|
|
1221
1484
|
resetHashSourceCache();
|
|
1485
|
+
resetSidecarLoadFailureCache();
|
|
1222
1486
|
}
|
|
1223
1487
|
function loadModuleId(fn2) {
|
|
1224
1488
|
if (!fn2) return 0;
|
|
@@ -1525,8 +1789,9 @@ function projectCaseArgField(arg, field) {
|
|
|
1525
1789
|
}
|
|
1526
1790
|
function scanCaseInconsistency(source, knownFns, opts) {
|
|
1527
1791
|
const out = [];
|
|
1528
|
-
|
|
1529
|
-
|
|
1792
|
+
const directiveSrc = stripStringsKeepComments(source);
|
|
1793
|
+
if (!directiveSrc.includes("@nudo:case")) return out;
|
|
1794
|
+
const hasContractOrigin = directiveSrc.includes("@nudo:contract") || opts.sidecarPresent === true;
|
|
1530
1795
|
if (!hasContractOrigin) return out;
|
|
1531
1796
|
const file = opts.file ?? parseSource(source);
|
|
1532
1797
|
const parseLitArg = (s) => {
|
|
@@ -1749,6 +2014,7 @@ function checkSource(filePath, source, phi = pTrue, opts = {}) {
|
|
|
1749
2014
|
}
|
|
1750
2015
|
setRefineDiagCollector(null);
|
|
1751
2016
|
setInterfaceDiagCollector(null);
|
|
2017
|
+
resetSidecarLoadFailureCache();
|
|
1752
2018
|
const refineSince = refineDiagCount();
|
|
1753
2019
|
const ifaceSince = interfaceDiagCount();
|
|
1754
2020
|
const useMemo = phi.op === "true";
|
|
@@ -1824,7 +2090,7 @@ function sidecarDiagIssues(diags) {
|
|
|
1824
2090
|
return out;
|
|
1825
2091
|
}
|
|
1826
2092
|
function checkSourceInner(filePath, source, file, phi, opts, issues, signatures, names, truncated, identityOpts = opts, depsFp, sidecarFp) {
|
|
1827
|
-
const hasRefineDirective = source
|
|
2093
|
+
const hasRefineDirective = stripStringsKeepComments(source).includes("@nudo:contract");
|
|
1828
2094
|
const exportedNames = sidecarFp !== void 0 ? localNamedExports(source) : void 0;
|
|
1829
2095
|
const entryNames = localNamedExports(source);
|
|
1830
2096
|
const entryThrowsMode = opts.entryThrows ?? "error";
|
|
@@ -1889,7 +2155,7 @@ function checkSourceInner(filePath, source, file, phi, opts, issues, signatures,
|
|
|
1889
2155
|
eff.returns.constraint,
|
|
1890
2156
|
declared
|
|
1891
2157
|
);
|
|
1892
|
-
if (retIssues.
|
|
2158
|
+
if (retIssues.some((i) => i.severity === "error")) returnViolated.add(name);
|
|
1893
2159
|
issues.push(...retIssues);
|
|
1894
2160
|
}
|
|
1895
2161
|
continue;
|
|
@@ -1935,7 +2201,7 @@ function checkSourceInner(filePath, source, file, phi, opts, issues, signatures,
|
|
|
1935
2201
|
message: `${name} (export): may throw ${gateDisplay}`,
|
|
1936
2202
|
actual: `${name}(\u2026) throws ${gateDisplay}`,
|
|
1937
2203
|
expected: "entry total, or @nudo:throws / try-catch",
|
|
1938
|
-
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} / 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} / refine / guard / 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} / sidecar fn({ \u2026 }) contract / 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 }) contract / refine / guard / try-catch`,
|
|
1939
2205
|
fn: name,
|
|
1940
2206
|
...loc.line !== void 0 ? { line: loc.line } : {},
|
|
1941
2207
|
...loc.column !== void 0 ? { column: loc.column } : {}
|
|
@@ -1980,7 +2246,7 @@ function checkSourceInner(filePath, source, file, phi, opts, issues, signatures,
|
|
|
1980
2246
|
message: `${name} (export): may throw ${gateDisplay}`,
|
|
1981
2247
|
actual: `${formatEntrySigLine(name, g, gateDisplay)}`,
|
|
1982
2248
|
expected: "entry total, or @nudo:throws / try-catch",
|
|
1983
|
-
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} / 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} / refine / guard / 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} / sidecar fn({ \u2026 }) contract / 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 }) contract / refine / guard / try-catch`,
|
|
1984
2250
|
fn: name,
|
|
1985
2251
|
...loc.line !== void 0 ? { line: loc.line } : {},
|
|
1986
2252
|
...loc.column !== void 0 ? { column: loc.column } : {}
|
|
@@ -1998,7 +2264,8 @@ function checkSourceInner(filePath, source, file, phi, opts, issues, signatures,
|
|
|
1998
2264
|
});
|
|
1999
2265
|
signatures.push({
|
|
2000
2266
|
name,
|
|
2001
|
-
|
|
2267
|
+
// 解构形参展示 `{ grade, findings }`,不落 `_p0`(#64:契约要上屏)
|
|
2268
|
+
params: g.formals && g.formals.length > 0 ? formalParamSignatureNames(g.formals) : g.params,
|
|
2002
2269
|
paramTypes,
|
|
2003
2270
|
abs: g.symbolic,
|
|
2004
2271
|
display: throwsDisplay ? `${fmt.display} throws ${throwsDisplay}` : fmt.display,
|
|
@@ -2078,7 +2345,7 @@ function checkSourceInner(filePath, source, file, phi, opts, issues, signatures,
|
|
|
2078
2345
|
eff.returns.constraint,
|
|
2079
2346
|
g.symbolic
|
|
2080
2347
|
);
|
|
2081
|
-
if (retIssues.
|
|
2348
|
+
if (retIssues.some((i) => i.severity === "error")) returnViolated.add(name);
|
|
2082
2349
|
issues.push(...retIssues);
|
|
2083
2350
|
}
|
|
2084
2351
|
if (eff && eff.source === "generated") {
|
|
@@ -2105,7 +2372,25 @@ function checkSourceInner(filePath, source, file, phi, opts, issues, signatures,
|
|
|
2105
2372
|
severity: "info",
|
|
2106
2373
|
code: "nudo:fork-truncated",
|
|
2107
2374
|
message: `Branch expansion was truncated (fork budget); affected results widened to unknown#opaque (budget)`,
|
|
2108
|
-
suggestion: "optional:
|
|
2375
|
+
suggestion: "optional: raise nudo.analysis.maxForks, or @nudo:budget forks=\u2026 on the function \u2014 non-blocking"
|
|
2376
|
+
});
|
|
2377
|
+
continue;
|
|
2378
|
+
}
|
|
2379
|
+
if (label === PROMISE_MICRO_OVERFLOW_LABEL) {
|
|
2380
|
+
issues.push({
|
|
2381
|
+
severity: "info",
|
|
2382
|
+
code: "nudo:promise-micro-truncated",
|
|
2383
|
+
message: `Promise microtask queue hit its hard cap; further then/catch callbacks were dropped (results stay fail-closed)`,
|
|
2384
|
+
suggestion: "optional: reduce top-level Promise.then fan-out \u2014 non-blocking"
|
|
2385
|
+
});
|
|
2386
|
+
continue;
|
|
2387
|
+
}
|
|
2388
|
+
if (label === PROMISE_MICRO_ERROR_LABEL) {
|
|
2389
|
+
issues.push({
|
|
2390
|
+
severity: "info",
|
|
2391
|
+
code: "nudo:promise-micro-error",
|
|
2392
|
+
message: `A promise microtask threw while draining; the error was recorded and did not rewrite the synchronous return value`,
|
|
2393
|
+
suggestion: "optional: inspect the then/catch callback for a throw path \u2014 non-blocking"
|
|
2109
2394
|
});
|
|
2110
2395
|
continue;
|
|
2111
2396
|
}
|
|
@@ -2124,7 +2409,7 @@ function checkSourceInner(filePath, source, file, phi, opts, issues, signatures,
|
|
|
2124
2409
|
severity: "info",
|
|
2125
2410
|
code: "nudo:recursion-truncated",
|
|
2126
2411
|
message: `Recursive evaluation of '${label}' was truncated (depth/size budget); result widened to unknown#opaque (budget \u2014 not inference debt)`,
|
|
2127
|
-
suggestion: "narrow the recursion base case
|
|
2412
|
+
suggestion: "raise the function budget with @nudo:budget calls=\u2026 depth=\u2026 (or narrow the recursion base case / declare @nudo:contract return)",
|
|
2128
2413
|
fn: label
|
|
2129
2414
|
});
|
|
2130
2415
|
}
|
|
@@ -2187,7 +2472,7 @@ function checkSourceInner(filePath, source, file, phi, opts, issues, signatures,
|
|
|
2187
2472
|
rc.constraint,
|
|
2188
2473
|
rec.result
|
|
2189
2474
|
);
|
|
2190
|
-
if (retIssues.
|
|
2475
|
+
if (retIssues.some((i) => i.severity === "error")) returnViolated.add(rec.fnName);
|
|
2191
2476
|
issues.push(...retIssues);
|
|
2192
2477
|
}
|
|
2193
2478
|
}
|
|
@@ -2246,118 +2531,33 @@ function checkSourceInner(filePath, source, file, phi, opts, issues, signatures,
|
|
|
2246
2531
|
};
|
|
2247
2532
|
}
|
|
2248
2533
|
function checkReturnConstraint(fnName, cName, constraint, ret) {
|
|
2249
|
-
const
|
|
2250
|
-
if (
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
for (const m of ret.shape.members) {
|
|
2256
|
-
for (const issue of checkReturnConstraint(fnName, cName, constraint, m)) {
|
|
2257
|
-
const key = `${issue.message}\0${issue.actual ?? ""}\0${issue.expected ?? ""}`;
|
|
2258
|
-
if (seen.has(key)) continue;
|
|
2259
|
-
seen.add(key);
|
|
2260
|
-
out.push(issue);
|
|
2261
|
-
}
|
|
2262
|
-
}
|
|
2263
|
-
return out;
|
|
2264
|
-
}
|
|
2265
|
-
const push = (actual, expected, suggestion) => {
|
|
2266
|
-
out.push({
|
|
2267
|
-
severity: "error",
|
|
2268
|
-
code: "nudo:constraint-violated",
|
|
2534
|
+
const proof = assertImplies(ret, constraint);
|
|
2535
|
+
if (proof.status === "proved") return [];
|
|
2536
|
+
const push = (severity, actual, expected, suggestion) => [
|
|
2537
|
+
{
|
|
2538
|
+
severity,
|
|
2539
|
+
code: severity === "error" ? "nudo:constraint-violated" : "nudo:unproven-return",
|
|
2269
2540
|
message: `${fnName}: return value \u22AD @nudo:contract return ${cName}`,
|
|
2270
2541
|
actual,
|
|
2271
2542
|
expected,
|
|
2272
2543
|
suggestion,
|
|
2273
2544
|
fn: fnName
|
|
2274
|
-
});
|
|
2275
|
-
};
|
|
2276
|
-
if (constraint.fields) {
|
|
2277
|
-
const slots = ret.shape.k === "obj" ? ret.shape.slots : void 0;
|
|
2278
|
-
if (!slots) {
|
|
2279
|
-
if (ret.shape.k !== "never") {
|
|
2280
|
-
push(formatAbs(ret), `object shape (${cName})`, `return an object satisfying the ${cName} shape`);
|
|
2281
|
-
}
|
|
2282
|
-
return out;
|
|
2283
2545
|
}
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
if (field.constraint.prim && slot.value.shape.k === "prim") {
|
|
2293
|
-
const actualPrim = slot.value.shape.type;
|
|
2294
|
-
if (actualPrim !== field.constraint.prim) {
|
|
2295
|
-
push(
|
|
2296
|
-
formatAbs(slot.value),
|
|
2297
|
-
`typeof ${key} = "${field.constraint.prim}"`,
|
|
2298
|
-
`change the return value's ${key} to ${field.constraint.prim}`
|
|
2299
|
-
);
|
|
2300
|
-
continue;
|
|
2301
|
-
}
|
|
2302
|
-
}
|
|
2303
|
-
const lv2 = litValue(slot.value);
|
|
2304
|
-
if (lv2 !== void 0 && typeof lv2 === "number") {
|
|
2305
|
-
for (const p of field.constraint.preds) {
|
|
2306
|
-
const flat = p.op === "and" ? p.args : [p];
|
|
2307
|
-
for (const atom of flat) {
|
|
2308
|
-
if ((atom.op === "gt" || atom.op === "ge" || atom.op === "lt" || atom.op === "le") && atom.b.op === "lit" && typeof atom.b.value === "number") {
|
|
2309
|
-
const n = atom.b.value;
|
|
2310
|
-
let ok = true;
|
|
2311
|
-
if (atom.op === "gt") ok = lv2 > n;
|
|
2312
|
-
if (atom.op === "ge") ok = lv2 >= n;
|
|
2313
|
-
if (atom.op === "lt") ok = lv2 < n;
|
|
2314
|
-
if (atom.op === "le") ok = lv2 <= n;
|
|
2315
|
-
if (!ok) {
|
|
2316
|
-
const opSym = { gt: ">", ge: "\u2265", lt: "<", le: "\u2264" }[atom.op];
|
|
2317
|
-
push(
|
|
2318
|
-
formatAbs(slot.value),
|
|
2319
|
-
`${key} ${opSym} ${n}`,
|
|
2320
|
-
`the return value's ${key} should satisfy ${key} ${opSym} ${n}`
|
|
2321
|
-
);
|
|
2322
|
-
}
|
|
2323
|
-
}
|
|
2324
|
-
}
|
|
2325
|
-
}
|
|
2326
|
-
}
|
|
2327
|
-
}
|
|
2328
|
-
return out;
|
|
2329
|
-
}
|
|
2330
|
-
if (constraint.prim && ret.shape.k === "prim") {
|
|
2331
|
-
const actualPrim = ret.shape.type;
|
|
2332
|
-
if (actualPrim !== constraint.prim) {
|
|
2333
|
-
push(formatAbs(ret), `typeof return = "${constraint.prim}"`, `return ${constraint.prim}`);
|
|
2334
|
-
return out;
|
|
2335
|
-
}
|
|
2336
|
-
}
|
|
2337
|
-
const lv = litValue(ret);
|
|
2338
|
-
if (lv !== void 0 && typeof lv === "number") {
|
|
2339
|
-
for (const p of constraint.preds) {
|
|
2340
|
-
const flat = p.op === "and" ? p.args : [p];
|
|
2341
|
-
for (const atom of flat) {
|
|
2342
|
-
if ((atom.op === "gt" || atom.op === "ge" || atom.op === "lt" || atom.op === "le") && atom.b.op === "lit" && typeof atom.b.value === "number") {
|
|
2343
|
-
const n = atom.b.value;
|
|
2344
|
-
let ok = true;
|
|
2345
|
-
if (atom.op === "gt") ok = lv > n;
|
|
2346
|
-
if (atom.op === "ge") ok = lv >= n;
|
|
2347
|
-
if (atom.op === "lt") ok = lv < n;
|
|
2348
|
-
if (atom.op === "le") ok = lv <= n;
|
|
2349
|
-
if (!ok) {
|
|
2350
|
-
const opSym = { gt: ">", ge: "\u2265", lt: "<", le: "\u2264" }[atom.op];
|
|
2351
|
-
push(formatAbs(ret), `return ${opSym} ${n}`, `return a value satisfying ${opSym} ${n}`);
|
|
2352
|
-
}
|
|
2353
|
-
}
|
|
2354
|
-
}
|
|
2355
|
-
}
|
|
2356
|
-
}
|
|
2357
|
-
if (lv !== void 0 && (typeof lv === "number" || typeof lv === "string" || typeof lv === "boolean") && ((constraint.members?.length ?? 0) > 0 || constraint.preds.some((p) => p.op === "eq") || typeof lv === "string" && constraint.preds.length > 0) && !literalMeetsConstraint(lv, constraint)) {
|
|
2358
|
-
push(formatAbs(ret), formatConstraint(constraint), `return a value satisfying ${formatConstraint(constraint)}`);
|
|
2546
|
+
];
|
|
2547
|
+
if (proof.status === "disproved") {
|
|
2548
|
+
return push(
|
|
2549
|
+
"error",
|
|
2550
|
+
formatAbs(ret),
|
|
2551
|
+
proof.reason,
|
|
2552
|
+
proof.reason.includes("nullish") ? `use nullable(${formatConstraint(constraint)}) or union(..., lit(null)) to allow nullish returns` : `return a value satisfying ${formatConstraint(constraint)}`
|
|
2553
|
+
);
|
|
2359
2554
|
}
|
|
2360
|
-
return
|
|
2555
|
+
return push(
|
|
2556
|
+
"warning",
|
|
2557
|
+
formatAbs(ret),
|
|
2558
|
+
formatConstraint(constraint),
|
|
2559
|
+
`${proof.reason}; add a precondition, narrow the return expression, or relax the return contract`
|
|
2560
|
+
);
|
|
2361
2561
|
}
|
|
2362
2562
|
|
|
2363
2563
|
// src/algebra/check-report.ts
|
|
@@ -2393,6 +2593,12 @@ function actionsForIssue(i) {
|
|
|
2393
2593
|
];
|
|
2394
2594
|
case "nudo:entry-may-throw":
|
|
2395
2595
|
return [
|
|
2596
|
+
{
|
|
2597
|
+
kind: "draft",
|
|
2598
|
+
command: "nudo contract --draft",
|
|
2599
|
+
label: "narrow the entry with a sidecar fn({ \u2026 }) param contract \u2014 most honest fix for helpers (also tightens the signature)",
|
|
2600
|
+
...i.fn ? { hint: i.fn } : {}
|
|
2601
|
+
},
|
|
2396
2602
|
{
|
|
2397
2603
|
kind: "relax",
|
|
2398
2604
|
label: "declare intentional fail-fast: @nudo:throws Error (or case `!! throws`)",
|
|
@@ -2406,8 +2612,7 @@ function actionsForIssue(i) {
|
|
|
2406
2612
|
kind: "ignore-throws",
|
|
2407
2613
|
command: "nudo check --ignore-throws TypeError",
|
|
2408
2614
|
label: "migration switch: ignore this throw class on L2"
|
|
2409
|
-
}
|
|
2410
|
-
draft
|
|
2615
|
+
}
|
|
2411
2616
|
];
|
|
2412
2617
|
case "nudo:unknown-inference":
|
|
2413
2618
|
case "nudo:opaque-result":
|
|
@@ -2424,10 +2629,12 @@ function actionsForIssue(i) {
|
|
|
2424
2629
|
];
|
|
2425
2630
|
case "nudo:fork-truncated":
|
|
2426
2631
|
case "nudo:recursion-truncated":
|
|
2632
|
+
case "nudo:promise-micro-truncated":
|
|
2633
|
+
case "nudo:promise-micro-error":
|
|
2427
2634
|
return [
|
|
2428
2635
|
{
|
|
2429
2636
|
kind: "info",
|
|
2430
|
-
label: "results widened to unknown \u2014 raise budget or narrow control flow"
|
|
2637
|
+
label: "results widened to unknown \u2014 raise budget (@nudo:budget forks/calls/depth on the function) or narrow control flow"
|
|
2431
2638
|
}
|
|
2432
2639
|
];
|
|
2433
2640
|
case "nudo:host-effect-blocked":
|
|
@@ -2661,107 +2868,6 @@ function formatGitlabCodeQuality(r, opts = {}) {
|
|
|
2661
2868
|
};
|
|
2662
2869
|
});
|
|
2663
2870
|
}
|
|
2664
|
-
|
|
2665
|
-
// src/algebra/abs-modules.ts
|
|
2666
|
-
function bindImports(node, env, modules) {
|
|
2667
|
-
const mod2 = modules[node.source.value];
|
|
2668
|
-
if (!mod2) {
|
|
2669
|
-
for (const s of node.specifiers) {
|
|
2670
|
-
env.vars.set(s.local.name, unknown);
|
|
2671
|
-
}
|
|
2672
|
-
return;
|
|
2673
|
-
}
|
|
2674
|
-
for (const s of node.specifiers) {
|
|
2675
|
-
if (s.type === "ImportDefaultSpecifier") {
|
|
2676
|
-
env.vars.set(s.local.name, mod2.default ?? unknown);
|
|
2677
|
-
} else if (s.type === "ImportSpecifier") {
|
|
2678
|
-
const imported = s.imported.type === "Identifier" ? s.imported.name : String(s.imported);
|
|
2679
|
-
env.vars.set(s.local.name, mod2.named[imported] ?? unknown);
|
|
2680
|
-
} else if (s.type === "ImportNamespaceSpecifier") {
|
|
2681
|
-
const slots = {};
|
|
2682
|
-
for (const [k, v2] of Object.entries(mod2.named)) slots[k] = { value: v2 };
|
|
2683
|
-
if (mod2.default) slots["default"] = { value: mod2.default };
|
|
2684
|
-
env.vars.set(s.local.name, obj(slots));
|
|
2685
|
-
}
|
|
2686
|
-
}
|
|
2687
|
-
}
|
|
2688
|
-
function fnToAbs(env, name) {
|
|
2689
|
-
const impl = env.fns.get(name);
|
|
2690
|
-
if (!impl) return void 0;
|
|
2691
|
-
return absFunction(impl.params, {
|
|
2692
|
-
body: impl.body,
|
|
2693
|
-
async: impl.async,
|
|
2694
|
-
env
|
|
2695
|
-
});
|
|
2696
|
-
}
|
|
2697
|
-
function lookupExport(env, name) {
|
|
2698
|
-
if (env.vars.has(name)) return env.vars.get(name);
|
|
2699
|
-
return fnToAbs(env, name);
|
|
2700
|
-
}
|
|
2701
|
-
function collectAbsExports(file, env, modules) {
|
|
2702
|
-
const named = {};
|
|
2703
|
-
let defaultExport;
|
|
2704
|
-
for (const stmt of file.program.body) {
|
|
2705
|
-
if (stmt.type === "ExportNamedDeclaration") {
|
|
2706
|
-
if (stmt.source && modules) {
|
|
2707
|
-
const mod2 = modules[stmt.source.value];
|
|
2708
|
-
if (mod2) {
|
|
2709
|
-
for (const spec of stmt.specifiers) {
|
|
2710
|
-
if (spec.type !== "ExportSpecifier") continue;
|
|
2711
|
-
const local = spec.local.type === "Identifier" ? spec.local.name : spec.local.value;
|
|
2712
|
-
const exported = spec.exported.type === "Identifier" ? spec.exported.name : spec.exported.value;
|
|
2713
|
-
const v2 = local === "default" ? mod2.default : mod2.named[local];
|
|
2714
|
-
if (v2 === void 0) continue;
|
|
2715
|
-
if (exported === "default") defaultExport = v2;
|
|
2716
|
-
else named[exported] = v2;
|
|
2717
|
-
}
|
|
2718
|
-
}
|
|
2719
|
-
continue;
|
|
2720
|
-
}
|
|
2721
|
-
const decl = stmt.declaration;
|
|
2722
|
-
if (decl) {
|
|
2723
|
-
if (decl.type === "FunctionDeclaration" && decl.id) {
|
|
2724
|
-
const v2 = lookupExport(env, decl.id.name);
|
|
2725
|
-
if (v2) named[decl.id.name] = v2;
|
|
2726
|
-
} else if (decl.type === "ClassDeclaration" && decl.id) {
|
|
2727
|
-
const v2 = lookupExport(env, decl.id.name);
|
|
2728
|
-
if (v2) named[decl.id.name] = v2;
|
|
2729
|
-
} else if (decl.type === "VariableDeclaration") {
|
|
2730
|
-
for (const d of decl.declarations) {
|
|
2731
|
-
if (d.id.type === "Identifier") {
|
|
2732
|
-
const v2 = lookupExport(env, d.id.name);
|
|
2733
|
-
if (v2) named[d.id.name] = v2;
|
|
2734
|
-
}
|
|
2735
|
-
}
|
|
2736
|
-
}
|
|
2737
|
-
}
|
|
2738
|
-
for (const spec of stmt.specifiers) {
|
|
2739
|
-
if (spec.type !== "ExportSpecifier") continue;
|
|
2740
|
-
const local = spec.local.type === "Identifier" ? spec.local.name : spec.local.value;
|
|
2741
|
-
const exported = spec.exported.type === "Identifier" ? spec.exported.name : spec.exported.value;
|
|
2742
|
-
const v2 = lookupExport(env, local);
|
|
2743
|
-
if (v2) named[exported] = v2;
|
|
2744
|
-
}
|
|
2745
|
-
} else if (stmt.type === "ExportAllDeclaration" && stmt.source && modules) {
|
|
2746
|
-
const mod2 = modules[stmt.source.value];
|
|
2747
|
-
if (mod2?.named) {
|
|
2748
|
-
for (const [k, v2] of Object.entries(mod2.named)) named[k] = v2;
|
|
2749
|
-
}
|
|
2750
|
-
} else if (stmt.type === "ExportDefaultDeclaration") {
|
|
2751
|
-
const d = stmt.declaration;
|
|
2752
|
-
if (d.type === "FunctionDeclaration") {
|
|
2753
|
-
defaultExport = lookupExport(env, d.id ? d.id.name : "default");
|
|
2754
|
-
} else if (d.type === "ClassDeclaration" && d.id) {
|
|
2755
|
-
defaultExport = lookupExport(env, d.id.name);
|
|
2756
|
-
} else if (d.type === "Identifier") {
|
|
2757
|
-
defaultExport = lookupExport(env, d.name);
|
|
2758
|
-
}
|
|
2759
|
-
}
|
|
2760
|
-
}
|
|
2761
|
-
const result = { named };
|
|
2762
|
-
if (defaultExport) result.default = defaultExport;
|
|
2763
|
-
return result;
|
|
2764
|
-
}
|
|
2765
2871
|
export {
|
|
2766
2872
|
$add,
|
|
2767
2873
|
$arguments,
|
|
@@ -2905,6 +3011,7 @@ export {
|
|
|
2905
3011
|
asAbs,
|
|
2906
3012
|
asAbsVal,
|
|
2907
3013
|
assignSourceSlots,
|
|
3014
|
+
assumeFinite,
|
|
2908
3015
|
attachFnImpl,
|
|
2909
3016
|
beginCollectionFork,
|
|
2910
3017
|
betaOf,
|
|
@@ -2938,6 +3045,7 @@ export {
|
|
|
2938
3045
|
collectionElementJoin,
|
|
2939
3046
|
collectionExactLen,
|
|
2940
3047
|
confJoin,
|
|
3048
|
+
constraintAdmitsNullish,
|
|
2941
3049
|
constraintToEntryAbs,
|
|
2942
3050
|
contractParamNameSet,
|
|
2943
3051
|
createEnvironment,
|
|
@@ -2984,6 +3092,7 @@ export {
|
|
|
2984
3092
|
extStateOf,
|
|
2985
3093
|
extractDeclaredThrows,
|
|
2986
3094
|
extractFn,
|
|
3095
|
+
extractFnBudget,
|
|
2987
3096
|
extractNudoImports,
|
|
2988
3097
|
extractRefineReturnFromSource,
|
|
2989
3098
|
extractRefinesFromSource,
|
|
@@ -2995,6 +3104,7 @@ export {
|
|
|
2995
3104
|
foldRequireSpecArg,
|
|
2996
3105
|
foldStaticStringExpr,
|
|
2997
3106
|
formalParamDisplayNames,
|
|
3107
|
+
formalParamSignatureNames,
|
|
2998
3108
|
formalParamsFromNodes,
|
|
2999
3109
|
formatAbs,
|
|
3000
3110
|
formatAbsMultiline,
|
|
@@ -3100,6 +3210,7 @@ export {
|
|
|
3100
3210
|
mock,
|
|
3101
3211
|
mod,
|
|
3102
3212
|
mul,
|
|
3213
|
+
namespaceAbsOf,
|
|
3103
3214
|
namespaceNameOf,
|
|
3104
3215
|
ne,
|
|
3105
3216
|
negAbs,
|
|
@@ -3111,6 +3222,7 @@ export {
|
|
|
3111
3222
|
noteEvalCallRecord,
|
|
3112
3223
|
noteEvalFallback,
|
|
3113
3224
|
notePromiseExecutorFork,
|
|
3225
|
+
nullable,
|
|
3114
3226
|
num,
|
|
3115
3227
|
numLit,
|
|
3116
3228
|
numVar,
|
|
@@ -3160,6 +3272,7 @@ export {
|
|
|
3160
3272
|
resetNudoModuleExecCache,
|
|
3161
3273
|
resetParseSourceCache,
|
|
3162
3274
|
resetPhi,
|
|
3275
|
+
resetSidecarLoadFailureCache,
|
|
3163
3276
|
runTranspiled,
|
|
3164
3277
|
runTranspiledOptionsMemoKey,
|
|
3165
3278
|
runWithLoopExits,
|