mirror of
https://github.com/danbulant/oxc
synced 2026-05-25 04:42:10 +00:00
fix(transformer): TS namespace transform do not track var decl names (#3501)
Don't track variable declaration or import binding names in TS namespace transform. Babel does, but it appears to be wrong. It's illegal to have a `var`/`let`/`const` declaration or import in same scope as a TS namespace declaration with same binding. https://www.typescriptlang.org/play/?#code/JYWwDg9gTgLgBAQTgMyhEcDkUCmBDAYxkwG4AoAOzxBwGcxCdE4BvAXzLIIgtvgCE4AXjgBGclRr1GcQSzJxFcADY54AD3Icyq+AGFhYidToMCTA-KUq1cTWW0A3PFDgARQ+Monp596wUlXTstMiA
This commit is contained in:
parent
8d2beff2fe
commit
837776e1ab
3 changed files with 42 additions and 57 deletions
|
|
@ -30,7 +30,7 @@ impl<'a> TypeScript<'a> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect all binding names. Such as function name and class name.
|
// Collect function/class/enum/namespace binding names
|
||||||
let mut names: FxHashSet<Atom<'a>> = FxHashSet::default();
|
let mut names: FxHashSet<Atom<'a>> = FxHashSet::default();
|
||||||
|
|
||||||
// Recreate the statements vec for memory efficiency.
|
// Recreate the statements vec for memory efficiency.
|
||||||
|
|
@ -59,12 +59,11 @@ impl<'a> TypeScript<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
new_stmts.push(Statement::TSModuleDeclaration(decl));
|
new_stmts.push(Statement::TSModuleDeclaration(decl));
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
match_module_declaration!(Statement) => {
|
Statement::ExportNamedDeclaration(ref export_decl) => {
|
||||||
if let Statement::ExportNamedDeclaration(export_decl) = &stmt {
|
match &export_decl.declaration {
|
||||||
if let Some(Declaration::TSModuleDeclaration(decl)) =
|
Some(Declaration::TSModuleDeclaration(decl)) => {
|
||||||
&export_decl.declaration
|
|
||||||
{
|
|
||||||
if !decl.modifiers.is_contains_declare() {
|
if !decl.modifiers.is_contains_declare() {
|
||||||
if !self.options.allow_namespaces {
|
if !self.options.allow_namespaces {
|
||||||
self.ctx.error(namespace_not_supported(decl.span));
|
self.ctx.error(namespace_not_supported(decl.span));
|
||||||
|
|
@ -91,37 +90,32 @@ impl<'a> TypeScript<'a> {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stmt.to_module_declaration().bound_names(&mut |id| {
|
if let TSModuleDeclarationName::Identifier(id) = &decl.id {
|
||||||
names.insert(id.name.clone());
|
names.insert(id.name.clone());
|
||||||
});
|
}
|
||||||
new_stmts.push(stmt);
|
}
|
||||||
|
Some(decl) => match decl {
|
||||||
|
Declaration::FunctionDeclaration(_)
|
||||||
|
| Declaration::ClassDeclaration(_)
|
||||||
|
| Declaration::TSEnumDeclaration(_) => {
|
||||||
|
names.insert(decl.id().as_ref().unwrap().name.clone());
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Collect bindings from class, function, variable and enum declarations
|
// Collect bindings from class, function and enum declarations
|
||||||
Statement::FunctionDeclaration(ref decl) => {
|
Statement::FunctionDeclaration(_)
|
||||||
names.insert(decl.id.as_ref().unwrap().name.clone());
|
| Statement::ClassDeclaration(_)
|
||||||
new_stmts.push(stmt);
|
| Statement::TSEnumDeclaration(_) => {
|
||||||
}
|
names.insert(stmt.to_declaration().id().as_ref().unwrap().name.clone());
|
||||||
Statement::ClassDeclaration(ref decl) => {
|
|
||||||
names.insert(decl.id.as_ref().unwrap().name.clone());
|
|
||||||
new_stmts.push(stmt);
|
|
||||||
}
|
|
||||||
Statement::TSEnumDeclaration(ref decl) => {
|
|
||||||
names.insert(decl.id.name.clone());
|
|
||||||
new_stmts.push(stmt);
|
|
||||||
}
|
|
||||||
Statement::VariableDeclaration(ref decl) => {
|
|
||||||
decl.bound_names(&mut |id| {
|
|
||||||
names.insert(id.name.clone());
|
|
||||||
});
|
|
||||||
new_stmts.push(stmt);
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
new_stmts.push(stmt);
|
|
||||||
}
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
new_stmts.push(stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
program.body = new_stmts;
|
program.body = new_stmts;
|
||||||
|
|
@ -185,24 +179,7 @@ impl<'a> TypeScript<'a> {
|
||||||
}
|
}
|
||||||
new_stmts.push(transformed);
|
new_stmts.push(transformed);
|
||||||
}
|
}
|
||||||
}
|
continue;
|
||||||
Statement::ClassDeclaration(ref decl) => {
|
|
||||||
names.insert(decl.id.as_ref().unwrap().name.clone());
|
|
||||||
new_stmts.push(stmt);
|
|
||||||
}
|
|
||||||
Statement::FunctionDeclaration(ref decl) => {
|
|
||||||
names.insert(decl.id.as_ref().unwrap().name.clone());
|
|
||||||
new_stmts.push(stmt);
|
|
||||||
}
|
|
||||||
Statement::TSEnumDeclaration(ref enum_decl) => {
|
|
||||||
names.insert(enum_decl.id.name.clone());
|
|
||||||
new_stmts.push(stmt);
|
|
||||||
}
|
|
||||||
Statement::VariableDeclaration(ref decl) => {
|
|
||||||
decl.bound_names(&mut |id| {
|
|
||||||
names.insert(id.name.clone());
|
|
||||||
});
|
|
||||||
new_stmts.push(stmt);
|
|
||||||
}
|
}
|
||||||
Statement::ExportNamedDeclaration(export_decl) => {
|
Statement::ExportNamedDeclaration(export_decl) => {
|
||||||
// NB: `ExportNamedDeclaration` with no declaration (e.g. `export {x}`) is not
|
// NB: `ExportNamedDeclaration` with no declaration (e.g. `export {x}`) is not
|
||||||
|
|
@ -252,14 +229,20 @@ impl<'a> TypeScript<'a> {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Collect bindings from class, function and enum declarations
|
||||||
|
Statement::ClassDeclaration(_)
|
||||||
|
| Statement::FunctionDeclaration(_)
|
||||||
|
| Statement::TSEnumDeclaration(_) => {
|
||||||
|
names.insert(stmt.to_declaration().id().as_ref().unwrap().name.clone());
|
||||||
}
|
}
|
||||||
Statement::TSTypeAliasDeclaration(_)
|
Statement::TSTypeAliasDeclaration(_)
|
||||||
| Statement::TSInterfaceDeclaration(_)
|
| Statement::TSInterfaceDeclaration(_)
|
||||||
| Statement::TSImportEqualsDeclaration(_) => {}
|
| Statement::TSImportEqualsDeclaration(_) => continue,
|
||||||
_ => {
|
_ => {}
|
||||||
new_stmts.push(stmt);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
new_stmts.push(stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
if new_stmts.is_empty() {
|
if new_stmts.is_empty() {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
commit: 4bd1b2c2
|
commit: 4bd1b2c2
|
||||||
|
|
||||||
Passed: 480/928
|
Passed: 478/926
|
||||||
|
|
||||||
# All Passed:
|
# All Passed:
|
||||||
* babel-preset-react
|
* babel-preset-react
|
||||||
|
|
@ -445,7 +445,7 @@ Passed: 480/928
|
||||||
* opts/optimizeConstEnums/input.ts
|
* opts/optimizeConstEnums/input.ts
|
||||||
* opts/rewriteImportExtensions/input.ts
|
* opts/rewriteImportExtensions/input.ts
|
||||||
|
|
||||||
# babel-plugin-transform-typescript (136/152)
|
# babel-plugin-transform-typescript (134/150)
|
||||||
* enum/mix-references/input.ts
|
* enum/mix-references/input.ts
|
||||||
* enum/ts5.0-const-foldable/input.ts
|
* enum/ts5.0-const-foldable/input.ts
|
||||||
* exports/declared-types/input.ts
|
* exports/declared-types/input.ts
|
||||||
|
|
|
||||||
|
|
@ -91,5 +91,7 @@ pub(crate) const SKIP_TESTS: &[&str] = &[
|
||||||
"typescript/test/fixtures/namespace/nested-shorthand-export/input.ts",
|
"typescript/test/fixtures/namespace/nested-shorthand-export/input.ts",
|
||||||
"react-jsx-development/test/fixtures/cross-platform/self-inside-arrow/input.mjs",
|
"react-jsx-development/test/fixtures/cross-platform/self-inside-arrow/input.mjs",
|
||||||
// Babel outputs is not correct
|
// Babel outputs is not correct
|
||||||
|
"typescript/test/fixtures/namespace/clobber-import/input.ts",
|
||||||
|
"typescript/test/fixtures/namespace/namespace-nested-module/input.ts",
|
||||||
"typescript/test/fixtures/namespace/nested-destructuring/input.ts",
|
"typescript/test/fixtures/namespace/nested-destructuring/input.ts",
|
||||||
];
|
];
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue