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
4 changes: 4 additions & 0 deletions crates/oxc_semantic/src/scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,10 @@ impl ScopeTree {
self.bindings[scope_id].insert(name, symbol_id);
}

pub fn remove_binding(&mut self, scope_id: ScopeId, name: &CompactStr) {
self.bindings[scope_id].shift_remove(name);
}

pub(crate) fn add_unresolved_reference(
&mut self,
scope_id: ScopeId,
Expand Down
4 changes: 2 additions & 2 deletions crates/oxc_transformer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,8 @@ impl<'a> Transformer<'a> {
}

impl<'a> Traverse<'a> for Transformer<'a> {
fn enter_program(&mut self, program: &mut Program<'a>, _ctx: &mut TraverseCtx<'a>) {
self.x0_typescript.transform_program(program);
fn enter_program(&mut self, program: &mut Program<'a>, ctx: &mut TraverseCtx<'a>) {
self.x0_typescript.transform_program(program, ctx);
}

fn exit_program(&mut self, program: &mut Program<'a>, _ctx: &mut TraverseCtx<'a>) {
Expand Down
4 changes: 2 additions & 2 deletions crates/oxc_transformer/src/typescript/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ impl<'a> TypeScript<'a> {

// Transforms
impl<'a> TypeScript<'a> {
pub fn transform_program(&self, program: &mut Program<'a>) {
self.transform_program_for_namespace(program);
pub fn transform_program(&self, program: &mut Program<'a>, ctx: &mut TraverseCtx) {
self.transform_program_for_namespace(program, ctx);
}

pub fn transform_program_on_exit(&self, program: &mut Program<'a>) {
Expand Down
33 changes: 26 additions & 7 deletions crates/oxc_transformer/src/typescript/namespace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,22 @@ use super::{diagnostics::ambient_module_nested, TypeScript};

use oxc_allocator::{Box, Vec};
use oxc_ast::{ast::*, syntax_directed_operations::BoundNames};
use oxc_span::{Atom, SPAN};
use oxc_syntax::operator::{AssignmentOperator, LogicalOperator};
use oxc_span::{Atom, CompactStr, SPAN};
use oxc_syntax::{
operator::{AssignmentOperator, LogicalOperator},
symbol::SymbolFlags,
};
use oxc_traverse::TraverseCtx;

// TODO:
// 1. register scope for the newly created function: <https://github.com/babel/babel/blob/08b0472069cd207f043dd40a4d157addfdd36011/packages/babel-plugin-transform-typescript/src/namespace.ts#L38>
impl<'a> TypeScript<'a> {
// `namespace Foo { }` -> `let Foo; (function (_Foo) { })(Foo || (Foo = {}));`
pub(super) fn transform_program_for_namespace(&self, program: &mut Program<'a>) {
pub(super) fn transform_program_for_namespace(
&self,
program: &mut Program<'a>,
ctx: &mut TraverseCtx,
) {
// namespace declaration is only allowed at the top level

if !has_namespace(program.body.as_slice()) {
Expand All @@ -31,7 +39,7 @@ impl<'a> TypeScript<'a> {
Statement::TSModuleDeclaration(decl) => {
if !decl.modifiers.is_contains_declare() {
if let Some(transformed_stmt) =
self.handle_nested(self.ctx.ast.copy(&decl).unbox(), None)
self.handle_nested(self.ctx.ast.copy(&decl).unbox(), None, ctx)
{
let name = decl.id.name();
if names.insert(name.clone()) {
Expand All @@ -51,7 +59,7 @@ impl<'a> TypeScript<'a> {
{
if !decl.modifiers.is_contains_declare() {
if let Some(transformed_stmt) =
self.handle_nested(self.ctx.ast.copy(decl), None)
self.handle_nested(self.ctx.ast.copy(decl), None, ctx)
{
let name = decl.id.name();
if names.insert(name.clone()) {
Expand Down Expand Up @@ -119,12 +127,17 @@ impl<'a> TypeScript<'a> {
&self,
decl: TSModuleDeclaration<'a>,
parent_export: Option<Expression<'a>>,
ctx: &mut TraverseCtx,
) -> Option<Statement<'a>> {
let mut names: FxHashSet<Atom<'a>> = FxHashSet::default();

let real_name = decl.id.name();

let name = self.ctx.ast.new_atom(&format!("_{}", real_name.clone())); // path.scope.generateUid(realName.name);
// TODO: This binding is created in wrong scope.
// Needs to be created in scope of function which `transform_namespace` creates below.
let name = self.ctx.ast.new_atom(
&ctx.generate_uid_in_current_scope(real_name, SymbolFlags::FunctionScopedVariable),
);

let namespace_top_level = if let Some(body) = decl.body {
match body {
Expand Down Expand Up @@ -161,7 +174,7 @@ impl<'a> TypeScript<'a> {
}

let module_name = decl.id.name().clone();
if let Some(transformed) = self.handle_nested(decl.unbox(), None) {
if let Some(transformed) = self.handle_nested(decl.unbox(), None, ctx) {
is_empty = false;
if names.insert(module_name.clone()) {
new_stmts.push(Statement::from(
Expand Down Expand Up @@ -233,6 +246,7 @@ impl<'a> TypeScript<'a> {
Some(self.ctx.ast.identifier_reference_expression(
IdentifierReference::new(SPAN, name.clone()),
)),
ctx,
) {
is_empty = false;
if names.insert(module_name.clone()) {
Expand Down Expand Up @@ -267,6 +281,11 @@ impl<'a> TypeScript<'a> {
}

if is_empty {
// Delete the scope binding that `ctx.generate_uid_in_current_scope` created above,
// as no binding is actually being created
let current_scope_id = ctx.current_scope_id();
ctx.scopes_mut().remove_binding(current_scope_id, &CompactStr::from(name.as_str()));

return None;
}

Expand Down
8 changes: 2 additions & 6 deletions tasks/transform_conformance/babel.snap.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
commit: 4bd1b2c2

Passed: 309/351
Passed: 313/351

# All Passed:
* babel-preset-react
Expand All @@ -21,18 +21,14 @@ Passed: 309/351
* opts/optimizeConstEnums/input.ts
* opts/rewriteImportExtensions/input.ts

# babel-plugin-transform-typescript (123/154)
# babel-plugin-transform-typescript (127/154)
* enum/mix-references/input.ts
* enum/scoped/input.ts
* enum/ts5.0-const-foldable/input.ts
* exports/declared-types/input.ts
* imports/enum-value/input.ts
* imports/type-only-export-specifier-2/input.ts
* namespace/contentious-names/input.ts
* namespace/empty-removed/input.ts
* namespace/module-nested/input.ts
* namespace/module-nested-export/input.ts
* namespace/multiple/input.ts
* namespace/mutable-fail/input.ts
* namespace/namespace-flag/input.ts
* namespace/namespace-nested-module/input.ts
Expand Down