Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions crates/oxc_semantic/src/checker/javascript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,34 @@ pub fn check_unresolved_exports(program: &Program<'_>, ctx: &SemanticBuilder<'_>
}
}

/// It is a Syntax Error if any element of the BoundNames of ImportDeclaration
/// also occurs in the VarDeclaredNames or LexicallyDeclaredNames of ModuleItemList.
/// <https://tc39.es/ecma262/#sec-imports-static-semantics-early-errors>
pub fn check_import_value_redeclarations(ctx: &SemanticBuilder<'_>) {
if !ctx.source_type.is_module() || ctx.source_type.is_typescript() {
return;
}

let scope_id = ctx.scoping.root_scope_id();
for (_, &symbol_id) in ctx.scoping.get_bindings(scope_id) {
let flags = ctx.scoping.symbol_flags(symbol_id);
if !flags.contains(SymbolFlags::Import) {
continue;
}
if !flags.intersects(SymbolFlags::Variable | SymbolFlags::Class | SymbolFlags::Function) {
continue;
}
let redeclarations = ctx.scoping.symbol_redeclarations(symbol_id);
if redeclarations.len() < 2 {
continue;
}
let name = ctx.scoping.symbol_name(symbol_id);
let first = &redeclarations[0];
let last = &redeclarations[redeclarations.len() - 1];
ctx.error(diagnostics::redeclaration(name, first.span, last.span));
}
}

pub fn check_duplicate_class_elements(ctx: &SemanticBuilder<'_>) {
let classes = &ctx.class_table_builder.classes;
classes.iter_enumerated().for_each(|(class_id, _)| {
Expand Down
1 change: 1 addition & 0 deletions crates/oxc_semantic/src/checker/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub fn check<'a>(kind: AstKind<'a>, ctx: &SemanticBuilder<'a>) {
AstKind::Program(program) => {
js::check_duplicate_class_elements(ctx);
js::check_unresolved_exports(program, ctx);
js::check_import_value_redeclarations(ctx);
ts::check_ts_export_assignment_in_program(program, ctx);
}
AstKind::BindingIdentifier(ident) => {
Expand Down
24 changes: 24 additions & 0 deletions crates/oxc_semantic/tests/integration/symbols.rs
Original file line number Diff line number Diff line change
Expand Up @@ -452,3 +452,27 @@ fn test_function_var_redeclaration_in_module() {
SemanticTester::js("function a() {} var a = ''").has_error("already been declared");
SemanticTester::js("var a = ''; function a() {}").has_error("already been declared");
}

// https://github.com/oxc-project/oxc/issues/15961
#[test]
fn test_import_value_redeclaration_in_module() {
// Import + var
SemanticTester::js("import { Foo } from './foo.js'; var Foo;")
.has_error("already been declared");
SemanticTester::js("var Foo; import { Foo } from './foo.js';")
.has_error("already been declared");
// Import + let
SemanticTester::js("import { Foo } from './foo.js'; let Foo;")
.has_error("already been declared");
// Import + const
SemanticTester::js("import { Foo } from './foo.js'; const Foo = 1;")
.has_error("already been declared");
// Import + class
SemanticTester::js("import { Foo } from './foo.js'; class Foo {}")
.has_error("already been declared");
// Import + function
SemanticTester::js("import { Foo } from './foo.js'; function Foo() {}")
.has_error("already been declared");
// TypeScript should NOT report this error (declaration merging)
SemanticTester::ts("import { Foo } from './foo.js'; var Foo;").has_root_symbol("Foo").test();
}
4 changes: 2 additions & 2 deletions tasks/coverage/snapshots/codegen_typescript.snap
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
commit: 95e3aaa9

codegen_typescript Summary:
AST Parsed : 9841/9841 (100.00%)
Positive Passed: 9841/9841 (100.00%)
AST Parsed : 9840/9840 (100.00%)
Positive Passed: 9840/9840 (100.00%)
4 changes: 2 additions & 2 deletions tasks/coverage/snapshots/estree_typescript.snap
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
commit: 95e3aaa9

estree_typescript Summary:
AST Parsed : 9774/9774 (100.00%)
Positive Passed: 9756/9774 (99.82%)
AST Parsed : 9773/9773 (100.00%)
Positive Passed: 9755/9773 (99.82%)
Mismatch: tasks/coverage/typescript/tests/cases/compiler/moduleDetectionIsolatedModulesCjsFileScope.ts

Mismatch: tasks/coverage/typescript/tests/cases/compiler/moduleNodeImportRequireEmit.ts
Expand Down
4 changes: 2 additions & 2 deletions tasks/coverage/snapshots/formatter_typescript.snap
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
commit: 95e3aaa9

formatter_typescript Summary:
AST Parsed : 9841/9841 (100.00%)
Positive Passed: 9789/9841 (99.47%)
AST Parsed : 9840/9840 (100.00%)
Positive Passed: 9788/9840 (99.47%)
Mismatch: tasks/coverage/typescript/tests/cases/compiler/amdLikeInputDeclarationEmit.ts

Mismatch: tasks/coverage/typescript/tests/cases/compiler/castExpressionParentheses.ts
Expand Down
4 changes: 2 additions & 2 deletions tasks/coverage/snapshots/parser_typescript.snap
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
commit: 95e3aaa9

parser_typescript Summary:
AST Parsed : 9841/9841 (100.00%)
Positive Passed: 9841/9841 (100.00%)
AST Parsed : 9840/9840 (100.00%)
Positive Passed: 9840/9840 (100.00%)
Negative Passed: 1530/2558 (59.81%)
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/FunctionDeclaration3.ts

Expand Down
4 changes: 2 additions & 2 deletions tasks/coverage/snapshots/semantic_typescript.snap
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
commit: 95e3aaa9

semantic_typescript Summary:
AST Parsed : 5483/5483 (100.00%)
Positive Passed: 2951/5483 (53.82%)
AST Parsed : 5482/5482 (100.00%)
Positive Passed: 2950/5482 (53.81%)
semantic Error: tasks/coverage/typescript/tests/cases/compiler/2dArrays.ts
Symbol reference IDs mismatch for "Cell":
after transform: SymbolId(0): [ReferenceId(1)]
Expand Down
4 changes: 2 additions & 2 deletions tasks/coverage/snapshots/transformer_typescript.snap
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
commit: 95e3aaa9

transformer_typescript Summary:
AST Parsed : 9841/9841 (100.00%)
Positive Passed: 9819/9841 (99.78%)
AST Parsed : 9840/9840 (100.00%)
Positive Passed: 9818/9840 (99.78%)
Mismatch: tasks/coverage/typescript/tests/cases/compiler/classOverloadForFunction.ts

Mismatch: tasks/coverage/typescript/tests/cases/compiler/exportSpecifierForAGlobal.ts
Expand Down
3 changes: 3 additions & 0 deletions tasks/coverage/src/typescript/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ pub static NOT_SUPPORTED_TEST_PATHS: phf::Set<&'static str> = phf::phf_set![
// TSC: Does not report errors since `.js` file with `checkJs: false`
// OXC: Reports errors
"plainJSRedeclare3.ts",
// TSC: Allows import+const redeclaration in `.js` file with `allowJs: true`
// OXC: Reports redeclaration error per ES spec
"usedImportNotElidedInJs.ts",
// TSC: Parse without error, they support BOM
// OXC: We do not ignore or exclude BOM, will be invalid character error
"bom-utf16be.ts",
Expand Down
Loading