From 628a49762e75299232648dc6ee473ad25347d9ce Mon Sep 17 00:00:00 2001 From: Rel1cx Date: Fri, 21 Nov 2025 11:42:03 +0800 Subject: [PATCH] 'no-leaked-event-listener' does not report handlers with a singal arg, closes #1282 --- .../rules/no-leaked-event-listener.spec.ts | 124 +++++++++--------- .../src/rules/no-leaked-event-listener.ts | 6 +- 2 files changed, 67 insertions(+), 63 deletions(-) diff --git a/packages/plugins/eslint-plugin-react-web-api/src/rules/no-leaked-event-listener.spec.ts b/packages/plugins/eslint-plugin-react-web-api/src/rules/no-leaked-event-listener.spec.ts index 61626033fc..380766fc71 100644 --- a/packages/plugins/eslint-plugin-react-web-api/src/rules/no-leaked-event-listener.spec.ts +++ b/packages/plugins/eslint-plugin-react-web-api/src/rules/no-leaked-event-listener.spec.ts @@ -146,24 +146,24 @@ ruleTester.run(RULE_NAME, rule, { }, ], }, - { - code: tsx` - function Example() { - useEffect(() => { - const ab = new AbortController(); - window.addEventListener("resize", () => {}, { signal: ab.signal }); - return () => { - // ab.abort(); - }; - }, []); - } - `, - errors: [ - { - messageId: "expectedRemoveEventListenerInCleanup", - }, - ], - }, + // { + // code: tsx` + // function Example() { + // useEffect(() => { + // const ab = new AbortController(); + // window.addEventListener("resize", () => {}, { signal: ab.signal }); + // return () => { + // // ab.abort(); + // }; + // }, []); + // } + // `, + // errors: [ + // { + // messageId: "expectedRemoveEventListenerInCleanup", + // }, + // ], + // }, { code: tsx` function Example() { @@ -385,50 +385,50 @@ ruleTester.run(RULE_NAME, rule, { }, ], }, - { - code: tsx` - const abortController = new AbortController(); - function Example() { - const rHandleResize = useRef(() => {}); - useEffect(() => { - window.addEventListener("focus", rHandleResize.current, { once: false, passive: true, capture: true, signal: abortController.signal }); - window.addEventListener("resize", rHandleResize.current, { once: false, passive: true, capture: true, signal: abortController.signal }); - return () => { - // abortController.abort(); - }; - }, []); - } - `, - errors: [ - { - messageId: "expectedRemoveEventListenerInCleanup", - }, - { - messageId: "expectedRemoveEventListenerInCleanup", - }, - ], - }, - { - code: tsx` - const abortController1 = new AbortController(); - const abortController2 = new AbortController(); - function Example() { - const rHandleResize = useRef(() => {}); - useEffect(() => { - window.addEventListener("focus", rHandleResize.current, { once: false, passive: true, capture: true, signal: abortController1.signal }); - window.addEventListener("resize", rHandleResize.current, { once: false, passive: true, capture: true, signal: abortController2.signal }); - return () => { - abortController1.abort(); - }; - }, []); - } - `, - errors: [ - { - messageId: "expectedRemoveEventListenerInCleanup", - }, - ], - }, + // { + // code: tsx` + // const abortController = new AbortController(); + // function Example() { + // const rHandleResize = useRef(() => {}); + // useEffect(() => { + // window.addEventListener("focus", rHandleResize.current, { once: false, passive: true, capture: true, signal: abortController.signal }); + // window.addEventListener("resize", rHandleResize.current, { once: false, passive: true, capture: true, signal: abortController.signal }); + // return () => { + // // abortController.abort(); + // }; + // }, []); + // } + // `, + // errors: [ + // { + // messageId: "expectedRemoveEventListenerInCleanup", + // }, + // { + // messageId: "expectedRemoveEventListenerInCleanup", + // }, + // ], + // }, + // { + // code: tsx` + // const abortController1 = new AbortController(); + // const abortController2 = new AbortController(); + // function Example() { + // const rHandleResize = useRef(() => {}); + // useEffect(() => { + // window.addEventListener("focus", rHandleResize.current, { once: false, passive: true, capture: true, signal: abortController1.signal }); + // window.addEventListener("resize", rHandleResize.current, { once: false, passive: true, capture: true, signal: abortController2.signal }); + // return () => { + // abortController1.abort(); + // }; + // }, []); + // } + // `, + // errors: [ + // { + // messageId: "expectedRemoveEventListenerInCleanup", + // }, + // ], + // }, { code: tsx` import { useEffect } from "react"; diff --git a/packages/plugins/eslint-plugin-react-web-api/src/rules/no-leaked-event-listener.ts b/packages/plugins/eslint-plugin-react-web-api/src/rules/no-leaked-event-listener.ts index ceb3df2947..fa2087cfdd 100644 --- a/packages/plugins/eslint-plugin-react-web-api/src/rules/no-leaked-event-listener.ts +++ b/packages/plugins/eslint-plugin-react-web-api/src/rules/no-leaked-event-listener.ts @@ -292,7 +292,11 @@ export function create(context: RuleContext): RuleListener { ["Program:exit"]() { for (const aEntry of aEntries) { const signal = aEntry.signal; - if (signal != null && abortedSignals.some((a) => isSameObject(a, signal))) { + // https://github.com/Rel1cx/eslint-react/issues/1282#issuecomment-3536511881 + // if (signal != null && abortedSignals.some((a) => isSameObject(a, signal))) { + // continue; + // } + if (signal != null) { continue; } if (rEntries.some((rEntry) => isInverseEntry(aEntry, rEntry))) {