nudojs 1.3.0 → 1.3.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.
- package/dist/index.js +86 -31
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -37924,7 +37924,7 @@ function scanLiteralCalls(source, knownFns, phi2, opts) {
|
|
|
37924
37924
|
if (absArg.shape.k === "unknown" && !absArg.term) return;
|
|
37925
37925
|
const slots = absArg.shape.k === "obj" ? absArg.shape.slots : void 0;
|
|
37926
37926
|
if (!slots) {
|
|
37927
|
-
if (absArg.shape.k !== "unknown" && absArg.shape.k !== "never") {
|
|
37927
|
+
if (absArg.shape.k !== "unknown" && absArg.shape.k !== "never" && absArg.shape.k !== "any") {
|
|
37928
37928
|
out.push({
|
|
37929
37929
|
severity: "error",
|
|
37930
37930
|
code: "nudo:constraint-violated",
|
|
@@ -279237,12 +279237,38 @@ function collectParamBodyReadTypes(source) {
|
|
|
279237
279237
|
const visitFn = (fnName, fnNode, paramNames) => {
|
|
279238
279238
|
if (paramNames.size === 0) return;
|
|
279239
279239
|
const byParam = /* @__PURE__ */ new Map();
|
|
279240
|
-
const add2 = (pname,
|
|
279241
|
-
if (
|
|
279242
|
-
|
|
279243
|
-
if (!
|
|
279244
|
-
|
|
279240
|
+
const add2 = (pname, path, hint) => {
|
|
279241
|
+
if (path.length === 0) return;
|
|
279242
|
+
let m = byParam.get(pname);
|
|
279243
|
+
if (!m) byParam.set(pname, m = /* @__PURE__ */ new Map());
|
|
279244
|
+
const k = JSON.stringify(path);
|
|
279245
|
+
let e = m.get(k);
|
|
279246
|
+
if (!e) m.set(k, e = { path, hints: [] });
|
|
279247
|
+
if (hint) e.hints.push(hint);
|
|
279245
279248
|
};
|
|
279249
|
+
const downChainPath = (mem) => {
|
|
279250
|
+
const keys = [];
|
|
279251
|
+
let cur = mem;
|
|
279252
|
+
let param;
|
|
279253
|
+
while (cur) {
|
|
279254
|
+
if (cur.type !== "MemberExpression" && cur.type !== "OptionalMemberExpression" || cur.computed === true) {
|
|
279255
|
+
return void 0;
|
|
279256
|
+
}
|
|
279257
|
+
const key = keyOf(cur.property);
|
|
279258
|
+
if (key === void 0) return void 0;
|
|
279259
|
+
keys.unshift(key);
|
|
279260
|
+
const obj2 = cur.object;
|
|
279261
|
+
if (!obj2) return void 0;
|
|
279262
|
+
if (obj2.type === "Identifier") {
|
|
279263
|
+
param = obj2.name;
|
|
279264
|
+
break;
|
|
279265
|
+
}
|
|
279266
|
+
cur = obj2;
|
|
279267
|
+
}
|
|
279268
|
+
if (param === void 0) return void 0;
|
|
279269
|
+
return { path: keys, param };
|
|
279270
|
+
};
|
|
279271
|
+
const synthMemberParent = (prop) => ({ type: "MemberExpression", property: { type: "Identifier", name: prop } });
|
|
279246
279272
|
const walk = (node, shadowed, parent, parentKey) => {
|
|
279247
279273
|
if (!node || typeof node !== "object") return;
|
|
279248
279274
|
const n = node;
|
|
@@ -279254,29 +279280,31 @@ function collectParamBodyReadTypes(source) {
|
|
|
279254
279280
|
const arg = n.argument;
|
|
279255
279281
|
const mem = arg;
|
|
279256
279282
|
if (mem && (mem.type === "MemberExpression" || mem.type === "OptionalMemberExpression")) {
|
|
279257
|
-
const
|
|
279258
|
-
|
|
279259
|
-
|
|
279260
|
-
|
|
279261
|
-
const pname = obj2.name;
|
|
279262
|
-
if (key !== void 0) {
|
|
279263
|
-
const gp = parent;
|
|
279264
|
-
add2(pname, key, hintFromTypeof(n, gp));
|
|
279265
|
-
}
|
|
279283
|
+
const chain = downChainPath(mem);
|
|
279284
|
+
if (chain && paramNames.has(chain.param) && !shadowed.has(chain.param)) {
|
|
279285
|
+
const gp = parent;
|
|
279286
|
+
add2(chain.param, chain.path, hintFromTypeof(n, gp));
|
|
279266
279287
|
}
|
|
279267
279288
|
}
|
|
279268
279289
|
}
|
|
279269
279290
|
if (n.type === "MemberExpression" || n.type === "OptionalMemberExpression") {
|
|
279270
|
-
const
|
|
279271
|
-
|
|
279272
|
-
const
|
|
279273
|
-
if (
|
|
279274
|
-
const
|
|
279275
|
-
|
|
279276
|
-
|
|
279277
|
-
|
|
279278
|
-
|
|
279291
|
+
const innerLink = !!parent && (parent.type === "MemberExpression" || parent.type === "OptionalMemberExpression") && parentKey === "object" && parent.computed !== true;
|
|
279292
|
+
if (innerLink) return;
|
|
279293
|
+
const chain = downChainPath(n);
|
|
279294
|
+
if (chain && paramNames.has(chain.param) && !shadowed.has(chain.param)) {
|
|
279295
|
+
const rev = chain.path;
|
|
279296
|
+
let leafLen = rev.length;
|
|
279297
|
+
let leafHint;
|
|
279298
|
+
for (let i = 0; i < rev.length; i++) {
|
|
279299
|
+
const nextProp = i + 1 < rev.length ? rev[i + 1] : void 0;
|
|
279300
|
+
const h = nextProp !== void 0 ? hintFromUse(synthMemberParent(nextProp), "object") : hintFromUse(parent, parentKey ?? "object");
|
|
279301
|
+
if (h) {
|
|
279302
|
+
leafLen = i + 1;
|
|
279303
|
+
leafHint = h;
|
|
279304
|
+
break;
|
|
279305
|
+
}
|
|
279279
279306
|
}
|
|
279307
|
+
add2(chain.param, rev.slice(0, leafLen), leafHint);
|
|
279280
279308
|
}
|
|
279281
279309
|
}
|
|
279282
279310
|
for (const k of Object.keys(n)) {
|
|
@@ -279292,13 +279320,20 @@ function collectParamBodyReadTypes(source) {
|
|
|
279292
279320
|
walk(fnNode, /* @__PURE__ */ new Set());
|
|
279293
279321
|
if (byParam.size === 0) return;
|
|
279294
279322
|
const fieldsOf = /* @__PURE__ */ new Map();
|
|
279295
|
-
for (const [pname,
|
|
279296
|
-
const
|
|
279297
|
-
for (const
|
|
279298
|
-
|
|
279323
|
+
for (const [pname, pathMap] of byParam) {
|
|
279324
|
+
const root = { hints: [], children: /* @__PURE__ */ new Map() };
|
|
279325
|
+
for (const { path, hints } of pathMap.values()) {
|
|
279326
|
+
let node = root;
|
|
279327
|
+
for (const seg of path) {
|
|
279328
|
+
let child = node.children.get(seg);
|
|
279329
|
+
if (!child) {
|
|
279330
|
+
node.children.set(seg, child = { hints: [], children: /* @__PURE__ */ new Map() });
|
|
279331
|
+
}
|
|
279332
|
+
node = child;
|
|
279333
|
+
}
|
|
279334
|
+
node.hints.push(...hints);
|
|
279299
279335
|
}
|
|
279300
|
-
|
|
279301
|
-
fieldsOf.set(pname, list);
|
|
279336
|
+
fieldsOf.set(pname, emitFields(root));
|
|
279302
279337
|
}
|
|
279303
279338
|
out.set(fnName, fieldsOf);
|
|
279304
279339
|
};
|
|
@@ -279377,6 +279412,24 @@ function collectParamBodyReadTypes(source) {
|
|
|
279377
279412
|
}
|
|
279378
279413
|
return out;
|
|
279379
279414
|
}
|
|
279415
|
+
function emitFields(trie) {
|
|
279416
|
+
const list = [];
|
|
279417
|
+
for (const [name, child] of [...trie.children.entries()].sort(
|
|
279418
|
+
(a, b) => a[0] < b[0] ? -1 : 1
|
|
279419
|
+
)) {
|
|
279420
|
+
if (child.children.size > 0) {
|
|
279421
|
+
list.push({
|
|
279422
|
+
field: name,
|
|
279423
|
+
type: "shape({ \u2026 })",
|
|
279424
|
+
via: "dereferenced member read (nested shape)",
|
|
279425
|
+
fields: emitFields(child)
|
|
279426
|
+
});
|
|
279427
|
+
} else {
|
|
279428
|
+
list.push({ field: name, ...mergeHints(child.hints) });
|
|
279429
|
+
}
|
|
279430
|
+
}
|
|
279431
|
+
return list;
|
|
279432
|
+
}
|
|
279380
279433
|
function mergeHints(hints) {
|
|
279381
279434
|
if (hints.length === 0) return { type: "any()", via: "read (no type evidence)" };
|
|
279382
279435
|
const types2 = [...new Set(hints.map((h) => h.type))];
|
|
@@ -279419,7 +279472,9 @@ function bodyReadFieldsFor(map, fnName, paramName2) {
|
|
|
279419
279472
|
}
|
|
279420
279473
|
function shapeDslFromFields(fields) {
|
|
279421
279474
|
if (fields.length === 0) return "shape({})";
|
|
279422
|
-
const parts = fields.map(
|
|
279475
|
+
const parts = fields.map(
|
|
279476
|
+
(f) => f.fields && f.fields.length > 0 ? `${f.field}: ${shapeDslFromFields(f.fields)}` : `${f.field}: ${f.type}`
|
|
279477
|
+
);
|
|
279423
279478
|
return `shape({ ${parts.join(", ")} })`;
|
|
279424
279479
|
}
|
|
279425
279480
|
function collectParamBodyAccesses(source) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nudojs",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"engines": {
|
|
5
5
|
"node": ">=20"
|
|
6
6
|
},
|
|
@@ -46,14 +46,14 @@
|
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@babel/generator": "^8.0.6",
|
|
48
48
|
"@babel/types": "^8.0.6",
|
|
49
|
-
"@nudojs/core": "1.
|
|
50
|
-
"@nudojs/parser": "1.3.
|
|
51
|
-
"@nudojs/service": "1.
|
|
52
|
-
"@nudojs/harvester": "0.3.
|
|
49
|
+
"@nudojs/core": "1.7.0",
|
|
50
|
+
"@nudojs/parser": "1.3.1",
|
|
51
|
+
"@nudojs/service": "1.6.0",
|
|
52
|
+
"@nudojs/harvester": "0.3.1",
|
|
53
53
|
"commander": "^15.0.0"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@types/node": "^26.6.
|
|
56
|
+
"@types/node": "^26.6.3"
|
|
57
57
|
},
|
|
58
58
|
"scripts": {
|
|
59
59
|
"build": "tsup"
|