diff --git a/apps/oxlint/test/fixtures/languageOptions/output.snap.md b/apps/oxlint/test/fixtures/languageOptions/output.snap.md index 4abc4cf6b799d..74125083ac3ae 100644 --- a/apps/oxlint/test/fixtures/languageOptions/output.snap.md +++ b/apps/oxlint/test/fixtures/languageOptions/output.snap.md @@ -4,9 +4,9 @@ # stdout ``` x language-options-plugin(lang): languageOptions: - | sourceType: script + | sourceType: commonjs | ecmaVersion: 2026 - | parserOptions: {"sourceType":"script"} + | parserOptions: {"sourceType":"commonjs"} | globals: {} | env: {"builtin":true} ,-[files/index.cjs:1:1] diff --git a/crates/oxc_linter/src/loader/partial_loader/vue.rs b/crates/oxc_linter/src/loader/partial_loader/vue.rs index 14804f6870666..c66b3510ee4bf 100644 --- a/crates/oxc_linter/src/loader/partial_loader/vue.rs +++ b/crates/oxc_linter/src/loader/partial_loader/vue.rs @@ -316,7 +316,10 @@ mod test { let cases = [ ("", Some(SourceType::mjs())), ("", Some(SourceType::tsx())), - (r#""#, Some(SourceType::cjs())), + ( + r#""#, + Some(SourceType::from_extension("cjs").unwrap()), + ), ("", Some(SourceType::tsx())), ("", None), (r#""#, None), diff --git a/crates/oxc_linter/src/rules/eslint/no_eval.rs b/crates/oxc_linter/src/rules/eslint/no_eval.rs index b31affd1b8acd..fa966421209b5 100644 --- a/crates/oxc_linter/src/rules/eslint/no_eval.rs +++ b/crates/oxc_linter/src/rules/eslint/no_eval.rs @@ -200,7 +200,9 @@ impl Rule for NoEval { } let is_valid = if scope_flags.is_top() { - ctx.semantic().source_type().is_script() + // In scripts and CommonJS, `this` at top level refers to the global object + // In ES modules, `this` at top level is undefined + !ctx.semantic().source_type().is_module() } else { let node = ctx.nodes().get_node(ctx.scoping().get_node_id(scope_id)); ast_util::is_default_this_binding(ctx, node, true) diff --git a/crates/oxc_linter/src/rules/eslint/no_redeclare.rs b/crates/oxc_linter/src/rules/eslint/no_redeclare.rs index caa0049a1bd48..ec188fcf016a9 100644 --- a/crates/oxc_linter/src/rules/eslint/no_redeclare.rs +++ b/crates/oxc_linter/src/rules/eslint/no_redeclare.rs @@ -2,7 +2,7 @@ use javascript_globals::GLOBALS; use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; -use oxc_span::{ModuleKind, Span}; +use oxc_span::Span; use schemars::JsonSchema; use serde::Deserialize; @@ -122,8 +122,8 @@ impl Rule for NoRedeclare { } fn should_run(&self, ctx: &ContextHost) -> bool { - // Modules run in their own scope, and don't conflict with existing globals - ctx.source_type().module_kind() == ModuleKind::Script + // ES modules run in their own scope, and don't conflict with existing globals + !ctx.source_type().is_module() } } diff --git a/crates/oxc_span/src/source_type.rs b/crates/oxc_span/src/source_type.rs index 04720dd960841..84ba3f7509014 100644 --- a/crates/oxc_span/src/source_type.rs +++ b/crates/oxc_span/src/source_type.rs @@ -194,7 +194,7 @@ impl From for SourceType { let module_kind = match file_ext { Js | Tsx | Ts | Jsx | Mts | Mjs => ModuleKind::Module, - Cjs | Cts => ModuleKind::Script, + Cjs | Cts => ModuleKind::CommonJS, }; let variant = match file_ext { @@ -665,9 +665,14 @@ mod tests { assert!(!ts.is_script()); assert!(!mts.is_script()); - assert!(cts.is_script()); + assert!(!cts.is_script()); assert!(!tsx.is_script()); + assert!(!ts.is_commonjs()); + assert!(!mts.is_commonjs()); + assert!(cts.is_commonjs()); + assert!(!tsx.is_commonjs()); + assert!(ts.is_strict()); assert!(mts.is_strict()); assert!(!cts.is_strict()); @@ -700,7 +705,11 @@ mod tests { assert!(!dts.is_script()); assert!(!dmts.is_script()); - assert!(dcts.is_script()); + assert!(!dcts.is_script()); + + assert!(!dts.is_commonjs()); + assert!(!dmts.is_commonjs()); + assert!(dcts.is_commonjs()); assert!(dts.is_strict()); assert!(dmts.is_strict()); diff --git a/tasks/coverage/snapshots/parser_misc.snap b/tasks/coverage/snapshots/parser_misc.snap index 9d516d25503cf..f1dc25bcf3de6 100644 --- a/tasks/coverage/snapshots/parser_misc.snap +++ b/tasks/coverage/snapshots/parser_misc.snap @@ -1,47 +1,9 @@ parser_misc Summary: AST Parsed : 59/59 (100.00%) -Positive Passed: 55/59 (93.22%) +Positive Passed: 59/59 (100.00%) Negative Passed: 128/129 (99.22%) Expect Syntax Error: tasks/coverage/misc/fail/script-top-level-using.js -Expect to Parse: tasks/coverage/misc/pass/commonjs-top-level-new-target.cjs - - × Unexpected new.target expression - ╭─[misc/pass/commonjs-top-level-new-target.cjs:2:1] - 1 │ // CommonJS allows top-level new.target because the file is wrapped in a function - 2 │ new.target; - · ────────── - ╰──── - help: new.target is only allowed in constructors and functions invoked using the `new` operator - -Expect to Parse: tasks/coverage/misc/pass/commonjs-top-level-new-target.cts - - × Unexpected new.target expression - ╭─[misc/pass/commonjs-top-level-new-target.cts:2:1] - 1 │ // TypeScript CommonJS allows top-level new.target - 2 │ new.target; - · ────────── - ╰──── - help: new.target is only allowed in constructors and functions invoked using the `new` operator - -Expect to Parse: tasks/coverage/misc/pass/commonjs-top-level-return.cjs - - × TS(1108): A 'return' statement can only be used within a function body. - ╭─[misc/pass/commonjs-top-level-return.cjs:2:1] - 1 │ // CommonJS allows top-level return because the file is wrapped in a function - 2 │ return 42; - · ────── - ╰──── - -Expect to Parse: tasks/coverage/misc/pass/commonjs-top-level-return.cts - - × TS(1108): A 'return' statement can only be used within a function body. - ╭─[misc/pass/commonjs-top-level-return.cts:2:1] - 1 │ // TypeScript CommonJS allows top-level return - 2 │ return 42; - · ────── - ╰──── - × Cannot assign to 'arguments' in strict mode ╭─[misc/fail/arguments-eval.ts:1:10] diff --git a/tasks/coverage/snapshots/semantic_misc.snap b/tasks/coverage/snapshots/semantic_misc.snap index 4515290530afa..82e4ad41286a6 100644 --- a/tasks/coverage/snapshots/semantic_misc.snap +++ b/tasks/coverage/snapshots/semantic_misc.snap @@ -1,18 +1,6 @@ semantic_misc Summary: AST Parsed : 59/59 (100.00%) -Positive Passed: 36/59 (61.02%) -semantic Error: tasks/coverage/misc/pass/commonjs-top-level-new-target.cjs -Unexpected new.target expression - -semantic Error: tasks/coverage/misc/pass/commonjs-top-level-new-target.cts -Unexpected new.target expression - -semantic Error: tasks/coverage/misc/pass/commonjs-top-level-return.cjs -A 'return' statement can only be used within a function body. - -semantic Error: tasks/coverage/misc/pass/commonjs-top-level-return.cts -A 'return' statement can only be used within a function body. - +Positive Passed: 40/59 (67.80%) semantic Error: tasks/coverage/misc/pass/declare-let-private.ts Bindings mismatch: after transform: ScopeId(0): ["private"]