@nudojs/core 1.9.4 → 1.10.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.
@@ -47,7 +47,7 @@ import {
47
47
  withEvalBudgetOverride,
48
48
  withExecPhi,
49
49
  withFnBudgetOverride
50
- } from "./chunk-PGTNSUTE.js";
50
+ } from "./chunk-YREYFITQ.js";
51
51
 
52
52
  // src/algebra/directive-scan.ts
53
53
  function cleanDirectiveLine(raw, kind) {
@@ -988,6 +988,75 @@ function rewriteSidecarSource(src, fromFile) {
988
988
  }
989
989
  }
990
990
  }
991
+ const aliasToImported = /* @__PURE__ */ new Map();
992
+ const fnAliases = /* @__PURE__ */ new Set(["fn"]);
993
+ for (const imp of imports) {
994
+ for (const n of imp.names) {
995
+ if (n.ns) continue;
996
+ if (n.imported !== void 0 && n.local !== void 0 && n.imported !== n.local) {
997
+ aliasToImported.set(n.local, n.imported);
998
+ }
999
+ if (n.imported === "fn" && n.local !== void 0) fnAliases.add(n.local);
1000
+ }
1001
+ }
1002
+ const paramTextsOfFnCall = (init) => {
1003
+ const call = init;
1004
+ if (!call || call.type !== "CallExpression") return void 0;
1005
+ if (call.callee?.type !== "Identifier" || !fnAliases.has(call.callee.name ?? "")) {
1006
+ return void 0;
1007
+ }
1008
+ const first = call.arguments?.[0];
1009
+ if (!first || first.type !== "ObjectExpression") return void 0;
1010
+ const texts = /* @__PURE__ */ new Map();
1011
+ for (const prop of first.properties ?? []) {
1012
+ if (prop.type !== "ObjectProperty" || prop.computed) continue;
1013
+ const key = prop.key?.type === "Identifier" ? prop.key.name : prop.key?.type === "StringLiteral" ? prop.key.value : void 0;
1014
+ if (key === void 0) continue;
1015
+ const v2 = prop.value;
1016
+ if (!v2 || v2.start == null || v2.end == null) continue;
1017
+ texts.set(
1018
+ key,
1019
+ v2.type === "Identifier" && aliasToImported.has(v2.name ?? "") ? aliasToImported.get(v2.name ?? "") : src.slice(v2.start, v2.end)
1020
+ );
1021
+ }
1022
+ return texts;
1023
+ };
1024
+ const paramInfosByLocal = /* @__PURE__ */ new Map();
1025
+ const collectVarFns = (decls) => {
1026
+ for (const d of decls) {
1027
+ if (d?.id?.type !== "Identifier" || d.id.name === void 0) continue;
1028
+ const texts = paramTextsOfFnCall(d.init);
1029
+ if (texts)
1030
+ paramInfosByLocal.set(d.id.name, {
1031
+ texts,
1032
+ line: d.loc?.start?.line ?? 1
1033
+ });
1034
+ }
1035
+ };
1036
+ for (const stmt of ast.program.body) {
1037
+ if (stmt.type === "ExportNamedDeclaration" && stmt.declaration?.type === "VariableDeclaration") {
1038
+ collectVarFns(
1039
+ stmt.declaration?.declarations ?? []
1040
+ );
1041
+ } else if (stmt.type === "VariableDeclaration") {
1042
+ collectVarFns(
1043
+ stmt.declarations ?? []
1044
+ );
1045
+ } else if (stmt.type === "ExportDefaultDeclaration") {
1046
+ const decl = stmt.declaration;
1047
+ const texts = paramTextsOfFnCall(decl);
1048
+ if (texts)
1049
+ paramInfosByLocal.set(DEFAULT_LOCAL, {
1050
+ texts,
1051
+ line: stmt.loc?.start?.line ?? 1
1052
+ });
1053
+ }
1054
+ }
1055
+ const bindingInfos = /* @__PURE__ */ new Map();
1056
+ for (const p of exportPairs) {
1057
+ const info = paramInfosByLocal.get(p.expr);
1058
+ if (info) bindingInfos.set(p.key, info);
1059
+ }
991
1060
  if (fromFile?.endsWith(".nudo.ts")) {
992
1061
  for (const cut of collectTsSyntaxCuts(ast.program, src)) {
993
1062
  cuts.push({ start: cut.start, end: cut.end, text: "" });
@@ -1011,7 +1080,7 @@ function rewriteSidecarSource(src, fromFile) {
1011
1080
  pos = c.end;
1012
1081
  }
1013
1082
  code += src.slice(pos);
1014
- return { code, exportPairs, imports };
1083
+ return { code, exportPairs, imports, bindingInfos };
1015
1084
  }
1016
1085
  var TS_STMT_CUT_TYPES = /* @__PURE__ */ new Set([
1017
1086
  "TSInterfaceDeclaration",
@@ -1083,9 +1152,25 @@ function collectTsSyntaxCuts(node, src, cuts = []) {
1083
1152
  }
1084
1153
  return cuts;
1085
1154
  }
1155
+ function registerSidecarParamTexts(sidecarPath, contentKey, infos) {
1156
+ let perPath = sidecarParamTextsRegistry.get(sidecarPath);
1157
+ if (perPath === void 0) {
1158
+ perPath = /* @__PURE__ */ new Map();
1159
+ sidecarParamTextsRegistry.set(sidecarPath, perPath);
1160
+ if (sidecarParamTextsRegistry.size > MAX_SIDECAR_PARAM_TEXTS_PATHS) {
1161
+ const oldest = sidecarParamTextsRegistry.keys().next().value;
1162
+ if (oldest !== void 0) sidecarParamTextsRegistry.delete(oldest);
1163
+ }
1164
+ }
1165
+ perPath.set(contentKey, infos);
1166
+ if (perPath.size > MAX_SIDECAR_PARAM_TEXTS_VERSIONS) {
1167
+ const oldest = perPath.keys().next().value;
1168
+ if (oldest !== void 0) perPath.delete(oldest);
1169
+ }
1170
+ }
1086
1171
  function execSidecar(src, opts, chain, preloaded) {
1087
1172
  const fromFile = opts?.fromFile;
1088
- const { code, exportPairs, imports } = rewriteSidecarSource(src, fromFile);
1173
+ const { code, exportPairs, imports, bindingInfos } = rewriteSidecarSource(src, fromFile);
1089
1174
  const prologue = [];
1090
1175
  const deps = {};
1091
1176
  for (const imp of imports) {
@@ -1167,12 +1252,13 @@ function execSidecar(src, opts, chain, preloaded) {
1167
1252
  for (const n of imp.names) deps[n.local] = void 0;
1168
1253
  continue;
1169
1254
  }
1170
- const depExports = execSidecar(
1255
+ const depOut = execSidecar(
1171
1256
  depSrc,
1172
1257
  { loadModule: load, fromFile: canonical },
1173
1258
  [...chain, canonical],
1174
1259
  preloaded
1175
1260
  );
1261
+ const depExports = depOut.exports;
1176
1262
  for (const n of imp.names) {
1177
1263
  if (n.ns) {
1178
1264
  deps[n.local] = depExports;
@@ -1212,7 +1298,11 @@ return { ${returnObj} };`;
1212
1298
  "__nudoDeps",
1213
1299
  body
1214
1300
  );
1215
- return fn(...Object.values(sidecarInjects), sidecarInjects, deps);
1301
+ const result = fn(...Object.values(sidecarInjects), sidecarInjects, deps);
1302
+ if (fromFile !== void 0 && bindingInfos.size > 0) {
1303
+ registerSidecarParamTexts(fromFile, hashSource(src), bindingInfos);
1304
+ }
1305
+ return { exports: result, bindingInfos };
1216
1306
  }
1217
1307
  function execNudoModule(src, opts) {
1218
1308
  return execNudoModuleCached(src, opts ?? {});
@@ -1268,22 +1358,29 @@ function execNudoModuleCached(src, opts) {
1268
1358
  if (hit !== void 0) {
1269
1359
  nudoModuleExecCache.delete(key);
1270
1360
  nudoModuleExecCache.set(key, hit);
1271
- return hit;
1361
+ if (opts.fromFile !== void 0 && hit.bindingInfos.size > 0) {
1362
+ registerSidecarParamTexts(
1363
+ opts.fromFile,
1364
+ hashSource(src),
1365
+ hit.bindingInfos
1366
+ );
1367
+ }
1368
+ return hit.exports;
1272
1369
  }
1273
1370
  if (nudoModuleFailCache.has(key)) {
1274
1371
  throw nudoModuleFailCache.get(key);
1275
1372
  }
1276
1373
  }
1277
1374
  try {
1278
- const out = execSidecar(src, opts, opts.fromFile ? [opts.fromFile] : [], preloaded);
1375
+ const { exports, bindingInfos } = execSidecar(src, opts, opts.fromFile ? [opts.fromFile] : [], preloaded);
1279
1376
  if (key !== void 0) {
1280
1377
  if (nudoModuleExecCache.size >= MAX_NUDO_MODULE_EXEC) {
1281
1378
  const oldest = nudoModuleExecCache.keys().next().value;
1282
1379
  if (oldest !== void 0) nudoModuleExecCache.delete(oldest);
1283
1380
  }
1284
- nudoModuleExecCache.set(key, out);
1381
+ nudoModuleExecCache.set(key, { exports, bindingInfos });
1285
1382
  }
1286
- return out;
1383
+ return exports;
1287
1384
  } catch (e) {
1288
1385
  if (key !== void 0) {
1289
1386
  if (nudoModuleFailCache.size >= MAX_NUDO_MODULE_EXEC) {
@@ -1298,6 +1395,17 @@ function execNudoModuleCached(src, opts) {
1298
1395
  function resetNudoModuleExecCache() {
1299
1396
  nudoModuleExecCache.clear();
1300
1397
  nudoModuleFailCache.clear();
1398
+ sidecarParamTextsRegistry.clear();
1399
+ }
1400
+ var sidecarParamTextsRegistry = /* @__PURE__ */ new Map();
1401
+ var MAX_SIDECAR_PARAM_TEXTS_PATHS = 64;
1402
+ var MAX_SIDECAR_PARAM_TEXTS_VERSIONS = 32;
1403
+ function lookupSidecarParamTexts(sidecarPath, srcHash, bindingName) {
1404
+ const perPath = sidecarParamTextsRegistry.get(sidecarPath);
1405
+ if (perPath === void 0) return void 0;
1406
+ const perHash = perPath.get(srcHash);
1407
+ if (perHash === void 0) return void 0;
1408
+ return perHash.get(bindingName);
1301
1409
  }
1302
1410
  function collectConstraints(source, opts) {
1303
1411
  const map = /* @__PURE__ */ new Map();
@@ -1411,7 +1519,8 @@ function extractRefinesFromSource(source, fnName, opts = {}) {
1411
1519
  out.push({
1412
1520
  param,
1413
1521
  pred: instantiateConstraint(c, param),
1414
- constraint: c
1522
+ constraint: c,
1523
+ name: cName
1415
1524
  });
1416
1525
  }
1417
1526
  }
@@ -1858,18 +1967,25 @@ function loadSidecarBinding(source, fnName, opts) {
1858
1967
  return { ok: false };
1859
1968
  }
1860
1969
  let binding = Object.hasOwn(exports, fnName) ? exports[fnName] : void 0;
1970
+ let bindingKey;
1971
+ if (binding !== void 0) bindingKey = fnName;
1861
1972
  if (binding === void 0) {
1862
1973
  const aliasExport2 = exportedNameOfLocal(source, fnName);
1863
1974
  if (aliasExport2 !== void 0 && Object.hasOwn(exports, aliasExport2)) {
1864
1975
  binding = exports[aliasExport2];
1976
+ bindingKey = aliasExport2;
1865
1977
  }
1866
1978
  }
1867
1979
  if (binding === void 0 && exports.default !== void 0 && isDefaultExportLocal(source, fnName)) {
1868
1980
  binding = exports.default;
1981
+ bindingKey = "default";
1869
1982
  }
1870
1983
  if (binding === void 0 && fnName.includes(".")) {
1871
1984
  const [cls, method] = fnName.split(".", 2);
1872
- binding = Object.hasOwn(exports, `${cls}_${method}`) ? exports[`${cls}_${method}`] : void 0;
1985
+ if (Object.hasOwn(exports, `${cls}_${method}`)) {
1986
+ binding = exports[`${cls}_${method}`];
1987
+ bindingKey = `${cls}_${method}`;
1988
+ }
1873
1989
  if (binding === void 0) {
1874
1990
  const bag = Object.hasOwn(exports, cls) ? exports[cls] : void 0;
1875
1991
  if (bag && typeof bag === "object" && !isNudoConstraint(bag)) {
@@ -1907,11 +2023,14 @@ function loadSidecarBinding(source, fnName, opts) {
1907
2023
  const [cls, method] = fnName.split(".", 2);
1908
2024
  return generatedNames.has(`${cls}_${method}`) || generatedNames.has(cls);
1909
2025
  })() : false);
2026
+ const info = bindingKey !== void 0 ? lookupSidecarParamTexts(sidecarPath, hashSource(sidecarSrc), bindingKey) : void 0;
1910
2027
  return {
1911
2028
  ok: true,
1912
2029
  sidecarPath,
1913
2030
  constraint: binding,
1914
- generated: isGenerated
2031
+ generated: isGenerated,
2032
+ ...info?.texts !== void 0 ? { paramTexts: info.texts } : {},
2033
+ ...info?.line !== void 0 ? { sidecarLine: info.line } : {}
1915
2034
  };
1916
2035
  }
1917
2036
  function boundsOf(c) {
@@ -2014,8 +2133,24 @@ function effectiveInterface(source, fnName, opts = {}) {
2014
2133
  collectDiag2({ code: d.code, message: d.message, ...d.file ? { file: d.file } : {} });
2015
2134
  }
2016
2135
  const sidecarFn = sidecar.ok ? sidecar.constraint : void 0;
2136
+ const sidecarParamTexts = sidecar.ok ? sidecar.paramTexts : void 0;
2017
2137
  const sidecarGenerated = sidecar.ok && sidecar.generated;
2018
2138
  const sidecarParams = sidecarFn ? fnConstraintToEntryReqs(sidecarFn) : [];
2139
+ const sidecarParamSet = new Set(sidecarParams.map((p) => p.param));
2140
+ const sidecarTexts = /* @__PURE__ */ new Map();
2141
+ if (sidecarParamTexts) {
2142
+ for (const param of sidecarParamSet) {
2143
+ const t = sidecarParamTexts.get(param);
2144
+ if (t !== void 0) sidecarTexts.set(param, t);
2145
+ }
2146
+ }
2147
+ const directiveNames = /* @__PURE__ */ new Map();
2148
+ for (const e of sourceEntries) {
2149
+ if (e.name === void 0) continue;
2150
+ const list = directiveNames.get(e.param);
2151
+ if (list === void 0) directiveNames.set(e.param, [e.name]);
2152
+ else if (!list.includes(e.name)) list.push(e.name);
2153
+ }
2019
2154
  const sidecarReturns = sidecarFn?.fn.returns;
2020
2155
  const sidecarThrowsKinds = throwConstraintToKinds(sidecarFn?.fn.throws);
2021
2156
  const mergedThrows = (() => {
@@ -2028,9 +2163,16 @@ function effectiveInterface(source, fnName, opts = {}) {
2028
2163
  if (sidecarFn !== void 0 && sidecarGenerated) {
2029
2164
  return {
2030
2165
  fnName,
2031
- params: sidecarParams,
2166
+ params: sidecarParams.map(({ param, constraint }) => {
2167
+ const display = sidecarTexts.get(param);
2168
+ return display !== void 0 ? { param, constraint, display } : { param, constraint };
2169
+ }),
2032
2170
  ...sidecarReturns !== void 0 ? { returns: { constraint: sidecarReturns } } : {},
2033
2171
  ...mergedThrows !== void 0 ? { throws: { kinds: mergedThrows } } : {},
2172
+ ...sidecar.ok ? {
2173
+ sidecarPath: sidecar.sidecarPath,
2174
+ ...sidecar.sidecarLine !== void 0 ? { sidecarLine: sidecar.sidecarLine } : {}
2175
+ } : {},
2034
2176
  source: "generated"
2035
2177
  };
2036
2178
  }
@@ -2083,9 +2225,27 @@ function effectiveInterface(source, fnName, opts = {}) {
2083
2225
  }
2084
2226
  return {
2085
2227
  fnName,
2086
- params: [...params.entries()].map(([param, constraint]) => ({ param, constraint })),
2228
+ params: [...params.entries()].map(([param, constraint]) => {
2229
+ const sidecarText = sidecarTexts.get(param);
2230
+ const names = directiveNames.get(param);
2231
+ const fromSidecar = sidecarFn !== void 0 && !sidecarGenerated && sidecarParamSet.has(param);
2232
+ const fromDirective = names !== void 0;
2233
+ let display;
2234
+ if (fromSidecar && fromDirective) {
2235
+ display = sidecarText !== void 0 ? `${sidecarText} \u2227 ${names.join(" \u2227 ")}` : void 0;
2236
+ } else if (fromSidecar) {
2237
+ display = sidecarText;
2238
+ } else if (fromDirective) {
2239
+ display = names.join(" \u2227 ");
2240
+ }
2241
+ return display !== void 0 ? { param, constraint, display } : { param, constraint };
2242
+ }),
2087
2243
  ...returnsC !== void 0 ? { returns: { constraint: returnsC } } : {},
2088
2244
  ...mergedThrows !== void 0 ? { throws: { kinds: mergedThrows } } : {},
2245
+ ...sidecar.ok ? {
2246
+ sidecarPath: sidecar.sidecarPath,
2247
+ ...sidecar.sidecarLine !== void 0 ? { sidecarLine: sidecar.sidecarLine } : {}
2248
+ } : {},
2089
2249
  source: "handwritten",
2090
2250
  ...conflictParams.length > 0 || conflictReturns ? {
2091
2251
  conflict: {
@@ -2236,7 +2396,7 @@ function formatConstraint(c) {
2236
2396
  return fmtConstraint(c);
2237
2397
  }
2238
2398
  function formatEffectiveInterfaceDisplay(eff) {
2239
- const params = eff.params.map((p) => `${p.param}: ${formatConstraint(p.constraint)}`).join(", ");
2399
+ const params = eff.params.map((p) => `${p.param}: ${p.display ?? formatConstraint(p.constraint)}`).join(", ");
2240
2400
  let s = `(${params})`;
2241
2401
  if (eff.returns) s += ` \u2192 ${formatConstraint(eff.returns.constraint)}`;
2242
2402
  return s;
@@ -2254,7 +2414,12 @@ function interfaceTierOf(source, fnName, fromFile, opts = {}) {
2254
2414
  const eff = effectiveInterface(source, fnName, { fromFile, ...opts });
2255
2415
  const src = eff?.source ?? "implicit";
2256
2416
  if (eff && src !== "implicit") {
2257
- return { source: src, display: formatEffectiveInterfaceDisplay(eff) };
2417
+ return {
2418
+ source: src,
2419
+ display: formatEffectiveInterfaceDisplay(eff),
2420
+ ...eff.sidecarPath !== void 0 ? { sidecarPath: eff.sidecarPath } : {},
2421
+ ...eff.sidecarLine !== void 0 ? { sidecarLine: eff.sidecarLine } : {}
2422
+ };
2258
2423
  }
2259
2424
  return { source: src };
2260
2425
  }
@@ -3480,7 +3645,8 @@ function generalizeFromAstUncached(fnName, source, opts = {}) {
3480
3645
  if (reqs.length > 0) {
3481
3646
  entryReqs = reqs.map((e) => ({
3482
3647
  param: e.param,
3483
- pred: instantiateConstraint(e.constraint, e.param)
3648
+ pred: instantiateConstraint(e.constraint, e.param),
3649
+ ...e.display !== void 0 ? { display: e.display } : {}
3484
3650
  }));
3485
3651
  const patternFields = /* @__PURE__ */ new Map();
3486
3652
  for (const e of reqs) {