@nudojs/core 1.16.0 → 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.
@@ -6,6 +6,7 @@ import {
6
6
  LAZY_TEMPLATE_DEPTH,
7
7
  TYPEOF_NAMES,
8
8
  abs,
9
+ absKey,
9
10
  absLit,
10
11
  and,
11
12
  andC,
@@ -32,6 +33,7 @@ import {
32
33
  freeIdentifiers,
33
34
  getFnImpl,
34
35
  getSlot,
36
+ hasUseStrictDirective,
35
37
  identBoundaryRegex,
36
38
  implies,
37
39
  instantiateConstraint,
@@ -50,10 +52,12 @@ import {
50
52
  numLit,
51
53
  pTrue,
52
54
  parseSource,
55
+ predKey,
53
56
  predToString,
54
57
  registerCollectorScopeParticipant,
55
58
  runTranspiledOptionsMemoKey,
56
59
  snapshotAbs,
60
+ sourceIsStrict,
57
61
  stripStringsKeepComments,
58
62
  termEquals,
59
63
  termToString,
@@ -65,7 +69,7 @@ import {
65
69
  withExecPhi,
66
70
  withFnBudgetOverride,
67
71
  withOptionalParams
68
- } from "./chunk-OM6SAY2M.js";
72
+ } from "./chunk-ARIQO5XX.js";
69
73
 
70
74
  // src/algebra/directive-scan.ts
71
75
  function cleanDirectiveLine(raw, kind) {
@@ -4031,87 +4035,8 @@ function loadModuleDepsFingerprint(source, loadModule, fromFile, opts) {
4031
4035
  }
4032
4036
 
4033
4037
  // 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
4038
  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}`;
4039
+ return absKey(a, seen, rename);
4115
4040
  }
4116
4041
  function collectTermVars(t, acc) {
4117
4042
  if (t.op === "var") acc.add(t.id);
@@ -4239,43 +4164,58 @@ function renameShape(s, map) {
4239
4164
  case "prim":
4240
4165
  return s;
4241
4166
  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) };
4167
+ return { ...s, shape: renameAbs(s.shape, map) };
4168
+ case "eff": {
4169
+ const out = { ...s, inner: renameAbs(s.inner, map) };
4170
+ if (s.rejected) out.rejected = renameAbs(s.rejected, map);
4171
+ return out;
4172
+ }
4245
4173
  case "arr":
4246
- return { k: "arr", element: renameAbs(s.element, map) };
4174
+ return { ...s, element: renameAbs(s.element, map) };
4247
4175
  case "tuple": {
4248
4176
  const out = {
4249
- k: "tuple",
4177
+ ...s,
4250
4178
  elements: s.elements.map((e) => renameAbs(e, map))
4251
4179
  };
4252
4180
  if (s.rest) out.rest = renameAbs(s.rest, map);
4181
+ if (s.holes) out.holes = [...s.holes];
4253
4182
  return out;
4254
4183
  }
4255
4184
  case "fn": {
4256
- const out = { k: "fn", params: s.params };
4257
- if (s.name !== void 0) out.name = s.name;
4185
+ const out = { ...s, params: [...s.params] };
4258
4186
  if (s.paramTypes) out.paramTypes = s.paramTypes.map((t) => renameAbs(t, map));
4259
4187
  if (s.returnType) out.returnType = renameAbs(s.returnType, map);
4260
- if (s.ctor !== void 0) out.ctor = s.ctor;
4188
+ if (s.optionalParams) out.optionalParams = [...s.optionalParams];
4189
+ if (s.slots) {
4190
+ const slots = {};
4191
+ for (const [k, slot] of Object.entries(s.slots)) {
4192
+ Object.defineProperty(slots, k, {
4193
+ value: { ...slot, value: renameAbs(slot.value, map) },
4194
+ enumerable: true,
4195
+ writable: true,
4196
+ configurable: true
4197
+ });
4198
+ }
4199
+ out.slots = slots;
4200
+ }
4261
4201
  return out;
4262
4202
  }
4263
4203
  case "sum":
4264
- return { k: "sum", members: s.members.map((m) => renameAbs(m, map)) };
4204
+ return { ...s, members: s.members.map((m) => renameAbs(m, map)) };
4265
4205
  case "obj": {
4266
4206
  const slots = {};
4267
4207
  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
- };
4208
+ Object.defineProperty(slots, k, {
4209
+ value: { ...slot, value: renameAbs(slot.value, map) },
4210
+ enumerable: true,
4211
+ writable: true,
4212
+ configurable: true
4213
+ });
4273
4214
  }
4274
- const out = { k: "obj", slots };
4215
+ const out = { ...s, slots };
4275
4216
  if (s.index) {
4276
4217
  out.index = { key: renameAbs(s.index.key, map), value: renameAbs(s.index.value, map) };
4277
4218
  }
4278
- if (s.open) out.open = true;
4279
4219
  return out;
4280
4220
  }
4281
4221
  }
@@ -4306,6 +4246,130 @@ function alphaRenameResult(result, fromOrder, toOrder) {
4306
4246
  return renameAbs(result, map);
4307
4247
  }
4308
4248
 
4249
+ // src/algebra/generalize.ts
4250
+ import { VISITOR_KEYS } from "@babel/types";
4251
+
4252
+ // src/algebra/memo-store.ts
4253
+ var DependencyMemo = class {
4254
+ constructor(max) {
4255
+ this.max = max;
4256
+ }
4257
+ max;
4258
+ values = /* @__PURE__ */ new Map();
4259
+ keyDeps = /* @__PURE__ */ new Map();
4260
+ depIndex = /* @__PURE__ */ new Map();
4261
+ get size() {
4262
+ return this.values.size;
4263
+ }
4264
+ /** 命中 ⇒ 移到队尾(LRU 刷新);`hit` 区分存了 undefined 与 miss */
4265
+ lookup(key) {
4266
+ if (!this.values.has(key)) return { hit: false };
4267
+ const value = this.values.get(key);
4268
+ this.values.delete(key);
4269
+ this.values.set(key, value);
4270
+ return { hit: true, value };
4271
+ }
4272
+ set(key, value, depPaths) {
4273
+ if (!this.values.has(key) && this.values.size >= this.max) {
4274
+ const oldest = this.values.keys().next().value;
4275
+ if (oldest !== void 0) {
4276
+ this.values.delete(oldest);
4277
+ this.unindex(oldest);
4278
+ }
4279
+ }
4280
+ this.values.set(key, value);
4281
+ if (depPaths.length > 0) {
4282
+ const normDeps = [...new Set(depPaths.map(stablePathKey))];
4283
+ this.keyDeps.set(key, normDeps);
4284
+ for (const p of normDeps) {
4285
+ let set = this.depIndex.get(p);
4286
+ if (!set) {
4287
+ set = /* @__PURE__ */ new Set();
4288
+ this.depIndex.set(p, set);
4289
+ }
4290
+ set.add(key);
4291
+ }
4292
+ }
4293
+ }
4294
+ /** 定向逐出依赖这些路径的条目;返回删除数。查找与索引同走 stablePathKey */
4295
+ evictForPaths(paths) {
4296
+ let n = 0;
4297
+ for (const raw of paths) {
4298
+ const p = stablePathKey(raw);
4299
+ const keys = this.depIndex.get(p);
4300
+ if (!keys) continue;
4301
+ for (const key of [...keys]) {
4302
+ this.values.delete(key);
4303
+ this.unindex(key);
4304
+ n++;
4305
+ }
4306
+ }
4307
+ return n;
4308
+ }
4309
+ reset() {
4310
+ this.values.clear();
4311
+ this.keyDeps.clear();
4312
+ this.depIndex.clear();
4313
+ }
4314
+ unindex(key) {
4315
+ const deps = this.keyDeps.get(key);
4316
+ if (!deps) return;
4317
+ for (const p of deps) {
4318
+ const set = this.depIndex.get(p);
4319
+ if (!set) continue;
4320
+ set.delete(key);
4321
+ if (set.size === 0) this.depIndex.delete(p);
4322
+ }
4323
+ this.keyDeps.delete(key);
4324
+ }
4325
+ };
4326
+
4327
+ // src/algebra/memo-identity.ts
4328
+ var loadModuleIds = /* @__PURE__ */ new WeakMap();
4329
+ var nextLoadModuleId = 1;
4330
+ function loadModuleId(fn) {
4331
+ if (!fn) return 0;
4332
+ let id = loadModuleIds.get(fn);
4333
+ if (id === void 0) {
4334
+ id = nextLoadModuleId++;
4335
+ loadModuleIds.set(fn, id);
4336
+ }
4337
+ return id;
4338
+ }
4339
+ var moduleMapIds = /* @__PURE__ */ new WeakMap();
4340
+ var moduleMapIdSeq = 0;
4341
+ function moduleMapId(m) {
4342
+ if (!m) return "-";
4343
+ let id = moduleMapIds.get(m);
4344
+ if (id === void 0) {
4345
+ id = ++moduleMapIdSeq;
4346
+ moduleMapIds.set(m, id);
4347
+ }
4348
+ return `m${id}`;
4349
+ }
4350
+
4351
+ // src/algebra/bridge-instance.ts
4352
+ function bareInstanceOf(clsAbs, clsName) {
4353
+ const name = clsAbs.shape.k === "brand" && clsAbs.shape.name.length > 0 ? clsAbs.shape.name : clsName;
4354
+ return abs(
4355
+ {
4356
+ k: "brand",
4357
+ name,
4358
+ shape: abs({ k: "unknown" }, void 0, void 0, "partial")
4359
+ },
4360
+ void 0,
4361
+ void 0,
4362
+ "path"
4363
+ );
4364
+ }
4365
+ function instanceForMethodBridge(clsAbs, clsName, ctorArgs, isolate) {
4366
+ try {
4367
+ return isolate ? isolate(() => $new(clsAbs, ctorArgs)) : $new(clsAbs, ctorArgs);
4368
+ } catch {
4369
+ return bareInstanceOf(clsAbs, clsName);
4370
+ }
4371
+ }
4372
+
4309
4373
  // src/algebra/promote-scan.ts
4310
4374
  var HOF_ARR_METHODS = /* @__PURE__ */ new Set(["map", "filter", "reduce", "flatMap"]);
4311
4375
  function alphaOfTerm(t, ctx) {
@@ -4663,23 +4727,6 @@ function evalRunOf(source, modules, inject, scopeKey) {
4663
4727
  }
4664
4728
  return run;
4665
4729
  }
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
4730
  function ctorParamCountOf(fileAst, clsName) {
4684
4731
  for (const stmt of fileAst.program.body) {
4685
4732
  if ((stmt.type === "ClassDeclaration" || stmt.type === "ExportNamedDeclaration") && "declaration" in stmt) {
@@ -4769,55 +4816,18 @@ function bodyReferencesName(body, name) {
4769
4816
  visit2(body);
4770
4817
  return found;
4771
4818
  }
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
4819
  var MAX_GENERALIZE_MEMO = 1024;
4820
+ var generalizeMemo = new DependencyMemo(MAX_GENERALIZE_MEMO);
4778
4821
  function resetGeneralizeMemo() {
4779
- generalizeMemo.clear();
4780
- memoKeyDeps.clear();
4781
- memoDepIndex.clear();
4822
+ generalizeMemo.reset();
4782
4823
  resetFnFpCache();
4783
4824
  resetHashSourceCache();
4784
4825
  }
4785
4826
  function getGeneralizeMemoSize() {
4786
4827
  return generalizeMemo.size;
4787
4828
  }
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
4829
  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;
4830
+ return generalizeMemo.evictForPaths(paths);
4821
4831
  }
4822
4832
  function refineDepsFingerprint(source, refine) {
4823
4833
  if (!refine?.loadModule || !refine.fromFile) {
@@ -4825,17 +4835,6 @@ function refineDepsFingerprint(source, refine) {
4825
4835
  }
4826
4836
  return loadModuleDepsFingerprint(source, refine.loadModule, refine.fromFile);
4827
4837
  }
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
4838
  function generalizeMemoKey(fnName, source, opts) {
4840
4839
  const r = opts.refine;
4841
4840
  const budget = opts.budget ?? defaultLeakBudget;
@@ -4861,41 +4860,64 @@ function generalizeMemoKey(fnName, source, opts) {
4861
4860
  };
4862
4861
  }
4863
4862
  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;
4863
+ const hit = generalizeMemo.lookup(key);
4864
+ return hit.hit ? hit.value : null;
4869
4865
  }
4870
4866
  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
- }
4867
+ generalizeMemo.set(key, value, depPaths);
4891
4868
  }
4892
4869
  function isCacheableAbs(a) {
4893
4870
  return a.conf === "exact" || a.conf === "path" || a.conf === "widened" || a.conf === "mock";
4894
4871
  }
4872
+ var strictRegionCache = /* @__PURE__ */ new WeakMap();
4873
+ function strictRegionsOf(file) {
4874
+ const cached = strictRegionCache.get(file);
4875
+ if (cached !== void 0) return cached;
4876
+ const out = [];
4877
+ const add = (n) => {
4878
+ if (typeof n.start === "number" && typeof n.end === "number") {
4879
+ out.push({ start: n.start, end: n.end });
4880
+ }
4881
+ };
4882
+ const walk = (n) => {
4883
+ if (n.type === "ClassDeclaration" || n.type === "ClassExpression") {
4884
+ add(n);
4885
+ return;
4886
+ }
4887
+ if (n.type === "BlockStatement" && hasUseStrictDirective(n)) {
4888
+ add(n);
4889
+ return;
4890
+ }
4891
+ for (const key of VISITOR_KEYS[n.type] ?? []) {
4892
+ const child = n[key];
4893
+ if (Array.isArray(child)) {
4894
+ for (const c of child) {
4895
+ if (c && typeof c === "object" && typeof c.type === "string") {
4896
+ walk(c);
4897
+ }
4898
+ }
4899
+ } else if (child && typeof child === "object") {
4900
+ if (typeof child.type === "string") walk(child);
4901
+ }
4902
+ }
4903
+ };
4904
+ walk(file);
4905
+ strictRegionCache.set(file, out);
4906
+ return out;
4907
+ }
4895
4908
  function extractFn(source, fnName, fileAst) {
4896
4909
  const file = fileAst ?? parseSource(source);
4897
4910
  const env = emptyEnv();
4898
4911
  const formalsByName = /* @__PURE__ */ new Map();
4912
+ const fnStrict = sourceIsStrict(source, file);
4913
+ const strictRegions = fnStrict ? [] : strictRegionsOf(file);
4914
+ const inStrictRegion = (node) => {
4915
+ const start = node.start;
4916
+ const end = node.end;
4917
+ if (typeof start !== "number" || typeof end !== "number") return false;
4918
+ return strictRegions.some((r) => start >= r.start && end <= r.end);
4919
+ };
4920
+ const entryStrict = (body) => fnStrict || hasUseStrictDirective(body) || inStrictRegion(body);
4899
4921
  for (const stmt of file.program.body) {
4900
4922
  let decl = stmt;
4901
4923
  if (stmt.type === "ExportNamedDeclaration" && stmt.declaration) {
@@ -4912,7 +4934,8 @@ function extractFn(source, fnName, fileAst) {
4912
4934
  // 不再靠名字后缀猜(默认形参渲染成光秃秃的名字 ⇒ 被计成必选)
4913
4935
  optionalParams: formals.map((f) => f.optional === true),
4914
4936
  body: decl.body,
4915
- async: decl.async === true
4937
+ async: decl.async === true,
4938
+ strict: entryStrict(decl.body)
4916
4939
  });
4917
4940
  formalsByName.set(decl.id.name, formals);
4918
4941
  if (stmt.type === "ExportDefaultDeclaration") {
@@ -4940,7 +4963,10 @@ function extractFn(source, fnName, fileAst) {
4940
4963
  // 不再靠名字后缀猜(默认形参渲染成光秃秃的名字 ⇒ 被计成必选)
4941
4964
  optionalParams: formals.map((f) => f.optional === true),
4942
4965
  body: mem.body,
4943
- async: mem.async === true
4966
+ async: mem.async === true,
4967
+ // class 体恒 strict(原生:类定义整体是 strict mode code,与所在
4968
+ // 文件种类无关)⇒ 方法体内的块级函数声明不得 Annex B 提升。
4969
+ strict: true
4944
4970
  });
4945
4971
  formalsByName.set(fullName, formals);
4946
4972
  }
@@ -4956,7 +4982,8 @@ function extractFn(source, fnName, fileAst) {
4956
4982
  // 不再靠名字后缀猜(默认形参渲染成光秃秃的名字 ⇒ 被计成必选)
4957
4983
  optionalParams: formals.map((f) => f.optional === true),
4958
4984
  body: init.body,
4959
- async: init.async === true
4985
+ async: init.async === true,
4986
+ strict: entryStrict(init.body)
4960
4987
  });
4961
4988
  formalsByName.set(d.id.name, formals);
4962
4989
  }
@@ -4971,7 +4998,8 @@ function extractFn(source, fnName, fileAst) {
4971
4998
  // 不再靠名字后缀猜(默认形参渲染成光秃秃的名字 ⇒ 被计成必选)
4972
4999
  optionalParams: formals.map((f) => f.optional === true),
4973
5000
  body: init.body,
4974
- async: init.async === true
5001
+ async: init.async === true,
5002
+ strict: entryStrict(init.body)
4975
5003
  });
4976
5004
  formalsByName.set("default", formals);
4977
5005
  }
@@ -4988,7 +5016,9 @@ function extractFn(source, fnName, fileAst) {
4988
5016
  // 不再靠名字后缀猜(默认形参渲染成光秃秃的名字 ⇒ 被计成必选)
4989
5017
  optionalParams: formals.map((f) => f.optional === true),
4990
5018
  body: node.body,
4991
- async: node.async === true
5019
+ async: node.async === true,
5020
+ // ClassMethod(防御面)恒 strict;其余按源级 ∨ 函数体指令 ∨ 严格区继承。
5021
+ strict: node.type === "ClassMethod" ? true : entryStrict(node.body)
4992
5022
  });
4993
5023
  formalsByName.set(key, formals);
4994
5024
  };
@@ -5069,6 +5099,7 @@ function extractFn(source, fnName, fileAst) {
5069
5099
  if ((n.type === "ClassMethod" || n.type === "ClassPrivateMethod" || n.type === "ObjectMethod") && n.kind && n.kind !== "method") {
5070
5100
  continue;
5071
5101
  }
5102
+ const isClassMethod = n.type === "ClassMethod" || n.type === "ClassPrivateMethod";
5072
5103
  const formals = formalParamsFromNodes(n.params ?? []);
5073
5104
  env.fns.set(scope.name, {
5074
5105
  params: formalParamDisplayNames(formals),
@@ -5076,7 +5107,8 @@ function extractFn(source, fnName, fileAst) {
5076
5107
  // 不再靠名字后缀猜(默认形参渲染成光秃秃的名字 ⇒ 被计成必选)
5077
5108
  optionalParams: formals.map((f) => f.optional === true),
5078
5109
  body: n.body,
5079
- async: n.async === true
5110
+ async: n.async === true,
5111
+ strict: isClassMethod ? true : entryStrict(n.body)
5080
5112
  });
5081
5113
  formalsByName.set(scope.name, formals);
5082
5114
  }
@@ -5279,7 +5311,8 @@ function generalizeFromAstUncached(fnName, source, opts = {}) {
5279
5311
  const boundNames = formals.flatMap(
5280
5312
  (f) => f.kind === "pattern" ? f.bound : [f.name]
5281
5313
  );
5282
- const envGated = envGatedSource && freeIdentifiers(body, boundNames).size > 0;
5314
+ const fnBodyStrict = env.fns.get(fnName)?.strict === true;
5315
+ const envGated = envGatedSource && freeIdentifiers(body, boundNames, fnBodyStrict).size > 0;
5283
5316
  const replaceGated = /@nudo:replace\b/.test(directiveSrc) && !hasReps;
5284
5317
  const evalEligible = !unresolvableImports && !mockGated && !envGated && !replaceGated;
5285
5318
  const fnBudget = extractFnBudget(source, fnName);
@@ -5322,7 +5355,7 @@ function generalizeFromAstUncached(fnName, source, opts = {}) {
5322
5355
  }
5323
5356
  return a;
5324
5357
  });
5325
- return callTranspiledExportFull(evalRun, fnName, evalArgs, { phi }).result;
5358
+ return callTranspiledExportFull(evalRun, fnName, evalArgs, { phi, preferLocal: true }).result;
5326
5359
  } else {
5327
5360
  const slot = resolveExportSlotCall(fileAst, fnName, evalRun);
5328
5361
  if (!slot) return void 0;
@@ -5340,7 +5373,10 @@ function generalizeFromAstUncached(fnName, source, opts = {}) {
5340
5373
  if (dAbs.shape.k !== "obj") return void 0;
5341
5374
  return withExecPhi(phi, () => $invoke(dAbs, slot.member, evalArgs));
5342
5375
  }
5343
- return callTranspiledExportFull(evalRun, slot.key, evalArgs, { phi }).result;
5376
+ return callTranspiledExportFull(evalRun, slot.key, evalArgs, {
5377
+ phi,
5378
+ preferLocal: true
5379
+ }).result;
5344
5380
  }
5345
5381
  } catch (e) {
5346
5382
  noteEvalFallback(e);
@@ -5462,26 +5498,6 @@ function formatPoly(name, renderNames, params, typeParams, symbolic, entryReqs,
5462
5498
  const predPart = symbolic.pred && symbolic.pred.op !== "true" ? ` where ${predToString(symbolic.pred)}` : "";
5463
5499
  return `${name}: (${ps}) => ${ret}${predPart}`;
5464
5500
  }
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
5501
  function listFunctionNames(source) {
5486
5502
  const file = parseSource(source);
5487
5503
  const names = [];
@@ -7282,8 +7298,22 @@ function defaultArgAbss(fnName, source, fileAst, lookupVar) {
7282
7298
  return { values: out, defaulted };
7283
7299
  }
7284
7300
 
7301
+ // src/algebra/scan/path-projection.ts
7302
+ function projectAbsPath(arg, segments) {
7303
+ let cur = arg;
7304
+ for (const seg of segments) {
7305
+ if (!cur) return void 0;
7306
+ if (cur.shape.k === "brand") {
7307
+ cur = cur.shape.shape;
7308
+ }
7309
+ if (cur.shape.k !== "obj") return void 0;
7310
+ cur = getSlot(cur.shape.slots, seg)?.value;
7311
+ }
7312
+ return cur;
7313
+ }
7314
+
7285
7315
  // src/algebra/scan/literal-preds.ts
7286
- function isExactUndef(a) {
7316
+ function isNullishLitAbs(a) {
7287
7317
  return a.term?.op === "lit" && (a.term.value === void 0 || a.term.value === null);
7288
7318
  }
7289
7319
  function nullishKindOf(a) {
@@ -7405,7 +7435,7 @@ function argTypeofName(arg) {
7405
7435
  if (sh.k === "prim") return sh.type;
7406
7436
  if (sh.k === "obj" || sh.k === "arr" || sh.k === "tuple") return "object";
7407
7437
  if (sh.k === "fn") return "function";
7408
- return isExactUndef(arg) ? "undefined" : void 0;
7438
+ return isNullishLitAbs(arg) ? "undefined" : void 0;
7409
7439
  }
7410
7440
  function predOnVar(p) {
7411
7441
  switch (p.op) {
@@ -7495,18 +7525,6 @@ function judgeOrUnion(or, arg, argLen) {
7495
7525
  if (undecided) return void 0;
7496
7526
  return hasFalse ? false : void 0;
7497
7527
  }
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
7528
  function checkReqs(ctx, displayName, reqs, paramNames, absArgs, argIndexOf, loc, skipParams) {
7511
7529
  const out = ctx.out;
7512
7530
  for (const [idx, pred, fieldPath, contractParam, rest] of reqs) {
@@ -7518,7 +7536,7 @@ function checkReqs(ctx, displayName, reqs, paramNames, absArgs, argIndexOf, loc,
7518
7536
  if (rest) arg = restArgAbs(absArgs.slice(argIdx));
7519
7537
  const paramName = contractParam || paramNames[idx] || `arg${idx}`;
7520
7538
  if (fieldPath) {
7521
- const projected = projectArgPath(arg, fieldPath);
7539
+ const projected = projectAbsPath(arg, fieldPath);
7522
7540
  if (!projected) {
7523
7541
  const k = arg.shape.k;
7524
7542
  if (k !== "unknown" && k !== "any") {
@@ -7543,7 +7561,7 @@ function checkReqs(ctx, displayName, reqs, paramNames, absArgs, argIndexOf, loc,
7543
7561
  const lv = lvR.ok ? lvR.value : void 0;
7544
7562
  const isStr = arg.shape.k === "prim" && arg.shape.type === "string";
7545
7563
  const argLen = typeof lv === "string" ? lv.length : arrayLengthOf(arg);
7546
- const argIsUndef = isExactUndef(arg);
7564
+ const argIsUndef = isNullishLitAbs(arg);
7547
7565
  const flat = flattenPred(pred);
7548
7566
  const hasVarTypeof = flat.some((q) => q.op === "typeof" && q.t.op === "var");
7549
7567
  let typeofReported = false;
@@ -7955,7 +7973,7 @@ function checkShapeReqs(ctx, displayName, reqs, paramNames, absArgs, argIndexOf,
7955
7973
  }
7956
7974
  const paramName = entry.param || paramNames[idx] || `arg${idx}`;
7957
7975
  if (fieldPath) {
7958
- const projected = projectArgPath(arg, fieldPath);
7976
+ const projected = projectAbsPath(arg, fieldPath);
7959
7977
  if (!projected) {
7960
7978
  continue;
7961
7979
  }
@@ -7996,7 +8014,7 @@ function checkShapeReqs(ctx, displayName, reqs, paramNames, absArgs, argIndexOf,
7996
8014
  restAgg
7997
8015
  );
7998
8016
  });
7999
- } else if (isExactUndef(arg) || arg.shape.k !== "unknown" && arg.shape.k !== "any") {
8017
+ } else if (isNullishLitAbs(arg) || arg.shape.k !== "unknown" && arg.shape.k !== "any") {
8000
8018
  out.push({
8001
8019
  severity: "error",
8002
8020
  code: DIAG.constraintViolated,
@@ -9018,6 +9036,10 @@ export {
9018
9036
  extractAllLoadSpecs,
9019
9037
  sidecarSpecsOf,
9020
9038
  loadModuleDepsFingerprint,
9039
+ DependencyMemo,
9040
+ loadModuleId,
9041
+ moduleMapId,
9042
+ instanceForMethodBridge,
9021
9043
  resolveExportSlotCall,
9022
9044
  collectAbsFreeVars,
9023
9045
  ctorParamCountOf,
@@ -9026,7 +9048,6 @@ export {
9026
9048
  evictGeneralizeMemoForPaths,
9027
9049
  extractFn,
9028
9050
  generalizeFromAst,
9029
- generalizeAll,
9030
9051
  listFunctionNames,
9031
9052
  buildArgsFromAssume,
9032
9053
  checkArg,
@@ -9036,6 +9057,7 @@ export {
9036
9057
  guardLoadModule,
9037
9058
  listTopFunctions,
9038
9059
  listClassEntryNames,
9060
+ projectAbsPath,
9039
9061
  scanLiteralCalls,
9040
9062
  checkInjectedDomainEvidence,
9041
9063
  absWithStableTermIds,