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
39 changes: 12 additions & 27 deletions crates/oxc/src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use oxc_isolated_declarations::{IsolatedDeclarations, IsolatedDeclarationsOption
use oxc_mangler::{MangleOptions, Mangler};
use oxc_minifier::{CompressOptions, Compressor};
use oxc_parser::{ParseOptions, Parser, ParserReturn};
use oxc_semantic::{ScopeTree, SemanticBuilder, SemanticBuilderReturn, SymbolTable};
use oxc_semantic::{Scoping, SemanticBuilder, SemanticBuilderReturn, SymbolTable};
use oxc_span::SourceType;
use oxc_transformer::{
InjectGlobalVariables, InjectGlobalVariablesConfig, ReplaceGlobalDefines,
Expand Down Expand Up @@ -149,13 +149,13 @@ pub trait CompilerInterface {
}

let stats = semantic_return.semantic.stats();
let (mut symbols, mut scopes) = semantic_return.semantic.into_symbol_table_and_scope_tree();
let mut scoping = semantic_return.semantic.into_scoping();

/* Transform */

if let Some(options) = self.transform_options() {
let mut transformer_return =
self.transform(options, &allocator, &mut program, source_path, symbols, scopes);
self.transform(options, &allocator, &mut program, source_path, scoping);

if !transformer_return.errors.is_empty() {
self.handle_errors(transformer_return.errors);
Expand All @@ -166,40 +166,27 @@ pub trait CompilerInterface {
return;
}

(symbols, scopes) = (transformer_return.symbols, transformer_return.scopes);
(scoping) = transformer_return.scoping;
}

let inject_options = self.inject_options();
let define_options = self.define_options();

// Symbols and scopes are out of sync.
if inject_options.is_some() || define_options.is_some() {
(symbols, scopes) = SemanticBuilder::new()
.with_stats(stats)
.build(&program)
.semantic
.into_symbol_table_and_scope_tree();
scoping =
SemanticBuilder::new().with_stats(stats).build(&program).semantic.into_scoping();
}

if let Some(options) = inject_options {
let ret = InjectGlobalVariables::new(&allocator, options).build(
symbols,
scopes,
&mut program,
);
symbols = ret.symbols;
scopes = ret.scopes;
let ret = InjectGlobalVariables::new(&allocator, options).build(scoping, &mut program);
scoping = ret.scoping;
}

if let Some(options) = define_options {
let ret =
ReplaceGlobalDefines::new(&allocator, options).build(symbols, scopes, &mut program);
let ret = ReplaceGlobalDefines::new(&allocator, options).build(scoping, &mut program);
Compressor::new(&allocator, CompressOptions::default())
.dead_code_elimination_with_symbols_and_scopes(
ret.symbols,
ret.scopes,
&mut program,
);
.dead_code_elimination_with_scoping(ret.scoping, &mut program);
// symbols = ret.symbols;
// scopes = ret.scopes;
}
Expand Down Expand Up @@ -269,11 +256,9 @@ pub trait CompilerInterface {
allocator: &'a Allocator,
program: &mut Program<'a>,
source_path: &Path,
symbols: SymbolTable,
scopes: ScopeTree,
scoping: Scoping,
) -> TransformerReturn {
Transformer::new(allocator, source_path, options)
.build_with_symbols_and_scopes(symbols, scopes, program)
Transformer::new(allocator, source_path, options).build_with_scoping(scoping, program)
}

fn compress<'a>(
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_mangler/src/base54.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ struct Aligned64([u8; 64]);
///
/// This list was generated by the following steps:
/// 1. Generate a source code with replacing all manglable variable names with `$` (assuming `$` is the least used character).
/// You can do this by passing the following `blank` function to the `generate_name` parameter of [crate::Mangler::build_with_symbols_and_scopes_impl].
/// You can do this by passing the following `blank` function to the `generate_name` parameter of [crate::Mangler::build_with_semantic_impl].
/// ```no_run
/// fn blank(_: usize) -> InlineString<12> {
/// let mut str = InlineString::new();
Expand Down
12 changes: 5 additions & 7 deletions crates/oxc_mangler/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,22 +177,20 @@ impl Mangler {
#[must_use]
pub fn build_with_semantic(self, semantic: Semantic<'_>, program: &Program<'_>) -> SymbolTable {
if self.options.debug {
self.build_with_symbols_and_scopes_impl(semantic, program, debug_name)
self.build_with_semantic_impl(semantic, program, debug_name)
} else {
self.build_with_symbols_and_scopes_impl(semantic, program, base54)
self.build_with_semantic_impl(semantic, program, base54)
}
}

fn build_with_symbols_and_scopes_impl<
const CAPACITY: usize,
G: Fn(u32) -> InlineString<CAPACITY, u8>,
>(
fn build_with_semantic_impl<const CAPACITY: usize, G: Fn(u32) -> InlineString<CAPACITY, u8>>(
self,
semantic: Semantic<'_>,
program: &Program<'_>,
generate_name: G,
) -> SymbolTable {
let (mut symbol_table, scope_tree, ast_nodes) = semantic.into_symbols_scopes_nodes();
let (scoping, ast_nodes) = semantic.into_scoping_and_nodes();
let (mut symbol_table, scope_tree) = scoping.into_symbols_scopes();

assert!(scope_tree.has_child_ids(), "child_id needs to be generated");

Expand Down
30 changes: 9 additions & 21 deletions crates/oxc_minifier/src/compressor.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use oxc_allocator::Allocator;
use oxc_ast::ast::*;
use oxc_semantic::{ScopeTree, SemanticBuilder, SymbolTable};
use oxc_semantic::{Scoping, SemanticBuilder};
use oxc_traverse::ReusableTraverseCtx;

use crate::{
Expand All @@ -22,18 +22,12 @@ impl<'a> Compressor<'a> {
}

pub fn build(self, program: &mut Program<'a>) {
let (symbols, scopes) =
SemanticBuilder::new().build(program).semantic.into_symbol_table_and_scope_tree();
self.build_with_symbols_and_scopes(symbols, scopes, program);
let scoping = SemanticBuilder::new().build(program).semantic.into_scoping();
self.build_with_scoping(scoping, program);
}

pub fn build_with_symbols_and_scopes(
self,
symbols: SymbolTable,
scopes: ScopeTree,
program: &mut Program<'a>,
) {
let mut ctx = ReusableTraverseCtx::new(scopes, symbols, self.allocator);
pub fn build_with_scoping(self, scoping: Scoping, program: &mut Program<'a>) {
let mut ctx = ReusableTraverseCtx::new(scoping, self.allocator);
let normalize_options =
NormalizeOptions { convert_while_to_fors: true, convert_const_to_let: true };
Normalize::new(normalize_options, self.options).build(program, &mut ctx);
Expand All @@ -42,18 +36,12 @@ impl<'a> Compressor<'a> {
}

pub fn dead_code_elimination(self, program: &mut Program<'a>) {
let (symbols, scopes) =
SemanticBuilder::new().build(program).semantic.into_symbol_table_and_scope_tree();
self.dead_code_elimination_with_symbols_and_scopes(symbols, scopes, program);
let scoping = SemanticBuilder::new().build(program).semantic.into_scoping();
self.dead_code_elimination_with_scoping(scoping, program);
}

pub fn dead_code_elimination_with_symbols_and_scopes(
self,
symbols: SymbolTable,
scopes: ScopeTree,
program: &mut Program<'a>,
) {
let mut ctx = ReusableTraverseCtx::new(scopes, symbols, self.allocator);
pub fn dead_code_elimination_with_scoping(self, scoping: Scoping, program: &mut Program<'a>) {
let mut ctx = ReusableTraverseCtx::new(scoping, self.allocator);
let normalize_options =
NormalizeOptions { convert_while_to_fors: false, convert_const_to_let: false };
Normalize::new(normalize_options, self.options).build(program, &mut ctx);
Expand Down
5 changes: 2 additions & 3 deletions crates/oxc_minifier/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,8 @@ impl Minifier {
let stats = if let Some(compress) = self.options.compress {
let semantic = SemanticBuilder::new().build(program).semantic;
let stats = semantic.stats();
let (symbols, scopes) = semantic.into_symbol_table_and_scope_tree();
Compressor::new(allocator, compress)
.build_with_symbols_and_scopes(symbols, scopes, program);
let scoping = semantic.into_scoping();
Compressor::new(allocator, compress).build_with_scoping(scoping, program);
stats
} else {
Stats::default()
Expand Down
14 changes: 8 additions & 6 deletions crates/oxc_semantic/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ mod jsdoc;
mod label;
mod node;
mod scope;
mod scoping;
mod stats;
mod symbol;
mod unresolved_stack;
Expand All @@ -41,6 +42,7 @@ pub use is_global_reference::IsGlobalReference;
pub use jsdoc::{JSDoc, JSDocFinder, JSDocTag};
pub use node::{AstNode, AstNodes};
pub use scope::ScopeTree;
pub use scoping::Scoping;
pub use stats::Stats;
pub use symbol::SymbolTable;

Expand Down Expand Up @@ -92,14 +94,14 @@ pub struct Semantic<'a> {
}

impl<'a> Semantic<'a> {
/// Extract [`SymbolTable`] and [`ScopeTree`] from [`Semantic`].
pub fn into_symbol_table_and_scope_tree(self) -> (SymbolTable, ScopeTree) {
(self.symbols, self.scopes)
/// Extract [`Scoping`] from [`Semantic`].
pub fn into_scoping(self) -> Scoping {
Scoping::new(self.symbols, self.scopes)
}

/// Extract [`SymbolTable`], [`ScopeTree`] and [`AstNode`] from the [`Semantic`].
pub fn into_symbols_scopes_nodes(self) -> (SymbolTable, ScopeTree, AstNodes<'a>) {
(self.symbols, self.scopes, self.nodes)
/// Extract [`Scoping`] and [`AstNode`] from the [`Semantic`].
pub fn into_scoping_and_nodes(self) -> (Scoping, AstNodes<'a>) {
(Scoping::new(self.symbols, self.scopes), self.nodes)
}

/// Source code of the JavaScript/TypeScript program being analyzed.
Expand Down
24 changes: 24 additions & 0 deletions crates/oxc_semantic/src/scoping.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use crate::{ScopeTree, SymbolTable};

pub struct Scoping {
symbols: SymbolTable,
scopes: ScopeTree,
}

impl Scoping {
pub fn new(symbols: SymbolTable, scopes: ScopeTree) -> Self {
Self { symbols, scopes }
}

pub fn symbols(&self) -> &SymbolTable {
&self.symbols
}

pub fn scopes(&self) -> &ScopeTree {
&self.scopes
}

pub fn into_symbols_scopes(self) -> (SymbolTable, ScopeTree) {
(self.symbols, self.scopes)
}
}
3 changes: 2 additions & 1 deletion crates/oxc_semantic/tests/integration/scopes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,8 @@ fn get_child_ids() {
)
.with_scope_tree_child_ids(true);
let semantic = test.build();
let (_symbols, scopes) = semantic.into_symbol_table_and_scope_tree();
let scoping = semantic.into_scoping();
let scopes = scoping.scopes();

let child_scope_ids = scopes.get_child_ids(scopes.root_scope_id());
assert_eq!(child_scope_ids.len(), 1);
Expand Down
9 changes: 3 additions & 6 deletions crates/oxc_transformer/examples/transformer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ fn main() {
}
}

let (symbols, scopes) = ret.semantic.into_symbol_table_and_scope_tree();
let scoping = ret.semantic.into_scoping();

let mut transform_options = if let Some(babel_options_path) = babel_options_path {
let babel_options_path = Path::new(&babel_options_path);
Expand All @@ -74,11 +74,8 @@ fn main() {

transform_options.helper_loader.mode = HelperLoaderMode::External;

let ret = Transformer::new(&allocator, path, &transform_options).build_with_symbols_and_scopes(
symbols,
scopes,
&mut program,
);
let ret = Transformer::new(&allocator, path, &transform_options)
.build_with_scoping(scoping, &mut program);

if !ret.errors.is_empty() {
println!("Transformer Errors:");
Expand Down
7 changes: 3 additions & 4 deletions crates/oxc_transformer/src/es2022/class_static_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,17 +260,16 @@ impl<'a> Keys<'a> {
#[cfg(test)]
mod test {
use oxc_allocator::Allocator;
use oxc_semantic::{ScopeTree, SymbolTable};
use oxc_semantic::{ScopeTree, Scoping, SymbolTable};
use oxc_traverse::ReusableTraverseCtx;

use super::Keys;

macro_rules! setup {
($ctx:ident) => {
let allocator = Allocator::default();
let scopes = ScopeTree::default();
let symbols = SymbolTable::default();
let ctx = ReusableTraverseCtx::new(scopes, symbols, &allocator);
let scoping = Scoping::new(SymbolTable::default(), ScopeTree::default());
let ctx = ReusableTraverseCtx::new(scoping, &allocator);
// SAFETY: Macro user only gets a `&mut TraverseCtx`, which cannot be abused
let mut ctx = unsafe { ctx.unwrap() };
let $ctx = &mut ctx;
Expand Down
5 changes: 3 additions & 2 deletions crates/oxc_transformer/src/jsx/jsx_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1111,7 +1111,7 @@ mod test {

use oxc_allocator::Allocator;
use oxc_ast::ast::Expression;
use oxc_semantic::{ScopeTree, SymbolTable};
use oxc_semantic::{ScopeTree, Scoping, SymbolTable};
use oxc_syntax::{node::NodeId, scope::ScopeFlags};
use oxc_traverse::ReusableTraverseCtx;

Expand All @@ -1125,7 +1125,8 @@ mod test {
let mut scopes = ScopeTree::default();
scopes.add_scope(None, NodeId::DUMMY, ScopeFlags::Top);

let traverse_ctx = ReusableTraverseCtx::new(scopes, SymbolTable::default(), &allocator);
let scoping = Scoping::new(SymbolTable::default(), scopes);
let traverse_ctx = ReusableTraverseCtx::new(scoping, &allocator);
// SAFETY: Macro user only gets a `&mut TraverseCtx`, which cannot be abused
let mut traverse_ctx = unsafe { traverse_ctx.unwrap() };
let $traverse_ctx = &mut traverse_ctx;
Expand Down
14 changes: 6 additions & 8 deletions crates/oxc_transformer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use std::path::Path;
use oxc_allocator::{Allocator, Vec as ArenaVec};
use oxc_ast::{AstBuilder, ast::*};
use oxc_diagnostics::OxcDiagnostic;
use oxc_semantic::{ScopeTree, SymbolTable};
use oxc_semantic::Scoping;
use oxc_span::SPAN;
use oxc_traverse::{Traverse, TraverseCtx, traverse_mut};

Expand Down Expand Up @@ -70,8 +70,7 @@ pub use crate::{
#[non_exhaustive]
pub struct TransformerReturn {
pub errors: std::vec::Vec<OxcDiagnostic>,
pub symbols: SymbolTable,
pub scopes: ScopeTree,
pub scoping: Scoping,
/// Helpers used by this transform.
#[deprecated = "Internal usage only"]
pub helpers_used: FxHashMap<Helper, String>,
Expand Down Expand Up @@ -101,10 +100,9 @@ impl<'a> Transformer<'a> {
}
}

pub fn build_with_symbols_and_scopes(
pub fn build_with_scoping(
mut self,
symbols: SymbolTable,
scopes: ScopeTree,
scoping: Scoping,
program: &mut Program<'a>,
) -> TransformerReturn {
let allocator = self.allocator;
Expand Down Expand Up @@ -138,10 +136,10 @@ impl<'a> Transformer<'a> {
x4_regexp: RegExp::new(self.env.regexp, &self.ctx),
};

let (symbols, scopes) = traverse_mut(&mut transformer, allocator, program, symbols, scopes);
let scoping = traverse_mut(&mut transformer, allocator, program, scoping);
let helpers_used = self.ctx.helper_loader.used_helpers.borrow_mut().drain().collect();
#[expect(deprecated)]
TransformerReturn { errors: self.ctx.take_errors(), symbols, scopes, helpers_used }
TransformerReturn { errors: self.ctx.take_errors(), scoping, helpers_used }
}
}

Expand Down
Loading
Loading