@nudojs/core 1.16.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.
@@ -1,11 +1,13 @@
1
1
  import {
2
2
  $invoke,
3
3
  $new,
4
+ BoundedLruMap,
4
5
  CONSTRAINT_BUILDERS,
5
6
  DIAG,
6
7
  LAZY_TEMPLATE_DEPTH,
7
8
  TYPEOF_NAMES,
8
9
  abs,
10
+ absKey,
9
11
  absLit,
10
12
  and,
11
13
  andC,
@@ -32,6 +34,7 @@ import {
32
34
  freeIdentifiers,
33
35
  getFnImpl,
34
36
  getSlot,
37
+ hasUseStrictDirective,
35
38
  identBoundaryRegex,
36
39
  implies,
37
40
  instantiateConstraint,
@@ -50,10 +53,12 @@ import {
50
53
  numLit,
51
54
  pTrue,
52
55
  parseSource,
56
+ predKey,
53
57
  predToString,
54
58
  registerCollectorScopeParticipant,
55
59
  runTranspiledOptionsMemoKey,
56
60
  snapshotAbs,
61
+ sourceIsStrict,
57
62
  stripStringsKeepComments,
58
63
  termEquals,
59
64
  termToString,
@@ -65,7 +70,7 @@ import {
65
70
  withExecPhi,
66
71
  withFnBudgetOverride,
67
72
  withOptionalParams
68
- } from "./chunk-OM6SAY2M.js";
73
+ } from "./chunk-CUFP2AYV.js";
69
74
 
70
75
  // src/algebra/directive-scan.ts
71
76
  function cleanDirectiveLine(raw, kind) {
@@ -617,8 +622,16 @@ function nestedBodyRanges(source) {
617
622
  return [];
618
623
  }
619
624
  }
625
+ var BODY_GATE_RANGES_CACHE_MAX = 16;
626
+ var bodyGateRangesCache = new BoundedLruMap(
627
+ BODY_GATE_RANGES_CACHE_MAX
628
+ );
620
629
  function bodyGateRanges(source) {
621
- 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;
622
635
  }
623
636
  function inBodyRange(ranges, offset) {
624
637
  return ranges.some(([s, e]) => offset >= s && offset < e);
@@ -2380,7 +2393,27 @@ function extractFnBudget(source, fnName) {
2380
2393
  }
2381
2394
 
2382
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
+ }
2383
2413
  function localNamedExports(source) {
2414
+ return memoizedLocalExports(source, () => computeLocalNamedExports(source));
2415
+ }
2416
+ function computeLocalNamedExports(source) {
2384
2417
  const out = /* @__PURE__ */ new Set();
2385
2418
  let ast;
2386
2419
  try {
@@ -4031,87 +4064,8 @@ function loadModuleDepsFingerprint(source, loadModule, fromFile, opts) {
4031
4064
  }
4032
4065
 
4033
4066
  // src/algebra/generalize-key.ts
4034
- function termKey(t, rename) {
4035
- switch (t.op) {
4036
- case "lit":
4037
- return `L:${typeof t.value}:${litKeyString(t.value)}`;
4038
- case "var":
4039
- return `V:${rename?.get(t.id) ?? t.id}`;
4040
- case "app":
4041
- return `A:${t.fn}(${t.args.map((a) => termKey(a, rename)).join(",")})`;
4042
- }
4043
- }
4044
- function predKey(p, rename) {
4045
- switch (p.op) {
4046
- case "true":
4047
- return "T";
4048
- case "false":
4049
- return "F";
4050
- case "eq":
4051
- case "ne":
4052
- case "lt":
4053
- case "le":
4054
- case "gt":
4055
- case "ge":
4056
- return `${p.op}(${termKey(p.a, rename)},${termKey(p.b, rename)})`;
4057
- case "and":
4058
- case "or": {
4059
- const keys = p.args.map((a) => predKey(a, rename)).sort();
4060
- return `${p.op}(${keys.join(",")})`;
4061
- }
4062
- case "not":
4063
- return `not(${predKey(p.arg, rename)})`;
4064
- case "typeof":
4065
- return `typeof(${termKey(p.t, rename)},${p.type})`;
4066
- case "assumeFinite":
4067
- return `assumeFinite(${termKey(p.t, rename)})`;
4068
- }
4069
- }
4070
- function shapeKey(s, seen, rename) {
4071
- switch (s.k) {
4072
- case "never":
4073
- case "any":
4074
- case "unknown":
4075
- return s.k;
4076
- case "prim":
4077
- return `p:${s.type}`;
4078
- case "brand":
4079
- return `b:${s.name}(${absKeyInner(s.shape, seen, rename)})`;
4080
- case "eff":
4081
- return `e:${s.eff}<${absKeyInner(s.inner, seen, rename)}>`;
4082
- case "arr":
4083
- return `arr(${absKeyInner(s.element, seen, rename)})`;
4084
- case "tuple": {
4085
- const els = s.elements.map((e) => absKeyInner(e, seen, rename)).join(",");
4086
- const rest = s.rest ? `...${absKeyInner(s.rest, seen, rename)}` : "";
4087
- return `tup[${els}${rest}]`;
4088
- }
4089
- case "fn": {
4090
- const pts = (s.paramTypes ?? []).map((t) => absKeyInner(t, seen, rename)).join(",");
4091
- const ret = s.returnType ? absKeyInner(s.returnType, seen, rename) : "?";
4092
- const name = s.name ? `#${s.name}` : "";
4093
- return `fn${name}(${s.params.join(",")}|${pts})=>${ret}`;
4094
- }
4095
- case "sum":
4096
- return `sum(${s.members.map((m) => absKeyInner(m, seen, rename)).join("|")})`;
4097
- case "obj": {
4098
- const slots = Object.keys(s.slots).sort().map((k) => {
4099
- const slot = s.slots[k];
4100
- const flags = (slot.optional ? "?" : "") + (slot.readonly ? "r" : "");
4101
- return `${k}${flags}:${absKeyInner(slot.value, seen, rename)}`;
4102
- }).join(",");
4103
- const idx = s.index ? `idx(${absKeyInner(s.index.key, seen, rename)}\u2192${absKeyInner(s.index.value, seen, rename)})` : "";
4104
- const open = s.open ? "open" : "";
4105
- return `obj{${slots}}${idx}${open}`;
4106
- }
4107
- }
4108
- }
4109
4067
  function absKeyInner(a, seen, rename) {
4110
- if (seen.has(a)) return "cycle";
4111
- seen.add(a);
4112
- const t = a.term ? `=${termKey(a.term, rename)}` : "";
4113
- const p = a.pred ? `@${predKey(a.pred, rename)}` : "";
4114
- return `${shapeKey(a.shape, seen, rename)}${t}${p}`;
4068
+ return absKey(a, seen, rename);
4115
4069
  }
4116
4070
  function collectTermVars(t, acc) {
4117
4071
  if (t.op === "var") acc.add(t.id);
@@ -4239,43 +4193,58 @@ function renameShape(s, map) {
4239
4193
  case "prim":
4240
4194
  return s;
4241
4195
  case "brand":
4242
- return { k: "brand", name: s.name, shape: renameAbs(s.shape, map) };
4243
- case "eff":
4244
- return { k: "eff", eff: s.eff, inner: renameAbs(s.inner, map) };
4196
+ return { ...s, shape: renameAbs(s.shape, map) };
4197
+ case "eff": {
4198
+ const out = { ...s, inner: renameAbs(s.inner, map) };
4199
+ if (s.rejected) out.rejected = renameAbs(s.rejected, map);
4200
+ return out;
4201
+ }
4245
4202
  case "arr":
4246
- return { k: "arr", element: renameAbs(s.element, map) };
4203
+ return { ...s, element: renameAbs(s.element, map) };
4247
4204
  case "tuple": {
4248
4205
  const out = {
4249
- k: "tuple",
4206
+ ...s,
4250
4207
  elements: s.elements.map((e) => renameAbs(e, map))
4251
4208
  };
4252
4209
  if (s.rest) out.rest = renameAbs(s.rest, map);
4210
+ if (s.holes) out.holes = [...s.holes];
4253
4211
  return out;
4254
4212
  }
4255
4213
  case "fn": {
4256
- const out = { k: "fn", params: s.params };
4257
- if (s.name !== void 0) out.name = s.name;
4214
+ const out = { ...s, params: [...s.params] };
4258
4215
  if (s.paramTypes) out.paramTypes = s.paramTypes.map((t) => renameAbs(t, map));
4259
4216
  if (s.returnType) out.returnType = renameAbs(s.returnType, map);
4260
- if (s.ctor !== void 0) out.ctor = s.ctor;
4217
+ if (s.optionalParams) out.optionalParams = [...s.optionalParams];
4218
+ if (s.slots) {
4219
+ const slots = {};
4220
+ for (const [k, slot] of Object.entries(s.slots)) {
4221
+ Object.defineProperty(slots, k, {
4222
+ value: { ...slot, value: renameAbs(slot.value, map) },
4223
+ enumerable: true,
4224
+ writable: true,
4225
+ configurable: true
4226
+ });
4227
+ }
4228
+ out.slots = slots;
4229
+ }
4261
4230
  return out;
4262
4231
  }
4263
4232
  case "sum":
4264
- return { k: "sum", members: s.members.map((m) => renameAbs(m, map)) };
4233
+ return { ...s, members: s.members.map((m) => renameAbs(m, map)) };
4265
4234
  case "obj": {
4266
4235
  const slots = {};
4267
4236
  for (const [k, slot] of Object.entries(s.slots)) {
4268
- slots[k] = {
4269
- value: renameAbs(slot.value, map),
4270
- ...slot.optional ? { optional: true } : {},
4271
- ...slot.readonly ? { readonly: true } : {}
4272
- };
4237
+ Object.defineProperty(slots, k, {
4238
+ value: { ...slot, value: renameAbs(slot.value, map) },
4239
+ enumerable: true,
4240
+ writable: true,
4241
+ configurable: true
4242
+ });
4273
4243
  }
4274
- const out = { k: "obj", slots };
4244
+ const out = { ...s, slots };
4275
4245
  if (s.index) {
4276
4246
  out.index = { key: renameAbs(s.index.key, map), value: renameAbs(s.index.value, map) };
4277
4247
  }
4278
- if (s.open) out.open = true;
4279
4248
  return out;
4280
4249
  }
4281
4250
  }
@@ -4306,6 +4275,130 @@ function alphaRenameResult(result, fromOrder, toOrder) {
4306
4275
  return renameAbs(result, map);
4307
4276
  }
4308
4277
 
4278
+ // src/algebra/generalize.ts
4279
+ import { VISITOR_KEYS } from "@babel/types";
4280
+
4281
+ // src/algebra/memo-store.ts
4282
+ var DependencyMemo = class {
4283
+ constructor(max) {
4284
+ this.max = max;
4285
+ }
4286
+ max;
4287
+ values = /* @__PURE__ */ new Map();
4288
+ keyDeps = /* @__PURE__ */ new Map();
4289
+ depIndex = /* @__PURE__ */ new Map();
4290
+ get size() {
4291
+ return this.values.size;
4292
+ }
4293
+ /** 命中 ⇒ 移到队尾(LRU 刷新);`hit` 区分存了 undefined 与 miss */
4294
+ lookup(key) {
4295
+ if (!this.values.has(key)) return { hit: false };
4296
+ const value = this.values.get(key);
4297
+ this.values.delete(key);
4298
+ this.values.set(key, value);
4299
+ return { hit: true, value };
4300
+ }
4301
+ set(key, value, depPaths) {
4302
+ if (!this.values.has(key) && this.values.size >= this.max) {
4303
+ const oldest = this.values.keys().next().value;
4304
+ if (oldest !== void 0) {
4305
+ this.values.delete(oldest);
4306
+ this.unindex(oldest);
4307
+ }
4308
+ }
4309
+ this.values.set(key, value);
4310
+ if (depPaths.length > 0) {
4311
+ const normDeps = [...new Set(depPaths.map(stablePathKey))];
4312
+ this.keyDeps.set(key, normDeps);
4313
+ for (const p of normDeps) {
4314
+ let set = this.depIndex.get(p);
4315
+ if (!set) {
4316
+ set = /* @__PURE__ */ new Set();
4317
+ this.depIndex.set(p, set);
4318
+ }
4319
+ set.add(key);
4320
+ }
4321
+ }
4322
+ }
4323
+ /** 定向逐出依赖这些路径的条目;返回删除数。查找与索引同走 stablePathKey */
4324
+ evictForPaths(paths) {
4325
+ let n = 0;
4326
+ for (const raw of paths) {
4327
+ const p = stablePathKey(raw);
4328
+ const keys = this.depIndex.get(p);
4329
+ if (!keys) continue;
4330
+ for (const key of [...keys]) {
4331
+ this.values.delete(key);
4332
+ this.unindex(key);
4333
+ n++;
4334
+ }
4335
+ }
4336
+ return n;
4337
+ }
4338
+ reset() {
4339
+ this.values.clear();
4340
+ this.keyDeps.clear();
4341
+ this.depIndex.clear();
4342
+ }
4343
+ unindex(key) {
4344
+ const deps = this.keyDeps.get(key);
4345
+ if (!deps) return;
4346
+ for (const p of deps) {
4347
+ const set = this.depIndex.get(p);
4348
+ if (!set) continue;
4349
+ set.delete(key);
4350
+ if (set.size === 0) this.depIndex.delete(p);
4351
+ }
4352
+ this.keyDeps.delete(key);
4353
+ }
4354
+ };
4355
+
4356
+ // src/algebra/memo-identity.ts
4357
+ var loadModuleIds = /* @__PURE__ */ new WeakMap();
4358
+ var nextLoadModuleId = 1;
4359
+ function loadModuleId(fn) {
4360
+ if (!fn) return 0;
4361
+ let id = loadModuleIds.get(fn);
4362
+ if (id === void 0) {
4363
+ id = nextLoadModuleId++;
4364
+ loadModuleIds.set(fn, id);
4365
+ }
4366
+ return id;
4367
+ }
4368
+ var moduleMapIds = /* @__PURE__ */ new WeakMap();
4369
+ var moduleMapIdSeq = 0;
4370
+ function moduleMapId(m) {
4371
+ if (!m) return "-";
4372
+ let id = moduleMapIds.get(m);
4373
+ if (id === void 0) {
4374
+ id = ++moduleMapIdSeq;
4375
+ moduleMapIds.set(m, id);
4376
+ }
4377
+ return `m${id}`;
4378
+ }
4379
+
4380
+ // src/algebra/bridge-instance.ts
4381
+ function bareInstanceOf(clsAbs, clsName) {
4382
+ const name = clsAbs.shape.k === "brand" && clsAbs.shape.name.length > 0 ? clsAbs.shape.name : clsName;
4383
+ return abs(
4384
+ {
4385
+ k: "brand",
4386
+ name,
4387
+ shape: abs({ k: "unknown" }, void 0, void 0, "partial")
4388
+ },
4389
+ void 0,
4390
+ void 0,
4391
+ "path"
4392
+ );
4393
+ }
4394
+ function instanceForMethodBridge(clsAbs, clsName, ctorArgs, isolate) {
4395
+ try {
4396
+ return isolate ? isolate(() => $new(clsAbs, ctorArgs)) : $new(clsAbs, ctorArgs);
4397
+ } catch {
4398
+ return bareInstanceOf(clsAbs, clsName);
4399
+ }
4400
+ }
4401
+
4309
4402
  // src/algebra/promote-scan.ts
4310
4403
  var HOF_ARR_METHODS = /* @__PURE__ */ new Set(["map", "filter", "reduce", "flatMap"]);
4311
4404
  function alphaOfTerm(t, ctx) {
@@ -4663,23 +4756,6 @@ function evalRunOf(source, modules, inject, scopeKey) {
4663
4756
  }
4664
4757
  return run;
4665
4758
  }
4666
- function instanceForMethodBridge(clsAbs, clsName, ctorArgs) {
4667
- try {
4668
- return $new(clsAbs, ctorArgs);
4669
- } catch {
4670
- const name = clsAbs.shape.k === "brand" && clsAbs.shape.name.length > 0 ? clsAbs.shape.name : clsName;
4671
- return abs(
4672
- {
4673
- k: "brand",
4674
- name,
4675
- shape: abs({ k: "unknown" }, void 0, void 0, "partial")
4676
- },
4677
- void 0,
4678
- void 0,
4679
- "path"
4680
- );
4681
- }
4682
- }
4683
4759
  function ctorParamCountOf(fileAst, clsName) {
4684
4760
  for (const stmt of fileAst.program.body) {
4685
4761
  if ((stmt.type === "ClassDeclaration" || stmt.type === "ExportNamedDeclaration") && "declaration" in stmt) {
@@ -4769,55 +4845,18 @@ function bodyReferencesName(body, name) {
4769
4845
  visit2(body);
4770
4846
  return found;
4771
4847
  }
4772
- var generalizeMemo = /* @__PURE__ */ new Map();
4773
- var memoKeyDeps = /* @__PURE__ */ new Map();
4774
- var memoDepIndex = /* @__PURE__ */ new Map();
4775
- var loadModuleIds = /* @__PURE__ */ new WeakMap();
4776
- var nextLoadModuleId = 1;
4777
4848
  var MAX_GENERALIZE_MEMO = 1024;
4849
+ var generalizeMemo = new DependencyMemo(MAX_GENERALIZE_MEMO);
4778
4850
  function resetGeneralizeMemo() {
4779
- generalizeMemo.clear();
4780
- memoKeyDeps.clear();
4781
- memoDepIndex.clear();
4851
+ generalizeMemo.reset();
4782
4852
  resetFnFpCache();
4783
4853
  resetHashSourceCache();
4784
4854
  }
4785
4855
  function getGeneralizeMemoSize() {
4786
4856
  return generalizeMemo.size;
4787
4857
  }
4788
- function unindexMemoKey(key) {
4789
- const deps = memoKeyDeps.get(key);
4790
- if (!deps) return;
4791
- for (const p of deps) {
4792
- const set = memoDepIndex.get(p);
4793
- if (!set) continue;
4794
- set.delete(key);
4795
- if (set.size === 0) memoDepIndex.delete(p);
4796
- }
4797
- memoKeyDeps.delete(key);
4798
- }
4799
4858
  function evictGeneralizeMemoForPaths(paths) {
4800
- let n = 0;
4801
- for (const raw of paths) {
4802
- const p = stablePathKey(raw);
4803
- const keys = memoDepIndex.get(p);
4804
- if (!keys) continue;
4805
- for (const key of [...keys]) {
4806
- generalizeMemo.delete(key);
4807
- unindexMemoKey(key);
4808
- n++;
4809
- }
4810
- }
4811
- return n;
4812
- }
4813
- function loadModuleId(fn) {
4814
- if (!fn) return 0;
4815
- let id = loadModuleIds.get(fn);
4816
- if (id === void 0) {
4817
- id = nextLoadModuleId++;
4818
- loadModuleIds.set(fn, id);
4819
- }
4820
- return id;
4859
+ return generalizeMemo.evictForPaths(paths);
4821
4860
  }
4822
4861
  function refineDepsFingerprint(source, refine) {
4823
4862
  if (!refine?.loadModule || !refine.fromFile) {
@@ -4825,17 +4864,6 @@ function refineDepsFingerprint(source, refine) {
4825
4864
  }
4826
4865
  return loadModuleDepsFingerprint(source, refine.loadModule, refine.fromFile);
4827
4866
  }
4828
- var moduleMapIds = /* @__PURE__ */ new WeakMap();
4829
- var moduleMapIdSeq = 0;
4830
- function moduleMapId(m) {
4831
- if (!m) return "-";
4832
- let id = moduleMapIds.get(m);
4833
- if (id === void 0) {
4834
- id = ++moduleMapIdSeq;
4835
- moduleMapIds.set(m, id);
4836
- }
4837
- return `m${id}`;
4838
- }
4839
4867
  function generalizeMemoKey(fnName, source, opts) {
4840
4868
  const r = opts.refine;
4841
4869
  const budget = opts.budget ?? defaultLeakBudget;
@@ -4861,41 +4889,64 @@ function generalizeMemoKey(fnName, source, opts) {
4861
4889
  };
4862
4890
  }
4863
4891
  function generalizeMemoGet(key) {
4864
- if (!generalizeMemo.has(key)) return null;
4865
- const v2 = generalizeMemo.get(key);
4866
- generalizeMemo.delete(key);
4867
- generalizeMemo.set(key, v2);
4868
- return v2;
4892
+ const hit = generalizeMemo.lookup(key);
4893
+ return hit.hit ? hit.value : null;
4869
4894
  }
4870
4895
  function generalizeMemoSet(key, value, depPaths) {
4871
- if (generalizeMemo.size >= MAX_GENERALIZE_MEMO) {
4872
- const oldest = generalizeMemo.keys().next().value;
4873
- if (oldest !== void 0) {
4874
- generalizeMemo.delete(oldest);
4875
- unindexMemoKey(oldest);
4876
- }
4877
- }
4878
- generalizeMemo.set(key, value);
4879
- if (depPaths.length > 0) {
4880
- const normDeps = [...new Set(depPaths.map(stablePathKey))];
4881
- memoKeyDeps.set(key, normDeps);
4882
- for (const p of normDeps) {
4883
- let set = memoDepIndex.get(p);
4884
- if (!set) {
4885
- set = /* @__PURE__ */ new Set();
4886
- memoDepIndex.set(p, set);
4887
- }
4888
- set.add(key);
4889
- }
4890
- }
4896
+ generalizeMemo.set(key, value, depPaths);
4891
4897
  }
4892
4898
  function isCacheableAbs(a) {
4893
4899
  return a.conf === "exact" || a.conf === "path" || a.conf === "widened" || a.conf === "mock";
4894
4900
  }
4901
+ var strictRegionCache = /* @__PURE__ */ new WeakMap();
4902
+ function strictRegionsOf(file) {
4903
+ const cached = strictRegionCache.get(file);
4904
+ if (cached !== void 0) return cached;
4905
+ const out = [];
4906
+ const add = (n) => {
4907
+ if (typeof n.start === "number" && typeof n.end === "number") {
4908
+ out.push({ start: n.start, end: n.end });
4909
+ }
4910
+ };
4911
+ const walk = (n) => {
4912
+ if (n.type === "ClassDeclaration" || n.type === "ClassExpression") {
4913
+ add(n);
4914
+ return;
4915
+ }
4916
+ if (n.type === "BlockStatement" && hasUseStrictDirective(n)) {
4917
+ add(n);
4918
+ return;
4919
+ }
4920
+ for (const key of VISITOR_KEYS[n.type] ?? []) {
4921
+ const child = n[key];
4922
+ if (Array.isArray(child)) {
4923
+ for (const c of child) {
4924
+ if (c && typeof c === "object" && typeof c.type === "string") {
4925
+ walk(c);
4926
+ }
4927
+ }
4928
+ } else if (child && typeof child === "object") {
4929
+ if (typeof child.type === "string") walk(child);
4930
+ }
4931
+ }
4932
+ };
4933
+ walk(file);
4934
+ strictRegionCache.set(file, out);
4935
+ return out;
4936
+ }
4895
4937
  function extractFn(source, fnName, fileAst) {
4896
4938
  const file = fileAst ?? parseSource(source);
4897
4939
  const env = emptyEnv();
4898
4940
  const formalsByName = /* @__PURE__ */ new Map();
4941
+ const fnStrict = sourceIsStrict(source, file);
4942
+ const strictRegions = fnStrict ? [] : strictRegionsOf(file);
4943
+ const inStrictRegion = (node) => {
4944
+ const start = node.start;
4945
+ const end = node.end;
4946
+ if (typeof start !== "number" || typeof end !== "number") return false;
4947
+ return strictRegions.some((r) => start >= r.start && end <= r.end);
4948
+ };
4949
+ const entryStrict = (body) => fnStrict || hasUseStrictDirective(body) || inStrictRegion(body);
4899
4950
  for (const stmt of file.program.body) {
4900
4951
  let decl = stmt;
4901
4952
  if (stmt.type === "ExportNamedDeclaration" && stmt.declaration) {
@@ -4912,7 +4963,8 @@ function extractFn(source, fnName, fileAst) {
4912
4963
  // 不再靠名字后缀猜(默认形参渲染成光秃秃的名字 ⇒ 被计成必选)
4913
4964
  optionalParams: formals.map((f) => f.optional === true),
4914
4965
  body: decl.body,
4915
- async: decl.async === true
4966
+ async: decl.async === true,
4967
+ strict: entryStrict(decl.body)
4916
4968
  });
4917
4969
  formalsByName.set(decl.id.name, formals);
4918
4970
  if (stmt.type === "ExportDefaultDeclaration") {
@@ -4940,7 +4992,10 @@ function extractFn(source, fnName, fileAst) {
4940
4992
  // 不再靠名字后缀猜(默认形参渲染成光秃秃的名字 ⇒ 被计成必选)
4941
4993
  optionalParams: formals.map((f) => f.optional === true),
4942
4994
  body: mem.body,
4943
- async: mem.async === true
4995
+ async: mem.async === true,
4996
+ // class 体恒 strict(原生:类定义整体是 strict mode code,与所在
4997
+ // 文件种类无关)⇒ 方法体内的块级函数声明不得 Annex B 提升。
4998
+ strict: true
4944
4999
  });
4945
5000
  formalsByName.set(fullName, formals);
4946
5001
  }
@@ -4956,7 +5011,8 @@ function extractFn(source, fnName, fileAst) {
4956
5011
  // 不再靠名字后缀猜(默认形参渲染成光秃秃的名字 ⇒ 被计成必选)
4957
5012
  optionalParams: formals.map((f) => f.optional === true),
4958
5013
  body: init.body,
4959
- async: init.async === true
5014
+ async: init.async === true,
5015
+ strict: entryStrict(init.body)
4960
5016
  });
4961
5017
  formalsByName.set(d.id.name, formals);
4962
5018
  }
@@ -4971,7 +5027,8 @@ function extractFn(source, fnName, fileAst) {
4971
5027
  // 不再靠名字后缀猜(默认形参渲染成光秃秃的名字 ⇒ 被计成必选)
4972
5028
  optionalParams: formals.map((f) => f.optional === true),
4973
5029
  body: init.body,
4974
- async: init.async === true
5030
+ async: init.async === true,
5031
+ strict: entryStrict(init.body)
4975
5032
  });
4976
5033
  formalsByName.set("default", formals);
4977
5034
  }
@@ -4988,7 +5045,9 @@ function extractFn(source, fnName, fileAst) {
4988
5045
  // 不再靠名字后缀猜(默认形参渲染成光秃秃的名字 ⇒ 被计成必选)
4989
5046
  optionalParams: formals.map((f) => f.optional === true),
4990
5047
  body: node.body,
4991
- async: node.async === true
5048
+ async: node.async === true,
5049
+ // ClassMethod(防御面)恒 strict;其余按源级 ∨ 函数体指令 ∨ 严格区继承。
5050
+ strict: node.type === "ClassMethod" ? true : entryStrict(node.body)
4992
5051
  });
4993
5052
  formalsByName.set(key, formals);
4994
5053
  };
@@ -5069,6 +5128,7 @@ function extractFn(source, fnName, fileAst) {
5069
5128
  if ((n.type === "ClassMethod" || n.type === "ClassPrivateMethod" || n.type === "ObjectMethod") && n.kind && n.kind !== "method") {
5070
5129
  continue;
5071
5130
  }
5131
+ const isClassMethod = n.type === "ClassMethod" || n.type === "ClassPrivateMethod";
5072
5132
  const formals = formalParamsFromNodes(n.params ?? []);
5073
5133
  env.fns.set(scope.name, {
5074
5134
  params: formalParamDisplayNames(formals),
@@ -5076,7 +5136,8 @@ function extractFn(source, fnName, fileAst) {
5076
5136
  // 不再靠名字后缀猜(默认形参渲染成光秃秃的名字 ⇒ 被计成必选)
5077
5137
  optionalParams: formals.map((f) => f.optional === true),
5078
5138
  body: n.body,
5079
- async: n.async === true
5139
+ async: n.async === true,
5140
+ strict: isClassMethod ? true : entryStrict(n.body)
5080
5141
  });
5081
5142
  formalsByName.set(scope.name, formals);
5082
5143
  }
@@ -5279,7 +5340,8 @@ function generalizeFromAstUncached(fnName, source, opts = {}) {
5279
5340
  const boundNames = formals.flatMap(
5280
5341
  (f) => f.kind === "pattern" ? f.bound : [f.name]
5281
5342
  );
5282
- const envGated = envGatedSource && freeIdentifiers(body, boundNames).size > 0;
5343
+ const fnBodyStrict = env.fns.get(fnName)?.strict === true;
5344
+ const envGated = envGatedSource && freeIdentifiers(body, boundNames, fnBodyStrict).size > 0;
5283
5345
  const replaceGated = /@nudo:replace\b/.test(directiveSrc) && !hasReps;
5284
5346
  const evalEligible = !unresolvableImports && !mockGated && !envGated && !replaceGated;
5285
5347
  const fnBudget = extractFnBudget(source, fnName);
@@ -5322,7 +5384,7 @@ function generalizeFromAstUncached(fnName, source, opts = {}) {
5322
5384
  }
5323
5385
  return a;
5324
5386
  });
5325
- return callTranspiledExportFull(evalRun, fnName, evalArgs, { phi }).result;
5387
+ return callTranspiledExportFull(evalRun, fnName, evalArgs, { phi, preferLocal: true }).result;
5326
5388
  } else {
5327
5389
  const slot = resolveExportSlotCall(fileAst, fnName, evalRun);
5328
5390
  if (!slot) return void 0;
@@ -5340,7 +5402,10 @@ function generalizeFromAstUncached(fnName, source, opts = {}) {
5340
5402
  if (dAbs.shape.k !== "obj") return void 0;
5341
5403
  return withExecPhi(phi, () => $invoke(dAbs, slot.member, evalArgs));
5342
5404
  }
5343
- return callTranspiledExportFull(evalRun, slot.key, evalArgs, { phi }).result;
5405
+ return callTranspiledExportFull(evalRun, slot.key, evalArgs, {
5406
+ phi,
5407
+ preferLocal: true
5408
+ }).result;
5344
5409
  }
5345
5410
  } catch (e) {
5346
5411
  noteEvalFallback(e);
@@ -5462,26 +5527,6 @@ function formatPoly(name, renderNames, params, typeParams, symbolic, entryReqs,
5462
5527
  const predPart = symbolic.pred && symbolic.pred.op !== "true" ? ` where ${predToString(symbolic.pred)}` : "";
5463
5528
  return `${name}: (${ps}) => ${ret}${predPart}`;
5464
5529
  }
5465
- function generalizeAll(source, opts = {}) {
5466
- const file = parseSource(source);
5467
- const names = [];
5468
- for (const stmt of file.program.body) {
5469
- if (stmt.type === "FunctionDeclaration" && stmt.id) names.push(stmt.id.name);
5470
- if (stmt.type === "VariableDeclaration") {
5471
- for (const d of stmt.declarations) {
5472
- if (d.id.type === "Identifier" && d.init && (d.init.type === "ArrowFunctionExpression" || d.init.type === "FunctionExpression")) {
5473
- names.push(d.id.name);
5474
- }
5475
- }
5476
- }
5477
- }
5478
- const out = [];
5479
- for (const n of names) {
5480
- const g = generalizeFromAst(n, source, opts);
5481
- if (g) out.push(g);
5482
- }
5483
- return out;
5484
- }
5485
5530
  function listFunctionNames(source) {
5486
5531
  const file = parseSource(source);
5487
5532
  const names = [];
@@ -7282,8 +7327,22 @@ function defaultArgAbss(fnName, source, fileAst, lookupVar) {
7282
7327
  return { values: out, defaulted };
7283
7328
  }
7284
7329
 
7330
+ // src/algebra/scan/path-projection.ts
7331
+ function projectAbsPath(arg, segments) {
7332
+ let cur = arg;
7333
+ for (const seg of segments) {
7334
+ if (!cur) return void 0;
7335
+ if (cur.shape.k === "brand") {
7336
+ cur = cur.shape.shape;
7337
+ }
7338
+ if (cur.shape.k !== "obj") return void 0;
7339
+ cur = getSlot(cur.shape.slots, seg)?.value;
7340
+ }
7341
+ return cur;
7342
+ }
7343
+
7285
7344
  // src/algebra/scan/literal-preds.ts
7286
- function isExactUndef(a) {
7345
+ function isNullishLitAbs(a) {
7287
7346
  return a.term?.op === "lit" && (a.term.value === void 0 || a.term.value === null);
7288
7347
  }
7289
7348
  function nullishKindOf(a) {
@@ -7405,7 +7464,7 @@ function argTypeofName(arg) {
7405
7464
  if (sh.k === "prim") return sh.type;
7406
7465
  if (sh.k === "obj" || sh.k === "arr" || sh.k === "tuple") return "object";
7407
7466
  if (sh.k === "fn") return "function";
7408
- return isExactUndef(arg) ? "undefined" : void 0;
7467
+ return isNullishLitAbs(arg) ? "undefined" : void 0;
7409
7468
  }
7410
7469
  function predOnVar(p) {
7411
7470
  switch (p.op) {
@@ -7495,18 +7554,6 @@ function judgeOrUnion(or, arg, argLen) {
7495
7554
  if (undecided) return void 0;
7496
7555
  return hasFalse ? false : void 0;
7497
7556
  }
7498
- function projectArgPath(arg, segments) {
7499
- let cur = arg;
7500
- for (const seg of segments) {
7501
- if (!cur) return void 0;
7502
- if (cur.shape.k === "brand") {
7503
- cur = cur.shape.shape;
7504
- }
7505
- if (cur.shape.k !== "obj") return void 0;
7506
- cur = getSlot(cur.shape.slots, seg)?.value;
7507
- }
7508
- return cur;
7509
- }
7510
7557
  function checkReqs(ctx, displayName, reqs, paramNames, absArgs, argIndexOf, loc, skipParams) {
7511
7558
  const out = ctx.out;
7512
7559
  for (const [idx, pred, fieldPath, contractParam, rest] of reqs) {
@@ -7518,7 +7565,7 @@ function checkReqs(ctx, displayName, reqs, paramNames, absArgs, argIndexOf, loc,
7518
7565
  if (rest) arg = restArgAbs(absArgs.slice(argIdx));
7519
7566
  const paramName = contractParam || paramNames[idx] || `arg${idx}`;
7520
7567
  if (fieldPath) {
7521
- const projected = projectArgPath(arg, fieldPath);
7568
+ const projected = projectAbsPath(arg, fieldPath);
7522
7569
  if (!projected) {
7523
7570
  const k = arg.shape.k;
7524
7571
  if (k !== "unknown" && k !== "any") {
@@ -7543,7 +7590,7 @@ function checkReqs(ctx, displayName, reqs, paramNames, absArgs, argIndexOf, loc,
7543
7590
  const lv = lvR.ok ? lvR.value : void 0;
7544
7591
  const isStr = arg.shape.k === "prim" && arg.shape.type === "string";
7545
7592
  const argLen = typeof lv === "string" ? lv.length : arrayLengthOf(arg);
7546
- const argIsUndef = isExactUndef(arg);
7593
+ const argIsUndef = isNullishLitAbs(arg);
7547
7594
  const flat = flattenPred(pred);
7548
7595
  const hasVarTypeof = flat.some((q) => q.op === "typeof" && q.t.op === "var");
7549
7596
  let typeofReported = false;
@@ -7955,7 +8002,7 @@ function checkShapeReqs(ctx, displayName, reqs, paramNames, absArgs, argIndexOf,
7955
8002
  }
7956
8003
  const paramName = entry.param || paramNames[idx] || `arg${idx}`;
7957
8004
  if (fieldPath) {
7958
- const projected = projectArgPath(arg, fieldPath);
8005
+ const projected = projectAbsPath(arg, fieldPath);
7959
8006
  if (!projected) {
7960
8007
  continue;
7961
8008
  }
@@ -7996,7 +8043,7 @@ function checkShapeReqs(ctx, displayName, reqs, paramNames, absArgs, argIndexOf,
7996
8043
  restAgg
7997
8044
  );
7998
8045
  });
7999
- } else if (isExactUndef(arg) || arg.shape.k !== "unknown" && arg.shape.k !== "any") {
8046
+ } else if (isNullishLitAbs(arg) || arg.shape.k !== "unknown" && arg.shape.k !== "any") {
8000
8047
  out.push({
8001
8048
  severity: "error",
8002
8049
  code: DIAG.constraintViolated,
@@ -9018,6 +9065,10 @@ export {
9018
9065
  extractAllLoadSpecs,
9019
9066
  sidecarSpecsOf,
9020
9067
  loadModuleDepsFingerprint,
9068
+ DependencyMemo,
9069
+ loadModuleId,
9070
+ moduleMapId,
9071
+ instanceForMethodBridge,
9021
9072
  resolveExportSlotCall,
9022
9073
  collectAbsFreeVars,
9023
9074
  ctorParamCountOf,
@@ -9026,7 +9077,6 @@ export {
9026
9077
  evictGeneralizeMemoForPaths,
9027
9078
  extractFn,
9028
9079
  generalizeFromAst,
9029
- generalizeAll,
9030
9080
  listFunctionNames,
9031
9081
  buildArgsFromAssume,
9032
9082
  checkArg,
@@ -9036,6 +9086,7 @@ export {
9036
9086
  guardLoadModule,
9037
9087
  listTopFunctions,
9038
9088
  listClassEntryNames,
9089
+ projectAbsPath,
9039
9090
  scanLiteralCalls,
9040
9091
  checkInjectedDomainEvidence,
9041
9092
  absWithStableTermIds,