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
- Wrap the file body in an IIFE: (() => { ... })();.
- Convert the file to an ES module (add import/export or set "type": "module").
- If a real global is intended, assign it explicitly: globalThis.config = {...} or window.config = {...}.
- 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
- Wrap script-file bodies in IIFEs to obtain local scope.
- Prefer ES modules; set "type": "module" where possible.
- Assign deliberate globals explicitly on globalThis/window.
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
- Global variable leak.
- Unexpected lexical declaration in case block.
- Read-only global '{global_name}' should not be modified.
- Unexpected assignment to read-only global variable.
- Unexpected redeclaration of read-only global variable.
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/3f1ccead396a7c00.
Report an issue: GitHub.