Skip to content

Commit

Permalink
refactor: use scope way
Browse files Browse the repository at this point in the history
  • Loading branch information
Dunqing committed Jul 12, 2024
1 parent a6ebc10 commit 52172cf
Show file tree
Hide file tree
Showing 7 changed files with 37 additions and 27 deletions.
2 changes: 1 addition & 1 deletion crates/oxc_ast/src/ast/js.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1581,7 +1581,7 @@ pub struct YieldExpression<'a> {

/// Class Definitions
#[visited_node]
#[scope(flags(ScopeFlags::StrictMode))]
#[scope(flags(ScopeFlags::StrictMode | ScopeFlags::Class))]
#[derive(Debug)]
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
#[cfg_attr(feature = "serialize", serde(rename_all = "camelCase"))]
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_ast/src/generated/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2928,7 +2928,7 @@ pub mod walk {
if let Some(id) = &it.id {
visitor.visit_binding_identifier(id);
}
visitor.enter_scope(ScopeFlags::StrictMode, &it.scope_id);
visitor.enter_scope(ScopeFlags::StrictMode | ScopeFlags::Class, &it.scope_id);
if let Some(type_parameters) = &it.type_parameters {
visitor.visit_ts_type_parameter_declaration(type_parameters);
}
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_ast/src/generated/visit_mut.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3052,7 +3052,7 @@ pub mod walk_mut {
if let Some(id) = &mut it.id {
visitor.visit_binding_identifier(id);
}
visitor.enter_scope(ScopeFlags::StrictMode, &it.scope_id);
visitor.enter_scope(ScopeFlags::StrictMode | ScopeFlags::Class, &it.scope_id);
if let Some(type_parameters) = &mut it.type_parameters {
visitor.visit_ts_type_parameter_declaration(type_parameters);
}
Expand Down
5 changes: 1 addition & 4 deletions crates/oxc_semantic/src/binder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,7 @@ impl<'a> Binder for Class<'a> {
SymbolFlags::ClassExcludes,
)
} else {
let symbol_id = builder.declare_symbol(ident.span, &ident.name, SymbolFlags::Class);
builder.symbols.set_declaration_symbol(symbol_id, builder.current_node_id);
symbol_id
builder.declare_symbol(ident.span, &ident.name, SymbolFlags::Class)
};
ident.symbol_id.set(Some(symbol_id));
}
Expand Down Expand Up @@ -156,7 +154,6 @@ impl<'a> Binder for Function<'a> {
// 5. Perform ! funcEnv.CreateImmutableBinding(name, false).
let symbol_id =
builder.declare_symbol(ident.span, &ident.name, SymbolFlags::Function);
builder.symbols.set_declaration_symbol(symbol_id, builder.current_node_id);
ident.symbol_id.set(Some(symbol_id));
}
}
Expand Down
28 changes: 18 additions & 10 deletions crates/oxc_semantic/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@ impl<'a> SemanticBuilder<'a> {
}

