@fedify/lint 2.4.0-dev.2212 → 2.4.0-dev.2228
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/deno.json +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/{outbox-listener-delivery-required-zBDRIPHn.cjs → outbox-listener-delivery-required-BX1utrrk.cjs} +90 -12
- package/dist/{outbox-listener-delivery-required-C-3lDna2.js → outbox-listener-delivery-required-BlITas9r.js} +90 -12
- package/dist/oxlint.cjs +1 -1
- package/dist/oxlint.js +1 -1
- package/package.json +3 -3
package/deno.json
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -24,7 +24,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
24
24
|
enumerable: true
|
|
25
25
|
}) : target, mod));
|
|
26
26
|
//#endregion
|
|
27
|
-
const require_outbox_listener_delivery_required = require("./outbox-listener-delivery-required-
|
|
27
|
+
const require_outbox_listener_delivery_required = require("./outbox-listener-delivery-required-BX1utrrk.cjs");
|
|
28
28
|
let _fxts_core = require("@fxts/core");
|
|
29
29
|
let _typescript_eslint_parser = require("@typescript-eslint/parser");
|
|
30
30
|
_typescript_eslint_parser = __toESM(_typescript_eslint_parser, 1);
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as name, C as eslint$5, D as eslint$11, E as eslint$10, O as eslint$21, S as eslint$4, T as eslint$13, _ as eslint$15, a as eslint$23, b as eslint$2, c as eslint$16, d as eslint$22, f as eslint$6, g as eslint$14, h as eslint$9, i as eslint$27, j as version, k as RULE_IDS, l as eslint$17, m as eslint$8, n as eslint$25, o as eslint$18, p as eslint$7, r as eslint$26, s as eslint$19, t as eslint$24, u as eslint$20, v as eslint$1, w as eslint$12, x as eslint$3, y as eslint } from "./outbox-listener-delivery-required-
|
|
1
|
+
import { A as name, C as eslint$5, D as eslint$11, E as eslint$10, O as eslint$21, S as eslint$4, T as eslint$13, _ as eslint$15, a as eslint$23, b as eslint$2, c as eslint$16, d as eslint$22, f as eslint$6, g as eslint$14, h as eslint$9, i as eslint$27, j as version, k as RULE_IDS, l as eslint$17, m as eslint$8, n as eslint$25, o as eslint$18, p as eslint$7, r as eslint$26, s as eslint$19, t as eslint$24, u as eslint$20, v as eslint$1, w as eslint$12, x as eslint$3, y as eslint } from "./outbox-listener-delivery-required-BlITas9r.js";
|
|
2
2
|
import { fromEntries, keys, map, pipe } from "@fxts/core";
|
|
3
3
|
import parser from "@typescript-eslint/parser";
|
|
4
4
|
//#region src/index.ts
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
let _fxts_core = require("@fxts/core");
|
|
2
2
|
//#region deno.json
|
|
3
3
|
var name = "@fedify/lint";
|
|
4
|
-
var version = "2.4.0-dev.
|
|
4
|
+
var version = "2.4.0-dev.2228+6d017d55";
|
|
5
5
|
//#endregion
|
|
6
6
|
//#region src/lib/const.ts
|
|
7
7
|
/**
|
|
@@ -1740,7 +1740,7 @@ function collectCalls(node, out) {
|
|
|
1740
1740
|
if (n.type === "CallExpression") out.push(n);
|
|
1741
1741
|
}, false);
|
|
1742
1742
|
}
|
|
1743
|
-
function enclosingFunction(node) {
|
|
1743
|
+
function enclosingFunction$1(node) {
|
|
1744
1744
|
for (let current = parentOf(node); current != null;) {
|
|
1745
1745
|
if (isFunctionLikeNode(current)) return current;
|
|
1746
1746
|
current = parentOf(current);
|
|
@@ -1846,9 +1846,9 @@ function fateOf(expression, analysis, shape = "promise") {
|
|
|
1846
1846
|
switch (parent.type) {
|
|
1847
1847
|
case "AwaitExpression": return currentShape === "promise" ? {
|
|
1848
1848
|
fate: "awaited",
|
|
1849
|
-
owner: enclosingFunction(parent)
|
|
1849
|
+
owner: enclosingFunction$1(parent)
|
|
1850
1850
|
} : DROPPED;
|
|
1851
|
-
case "ReturnStatement": return currentShape === "promise" ? returnedOutcome(enclosingFunction(parent), analysis) : returnedContainerOutcome(enclosingFunction(parent), analysis);
|
|
1851
|
+
case "ReturnStatement": return currentShape === "promise" ? returnedOutcome(enclosingFunction$1(parent), analysis) : returnedContainerOutcome(enclosingFunction$1(parent), analysis);
|
|
1852
1852
|
case "ArrowFunctionExpression":
|
|
1853
1853
|
if (get(parent, "body") !== current) return HANDLED;
|
|
1854
1854
|
return currentShape === "promise" ? returnedOutcome(parent, analysis) : returnedContainerOutcome(parent, analysis);
|
|
@@ -2121,6 +2121,36 @@ function createBindingIndex() {
|
|
|
2121
2121
|
}
|
|
2122
2122
|
};
|
|
2123
2123
|
}
|
|
2124
|
+
const position = (node) => node.range?.[0] ?? node.start ?? -1;
|
|
2125
|
+
const enclosingFunction = (node) => {
|
|
2126
|
+
for (let parent = getParent(node); parent != null; parent = getParent(parent)) if (isFunctionLike(parent)) return parent;
|
|
2127
|
+
return null;
|
|
2128
|
+
};
|
|
2129
|
+
const isInside = (node, ancestor) => {
|
|
2130
|
+
for (let current = node; current != null; current = getParent(current)) if (current === ancestor) return true;
|
|
2131
|
+
return false;
|
|
2132
|
+
};
|
|
2133
|
+
const isDirectStatement = (node, fn) => {
|
|
2134
|
+
let current = node;
|
|
2135
|
+
while (getParent(current) !== fn.body) {
|
|
2136
|
+
const parent = getParent(current);
|
|
2137
|
+
if (parent == null || ![
|
|
2138
|
+
"AwaitExpression",
|
|
2139
|
+
"ExpressionStatement",
|
|
2140
|
+
"ReturnStatement",
|
|
2141
|
+
"VariableDeclarator",
|
|
2142
|
+
"VariableDeclaration",
|
|
2143
|
+
"BlockStatement"
|
|
2144
|
+
].includes(parent.type)) return false;
|
|
2145
|
+
current = parent;
|
|
2146
|
+
}
|
|
2147
|
+
return [
|
|
2148
|
+
"ExpressionStatement",
|
|
2149
|
+
"ReturnStatement",
|
|
2150
|
+
"VariableDeclaration",
|
|
2151
|
+
"BlockStatement"
|
|
2152
|
+
].includes(current.type);
|
|
2153
|
+
};
|
|
2124
2154
|
const resolveBindingValue = (expr, bindings, seen = /* @__PURE__ */ new Set()) => {
|
|
2125
2155
|
if (expr.type !== "Identifier") return expr;
|
|
2126
2156
|
const binding = bindings.lookup(expr, expr.name);
|
|
@@ -2290,7 +2320,7 @@ function buildContextExpressionPattern(contextName) {
|
|
|
2290
2320
|
* later replacement's length change never shifts the still-unprocessed
|
|
2291
2321
|
* offsets of an earlier one.
|
|
2292
2322
|
*/
|
|
2293
|
-
function collectDeliveryScanCode(sourceCode, root, used, visited) {
|
|
2323
|
+
function collectDeliveryScanCode(sourceCode, root, used, ignored, visited) {
|
|
2294
2324
|
if (visited.has(root)) return "";
|
|
2295
2325
|
visited.add(root);
|
|
2296
2326
|
const statements = [];
|
|
@@ -2304,7 +2334,7 @@ function collectDeliveryScanCode(sourceCode, root, used, visited) {
|
|
|
2304
2334
|
let result = text;
|
|
2305
2335
|
for (const fn of byDescendingStart) {
|
|
2306
2336
|
const [fnStart, fnEnd] = getRange(fn);
|
|
2307
|
-
const replacement = used.has(fn) ? collectDeliveryScanCode(sourceCode, fn.body, used, visited) : "";
|
|
2337
|
+
const replacement = used.has(fn) && !ignored.has(fn) ? collectDeliveryScanCode(sourceCode, fn.body, used, ignored, visited) : "";
|
|
2308
2338
|
result = result.slice(0, fnStart - statementStart) + `\n${replacement.length > 0 ? replacement : "()=>{}"}\n` + result.slice(fnEnd - statementStart);
|
|
2309
2339
|
}
|
|
2310
2340
|
return result;
|
|
@@ -2314,12 +2344,46 @@ function unwrapArgument(node) {
|
|
|
2314
2344
|
while (node.type === "TSAsExpression" || node.type === "TSTypeAssertion" || node.type === "TSNonNullExpression") node = node.expression;
|
|
2315
2345
|
return node;
|
|
2316
2346
|
}
|
|
2317
|
-
function
|
|
2347
|
+
function ignoredLocalSetupFunctions(listener, bindings, calls, assignments) {
|
|
2348
|
+
const ignored = [];
|
|
2349
|
+
const directCalls = calls.filter((call) => enclosingFunction(call) === listener && isDirectStatement(call, listener));
|
|
2350
|
+
for (const assignment of assignments) {
|
|
2351
|
+
if (assignment.type !== "AssignmentExpression" || assignment.operator !== "=" || assignment.left.type !== "MemberExpression" || !isFunction(assignment.right)) continue;
|
|
2352
|
+
const setup = enclosingFunction(assignment);
|
|
2353
|
+
if (setup == null || setup === listener || !isInside(setup, listener)) continue;
|
|
2354
|
+
const setupParent = getParent(setup);
|
|
2355
|
+
const namedLocalSetup = enclosingFunction(setup) === listener && (setup.type === "FunctionDeclaration" || setupParent?.type === "VariableDeclarator" && setupParent.init === setup && setupParent.id.type === "Identifier");
|
|
2356
|
+
const passedToCall = calls.some((call) => call.arguments.some((argument) => argument.type !== "SpreadElement" && resolveListenerReference(argument, bindings) === setup));
|
|
2357
|
+
if (!namedLocalSetup || passedToCall) continue;
|
|
2358
|
+
const installed = assignment.right;
|
|
2359
|
+
if (!isDirectStatement(assignment, setup) || assignment.left.object.type !== "Identifier") {
|
|
2360
|
+
ignored.push(installed);
|
|
2361
|
+
continue;
|
|
2362
|
+
}
|
|
2363
|
+
const property = getMemberPropertyName(assignment.left);
|
|
2364
|
+
if (property == null) continue;
|
|
2365
|
+
const setupCalls = directCalls.filter((call) => resolveListenerReference(call.callee, bindings) === setup);
|
|
2366
|
+
if (setupCalls.length === 0) {
|
|
2367
|
+
const called = calls.some((call) => resolveListenerReference(call.callee, bindings) === setup);
|
|
2368
|
+
ignored.push(called ? assignment.right : setup);
|
|
2369
|
+
continue;
|
|
2370
|
+
}
|
|
2371
|
+
const objectBinding = bindings.lookup(assignment.left.object, assignment.left.object.name);
|
|
2372
|
+
const deliveryCalls = directCalls.filter((call) => {
|
|
2373
|
+
const callee = call.callee;
|
|
2374
|
+
return callee.type === "MemberExpression" && callee.object.type === "Identifier" && getMemberPropertyName(callee) === property && bindings.lookup(callee.object, callee.object.name) === objectBinding;
|
|
2375
|
+
});
|
|
2376
|
+
if (!(objectBinding != null && setupCalls.some((setupCall) => deliveryCalls.some((deliveryCall) => position(setupCall) >= 0 && position(setupCall) < position(deliveryCall))))) ignored.push(installed);
|
|
2377
|
+
}
|
|
2378
|
+
return ignored;
|
|
2379
|
+
}
|
|
2380
|
+
function functionCallsDelivery(sourceCode, listener, bindings, calls, assignments, contextIndex = 0, visited = /* @__PURE__ */ new Map()) {
|
|
2318
2381
|
let indices = visited.get(listener);
|
|
2319
2382
|
if (indices?.has(contextIndex)) return false;
|
|
2320
2383
|
if (indices == null) visited.set(listener, indices = /* @__PURE__ */ new Set());
|
|
2321
2384
|
indices.add(contextIndex);
|
|
2322
|
-
|
|
2385
|
+
const ignored = ignoredLocalSetupFunctions(listener, bindings, calls, assignments);
|
|
2386
|
+
if (listenerCallsDeliveryMethod(sourceCode, listener, contextIndex, ignored, bindings, calls, assignments)) return true;
|
|
2323
2387
|
const param = unwrapContextParam(listener.params[contextIndex]);
|
|
2324
2388
|
if (param?.type !== "Identifier") return false;
|
|
2325
2389
|
const contextBinding = bindings.lookup(listener, param.name);
|
|
@@ -2346,14 +2410,24 @@ function functionCallsDelivery(sourceCode, listener, bindings, calls, contextInd
|
|
|
2346
2410
|
if (argument.type === "SpreadElement") break;
|
|
2347
2411
|
const arg = unwrapArgument(argument);
|
|
2348
2412
|
if (arg.type !== "Identifier" || arg.name !== param.name || bindings.lookup(arg, arg.name) !== contextBinding || helper.params[index]?.type === "RestElement") continue;
|
|
2349
|
-
if (functionCallsDelivery(sourceCode, helper, bindings, calls, index, visited)) return true;
|
|
2413
|
+
if (functionCallsDelivery(sourceCode, helper, bindings, calls, assignments, index, visited)) return true;
|
|
2350
2414
|
}
|
|
2351
2415
|
}
|
|
2352
2416
|
return false;
|
|
2353
2417
|
}
|
|
2354
|
-
const listenerCallsDeliveryMethod = (sourceCode, listener, contextIndex
|
|
2418
|
+
const listenerCallsDeliveryMethod = (sourceCode, listener, contextIndex, ignored, bindings, calls, assignments) => {
|
|
2355
2419
|
const used = computeUsedFunctions(listener.body);
|
|
2356
|
-
const
|
|
2420
|
+
const ignoredSet = new Set(ignored);
|
|
2421
|
+
for (const assignment of assignments) {
|
|
2422
|
+
if (assignment.type !== "AssignmentExpression" || assignment.left.type !== "MemberExpression" || assignment.left.object.type !== "Identifier" || !isFunction(assignment.right) || !isInside(assignment, listener)) continue;
|
|
2423
|
+
const property = getMemberPropertyName(assignment.left);
|
|
2424
|
+
const objectBinding = bindings.lookup(assignment.left.object, assignment.left.object.name);
|
|
2425
|
+
if (property == null || objectBinding == null || !calls.some((call) => enclosingFunction(call) === listener && call.callee.type === "MemberExpression" && call.callee.object.type === "Identifier" && getMemberPropertyName(call.callee) === property && bindings.lookup(call.callee.object, call.callee.object.name) === objectBinding)) continue;
|
|
2426
|
+
const installed = assignment.right;
|
|
2427
|
+
if (ignoredSet.has(installed)) continue;
|
|
2428
|
+
for (let fn = installed; fn != null && fn !== listener && !ignoredSet.has(fn); fn = enclosingFunction(fn)) used.add(fn);
|
|
2429
|
+
}
|
|
2430
|
+
const code = stripCommentsAndStrings(collectDeliveryScanCode(sourceCode, listener.body, used, ignoredSet, /* @__PURE__ */ new Set()));
|
|
2357
2431
|
const aliases = /* @__PURE__ */ new Set();
|
|
2358
2432
|
const contextParam = unwrapContextParam(listener.params[contextIndex]);
|
|
2359
2433
|
const contextName = contextParam?.type === "Identifier" ? contextParam.name : null;
|
|
@@ -2386,6 +2460,7 @@ function createRule(buildReport) {
|
|
|
2386
2460
|
const federationTracker = trackFederationVariables();
|
|
2387
2461
|
const bindings = createBindingIndex();
|
|
2388
2462
|
const pendingCalls = [];
|
|
2463
|
+
const pendingAssignments = [];
|
|
2389
2464
|
const sourceCode = context.sourceCode;
|
|
2390
2465
|
const inspectCall = (node) => {
|
|
2391
2466
|
if (!hasMemberExpressionCallee(node) || !hasIdentifierProperty(node) || !hasMethodName("on")(node) || node.arguments.length < 2) return;
|
|
@@ -2393,7 +2468,7 @@ function createRule(buildReport) {
|
|
|
2393
2468
|
const listener = node.arguments[1];
|
|
2394
2469
|
const resolvedListener = isNode(listener) && isFunction(listener) ? listener : isNode(listener) ? resolveListenerReference(listener, bindings) : null;
|
|
2395
2470
|
if (resolvedListener == null) return;
|
|
2396
|
-
if (functionCallsDelivery(sourceCode, resolvedListener, bindings, pendingCalls)) return;
|
|
2471
|
+
if (functionCallsDelivery(sourceCode, resolvedListener, bindings, pendingCalls, pendingAssignments)) return;
|
|
2397
2472
|
context.report({
|
|
2398
2473
|
node: resolvedListener,
|
|
2399
2474
|
...buildReport
|
|
@@ -2421,6 +2496,9 @@ function createRule(buildReport) {
|
|
|
2421
2496
|
CallExpression(node) {
|
|
2422
2497
|
pendingCalls.push(node);
|
|
2423
2498
|
},
|
|
2499
|
+
AssignmentExpression(node) {
|
|
2500
|
+
pendingAssignments.push(node);
|
|
2501
|
+
},
|
|
2424
2502
|
"Program:exit"() {
|
|
2425
2503
|
for (const node of pendingCalls) inspectCall(node);
|
|
2426
2504
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { always, every, head, isEmpty, isObject, negate, pipe, pipeLazy, prop, some, toArray, unless, when } from "@fxts/core";
|
|
2
2
|
//#region deno.json
|
|
3
3
|
var name = "@fedify/lint";
|
|
4
|
-
var version = "2.4.0-dev.
|
|
4
|
+
var version = "2.4.0-dev.2228+6d017d55";
|
|
5
5
|
//#endregion
|
|
6
6
|
//#region src/lib/const.ts
|
|
7
7
|
/**
|
|
@@ -1740,7 +1740,7 @@ function collectCalls(node, out) {
|
|
|
1740
1740
|
if (n.type === "CallExpression") out.push(n);
|
|
1741
1741
|
}, false);
|
|
1742
1742
|
}
|
|
1743
|
-
function enclosingFunction(node) {
|
|
1743
|
+
function enclosingFunction$1(node) {
|
|
1744
1744
|
for (let current = parentOf(node); current != null;) {
|
|
1745
1745
|
if (isFunctionLikeNode(current)) return current;
|
|
1746
1746
|
current = parentOf(current);
|
|
@@ -1846,9 +1846,9 @@ function fateOf(expression, analysis, shape = "promise") {
|
|
|
1846
1846
|
switch (parent.type) {
|
|
1847
1847
|
case "AwaitExpression": return currentShape === "promise" ? {
|
|
1848
1848
|
fate: "awaited",
|
|
1849
|
-
owner: enclosingFunction(parent)
|
|
1849
|
+
owner: enclosingFunction$1(parent)
|
|
1850
1850
|
} : DROPPED;
|
|
1851
|
-
case "ReturnStatement": return currentShape === "promise" ? returnedOutcome(enclosingFunction(parent), analysis) : returnedContainerOutcome(enclosingFunction(parent), analysis);
|
|
1851
|
+
case "ReturnStatement": return currentShape === "promise" ? returnedOutcome(enclosingFunction$1(parent), analysis) : returnedContainerOutcome(enclosingFunction$1(parent), analysis);
|
|
1852
1852
|
case "ArrowFunctionExpression":
|
|
1853
1853
|
if (get(parent, "body") !== current) return HANDLED;
|
|
1854
1854
|
return currentShape === "promise" ? returnedOutcome(parent, analysis) : returnedContainerOutcome(parent, analysis);
|
|
@@ -2121,6 +2121,36 @@ function createBindingIndex() {
|
|
|
2121
2121
|
}
|
|
2122
2122
|
};
|
|
2123
2123
|
}
|
|
2124
|
+
const position = (node) => node.range?.[0] ?? node.start ?? -1;
|
|
2125
|
+
const enclosingFunction = (node) => {
|
|
2126
|
+
for (let parent = getParent(node); parent != null; parent = getParent(parent)) if (isFunctionLike(parent)) return parent;
|
|
2127
|
+
return null;
|
|
2128
|
+
};
|
|
2129
|
+
const isInside = (node, ancestor) => {
|
|
2130
|
+
for (let current = node; current != null; current = getParent(current)) if (current === ancestor) return true;
|
|
2131
|
+
return false;
|
|
2132
|
+
};
|
|
2133
|
+
const isDirectStatement = (node, fn) => {
|
|
2134
|
+
let current = node;
|
|
2135
|
+
while (getParent(current) !== fn.body) {
|
|
2136
|
+
const parent = getParent(current);
|
|
2137
|
+
if (parent == null || ![
|
|
2138
|
+
"AwaitExpression",
|
|
2139
|
+
"ExpressionStatement",
|
|
2140
|
+
"ReturnStatement",
|
|
2141
|
+
"VariableDeclarator",
|
|
2142
|
+
"VariableDeclaration",
|
|
2143
|
+
"BlockStatement"
|
|
2144
|
+
].includes(parent.type)) return false;
|
|
2145
|
+
current = parent;
|
|
2146
|
+
}
|
|
2147
|
+
return [
|
|
2148
|
+
"ExpressionStatement",
|
|
2149
|
+
"ReturnStatement",
|
|
2150
|
+
"VariableDeclaration",
|
|
2151
|
+
"BlockStatement"
|
|
2152
|
+
].includes(current.type);
|
|
2153
|
+
};
|
|
2124
2154
|
const resolveBindingValue = (expr, bindings, seen = /* @__PURE__ */ new Set()) => {
|
|
2125
2155
|
if (expr.type !== "Identifier") return expr;
|
|
2126
2156
|
const binding = bindings.lookup(expr, expr.name);
|
|
@@ -2290,7 +2320,7 @@ function buildContextExpressionPattern(contextName) {
|
|
|
2290
2320
|
* later replacement's length change never shifts the still-unprocessed
|
|
2291
2321
|
* offsets of an earlier one.
|
|
2292
2322
|
*/
|
|
2293
|
-
function collectDeliveryScanCode(sourceCode, root, used, visited) {
|
|
2323
|
+
function collectDeliveryScanCode(sourceCode, root, used, ignored, visited) {
|
|
2294
2324
|
if (visited.has(root)) return "";
|
|
2295
2325
|
visited.add(root);
|
|
2296
2326
|
const statements = [];
|
|
@@ -2304,7 +2334,7 @@ function collectDeliveryScanCode(sourceCode, root, used, visited) {
|
|
|
2304
2334
|
let result = text;
|
|
2305
2335
|
for (const fn of byDescendingStart) {
|
|
2306
2336
|
const [fnStart, fnEnd] = getRange(fn);
|
|
2307
|
-
const replacement = used.has(fn) ? collectDeliveryScanCode(sourceCode, fn.body, used, visited) : "";
|
|
2337
|
+
const replacement = used.has(fn) && !ignored.has(fn) ? collectDeliveryScanCode(sourceCode, fn.body, used, ignored, visited) : "";
|
|
2308
2338
|
result = result.slice(0, fnStart - statementStart) + `\n${replacement.length > 0 ? replacement : "()=>{}"}\n` + result.slice(fnEnd - statementStart);
|
|
2309
2339
|
}
|
|
2310
2340
|
return result;
|
|
@@ -2314,12 +2344,46 @@ function unwrapArgument(node) {
|
|
|
2314
2344
|
while (node.type === "TSAsExpression" || node.type === "TSTypeAssertion" || node.type === "TSNonNullExpression") node = node.expression;
|
|
2315
2345
|
return node;
|
|
2316
2346
|
}
|
|
2317
|
-
function
|
|
2347
|
+
function ignoredLocalSetupFunctions(listener, bindings, calls, assignments) {
|
|
2348
|
+
const ignored = [];
|
|
2349
|
+
const directCalls = calls.filter((call) => enclosingFunction(call) === listener && isDirectStatement(call, listener));
|
|
2350
|
+
for (const assignment of assignments) {
|
|
2351
|
+
if (assignment.type !== "AssignmentExpression" || assignment.operator !== "=" || assignment.left.type !== "MemberExpression" || !isFunction(assignment.right)) continue;
|
|
2352
|
+
const setup = enclosingFunction(assignment);
|
|
2353
|
+
if (setup == null || setup === listener || !isInside(setup, listener)) continue;
|
|
2354
|
+
const setupParent = getParent(setup);
|
|
2355
|
+
const namedLocalSetup = enclosingFunction(setup) === listener && (setup.type === "FunctionDeclaration" || setupParent?.type === "VariableDeclarator" && setupParent.init === setup && setupParent.id.type === "Identifier");
|
|
2356
|
+
const passedToCall = calls.some((call) => call.arguments.some((argument) => argument.type !== "SpreadElement" && resolveListenerReference(argument, bindings) === setup));
|
|
2357
|
+
if (!namedLocalSetup || passedToCall) continue;
|
|
2358
|
+
const installed = assignment.right;
|
|
2359
|
+
if (!isDirectStatement(assignment, setup) || assignment.left.object.type !== "Identifier") {
|
|
2360
|
+
ignored.push(installed);
|
|
2361
|
+
continue;
|
|
2362
|
+
}
|
|
2363
|
+
const property = getMemberPropertyName(assignment.left);
|
|
2364
|
+
if (property == null) continue;
|
|
2365
|
+
const setupCalls = directCalls.filter((call) => resolveListenerReference(call.callee, bindings) === setup);
|
|
2366
|
+
if (setupCalls.length === 0) {
|
|
2367
|
+
const called = calls.some((call) => resolveListenerReference(call.callee, bindings) === setup);
|
|
2368
|
+
ignored.push(called ? assignment.right : setup);
|
|
2369
|
+
continue;
|
|
2370
|
+
}
|
|
2371
|
+
const objectBinding = bindings.lookup(assignment.left.object, assignment.left.object.name);
|
|
2372
|
+
const deliveryCalls = directCalls.filter((call) => {
|
|
2373
|
+
const callee = call.callee;
|
|
2374
|
+
return callee.type === "MemberExpression" && callee.object.type === "Identifier" && getMemberPropertyName(callee) === property && bindings.lookup(callee.object, callee.object.name) === objectBinding;
|
|
2375
|
+
});
|
|
2376
|
+
if (!(objectBinding != null && setupCalls.some((setupCall) => deliveryCalls.some((deliveryCall) => position(setupCall) >= 0 && position(setupCall) < position(deliveryCall))))) ignored.push(installed);
|
|
2377
|
+
}
|
|
2378
|
+
return ignored;
|
|
2379
|
+
}
|
|
2380
|
+
function functionCallsDelivery(sourceCode, listener, bindings, calls, assignments, contextIndex = 0, visited = /* @__PURE__ */ new Map()) {
|
|
2318
2381
|
let indices = visited.get(listener);
|
|
2319
2382
|
if (indices?.has(contextIndex)) return false;
|
|
2320
2383
|
if (indices == null) visited.set(listener, indices = /* @__PURE__ */ new Set());
|
|
2321
2384
|
indices.add(contextIndex);
|
|
2322
|
-
|
|
2385
|
+
const ignored = ignoredLocalSetupFunctions(listener, bindings, calls, assignments);
|
|
2386
|
+
if (listenerCallsDeliveryMethod(sourceCode, listener, contextIndex, ignored, bindings, calls, assignments)) return true;
|
|
2323
2387
|
const param = unwrapContextParam(listener.params[contextIndex]);
|
|
2324
2388
|
if (param?.type !== "Identifier") return false;
|
|
2325
2389
|
const contextBinding = bindings.lookup(listener, param.name);
|
|
@@ -2346,14 +2410,24 @@ function functionCallsDelivery(sourceCode, listener, bindings, calls, contextInd
|
|
|
2346
2410
|
if (argument.type === "SpreadElement") break;
|
|
2347
2411
|
const arg = unwrapArgument(argument);
|
|
2348
2412
|
if (arg.type !== "Identifier" || arg.name !== param.name || bindings.lookup(arg, arg.name) !== contextBinding || helper.params[index]?.type === "RestElement") continue;
|
|
2349
|
-
if (functionCallsDelivery(sourceCode, helper, bindings, calls, index, visited)) return true;
|
|
2413
|
+
if (functionCallsDelivery(sourceCode, helper, bindings, calls, assignments, index, visited)) return true;
|
|
2350
2414
|
}
|
|
2351
2415
|
}
|
|
2352
2416
|
return false;
|
|
2353
2417
|
}
|
|
2354
|
-
const listenerCallsDeliveryMethod = (sourceCode, listener, contextIndex
|
|
2418
|
+
const listenerCallsDeliveryMethod = (sourceCode, listener, contextIndex, ignored, bindings, calls, assignments) => {
|
|
2355
2419
|
const used = computeUsedFunctions(listener.body);
|
|
2356
|
-
const
|
|
2420
|
+
const ignoredSet = new Set(ignored);
|
|
2421
|
+
for (const assignment of assignments) {
|
|
2422
|
+
if (assignment.type !== "AssignmentExpression" || assignment.left.type !== "MemberExpression" || assignment.left.object.type !== "Identifier" || !isFunction(assignment.right) || !isInside(assignment, listener)) continue;
|
|
2423
|
+
const property = getMemberPropertyName(assignment.left);
|
|
2424
|
+
const objectBinding = bindings.lookup(assignment.left.object, assignment.left.object.name);
|
|
2425
|
+
if (property == null || objectBinding == null || !calls.some((call) => enclosingFunction(call) === listener && call.callee.type === "MemberExpression" && call.callee.object.type === "Identifier" && getMemberPropertyName(call.callee) === property && bindings.lookup(call.callee.object, call.callee.object.name) === objectBinding)) continue;
|
|
2426
|
+
const installed = assignment.right;
|
|
2427
|
+
if (ignoredSet.has(installed)) continue;
|
|
2428
|
+
for (let fn = installed; fn != null && fn !== listener && !ignoredSet.has(fn); fn = enclosingFunction(fn)) used.add(fn);
|
|
2429
|
+
}
|
|
2430
|
+
const code = stripCommentsAndStrings(collectDeliveryScanCode(sourceCode, listener.body, used, ignoredSet, /* @__PURE__ */ new Set()));
|
|
2357
2431
|
const aliases = /* @__PURE__ */ new Set();
|
|
2358
2432
|
const contextParam = unwrapContextParam(listener.params[contextIndex]);
|
|
2359
2433
|
const contextName = contextParam?.type === "Identifier" ? contextParam.name : null;
|
|
@@ -2386,6 +2460,7 @@ function createRule(buildReport) {
|
|
|
2386
2460
|
const federationTracker = trackFederationVariables();
|
|
2387
2461
|
const bindings = createBindingIndex();
|
|
2388
2462
|
const pendingCalls = [];
|
|
2463
|
+
const pendingAssignments = [];
|
|
2389
2464
|
const sourceCode = context.sourceCode;
|
|
2390
2465
|
const inspectCall = (node) => {
|
|
2391
2466
|
if (!hasMemberExpressionCallee(node) || !hasIdentifierProperty(node) || !hasMethodName("on")(node) || node.arguments.length < 2) return;
|
|
@@ -2393,7 +2468,7 @@ function createRule(buildReport) {
|
|
|
2393
2468
|
const listener = node.arguments[1];
|
|
2394
2469
|
const resolvedListener = isNode(listener) && isFunction(listener) ? listener : isNode(listener) ? resolveListenerReference(listener, bindings) : null;
|
|
2395
2470
|
if (resolvedListener == null) return;
|
|
2396
|
-
if (functionCallsDelivery(sourceCode, resolvedListener, bindings, pendingCalls)) return;
|
|
2471
|
+
if (functionCallsDelivery(sourceCode, resolvedListener, bindings, pendingCalls, pendingAssignments)) return;
|
|
2397
2472
|
context.report({
|
|
2398
2473
|
node: resolvedListener,
|
|
2399
2474
|
...buildReport
|
|
@@ -2421,6 +2496,9 @@ function createRule(buildReport) {
|
|
|
2421
2496
|
CallExpression(node) {
|
|
2422
2497
|
pendingCalls.push(node);
|
|
2423
2498
|
},
|
|
2499
|
+
AssignmentExpression(node) {
|
|
2500
|
+
pendingAssignments.push(node);
|
|
2501
|
+
},
|
|
2424
2502
|
"Program:exit"() {
|
|
2425
2503
|
for (const node of pendingCalls) inspectCall(node);
|
|
2426
2504
|
}
|
package/dist/oxlint.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const require_outbox_listener_delivery_required = require("./outbox-listener-delivery-required-
|
|
1
|
+
const require_outbox_listener_delivery_required = require("./outbox-listener-delivery-required-BX1utrrk.cjs");
|
|
2
2
|
//#region src/oxlint.ts
|
|
3
3
|
const rules = {
|
|
4
4
|
[require_outbox_listener_delivery_required.RULE_IDS.actorIdMismatch]: require_outbox_listener_delivery_required.eslint$18,
|
package/dist/oxlint.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as name, C as eslint$5, D as eslint$11, E as eslint$10, O as eslint$21, S as eslint$4, T as eslint$13, _ as eslint$15, a as eslint$23, b as eslint$2, c as eslint$16, d as eslint$22, f as eslint$6, g as eslint$14, h as eslint$9, i as eslint$27, j as version, k as RULE_IDS, l as eslint$17, m as eslint$8, n as eslint$25, o as eslint$18, p as eslint$7, r as eslint$26, s as eslint$19, t as eslint$24, u as eslint$20, v as eslint$1, w as eslint$12, x as eslint$3, y as eslint } from "./outbox-listener-delivery-required-
|
|
1
|
+
import { A as name, C as eslint$5, D as eslint$11, E as eslint$10, O as eslint$21, S as eslint$4, T as eslint$13, _ as eslint$15, a as eslint$23, b as eslint$2, c as eslint$16, d as eslint$22, f as eslint$6, g as eslint$14, h as eslint$9, i as eslint$27, j as version, k as RULE_IDS, l as eslint$17, m as eslint$8, n as eslint$25, o as eslint$18, p as eslint$7, r as eslint$26, s as eslint$19, t as eslint$24, u as eslint$20, v as eslint$1, w as eslint$12, x as eslint$3, y as eslint } from "./outbox-listener-delivery-required-BlITas9r.js";
|
|
2
2
|
//#region src/oxlint.ts
|
|
3
3
|
const rules = {
|
|
4
4
|
[RULE_IDS.actorIdMismatch]: eslint,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fedify/lint",
|
|
3
|
-
"version": "2.4.0-dev.
|
|
3
|
+
"version": "2.4.0-dev.2228+6d017d55",
|
|
4
4
|
"description": "Fedify linting rules and plugins",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Fedify",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
],
|
|
52
52
|
"peerDependencies": {
|
|
53
53
|
"eslint": ">=9.0.0",
|
|
54
|
-
"@fedify/fedify": "^2.4.0-dev.
|
|
54
|
+
"@fedify/fedify": "^2.4.0-dev.2228+6d017d55"
|
|
55
55
|
},
|
|
56
56
|
"peerDependenciesMeta": {
|
|
57
57
|
"eslint": {
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
"tsdown": "^0.22.0",
|
|
72
72
|
"typescript": "^6.0.0",
|
|
73
73
|
"@fedify/fixture": "2.0.0",
|
|
74
|
-
"@fedify/vocab": "2.4.0-dev.
|
|
74
|
+
"@fedify/vocab": "2.4.0-dev.2228+6d017d55"
|
|
75
75
|
},
|
|
76
76
|
"scripts": {
|
|
77
77
|
"build:self": "tsdown",
|