@nudojs/core 1.7.1 → 1.7.3

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.
@@ -6,6 +6,7 @@ import {
6
6
  anyAbs,
7
7
  app,
8
8
  callTranspiledExportFull,
9
+ createScopedSlot,
9
10
  defaultLeakBudget,
10
11
  emptyEnv,
11
12
  eq,
@@ -36,6 +37,7 @@ import {
36
37
  predToString,
37
38
  primToTypeof,
38
39
  ptypeof,
40
+ registerCollectorScopeParticipant,
39
41
  runTranspiledOptionsMemoKey,
40
42
  snapshotAbs,
41
43
  stripStringsKeepComments,
@@ -46,7 +48,7 @@ import {
46
48
  withEvalBudgetOverride,
47
49
  withExecPhi,
48
50
  withFnBudgetOverride
49
- } from "./chunk-BM3UPEA7.js";
51
+ } from "./chunk-TO2W45NU.js";
50
52
 
51
53
  // src/algebra/directive-scan.ts
52
54
  function cleanDirectiveLine(raw, kind) {
@@ -744,6 +746,63 @@ function sidecarPathOf(file) {
744
746
  return `${f}.nudo.js`;
745
747
  }
746
748
 
749
+ // src/algebra/diag-channel.ts
750
+ import { AsyncLocalStorage } from "async_hooks";
751
+ function createDiagChannel(cap) {
752
+ let collector = null;
753
+ let seq = 0;
754
+ const buf = [];
755
+ return {
756
+ setCollector(fn2) {
757
+ collector = fn2;
758
+ },
759
+ getCollector() {
760
+ return collector;
761
+ },
762
+ count() {
763
+ return seq;
764
+ },
765
+ take() {
766
+ const out = buf.map((e) => e.d);
767
+ buf.length = 0;
768
+ return out;
769
+ },
770
+ takeSince(since) {
771
+ const out = [];
772
+ let kept = 0;
773
+ for (const e of buf) {
774
+ if (e.seq > since) out.push(e.d);
775
+ else buf[kept++] = e;
776
+ }
777
+ buf.length = kept;
778
+ return out;
779
+ },
780
+ emit(d) {
781
+ if (buf.length >= cap) buf.shift();
782
+ buf.push({ seq: ++seq, d });
783
+ collector?.(d);
784
+ }
785
+ };
786
+ }
787
+ function createScopedDiagChannel(cap) {
788
+ const als = new AsyncLocalStorage();
789
+ const fallback = createDiagChannel(cap);
790
+ const chan = () => als.getStore() ?? fallback;
791
+ return {
792
+ setCollector: (fn2) => chan().setCollector(fn2),
793
+ getCollector: () => chan().getCollector(),
794
+ count: () => chan().count(),
795
+ take: () => chan().take(),
796
+ takeSince: (since) => chan().takeSince(since),
797
+ emit: (d) => chan().emit(d),
798
+ runScoped: (body) => {
799
+ const fresh = createDiagChannel(cap);
800
+ fresh.setCollector(chan().getCollector());
801
+ return als.run(fresh, body);
802
+ }
803
+ };
804
+ }
805
+
747
806
  // src/algebra/constraint.ts
748
807
  var SELF = "__nudo_self__";
749
808
  function selfTerm() {
@@ -1278,35 +1337,23 @@ function extractNudoImports(source) {
1278
1337
  spec: rec.spec
1279
1338
  }));
1280
1339
  }
1281
- var refineDiagCollector = null;
1282
- var refineDiagSeq = 0;
1283
- var refineDiags = [];
1284
1340
  var MAX_REFINE_DIAGS = 1024;
1341
+ var refineDiagChannel = createScopedDiagChannel(MAX_REFINE_DIAGS);
1342
+ registerCollectorScopeParticipant((body) => refineDiagChannel.runScoped(body));
1285
1343
  function setRefineDiagCollector(fn2) {
1286
- refineDiagCollector = fn2;
1344
+ refineDiagChannel.setCollector(fn2);
1287
1345
  }
1288
1346
  function refineDiagCount() {
1289
- return refineDiagSeq;
1347
+ return refineDiagChannel.count();
1290
1348
  }
1291
1349
  function takeRefineDiags() {
1292
- const out = refineDiags.map((e) => e.d);
1293
- refineDiags.length = 0;
1294
- return out;
1350
+ return refineDiagChannel.take();
1295
1351
  }
1296
1352
  function takeRefineDiagsSince(since) {
1297
- const out = [];
1298
- let kept = 0;
1299
- for (const e of refineDiags) {
1300
- if (e.seq > since) out.push(e.d);
1301
- else refineDiags[kept++] = e;
1302
- }
1303
- refineDiags.length = kept;
1304
- return out;
1353
+ return refineDiagChannel.takeSince(since);
1305
1354
  }
1306
1355
  function collectDiag(d) {
1307
- if (refineDiags.length >= MAX_REFINE_DIAGS) refineDiags.shift();
1308
- refineDiags.push({ seq: ++refineDiagSeq, d });
1309
- refineDiagCollector?.(d);
1356
+ refineDiagChannel.emit(d);
1310
1357
  }
1311
1358
  var NudoSidecarError = class extends Error {
1312
1359
  code;
@@ -1939,37 +1986,7 @@ function extractFnBudget(source, fnName) {
1939
1986
  return scanBudgetDecl(lines);
1940
1987
  }
1941
1988
 
1942
- // src/algebra/interface.ts
1943
- var interfaceDiagCollector = null;
1944
- var interfaceDiagSeq = 0;
1945
- var interfaceDiags = [];
1946
- var MAX_INTERFACE_DIAGS = 1024;
1947
- function setInterfaceDiagCollector(fn2) {
1948
- interfaceDiagCollector = fn2;
1949
- }
1950
- function interfaceDiagCount() {
1951
- return interfaceDiagSeq;
1952
- }
1953
- function takeInterfaceDiags() {
1954
- const out = interfaceDiags.map((e) => e.d);
1955
- interfaceDiags.length = 0;
1956
- return out;
1957
- }
1958
- function takeInterfaceDiagsSince(since) {
1959
- const out = [];
1960
- let kept = 0;
1961
- for (const e of interfaceDiags) {
1962
- if (e.seq > since) out.push(e.d);
1963
- else interfaceDiags[kept++] = e;
1964
- }
1965
- interfaceDiags.length = kept;
1966
- return out;
1967
- }
1968
- function collectDiag2(d) {
1969
- if (interfaceDiags.length >= MAX_INTERFACE_DIAGS) interfaceDiags.shift();
1970
- interfaceDiags.push({ seq: ++interfaceDiagSeq, d });
1971
- interfaceDiagCollector?.(d);
1972
- }
1989
+ // src/algebra/scan-named-exports.ts
1973
1990
  function localNamedExports(source) {
1974
1991
  const out = /* @__PURE__ */ new Set();
1975
1992
  let ast;
@@ -2216,6 +2233,26 @@ function regionHasGeneratedMarker(stmts, exportIdx, src) {
2216
2233
  return (t.startsWith("//") || t.startsWith("/*") || t.startsWith("*")) && /@generated/.test(t);
2217
2234
  });
2218
2235
  }
