From 04cffb49be1eed325e0e96310ecaf0ad96a737a6 Mon Sep 17 00:00:00 2001 From: Dunqing Date: Sun, 14 Jul 2024 01:09:30 +0800 Subject: [PATCH] refactor: deferred bind ClassExpression --- crates/oxc_ast/src/ast/js.rs | 2 +- crates/oxc_ast/src/generated/visit.rs | 2 +- crates/oxc_ast/src/generated/visit_mut.rs | 2 +- .../src/rules/nextjs/no_duplicate_head.rs | 2 +- crates/oxc_semantic/src/binder.rs | 72 ++++++++----------- crates/oxc_semantic/src/builder.rs | 64 ++++++++--------- crates/oxc_semantic/src/checker/javascript.rs | 9 ++- crates/oxc_semantic/src/lib.rs | 4 +- crates/oxc_semantic/src/symbol.rs | 30 +++----- .../oxc_semantic/tests/integration/scopes.rs | 2 +- .../oxc_semantic/tests/integration/symbols.rs | 4 ++ .../tests/integration/util/symbol_tester.rs | 10 ++- crates/oxc_transformer/src/typescript/enum.rs | 4 +- crates/oxc_traverse/src/context/scoping.rs | 8 +-- crates/oxc_traverse/src/walk.rs | 12 ++-- 15 files changed, 97 insertions(+), 130 deletions(-) diff --git a/crates/oxc_ast/src/ast/js.rs b/crates/oxc_ast/src/ast/js.rs index a9d3fd4a0c162..a590952569f03 100644 --- a/crates/oxc_ast/src/ast/js.rs +++ b/crates/oxc_ast/src/ast/js.rs @@ -1590,8 +1590,8 @@ pub struct Class<'a> { #[cfg_attr(feature = "serialize", serde(flatten))] pub span: Span, pub decorators: Vec<'a, Decorator<'a>>, - pub id: Option>, #[scope(enter_before)] + pub id: Option>, pub type_parameters: Option>>, #[visit_as(ClassHeritage)] pub super_class: Option>, diff --git a/crates/oxc_ast/src/generated/visit.rs b/crates/oxc_ast/src/generated/visit.rs index 3b7a57c1bd63d..ddfe5c856dc93 100644 --- a/crates/oxc_ast/src/generated/visit.rs +++ b/crates/oxc_ast/src/generated/visit.rs @@ -2925,10 +2925,10 @@ pub mod walk { let kind = AstKind::Class(visitor.alloc(it)); visitor.enter_node(kind); visitor.visit_decorators(&it.decorators); + visitor.enter_scope(ScopeFlags::StrictMode, &it.scope_id); if let Some(id) = &it.id { visitor.visit_binding_identifier(id); } - visitor.enter_scope(ScopeFlags::StrictMode, &it.scope_id); if let Some(type_parameters) = &it.type_parameters { visitor.visit_ts_type_parameter_declaration(type_parameters); } diff --git a/crates/oxc_ast/src/generated/visit_mut.rs b/crates/oxc_ast/src/generated/visit_mut.rs index 72d7f11f4545d..fecc459acbc39 100644 --- a/crates/oxc_ast/src/generated/visit_mut.rs +++ b/crates/oxc_ast/src/generated/visit_mut.rs @@ -3049,10 +3049,10 @@ pub mod walk_mut { let kind = AstType::Class; visitor.enter_node(kind); visitor.visit_decorators(&mut it.decorators); + visitor.enter_scope(ScopeFlags::StrictMode, &it.scope_id); if let Some(id) = &mut it.id { visitor.visit_binding_identifier(id); } - visitor.enter_scope(ScopeFlags::StrictMode, &it.scope_id); if let Some(type_parameters) = &mut it.type_parameters { visitor.visit_ts_type_parameter_declaration(type_parameters); } diff --git a/crates/oxc_linter/src/rules/nextjs/no_duplicate_head.rs b/crates/oxc_linter/src/rules/nextjs/no_duplicate_head.rs index ae376e75072ba..4be6dd539e167 100644 --- a/crates/oxc_linter/src/rules/nextjs/no_duplicate_head.rs +++ b/crates/oxc_linter/src/rules/nextjs/no_duplicate_head.rs @@ -52,7 +52,7 @@ impl Rule for NoDuplicateHead { return; } - let Some(scope_id) = symbols.get_scope_id(symbol_id) else { return }; + let scope_id = symbols.get_scope_id(symbol_id); if scope_id != ctx.scopes().root_scope_id() { return; } diff --git a/crates/oxc_semantic/src/binder.rs b/crates/oxc_semantic/src/binder.rs index fc548926c35bb..a5b67627ee1c3 100644 --- a/crates/oxc_semantic/src/binder.rs +++ b/crates/oxc_semantic/src/binder.rs @@ -34,12 +34,7 @@ impl<'a> Binder for VariableDeclarator<'a> { if self.kind.is_lexical() { self.id.bound_names(&mut |ident| { - let symbol_id = builder.declare_symbol_on_current_scope( - ident.span, - &ident.name, - includes, - excludes, - ); + let symbol_id = builder.declare_symbol(ident.span, &ident.name, includes, excludes); ident.symbol_id.set(Some(symbol_id)); }); return; @@ -83,18 +78,18 @@ impl<'a> Binder for VariableDeclarator<'a> { impl<'a> Binder for Class<'a> { fn bind(&self, builder: &mut SemanticBuilder) { - let Some(ident) = &self.id else { return }; if !self.declare { - let symbol_id = if self.is_declaration() { - builder.declare_symbol_on_current_scope( - ident.span, - &ident.name, - SymbolFlags::Class, - SymbolFlags::ClassExcludes, - ) - } else { - builder.declare_symbol(ident.span, &ident.name, SymbolFlags::Class) - }; + let Some(ident) = &self.id else { return }; + let symbol_id = builder.declare_symbol( + ident.span, + &ident.name, + SymbolFlags::Class, + if self.is_declaration() { + SymbolFlags::ClassExcludes + } else { + SymbolFlags::empty() + }, + ); ident.symbol_id.set(Some(symbol_id)); } } @@ -152,8 +147,12 @@ impl<'a> Binder for Function<'a> { } else if self.r#type == FunctionType::FunctionExpression { // https://tc39.es/ecma262/#sec-runtime-semantics-instantiateordinaryfunctionexpression // 5. Perform ! funcEnv.CreateImmutableBinding(name, false). - let symbol_id = - builder.declare_symbol(ident.span, &ident.name, SymbolFlags::Function); + let symbol_id = builder.declare_symbol( + ident.span, + &ident.name, + SymbolFlags::Function, + SymbolFlags::empty(), + ); ident.symbol_id.set(Some(symbol_id)); } } @@ -201,12 +200,7 @@ impl<'a> Binder for BindingRestElement<'a> { let excludes = SymbolFlags::FunctionScopedVariable | SymbolFlags::FunctionScopedVariableExcludes; self.bound_names(&mut |ident| { - let symbol_id = builder.declare_symbol_on_current_scope( - ident.span, - &ident.name, - includes, - excludes, - ); + let symbol_id = builder.declare_symbol(ident.span, &ident.name, includes, excludes); ident.symbol_id.set(Some(symbol_id)); }); } @@ -245,12 +239,7 @@ impl<'a> Binder for FormalParameter<'a> { }; self.bound_names(&mut |ident| { - let symbol_id = builder.declare_symbol_on_current_scope( - ident.span, - &ident.name, - includes, - excludes, - ); + let symbol_id = builder.declare_symbol(ident.span, &ident.name, includes, excludes); ident.symbol_id.set(Some(symbol_id)); }); } @@ -269,7 +258,7 @@ impl<'a> Binder for CatchParameter<'a> { ident.symbol_id.set(Some(symbol_id)); } else { self.pattern.bound_names(&mut |ident| { - let symbol_id = builder.declare_symbol_on_current_scope( + let symbol_id = builder.declare_symbol( ident.span, &ident.name, SymbolFlags::BlockScopedVariable | SymbolFlags::CatchVariable, @@ -282,7 +271,7 @@ impl<'a> Binder for CatchParameter<'a> { } fn declare_symbol_for_import_specifier(ident: &BindingIdentifier, builder: &mut SemanticBuilder) { - let symbol_id = builder.declare_symbol_on_current_scope( + let symbol_id = builder.declare_symbol( ident.span, &ident.name, SymbolFlags::ImportBinding, @@ -317,7 +306,7 @@ impl<'a> Binder for TSImportEqualsDeclaration<'a> { impl<'a> Binder for TSTypeAliasDeclaration<'a> { fn bind(&self, builder: &mut SemanticBuilder) { - let symbol_id = builder.declare_symbol_on_current_scope( + let symbol_id = builder.declare_symbol( self.id.span, &self.id.name, SymbolFlags::TypeAlias, @@ -329,7 +318,7 @@ impl<'a> Binder for TSTypeAliasDeclaration<'a> { impl<'a> Binder for TSInterfaceDeclaration<'a> { fn bind(&self, builder: &mut SemanticBuilder) { - let symbol_id = builder.declare_symbol_on_current_scope( + let symbol_id = builder.declare_symbol( self.id.span, &self.id.name, SymbolFlags::Interface, @@ -348,12 +337,7 @@ impl<'a> Binder for TSEnumDeclaration<'a> { } else { SymbolFlags::RegularEnumExcludes }; - let symbol_id = builder.declare_symbol_on_current_scope( - self.id.span, - &self.id.name, - includes, - excludes, - ); + let symbol_id = builder.declare_symbol(self.id.span, &self.id.name, includes, excludes); self.id.symbol_id.set(Some(symbol_id)); } } @@ -370,7 +354,7 @@ impl<'a> Binder for TSEnumMember<'a> { TSEnumMemberName::StaticNumericLiteral(n) => Cow::Owned(n.value.to_string()), match_expression!(TSEnumMemberName) => panic!("TODO: implement"), }; - builder.declare_symbol_on_current_scope( + builder.declare_symbol( self.span, &name, SymbolFlags::EnumMember, @@ -384,7 +368,7 @@ impl<'a> Binder for TSModuleDeclaration<'a> { // At declaration time a module has no value declaration it is only when a value declaration // is made inside a the scope of a module that the symbol is modified let ambient = if self.declare { SymbolFlags::Ambient } else { SymbolFlags::None }; - builder.declare_symbol_on_current_scope( + builder.declare_symbol( self.span, self.id.name().as_str(), SymbolFlags::NameSpaceModule | ambient, @@ -395,7 +379,7 @@ impl<'a> Binder for TSModuleDeclaration<'a> { impl<'a> Binder for TSTypeParameter<'a> { fn bind(&self, builder: &mut SemanticBuilder) { - let symbol_id = builder.declare_symbol_on_current_scope( + let symbol_id = builder.declare_symbol( self.name.span, &self.name.name, SymbolFlags::TypeParameter, diff --git a/crates/oxc_semantic/src/builder.rs b/crates/oxc_semantic/src/builder.rs index cb185105fd48a..0e712bd6cc215 100644 --- a/crates/oxc_semantic/src/builder.rs +++ b/crates/oxc_semantic/src/builder.rs @@ -289,15 +289,6 @@ impl<'a> SemanticBuilder<'a> { } } - /// Declares a `Symbol` for the node, adds it to symbol table - /// - /// includes: the `SymbolFlags` that node has in addition to its declaration type (eg: export, ambient, etc.) - pub fn declare_symbol(&mut self, span: Span, name: &str, includes: SymbolFlags) -> SymbolId { - let includes = includes | self.current_symbol_flags; - let name = CompactStr::new(name); - self.symbols.create_symbol(span, name, self.current_node_id, includes, None) - } - /// Declares a `Symbol` for the node, adds it to symbol table, and binds it to the scope. /// /// includes: the `SymbolFlags` that node has in addition to its declaration type (eg: export, ambient, etc.) @@ -319,13 +310,14 @@ impl<'a> SemanticBuilder<'a> { } let includes = includes | self.current_symbol_flags; - let symbol_id = self.declare_symbol(span, name, includes); - self.symbols.set_scope_id(symbol_id, scope_id); - self.scope.add_binding(scope_id, CompactStr::new(name), symbol_id); + let name = CompactStr::new(name); + let symbol_id = self.symbols.create_symbol(span, name.clone(), includes, scope_id); + self.symbols.add_declaration(self.current_node_id); + self.scope.add_binding(scope_id, name, symbol_id); symbol_id } - pub fn declare_symbol_on_current_scope( + pub fn declare_symbol( &mut self, span: Span, name: &str, @@ -374,9 +366,11 @@ impl<'a> SemanticBuilder<'a> { includes: SymbolFlags, ) -> SymbolId { let includes = includes | self.current_symbol_flags; - let symbol_id = self.declare_symbol(span, name, includes); - self.symbols.set_scope_id(symbol_id, scope_id); - self.scope.get_bindings_mut(scope_id).insert(CompactStr::new(name), symbol_id); + let name = CompactStr::new(name); + let symbol_id = + self.symbols.create_symbol(span, name.clone(), includes, self.current_scope_id); + self.symbols.add_declaration(self.current_node_id); + self.scope.get_bindings_mut(scope_id).insert(name, symbol_id); symbol_id } @@ -390,22 +384,7 @@ impl<'a> SemanticBuilder<'a> { for (name, reference_ids) in current_refs.drain() { // 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(|| { - // If the current node is a class or function expression, - // try to get the id from the current node - // and check if it's the same name with the reference. - let id = match self.nodes.kind(self.current_node_id) { - AstKind::Function(func) if func.is_expression() => &func.id, - AstKind::Class(class) if class.is_expression() => &class.id, - _ => &None, - }; - if let Some(id) = id { - if id.name == name { - return id.symbol_id.get(); - } - } - None - }) { + if let Some(symbol_id) = bindings.get(&name).copied() { for reference_id in &reference_ids { self.symbols.references[*reference_id].set_symbol_id(symbol_id); } @@ -1481,8 +1460,8 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> { if let Some(annotation) = &func.return_type { self.visit_ts_type_annotation(annotation); } - self.leave_scope(); self.leave_node(kind); + self.leave_scope(); } fn visit_arrow_function_expression(&mut self, expr: &ArrowFunctionExpression<'a>) { @@ -1567,6 +1546,20 @@ impl<'a> SemanticBuilder<'a> { AstKind::ExportSpecifier(s) if s.export_kind.is_type() => { self.current_reference_flag = ReferenceFlag::Type; } + AstKind::BindingIdentifier(_) => { + if let Some(node) = self.nodes.parent_node(self.current_node_id) { + if let AstKind::Class(class) = node.kind() { + if class.is_expression() { + // We must to bind class expression when enter BindingIdentifier, + // because we should add binding to current scope + let previous_node_id = self.current_node_id; + self.current_node_id = node.id(); + class.bind(self); + self.current_node_id = previous_node_id; + } + } + } + } AstKind::ImportSpecifier(specifier) => { specifier.bind(self); } @@ -1598,9 +1591,10 @@ impl<'a> SemanticBuilder<'a> { } AstKind::Class(class) => { self.current_node_flags |= NodeFlags::Class; - class.bind(self); + if class.is_declaration() { + 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) => { diff --git a/crates/oxc_semantic/src/checker/javascript.rs b/crates/oxc_semantic/src/checker/javascript.rs index 396c7cde49d33..6e2024274fe57 100644 --- a/crates/oxc_semantic/src/checker/javascript.rs +++ b/crates/oxc_semantic/src/checker/javascript.rs @@ -137,8 +137,15 @@ pub fn check_identifier<'a>(name: &str, span: Span, node: &AstNode<'a>, ctx: &Se if ctx.source_type.is_module() { return ctx.error(reserved_keyword(name, span)); } + // It is a Syntax Error if ClassStaticBlockStatementList Contains await is true. - if ctx.scope.get_flags(node.scope_id()).is_class_static_block() { + if (matches!(ctx.nodes.parent_kind(node.id()), Some(AstKind::Class(_))) + && ctx + .scope + .get_parent_id(node.scope_id()) + .is_some_and(|id| ctx.scope.get_flags(id).is_class_static_block())) + || ctx.current_scope_flags().is_class_static_block() + { return ctx.error(class_static_block_await(span)); } } diff --git a/crates/oxc_semantic/src/lib.rs b/crates/oxc_semantic/src/lib.rs index 1a856d968f4d0..52376d4ff4974 100644 --- a/crates/oxc_semantic/src/lib.rs +++ b/crates/oxc_semantic/src/lib.rs @@ -121,7 +121,7 @@ impl<'a> Semantic<'a> { } /// Find which scope a symbol is declared in - pub fn symbol_scope(&self, symbol_id: SymbolId) -> Option { + pub fn symbol_scope(&self, symbol_id: SymbolId) -> ScopeId { self.symbols.get_scope_id(symbol_id) } @@ -198,7 +198,7 @@ mod tests { .iter_bindings() .find(|(_scope_id, _symbol_id, name)| name.as_str() == "Fn") .unwrap(); - assert_eq!(semantic.symbols.get_scope_id(top_level_a.1), Some(top_level_a.0)); + assert_eq!(semantic.symbols.get_scope_id(top_level_a.1), top_level_a.0); } #[test] diff --git a/crates/oxc_semantic/src/symbol.rs b/crates/oxc_semantic/src/symbol.rs index 43334d7870d2e..80bc798c1a0fa 100644 --- a/crates/oxc_semantic/src/symbol.rs +++ b/crates/oxc_semantic/src/symbol.rs @@ -32,7 +32,7 @@ pub struct SymbolTable { pub spans: IndexVec, pub names: IndexVec, pub flags: IndexVec, - pub scope_ids: IndexVec>, + pub scope_ids: IndexVec, /// Pointer to the AST Node where this symbol is declared pub declarations: IndexVec, pub resolved_references: IndexVec>, @@ -73,16 +73,6 @@ impl SymbolTable { }) } - pub fn get_symbol_id_from_declaration(&self, declaration: AstNodeId) -> Option { - 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] } @@ -107,20 +97,16 @@ impl SymbolTable { self.flags[symbol_id] |= includes; } - pub fn set_scope_id(&mut self, symbol_id: SymbolId, scope_id: ScopeId) { - self.scope_ids[symbol_id] = Some(scope_id); - } - - pub fn get_scope_id(&self, symbol_id: SymbolId) -> Option { + pub fn get_scope_id(&self, symbol_id: SymbolId) -> ScopeId { self.scope_ids[symbol_id] } pub fn get_scope_id_from_span(&self, span: &Span) -> Option { - self.get_symbol_id_from_span(span).and_then(|symbol_id| self.get_scope_id(symbol_id)) + self.get_symbol_id_from_span(span).map(|symbol_id| self.get_scope_id(symbol_id)) } pub fn get_scope_id_from_name(&self, name: &str) -> Option { - self.get_symbol_id_from_name(name).and_then(|symbol_id| self.get_scope_id(symbol_id)) + self.get_symbol_id_from_name(name).map(|symbol_id| self.get_scope_id(symbol_id)) } pub fn get_declaration(&self, symbol_id: SymbolId) -> AstNodeId { @@ -131,19 +117,21 @@ impl SymbolTable { &mut self, span: Span, name: CompactStr, - declaration: AstNodeId, flag: SymbolFlags, - scope_id: Option, + scope_id: ScopeId, ) -> SymbolId { _ = self.spans.push(span); _ = self.names.push(name); - _ = self.declarations.push(declaration); _ = self.flags.push(flag); _ = self.scope_ids.push(scope_id); _ = self.resolved_references.push(vec![]); self.redeclare_variables.push(vec![]) } + pub fn add_declaration(&mut self, node_id: AstNodeId) { + self.declarations.push(node_id); + } + pub fn add_redeclare_variable(&mut self, symbol_id: SymbolId, span: Span) { self.redeclare_variables[symbol_id].push(span); } diff --git a/crates/oxc_semantic/tests/integration/scopes.rs b/crates/oxc_semantic/tests/integration/scopes.rs index 235d0b979ab17..be50154e2b5d5 100644 --- a/crates/oxc_semantic/tests/integration/scopes.rs +++ b/crates/oxc_semantic/tests/integration/scopes.rs @@ -76,7 +76,7 @@ fn test_function_level_strict() { .is_in_scope(ScopeFlags::StrictMode | ScopeFlags::Function) .expect(|(semantic, symbol_id)| -> Result<(), &'static str> { let scope_id = semantic.symbol_scope(symbol_id); - let Some(parent_scope_id) = scope_id.and_then(|scope_id| semantic.scopes().get_parent_id(scope_id)) else { + let Some(parent_scope_id) = semantic.scopes().get_parent_id(scope_id) else { return Err("Expected x's scope to have a parent") }; let parent_flags = semantic.scopes().get_flags(parent_scope_id); diff --git a/crates/oxc_semantic/tests/integration/symbols.rs b/crates/oxc_semantic/tests/integration/symbols.rs index 0c55cd10bf1c3..8b43297749a19 100644 --- a/crates/oxc_semantic/tests/integration/symbols.rs +++ b/crates/oxc_semantic/tests/integration/symbols.rs @@ -27,6 +27,10 @@ fn test_function_simple() { #[test] fn test_function_expressions() { + SemanticTester::js("const x = function y() {}") + .has_some_symbol("y") + .contains_flags(SymbolFlags::Function) + .test(); SemanticTester::js("const x = () => {}") .has_some_symbol("x") .contains_flags(SymbolFlags::BlockScopedVariable | SymbolFlags::ConstVariable) diff --git a/crates/oxc_semantic/tests/integration/util/symbol_tester.rs b/crates/oxc_semantic/tests/integration/util/symbol_tester.rs index e4e65ab0059e5..ccc1929e9f78b 100644 --- a/crates/oxc_semantic/tests/integration/util/symbol_tester.rs +++ b/crates/oxc_semantic/tests/integration/util/symbol_tester.rs @@ -198,9 +198,8 @@ impl<'a> SymbolTester<'a> { self.test_result = match self.test_result { Ok(symbol_id) => { let scope_id = self.semantic.symbol_scope(symbol_id); - let scope_flags = - scope_id.map(|scope_id| self.semantic.scopes().get_flags(scope_id)); - if scope_flags.is_some_and(|flags| flags.contains(expected_flags)) { + let scope_flags = self.semantic.scopes().get_flags(scope_id); + if scope_flags.contains(expected_flags) { Ok(symbol_id) } else { Err(OxcDiagnostic::error(format!( @@ -220,9 +219,8 @@ impl<'a> SymbolTester<'a> { self.test_result = match self.test_result { Ok(symbol_id) => { let scope_id = self.semantic.symbol_scope(symbol_id); - let scope_flags = - scope_id.map(|scope_id| self.semantic.scopes().get_flags(scope_id)); - if scope_flags.is_some_and(|flag| flag.contains(excluded_flags)) { + let scope_flags = self.semantic.scopes().get_flags(scope_id); + if scope_flags.contains(excluded_flags) { Err(OxcDiagnostic::error(format!( "Binding {target_name} is in a scope with excluded flags.\n\tExpected: not {excluded_flags:?}\n\tActual: {scope_flags:?}" ))) diff --git a/crates/oxc_transformer/src/typescript/enum.rs b/crates/oxc_transformer/src/typescript/enum.rs index 1438a903d7d74..ba1de0af45093 100644 --- a/crates/oxc_transformer/src/typescript/enum.rs +++ b/crates/oxc_transformer/src/typescript/enum.rs @@ -2,7 +2,6 @@ use std::cell::Cell; use oxc_allocator::Vec; use oxc_ast::{ast::*, visit::walk_mut, VisitMut}; -use oxc_semantic::AstNodeId; use oxc_span::{Atom, Span, SPAN}; use oxc_syntax::{ number::{NumberBase, ToJsInt32, ToJsString}, @@ -78,9 +77,8 @@ impl<'a> TypeScriptEnum<'a> { let param_symbol_id = ctx.symbols_mut().create_symbol( decl.id.span, enum_name.to_compact_str(), - AstNodeId::dummy(), SymbolFlags::FunctionScopedVariable, - Some(func_scope_id), + func_scope_id, ); let ident = BindingIdentifier { span: decl.id.span, diff --git a/crates/oxc_traverse/src/context/scoping.rs b/crates/oxc_traverse/src/context/scoping.rs index 46da7b45d6b0d..b67a3adaa72e3 100644 --- a/crates/oxc_traverse/src/context/scoping.rs +++ b/crates/oxc_traverse/src/context/scoping.rs @@ -245,13 +245,7 @@ impl TraverseScoping { let name = CompactStr::new(&self.find_uid_name(name)); // Add binding to scope - let symbol_id = self.symbols.create_symbol( - SPAN, - name.clone(), - AstNodeId::dummy(), - flags, - Some(scope_id), - ); + let symbol_id = self.symbols.create_symbol(SPAN, name.clone(), flags, scope_id); self.scopes.add_binding(scope_id, name, symbol_id); symbol_id } diff --git a/crates/oxc_traverse/src/walk.rs b/crates/oxc_traverse/src/walk.rs index 8f6f9174a0fc8..59eb3a3e2f297 100644 --- a/crates/oxc_traverse/src/walk.rs +++ b/crates/oxc_traverse/src/walk.rs @@ -2459,12 +2459,6 @@ pub(crate) unsafe fn walk_class<'a, Tr: Traverse<'a>>( { walk_decorator(traverser, item as *mut _, ctx); } - if let Some(field) = - &mut *((node as *mut u8).add(ancestor::OFFSET_CLASS_ID) as *mut Option) - { - ctx.retag_stack(AncestorType::ClassId); - walk_binding_identifier(traverser, field as *mut _, ctx); - } let mut previous_scope_id = None; if let Some(scope_id) = (*((node as *mut u8).add(ancestor::OFFSET_CLASS_SCOPE_ID) as *mut Cell>)) @@ -2473,6 +2467,12 @@ pub(crate) unsafe fn walk_class<'a, Tr: Traverse<'a>>( previous_scope_id = Some(ctx.current_scope_id()); ctx.set_current_scope_id(scope_id); } + if let Some(field) = + &mut *((node as *mut u8).add(ancestor::OFFSET_CLASS_ID) as *mut Option) + { + ctx.retag_stack(AncestorType::ClassId); + walk_binding_identifier(traverser, field as *mut _, ctx); + } if let Some(field) = &mut *((node as *mut u8).add(ancestor::OFFSET_CLASS_TYPE_PARAMETERS) as *mut Option>) {