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

  1. Pass a function: setTimeout(() => doLogin(), 100) or setTimeout(doLogin, 100).
  2. When the call name comes from data, dispatch through a lookup map instead of composing a string.
  3. 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

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


AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20). Data as JSON: /api/errors/573460d9710e4724. Report an issue: GitHub.