2236
+
2237
+ // src/algebra/interface.ts
2238
+ var MAX_INTERFACE_DIAGS = 1024;
2239
+ var interfaceDiagChannel = createScopedDiagChannel(MAX_INTERFACE_DIAGS);
2240
+ registerCollectorScopeParticipant((body) => interfaceDiagChannel.runScoped(body));
2241
+ function setInterfaceDiagCollector(fn2) {
2242
+ interfaceDiagChannel.setCollector(fn2);
2243
+ }
2244
+ function interfaceDiagCount() {
2245
+ return interfaceDiagChannel.count();
2246
+ }
2247
+ function takeInterfaceDiags() {
2248
+ return interfaceDiagChannel.take();
2249
+ }
2250
+ function takeInterfaceDiagsSince(since) {
2251
+ return interfaceDiagChannel.takeSince(since);
2252
+ }
2253
+ function collectDiag2(d) {
2254
+ interfaceDiagChannel.emit(d);
2255
+ }
2219
2256
  function isUnderProjectRoot(sidecarPath, projectDir) {
2220
2257
  const norm = (p) => p.split("\\").join("/").replace(/\/+$/, "");
2221
2258
  const root = norm(projectDir);
@@ -2269,15 +2306,19 @@ function sidecarMayBind(sidecarNames, fnName, source) {
2269
2306
  }
2270
2307
  return false;
2271
2308
  }
2272
- var sidecarLoadFailures = /* @__PURE__ */ new Map();
2309
+ var sidecarLoadFailureSlot = createScopedSlot(
2310
+ () => /* @__PURE__ */ new Map()
2311
+ );
2312
+ registerCollectorScopeParticipant((body) => sidecarLoadFailureSlot.runScoped(body));
2273
2313
  function noteSidecarLoadFailure(sidecarPath, reason) {
2314
+ const sidecarLoadFailures = sidecarLoadFailureSlot.get();
2274
2315
  const key = `${sidecarPath}\0${reason}`;
2275
2316
  if (sidecarLoadFailures.has(key)) return false;
2276
2317
  sidecarLoadFailures.set(key, reason);
2277
2318
  return true;
2278
2319
  }
2279
2320
  function resetSidecarLoadFailureCache() {
2280
- sidecarLoadFailures.clear();
2321
+ sidecarLoadFailureSlot.get().clear();
2281
2322
  }
