oxc-project/oxc · warning

Unexpected {kind} declaration in the global scope.

Error message

Unexpected {kind} declaration in the global scope.

What it means

Diagnostic from oxlint's no-implicit-globals rule. In classic scripts (non-module files) a top-level var or function declaration does not create a file-local binding; it writes properties onto the global object shared by every script in the runtime. The rule reports 'Unexpected {kind} declaration in the global scope.' with kind 'var' or 'function' and suggests wrapping in an IIFE or assigning an explicit global property.

Source

Thrown at crates/oxc_linter/src/rules/eslint/no_implicit_globals.rs:17

use javascript_globals::{GLOBALS, GLOBALS_BUILTIN};
use oxc_ast::AstKind;
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{GetSpan, Span};
use oxc_syntax::{reference::Reference, symbol::SymbolFlags};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

use crate::{
    config::GlobalValue,
    context::LintContext,
    rule::{DefaultRuleConfig, Rule},
};

fn global_non_lexical_binding_diagnostic(kind: &'static str, span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn(format!("Unexpected {kind} declaration in the global scope."))
        .with_help(
            "Wrap it in an IIFE for a local variable, or assign it as a global property for a global variable.",
        )
        .with_label(span)
}

fn global_lexical_binding_diagnostic(kind: &'static str, span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn(format!("Unexpected {kind} declaration in the global scope."))
        .with_help("Wrap it in a block or in an IIFE.")
        .with_label(span)
}

fn global_variable_leak_diagnostic(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("Global variable leak.")
        .with_help("Declare the variable if it is intended to be local.")
        .with_label(span)
}

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Wrap the file body in an IIFE: (() => { ... })();.
  2. Convert the file to an ES module (add import/export or set "type": "module").
  3. If a real global is intended, assign it explicitly: globalThis.config = {...} or window.config = {...}.
  4. Introduce a bundler so each file gets its own scope.

Example fix

// before (script.js, loaded via <script>)
var config = { debug: false };
function boot() {
  /* ... */
}

// after
(() => {
  const config = { debug: false };
  function boot() {
    /* ... */
  }
})();
Defensive patterns

Strategy: validation

Validate before calling

const isScript = !/^\s*(?:import|export)\b/m.test(source);
const leaks = isScript && /^\s*(?:var\b|function\b)/m.test(source);

Prevention

When it happens

Trigger: A .js file loaded via a script tag containing top-level var config = {...} or function boot() {}; bundler-less deployments where several scripts share the page; script files with no import/export statements.

Common situations: Legacy browser apps and widgets; missing "type": "module" in package.json so files are treated as scripts; ads/analytics snippets polluting the page; migrating an old codebase toward modules.

Related errors


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