@nudojs/core 1.1.0 → 1.1.2
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.
|
@@ -10504,6 +10504,10 @@ var _bForkBudgetLimit = MAX_B_TOTAL_FORKS;
|
|
|
10504
10504
|
var _bForkCount = 0;
|
|
10505
10505
|
var _bForkTruncNoted = false;
|
|
10506
10506
|
var FORK_TRUNCATION_LABEL = "#fork-budget";
|
|
10507
|
+
var HOST_EFFECT_LABEL_PREFIX = "#host-effect:";
|
|
10508
|
+
function noteHostEffectBlocked(name) {
|
|
10509
|
+
noteAbsTruncation(`${HOST_EFFECT_LABEL_PREFIX}${name}`);
|
|
10510
|
+
}
|
|
10507
10511
|
function noteBForkTruncation() {
|
|
10508
10512
|
noteAbsTruncation(FORK_TRUNCATION_LABEL);
|
|
10509
10513
|
}
|
|
@@ -12529,7 +12533,9 @@ __export(calls_exports, {
|
|
|
12529
12533
|
$recordBinding: () => $recordBinding,
|
|
12530
12534
|
MAX_B_CALL_DEPTH: () => MAX_B_CALL_DEPTH,
|
|
12531
12535
|
MAX_B_TOTAL_CALLS: () => MAX_B_TOTAL_CALLS,
|
|
12536
|
+
blockHostSideEffect: () => blockHostSideEffect,
|
|
12532
12537
|
getBCallCollector: () => getBCallCollector,
|
|
12538
|
+
neverExecHostName: () => neverExecHostName,
|
|
12533
12539
|
noteBCallRecord: () => noteBCallRecord,
|
|
12534
12540
|
resetBCallBudget: () => resetBCallBudget,
|
|
12535
12541
|
setBAssignCollector: () => setBAssignCollector,
|
|
@@ -12578,6 +12584,32 @@ var GLOBAL_FNS = /* @__PURE__ */ new Set([
|
|
|
12578
12584
|
"eval",
|
|
12579
12585
|
"Symbol"
|
|
12580
12586
|
]);
|
|
12587
|
+
var NEVER_EXEC_HOST_FN_NAMES = [
|
|
12588
|
+
"fetch",
|
|
12589
|
+
"XMLHttpRequest",
|
|
12590
|
+
"WebSocket",
|
|
12591
|
+
"EventSource",
|
|
12592
|
+
"setTimeout",
|
|
12593
|
+
"setInterval",
|
|
12594
|
+
"setImmediate",
|
|
12595
|
+
"queueMicrotask",
|
|
12596
|
+
"requestAnimationFrame",
|
|
12597
|
+
"requestIdleCallback"
|
|
12598
|
+
];
|
|
12599
|
+
function neverExecHostName(fn) {
|
|
12600
|
+
if (typeof fn !== "function") return null;
|
|
12601
|
+
const g = globalThis;
|
|
12602
|
+
for (const n of NEVER_EXEC_HOST_FN_NAMES) {
|
|
12603
|
+
if (fn === g[n]) return n;
|
|
12604
|
+
}
|
|
12605
|
+
return null;
|
|
12606
|
+
}
|
|
12607
|
+
function blockHostSideEffect(fn) {
|
|
12608
|
+
const hostName = neverExecHostName(fn);
|
|
12609
|
+
if (hostName === null) return null;
|
|
12610
|
+
noteHostEffectBlocked(hostName);
|
|
12611
|
+
return abs({ k: "unknown" }, void 0, void 0, "opaque");
|
|
12612
|
+
}
|
|
12581
12613
|
function noteBCallRecord(r) {
|
|
12582
12614
|
if (!bCallCollector) return;
|
|
12583
12615
|
try {
|
|
@@ -12659,8 +12691,11 @@ function $callNamed(name, fn, args, loc, argLocs) {
|
|
|
12659
12691
|
try {
|
|
12660
12692
|
if (typeof fn === "function") {
|
|
12661
12693
|
const g = GLOBAL_FNS.has(name) && fn === globalThis[name] ? evalGlobalFn(name, args) : void 0;
|
|
12694
|
+
const blockedHost = g === void 0 ? blockHostSideEffect(fn) : null;
|
|
12662
12695
|
if (g !== void 0) {
|
|
12663
12696
|
result = g;
|
|
12697
|
+
} else if (blockedHost !== null) {
|
|
12698
|
+
result = blockedHost;
|
|
12664
12699
|
} else {
|
|
12665
12700
|
const entered = bEnterCall(name, fn, args);
|
|
12666
12701
|
if (!entered.ok) {
|
|
@@ -12759,7 +12794,13 @@ function execRegexBrand(re, method, args) {
|
|
|
12759
12794
|
if (method === "toString") return strLit(`/${parts.pat}/${parts.flags}`);
|
|
12760
12795
|
const subject = args[0] ? litValue(args[0]) : void 0;
|
|
12761
12796
|
if (typeof subject !== "string") {
|
|
12762
|
-
|
|
12797
|
+
if (method === "test") {
|
|
12798
|
+
return abs({ k: "prim", type: "boolean" }, void 0, void 0, "partial");
|
|
12799
|
+
}
|
|
12800
|
+
const element = joinAbs(str(), undefAbs());
|
|
12801
|
+
const matchAbs = abs({ k: "arr", element }, void 0, void 0, "path");
|
|
12802
|
+
const nullAbs = abs({ k: "unknown" }, { op: "lit", value: null }, void 0, "exact");
|
|
12803
|
+
return joinAbs(nullAbs, matchAbs);
|
|
12763
12804
|
}
|
|
12764
12805
|
try {
|
|
12765
12806
|
return regexExecWithState(re, method, subject).result;
|
|
@@ -12925,6 +12966,8 @@ function $new(cls, args) {
|
|
|
12925
12966
|
}
|
|
12926
12967
|
}
|
|
12927
12968
|
if (typeof cls === "function") {
|
|
12969
|
+
const blockedHost = blockHostSideEffect(cls);
|
|
12970
|
+
if (blockedHost) return blockedHost;
|
|
12928
12971
|
if (cls === Array) {
|
|
12929
12972
|
return makeArrayCtorAbs(args);
|
|
12930
12973
|
}
|
|
@@ -14936,6 +14979,8 @@ export {
|
|
|
14936
14979
|
exitCall,
|
|
14937
14980
|
MAX_B_TOTAL_FORKS,
|
|
14938
14981
|
FORK_TRUNCATION_LABEL,
|
|
14982
|
+
HOST_EFFECT_LABEL_PREFIX,
|
|
14983
|
+
noteHostEffectBlocked,
|
|
14939
14984
|
noteBForkTruncation,
|
|
14940
14985
|
setBForkBudgetLimit,
|
|
14941
14986
|
getBForkBudgetLimit,
|
package/dist/exec.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -67,7 +67,7 @@ import {
|
|
|
67
67
|
takeRefineDiagsSince,
|
|
68
68
|
throwConstraintToKinds,
|
|
69
69
|
union
|
|
70
|
-
} from "./chunk-
|
|
70
|
+
} from "./chunk-EFFPFUSD.js";
|
|
71
71
|
import {
|
|
72
72
|
$add,
|
|
73
73
|
$arguments,
|
|
@@ -178,6 +178,7 @@ import {
|
|
|
178
178
|
$yield,
|
|
179
179
|
DEFAULT_MAX_LOOP_ITERS,
|
|
180
180
|
FORK_TRUNCATION_LABEL,
|
|
181
|
+
HOST_EFFECT_LABEL_PREFIX,
|
|
181
182
|
MAX_B_CALL_DEPTH,
|
|
182
183
|
MAX_B_TOTAL_CALLS,
|
|
183
184
|
NudoLoopSignal,
|
|
@@ -465,7 +466,7 @@ import {
|
|
|
465
466
|
v,
|
|
466
467
|
withExecPhi,
|
|
467
468
|
withVar
|
|
468
|
-
} from "./chunk-
|
|
469
|
+
} from "./chunk-UC3LBZYR.js";
|
|
469
470
|
|
|
470
471
|
// src/environment.ts
|
|
471
472
|
function createEnvironment(parent, bindings = /* @__PURE__ */ new Map()) {
|
|
@@ -2101,6 +2102,17 @@ function checkSourceInner(filePath, source, file, phi, opts, issues, signatures,
|
|
|
2101
2102
|
});
|
|
2102
2103
|
continue;
|
|
2103
2104
|
}
|
|
2105
|
+
if (label.startsWith(HOST_EFFECT_LABEL_PREFIX)) {
|
|
2106
|
+
const hostName = label.slice(HOST_EFFECT_LABEL_PREFIX.length);
|
|
2107
|
+
issues.push({
|
|
2108
|
+
severity: "info",
|
|
2109
|
+
code: "nudo:host-effect-blocked",
|
|
2110
|
+
message: `Host function '${hostName}' is not executed during analysis (network/timer side effect); result widened to unknown#opaque`,
|
|
2111
|
+
suggestion: "optional: mock it with @nudo:mock / @nudo:env, or pass the value in from a call site",
|
|
2112
|
+
fn: hostName
|
|
2113
|
+
});
|
|
2114
|
+
continue;
|
|
2115
|
+
}
|
|
2104
2116
|
issues.push({
|
|
2105
2117
|
severity: "info",
|
|
2106
2118
|
code: "nudo:recursion-truncated",
|
|
@@ -2230,6 +2242,19 @@ function checkReturnConstraint(fnName, cName, constraint, ret) {
|
|
|
2230
2242
|
const out = [];
|
|
2231
2243
|
if (ret.shape.k === "unknown" && !ret.term) return out;
|
|
2232
2244
|
if (ret.shape.k === "any") return out;
|
|
2245
|
+
if (isNullishLitAbs(ret)) return out;
|
|
2246
|
+
if (ret.shape.k === "sum" && constraint.fields) {
|
|
2247
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2248
|
+
for (const m of ret.shape.members) {
|
|
2249
|
+
for (const issue of checkReturnConstraint(fnName, cName, constraint, m)) {
|
|
2250
|
+
const key = `${issue.message}\0${issue.actual ?? ""}\0${issue.expected ?? ""}`;
|
|
2251
|
+
if (seen.has(key)) continue;
|
|
2252
|
+
seen.add(key);
|
|
2253
|
+
out.push(issue);
|
|
2254
|
+
}
|
|
2255
|
+
}
|
|
2256
|
+
return out;
|
|
2257
|
+
}
|
|
2233
2258
|
const push = (actual, expected, suggestion) => {
|
|
2234
2259
|
out.push({
|
|
2235
2260
|
severity: "error",
|
|
@@ -2398,6 +2423,11 @@ function actionsForIssue(i) {
|
|
|
2398
2423
|
label: "results widened to unknown \u2014 raise budget or narrow control flow"
|
|
2399
2424
|
}
|
|
2400
2425
|
];
|
|
2426
|
+
case "nudo:host-effect-blocked":
|
|
2427
|
+
return [
|
|
2428
|
+
{ kind: "mock", label: "pin the host API with @nudo:mock / @nudo:env" },
|
|
2429
|
+
{ kind: "info", label: "results widened to unknown \u2014 or feed the value in from a call site" }
|
|
2430
|
+
];
|
|
2401
2431
|
case "nudo:interface-drift":
|
|
2402
2432
|
return [
|
|
2403
2433
|
{
|
package/dist/internal.d.ts
CHANGED
|
@@ -65,6 +65,15 @@ declare const MAX_B_TOTAL_FORKS = 5000;
|
|
|
65
65
|
* 映射为 `nudo:fork-truncated`(warning)。
|
|
66
66
|
*/
|
|
67
67
|
declare const FORK_TRUNCATION_LABEL = "#fork-budget";
|
|
68
|
+
/**
|
|
69
|
+
* 宿主副作用未执行标签前缀:网络/定时器全局(fetch/setTimeout…)在分析期
|
|
70
|
+
* 不真实执行(Abs 实参喂原生实现会真发请求/真排定时器,且可能崩进程),
|
|
71
|
+
* fail-closed 为 unknown#opaque。专用前缀让 check 映射为
|
|
72
|
+
* `nudo:host-effect-blocked`,不复用「某函数被截断」文案。
|
|
73
|
+
*/
|
|
74
|
+
declare const HOST_EFFECT_LABEL_PREFIX = "#host-effect:";
|
|
75
|
+
/** 宿主副作用未执行观测(service/LSP 映射 nudo:host-effect-blocked;与调用截断同 collector 管道) */
|
|
76
|
+
declare function noteHostEffectBlocked(name: string): void;
|
|
68
77
|
/** fork 超限观测(service/LSP 映射 nudo:fork-truncated;与调用截断同 collector 管道) */
|
|
69
78
|
declare function noteBForkTruncation(): void;
|
|
70
79
|
/**
|
|
@@ -538,4 +547,4 @@ declare function runWithEvalMissingSlot<T>(enabled: boolean, body: () => T): T;
|
|
|
538
547
|
*/
|
|
539
548
|
declare function noteObjSlotMissing(recv: Abs | undefined, name: string, loc?: [number, number]): boolean;
|
|
540
549
|
|
|
541
|
-
export { type AbsBudgetStats, type AbsInlay, type ArgDerivation, type BMemberDiag, type ClassDef, type CollectAbsInlaysOpts, type DerivationNode, FORK_TRUNCATION_LABEL, type FnFp, type InjectedDomainEvidenceOpts, type InjectedDomainRecord, MAX_B_TOTAL_FORKS, MAX_CALL_DEPTH, MAX_TOTAL_CALLS, type MethodDef, OBJECT_PROTO_NAMES, type TemplateMeta, type TemplatePartDesc, type TemplatePartView, type TemplatePredicateDecision, abortDerivationSession, absTemplateViews, allFixedTextOfViews, anyMemberResult, awaitAbs, beginDerivationSession, bumpBForkBudget, callBudgetKey, canSkipLiteralCallScan, checkInjectedDomainEvidence, classChainNames, classFromMethods, coerceAsyncReturn, collectAbsInlays, concatString, createTemplateAbs, decideEndsWith, decideIncludes, decideStartsWith, defineClass, definitelyUncallableMember, denoteGuard, derivationChain, endDerivationSession, enterCall, exitCall, fixedLengthOfViews, fnFingerprints, formatTemplateNameViews, generalizeSourceKeyPart, getAbsCallBudgetStats, getAbsOrigin, getBForkBudgetLimit, getBForkCount, getClass, getClassChain, getDerivation, getFnNameAndBodies, hasDerivationSession, hashSource, instanceOf, instantiateClass, isEvalMissingSlotEnabled, isNullishAbs, isTemplateLike, knownPrefixOfViews, knownSuffixOfViews, listTopFunctions, lookupMethod, lookupMethodWithOwner, lookupSuperMethod, mergeAdjacentFixedViews, noteAbsTruncation, noteAnyMemberMayThrow, noteBForkTruncation, noteDerivationAdd, noteDerivationJoin, noteMemberDispatchMiss, noteNullishMemberThrows, noteObjSlotMissing, notePrimMemberMissing, noteUnknownMemberMissing, popCallLoc, projectBrand, projectDerivationDsl, pushCallLoc, recordMemberDiag, resetAbsCallBudget, resetBForkBudget, resetFnFpCache, resetHashSourceCache, runWithEvalMissingSlot, setAbsTruncationCollector, setBForkBudgetLimit, setDerivation, setDerivationCollector, setEvalMissingSlotEnabled, setMemberDiagCollector, stableAnalyzeKeySource, stableCallId, superNameOf, tagAbsOrigin, tagDerivationRoot, templateMatchesValue, templatePartsOf, termKey, truncatedAbs, viewTemplateParts, wrapPromise };
|
|
550
|
+
export { type AbsBudgetStats, type AbsInlay, type ArgDerivation, type BMemberDiag, type ClassDef, type CollectAbsInlaysOpts, type DerivationNode, FORK_TRUNCATION_LABEL, type FnFp, HOST_EFFECT_LABEL_PREFIX, type InjectedDomainEvidenceOpts, type InjectedDomainRecord, MAX_B_TOTAL_FORKS, MAX_CALL_DEPTH, MAX_TOTAL_CALLS, type MethodDef, OBJECT_PROTO_NAMES, type TemplateMeta, type TemplatePartDesc, type TemplatePartView, type TemplatePredicateDecision, abortDerivationSession, absTemplateViews, allFixedTextOfViews, anyMemberResult, awaitAbs, beginDerivationSession, bumpBForkBudget, callBudgetKey, canSkipLiteralCallScan, checkInjectedDomainEvidence, classChainNames, classFromMethods, coerceAsyncReturn, collectAbsInlays, concatString, createTemplateAbs, decideEndsWith, decideIncludes, decideStartsWith, defineClass, definitelyUncallableMember, denoteGuard, derivationChain, endDerivationSession, enterCall, exitCall, fixedLengthOfViews, fnFingerprints, formatTemplateNameViews, generalizeSourceKeyPart, getAbsCallBudgetStats, getAbsOrigin, getBForkBudgetLimit, getBForkCount, getClass, getClassChain, getDerivation, getFnNameAndBodies, hasDerivationSession, hashSource, instanceOf, instantiateClass, isEvalMissingSlotEnabled, isNullishAbs, isTemplateLike, knownPrefixOfViews, knownSuffixOfViews, listTopFunctions, lookupMethod, lookupMethodWithOwner, lookupSuperMethod, mergeAdjacentFixedViews, noteAbsTruncation, noteAnyMemberMayThrow, noteBForkTruncation, noteDerivationAdd, noteDerivationJoin, noteHostEffectBlocked, noteMemberDispatchMiss, noteNullishMemberThrows, noteObjSlotMissing, notePrimMemberMissing, noteUnknownMemberMissing, popCallLoc, projectBrand, projectDerivationDsl, pushCallLoc, recordMemberDiag, resetAbsCallBudget, resetBForkBudget, resetFnFpCache, resetHashSourceCache, runWithEvalMissingSlot, setAbsTruncationCollector, setBForkBudgetLimit, setDerivation, setDerivationCollector, setEvalMissingSlotEnabled, setMemberDiagCollector, stableAnalyzeKeySource, stableCallId, superNameOf, tagAbsOrigin, tagDerivationRoot, templateMatchesValue, templatePartsOf, termKey, truncatedAbs, viewTemplateParts, wrapPromise };
|
package/dist/internal.js
CHANGED
|
@@ -16,13 +16,14 @@ import {
|
|
|
16
16
|
resolveDepPath,
|
|
17
17
|
sidecarSpecsOf,
|
|
18
18
|
stableAnalyzeKeySource
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-EFFPFUSD.js";
|
|
20
20
|
import {
|
|
21
21
|
$tryDigestSoft,
|
|
22
22
|
$tryMarkSoft,
|
|
23
23
|
$tryReleaseSoft,
|
|
24
24
|
ERROR_FAMILY,
|
|
25
25
|
FORK_TRUNCATION_LABEL,
|
|
26
|
+
HOST_EFFECT_LABEL_PREFIX,
|
|
26
27
|
MAX_B_TOTAL_FORKS,
|
|
27
28
|
MAX_CALL_DEPTH,
|
|
28
29
|
MAX_TOTAL_CALLS,
|
|
@@ -90,6 +91,7 @@ import {
|
|
|
90
91
|
noteBForkTruncation,
|
|
91
92
|
noteDerivationAdd,
|
|
92
93
|
noteDerivationJoin,
|
|
94
|
+
noteHostEffectBlocked,
|
|
93
95
|
noteMemberDispatchMiss,
|
|
94
96
|
noteNullishMemberThrows,
|
|
95
97
|
noteObjSlotMissing,
|
|
@@ -133,7 +135,7 @@ import {
|
|
|
133
135
|
truncatedAbs,
|
|
134
136
|
viewTemplateParts,
|
|
135
137
|
wrapPromise
|
|
136
|
-
} from "./chunk-
|
|
138
|
+
} from "./chunk-UC3LBZYR.js";
|
|
137
139
|
|
|
138
140
|
// src/algebra/inlay.ts
|
|
139
141
|
function listFunctions(source) {
|
|
@@ -458,6 +460,7 @@ export {
|
|
|
458
460
|
$tryReleaseSoft,
|
|
459
461
|
ERROR_FAMILY,
|
|
460
462
|
FORK_TRUNCATION_LABEL,
|
|
463
|
+
HOST_EFFECT_LABEL_PREFIX,
|
|
461
464
|
MAX_B_TOTAL_FORKS,
|
|
462
465
|
MAX_CALL_DEPTH,
|
|
463
466
|
MAX_TOTAL_CALLS,
|
|
@@ -535,6 +538,7 @@ export {
|
|
|
535
538
|
noteBForkTruncation,
|
|
536
539
|
noteDerivationAdd,
|
|
537
540
|
noteDerivationJoin,
|
|
541
|
+
noteHostEffectBlocked,
|
|
538
542
|
noteMemberDispatchMiss,
|
|
539
543
|
noteNullishMemberThrows,
|
|
540
544
|
noteObjSlotMissing,
|