@nudojs/core 1.17.0 → 1.17.1

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.
@@ -2219,7 +2219,7 @@ function transformNode(node, source, opts, ctx2) {
2219
2219
  function stripTypes(ast, source, opts) {
2220
2220
  const { valueRefs, typeRefs, ambiguousRefs } = collectValueReferences(ast);
2221
2221
  const ctx2 = { valueRefs, typeRefs, ambiguousRefs };
2222
- const directivesBefore = countNudoDirectives(ast);
2222
+ const directivesBefore = opts?.report ? countNudoDirectives(ast) : 0;
2223
2223
  transformValue(ast, source, opts, ctx2);
2224
2224
  if (opts?.report) {
2225
2225
  const directivesAfter = countNudoDirectives(ast);
@@ -2275,7 +2275,8 @@ function parseWithJsxFallback(source, plugins, opts) {
2275
2275
  function parseUncached(source, opts) {
2276
2276
  const mode = parseModeFor(opts?.filename);
2277
2277
  const ast = parseWithJsxFallback(source, PLUGINS_BY_MODE[mode], opts);
2278
- return opts?.keepTs === true ? ast : stripTypes(ast, source);
2278
+ if (opts?.keepTs === true || mode === "js") return ast;
2279
+ return stripTypes(ast, source);
2279
2280
  }
2280
2281
  function parseSource(source, opts) {
2281
2282
  if (opts?.keepTs === true || opts?.errorRecovery === true) {
@@ -12247,7 +12248,12 @@ function transpileFnBodyStmts(stmtsIn, depth, opts, varScope) {
12247
12248
  `${pad}let ${declNames.map((n) => `${n} = $lit(void 0)`).join(", ")};`
12248
12249
  );
12249
12250
  }
12250
- varOpts = { ...opts, hoistedVarNames: hoisted, keepVarDecl: void 0 };
12251
+ varOpts = {
12252
+ ...opts,
12253
+ hoistedVarNames: hoisted,
12254
+ keepVarDecl: void 0,
12255
+ paramNames: varScope.skip
12256
+ };
12251
12257
  if (opts.constNames && varScope.skip.size > 0) {
12252
12258
  varOpts = {
12253
12259
  ...varOpts,
@@ -14540,8 +14546,9 @@ function transpileAssignmentExpr(expr, opts = {}) {
14540
14546
  const locLine = expr.loc?.start.line ?? 0;
14541
14547
  const locCol = expr.loc?.start.column ?? 0;
14542
14548
  const valSrc = compoundFn ? `${compoundFn}(${name}, ${right})` : right;
14549
+ const paramFlag = opts.paramNames?.has(name) === true ? ", true" : "";
14543
14550
  const bindSrc = !opts.inFunction ? ` $recordBinding(${JSON.stringify(name)}, ${assignV});` : "";
14544
- return `((${assignV}) => { $assignRecord(${JSON.stringify(name)}, ${name}, ${assignV}, ${locLine}, ${locCol}, ${cond});${bindSrc} return ${name} = ${assignV}; })(${valSrc})`;
14551
+ return `((${assignV}) => { $assignRecord(${JSON.stringify(name)}, ${name}, ${assignV}, ${locLine}, ${locCol}, ${cond}${paramFlag});${bindSrc} return ${name} = ${assignV}; })(${valSrc})`;
14545
14552
  }
14546
14553
  throw new NudoUnsupportedError(
14547
14554
  `assign-target`,
@@ -19743,7 +19750,7 @@ function setEvalAssignCollector(collector) {
19743
19750
  evalAssignCollectorSlot.set(collector);
19744
19751
  return prev;
19745
19752
  }
19746
- function $assignRecord(name, prev, next, line, column, conditional) {
19753
+ function $assignRecord(name, prev, next, line, column, conditional, paramBinding) {
19747
19754
  const evalAssignCollector = evalAssignCollectorSlot.get();
19748
19755
  if (!evalAssignCollector) return;
19749
19756
  try {
@@ -19754,6 +19761,7 @@ function $assignRecord(name, prev, next, line, column, conditional) {
19754
19761
  line: line || void 0,
19755
19762
  column: column || void 0,
19756
19763
  conditional,
19764
+ ...paramBinding === true ? { paramBinding: true } : {},
19757
19765
  // 调用方帧深度(与 EvalCallRecord.depth 同口径——局部量投影按帧过滤)
19758
19766
  depth: evalBudget.depth
19759
19767
  });
@@ -34119,6 +34127,9 @@ var stripStringsKeepCommentsCache = new BoundedLruMap(
34119
34127
  var maskCommentsAndStringsCache = new BoundedLruMap(
34120
34128
  SOURCE_SCAN_CACHE_MAX
34121
34129
  );
34130
+ var maskStringsKeepCommentsCache = new BoundedLruMap(
34131
+ SOURCE_SCAN_CACHE_MAX
34132
+ );
34122
34133
  var REGEX_KEYWORDS = /* @__PURE__ */ new Set([
34123
34134
  "await",
34124
34135
  "case",
@@ -34194,7 +34205,15 @@ function scanRegex(source, start) {
34194
34205
  }
34195
34206
  return n;
34196
34207
  }
34208
+ var scanSourceCache = new BoundedLruMap(8);
34197
34209
  function scanSource(source) {
34210
+ const hit = scanSourceCache.get(source);
34211
+ if (hit !== void 0) return hit;
34212
+ const out = scanSourceUncached(source);
34213
+ scanSourceCache.set(source, out);
34214
+ return out;
34215
+ }
34216
+ function scanSourceUncached(source) {
34198
34217
  const spans = [];
34199
34218
  const literals = [];
34200
34219
  const n = source.length;
@@ -34388,14 +34407,17 @@ function maskCommentsAndStrings(source) {
34388
34407
  return out;
34389
34408
  }
34390
34409
  function maskStringsKeepComments(source) {
34410
+ const hit = maskStringsKeepCommentsCache.get(source);
34411
+ if (hit !== void 0) return hit;
34391
34412
  let out = "";
34392
34413
  for (const span of scanSource(source).spans) {
34393
34414
  out += span.kind === "string" ? span.text.replace(/[^\n]/g, " ") : span.text;
34394
34415
  }
34416
+ maskStringsKeepCommentsCache.set(source, out);
34395
34417
  return out;
34396
34418
  }
34397
34419
  function scanStringLiterals(source) {
34398
- return scanSource(source).literals;
34420
+ return [...scanSource(source).literals];
34399
34421
  }
34400
34422
  function sourceHasRequireCall(source) {
34401
34423
  return /\brequire\s*\(/.test(stripCommentsAndStrings(source));
@@ -41502,6 +41524,7 @@ export {
41502
41524
  isEvalMissingSlotEnabled,
41503
41525
  runWithEvalMissingSlot,
41504
41526
  noteObjSlotMissing,
41527
+ BoundedLruMap,
41505
41528
  numericBoundsImply,
41506
41529
  getClassChain,
41507
41530
  wrapPromise,
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  $invoke,
3
3
  $new,
4
+ BoundedLruMap,
4
5
  CONSTRAINT_BUILDERS,
5
6
  DIAG,
6
7
  LAZY_TEMPLATE_DEPTH,
@@ -69,7 +70,7 @@ import {
69
70
  withExecPhi,
70
71
  withFnBudgetOverride,
71
72
  withOptionalParams
72
- } from "./chunk-ARIQO5XX.js";
73
+ } from "./chunk-CUFP2AYV.js";
73
74
 
74
75
  // src/algebra/directive-scan.ts
75
76
  function cleanDirectiveLine(raw, kind) {
@@ -621,8 +622,16 @@ function nestedBodyRanges(source) {
621
622
  return [];
622
623
  }
623
624
  }
625
+ var BODY_GATE_RANGES_CACHE_MAX = 16;
626
+ var bodyGateRangesCache = new BoundedLruMap(
627
+ BODY_GATE_RANGES_CACHE_MAX
628
+ );
624
629
  function bodyGateRanges(source) {
625
- return [...functionBodyRanges(source), ...nestedBodyRanges(source)];
630
+ const hit = bodyGateRangesCache.get(source);
631
+ if (hit !== void 0) return hit;
632
+ const out = [...functionBodyRanges(source), ...nestedBodyRanges(source)];
633
+ bodyGateRangesCache.set(source, out);
634
+ return out;
626
635
  }
627
636
  function inBodyRange(ranges, offset) {
628
637
  return ranges.some(([s, e]) => offset >= s && offset < e);
@@ -2384,7 +2393,27 @@ function extractFnBudget(source, fnName) {
2384
2393
  }
2385
2394
 
2386
2395
  // src/algebra/scan-named-exports.ts
2396
+ var LOCAL_EXPORTS_CACHE_MAX = 16;
2397
+ var localExportsCache = /* @__PURE__ */ new Map();
2398
+ function memoizedLocalExports(source, compute) {
2399
+ const hit = localExportsCache.get(source);
2400
+ if (hit !== void 0) {
2401
+ localExportsCache.delete(source);
2402
+ localExportsCache.set(source, hit);
2403
+ return new Set(hit);
2404
+ }
2405
+ const out = compute();
2406
+ if (localExportsCache.size >= LOCAL_EXPORTS_CACHE_MAX) {
2407
+ const oldest = localExportsCache.keys().next().value;
2408
+ if (oldest !== void 0) localExportsCache.delete(oldest);
2409
+ }
2410
+ localExportsCache.set(source, out);
2411
+ return new Set(out);
2412
+ }
2387
2413
  function localNamedExports(source) {
2414
+ return memoizedLocalExports(source, () => computeLocalNamedExports(source));
2415
+ }
2416
+ function computeLocalNamedExports(source) {
2388
2417
  const out = /* @__PURE__ */ new Set();
2389
2418
  let ast;
2390
2419
  try {
package/dist/exec.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { A as Abs, M as MayThrowEffect, b as Phi } from './run-tV2J7PNI.js';
2
- export { V as $assignRecord, W as $call, X as $callNamed, bG as $nodoPos, Y as $recordBinding, a4 as EvalAbsAssignRecord, a5 as EvalCallRecord, a6 as EvalFallback, g as EvalFallbackStats, a7 as EvalPosRecord, aa as MAX_EVAL_CALL_DEPTH, ab as MAX_EVAL_TOTAL_CALLS, R as RunTranspiledOptions, ad as TranspiledCallResult, ar as bindingsOf, au as callTranspiledExport, av as callTranspiledExportApply, aw as callTranspiledExportFull, l as clearPureCallMemo, m as clearPureMemo, n as enterEvalCallBudgetSession, aB as evalExprAbs, p as exitEvalCallBudgetSession, v as getEvalCallBudgetState, aE as getEvalCallCollector, w as getEvalFallbackStats, bH as getPosCollector, aM as isAbsVal, aO as isCjsMainRun, b3 as noteEvalCallRecord, b4 as noteEvalFallback, bl as resetEvalCallBudget, H as resetEvalFallbackStats, bI as routeApplyThrows, bm as runTranspiled, bn as runTranspiledOptionsMemoKey, bo as setEvalAssignCollector, bp as setEvalBindingSink, bq as setEvalCallCollector, br as setEvalFallbackCollector, bt as setPosCollector, bD as tryRunTranspiled, O as withEvalBudgetOverride } from './run-tV2J7PNI.js';
1
+ import { A as Abs, M as MayThrowEffect, b as Phi } from './run-DeKkteRZ.js';
2
+ export { V as $assignRecord, W as $call, X as $callNamed, bG as $nodoPos, Y as $recordBinding, a4 as EvalAbsAssignRecord, a5 as EvalCallRecord, a6 as EvalFallback, g as EvalFallbackStats, a7 as EvalPosRecord, aa as MAX_EVAL_CALL_DEPTH, ab as MAX_EVAL_TOTAL_CALLS, R as RunTranspiledOptions, ad as TranspiledCallResult, ar as bindingsOf, au as callTranspiledExport, av as callTranspiledExportApply, aw as callTranspiledExportFull, l as clearPureCallMemo, m as clearPureMemo, n as enterEvalCallBudgetSession, aB as evalExprAbs, p as exitEvalCallBudgetSession, v as getEvalCallBudgetState, aE as getEvalCallCollector, w as getEvalFallbackStats, bH as getPosCollector, aM as isAbsVal, aO as isCjsMainRun, b3 as noteEvalCallRecord, b4 as noteEvalFallback, bl as resetEvalCallBudget, H as resetEvalFallbackStats, bI as routeApplyThrows, bm as runTranspiled, bn as runTranspiledOptionsMemoKey, bo as setEvalAssignCollector, bp as setEvalBindingSink, bq as setEvalCallCollector, br as setEvalFallbackCollector, bt as setPosCollector, bD as tryRunTranspiled, O as withEvalBudgetOverride } from './run-DeKkteRZ.js';
3
3
  import { Node, Expression, File } from '@babel/types';
4
4
 
5
5
  /**
@@ -1106,6 +1106,20 @@ type TranspileOptions = {
1106
1106
  asyncForAwaitGates?: ReadonlySet<string>;
1107
1107
  /** 函数/箭头体内(顶层绑定表只收顶层作用域) */
1108
1108
  inFunction?: boolean;
1109
+ /**
1110
+ * 当前**函数体作用域**的形参名(含解构 / rest 模式名)。
1111
+ *
1112
+ * 用途:标识符赋值的结构检查插桩(`$assignRecord` 第 7 实参
1113
+ * `paramBinding`)——JS 形参没有声明类型,分析面看到的「旧值」是本次
1114
+ * 调用实参的形状而非绑定的声明的域 ⇒ 形参重赋值不参与
1115
+ * `nudo:assign-mismatch`(归一化形参 `x = [].concat(x)` 是常规写法,
1116
+ * 否则真实包假阳性)。
1117
+ *
1118
+ * 生命周期:函数/方法体边界由 `transpileFnBodyStmts` 按该体自身的形参
1119
+ * 重算(嵌套函数体不继承外层的表);模块顶层无此表。**表达式体箭头**
1120
+ * (`(x) => (x = 1)`)不经语句表 ⇒ 无表(该形态不插标)。
1121
+ */
1122
+ paramNames?: ReadonlySet<string>;
1109
1123
  /**
1110
1124
  * 当前词法作用域的 `arguments` 绑定名(非箭头函数 prologue 里 `$arguments(...)`)。
1111
1125
  * 箭头沿外层继承;无绑定(模块顶层 / 仅嵌套箭头引用)→ Identifier 分支折 $unknown()。
package/dist/exec.js CHANGED
@@ -208,7 +208,7 @@ import {
208
208
  withAssumePremises,
209
209
  withEvalBudgetOverride,
210
210
  withExecPhi
211
- } from "./chunk-ARIQO5XX.js";
211
+ } from "./chunk-CUFP2AYV.js";
212
212
  export {
213
213
  $absVal,
214
214
  $add,
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { d as AstEnv, A as Abs, C as Confidence, a as Pred, b as Phi, S as Shape, Q as RelSource, U as HofSite, c as AbsModuleExports, R as RunTranspiledOptions, L as LiteralValue } from './run-tV2J7PNI.js';
2
- export { V as $assignRecord, W as $call, X as $callNamed, Y as $recordBinding, Z as AbsApplyNoThrow, _ as AbsApplyNoThrowFn, a0 as AbsApplyResult, a1 as AbsApplyReturn, a2 as AbsFnImpl, a3 as AbsSigImpl, a4 as EvalAbsAssignRecord, a5 as EvalCallRecord, a6 as EvalFallback, a7 as EvalPosRecord, a8 as ImplicationOracle, a9 as LitValueResult, aa as MAX_EVAL_CALL_DEPTH, ab as MAX_EVAL_TOTAL_CALLS, P as PrimName, ac as TYPEOF_NAMES, T as Term, ad as TranspiledCallResult, ae as TypeofName, af as abs, ag as absFunction, ah as absOnly, ai as absToString, aj as and, ak as anyAbs, al as anyVar, am as app, an as assumeFinite, ao as attachFnImpl, ap as bigintLit, aq as bindImports, ar as bindingsOf, as as bool, at as boolLit, au as callTranspiledExport, av as callTranspiledExportApply, aw as callTranspiledExportFull, ax as collectAbsExports, ay as confJoin, az as emptyPhi, aA as eq, aB as evalExprAbs, aC as ge, aD as geNum, aE as getEvalCallCollector, aF as getFnImpl, aG as getImplicationOracle, aH as gt, aI as gtNum, aJ as hostFnCtorFacet, aK as implies, aL as isAbsApplyResult, aM as isAbsVal, aN as isBigPrim, aO as isCjsMainRun, aP as isExactLit, aQ as isNumPrim, aR as isStrPrim, aS as le, aT as leNum, aU as lit, aV as litValue, aW as lt, aX as ltNum, aY as makeAbsApplyResult, aZ as markPureFn, a_ as namespaceAbsOf, a$ as ne, b0 as negatePred, b1 as never, b2 as not, b3 as noteEvalCallRecord, b4 as noteEvalFallback, b5 as num, b6 as numLit, b7 as numVar, b8 as obj, b9 as or, ba as pFalse, bb as pTrue, bc as phiAnd, bd as predEquals, be as predToString, bf as predVars, bg as primToTypeof, bh as ptypeof, bi as pureFnNameOf, bj as relationFingerprint, bk as relationFn, bl as resetEvalCallBudget, bm as runTranspiled, bn as runTranspiledOptionsMemoKey, bo as setEvalAssignCollector, bp as setEvalBindingSink, bq as setEvalCallCollector, br as setEvalFallbackCollector, bs as setImplicationOracle, bt as setPosCollector, bu as shapeOfTerm, bv as shapeOnlyFn, bw as shapeToString, bx as simplifyTerm, by as str, bz as strLit, bA as substPred, bB as termEquals, bC as termToString, bD as tryRunTranspiled, bE as unknown, bF as v } from './run-tV2J7PNI.js';
1
+ import { d as AstEnv, A as Abs, C as Confidence, a as Pred, b as Phi, S as Shape, Q as RelSource, U as HofSite, c as AbsModuleExports, R as RunTranspiledOptions, L as LiteralValue } from './run-DeKkteRZ.js';
2
+ export { V as $assignRecord, W as $call, X as $callNamed, Y as $recordBinding, Z as AbsApplyNoThrow, _ as AbsApplyNoThrowFn, a0 as AbsApplyResult, a1 as AbsApplyReturn, a2 as AbsFnImpl, a3 as AbsSigImpl, a4 as EvalAbsAssignRecord, a5 as EvalCallRecord, a6 as EvalFallback, a7 as EvalPosRecord, a8 as ImplicationOracle, a9 as LitValueResult, aa as MAX_EVAL_CALL_DEPTH, ab as MAX_EVAL_TOTAL_CALLS, P as PrimName, ac as TYPEOF_NAMES, T as Term, ad as TranspiledCallResult, ae as TypeofName, af as abs, ag as absFunction, ah as absOnly, ai as absToString, aj as and, ak as anyAbs, al as anyVar, am as app, an as assumeFinite, ao as attachFnImpl, ap as bigintLit, aq as bindImports, ar as bindingsOf, as as bool, at as boolLit, au as callTranspiledExport, av as callTranspiledExportApply, aw as callTranspiledExportFull, ax as collectAbsExports, ay as confJoin, az as emptyPhi, aA as eq, aB as evalExprAbs, aC as ge, aD as geNum, aE as getEvalCallCollector, aF as getFnImpl, aG as getImplicationOracle, aH as gt, aI as gtNum, aJ as hostFnCtorFacet, aK as implies, aL as isAbsApplyResult, aM as isAbsVal, aN as isBigPrim, aO as isCjsMainRun, aP as isExactLit, aQ as isNumPrim, aR as isStrPrim, aS as le, aT as leNum, aU as lit, aV as litValue, aW as lt, aX as ltNum, aY as makeAbsApplyResult, aZ as markPureFn, a_ as namespaceAbsOf, a$ as ne, b0 as negatePred, b1 as never, b2 as not, b3 as noteEvalCallRecord, b4 as noteEvalFallback, b5 as num, b6 as numLit, b7 as numVar, b8 as obj, b9 as or, ba as pFalse, bb as pTrue, bc as phiAnd, bd as predEquals, be as predToString, bf as predVars, bg as primToTypeof, bh as ptypeof, bi as pureFnNameOf, bj as relationFingerprint, bk as relationFn, bl as resetEvalCallBudget, bm as runTranspiled, bn as runTranspiledOptionsMemoKey, bo as setEvalAssignCollector, bp as setEvalBindingSink, bq as setEvalCallCollector, br as setEvalFallbackCollector, bs as setImplicationOracle, bt as setPosCollector, bu as shapeOfTerm, bv as shapeOnlyFn, bw as shapeToString, bx as simplifyTerm, by as str, bz as strLit, bA as substPred, bB as termEquals, bC as termToString, bD as tryRunTranspiled, bE as unknown, bF as v } from './run-DeKkteRZ.js';
3
3
  import { Node, File } from '@babel/types';
4
- import { p as parseSource, L as LeakBudget, E as EffectiveInterfaceOpts, b as LoadDepsFingerprint, w as CheckReport, N as NudoConstraint, c as ProjectionBudget } from './projection-budget-BkFV9pcs.js';
5
- export { x as CONSTRAINT_BUILDERS, y as CONSTRAINT_BUILDER_NAMES, z as CONSTRAINT_EXPR_RE, A as CheckAction, C as CheckIssue, B as CheckJson, D as CheckJsonMulti, F as ConstraintBuilder, G as Diagnostic, H as EffectiveInterface, J as GitlabCodeQualityIssue, K as INTERFACE_SOURCE_ABBR, O as InterfaceDiag, I as InterfaceSource, Q as InterfaceTierInfo, a as InterfaceTierOpts, R as NamedImport, S as NudoField, T as NudoFnConstraint, U as NudoSidecarError, V as NudoSig, W as RefineDiag, X as RefineEntry, Y as RefineResolveOpts, Z as SELF, _ as actionsForIssue, $ as andC, a0 as any, a1 as array, a2 as boolean, a3 as checkArg, a4 as checkCall, a5 as constraintAdmitsNullish, a6 as constraintToEntryAbs, a7 as derefConstraint, a8 as drainPromiseMicros, a9 as effectiveInterface, aa as enterPromiseExecutorScope, ab as evalPromiseCtor, ac as evalPromiseMethod, ad as evalPromiseStatic, ae as execNudoModule, af as extractDeclaredThrows, ag as extractFnBudget, ah as extractNudoImports, ai as extractRefineReturnFromSource, aj as extractRefinesFromSource, ak as fn, al as fnConstraintToEntryReqs, am as formatCheckReport, an as formatConstraint, ao as formatDiagnostics, ap as formatEffectiveInterfaceDisplay, aq as formatGithubAnnotations, ar as formatGitlabCodeQuality, as as formatInterfaceTierLine, at as generatedExportNames, au as getParseSourceCacheSize, av as getTerm, aw as instantiateConstraint, ax as interfaceDiagCount, ay as interfaceSourceOf, az as interfaceTierOf, aA as isIntFlag, aB as isNodeModulesPath, aC as isNudoConstraint, aD as lazy, aE as leavePromiseExecutorScope, aF as lenTerm, aG as litC, aH as localNamedExports, aI as notePromiseExecutorFork, aJ as nullable, aK as number, aL as omit, aM as partial, aN as pick, aO as queuePromiseMicro, aP as refineDiagCount, aQ as refineToIndexedFull, aR as resetNudoModuleExecCache, aS as resetParseSourceCache, aT as resetSidecarLoadFailureCache, aU as serializeCheckJson, aV as serializeCheckJsonMulti, aW as setInterfaceDiagCollector, aX as setRefineDiagCollector, aY as shape, aZ as sidecarClosureFingerprint, a_ as sidecarPathOf, a$ as string, b0 as takeInterfaceDiags, b1 as takeInterfaceDiagsSince, b2 as takeRefineDiags, b3 as takeRefineDiagsSince, b4 as throwConstraintToKinds, b5 as union } from './projection-budget-BkFV9pcs.js';
4
+ import { p as parseSource, L as LeakBudget, E as EffectiveInterfaceOpts, b as LoadDepsFingerprint, w as CheckReport, N as NudoConstraint, c as ProjectionBudget } from './projection-budget-NCXMnUDn.js';
5
+ export { x as CONSTRAINT_BUILDERS, y as CONSTRAINT_BUILDER_NAMES, z as CONSTRAINT_EXPR_RE, A as CheckAction, C as CheckIssue, B as CheckJson, D as CheckJsonMulti, F as ConstraintBuilder, G as Diagnostic, H as EffectiveInterface, J as GitlabCodeQualityIssue, K as INTERFACE_SOURCE_ABBR, O as InterfaceDiag, I as InterfaceSource, Q as InterfaceTierInfo, a as InterfaceTierOpts, R as NamedImport, S as NudoField, T as NudoFnConstraint, U as NudoSidecarError, V as NudoSig, W as RefineDiag, X as RefineEntry, Y as RefineResolveOpts, Z as SELF, _ as actionsForIssue, $ as andC, a0 as any, a1 as array, a2 as boolean, a3 as checkArg, a4 as checkCall, a5 as constraintAdmitsNullish, a6 as constraintToEntryAbs, a7 as derefConstraint, a8 as drainPromiseMicros, a9 as effectiveInterface, aa as enterPromiseExecutorScope, ab as evalPromiseCtor, ac as evalPromiseMethod, ad as evalPromiseStatic, ae as execNudoModule, af as extractDeclaredThrows, ag as extractFnBudget, ah as extractNudoImports, ai as extractRefineReturnFromSource, aj as extractRefinesFromSource, ak as fn, al as fnConstraintToEntryReqs, am as formatCheckReport, an as formatConstraint, ao as formatDiagnostics, ap as formatEffectiveInterfaceDisplay, aq as formatGithubAnnotations, ar as formatGitlabCodeQuality, as as formatInterfaceTierLine, at as generatedExportNames, au as getParseSourceCacheSize, av as getTerm, aw as instantiateConstraint, ax as interfaceDiagCount, ay as interfaceSourceOf, az as interfaceTierOf, aA as isIntFlag, aB as isNodeModulesPath, aC as isNudoConstraint, aD as lazy, aE as leavePromiseExecutorScope, aF as lenTerm, aG as litC, aH as localNamedExports, aI as notePromiseExecutorFork, aJ as nullable, aK as number, aL as omit, aM as partial, aN as pick, aO as queuePromiseMicro, aP as refineDiagCount, aQ as refineToIndexedFull, aR as resetNudoModuleExecCache, aS as resetParseSourceCache, aT as resetSidecarLoadFailureCache, aU as serializeCheckJson, aV as serializeCheckJsonMulti, aW as setInterfaceDiagCollector, aX as setRefineDiagCollector, aY as shape, aZ as sidecarClosureFingerprint, a_ as sidecarPathOf, a$ as string, b0 as takeInterfaceDiags, b1 as takeInterfaceDiagsSince, b2 as takeRefineDiags, b3 as takeRefineDiagsSince, b4 as throwConstraintToKinds, b5 as union } from './projection-budget-NCXMnUDn.js';
6
6
  export { $add, $arguments, $arr, $arrMutContainer, $arrRest, $arrWithHoles, $async, $await, $bitand, $bitnot, $bitor, $bitxor, $catchVal, $class, $classExpr, $collectionForEach, $concat, $copy, $del, $delRes, $div, $dynamicImport, $elems, $eq, $eqLoose, $fnVal, $for, $forInKeys, $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, $sub, $super, $switch, $throw, $toNumber, $toNumeric, $tryCurrentMark, $tryDetachSoftCatch, $tryDigestSoftCatch, $tryDiscardSoft, $tryMark, $tryOrphanSoft, $tryPopMark, $tryReleaseSoftCatch, $tryReleaseSoftOut, $tryTakeSince, $typeof, $unknown, $updateAdd, $updateSub, $ushr, $whileSeq, $yield, DEFAULT_MAX_LOOP_ITERS, EvalClassSpec, NudoLoopSignal, NudoReturn, NudoThrow, NudoUnsupportedError, RUNTIME_IMPORT_RE, 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
  /**
@@ -1139,6 +1139,18 @@ type AbsAssignRecord = {
1139
1139
  column?: number;
1140
1140
  /** 分支/循环体内发生:可变绑定在路径上取并集是合法 JS,不参与结构检查 */
1141
1141
  conditional?: boolean;
1142
+ /**
1143
+ * 写目标是**函数形参**(不是 let/const/var 声明绑定)。
1144
+ *
1145
+ * JS 形参没有声明类型——分析面看到的 `prev` 是**本次调用实参**的形状,
1146
+ * 不是绑定的声明的域。真实代码里「归一化形参」是常规写法:
1147
+ * `global(globals) { globals = [].concat(globals); … }`(yargs)在某个
1148
+ * 调用点上传入 `"_"` 时,`prev = "_"`、`next = ["_"]` ⇒ 结构检查判
1149
+ * 「arr ⊭ prim string」**假阳性**(形参的真实域是 `string | string[]`)。
1150
+ * ⇒ 形参重赋值不参与 `nudo:assign-mismatch`(该通道只对**有声明值的绑定**
1151
+ * 负义务;调用点实参的形状义务归契约 / `nudo:arg-structure` 通道)。
1152
+ */
1153
+ paramBinding?: boolean;
1142
1154
  };
1143
1155
 
1144
1156
  /**
package/dist/index.js CHANGED
@@ -91,7 +91,7 @@ import {
91
91
  takeInterfaceDiagsSince,
92
92
  takeRefineDiags,
93
93
  takeRefineDiagsSince
94
- } from "./chunk-4MRLOJMI.js";
94
+ } from "./chunk-G27PMV2U.js";
95
95
  import {
96
96
  $add,
97
97
  $arguments,
@@ -549,7 +549,7 @@ import {
549
549
  withExecPhi,
550
550
  withInvariantSpecs,
551
551
  withVar
552
- } from "./chunk-ARIQO5XX.js";
552
+ } from "./chunk-CUFP2AYV.js";
553
553
 
554
554
  // src/environment.ts
555
555
  function createEnvironment(parent, bindings = /* @__PURE__ */ new Map()) {
@@ -2210,6 +2210,7 @@ function structuralAssignIssues(records) {
2210
2210
  if (!r.prev) continue;
2211
2211
  if (!isAbsLike(r.prev) || !isAbsLike(r.next)) continue;
2212
2212
  if (r.conditional) continue;
2213
+ if (r.paramBinding === true) continue;
2213
2214
  if (r.next.shape.k === "unknown" && !r.next.term) continue;
2214
2215
  if (r.prev.shape.k === "unknown" && !r.prev.term) continue;
2215
2216
  const leq = leqAbs(widenForAssign(r.next), shapeOnly(widenForAssign(r.prev)));
@@ -1,7 +1,7 @@
1
- import { I as InterfaceSource, a as InterfaceTierOpts, p as parseSource, C as CheckIssue } from './projection-budget-BkFV9pcs.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 budgetAttributionSegs, f as defaultLeakBudget, g as exceedsBudget, h as exportedNameOfLocal, i as extractAllLoadSpecs, j as getPromiseMicrosLength, l as leakIfNeeded, k as loadModuleDepsFingerprint, m as maybeLeak, n as normPath, r as resetLeakCounter, o as resolveDepPath, s as sidecarSpecsOf, q as stablePathKey, t as stablePathKeyGraph, u as termDepth, v as termNodes } from './projection-budget-BkFV9pcs.js';
3
- import { A as Abs, T as Term, c as AbsModuleExports, R as RunTranspiledOptions, d as AstEnv } from './run-tV2J7PNI.js';
4
- export { $ as $tryDigestSoft, e as $tryMarkSoft, f as $tryReleaseSoft, E as ERROR_FAMILY, g as EvalFallbackStats, M as MayThrowEffect, h as absLit, i as absNumLit, j as absStrLit, k as allAbsStr, l as clearPureCallMemo, m as clearPureMemo, n as enterEvalCallBudgetSession, o as errorTypeAbs, p as exitEvalCallBudgetSession, q as filterDeclaredThrows, r as filterGateThrows, s as filterIgnoredThrows, t as flushMayThrowEffects, u as formatThrowsAbs, v as getEvalCallBudgetState, w as getEvalFallbackStats, x as getMayThrowCollector, y as isThrowsIgnored, z as mayThrowEffectsToAbs, B as orphanMayThrowEffects, D as popMayThrowFrame, F as pushMayThrowFrame, G as recordMayThrow, H as resetEvalFallbackStats, I as runWithMayThrowSession, J as setMayThrowCollector, K as throwAbsToKinds, N as throwsKindCovered, O as withEvalBudgetOverride } from './run-tV2J7PNI.js';
1
+ import { I as InterfaceSource, a as InterfaceTierOpts, p as parseSource, C as CheckIssue } from './projection-budget-NCXMnUDn.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 budgetAttributionSegs, f as defaultLeakBudget, g as exceedsBudget, h as exportedNameOfLocal, i as extractAllLoadSpecs, j as getPromiseMicrosLength, l as leakIfNeeded, k as loadModuleDepsFingerprint, m as maybeLeak, n as normPath, r as resetLeakCounter, o as resolveDepPath, s as sidecarSpecsOf, q as stablePathKey, t as stablePathKeyGraph, u as termDepth, v as termNodes } from './projection-budget-NCXMnUDn.js';
3
+ import { A as Abs, T as Term, c as AbsModuleExports, R as RunTranspiledOptions, d as AstEnv } from './run-DeKkteRZ.js';
4
+ export { $ as $tryDigestSoft, e as $tryMarkSoft, f as $tryReleaseSoft, E as ERROR_FAMILY, g as EvalFallbackStats, M as MayThrowEffect, h as absLit, i as absNumLit, j as absStrLit, k as allAbsStr, l as clearPureCallMemo, m as clearPureMemo, n as enterEvalCallBudgetSession, o as errorTypeAbs, p as exitEvalCallBudgetSession, q as filterDeclaredThrows, r as filterGateThrows, s as filterIgnoredThrows, t as flushMayThrowEffects, u as formatThrowsAbs, v as getEvalCallBudgetState, w as getEvalFallbackStats, x as getMayThrowCollector, y as isThrowsIgnored, z as mayThrowEffectsToAbs, B as orphanMayThrowEffects, D as popMayThrowFrame, F as pushMayThrowFrame, G as recordMayThrow, H as resetEvalFallbackStats, I as runWithMayThrowSession, J as setMayThrowCollector, K as throwAbsToKinds, N as throwsKindCovered, O as withEvalBudgetOverride } from './run-DeKkteRZ.js';
5
5
  import { File, Node } from '@babel/types';
6
6
 
7
7
  /**
package/dist/internal.js CHANGED
@@ -30,7 +30,7 @@ import {
30
30
  stablePathKey,
31
31
  stablePathKeyGraph,
32
32
  toJsBindingIdent
33
- } from "./chunk-4MRLOJMI.js";
33
+ } from "./chunk-G27PMV2U.js";
34
34
  import {
35
35
  $tryDigestSoft,
36
36
  $tryMarkSoft,
@@ -172,7 +172,7 @@ import {
172
172
  withEvalBudgetOverride,
173
173
  withFnBudgetOverride,
174
174
  wrapPromise
175
- } from "./chunk-ARIQO5XX.js";
175
+ } from "./chunk-CUFP2AYV.js";
176
176
 
177
177
  // src/algebra/inlay.ts
178
178
  function listFunctions(source) {
@@ -1,5 +1,5 @@
1
1
  import { File } from '@babel/types';
2
- import { A as Abs, T as Term, P as PrimName, a as Pred, L as LiteralValue, C as Confidence, b as Phi } from './run-tV2J7PNI.js';
2
+ import { A as Abs, T as Term, P as PrimName, a as Pred, L as LiteralValue, C as Confidence, b as Phi } from './run-DeKkteRZ.js';
3
3
 
4
4
  declare function resetParseSourceCache(): void;
5
5
  declare function getParseSourceCacheSize(): number;
@@ -461,6 +461,9 @@ declare function extractFnBudget(source: string, fnName: string): {
461
461
  * - CJS(C4.3):`module.exports = { a, b }`、`module.exports.a = …`、
462
462
  * `exports.a = …`、`module.exports = localFn`(登记 localFn 名)。
463
463
  * 排除 re-export(`export {x} from` / `export *`)。
464
+ *
465
+ * 结果按源码文本 memo(见 `memoizedLocalExports`)——本函数在逐候选循环里
466
+ * 被反复调用,没有 memo 时每次都是整文件 reparse + strip。
464
467
  */
465
468
  declare function localNamedExports(source: string): Set<string>;
466
469
  /**
@@ -431,13 +431,17 @@ type EvalAbsAssignRecord = {
431
431
  line?: number;
432
432
  column?: number;
433
433
  conditional?: boolean;
434
+ /** 写目标是函数形参(AbsAssignRecord.paramBinding) */
435
+ paramBinding?: boolean;
434
436
  /** 调用方帧深度(0 = 最外层求值帧;与 EvalCallRecord.depth 同口径) */
435
437
  depth?: number;
436
438
  };
437
439
  /** 返回先前 collector,便于嵌套调用 save/restore(禁止 finally 置 null 砸外层) */
438
440
  declare function setEvalAssignCollector(collector: ((r: EvalAbsAssignRecord) => void) | null): ((r: EvalAbsAssignRecord) => void) | null;
439
441
  /** 结构赋值记录(transpile 插桩调用;无收集器时 no-op) */
440
- declare function $assignRecord(name: string, prev: Abs | undefined, next: Abs, line: number, column: number, conditional: boolean): void;
442
+ declare function $assignRecord(name: string, prev: Abs | undefined, next: Abs, line: number, column: number, conditional: boolean,
443
+ /** 写目标是函数形参(可选;缺省 false ⇒ 产物逐字不变) */
444
+ paramBinding?: boolean): void;
441
445
  /** 位置级 Abs 记录(hover 重放插桩 `$nodoPos` 消费):
442
446
  * (1-based 行, 0-based 列) → 该位置表达式求值态 Abs */
443
447
  type EvalPosRecord = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nudojs/core",
3
- "version": "1.17.0",
3
+ "version": "1.17.1",
4
4
  "engines": {
5
5
  "node": ">=22"
6
6
  },