oxc-project/oxc · warning · OxcDiagnostic
All 'var' declarations must be at the top of the function sc
Error message
All 'var' declarations must be at the top of the function scope.
What it means
oxlint's `vars-on-top` rule enforces the style where every `var` declaration in a function (or program) scope precedes all other statements — matching what hoisting actually does at runtime. The diagnostic fires on any var declaration that follows a non-var statement in its scope; ambient TypeScript contexts are exempted via `has_ambient_typescript_ancestor`.
Source
Thrown at crates/oxc_linter/src/rules/eslint/vars_on_top.rs:10
use oxc_ast::AstKind;
use oxc_ast::ast::{Declaration, Expression, Program, Statement, VariableDeclarationKind};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{GetSpan, Span};
use crate::{AstNode, context::LintContext, rule::Rule, utils::has_ambient_typescript_ancestor};
fn vars_on_top_diagnostic(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("All 'var' declarations must be at the top of the function scope.")
.with_help("Consider moving this to the top of the functions scope or using let or const to declare this variable.")
.with_label(span)
}
#[derive(Debug, Default, Clone)]
pub struct VarsOnTop;
declare_oxc_lint!(
/// ### What it does
///
/// Enforces that all `var` declarations are placed at the top of their containing scope.
///
/// ### Why is this bad?
///
/// In JavaScript, `var` declarations are hoisted to the top of their containing scope. Placing `var` declarations at the top explicitly improves code readability and maintainability by making the scope of variables clear.
///
/// ### Examples
///View on GitHub (pinned to e1e7af627c)
Solutions
- Replace var with let/const declared where the value is first needed (preferred modern fix)
- Or move the var declarations to the top of the function scope
- Disable or downgrade `vars-on-top` if the team has fully adopted let/const and the rule is pure noise
Example fix
// before
function process(input) {
validate(input);
var results = [];
for (var item of input) results.push(transform(item));
return results;
}
// after
function process(input) {
validate(input);
const results = [];
for (const item of input) results.push(transform(item));
return results;
} Defensive patterns
Strategy: validation
Validate before calling
// .oxlintrc.json
{ "rules": { "vars-on-top": "warn" } }
// pre-commit: npx oxlint --fix src/legacy/ Prevention
- Prefer let/const at point of use; var should be rare enough that the rule stays quiet
- Isolate hoisting-prone ES5 code in folders with their own lint config
- Watch merge conflicts that move statements above existing var declarations
- Run the fixer on legacy directories during migrations, not hand-edits
When it happens
Trigger: `function f() { doFirst(); var x = 1; }` — a VariableDeclaration of kind var appearing after expression or other statements within the same function scope (or top-level program scope).
Common situations: Legacy ES5 codebases; incremental migrations where pockets of var remain; merge conflicts that move statements above existing var declarations.
Related errors
- Unexpected comment inline with code
- Variable or `function` declarations are not allowed in neste
- Unexpected var, use let or const instead.
- Use a regular expression literal instead of the `RegExp` con
- Expected '{curr_kind}' syntax before '{prev_kind}' syntax.
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/322bc7444c339176.
Report an issue: GitHub.