@nudojs/core 1.8.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7141,6 +7141,64 @@ function narrowTypeArmThunk(thunk, guard, arm, forkBindingNames) {
7141
7141
  const keep = arm === guard.arm;
7142
7142
  return `((${guard.name}) => ${thunk})($narrowTypeOf(${guard.name}, ${JSON.stringify(guard.typeOf)}, ${keep}))`;
7143
7143
  }
7144
+ var isPrimLitNode = (n) => {
7145
+ const t = n;
7146
+ if (t?.type === "StringLiteral") return typeof t.value === "string";
7147
+ if (t?.type === "NumericLiteral") return typeof t.value === "number";
7148
+ if (t?.type === "BooleanLiteral") return typeof t.value === "boolean";
7149
+ return false;
7150
+ };
7151
+ function discriminantGuardOf(test) {
7152
+ const t = test;
7153
+ if (t?.type !== "BinaryExpression") return void 0;
7154
+ if (t.operator !== "===" && t.operator !== "!==") return void 0;
7155
+ const lm = memberGuardTarget(t.left);
7156
+ const rm = memberGuardTarget(t.right);
7157
+ const m = lm !== void 0 && isPrimLitNode(t.right) ? { target: lm, lit: t.right } : rm !== void 0 && isPrimLitNode(t.left) ? { target: rm, lit: t.left } : void 0;
7158
+ if (!m) return void 0;
7159
+ return {
7160
+ name: m.target.name,
7161
+ key: m.target.key,
7162
+ value: m.lit.value,
7163
+ arm: t.operator === "===" ? "cons" : "alt"
7164
+ };
7165
+ }
7166
+ function discriminantGuardsOf(test) {
7167
+ const t = test;
7168
+ if (t?.type === "LogicalExpression" && (t.operator === "&&" || t.operator === "||")) {
7169
+ const wantArm = t.operator === "&&" ? "cons" : "alt";
7170
+ const out = [];
7171
+ for (const g2 of [...discriminantGuardsOf(t.left), ...discriminantGuardsOf(t.right)]) {
7172
+ if (g2.arm !== wantArm) continue;
7173
+ if (out.some((x) => x.name === g2.name && x.key === g2.key && x.value === g2.value)) continue;
7174
+ out.push(g2);
7175
+ }
7176
+ return out;
7177
+ }
7178
+ const g = discriminantGuardOf(test);
7179
+ return g ? [g] : [];
7180
+ }
7181
+ function narrowDiscriminantArmThunks(thunk, guards, arm, forkBindingNames) {
7182
+ if (!guards || guards.length === 0) return thunk;
7183
+ const matching = guards.filter((g) => g.arm === arm);
7184
+ if (matching.length === 0) return thunk;
7185
+ const names = forkBindingNames instanceof Set ? forkBindingNames : new Set(forkBindingNames);
7186
+ if (matching.some((g) => names.has(g.name))) return thunk;
7187
+ const byName = /* @__PURE__ */ new Map();
7188
+ for (const g of matching) {
7189
+ const list = byName.get(g.name) ?? [];
7190
+ if (!list.some((x) => x.key === g.key && x.value === g.value)) list.push(g);
7191
+ byName.set(g.name, list);
7192
+ }
7193
+ const params = [...byName.keys()].join(", ");
7194
+ const args = [...byName.entries()].map(
7195
+ ([name, gs]) => gs.reduce(
7196
+ (acc, g) => `$narrowMemberEq(${acc}, ${JSON.stringify(g.key)}, ${JSON.stringify(g.value)}, true)`,
7197
+ name
7198
+ )
7199
+ ).join(", ");
7200
+ return `((${params}) => ${thunk})(${args})`;
7201
+ }
7144
7202
 
7145
7203
  // src/algebra/exec/transpile/stmt.ts
7146
7204
  var switchBodySeq = 0;
