@nudojs/core 1.15.2 → 1.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/internal.js CHANGED
@@ -4,25 +4,33 @@ import {
4
4
  checkInjectedDomainEvidence,
5
5
  createDiagChannel,
6
6
  createScopedDiagChannel,
7
+ escapeTemplateTypeFixed,
7
8
  exportedNameOfLocal,
8
9
  extractAllLoadSpecs,
9
10
  fnFingerprints,
11
+ formatObjectKey,
10
12
  generalizeFromAst,
11
13
  generalizeSourceKeyPart,
12
14
  getFnNameAndBodies,
13
15
  hashSource,
14
16
  interfaceTierOf,
17
+ isJsBindingIdent,
18
+ isJsIdent,
15
19
  listTopFunctions,
16
20
  loadModuleDepsFingerprint,
21
+ localNamedExports,
17
22
  normPath,
18
23
  resetFnFpCache,
19
24
  resetHashSourceCache,
20
25
  resolveDepPath,
26
+ safeMemberAccess,
27
+ sanitizeCommentText,
21
28
  sidecarSpecsOf,
22
29
  stableAnalyzeKeySource,
23
30
  stablePathKey,
24
- stablePathKeyGraph
25
- } from "./chunk-NXZSRLCT.js";
31
+ stablePathKeyGraph,
32
+ toJsBindingIdent
33
+ } from "./chunk-4MRLOJMI.js";
26
34
  import {
27
35
  $tryDigestSoft,
28
36
  $tryMarkSoft,
@@ -40,24 +48,22 @@ import {
40
48
  PROMISE_MICRO_ERROR_LABEL,
41
49
  PROMISE_MICRO_OVERFLOW_LABEL,
42
50
  ProjectionBudget,
51
+ SELF,
43
52
  abortDerivationSession,
44
53
  absLit,
45
54
  absNumLit,
46
55
  absStrLit,
47
56
  absTemplateViews,
57
+ accessorReadDomain,
48
58
  allAbsStr,
49
59
  allFixedTextOfViews,
50
60
  anyMemberResult,
51
- awaitAbs,
52
61
  beginDerivationSession,
53
62
  bumpEvalForkBudget,
54
63
  callBudgetKey,
55
- classChainNames,
56
- classFromMethods,
57
64
  clearLiveImportRefreshers,
58
65
  clearPureCallMemo,
59
66
  clearPureMemo,
60
- coerceAsyncReturn,
61
67
  concatString,
62
68
  createScopedSlot,
63
69
  createTemplateAbs,
@@ -65,7 +71,6 @@ import {
65
71
  decideIncludes,
66
72
  decideStartsWith,
67
73
  defaultLeakBudget,
68
- defineClass,
69
74
  definitelyUncallableMember,
70
75
  derivationChain,
71
76
  endDerivationSession,
@@ -85,7 +90,6 @@ import {
85
90
  formatThrowsAbs,
86
91
  getAbsCallBudgetStats,
87
92
  getAbsOrigin,
88
- getClass,
89
93
  getClassChain,
90
94
  getDerivation,
91
95
  getEvalCallBudgetState,
@@ -95,19 +99,16 @@ import {
95
99
  getMayThrowCollector,
96
100
  getPromiseMicrosLength,
97
101
  hasDerivationSession,
98
- instanceOf,
99
- instantiateClass,
100
102
  isEvalMissingSlotEnabled,
103
+ isHiddenInternalSlot,
101
104
  isNullishAbs,
102
105
  isTemplateLike,
103
106
  isThrowsIgnored,
104
107
  knownPrefixOfViews,
105
108
  knownSuffixOfViews,
106
109
  leakIfNeeded,
110
+ litKeyString,
107
111
  litValue,
108
- lookupMethod,
109
- lookupMethodWithOwner,
110
- lookupSuperMethod,
111
112
  maskCommentsAndStrings,
112
113
  mayThrowEffectsToAbs,
113
114
  maybeLeak,
@@ -128,7 +129,6 @@ import {
128
129
  popCallLoc,
129
130
  popMayThrowFrame,
130
131
  predToString,
131
- projectBrand,
132
132
  projectDerivationDsl,
133
133
  pushCallLoc,
134
134
  pushMayThrowFrame,
@@ -156,12 +156,12 @@ import {
156
156
  stableCallId,
157
157
  stripCommentsAndStrings,
158
158
  stripStringsKeepComments,
159
- superNameOf,
160
159
  tagAbsOrigin,
161
160
  tagDerivationRoot,
162
161
  templateMatchesValue,
163
162
  templatePartsOf,
164
163
  termDepth,
164
+ termEquals,
165
165
  termKey,
166
166
  termNodes,
167
167
  termToString,
@@ -172,17 +172,33 @@ import {
172
172
  withEvalBudgetOverride,
173
173
  withFnBudgetOverride,
174
174
  wrapPromise
175
- } from "./chunk-WKIRPUHZ.js";
175
+ } from "./chunk-ARIQO5XX.js";
176
176
 
177
177
  // src/algebra/inlay.ts
178
178
  function listFunctions(source) {
179
179
  const file = parseSource(source);
180
180
  const out = [];
181
+ const exported = localNamedExports(source);
181
182
  const visitDecl = (decl) => {
182
183
  if (decl.type === "FunctionDeclaration" && decl.id) {
183
184
  const fd = decl;
184
185
  out.push({ name: fd.id.name, node: fd });
185
186
  }
187
+ if (decl.type === "ClassDeclaration") {
188
+ const cd = decl;
189
+ const clsName = cd.id?.name;
190
+ if (clsName) {
191
+ for (const m of cd.body?.body ?? []) {
192
+ if (m.type !== "ClassMethod") continue;
193
+ if (m.kind && m.kind !== "method") continue;
194
+ const keyName = m.key?.type === "Identifier" ? m.key.name : void 0;
195
+ if (!keyName) continue;
196
+ const fullName = `${clsName}.${keyName}`;
197
+ if (!exported.has(fullName)) continue;
198
+ out.push({ name: fullName, node: m });
199
+ }
200
+ }
201
+ }
186
202
  if (decl.type === "VariableDeclaration") {
187
203
  const dcls = decl.declarations ?? [];
188
204
  for (const d of dcls) {
@@ -194,11 +210,40 @@ function listFunctions(source) {
194
210
  }
195
211
  }
196
212
  };
213
+ const isExportsTarget = (n) => {
214
+ if (!n) return false;
215
+ if (n.type === "Identifier") return n.name === "exports";
216
+ if (n.type === "MemberExpression") {
217
+ const me = n;
218
+ return me.object?.type === "Identifier" && me.object.name === "module" && me.property?.type === "Identifier" && me.property.name === "exports";
219
+ }
220
+ return false;
221
+ };
222
+ const visitCjsAssign = (stmt) => {
223
+ const expr = stmt.expression;
224
+ if (!expr || expr.type !== "AssignmentExpression") return;
225
+ const assign = expr;
226
+ if (assign.operator !== "=") return;
227
+ const left = assign.left;
228
+ const right = assign.right;
229
+ if (!left || !right || left.type !== "MemberExpression") return;
230
+ const me = left;
231
+ if (me.computed === true) return;
232
+ if (!isExportsTarget(me.object)) return;
233
+ const prop = me.property;
234
+ const propName = prop?.type === "Identifier" ? prop.name : void 0;
235
+ if (!propName) return;
236
+ if (!exported.has(propName)) return;
237
+ if (right.type !== "FunctionExpression" && right.type !== "ArrowFunctionExpression") return;
238
+ out.push({ name: propName, node: right });
239
+ };
197
240
  for (const stmt of file.program.body) {
198
241
  if (stmt.type === "ExportNamedDeclaration" && stmt.declaration) {
199
242
  visitDecl(stmt.declaration);
200
243
  } else if (stmt.type === "ExportDefaultDeclaration" && stmt.declaration) {
201
244
  visitDecl(stmt.declaration);
245
+ } else if (stmt.type === "ExpressionStatement") {
246
+ visitCjsAssign(stmt);
202
247
  } else {
203
248
  visitDecl(stmt);
204
249
  }
@@ -213,6 +258,17 @@ function renameTypeVars(s, varMap) {
213
258
  }
214
259
  return out;
215
260
  }
261
+ var INTERNAL_LEN_ID_RE = /^len#\d+$/;
262
+ var READABLE_LEN_ID = "len";
263
+ function readableTerm(t) {
264
+ if (t.op === "var") {
265
+ return INTERNAL_LEN_ID_RE.test(t.id) ? { op: "var", id: READABLE_LEN_ID } : t;
266
+ }
267
+ if (t.op === "app") {
268
+ return { op: "app", fn: t.fn, args: t.args.map(readableTerm) };
269
+ }
270
+ return t;
271
+ }
216
272
  function formatReturnDisplay(g) {
217
273
  const varMap = /* @__PURE__ */ new Map();
218
274
  for (let i = 0; i < (g.typeParams?.length ?? 0); i++) {
@@ -221,28 +277,28 @@ function formatReturnDisplay(g) {
221
277
  if (pname) varMap.set(id, pname);
222
278
  }
223
279
  const stripParens = (t) => t.startsWith("(") && t.endsWith(")") ? t.slice(1, -1) : t;
280
+ const termText = (t) => stripParens(renameTypeVars(termToString(readableTerm(t)), varMap));
224
281
  const memberPath = (m) => {
225
282
  if (m.term?.op === "var") {
226
- const name = renameTypeVars(m.term.id, varMap);
283
+ const name = INTERNAL_LEN_ID_RE.test(m.term.id) ? READABLE_LEN_ID : renameTypeVars(m.term.id, varMap);
227
284
  return { key: `var:${name}`, text: name };
228
285
  }
229
286
  if (m.term?.op === "app") {
230
- const t = stripParens(renameTypeVars(termToString(m.term), varMap));
287
+ const t = termText(m.term);
231
288
  return { key: `app:${t}`, text: t };
232
289
  }
233
290
  const lvR = litValue(m);
234
291
  if (lvR.ok) {
235
292
  const lv = lvR.value;
236
- if (typeof lv === "number" && !Number.isFinite(lv)) {
237
- return { key: `lit:${String(lv)}`, text: String(lv) };
238
- }
239
- return { key: `lit:${String(lv)}`, text: JSON.stringify(lv) ?? "undefined" };
293
+ const text = termToString({ op: "lit", value: lv });
294
+ const key = `lit:${typeof lv}:${litKeyString(lv)}`;
295
+ return { key, text };
240
296
  }
241
297
  return { key: `shape:${formatShape(m)}`, text: formatShape(m) };
242
298
  };
243
299
  const abs = g.symbolic;
244
300
  if (abs.term && abs.term.op !== "lit") {
245
- return stripParens(renameTypeVars(termToString(abs.term), varMap));
301
+ return termText(abs.term);
246
302
  }
247
303
  if (abs.shape.k === "sum") {
248
304
  const parts = [];
@@ -269,7 +325,10 @@ function collectAbsInlays(source, opts) {
269
325
  try {
270
326
  g = generalizeFromAst(name, source, {
271
327
  ...refineOpts ? { refine: refineOpts } : {},
272
- ...opts?.modules ? { modules: opts.modules } : {}
328
+ ...opts?.modules ? { modules: opts.modules } : {},
329
+ // 注入包透传(Bug 786):@nudo:mock / @nudo:as / @nudo:replace /
330
+ // env 全局缺席 ⇒ 推导链塌缩 unknown(与 CLI 面分叉)。
331
+ ...opts?.inject ? { inject: opts.inject } : {}
273
332
  });
274
333
  } catch {
275
334
  continue;
@@ -311,8 +370,10 @@ function collectAbsInlays(source, opts) {
311
370
  });
312
371
  }
313
372
  }
314
- const bodyLoc = fnNode.body?.loc;
315
- if (bodyLoc?.start) {
373
+ const bodyNode = fnNode.body;
374
+ const bodyLoc = bodyNode?.loc;
375
+ const anchor = bodyNode?.type === "BlockStatement" ? bodyLoc?.start : bodyLoc?.end ?? bodyLoc?.start;
376
+ if (anchor) {
316
377
  let label;
317
378
  try {
318
379
  label = `: ${formatReturnDisplay(g)}`;
@@ -321,8 +382,8 @@ function collectAbsInlays(source, opts) {
321
382
  }
322
383
  if (isImplicitExport) label += " \xB7 derived";
323
384
  inlays.push({
324
- line: bodyLoc.start.line,
325
- character: Math.max(0, bodyLoc.start.column),
385
+ line: anchor.line,
386
+ character: Math.max(0, anchor.column),
326
387
  label: `${label} `,
327
388
  kind: "type",
328
389
  ...tierSrc ? { interfaceSource: tierSrc } : {},
@@ -333,103 +394,32 @@ function collectAbsInlays(source, opts) {
333
394
  return inlays;
334
395
  }
335
396
 
336
- // src/algebra/codegen-escape.ts
337
- var JS_IDENT = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
338
- var JS_BINDING_IDENT = /^(?:[$_\p{ID_Start}])(?:[$\u200C\u200D\p{ID_Continue}])*$/u;
339
- var JS_BINDING_RESERVED = /* @__PURE__ */ new Set([
340
- // ECMA-262 keywords
341
- "break",
342
- "case",
343
- "catch",
344
- "class",
345
- "const",
346
- "continue",
347
- "debugger",
348
- "default",
349
- "delete",
350
- "do",
351
- "else",
352
- "enum",
353
- "export",
354
- "extends",
355
- "false",
356
- "finally",
357
- "for",
358
- "function",
359
- "if",
360
- "import",
361
- "in",
362
- "instanceof",
363
- "new",
364
- "null",
365
- "return",
366
- "super",
367
- "switch",
368
- "this",
369
- "throw",
370
- "true",
371
- "try",
372
- "typeof",
373
- "var",
374
- "void",
375
- "while",
376
- "with",
377
- "yield",
378
- // strict mode / module-code reserved
379
- "let",
380
- "static",
381
- "await",
382
- "implements",
383
- "interface",
384
- "package",
385
- "private",
386
- "protected",
387
- "public",
388
- // never legal bindings in strict / module code
397
+ // src/algebra/denote.ts
398
+ var PROTOTYPE_LESS_GLOBALS = /* @__PURE__ */ new Set([
399
+ // 可调用但没有对象 prototype
400
+ "Proxy",
401
+ "parseFloat",
402
+ "parseInt",
403
+ "decodeURI",
404
+ "decodeURIComponent",
405
+ "encodeURI",
406
+ "encodeURIComponent",
407
+ "escape",
408
+ "unescape",
389
409
  "eval",
390
- "arguments"
410
+ "isFinite",
411
+ "isNaN",
412
+ // 不可调用(非构造器)
413
+ "Math",
414
+ "JSON",
415
+ "Intl",
416
+ "Reflect",
417
+ "Atomics",
418
+ "globalThis"
391
419
  ]);
392
- var JS_CANONICAL_INT = /^(?:0|[1-9]\d*)$/;
393
- function isJsIdent(name) {
394
- return JS_IDENT.test(name);
395
- }
396
- function isJsBindingIdent(name) {
397
- return JS_BINDING_IDENT.test(name) && !JS_BINDING_RESERVED.has(name);
398
- }
399
- function toJsBindingIdent(name, used) {
400
- let base = name;
401
- if (!JS_BINDING_IDENT.test(base)) {
402
- base = base.replace(/[^\p{ID_Continue}$\u200C\u200D]/gu, "_");
403
- if (base.length === 0) base = "_";
404
- else if (!/^[$_\p{ID_Start}]/u.test(base)) base = `_${base}`;
405
- }
406
- if (JS_BINDING_RESERVED.has(base)) base = `_${base}`;
407
- if (!used) return base;
408
- let n = base;
409
- let i = 2;
410
- while (used.has(n)) {
411
- n = `${base}_${i}`;
412
- i++;
413
- }
414
- used.add(n);
415
- return n;
416
- }
417
- function formatObjectKey(k) {
418
- if (JS_IDENT.test(k)) return k;
419
- if (JS_CANONICAL_INT.test(k)) return k;
420
- return JSON.stringify(k);
421
- }
422
- function safeMemberAccess(recv, key) {
423
- return JS_IDENT.test(key) ? `${recv}.${key}` : `${recv}[${JSON.stringify(key)}]`;
424
- }
425
- function escapeTemplateTypeFixed(text) {
426
- return text.replace(/[\\`$]/g, "\\$&");
420
+ function hasUnusablePrototype(name) {
421
+ return PROTOTYPE_LESS_GLOBALS.has(name);
427
422
  }
428
- function sanitizeCommentText(text) {
429
- return text.replace(/\*\//g, "*\\/").replace(/[\r\n\u2028\u2029\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, " ");
430
- }
431
-
432
- // src/algebra/denote.ts
433
423
  function denoteGuard(a, v) {
434
424
  return denoteGuardB(a, v, new ProjectionBudget());
435
425
  }
@@ -440,7 +430,7 @@ function denoteGuardB(a, v, budget) {
440
430
  if (a.term?.op === "lit" && (!a.pred || a.pred.op === "true")) {
441
431
  return eqGuard(v, a.term.value);
442
432
  }
443
- const shape = denoteShape(a.shape, v, budget);
433
+ const shape = denoteShape(a, v, budget);
444
434
  const pred = denotePred(a, v);
445
435
  if (shape === "true") return pred;
446
436
  if (pred === "true") return shape;
@@ -449,7 +439,8 @@ function denoteGuardB(a, v, budget) {
449
439
  budget.exit();
450
440
  }
451
441
  }
452
- function denoteShape(s, v, budget) {
442
+ function denoteShape(a, v, budget) {
443
+ const s = a.shape;
453
444
  switch (s.k) {
454
445
  case "never":
455
446
  return "false";
@@ -472,13 +463,16 @@ function denoteShape(s, v, budget) {
472
463
  return "true";
473
464
  }
474
465
  case "obj": {
475
- const checks = [`typeof ${v} === "object"`, `${v} !== null`];
466
+ const checks = [`typeof ${v} === "object"`, `${v} !== null`, `!Array.isArray(${v})`];
476
467
  for (const [key, slot] of Object.entries(s.slots)) {
468
+ if (isHiddenInternalSlot(key, slot)) continue;
477
469
  const access = safeMemberAccess(v, key);
478
- const inner = denoteGuardB(slot.value, access, budget);
470
+ const slotAbs = accessorReadDomain(a, key) ?? slot.value;
471
+ const inner = denoteGuardB(slotAbs, access, budget);
479
472
  if (slot.optional) {
480
473
  if (inner !== "true") checks.push(`(${access} === undefined || ${inner})`);
481
474
  } else {
475
+ checks.push(hasPropertyClause(v, key));
482
476
  if (inner !== "true") checks.push(inner);
483
477
  }
484
478
  }
@@ -515,8 +509,13 @@ function denoteShape(s, v, budget) {
515
509
  case "eff":
516
510
  if (s.eff === "promise") return `${v} instanceof Promise`;
517
511
  return "true";
518
- case "brand":
519
- return denoteShape(s.shape.shape, v, budget);
512
+ case "brand": {
513
+ const inner = denoteShape(s.shape, v, budget);
514
+ if (hasUnusablePrototype(s.name)) return inner;
515
+ const identity = brandIdentityClause(s.name, v);
516
+ if (inner === "true") return identity;
517
+ return `(${identity}) && (${inner})`;
518
+ }
520
519
  case "sum": {
521
520
  if (s.members.length === 0) return "false";
522
521
  const parts = s.members.map((m) => denoteGuardB(m, v, budget));
@@ -566,12 +565,29 @@ function predAsJs(p, v, a) {
566
565
  if (leftLitTerm && rightLitTerm) {
567
566
  return `${jsLit(leftLitTerm.value)} ${op} ${jsLit(rightLitTerm.value)}`;
568
567
  }
568
+ if (rightLitTerm && typeof rightLitTerm.value === "number" && isLengthSelf(p.a, a)) {
569
+ return `${v}.length ${op} ${rightLitTerm.value}`;
570
+ }
569
571
  return "true";
570
572
  }
571
573
  default:
572
574
  return "true";
573
575
  }
574
576
  }
577
+ function hasPropertyClause(v, key) {
578
+ const k = JSON.stringify(key);
579
+ return `(Object.hasOwn(${v}, ${k}) || (${k} in ${v} && !Object.hasOwn(Object.prototype, ${k})))`;
580
+ }
581
+ function brandIdentityClause(name, v) {
582
+ const ctor = `Reflect.get(globalThis, ${JSON.stringify(name)})`;
583
+ return `(typeof ${ctor} !== "function" || ${v} instanceof ${ctor})`;
584
+ }
585
+ function isLengthSelf(t, a) {
586
+ if (t.op !== "app" || t.fn !== "length" || t.args.length !== 1) return false;
587
+ const arg = t.args[0];
588
+ if (a.term && termEquals(arg, a.term)) return true;
589
+ return arg.op === "var" && arg.id === SELF;
590
+ }
575
591
  function jsLit(v) {
576
592
  if (v === void 0) return "undefined";
577
593
  if (v === null) return "null";
@@ -634,19 +650,15 @@ export {
634
650
  allAbsStr,
635
651
  allFixedTextOfViews,
636
652
  anyMemberResult,
637
- awaitAbs,
638
653
  beginDerivationSession,
639
654
  budgetAttributionSegs,
640
655
  bumpEvalForkBudget,
641
656
  callBudgetKey,
642
657
  canSkipLiteralCallScan,
643
658
  checkInjectedDomainEvidence,
644
- classChainNames,
645
- classFromMethods,
646
659
  clearLiveImportRefreshers,
647
660
  clearPureCallMemo,
648
661
  clearPureMemo,
649
- coerceAsyncReturn,
650
662
  collectAbsInlays,
651
663
  concatString,
652
664
  createDiagChannel,
@@ -657,7 +669,6 @@ export {
657
669
  decideIncludes,
658
670
  decideStartsWith,
659
671
  defaultLeakBudget,
660
- defineClass,
661
672
  definitelyUncallableMember,
662
673
  denoteGuard,
663
674
  derivationChain,
@@ -683,7 +694,6 @@ export {
683
694
  generalizeSourceKeyPart,
684
695
  getAbsCallBudgetStats,
685
696
  getAbsOrigin,
686
- getClass,
687
697
  getClassChain,
688
698
  getDerivation,
689
699
  getEvalCallBudgetState,
@@ -695,8 +705,6 @@ export {
695
705
  getPromiseMicrosLength,
696
706
  hasDerivationSession,
697
707
  hashSource,
698
- instanceOf,
699
- instantiateClass,
700
708
  isEvalMissingSlotEnabled,
701
709
  isJsBindingIdent,
702
710
  isJsIdent,
@@ -708,9 +716,6 @@ export {
708
716
  leakIfNeeded,
709
717
  listTopFunctions,
710
718
  loadModuleDepsFingerprint,
711
- lookupMethod,
712
- lookupMethodWithOwner,
713
- lookupSuperMethod,
714
719
  maskCommentsAndStrings,
715
720
  mayThrowEffectsToAbs,
716
721
  maybeLeak,
@@ -730,7 +735,6 @@ export {
730
735
  orphanMayThrowEffects,
731
736
  popCallLoc,
732
737
  popMayThrowFrame,
733
- projectBrand,
734
738
  projectDerivationDsl,
735
739
  pushCallLoc,
736
740
  pushMayThrowFrame,
@@ -767,7 +771,6 @@ export {
767
771
  stablePathKeyGraph,
768
772
  stripCommentsAndStrings,
769
773
  stripStringsKeepComments,
770
- superNameOf,
771
774
  tagAbsOrigin,
772
775
  tagDerivationRoot,
773
776
  templateMatchesValue,