2282
2323
  function loadSidecarBinding(source, fnName, opts) {
2283
2324
  const { loadModule, fromFile, autoBind, projectDir } = opts;
@@ -4939,7 +4980,7 @@ function collectForwarders(source, knownFns, resolve, fileAst) {
4939
4980
  return forwards;
4940
4981
  }
4941
4982
 
4942
- // src/algebra/scan.ts
4983
+ // src/algebra/scan-literal-calls.ts
4943
4984
  function hofFnArgOk(src, tgt) {
4944
4985
  if (src.shape.k !== "fn") return false;
4945
4986
  const t = tgt.shape;
@@ -5828,6 +5869,8 @@ export {
5828
5869
  resolveDepPath,
5829
5870
  isNodeModulesPath,
5830
5871
  sidecarPathOf,
5872
+ createDiagChannel,
5873
+ createScopedDiagChannel,
5831
5874
  SELF,
5832
5875
  getTerm,
5833
5876
  lenTerm,
@@ -5869,13 +5912,13 @@ export {
5869
5912
  extractRefineReturnFromSource,
5870
5913
  extractDeclaredThrows,
5871
5914
  extractFnBudget,
5915
+ localNamedExports,
5916
+ exportedNameOfLocal,
5917
+ generatedExportNames,
5872
5918
  setInterfaceDiagCollector,
5873
5919
  interfaceDiagCount,
5874
5920
  takeInterfaceDiags,
5875
5921
  takeInterfaceDiagsSince,
5876
- localNamedExports,
5877
- exportedNameOfLocal,
5878
- generatedExportNames,
5879
5922
  resetSidecarLoadFailureCache,
5880
5923
  effectiveInterface,
5881
5924
  sidecarClosureFingerprint,
@@ -5904,6 +5947,6 @@ export {
5904
5947
  literalMeetsConstraint,
5905
5948
  stableAnalyzeKeySource,
5906
5949
  listTopFunctions,
5907
- checkInjectedDomainEvidence,
5908
- scanLiteralCalls
5950
+ scanLiteralCalls,
5951
+ checkInjectedDomainEvidence
5909
5952
  };
package/dist/exec.d.ts CHANGED
@@ -1,13 +1,16 @@
1
- import { A as Abs, M as MayThrowEffect, b as Phi } from './run-Dg7gQO2z.js';
2
- export { O as $assignRecord, Q as $call, U as $callNamed, V as $recordBinding, a1 as EvalAbsAssignRecord, a2 as EvalCallRecord, a3 as EvalFallback, f as EvalFallbackStats, a6 as MAX_EVAL_CALL_DEPTH, a7 as MAX_EVAL_TOTAL_CALLS, a8 as RUNTIME_IMPORT_RE, N as RunTranspiledOptions, aa as TranspiledCallResult, ao as bindingsOf, ar as callTranspiledExport, as as callTranspiledExportApply, at as callTranspiledExportFull, g as clearPureCallMemo, h as clearPureMemo, i as enterEvalCallBudgetSession, ay as evalExprAbs, k as exitEvalCallBudgetSession, q as getEvalCallBudgetState, aB as getEvalCallCollector, r as getEvalFallbackStats, aI as isAbsVal, a_ as noteEvalCallRecord, a$ as noteEvalFallback, bg as resetEvalCallBudget, z as resetEvalFallbackStats, bA as routeApplyThrows, bh as runTranspiled, bi as runTranspiledOptionsMemoKey, bj as setEvalAssignCollector, bk as setEvalBindingSink, bl as setEvalCallCollector, bm as setEvalFallbackCollector, bx as tryRunTranspiled, H as withEvalBudgetOverride } from './run-Dg7gQO2z.js';
1
+ import { A as Abs, M as MayThrowEffect, b as Phi } from './run-BuTz_p4k.js';
2
+ export { W as $assignRecord, X as $call, Y as $callNamed, Z as $recordBinding, a5 as EvalAbsAssignRecord, a6 as EvalCallRecord, a7 as EvalFallback, f as EvalFallbackStats, aa as MAX_EVAL_CALL_DEPTH, ab as MAX_EVAL_TOTAL_CALLS, ac as RUNTIME_IMPORT_RE, V as RunTranspiledOptions, ae as TranspiledCallResult, as as bindingsOf, av as callTranspiledExport, aw as callTranspiledExportApply, ax as callTranspiledExportFull, k as clearPureCallMemo, l as clearPureMemo, m as enterEvalCallBudgetSession, aC as evalExprAbs, o as exitEvalCallBudgetSession, u as getEvalCallBudgetState, aF as getEvalCallCollector, v as getEvalFallbackStats, aM as isAbsVal, b2 as noteEvalCallRecord, b3 as noteEvalFallback, bk as resetEvalCallBudget, G as resetEvalFallbackStats, bE as routeApplyThrows, bl as runTranspiled, bm as runTranspiledOptionsMemoKey, bn as setEvalAssignCollector, bo as setEvalBindingSink, bp as setEvalCallCollector, bq as setEvalFallbackCollector, bB as tryRunTranspiled, N as withEvalBudgetOverride } from './run-BuTz_p4k.js';
3
3
  import { Node, Expression, File } from '@babel/types';
4
4
 
5
5
  /**
6
- * 求值引擎 throw 载荷(独立叶子模块):
7
- * builtins.ts(evalJsonMethod 等 Abs builtin)需要硬抛 TypeError/SyntaxError,
8
- * 而 exec/runtime.ts 又 import builtins.ts(evalNamespaceCall 等)——
9
- * 直接互引成环。NudoThrow 无依赖(仅 Abs 类型 + Error),抽成叶子,
10
- * runtime.ts re-export 保持既有 import 面不变。
6
+ * 求值引擎 throw 载荷(内核叶子模块)。
7
+ * 历史:builtins.ts(evalJsonMethod 等 Abs builtin)需要硬抛
8
+ * TypeError/SyntaxError,而 exec/runtime.ts 又 import builtins.ts
9
+ * (evalNamespaceCall 等)——直接互引成环,故 NudoThrow 抽成无依赖叶子
10
+ * (仅 Abs 类型 + Error)。
11
+ * 现居 algebra/:Abs 代数内核(arithmetic/surface/methods、builtins/*)
12
+ * 也消费它,而内核不得 import exec/(exec 是引擎消费者,不是真理源)——
13
+ * exec/nudo-throw.ts re-export 维持引擎侧既有 import 面不变。
11
14
  */
12
15
 
13
16
  /** 求值引擎 throw 载荷:携带 Abs 抛出值 */
@@ -250,6 +253,12 @@ declare function $whileSeq(test: () => Abs, body: () => void, maxIters?: number,
250
253
  /** 标签循环:仅吸收同标签 break/continue 信号 */
251
254
  label?: string;
252
255
  }): void;
256
+ /**
257
+ * switch:具体 disc 选中匹配 case;抽象 disc 并所有分支。
258
+ * 抽象路径与 $fork 同构:集合 side-table 按臂 overlay,共享 body 只跑一次;
259
+ * 臂内 NudoReturn/NudoThrow 不冒泡污染兄弟臂。
260
+ * **无 default 时必须隐式 fall-through 臂(undef)**,否则无匹配路径被丢掉(P0-2)。
261
+ */
253
262
  declare function $switch(disc: Abs, cases: Array<{
254
263
  test: Abs;
255
264
  run: () => Abs;
@@ -348,10 +357,6 @@ declare function $forOf(iterable: Abs, body: (item: Abs, index: Abs) => void, ma
348
357
  /** 标签循环:仅吸收同标签 break/continue 信号 */
349
358
  label?: string;
350
359
  }): void;
351
- /**
352
- * 命名空间身份表:transpile 后 `Math.max(0, x)` 的接收者是宿主 JS 全局对象
353
- * (非 Abs)。按对象身份识别命名空间,路由到 Abs builtin 表。
354
- */
355
360
  declare function namespaceNameOf(v: unknown): string | undefined;
356
361
  /** 正则字面量 → RegExp brand(source/flags/lastIndex 进 slots,供 exec/test 精确执行) */
357
362
  declare function $regex(pattern: string, flags?: string): Abs;
@@ -369,7 +374,7 @@ declare function $collectionForEach(recv: Abs, cb: unknown): Abs | undefined;
369
374
  declare function $set(o: Abs, key: string, value: Abs): Abs;
370
375
 
371
376
  /**
372
- * async / await / generator / $switch / $nullishTest。
377
+ * async / await / generator / ??($nullishTest / $removeNullish)。
373
378
  */
374
379
 
375
380
  /**
@@ -385,11 +390,13 @@ declare function $gen(body: () => void): Abs;
385
390
  /** yield v:压入当前生成器收集器;表达式值用 unknown */
386
391
  declare function $yield(v: Abs): Abs;
387
392
  /**
388
- * switch:具体 disc 选中匹配 case;抽象 disc 并所有分支。
389
- * 抽象路径与 $fork 同构:集合 side-table 按臂 overlay,共享 body 只跑一次;
390
- * 臂内 NudoReturn/NudoThrow 不冒泡污染兄弟臂。
391
- * **无 default 时必须隐式 fall-through 臂(undef)**,否则无匹配路径被丢掉(P0-2)。
393
+ * `??` 非 nullish 臂:从左值 Abs 剥离 nullish 部分($nullishTest 判 true
394
+ * 的成员)。索引访问 `M[k]` 对抽象键产出 joinAbs(element, undef()),
395
+ * 左值 sum 保留 undefined 臂;`l ?? fallback` 的 alt(非 nullish 路径)
396
+ * 必须只取左值的非 nullish 部分——否则 false-positive `nullish return arm`
397
+ * (issue #90)、`for (const x of o.items ?? [])` 假 may-throw。
392
398
  */
399
+ declare function $removeNullish(a: Abs): Abs;
393
400
  /** `??` / `??=` 测试:确定非 nullish → false;lit nullish → true;否则抽象 boolean */
394
401
  declare function $nullishTest(v: Abs): Abs;
395
402
 
@@ -589,4 +596,4 @@ declare class NudoUnsupportedError extends Error {
589
596
  detail?: string);
590
597
  }
591
598
 
592
- export { $add, $arguments, $arr, $arrMutContainer, $arrRest, $arrWithHoles, $async, $asyncReturn, $await, $bitand, $bitnot, $bitor, $bitxor, $catchVal, $class, $classExpr, $collectionForEach, $concat, $copy, $del, $delRes, $div, $dynamicImport, $elems, $eq, $eqLoose, $fnVal, $for, $forInKeys, $forIter, $forOf, $fork, $ge, $gen, $get, $gt, $idx, $idxSet, $importMeta, $in, $instanceof, $instanceofNonIdent, $invoke, $invokeSuper, $isBreakTo, $isForkExit, $join, $le, $len, $lit, $loopBreak, $loopContinue, $loopReturn, $lt, $mod, $mul, $ne, $neLoose, $neg, $new, $not, $nullishTest, $obj, $objAccessor, $objRest, $optionalGet, $optionalInvoke, $orDefault, $pow, $pushLoopExit, $rawThis, $reStateCall, $regex, $rethrowIfNudoReturn, $set, $setKey, $setProto, $shl, $shr, $spread, $staticInvoke, $sub, $super, $switch, $thisGet, $thisSet, $throw, $toNumber, $toNumeric, $tryCurrentMark, $tryDetachSoftCatch, $tryDigestSoftCatch, $tryDiscardSoft, $tryMark, $tryOrphanSoft, $tryPopMark, $tryReleaseSoftCatch, $tryReleaseSoftOut, $tryTakeSince, $typeof, $unknown, $updateAdd, $updateSub, $ushr, $while, $whileSeq, $yield, DEFAULT_MAX_LOOP_ITERS, type EvalClassSpec, NudoLoopSignal, NudoReturn, NudoThrow, NudoUnsupportedError, type TranspileOptions, asAbsVal, callAtFunctionBoundary, clearBClasses, clearStaleTermPred, currentExecPhi, fillTuple, foldRequireSpecArg, foldStaticStringExpr, getEvalClass, isArrMutator, isDefinitelyFalse, isDefinitelyTrue, isNudoBreak, isNudoContinue, isNudoReturn, isNudoThrow, litTruth, lookupObjAccessor, namespaceNameOf, pushLoopExit, pushThrowExit, registerEvalClass, runWithLoopExits, runtimeImportOf, takeLoopExits, takeThrowExits, transpile, transpileBodyNode, transpileExpression, transpileFile, transpileSource, withExecPhi };
599
+ export { $add, $arguments, $arr, $arrMutContainer, $arrRest, $arrWithHoles, $async, $asyncReturn, $await, $bitand, $bitnot, $bitor, $bitxor, $catchVal, $class, $classExpr, $collectionForEach, $concat, $copy, $del, $delRes, $div, $dynamicImport, $elems, $eq, $eqLoose, $fnVal, $for, $forInKeys, $forIter, $forOf, $fork, $ge, $gen, $get, $gt, $idx, $idxSet, $importMeta, $in, $instanceof, $instanceofNonIdent, $invoke, $invokeSuper, $isBreakTo, $isForkExit, $join, $le, $len, $lit, $loopBreak, $loopContinue, $loopReturn, $lt, $mod, $mul, $ne, $neLoose, $neg, $new, $not, $nullishTest, $obj, $objAccessor, $objRest, $optionalGet, $optionalInvoke, $orDefault, $pow, $pushLoopExit, $rawThis, $reStateCall, $regex, $removeNullish, $rethrowIfNudoReturn, $set, $setKey, $setProto, $shl, $shr, $spread, $staticInvoke, $sub, $super, $switch, $thisGet, $thisSet, $throw, $toNumber, $toNumeric, $tryCurrentMark, $tryDetachSoftCatch, $tryDigestSoftCatch, $tryDiscardSoft, $tryMark, $tryOrphanSoft, $tryPopMark, $tryReleaseSoftCatch, $tryReleaseSoftOut, $tryTakeSince, $typeof, $unknown, $updateAdd, $updateSub, $ushr, $while, $whileSeq, $yield, DEFAULT_MAX_LOOP_ITERS, type EvalClassSpec, NudoLoopSignal, NudoReturn, NudoThrow, NudoUnsupportedError, type TranspileOptions, asAbsVal, callAtFunctionBoundary, clearBClasses, clearStaleTermPred, currentExecPhi, fillTuple, foldRequireSpecArg, foldStaticStringExpr, getEvalClass, isArrMutator, isDefinitelyFalse, isDefinitelyTrue, isNudoBreak, isNudoContinue, isNudoReturn, isNudoThrow, litTruth, lookupObjAccessor, namespaceNameOf, pushLoopExit, pushThrowExit, registerEvalClass, runWithLoopExits, runtimeImportOf, takeLoopExits, takeThrowExits, transpile, transpileBodyNode, transpileExpression, transpileFile, transpileSource, withExecPhi };
package/dist/exec.js CHANGED
@@ -77,6 +77,7 @@ import {
77
77
  $reStateCall,
78
78
  $recordBinding,
79
79
  $regex,
80
+ $removeNullish,
80
81
  $rethrowIfNudoReturn,
81
82
  $set,
82
83
  $setKey,
@@ -177,7 +178,7 @@ import {
177
178
  tryRunTranspiled,
178
179
  withEvalBudgetOverride,
179
180
  withExecPhi
180
- } from "./chunk-BM3UPEA7.js";
181
+ } from "./chunk-TO2W45NU.js";
181
182
  export {
182
183
  $add,
183
184
  $arguments,
@@ -256,6 +257,7 @@ export {
256
257
  $reStateCall,
257
258
  $recordBinding,
258
259
  $regex,
260
+ $removeNullish,
259
261
  $rethrowIfNudoReturn,
260
262
  $set,
261
263
  $setKey,
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { c as AstEnv, A as Abs, b as Phi, T as Term, I as HofCollectCtx, C as Confidence, S as Shape, a as Pred, R as RelSource, J as HofSite, K as AbsModuleExports, N as RunTranspiledOptions } from './run-Dg7gQO2z.js';
2
- export { O as $assignRecord, Q as $call, U as $callNamed, V as $recordBinding, W as AbsApplyNoThrow, X as AbsApplyNoThrowFn, Y as AbsApplyResult, Z as AbsApplyReturn, _ as AbsFnImpl, a0 as AbsSigImpl, a1 as EvalAbsAssignRecord, a2 as EvalCallRecord, a3 as EvalFallback, a4 as ImplicationOracle, a5 as LitValueResult, L as LiteralValue, a6 as MAX_EVAL_CALL_DEPTH, a7 as MAX_EVAL_TOTAL_CALLS, P as PrimName, a8 as RUNTIME_IMPORT_RE, a9 as TYPEOF_NAMES, aa as TranspiledCallResult, ab as TypeofName, ac as abs, ad as absFunction, ae as absOnly, af as absToString, ag as and, ah as anyAbs, ai as anyVar, aj as app, ak as assumeFinite, al as attachFnImpl, am as bigintLit, an as bindImports, ao as bindingsOf, ap as bool, aq as boolLit, ar as callTranspiledExport, as as callTranspiledExportApply, at as callTranspiledExportFull, au as collectAbsExports, av as confJoin, aw as emptyPhi, ax as eq, ay as evalExprAbs, az as ge, aA as geNum, aB as getEvalCallCollector, aC as getFnImpl, aD as getImplicationOracle, aE as gt, aF as gtNum, aG as implies, aH as isAbsApplyResult, aI as isAbsVal, aJ as isBigPrim, aK as isExactLit, aL as isNumPrim, aM as isStrPrim, aN as le, aO as leNum, aP as lit, aQ as litValue, aR as lt, aS as ltNum, aT as makeAbsApplyResult, aU as markPureFn, aV as namespaceAbsOf, aW as ne, aX as negatePred, aY as never, aZ as not, a_ as noteEvalCallRecord, a$ as noteEvalFallback, b0 as num, b1 as numLit, b2 as numVar, b3 as obj, b4 as or, b5 as pFalse, b6 as pTrue, b7 as phiAnd, b8 as predEquals, b9 as predToString, ba as predVars, bb as primToTypeof, bc as ptypeof, bd as pureFnNameOf, be as relationFingerprint, bf as relationFn, bg as resetEvalCallBudget, bh as runTranspiled, bi as runTranspiledOptionsMemoKey, bj as setEvalAssignCollector, bk as setEvalBindingSink, bl as setEvalCallCollector, bm as setEvalFallbackCollector, bn as setImplicationOracle, bo as shapeOfTerm, bp as shapeOnlyFn, bq as shapeToString, br as simplifyTerm, bs as str, bt as strLit, bu as substPred, bv as termEquals, bw as termToString, bx as tryRunTranspiled, by as unknown, bz as v } from './run-Dg7gQO2z.js';
1
+ import { c as AstEnv, A as Abs, b as Phi, T as Term, O as HofCollectCtx, C as Confidence, S as Shape, a as Pred, R as RelSource, Q as HofSite, U as AbsModuleExports, V as RunTranspiledOptions } from './run-BuTz_p4k.js';
2
+ export { W as $assignRecord, X as $call, Y as $callNamed, Z as $recordBinding, _ as AbsApplyNoThrow, a0 as AbsApplyNoThrowFn, a1 as AbsApplyResult, a2 as AbsApplyReturn, a3 as AbsFnImpl, a4 as AbsSigImpl, a5 as EvalAbsAssignRecord, a6 as EvalCallRecord, a7 as EvalFallback, a8 as ImplicationOracle, a9 as LitValueResult, L as LiteralValue, aa as MAX_EVAL_CALL_DEPTH, ab as MAX_EVAL_TOTAL_CALLS, P as PrimName, ac as RUNTIME_IMPORT_RE, ad as TYPEOF_NAMES, ae as TranspiledCallResult, af as TypeofName, ag as abs, ah as absFunction, ai as absOnly, aj as absToString, ak as and, al as anyAbs, am as anyVar, an as app, ao as assumeFinite, ap as attachFnImpl, aq as bigintLit, ar as bindImports, as as bindingsOf, at as bool, au as boolLit, av as callTranspiledExport, aw as callTranspiledExportApply, ax as callTranspiledExportFull, ay as collectAbsExports, az as confJoin, aA as emptyPhi, aB as eq, aC as evalExprAbs, aD as ge, aE as geNum, aF as getEvalCallCollector, aG as getFnImpl, aH as getImplicationOracle, aI as gt, aJ as gtNum, aK as implies, aL as isAbsApplyResult, aM as isAbsVal, aN as isBigPrim, aO as isExactLit, aP as isNumPrim, aQ as isStrPrim, aR as le, aS as leNum, aT as lit, aU as litValue, aV as lt, aW as ltNum, aX as makeAbsApplyResult, aY as markPureFn, aZ as namespaceAbsOf, a_ as ne, a$ as negatePred, b0 as never, b1 as not, b2 as noteEvalCallRecord, b3 as noteEvalFallback, b4 as num, b5 as numLit, b6 as numVar, b7 as obj, b8 as or, b9 as pFalse, ba as pTrue, bb as phiAnd, bc as predEquals, bd as predToString, be as predVars, bf as primToTypeof, bg as ptypeof, bh as pureFnNameOf, bi as relationFingerprint, bj as relationFn, bk as resetEvalCallBudget, bl as runTranspiled, bm as runTranspiledOptionsMemoKey, bn as setEvalAssignCollector, bo as setEvalBindingSink, bp as setEvalCallCollector, bq as setEvalFallbackCollector, br as setImplicationOracle, bs as shapeOfTerm, bt as shapeOnlyFn, bu as shapeToString, bv as simplifyTerm, bw as str, bx as strLit, by as substPred, bz as termEquals, bA as termToString, bB as tryRunTranspiled, bC as unknown, bD as v } from './run-BuTz_p4k.js';
3
3
  import { Node, File } from '@babel/types';
4
- import { p as parseSource, L as LeakBudget, E as EffectiveInterfaceOpts, b as LoadDepsFingerprint, v as CheckReport, N as NudoConstraint, c as ProjectionBudget } from './projection-budget-CGbs16aX.js';
5
- export { w as CONSTRAINT_BUILDERS, x as CONSTRAINT_BUILDER_NAMES, y as CONSTRAINT_EXPR_RE, z as CheckAction, C as CheckIssue, A as CheckJson, B as CheckJsonMulti, D as ConstraintBuilder, F as Diagnostic, G as EffectiveInterface, H as GitlabCodeQualityIssue, J as InterfaceDiag, I as InterfaceSource, K as InterfaceTierInfo, a as InterfaceTierOpts, O as NamedImport, Q as NudoField, R as NudoFnConstraint, S as NudoSidecarError, T as NudoSig, U as RefineDiag, V as RefineEntry, W as RefineResolveOpts, X as SELF, Y as actionsForIssue, Z as andC, _ as any, $ as array, a0 as boolean, a1 as checkArg, a2 as checkCall, a3 as constraintAdmitsNullish, a4 as constraintToEntryAbs, a5 as drainPromiseMicros, a6 as effectiveInterface, a7 as enterPromiseExecutorScope, a8 as evalPromiseCtor, a9 as evalPromiseMethod, aa as evalPromiseStatic, ab as execNudoModule, ac as extractDeclaredThrows, ad as extractFnBudget, ae as extractNudoImports, af as extractRefineReturnFromSource, ag as extractRefinesFromSource, ah as fn, ai as fnConstraintToEntryReqs, aj as formatCheckReport, ak as formatConstraint, al as formatDiagnostics, am as formatEffectiveInterfaceDisplay, an as formatGithubAnnotations, ao as formatGitlabCodeQuality, ap as formatInterfaceTierLine, aq as generatedExportNames, ar as getParseSourceCacheSize, as as getTerm, at as instantiateConstraint, au as interfaceDiagCount, av as interfaceSourceOf, aw as interfaceTierOf, ax as isIntFlag, ay as isNodeModulesPath, az as isNudoConstraint, aA as leavePromiseExecutorScope, aB as lenTerm, aC as litC, aD as localNamedExports, aE as notePromiseExecutorFork, aF as nullable, aG as number, aH as omit, aI as partial, aJ as pick, aK as queuePromiseMicro, aL as refineDiagCount, aM as refineToIndexedFull, aN as resetNudoModuleExecCache, aO as resetParseSourceCache, aP as resetSidecarLoadFailureCache, aQ as serializeCheckJson, aR as serializeCheckJsonMulti, aS as setInterfaceDiagCollector, aT as setRefineDiagCollector, aU as shape, aV as sidecarClosureFingerprint, aW as sidecarPathOf, aX as string, aY as takeInterfaceDiags, aZ as takeInterfaceDiagsSince, a_ as takeRefineDiags, a$ as takeRefineDiagsSince, b0 as throwConstraintToKinds, b1 as union } from './projection-budget-CGbs16aX.js';
4
+ import { p as parseSource, L as LeakBudget, E as EffectiveInterfaceOpts, b as LoadDepsFingerprint, v as CheckReport, N as NudoConstraint, c as ProjectionBudget } from './projection-budget-CWlRVYgL.js';
5
+ export { w as CONSTRAINT_BUILDERS, x as CONSTRAINT_BUILDER_NAMES, y as CONSTRAINT_EXPR_RE, z as CheckAction, C as CheckIssue, A as CheckJson, B as CheckJsonMulti, D as ConstraintBuilder, F as Diagnostic, G as EffectiveInterface, H as GitlabCodeQualityIssue, J as InterfaceDiag, I as InterfaceSource, K as InterfaceTierInfo, a as InterfaceTierOpts, O as NamedImport, Q as NudoField, R as NudoFnConstraint, S as NudoSidecarError, T as NudoSig, U as RefineDiag, V as RefineEntry, W as RefineResolveOpts, X as SELF, Y as actionsForIssue, Z as andC, _ as any, $ as array, a0 as boolean, a1 as checkArg, a2 as checkCall, a3 as constraintAdmitsNullish, a4 as constraintToEntryAbs, a5 as drainPromiseMicros, a6 as effectiveInterface, a7 as enterPromiseExecutorScope, a8 as evalPromiseCtor, a9 as evalPromiseMethod, aa as evalPromiseStatic, ab as execNudoModule, ac as extractDeclaredThrows, ad as extractFnBudget, ae as extractNudoImports, af as extractRefineReturnFromSource, ag as extractRefinesFromSource, ah as fn, ai as fnConstraintToEntryReqs, aj as formatCheckReport, ak as formatConstraint, al as formatDiagnostics, am as formatEffectiveInterfaceDisplay, an as formatGithubAnnotations, ao as formatGitlabCodeQuality, ap as formatInterfaceTierLine, aq as generatedExportNames, ar as getParseSourceCacheSize, as as getTerm, at as instantiateConstraint, au as interfaceDiagCount, av as interfaceSourceOf, aw as interfaceTierOf, ax as isIntFlag, ay as isNodeModulesPath, az as isNudoConstraint, aA as leavePromiseExecutorScope, aB as lenTerm, aC as litC, aD as localNamedExports, aE as notePromiseExecutorFork, aF as nullable, aG as number, aH as omit, aI as partial, aJ as pick, aK as queuePromiseMicro, aL as refineDiagCount, aM as refineToIndexedFull, aN as resetNudoModuleExecCache, aO as resetParseSourceCache, aP as resetSidecarLoadFailureCache, aQ as serializeCheckJson, aR as serializeCheckJsonMulti, aS as setInterfaceDiagCollector, aT as setRefineDiagCollector, aU as shape, aV as sidecarClosureFingerprint, aW as sidecarPathOf, aX as string, aY as takeInterfaceDiags, aZ as takeInterfaceDiagsSince, a_ as takeRefineDiags, a$ as takeRefineDiagsSince, b0 as throwConstraintToKinds, b1 as union } from './projection-budget-CWlRVYgL.js';
6
6
  export { $add, $arguments, $arr, $arrMutContainer, $arrRest, $arrWithHoles, $async, $asyncReturn, $await, $bitand, $bitnot, $bitor, $bitxor, $catchVal, $class, $classExpr, $collectionForEach, $concat, $copy, $del, $delRes, $div, $dynamicImport, $elems, $eq, $eqLoose, $fnVal, $for, $forInKeys, $forIter, $forOf, $fork, $ge, $gen, $get, $gt, $idx, $idxSet, $importMeta, $in, $instanceof, $instanceofNonIdent, $invoke, $invokeSuper, $isBreakTo, $isForkExit, $join, $le, $len, $lit, $loopBreak, $loopContinue, $loopReturn, $lt, $mod, $mul, $ne, $neLoose, $neg, $new, $not, $nullishTest, $obj, $objAccessor, $objRest, $optionalGet, $optionalInvoke, $orDefault, $pow, $pushLoopExit, $rawThis, $reStateCall, $regex, $rethrowIfNudoReturn, $set, $setKey, $shl, $shr, $spread, $staticInvoke, $sub, $super, $switch, $thisGet, $thisSet, $throw, $toNumber, $toNumeric, $tryCurrentMark, $tryDetachSoftCatch, $tryDigestSoftCatch, $tryDiscardSoft, $tryMark, $tryOrphanSoft, $tryPopMark, $tryReleaseSoftCatch, $tryReleaseSoftOut, $tryTakeSince, $typeof, $unknown, $updateAdd, $updateSub, $ushr, $while, $whileSeq, $yield, DEFAULT_MAX_LOOP_ITERS, EvalClassSpec, NudoLoopSignal, NudoReturn, NudoThrow, NudoUnsupportedError, TranspileOptions, asAbsVal, callAtFunctionBoundary, clearBClasses, clearStaleTermPred, currentExecPhi, fillTuple, foldRequireSpecArg, foldStaticStringExpr, getEvalClass, isArrMutator, isDefinitelyFalse, isDefinitelyTrue, isNudoBreak, isNudoContinue, isNudoReturn, isNudoThrow, litTruth, lookupObjAccessor, namespaceNameOf, pushLoopExit, pushThrowExit, registerEvalClass, runWithLoopExits, runtimeImportOf, takeLoopExits, takeThrowExits, transpile, transpileBodyNode, transpileExpression, transpileFile, transpileSource, withExecPhi } from './exec.js';
7
7
 
8
8
  /**
package/dist/index.js CHANGED
@@ -91,7 +91,7 @@ import {
91
91
  takeRefineDiagsSince,
92
92
  throwConstraintToKinds,
93
93
  union
94
- } from "./chunk-GC7VNUCB.js";
94
+ } from "./chunk-XVU2O6VF.js";
95
95
  import {
96
96
  $add,
97
97
  $arguments,
@@ -206,6 +206,7 @@ import {
206
206
  DEFAULT_MAX_LOOP_ITERS,
207
207
  FORK_TRUNCATION_LABEL,
208
208
  HOST_EFFECT_LABEL_PREFIX,
209
+ MATH_FOLD_ERROR_LABEL,
209
210
  MAX_EVAL_CALL_DEPTH,
210
211
  MAX_EVAL_TOTAL_CALLS,
211
212
  NudoLoopSignal,
@@ -446,6 +447,7 @@ import {
446
447
  resetParseSourceCache,
447
448
  runTranspiled,
448
449
  runTranspiledOptionsMemoKey,
450
+ runWithCollectorScope,
449
451
  runWithLoopExits,
450
452
  runWithMayThrowSession,
451
453
  runtimeImportOf,
@@ -509,7 +511,7 @@ import {
509
511
  v,
510
512
  withExecPhi,
511
513
  withVar
512
- } from "./chunk-BM3UPEA7.js";
514
+ } from "./chunk-TO2W45NU.js";
513
515
 
514
516
  // src/environment.ts
515
517
  function createEnvironment(parent, bindings = /* @__PURE__ */ new Map()) {
@@ -1773,6 +1775,14 @@ function evalThrowsOf(source, fnName, args, opts = {}, phi = pTrue) {
1773
1775
  // src/algebra/check-assign.ts
1774
1776
  function widenForAssign(a) {
1775
1777
  const s = a.shape;
1778
+ if (s.k === "sum") {
1779
+ if (s.members.length > 0 && s.members.every((m) => m.shape.k === "tuple" || m.shape.k === "arr")) {
1780
+ const els = s.members.map(widenForAssign).map((w) => w.shape.k === "arr" ? w.shape.element : w);
1781
+ const el = els.reduce((x, y) => joinAbs(x, y));
1782
+ return abs({ k: "arr", element: el }, void 0, void 0, a.conf);
1783
+ }
1784
+ return a;
1785
+ }
1776
1786
  if (s.k === "tuple") {
1777
1787
  const holes = new Set(s.holes ?? []);
1778
1788
  const els = s.elements.filter((_, i) => !holes.has(i));
@@ -2050,6 +2060,11 @@ function scanCaseInconsistency(source, knownFns, opts) {
2050
2060
 
2051
2061
  // src/algebra/check.ts
2052
2062
  function checkSource(filePath, source, phi = pTrue, opts = {}) {
2063
+ return runWithCollectorScope(
2064
+ () => checkSourceInScope(filePath, source, phi, opts)
2065
+ );
2066
+ }
2067
+ function checkSourceInScope(filePath, source, phi, opts) {
2053
2068
  let callOpts = opts;
2054
2069
  if (opts.loadModule && opts.fromFile) {
2055
2070
  const loadCache = /* @__PURE__ */ new Map();
@@ -2144,8 +2159,8 @@ function sidecarDiagIssues(diags) {
2144
2159
  }
2145
2160
  function checkSourceInner(filePath, source, file, phi, opts, issues, signatures, names, truncated, identityOpts = opts, depsFp, sidecarFp) {
2146
2161
  const hasRefineDirective = stripStringsKeepComments(source).includes("@nudo:contract");
2147
- const exportedNames = sidecarFp !== void 0 ? localNamedExports(source) : void 0;
2148
2162
  const entryNames = localNamedExports(source);
2163
+ const exportedNames = sidecarFp !== void 0 ? entryNames : void 0;
2149
2164
  const entryThrowsMode = opts.entryThrows ?? "error";
2150
2165
  const ignoreThrows = opts.ignoreThrows;
2151
2166
  const driftCandidates = [];
@@ -2447,6 +2462,15 @@ function checkSourceInner(filePath, source, file, phi, opts, issues, signatures,
2447
2462
  });
2448
2463
  continue;
2449
2464
  }
2465
+ if (label === MATH_FOLD_ERROR_LABEL) {
2466
+ issues.push({
2467
+ severity: "info",
2468
+ code: "nudo:math-fold-error",
2469
+ message: `A Math native fold threw during analysis (host-tampered or divergent Math.*); the result was widened to number`,
2470
+ suggestion: "optional: keep Math.* builtins unmodified in analyzed code, or mock them with @nudo:mock \u2014 non-blocking"
2471
+ });
2472
+ continue;
2473
+ }
2450
2474
  if (label.startsWith(HOST_EFFECT_LABEL_PREFIX)) {
2451
2475
  const hostName = label.slice(HOST_EFFECT_LABEL_PREFIX.length);
2452
2476
  issues.push({
@@ -1,7 +1,7 @@
1
- import { I as InterfaceSource, a as InterfaceTierOpts, p as parseSource, C as CheckIssue } from './projection-budget-CGbs16aX.js';
2
- export { L as LeakBudget, b as LoadDepsFingerprint, M as MAX_PROMISE_MICROS, P as PROJECTION_MAX_DEPTH, c as ProjectionBudget, d as ProjectionStopReason, e as defaultLeakBudget, f as exceedsBudget, g as exportedNameOfLocal, h as extractAllLoadSpecs, i as getPromiseMicrosLength, l as leakIfNeeded, j as loadModuleDepsFingerprint, m as maybeLeak, n as normPath, r as resetLeakCounter, k as resolveDepPath, s as sidecarSpecsOf, o as stablePathKey, q as stablePathKeyGraph, t as termDepth, u as termNodes } from './projection-budget-CGbs16aX.js';
3
- import { A as Abs, T as Term, c as AstEnv } from './run-Dg7gQO2z.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-Dg7gQO2z.js';
1
+ import { I as InterfaceSource, a as InterfaceTierOpts, p as parseSource, C as CheckIssue } from './projection-budget-CWlRVYgL.js';
2
+ export { L as LeakBudget, b as LoadDepsFingerprint, M as MAX_PROMISE_MICROS, P as PROJECTION_MAX_DEPTH, c as ProjectionBudget, d as ProjectionStopReason, e as defaultLeakBudget, f as exceedsBudget, g as exportedNameOfLocal, h as extractAllLoadSpecs, i as getPromiseMicrosLength, l as leakIfNeeded, j as loadModuleDepsFingerprint, m as maybeLeak, n as normPath, r as resetLeakCounter, k as resolveDepPath, s as sidecarSpecsOf, o as stablePathKey, q as stablePathKeyGraph, t as termDepth, u as termNodes } from './projection-budget-CWlRVYgL.js';
3
+ import { A as Abs, T as Term, c as AstEnv } from './run-BuTz_p4k.js';
4
+ export { $ as $tryDigestSoft, d as $tryMarkSoft, e as $tryReleaseSoft, E as ERROR_FAMILY, f as EvalFallbackStats, M as MayThrowEffect, g as absLit, h as absNumLit, i as absStrLit, j as allAbsStr, k as clearPureCallMemo, l as clearPureMemo, m as enterEvalCallBudgetSession, n as errorTypeAbs, o as exitEvalCallBudgetSession, p as filterDeclaredThrows, q as filterGateThrows, r as filterIgnoredThrows, s as flushMayThrowEffects, t as formatThrowsAbs, u as getEvalCallBudgetState, v as getEvalFallbackStats, w as getMayThrowCollector, x as isThrowsIgnored, y as mayThrowEffectsToAbs, z as orphanMayThrowEffects, B as popMayThrowFrame, D as pushMayThrowFrame, F as recordMayThrow, G as resetEvalFallbackStats, H as runWithMayThrowSession, I as setMayThrowCollector, J as throwAbsToKinds, K as throwsKindCovered, N as withEvalBudgetOverride } from './run-BuTz_p4k.js';
5
5
  import { File, Node } from '@babel/types';
6
6
 
7
7
  /**
@@ -149,6 +149,80 @@ declare function resetEvalForkBudget(): void;
149
149
  /** $fork 入口:超限放弃该分支(调用方返回 unknown = 最保守,安全)。 */
150
150
  declare function bumpEvalForkBudget(): boolean;
151
151
 
152
+ /**
153
+ * 可 ALS 隔离的模块级可变槽。
154
+ * 语义:`get`/`set` 作用于当前最内层 store(无作用域 = fallback);
155
+ * `runScoped` 以**进入时当前值**为初始值开新 store(继承语义:嵌套
156
+ * save/restore 与今日模块全局逐位一致)。
157
+ */
158
+ type ScopedSlot<T> = {
159
+ get(): T;
160
+ set(v: T): void;
161
+ runScoped<R>(body: () => R): R;
162
+ };
163
+ declare function createScopedSlot<T>(init: () => T): ScopedSlot<T>;
164
+ /** 作用域参与者:把 body 包进自己那条 ALS store(runWithCollectorScope 组合用) */
165
+ type CollectorScopeParticipant = <R>(body: () => R) => R;
166
+ /**
167
+ * 注册一个作用域参与者(模块加载时调用一次)。
168
+ * 参与者未加载 = 其状态本就无人触碰,不注册无影响。
169
+ */
170
+ declare function registerCollectorScopeParticipant(enter: CollectorScopeParticipant): void;
171
+ /**
172
+ * 进入一次完整分析的 collector 生命周期作用域。幂等(已在作用域内 →
173
+ * 直接执行)。body 可返回 Promise:async 续体沿 ALS 链继承 store,
174
+ * await 窗口内交错开启的其它作用域互不可见。
175
+ */
176
+ declare function runWithCollectorScope<R>(body: () => R): R;
177
+
178
+ /**
179
+ * 诊断 side-channel 共享原语(leaf 模块:零依赖)。
180
+ *
181
+ * refine(RefineDiag)/ interface(InterfaceDiag)各持一份同构实现
182
+ * (collector + seq + 定容环形缓冲 + takeSince 增量排干)——历史上多份
183
+ * 拷贝各自漂移过,收敛到本文件单一定义。
184
+ *
185
+ * seq 语义(消费方以此为 since 锚,不得改动):
186
+ * - emit 时 `++seq` 入队(首条 seq=1);
187
+ * - count() 返回当前累计序号——探测方先 count 取锚;
188
+ * - takeSince(since) 只排走 seq > since 的增量(清空仅限增量),
189
+ * 更早的在途条目保留给其真正消费方(全量 take 曾在 await 窗口
190
+ * 偷走在途诊断——两轮事故的根因)。
191
+ */
192
+ /** 诊断通道:一个具名 side-channel 的全部操作 */
193
+ type DiagChannel<T> = {
194
+ /** 设置诊断观察者(null 清除);缓冲照常累积,take 取走 */
195
+ setCollector(fn: ((d: T) => void) | null): void;
196
+ /** 当前观察者(作用域继承用;null = 无) */
197
+ getCollector(): ((d: T) => void) | null;
198
+ /** 当前诊断累计序号(since 锚) */
199
+ count(): number;
200
+ /** 取走已收集的诊断(收集即清空) */
201
+ take(): T[];
202
+ /** 只取走 seq > since 的增量(清空仅限增量;更早在途条目保留) */
203
+ takeSince(since: number): T[];
204
+ /** 入队一条诊断(缓冲满 cap 挤出最旧条目)并通知观察者 */
205
+ emit(d: T): void;
206
+ };
207
+ /**
208
+ * 创建定容诊断通道:缓冲达 cap 后挤出最旧条目(防长会话无界增长,
209
+ * 消费方 take/takeSince 按批取走)。
210
+ */
211
+ declare function createDiagChannel<T>(cap: number): DiagChannel<T>;
212
+ /**
213
+ * 可作用域隔离的诊断通道(collector-scope 配套)。
214
+ *
215
+ * - 无作用域:所有操作落到模块级 fallback 通道(行为 = 今日)。
216
+ * - `runScoped` 开新通道:**空缓冲、seq 归零**(锚/buffer 是消费方私有的,
217
+ * 不得跨分析携带——交错分析的条目混进同一缓冲正是「偷诊断」形态),
218
+ * 观察者**继承**进入时的当前观察者(宿主在分析外装的观察器继续可见,
219
+ * 但只收到本作用域内发出的条目)。
220
+ */
221
+ type ScopedDiagChannel<T> = DiagChannel<T> & {
222
+ runScoped<R>(body: () => R): R;
223
+ };
224
+ declare function createScopedDiagChannel<T>(cap: number): ScopedDiagChannel<T>;
225
+
152
226
  declare function hashSource(s: string): string;
153
227
  declare function resetHashSourceCache(): void;
154
228
 
@@ -669,4 +743,4 @@ declare function runWithEvalMissingSlot<T>(enabled: boolean, body: () => T): T;
669
743
  */
670
744
  declare function noteObjSlotMissing(recv: Abs | undefined, name: string, loc?: [number, number]): boolean;
671
745
 
672
- export { type AbsBudgetStats, type AbsInlay, type ArgDerivation, type ClassDef, type CollectAbsInlaysOpts, type DerivationNode, type EvalMemberDiag, FORK_TRUNCATION_LABEL, type FnFp, HOST_EFFECT_LABEL_PREFIX, type InjectedDomainEvidenceOpts, type InjectedDomainRecord, MAX_CALL_DEPTH, MAX_EVAL_TOTAL_FORKS, MAX_TOTAL_CALLS, type MethodDef, OBJECT_PROTO_NAMES, PROMISE_MICRO_ERROR_LABEL, PROMISE_MICRO_OVERFLOW_LABEL, type StringLiteralSpan, type TemplateMeta, type TemplatePartDesc, type TemplatePartView, type TemplatePredicateDecision, abortDerivationSession, absTemplateViews, allFixedTextOfViews, anyMemberResult, awaitAbs, beginDerivationSession, bumpEvalForkBudget, callBudgetKey, canSkipLiteralCallScan, checkInjectedDomainEvidence, classChainNames, classFromMethods, coerceAsyncReturn, collectAbsInlays, concatString, createTemplateAbs, decideEndsWith, decideIncludes, decideStartsWith, defineClass, definitelyUncallableMember, denoteGuard, derivationChain, endDerivationSession, enterCall, escapeTemplateTypeFixed, exitCall, fixedLengthOfViews, fnFingerprints, formatObjectKey, formatTemplateNameViews, generalizeSourceKeyPart, getAbsCallBudgetStats, getAbsOrigin, getClass, getClassChain, getDerivation, getEvalForkBudgetLimit, getEvalForkCount, getFnNameAndBodies, hasDerivationSession, hashSource, instanceOf, instantiateClass, isEvalMissingSlotEnabled, isJsBindingIdent, isJsIdent, isNullishAbs, isTemplateLike, knownPrefixOfViews, knownSuffixOfViews, listTopFunctions, lookupMethod, lookupMethodWithOwner, lookupSuperMethod, maskCommentsAndStrings, mergeAdjacentFixedViews, noteAbsTruncation, noteAnyMemberMayThrow, noteDerivationAdd, noteDerivationJoin, noteEvalForkTruncation, noteHostEffectBlocked, noteMemberDispatchMiss, noteNullishMemberThrows, noteObjSlotMissing, notePrimMemberMissing, noteUnknownMemberMissing, popCallLoc, projectBrand, projectDerivationDsl, pushCallLoc, recordMemberDiag, resetAbsCallBudget, resetEvalForkBudget, resetFnFpCache, resetHashSourceCache, runWithEvalMissingSlot, safeMemberAccess, sanitizeCommentText, scanStringLiterals, setAbsTruncationCollector, setDerivation, setDerivationCollector, setEvalForkBudgetLimit, setEvalMissingSlotEnabled, setMemberDiagCollector, sourceHasCjsExports, sourceHasModuleDependency, sourceHasRequireCall, stableAnalyzeKeySource, stableCallId, stripCommentsAndStrings, stripStringsKeepComments, superNameOf, tagAbsOrigin, tagDerivationRoot, templateMatchesValue, templatePartsOf, termKey, toJsBindingIdent, truncatedAbs, viewTemplateParts, withFnBudgetOverride, wrapPromise };
746
+ export { type AbsBudgetStats, type AbsInlay, type ArgDerivation, type ClassDef, type CollectAbsInlaysOpts, type CollectorScopeParticipant, type DerivationNode, type DiagChannel, type EvalMemberDiag, FORK_TRUNCATION_LABEL, type FnFp, HOST_EFFECT_LABEL_PREFIX, type InjectedDomainEvidenceOpts, type InjectedDomainRecord, MAX_CALL_DEPTH, MAX_EVAL_TOTAL_FORKS, MAX_TOTAL_CALLS, type MethodDef, OBJECT_PROTO_NAMES, PROMISE_MICRO_ERROR_LABEL, PROMISE_MICRO_OVERFLOW_LABEL, type ScopedDiagChannel, type ScopedSlot, type StringLiteralSpan, type TemplateMeta, type TemplatePartDesc, type TemplatePartView, type TemplatePredicateDecision, abortDerivationSession, absTemplateViews, allFixedTextOfViews, anyMemberResult, awaitAbs, beginDerivationSession, bumpEvalForkBudget, callBudgetKey, canSkipLiteralCallScan, checkInjectedDomainEvidence, classChainNames, classFromMethods, coerceAsyncReturn, collectAbsInlays, concatString, createDiagChannel, createScopedDiagChannel, createScopedSlot, createTemplateAbs, decideEndsWith, decideIncludes, decideStartsWith, defineClass, definitelyUncallableMember, denoteGuard, derivationChain, endDerivationSession, enterCall, escapeTemplateTypeFixed, exitCall, fixedLengthOfViews, fnFingerprints, formatObjectKey, formatTemplateNameViews, generalizeSourceKeyPart, getAbsCallBudgetStats, getAbsOrigin, getClass, getClassChain, getDerivation, getEvalForkBudgetLimit, getEvalForkCount, getFnNameAndBodies, hasDerivationSession, hashSource, instanceOf, instantiateClass, isEvalMissingSlotEnabled, isJsBindingIdent, isJsIdent, isNullishAbs, isTemplateLike, knownPrefixOfViews, knownSuffixOfViews, listTopFunctions, lookupMethod, lookupMethodWithOwner, lookupSuperMethod, maskCommentsAndStrings, mergeAdjacentFixedViews, noteAbsTruncation, noteAnyMemberMayThrow, noteDerivationAdd, noteDerivationJoin, noteEvalForkTruncation, noteHostEffectBlocked, noteMemberDispatchMiss, noteNullishMemberThrows, noteObjSlotMissing, notePrimMemberMissing, noteUnknownMemberMissing, popCallLoc, projectBrand, projectDerivationDsl, pushCallLoc, recordMemberDiag, registerCollectorScopeParticipant, resetAbsCallBudget, resetEvalForkBudget, resetFnFpCache, resetHashSourceCache, runWithCollectorScope, runWithEvalMissingSlot, safeMemberAccess, sanitizeCommentText, scanStringLiterals, setAbsTruncationCollector, setDerivation, setDerivationCollector, setEvalForkBudgetLimit, setEvalMissingSlotEnabled, setMemberDiagCollector, sourceHasCjsExports, sourceHasModuleDependency, sourceHasRequireCall, stableAnalyzeKeySource, stableCallId, stripCommentsAndStrings, stripStringsKeepComments, superNameOf, tagAbsOrigin, tagDerivationRoot, templateMatchesValue, templatePartsOf, termKey, toJsBindingIdent, truncatedAbs, viewTemplateParts, withFnBudgetOverride, wrapPromise };