oxc-project/oxc · warning
Implied eval. Consider passing a function instead of a strin
Error message
Implied eval. Consider passing a function instead of a string.
What it means
Diagnostic from oxlint's no-implied-eval rule. Calling setTimeout or setInterval with a string first argument behaves like eval: the string is compiled as code at runtime, enabling injection and defeating JIT optimization. The rule reports 'Implied eval. Consider passing a function instead of a string.', including concatenated or computed strings like setTimeout('run(' + id + ')', 0), after verifying the callee resolves to the global timer function.
Source
Thrown at crates/oxc_linter/src/rules/eslint/no_implied_eval.rs:14
use oxc_ast::{
AstKind,
ast::{Argument, CallExpression, Expression, IdentifierReference, MemberExpression},
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_semantic::IsGlobalReference;
use oxc_span::Span;
use oxc_syntax::operator::{BinaryOperator, UnaryOperator};
use crate::{AstNode, config::GlobalValue, context::LintContext, rule::Rule};
fn implied_eval_diagnostic(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("Implied eval. Consider passing a function instead of a string.")
.with_help("Pass a function callback instead of source text.")
.with_label(span)
}
fn exec_script_diagnostic(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("Implied eval. Do not use execScript().")
.with_help("Avoid executing source text at runtime.")
.with_label(span)
}
#[derive(Debug, Default, Clone)]
pub struct NoImpliedEval;
declare_oxc_lint!(
/// ### What it does
///
/// Disallows passing strings to `setTimeout()`, `setInterval()`, and
/// `execScript()`.View on GitHub (pinned to e1e7af627c)
Solutions
- Pass a function: setTimeout(() => doLogin(), 100) or setTimeout(doLogin, 100).
- When the call name comes from data, dispatch through a lookup map instead of composing a string.
- If truly unavoidable in a sandboxed legacy file, suppress with // oxlint-disable-next-line eslint/no-implied-eval.
Example fix
// before
setTimeout('refresh(' + id + ')', 500);
// after
setTimeout(() => refresh(id), 500); Defensive patterns
Strategy: validation
Validate before calling
const stringTimer = /(?:setTimeout|setInterval)\s*\(\s*['\"`]/.test(source);
Prevention
- Always pass functions or closures to setTimeout/setInterval.
- Map dynamic handler names through a lookup object instead of composing strings.
- Treat any string argument to a timer as a security smell in review.
When it happens
Trigger: setTimeout('doLogin()', 100);; setInterval("tick()", 1000);; setTimeout('refresh(' + id + ')', 500);; timer handlers built from server-provided strings.
Common situations: Legacy scheduling code from pre-ES5-era tutorials; dynamic handler names delivered by config or an API; security reviews that switch the rule on for the first time.
Related errors
- Implied eval. Do not use execScript().
- eval can be harmful.
- Empty array binding pattern
- Empty object binding pattern
- Using target=`_blank` without rel=`noreferrer` (which implie
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/573460d9710e4724.
Report an issue: GitHub.