@@ -7237,14 +7295,20 @@ function transpileFnBodyStmts(stmtsIn, depth, opts, varScope) {
7237
7295
  const testRebinds = testRecvs.size ? emitArrMutatorRebinds(stmt.test, scopedOpts, pad) : [];
7238
7296
  const earlyGuards = nullishGuardsOf(stmt.test);
7239
7297
  const earlyTGuard = typeGuardOf(stmt.test);
7240
- const consNarrowed = narrowTypeArmThunk(
7241
- narrowNullishArmThunks(
7242
- transpileBlockAsThunk(stmt.consequent, depth, scopedOpts),
7243
- earlyGuards,
7298
+ const earlyDGuards = discriminantGuardsOf(stmt.test);
7299
+ const consNarrowed = narrowDiscriminantArmThunks(
7300
+ narrowTypeArmThunk(
7301
+ narrowNullishArmThunks(
7302
+ transpileBlockAsThunk(stmt.consequent, depth, scopedOpts),
7303
+ earlyGuards,
7304
+ "cons",
7305
+ recvSet
7306
+ ),
7307
+ earlyTGuard,
7244
7308
  "cons",
7245
7309
  recvSet
7246
7310
  ),
7247
- earlyTGuard,
7311
+ earlyDGuards,
7248
7312
  "cons",
7249
7313
  recvSet
7250
7314
  );
@@ -7253,9 +7317,14 @@ function transpileFnBodyStmts(stmtsIn, depth, opts, varScope) {
7253
7317
  const altThunk = `() => {
7254
7318
  ${altBody}
7255
7319
  ${pad}}`;
7256
- const altNarrowed = narrowTypeArmThunk(
7257
- narrowNullishArmThunks(altThunk, earlyGuards, "alt", recvSet),
7258
- earlyTGuard,
7320
+ const altNarrowed = narrowDiscriminantArmThunks(
7321
+ narrowTypeArmThunk(
7322
+ narrowNullishArmThunks(altThunk, earlyGuards, "alt", recvSet),
7323
+ earlyTGuard,
7324
+ "alt",
7325
+ recvSet
7326
+ ),
7327
+ earlyDGuards,
7259
7328
  "alt",
7260
7329
  recvSet
7261
7330
  );
@@ -7586,15 +7655,26 @@ ${pad}export default ${name};`;
7586
7655
  }) : null;
7587
7656
  const guards = nullishGuardsOf(stmt.test);
7588
7657
  const tguard = typeGuardOf(stmt.test);
7589
- const consNarrowed = narrowTypeArmThunk(
7590
- narrowNullishArmThunks(consRaw, guards, "cons", recvSet),
7591
- tguard,
7658
+ const dguards = discriminantGuardsOf(stmt.test);
7659
+ const consNarrowed = narrowDiscriminantArmThunks(
7660
+ narrowTypeArmThunk(
7661
+ narrowNullishArmThunks(consRaw, guards, "cons", recvSet),
7662
+ tguard,
7663
+ "cons",
7664
+ recvSet
7665
+ ),
7666
+ dguards,
7592
7667
  "cons",
7593
7668
  recvSet
7594
7669
  );
7595
- const altNarrowed = altRaw === null ? null : narrowTypeArmThunk(
7596
- narrowNullishArmThunks(altRaw, guards, "alt", recvSet),
7597
- tguard,
7670
+ const altNarrowed = altRaw === null ? null : narrowDiscriminantArmThunks(
7671
+ narrowTypeArmThunk(
7672
+ narrowNullishArmThunks(altRaw, guards, "alt", recvSet),
7673
+ tguard,
7674
+ "alt",
7675
+ recvSet
7676
+ ),
7677
+ dguards,
7598
7678
  "alt",
7599
7679
  recvSet
7600
7680
  );
@@ -8528,14 +8608,27 @@ function transpileShortCircuitExpr(opts, parts) {
8528
8608
  consExpr = apply(consExpr, "cons");
8529
8609
  altExpr = apply(altExpr, "alt");
8530
8610
  }
8611
+ const applyDisc = (src, arm) => narrowDiscriminantArmThunks(src, parts.discGuards, arm, []);
8612
+ consExpr = applyDisc(consExpr, "cons");
8613
+ altExpr = applyDisc(altExpr, "alt");
8531
8614
  return `$fork(${forkTest2}, () => ${consExpr}, () => ${altExpr})`;
8532
8615
  }
8533
8616
  const consLines = parts.consSrc === "__test" ? [`return __test;`] : consRebinds.length === 0 ? [`return (${parts.consSrc});`] : [`const __v = (${parts.consSrc});`, ...consRebinds, `return __v;`];
8534
8617
  const altLines = parts.altSrc === "__test" ? [`return __test;`] : altRebinds.length === 0 ? [`return (${parts.altSrc});`] : [`const __v = (${parts.altSrc});`, ...altRebinds, `return __v;`];
8535
8618
  const forkTest = parts.testSrc ?? "__test";
8536
8619
  const guards = parts.narrowGuards;
8537
- const consFinal = narrowNullishArmThunks(forkArmThunk(consLines, "fk1_", names), guards, "cons", names);
8538
- const altFinal = narrowNullishArmThunks(forkArmThunk(altLines, "fk2_", names), guards, "alt", names);
8620
+ const consFinal = narrowDiscriminantArmThunks(
8621
+ narrowNullishArmThunks(forkArmThunk(consLines, "fk1_", names), guards, "cons", names),
8622
+ parts.discGuards,
8623
+ "cons",
8624
+ names
8625
+ );
8626
+ const altFinal = narrowDiscriminantArmThunks(
8627
+ narrowNullishArmThunks(forkArmThunk(altLines, "fk2_", names), guards, "alt", names),
8628
+ parts.discGuards,
8629
+ "alt",
8630
+ names
8631
+ );
8539
8632
  return [
8540
8633
  `(() => {`,
8541
8634
  ` const __test = (${parts.alwaysSrc});`,
@@ -8759,6 +8852,7 @@ ${inner}
8759
8852
  }
8760
8853
  const leftGuards = nullishGuardsOf(expr.left);
8761
8854
  const andTypeGuard = typeGuardOf(expr.left);
8855
+ const leftDiscGuards = discriminantGuardsOf(expr.left);
8762
8856
  return op === "&&" ? transpileShortCircuitExpr(opts, {
8763
8857
  alwaysNodes: [lNode],
8764
8858
  alwaysSrc: l,
@@ -8767,7 +8861,8 @@ ${inner}
8767
8861
  altSrc: "__test",
8768
8862
  altNodes: [],
8769
8863
  narrowGuards: leftGuards.filter((g) => g.arm === "cons"),
8770
- typeGuard: andTypeGuard
8864
+ typeGuard: andTypeGuard,
8865
+ discGuards: leftDiscGuards.filter((g) => g.arm === "cons")
8771
8866
  }) : transpileShortCircuitExpr(opts, {
8772
8867
  alwaysNodes: [lNode],
8773
8868
  alwaysSrc: l,
@@ -8776,7 +8871,8 @@ ${inner}
8776
8871
  altSrc: r,
8777
8872
  altNodes: [rNode],
8778
8873
  narrowGuards: leftGuards.filter((g) => g.arm === "alt"),
8779
- typeGuard: andTypeGuard
8874
+ typeGuard: andTypeGuard,
8875
+ discGuards: leftDiscGuards.filter((g) => g.arm === "alt")
8780
8876
  });
8781
8877
  }
8782
8878
  case "ConditionalExpression": {
@@ -8795,9 +8891,11 @@ ${inner}
8795
8891
  altNodes: [altNode],
8796
8892
  // 三元的 nullish/typeof 守卫臂收窄(issue #97:`p === null ? -1 : p.major`;
8797
8893
  // Bug 23:`typeof v === "string" ? v + "!" : 0`;#118 v3/#120:多名复合
8798
- // `obj == null || node.p == null ? … : node.p.name` 一臂多事实)
8894
+ // `obj == null || node.p == null ? … : node.p.name` 一臂多事实);
8895
+ // 判别等值守卫(issue #126):`node.type === 'TL' ? node.quasis[0] : null`
8799
8896
  narrowGuards: nullishGuardsOf(expr.test),
8800
- typeGuard: typeGuardOf(expr.test)
8897
+ typeGuard: typeGuardOf(expr.test),
8898
+ discGuards: discriminantGuardsOf(expr.test)
8801
8899
  });
8802
8900
  }
8803
8901
  case "RegExpLiteral": {
@@ -9540,7 +9638,7 @@ function transpileSource(source, opts = {}) {
9540
9638
  return transpileFile(file, { ...opts, source: opts.source ?? source });
9541
9639
  }
9542
9640
  function runtimeImportOf(runtime) {
9543
- return `import { $absVal, $add, $sub, $mul, $div, $mod, $bitand, $bitor, $bitxor, $bitnot, $shl, $shr, $ushr, $pow, $toNumber, $toNumeric, $updateAdd, $updateSub, $in, $instanceof, $instanceofNonIdent, $classExpr, $del, $delRes, $objAccessor, $objAccessorKey, $neg, $typeof, $not, $eq, $ne, $eqLoose, $neLoose, $lt, $le, $gt, $ge, $join, $lit, $fork, $for, $forIter, $obj, $get, $set, $setProto, $while, $whileSeq, $arr, $arrWithHoles, $arrMutContainer, $idx, $idxSet, $len, $call, $throw, $loopReturn, $loopBreak, $loopContinue, $class, $new, $invoke, $invokeSuper, $invokeSuperObj, $invokeSuperKey, $getSuper, $getSuperObj, $super, $async, $copy, $await, $asyncReturn, $orDefault, $callNamed, $optionalGet, $optionalInvoke, $spread, $concat, $forOf, $forInKeys, $iterCheck, $catchVal, $switch, $staticInvoke, $setKey, $gen, $newTarget, $staticInit, $yield, $fnVal, $regex, $reStateCall, $rethrowIfNudoReturn, $nullishTest, $removeNullish, $removeNull, $removeUndefined, $removeMemberNullish, $narrowTypeOf, $tryMark, $assignRecord, $recordBinding, $unknown, $importMeta, $dynamicImport, $tryTakeSince, $tryCurrentMark, $tryPopMark, $tryDigestSoftCatch, $tryReleaseSoftOut, $tryDetachSoftCatch, $tryDiscardSoft, $tryOrphanSoft, $pushLoopExit, $objRest, $arrRest, $elems, $arguments, $isForkExit, $rawThis, $isBreakTo, $yieldStar, $tpl } from ${JSON.stringify(runtime)};`;
9641
+ return `import { $absVal, $add, $sub, $mul, $div, $mod, $bitand, $bitor, $bitxor, $bitnot, $shl, $shr, $ushr, $pow, $toNumber, $toNumeric, $updateAdd, $updateSub, $in, $instanceof, $instanceofNonIdent, $classExpr, $del, $delRes, $objAccessor, $objAccessorKey, $neg, $typeof, $not, $eq, $ne, $eqLoose, $neLoose, $lt, $le, $gt, $ge, $join, $lit, $fork, $for, $forIter, $obj, $get, $set, $setProto, $while, $whileSeq, $arr, $arrWithHoles, $arrMutContainer, $idx, $idxSet, $len, $call, $throw, $loopReturn, $loopBreak, $loopContinue, $class, $new, $invoke, $invokeSuper, $invokeSuperObj, $invokeSuperKey, $getSuper, $getSuperObj, $super, $async, $copy, $await, $asyncReturn, $orDefault, $callNamed, $optionalGet, $optionalInvoke, $spread, $concat, $forOf, $forInKeys, $iterCheck, $catchVal, $switch, $staticInvoke, $setKey, $gen, $newTarget, $staticInit, $yield, $fnVal, $regex, $reStateCall, $rethrowIfNudoReturn, $nullishTest, $removeNullish, $removeNull, $removeUndefined, $removeMemberNullish, $narrowMemberEq, $narrowTypeOf, $tryMark, $assignRecord, $recordBinding, $unknown, $importMeta, $dynamicImport, $tryTakeSince, $tryCurrentMark, $tryPopMark, $tryDigestSoftCatch, $tryReleaseSoftOut, $tryDetachSoftCatch, $tryDiscardSoft, $tryOrphanSoft, $pushLoopExit, $objRest, $arrRest, $elems, $arguments, $isForkExit, $rawThis, $isBreakTo, $yieldStar, $tpl } from ${JSON.stringify(runtime)};`;
9544
9642
  }
9545
9643
  function transpileFile(file, opts = {}) {
9546
9644
  const runtime = opts.runtimeImport ?? "@nudojs/core/exec";
@@ -9561,7 +9659,7 @@ function transpileFile(file, opts = {}) {
9561
9659
  };
9562
9660
  const lines = [
9563
9661
  `// nudo evaluator transpile \u2014 values are Abs; operators are overloaded calls`,
9564
- `import { $absVal, $add, $sub, $mul, $div, $mod, $bitand, $bitor, $bitxor, $bitnot, $shl, $shr, $ushr, $pow, $toNumber, $toNumeric, $updateAdd, $updateSub, $in, $instanceof, $instanceofNonIdent, $classExpr, $del, $delRes, $objAccessor, $objAccessorKey, $neg, $typeof, $not, $eq, $ne, $eqLoose, $neLoose, $lt, $le, $gt, $ge, $join, $lit, $fork, $for, $forIter, $obj, $get, $set, $setProto, $while, $whileSeq, $arr, $arrWithHoles, $arrMutContainer, $idx, $idxSet, $len, $call, $throw, $loopReturn, $loopBreak, $loopContinue, $class, $new, $invoke, $invokeSuper, $invokeSuperObj, $invokeSuperKey, $getSuper, $getSuperObj, $super, $async, $copy, $await, $asyncReturn, $orDefault, $callNamed, $optionalGet, $optionalInvoke, $spread, $concat, $forOf, $forInKeys, $iterCheck, $catchVal, $switch, $staticInvoke, $setKey, $gen, $newTarget, $staticInit, $yield, $fnVal, $regex, $reStateCall, $rethrowIfNudoReturn, $nullishTest, $removeNullish, $removeNull, $removeUndefined, $removeMemberNullish, $narrowTypeOf, $tryMark, $assignRecord, $recordBinding, $unknown, $importMeta, $dynamicImport, $tryTakeSince, $tryCurrentMark, $tryPopMark, $tryDigestSoftCatch, $tryReleaseSoftOut, $tryDetachSoftCatch, $tryDiscardSoft, $tryOrphanSoft, $pushLoopExit, $objRest, $arrRest, $elems, $arguments, $isForkExit, $rawThis, $isBreakTo, $yieldStar, $tpl } from ${JSON.stringify(runtime)};`,
9662
+ `import { $absVal, $add, $sub, $mul, $div, $mod, $bitand, $bitor, $bitxor, $bitnot, $shl, $shr, $ushr, $pow, $toNumber, $toNumeric, $updateAdd, $updateSub, $in, $instanceof, $instanceofNonIdent, $classExpr, $del, $delRes, $objAccessor, $objAccessorKey, $neg, $typeof, $not, $eq, $ne, $eqLoose, $neLoose, $lt, $le, $gt, $ge, $join, $lit, $fork, $for, $forIter, $obj, $get, $set, $setProto, $while, $whileSeq, $arr, $arrWithHoles, $arrMutContainer, $idx, $idxSet, $len, $call, $throw, $loopReturn, $loopBreak, $loopContinue, $class, $new, $invoke, $invokeSuper, $invokeSuperObj, $invokeSuperKey, $getSuper, $getSuperObj, $super, $async, $copy, $await, $asyncReturn, $orDefault, $callNamed, $optionalGet, $optionalInvoke, $spread, $concat, $forOf, $forInKeys, $iterCheck, $catchVal, $switch, $staticInvoke, $setKey, $gen, $newTarget, $staticInit, $yield, $fnVal, $regex, $reStateCall, $rethrowIfNudoReturn, $nullishTest, $removeNullish, $removeNull, $removeUndefined, $removeMemberNullish, $narrowMemberEq, $narrowTypeOf, $tryMark, $assignRecord, $recordBinding, $unknown, $importMeta, $dynamicImport, $tryTakeSince, $tryCurrentMark, $tryPopMark, $tryDigestSoftCatch, $tryReleaseSoftOut, $tryDetachSoftCatch, $tryDiscardSoft, $tryOrphanSoft, $pushLoopExit, $objRest, $arrRest, $elems, $arguments, $isForkExit, $rawThis, $isBreakTo, $yieldStar, $tpl } from ${JSON.stringify(runtime)};`,
9565
9663
  ``
9566
9664
  ];
9567
9665
  if (varHoistLine) lines.push(varHoistLine);
@@ -9642,6 +9740,7 @@ __export(runtime_exports, {
9642
9740
  $lt: () => $lt,
9643
9741
  $mod: () => $mod,
9644
9742
  $mul: () => $mul,
9743
+ $narrowMemberEq: () => $narrowMemberEq,
9645
9744
  $narrowTypeOf: () => $narrowTypeOf,
9646
9745
  $ne: () => $ne,
9647
9746
  $neLoose: () => $neLoose,
@@ -13455,6 +13554,58 @@ function $narrowTypeOf(a, typeOf, keep) {
13455
13554
  if (kept.length === 0) return a;
13456
13555
  return kept.length === 1 ? kept[0] : { ...a, shape: { k: "sum", members: kept } };
13457
13556
  }
13557
+ function litRefutesEq(other, v2) {
13558
+ return other !== v2;
13559
+ }
13560
+ function memberEqClass(m, key, litAbs, value) {
13561
+ const sh = m.shape;
13562
+ if (sh.k === "obj") {
13563
+ const slots = sh.slots;
13564
+ if (!Object.prototype.hasOwnProperty.call(slots, key)) {
13565
+ return sh.open ? "may" : "never";
13566
+ }
13567
+ const slotValue = slots[key].value;
13568
+ if (slotValue.shape.k === "any" || slotValue.shape.k === "unknown") return "may";
13569
+ const shapeOnly = (s) => abs(s, void 0, void 0, "exact");
13570
+ if (!leqAbs(shapeOnly(litAbs.shape), shapeOnly(slotValue.shape)).ok) return "never";
13571
+ const t = slotValue.term;
13572
+ const p = slotValue.pred;
13573
+ if (!t || !p || p.op === "true") return "may";
13574
+ const litTerm = lit(value);
13575
+ if (implies(p, { op: "eq", a: t, b: litTerm })) return "only";
13576
+ if (implies(p, { op: "ne", a: t, b: litTerm })) return "never";
13577
+ const conjuncts = [];
13578
+ const visit = (c) => {
13579
+ if (c.op === "and") {
13580
+ c.args.forEach(visit);
13581
+ return;
13582
+ }
13583
+ conjuncts.push(c);
13584
+ };
13585
+ visit(p);
13586
+ for (const c of conjuncts) {
13587
+ if (c.op !== "eq") continue;
13588
+ const other = termEquals(c.a, t) && c.b.op === "lit" ? c.b.value : termEquals(c.b, t) && c.a.op === "lit" ? c.a.value : void 0;
13589
+ if (other !== void 0 && litRefutesEq(other, value)) return "never";
13590
+ }
13591
+ return "may";
13592
+ }
13593
+ if (m.term?.op === "lit") return "never";
13594
+ return "may";
13595
+ }
13596
+ function $narrowMemberEq(a, key, value, keep) {
13597
+ if (!a || typeof a !== "object" || !("shape" in a)) return a;
13598
+ if (a.shape.k !== "sum") return a;
13599
+ const litAbs = typeof value === "string" ? strLit(value) : typeof value === "number" ? numLit(value) : boolLit(value);
13600
+ const members = a.shape.members;
13601
+ const kept = members.filter((m) => {
13602
+ const c = memberEqClass(m, key, litAbs, value);
13603
+ return keep ? c !== "never" : c !== "only";
13604
+ });
13605
+ if (kept.length === members.length) return a;
13606
+ if (kept.length === 0) return a;
13607
+ return kept.length === 1 ? kept[0] : { ...a, shape: { k: "sum", members: kept } };
13608
+ }
13458
13609
  function primShapeOfTypeOf(typeOf) {
13459
13610
  switch (typeOf) {
13460
13611
  case "string":
@@ -22262,6 +22413,7 @@ export {
22262
22413
  $removeUndefined,
22263
22414
  $removeMemberNullish,
22264
22415
  $narrowTypeOf,
22416
+ $narrowMemberEq,
22265
22417
  $nullishTest,
22266
22418
  SELF,
22267
22419
  getTerm,
@@ -45,7 +45,7 @@ import {
45
45
  withEvalBudgetOverride,
46
46
  withExecPhi,
47
47
  withFnBudgetOverride
48
- } from "./chunk-P6O5BXOA.js";
48
+ } from "./chunk-3SLNJPNY.js";
49
49
 
50
50
  // src/algebra/directive-scan.ts
51
51
  function cleanDirectiveLine(raw, kind) {
package/dist/exec.d.ts CHANGED
@@ -485,6 +485,14 @@ declare function $removeMemberNullish(a: Abs, key: string): Abs;
485
485
  * 原样返回(臂不可达的保守近似,与 $removeNullish 空集口径一致)。
486
486
  */
487
487
  declare function $narrowTypeOf(a: Abs, typeOf: string, keep: boolean): Abs;
488
+ /**
489
+ * 判别等值守卫臂剪影(issue #126):`x.key === lit` 事实臂(keep=true)内把
490
+ * x 重绑为「key 值域可能等于 lit」的成员子集(剪 "never" 成员);对偶补集臂
491
+ * (keep=false)剪 "only" 成员。单形态无可剪原样返回;全剪空 → 原样返回
492
+ * (臂不可达的保守近似,与 $removeNullish / $narrowTypeOf 同口径);
493
+ * 单成员剪余直接返回该成员。
494
+ */
495
+ declare function $narrowMemberEq(a: Abs, key: string, value: string | number | boolean, keep: boolean): Abs;
488
496
  /** `??` / `??=` 测试:确定非 nullish → false;lit nullish → true;否则抽象 boolean */
489
497
  declare function $nullishTest(v: Abs): Abs;
490
498
 
@@ -754,4 +762,4 @@ declare class NudoUnsupportedError extends Error {
754
762
  detail?: string);
755
763
  }
756
764
 
757
- export { $absVal, $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, $getSuper, $getSuperObj, $gt, $idx, $idxSet, $importMeta, $in, $instanceof, $instanceofNonIdent, $invoke, $invokeSuper, $invokeSuperKey, $invokeSuperObj, $isBreakTo, $isForkExit, $iterCheck, $join, $le, $len, $lit, $loopBreak, $loopContinue, $loopReturn, $lt, $mod, $mul, $narrowTypeOf, $ne, $neLoose, $neg, $new, $newTarget, $not, $nullishTest, $obj, $objAccessor, $objAccessorKey, $objRest, $optionalGet, $optionalInvoke, $orDefault, $pow, $pushLoopExit, $rawThis, $reStateCall, $regex, $removeMemberNullish, $removeNull, $removeNullish, $removeUndefined, $rethrowIfNudoReturn, $set, $setKey, $setProto, $shl, $shr, $spread, $staticInit, $staticInvoke, $sub, $super, $switch, $thisGet, $thisSet, $throw, $toNumber, $toNumeric, $tpl, $tryCurrentMark, $tryDetachSoftCatch, $tryDigestSoftCatch, $tryDiscardSoft, $tryMark, $tryOrphanSoft, $tryPopMark, $tryReleaseSoftCatch, $tryReleaseSoftOut, $tryTakeSince, $typeof, $unknown, $updateAdd, $updateSub, $ushr, $while, $whileSeq, $yield, $yieldStar, 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 };
765
+ export { $absVal, $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, $getSuper, $getSuperObj, $gt, $idx, $idxSet, $importMeta, $in, $instanceof, $instanceofNonIdent, $invoke, $invokeSuper, $invokeSuperKey, $invokeSuperObj, $isBreakTo, $isForkExit, $iterCheck, $join, $le, $len, $lit, $loopBreak, $loopContinue, $loopReturn, $lt, $mod, $mul, $narrowMemberEq, $narrowTypeOf, $ne, $neLoose, $neg, $new, $newTarget, $not, $nullishTest, $obj, $objAccessor, $objAccessorKey, $objRest, $optionalGet, $optionalInvoke, $orDefault, $pow, $pushLoopExit, $rawThis, $reStateCall, $regex, $removeMemberNullish, $removeNull, $removeNullish, $removeUndefined, $rethrowIfNudoReturn, $set, $setKey, $setProto, $shl, $shr, $spread, $staticInit, $staticInvoke, $sub, $super, $switch, $thisGet, $thisSet, $throw, $toNumber, $toNumeric, $tpl, $tryCurrentMark, $tryDetachSoftCatch, $tryDigestSoftCatch, $tryDiscardSoft, $tryMark, $tryOrphanSoft, $tryPopMark, $tryReleaseSoftCatch, $tryReleaseSoftOut, $tryTakeSince, $typeof, $unknown, $updateAdd, $updateSub, $ushr, $while, $whileSeq, $yield, $yieldStar, 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
@@ -65,6 +65,7 @@ import {
65
65
  $lt,
66
66
  $mod,
67
67
  $mul,
68
+ $narrowMemberEq,
68
69
  $narrowTypeOf,
69
70
  $ne,
70
71
  $neLoose,
@@ -193,7 +194,7 @@ import {
193
194
  tryRunTranspiled,
194
195
  withEvalBudgetOverride,
195
196
  withExecPhi
196
- } from "./chunk-P6O5BXOA.js";
197
+ } from "./chunk-3SLNJPNY.js";
197
198
  export {
198
199
  $absVal,
199
200
  $add,
@@ -260,6 +261,7 @@ export {
260
261
  $lt,
261
262
  $mod,
262
263
  $mul,
264
+ $narrowMemberEq,
263
265
  $narrowTypeOf,
264
266
  $ne,
265
267
  $neLoose,
package/dist/index.js CHANGED
@@ -63,7 +63,7 @@ import {
63
63
  takeInterfaceDiagsSince,
64
64
  takeRefineDiags,
65
65
  takeRefineDiagsSince
66
- } from "./chunk-WT5J6QTZ.js";
66
+ } from "./chunk-UDIJKTYG.js";
67
67
  import {
68
68
  $add,
69
69
  $arguments,
@@ -519,7 +519,7 @@ import {
519
519
  v,
520
520
  withExecPhi,
521
521
  withVar
522
- } from "./chunk-P6O5BXOA.js";
522
+ } from "./chunk-3SLNJPNY.js";
523
523
 
524
524
  // src/environment.ts
525
525
  function createEnvironment(parent, bindings = /* @__PURE__ */ new Map()) {
package/dist/internal.js CHANGED
@@ -21,7 +21,7 @@ import {
21
21
  stableAnalyzeKeySource,
22
22
  stablePathKey,
23
23
  stablePathKeyGraph
24
- } from "./chunk-WT5J6QTZ.js";
24
+ } from "./chunk-UDIJKTYG.js";
25
25
  import {
26
26
  $tryDigestSoft,
27
27
  $tryMarkSoft,
@@ -169,7 +169,7 @@ import {
169
169
  withEvalBudgetOverride,
170
170
  withFnBudgetOverride,
171
171
  wrapPromise
172
- } from "./chunk-P6O5BXOA.js";
172
+ } from "./chunk-3SLNJPNY.js";
173
173
 
174
174
  // src/algebra/inlay.ts
175
175
  function listFunctions(source) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nudojs/core",
3
- "version": "1.8.0",
3
+ "version": "1.9.0",
4
4
  "engines": {
5
5
  "node": ">=20"
6
6
  },