diff --git a/crates/oxc_semantic/src/lib.rs b/crates/oxc_semantic/src/lib.rs index 3f556c058..4934c1748 100644 --- a/crates/oxc_semantic/src/lib.rs +++ b/crates/oxc_semantic/src/lib.rs @@ -72,6 +72,10 @@ impl<'a> Semantic<'a> { &self.scopes } + pub fn scopes_mut(&mut self) -> &mut ScopeTree { + &mut self.scopes + } + pub fn trivias(&self) -> &TriviasMap { &self.trivias } diff --git a/crates/oxc_transformer/examples/transformer.rs b/crates/oxc_transformer/examples/transformer.rs index 984060c8a..53e716030 100644 --- a/crates/oxc_transformer/examples/transformer.rs +++ b/crates/oxc_transformer/examples/transformer.rs @@ -1,4 +1,4 @@ -use std::{cell::RefCell, env, path::Path, rc::Rc}; +use std::{env, path::Path}; use oxc_allocator::Allocator; use oxc_codegen::{Codegen, CodegenOptions}; @@ -36,9 +36,6 @@ fn main() { println!("{printed}\n"); let semantic = SemanticBuilder::new(&source_text, source_type).build(&ret.program).semantic; - let (symbols, scopes) = semantic.into_symbol_table_and_scope_tree(); - let symbols = Rc::new(RefCell::new(symbols)); - let scopes = Rc::new(RefCell::new(scopes)); let program = allocator.alloc(ret.program); let transform_options = TransformOptions { @@ -49,7 +46,7 @@ fn main() { }), ..TransformOptions::default() }; - Transformer::new(&allocator, source_type, &symbols, &scopes, transform_options).build(program); + Transformer::new(&allocator, source_type, semantic, transform_options).build(program); let printed = Codegen::::new(source_text.len(), codegen_options).build(program); println!("Transformed:\n"); println!("{printed}"); diff --git a/crates/oxc_transformer/src/context.rs b/crates/oxc_transformer/src/context.rs index 84c0e8160..57c5388f2 100644 --- a/crates/oxc_transformer/src/context.rs +++ b/crates/oxc_transformer/src/context.rs @@ -1,30 +1,37 @@ use std::{ - cell::{Ref, RefCell}, + cell::{Ref, RefCell, RefMut}, rc::Rc, }; use oxc_ast::AstBuilder; -use oxc_semantic::{ScopeId, ScopeTree, SymbolId, SymbolTable}; +use oxc_semantic::{ScopeId, ScopeTree, Semantic, SymbolId, SymbolTable}; use oxc_span::Atom; #[derive(Clone)] pub struct TransformerCtx<'a> { pub ast: Rc>, - pub symbols: Rc>, - pub scopes: Rc>, + semantic: Rc>>, } impl<'a> TransformerCtx<'a> { - pub fn symbols(&self) -> Ref { - self.symbols.borrow() + pub fn new(ast: Rc>, semantic: Rc>>) -> Self { + Self { ast, semantic } } - pub fn scopes(&self) -> Ref { - self.scopes.borrow() + pub fn symbols(&self) -> Ref<'_, SymbolTable> { + Ref::map(self.semantic.borrow(), |semantic| semantic.symbols()) + } + + pub fn scopes(&self) -> Ref<'_, ScopeTree> { + Ref::map(self.semantic.borrow(), |semantic| semantic.scopes()) + } + + pub fn scopes_mut(&self) -> RefMut<'_, ScopeTree> { + RefMut::map(self.semantic.borrow_mut(), |semantic| semantic.scopes_mut()) } pub fn add_binding(&self, name: Atom) { // TODO: use the correct scope and symbol id - self.scopes.borrow_mut().add_binding(ScopeId::new(0), name, SymbolId::new(0)); + self.scopes_mut().add_binding(ScopeId::new(0), name, SymbolId::new(0)); } } diff --git a/crates/oxc_transformer/src/es2016/exponentiation_operator.rs b/crates/oxc_transformer/src/es2016/exponentiation_operator.rs index a13510d8c..347429902 100644 --- a/crates/oxc_transformer/src/es2016/exponentiation_operator.rs +++ b/crates/oxc_transformer/src/es2016/exponentiation_operator.rs @@ -163,7 +163,7 @@ impl<'a> ExponentiationOperator<'a> { if ident .reference_id .get() - .is_some_and(|reference_id| self.ctx.symbols.borrow().has_binding(reference_id)) + .is_some_and(|reference_id| self.ctx.symbols().has_binding(reference_id)) { // this variable is declared in scope so we can be 100% sure // that evaluating it multiple times won't trigger a getter @@ -185,7 +185,7 @@ impl<'a> ExponentiationOperator<'a> { // Super cannot be directly assigned so lets return it also if matches!(expr, Expression::Super(_)) || matches!(&expr, Expression::Identifier(ident) if - ident.reference_id.get().is_some_and(|reference_id| self.ctx.symbols.borrow().has_binding(reference_id))) + ident.reference_id.get().is_some_and(|reference_id| self.ctx.symbols().has_binding(reference_id))) { return Some(expr); } diff --git a/crates/oxc_transformer/src/lib.rs b/crates/oxc_transformer/src/lib.rs index 6db03e799..9e343a653 100644 --- a/crates/oxc_transformer/src/lib.rs +++ b/crates/oxc_transformer/src/lib.rs @@ -26,7 +26,7 @@ use std::{cell::RefCell, rc::Rc}; use oxc_allocator::{Allocator, Vec}; use oxc_ast::{ast::*, AstBuilder, VisitMut}; -use oxc_semantic::{ScopeTree, SymbolTable}; +use oxc_semantic::Semantic; use oxc_span::SourceType; use crate::{ @@ -66,16 +66,14 @@ impl<'a> Transformer<'a> { pub fn new( allocator: &'a Allocator, source_type: SourceType, - symbols: &Rc>, - scopes: &Rc>, + semantic: Semantic<'a>, options: TransformOptions, ) -> Self { let ast = Rc::new(AstBuilder::new(allocator)); - let ctx = TransformerCtx { - ast: Rc::clone(&ast), - symbols: Rc::clone(symbols), - scopes: Rc::clone(scopes), - }; + let ctx = TransformerCtx::new( + Rc::clone(&ast), + Rc::new(RefCell::new(semantic)), + ); Self { // TODO: pass verbatim_module_syntax from user config typescript: source_type.is_typescript().then(|| TypeScript::new(Rc::clone(&ast), ctx.clone(), false)), diff --git a/crates/oxc_transformer/src/tester.rs b/crates/oxc_transformer/src/tester.rs index db68b7172..ec80ee156 100644 --- a/crates/oxc_transformer/src/tester.rs +++ b/crates/oxc_transformer/src/tester.rs @@ -1,5 +1,3 @@ -use std::{cell::RefCell, rc::Rc}; - use oxc_allocator::Allocator; use oxc_codegen::{Codegen, CodegenOptions}; use oxc_parser::Parser; @@ -32,15 +30,9 @@ impl Tester { fn transform(&self, source_text: &str) -> String { let program = Parser::new(&self.allocator, source_text, self.source_type).parse().program; - let semantic = SemanticBuilder::new(source_text, self.source_type).build(&program).semantic; - let (symbols, scopes) = semantic.into_symbol_table_and_scope_tree(); - let symbols = Rc::new(RefCell::new(symbols)); - let scopes = Rc::new(RefCell::new(scopes)); - let program = self.allocator.alloc(program); - Transformer::new(&self.allocator, self.source_type, &symbols, &scopes, self.options) - .build(program); + Transformer::new(&self.allocator, self.source_type, semantic, self.options).build(program); Codegen::::new(source_text.len(), CodegenOptions).build(program) } diff --git a/crates/oxc_wasm/src/lib.rs b/crates/oxc_wasm/src/lib.rs index 0f122734c..3fb1dbfee 100644 --- a/crates/oxc_wasm/src/lib.rs +++ b/crates/oxc_wasm/src/lib.rs @@ -213,12 +213,9 @@ impl Oxc { // FIXME: this should not be duplicated with the linter semantic, // we need to fix the API so symbols and scopes can be shared. let semantic = SemanticBuilder::new(source_text, source_type).build(program).semantic; - let (symbols, scopes) = semantic.into_symbol_table_and_scope_tree(); - let symbols = Rc::new(RefCell::new(symbols)); - let scopes = Rc::new(RefCell::new(scopes)); let options = TransformOptions { target: TransformTarget::ES2015, ..TransformOptions::default() }; - Transformer::new(&allocator, source_type, &symbols, &scopes, options).build(program); + Transformer::new(&allocator, source_type, semantic, options).build(program); } let program = allocator.alloc(program); diff --git a/tasks/benchmark/benches/transformer.rs b/tasks/benchmark/benches/transformer.rs index 99c1e41b5..ce3a1c5e0 100644 --- a/tasks/benchmark/benches/transformer.rs +++ b/tasks/benchmark/benches/transformer.rs @@ -6,7 +6,7 @@ static GLOBAL: jemallocator::Jemalloc = jemallocator::Jemalloc; #[global_allocator] static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; -use std::{cell::RefCell, fs, hint::black_box, rc::Rc}; +use std::{fs, hint::black_box}; use oxc_allocator::Allocator; use oxc_benchmark::{criterion_group, criterion_main, BenchmarkId, Criterion}; @@ -35,12 +35,9 @@ fn bench_transformer(criterion: &mut Criterion) { let program = Parser::new(&allocator, source_text, source_type).parse().program; let semantic = SemanticBuilder::new(source_text, source_type).build(&program).semantic; - let (symbols, scopes) = semantic.into_symbol_table_and_scope_tree(); - let symbols = Rc::new(RefCell::new(symbols)); - let scopes = Rc::new(RefCell::new(scopes)); let program = allocator.alloc(program); let transform_options = TransformOptions::default(); - Transformer::new(&allocator, source_type, &symbols, &scopes, transform_options) + Transformer::new(&allocator, source_type, semantic, transform_options) .build(black_box(program)); allocator }); diff --git a/tasks/transform_conformance/src/test_case.rs b/tasks/transform_conformance/src/test_case.rs index f3c0e0f6b..9a442e39a 100644 --- a/tasks/transform_conformance/src/test_case.rs +++ b/tasks/transform_conformance/src/test_case.rs @@ -1,8 +1,6 @@ use std::{ - cell::RefCell, fs, path::{Path, PathBuf}, - rc::Rc, }; use oxc_allocator::Allocator; @@ -144,12 +142,9 @@ pub trait TestCase { let semantic = SemanticBuilder::new(&source_text, source_type).build(&transformed_program).semantic; - let (symbols, scopes) = semantic.into_symbol_table_and_scope_tree(); - let symbols = Rc::new(RefCell::new(symbols)); - let scopes = Rc::new(RefCell::new(scopes)); let transformed_program = allocator.alloc(transformed_program); - Transformer::new(&allocator, source_type, &symbols, &scopes, self.transform_options()) + Transformer::new(&allocator, source_type, semantic, self.transform_options()) .build(transformed_program); Codegen::::new(source_text.len(), CodegenOptions).build(transformed_program) } @@ -197,11 +192,8 @@ impl TestCase for ConformanceTestCase { // Transform input.js let program = Parser::new(&allocator, &input, source_type).parse().program; let semantic = SemanticBuilder::new(&input, source_type).build(&program).semantic; - let (symbols, scopes) = semantic.into_symbol_table_and_scope_tree(); - let symbols = Rc::new(RefCell::new(symbols)); - let scopes = Rc::new(RefCell::new(scopes)); let program = allocator.alloc(program); - Transformer::new(&allocator, source_type, &symbols, &scopes, self.transform_options()) + Transformer::new(&allocator, source_type, semantic, self.transform_options()) .build(program); let transformed_code = Codegen::::new(input.len(), CodegenOptions).build(program);