diff --git a/packages/eslint-plugin/src/rules/no-implied-eval.ts b/packages/eslint-plugin/src/rules/no-implied-eval.ts index 91bf0d0d319..8e19481653d 100644 --- a/packages/eslint-plugin/src/rules/no-implied-eval.ts +++ b/packages/eslint-plugin/src/rules/no-implied-eval.ts @@ -123,6 +123,15 @@ export default util.createRule({ } } + function isReferenceToGlobalFunction(calleeName: string): boolean { + const ref = context + .getScope() + .references.find(ref => ref.identifier.name === calleeName); + + // ensure it's the "global" version + return !ref?.resolved || ref.resolved.defs.length === 0; + } + function checkImpliedEval( node: TSESTree.NewExpression | TSESTree.CallExpression, ): void { @@ -156,7 +165,11 @@ export default util.createRule({ } const [handler] = node.arguments; - if (EVAL_LIKE_METHODS.has(calleeName) && !isFunction(handler)) { + if ( + EVAL_LIKE_METHODS.has(calleeName) && + !isFunction(handler) && + isReferenceToGlobalFunction(calleeName) + ) { context.report({ node: handler, messageId: 'noImpliedEvalError' }); } } diff --git a/packages/eslint-plugin/tests/rules/no-implied-eval.test.ts b/packages/eslint-plugin/tests/rules/no-implied-eval.test.ts index c789bd31121..f9c5bd137d6 100644 --- a/packages/eslint-plugin/tests/rules/no-implied-eval.test.ts +++ b/packages/eslint-plugin/tests/rules/no-implied-eval.test.ts @@ -276,6 +276,34 @@ class Foo { funcw(): void { setTimeout(this.a.b.c.bind(this), 1); } +} + `, + ` +function setTimeout(input: string, value: number) {} + +setTimeout('', 0); + `, + ` +declare module 'my-timers-promises' { + export function setTimeout(ms: number): void; +} + +import { setTimeout } from 'my-timers-promises'; + +setTimeout(1000); + `, + ` +function setTimeout() {} + +{ + setTimeout(100); +} + `, + ` +function setTimeout() {} + +{ + setTimeout("alert('evil!')"); } `, ],