fn resolve_references_for_current_scope(&mut self) {
let current_scope_flags = self.current_scope_flags();
// `iter_mut` to get mut references to 2 entries of `unresolved_references` simultaneously
let mut iter = self.unresolved_references.iter_mut();
let parent_refs = iter.nth(self.current_scope_depth - 1).unwrap();
Expand All @@ -391,18 +392,24 @@ impl<'a> SemanticBuilder<'a> {
// Try to resolve a reference.
// If unresolved, transfer it to parent scope's unresolved references.
if let Some(symbol_id) = bindings.get(&name).copied().or_else(|| {
self.symbols.get_symbol_id_from_declaration(self.current_node_id).and_then(
|symbol_id| {
let flag = self.symbols.get_flag(symbol_id);
if (flag.is_class() || flag.is_function())
&& self.symbols.get_name(symbol_id) == name
// If the current node is a class or function expression,
// Try to get the symbol by binding name
// and check if it's the same name with the reference.
if current_scope_flags.is_class() || current_scope_flags.is_function() {
let kind = self.nodes.kind(self.current_node_id);
if matches!(kind, AstKind::Function(func) if func.id.is_some() && func.is_expression())
|| matches!(kind, AstKind::Class(class) if class.id.is_some() && class.is_expression())
{
if let Some(symbol_id) =
self.symbols.get_symbol_id_from_declaration(self.current_node_id)
{
Some(symbol_id)
} else {
None
if self.symbols.get_name(symbol_id) == name {
return Some(symbol_id);
}
}
},
)
}
}
None
}) {
for reference_id in &reference_ids {
self.symbols.references[*reference_id].set_symbol_id(symbol_id);
Expand Down Expand Up @@ -1598,6 +1605,7 @@ impl<'a> SemanticBuilder<'a> {
self.current_node_flags |= NodeFlags::Class;
class.bind(self);
self.current_symbol_flags -= SymbolFlags::Export;
self.add_current_node_id_to_current_scope();
self.make_all_namespaces_valuelike();
}
AstKind::ClassBody(body) => {
Expand Down
20 changes: 10 additions & 10 deletions crates/oxc_semantic/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ pub use oxc_syntax::{
scope::ScopeId,
symbol::{SymbolFlags, SymbolId},
};
use rustc_hash::FxHashMap;

#[cfg(feature = "serialize")]
use serde::Serialize;
Expand Down Expand Up @@ -37,7 +36,6 @@ pub struct SymbolTable {
pub scope_ids: IndexVec<SymbolId, Option<ScopeId>>,
/// Pointer to the AST Node where this symbol is declared
pub declarations: IndexVec<SymbolId, AstNodeId>,
pub declaration_symbol: FxHashMap<AstNodeId, SymbolId>,
pub resolved_references: IndexVec<SymbolId, Vec<ReferenceId>>,
pub references: IndexVec<ReferenceId, Reference>,
pub redeclare_variables: IndexVec<SymbolId, Vec<Span>>,
Expand Down Expand Up @@ -66,10 +64,6 @@ impl SymbolTable {
.find_map(|(symbol, inner_span)| if inner_span == span { Some(symbol) } else { None })
}

pub fn get_symbol_id_from_declaration(&self, declaration: AstNodeId) -> Option<SymbolId> {
self.declaration_symbol.get(&declaration).copied()
}

pub fn get_symbol_id_from_name(&self, name: &str) -> Option<SymbolId> {
self.names.iter_enumerated().find_map(|(symbol, inner_name)| {
if inner_name.as_str() == name {
Expand All @@ -80,6 +74,16 @@ impl SymbolTable {
})
}

pub fn get_symbol_id_from_declaration(&self, declaration: AstNodeId) -> Option<SymbolId> {
self.declarations.iter_enumerated().find_map(|(symbol, inner_declaration)| {
if *inner_declaration == declaration {
Some(symbol)
} else {
None
}
})
}

pub fn get_span(&self, symbol_id: SymbolId) -> Span {
self.spans[symbol_id]
}
Expand Down Expand Up @@ -178,10 +182,6 @@ impl SymbolTable {
.map(|reference_id| &self.references[*reference_id])
}

pub fn set_declaration_symbol(&mut self, symbol_id: SymbolId, declaration: AstNodeId) {
self.declaration_symbol.insert(declaration, symbol_id);
}

/// Determine whether evaluating the specific input `node` is a consequenceless reference. ie.
/// evaluating it won't result in potentially arbitrary code from being ran. The following are
/// allowed and determined not to cause side effects:
Expand Down
5 changes: 5 additions & 0 deletions crates/oxc_syntax/src/scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ bitflags! {
const GetAccessor = 1 << 7;
const SetAccessor = 1 << 8;
const CatchClause = 1 << 9;
const Class = 1 << 10;
const Var = Self::Top.bits() | Self::Function.bits() | Self::ClassStaticBlock.bits() | Self::TsModuleBlock.bits();
const Modifiers = Self::Constructor.bits() | Self::GetAccessor.bits() | Self::SetAccessor.bits();
}
Expand Down Expand Up @@ -86,4 +87,8 @@ impl ScopeFlags {
pub fn is_catch_clause(&self) -> bool {
self.contains(Self::CatchClause)
}

pub fn is_class(&self) -> bool {
self.contains(Self::Class)
}
}

0 comments on commit 52172cf

Please sign in to comment.