From 9c9deaeffed3a5ca7c1e8d3e8ffebf44f6fc3653 Mon Sep 17 00:00:00 2001 From: Dunqing <29533304+Dunqing@users.noreply.github.com> Date: Tue, 26 Nov 2024 11:21:35 +0000 Subject: [PATCH] feat(traverse): add `generate_uid_in_current_hoist_scope` method (#7423) Add an API to handle variable hoisting. --- crates/oxc_traverse/scripts/lib/walk.mjs | 19 +- crates/oxc_traverse/src/context/mod.rs | 34 +++- crates/oxc_traverse/src/context/scoping.rs | 39 +++- crates/oxc_traverse/src/generated/walk.rs | 221 +++++++++++---------- 4 files changed, 186 insertions(+), 127 deletions(-) diff --git a/crates/oxc_traverse/scripts/lib/walk.mjs b/crates/oxc_traverse/scripts/lib/walk.mjs index c84ea048e263f..03f10795761d9 100644 --- a/crates/oxc_traverse/scripts/lib/walk.mjs +++ b/crates/oxc_traverse/scripts/lib/walk.mjs @@ -109,11 +109,26 @@ function generateWalkForStruct(type, types) { // but we don't take that into account. // Visitor should not do that though, so maybe it's OK. // In final version, we should not make `scope_id` fields `Cell`s to prevent this. + enterScopeCode = ` let previous_scope_id = ctx.current_scope_id(); - ctx.set_current_scope_id((*(${makeFieldCode(scopeIdField)})).get().unwrap()); + let current_scope_id = (*(${makeFieldCode(scopeIdField)})).get().unwrap(); + ctx.set_current_scope_id(current_scope_id); `; - exitScopeCode = `ctx.set_current_scope_id(previous_scope_id);`; + + exitScopeCode = 'ctx.set_current_scope_id(previous_scope_id);'; + + // const Var = Self::Top.bits() | Self::Function.bits() | Self::ClassStaticBlock.bits() | Self::TsModuleBlock.bits(); + // `Function` type is a special case as its flags are set dynamically depending on the parent. + let isVarHoistingScope = type.name == 'Function' || + ['Top', 'Function', 'ClassStaticBlock', 'TsModuleBlock'].some(flag => scopeArgs.flags.includes(flag)); + if (isVarHoistingScope) { + enterScopeCode += ` + let previous_hoist_scope_id = ctx.current_hoist_scope_id(); + ctx.set_current_hoist_scope_id(current_scope_id); + `; + exitScopeCode += 'ctx.set_current_hoist_scope_id(previous_hoist_scope_id);'; + } } const fieldsCodes = visitedFields.map((field, index) => { diff --git a/crates/oxc_traverse/src/context/mod.rs b/crates/oxc_traverse/src/context/mod.rs index eda09ba266cc6..fb9b22fdbb87c 100644 --- a/crates/oxc_traverse/src/context/mod.rs +++ b/crates/oxc_traverse/src/context/mod.rs @@ -3,8 +3,8 @@ use oxc_ast::{ ast::{Expression, IdentifierReference, Statement}, AstBuilder, }; -use oxc_semantic::{NodeId, ScopeTree, SymbolTable}; -use oxc_span::{Atom, CompactStr, Span, SPAN}; +use oxc_semantic::{ScopeTree, SymbolTable}; +use oxc_span::{Atom, CompactStr, Span}; use oxc_syntax::{ reference::{ReferenceFlags, ReferenceId}, scope::{ScopeFlags, ScopeId}, @@ -186,6 +186,14 @@ impl<'a> TraverseCtx<'a> { self.scoping.current_scope_id() } + /// Get current var hoisting scope ID. + /// + /// Shortcut for `ctx.scoping.current_hoist_scope_id`. + #[inline] + pub fn current_hoist_scope_id(&self) -> ScopeId { + self.scoping.current_hoist_scope_id() + } + /// Get current scope flags. /// /// Shortcut for `ctx.scoping.current_scope_flags`. @@ -356,12 +364,7 @@ impl<'a> TraverseCtx<'a> { // Get name for UID let name = self.generate_uid_name(name); let name_atom = self.ast.atom(&name); - - // Add binding to scope - let symbol_id = - self.symbols_mut().create_symbol(SPAN, name.clone(), flags, scope_id, NodeId::DUMMY); - self.scopes_mut().add_binding(scope_id, name, symbol_id); - + let symbol_id = self.scoping.add_binding(name, scope_id, flags); BoundIdentifier::new(name_atom, symbol_id) } @@ -421,6 +424,15 @@ impl<'a> TraverseCtx<'a> { self.generate_uid_based_on_node(node, self.current_scope_id(), flags) } + /// Generate UID in current hoist scope. + /// + /// See also comments on [`TraverseScoping::generate_uid_name`] for important information + /// on how UIDs are generated. There are some potential "gotchas". + #[inline] + pub fn generate_uid_in_current_hoist_scope(&mut self, name: &str) -> BoundIdentifier<'a> { + self.generate_uid(name, self.current_hoist_scope_id(), SymbolFlags::FunctionScopedVariable) + } + /// Create a reference bound to a `SymbolId`. /// /// This is a shortcut for `ctx.scoping.create_bound_reference`. @@ -623,4 +635,10 @@ impl<'a> TraverseCtx<'a> { pub(crate) fn set_current_scope_id(&mut self, scope_id: ScopeId) { self.scoping.set_current_scope_id(scope_id); } + + /// Shortcut for `ctx.scoping.set_current_hoist_scope_id`, to make `walk_*` methods less verbose. + #[inline] + pub(crate) fn set_current_hoist_scope_id(&mut self, scope_id: ScopeId) { + self.scoping.set_current_hoist_scope_id(scope_id); + } } diff --git a/crates/oxc_traverse/src/context/scoping.rs b/crates/oxc_traverse/src/context/scoping.rs index 06d61cf630041..d391acc3d8fce 100644 --- a/crates/oxc_traverse/src/context/scoping.rs +++ b/crates/oxc_traverse/src/context/scoping.rs @@ -26,6 +26,7 @@ pub struct TraverseScoping { symbols: SymbolTable, uid_names: Option>, current_scope_id: ScopeId, + current_hoist_scope_id: ScopeId, } // Public methods @@ -40,6 +41,12 @@ impl TraverseScoping { self.current_scope_id } + /// Get current var hoisting scope ID + #[inline] + pub(crate) fn current_hoist_scope_id(&self) -> ScopeId { + self.current_hoist_scope_id + } + /// Get current scope flags #[inline] pub fn current_scope_flags(&self) -> ScopeFlags { @@ -164,6 +171,21 @@ impl TraverseScoping { self.scopes.delete_scope(scope_id); } + /// Add binding to [`ScopeTree`] and [`SymbolTable`]. + #[inline] + pub(crate) fn add_binding( + &mut self, + name: CompactStr, + scope_id: ScopeId, + flags: SymbolFlags, + ) -> SymbolId { + let symbol_id = + self.symbols.create_symbol(SPAN, name.clone(), flags, scope_id, NodeId::DUMMY); + self.scopes.add_binding(scope_id, name, symbol_id); + + symbol_id + } + /// Generate binding. /// /// Creates a symbol with the provided name and flags and adds it to the specified scope. @@ -173,13 +195,7 @@ impl TraverseScoping { scope_id: ScopeId, flags: SymbolFlags, ) -> BoundIdentifier<'a> { - let owned_name = name.to_compact_str(); - - // Add binding to scope - let symbol_id = - self.symbols.create_symbol(SPAN, owned_name.clone(), flags, scope_id, NodeId::DUMMY); - self.scopes.add_binding(scope_id, owned_name, symbol_id); - + let symbol_id = self.add_binding(name.to_compact_str(), scope_id, flags); BoundIdentifier::new(name, symbol_id) } @@ -386,8 +402,9 @@ impl TraverseScoping { scopes, symbols, uid_names: None, - // Dummy value. Immediately overwritten in `walk_program`. + // Dummy values. Both immediately overwritten in `walk_program`. current_scope_id: ScopeId::new(0), + current_hoist_scope_id: ScopeId::new(0), } } @@ -397,6 +414,12 @@ impl TraverseScoping { self.current_scope_id = scope_id; } + /// Set current hoist scope ID + #[inline] + pub(crate) fn set_current_hoist_scope_id(&mut self, scope_id: ScopeId) { + self.current_hoist_scope_id = scope_id; + } + /// Get `uid_names`. /// /// Iterate through all symbols and unresolved references in AST and identify any var names diff --git a/crates/oxc_traverse/src/generated/walk.rs b/crates/oxc_traverse/src/generated/walk.rs index d6cfa0f453fdb..9229e3ac35823 100644 --- a/crates/oxc_traverse/src/generated/walk.rs +++ b/crates/oxc_traverse/src/generated/walk.rs @@ -32,11 +32,13 @@ pub(crate) unsafe fn walk_program<'a, Tr: Traverse<'a>>( ) { traverser.enter_program(&mut *node, ctx); let previous_scope_id = ctx.current_scope_id(); - ctx.set_current_scope_id( - (*((node as *mut u8).add(ancestor::OFFSET_PROGRAM_SCOPE_ID) as *mut Cell>)) - .get() - .unwrap(), - ); + let current_scope_id = (*((node as *mut u8).add(ancestor::OFFSET_PROGRAM_SCOPE_ID) + as *mut Cell>)) + .get() + .unwrap(); + ctx.set_current_scope_id(current_scope_id); + let previous_hoist_scope_id = ctx.current_hoist_scope_id(); + ctx.set_current_hoist_scope_id(current_scope_id); let pop_token = ctx .push_stack(Ancestor::ProgramHashbang(ancestor::ProgramWithoutHashbang(node, PhantomData))); if let Some(field) = @@ -59,6 +61,7 @@ pub(crate) unsafe fn walk_program<'a, Tr: Traverse<'a>>( ); ctx.pop_stack(pop_token); ctx.set_current_scope_id(previous_scope_id); + ctx.set_current_hoist_scope_id(previous_hoist_scope_id); traverser.exit_program(&mut *node, ctx); } @@ -1417,12 +1420,11 @@ pub(crate) unsafe fn walk_block_statement<'a, Tr: Traverse<'a>>( ) { traverser.enter_block_statement(&mut *node, ctx); let previous_scope_id = ctx.current_scope_id(); - ctx.set_current_scope_id( - (*((node as *mut u8).add(ancestor::OFFSET_BLOCK_STATEMENT_SCOPE_ID) - as *mut Cell>)) - .get() - .unwrap(), - ); + let current_scope_id = (*((node as *mut u8).add(ancestor::OFFSET_BLOCK_STATEMENT_SCOPE_ID) + as *mut Cell>)) + .get() + .unwrap(); + ctx.set_current_scope_id(current_scope_id); let pop_token = ctx.push_stack(Ancestor::BlockStatementBody( ancestor::BlockStatementWithoutBody(node, PhantomData), )); @@ -1623,12 +1625,11 @@ pub(crate) unsafe fn walk_for_statement<'a, Tr: Traverse<'a>>( ) { traverser.enter_for_statement(&mut *node, ctx); let previous_scope_id = ctx.current_scope_id(); - ctx.set_current_scope_id( - (*((node as *mut u8).add(ancestor::OFFSET_FOR_STATEMENT_SCOPE_ID) - as *mut Cell>)) - .get() - .unwrap(), - ); + let current_scope_id = (*((node as *mut u8).add(ancestor::OFFSET_FOR_STATEMENT_SCOPE_ID) + as *mut Cell>)) + .get() + .unwrap(); + ctx.set_current_scope_id(current_scope_id); let pop_token = ctx.push_stack(Ancestor::ForStatementInit(ancestor::ForStatementWithoutInit( node, PhantomData, @@ -1726,12 +1727,11 @@ pub(crate) unsafe fn walk_for_in_statement<'a, Tr: Traverse<'a>>( ) { traverser.enter_for_in_statement(&mut *node, ctx); let previous_scope_id = ctx.current_scope_id(); - ctx.set_current_scope_id( - (*((node as *mut u8).add(ancestor::OFFSET_FOR_IN_STATEMENT_SCOPE_ID) - as *mut Cell>)) - .get() - .unwrap(), - ); + let current_scope_id = (*((node as *mut u8).add(ancestor::OFFSET_FOR_IN_STATEMENT_SCOPE_ID) + as *mut Cell>)) + .get() + .unwrap(); + ctx.set_current_scope_id(current_scope_id); let pop_token = ctx.push_stack(Ancestor::ForInStatementLeft( ancestor::ForInStatementWithoutLeft(node, PhantomData), )); @@ -1791,12 +1791,11 @@ pub(crate) unsafe fn walk_for_of_statement<'a, Tr: Traverse<'a>>( ) { traverser.enter_for_of_statement(&mut *node, ctx); let previous_scope_id = ctx.current_scope_id(); - ctx.set_current_scope_id( - (*((node as *mut u8).add(ancestor::OFFSET_FOR_OF_STATEMENT_SCOPE_ID) - as *mut Cell>)) - .get() - .unwrap(), - ); + let current_scope_id = (*((node as *mut u8).add(ancestor::OFFSET_FOR_OF_STATEMENT_SCOPE_ID) + as *mut Cell>)) + .get() + .unwrap(); + ctx.set_current_scope_id(current_scope_id); let pop_token = ctx.push_stack(Ancestor::ForOfStatementLeft( ancestor::ForOfStatementWithoutLeft(node, PhantomData), )); @@ -1915,12 +1914,11 @@ pub(crate) unsafe fn walk_switch_statement<'a, Tr: Traverse<'a>>( ctx, ); let previous_scope_id = ctx.current_scope_id(); - ctx.set_current_scope_id( - (*((node as *mut u8).add(ancestor::OFFSET_SWITCH_STATEMENT_SCOPE_ID) - as *mut Cell>)) - .get() - .unwrap(), - ); + let current_scope_id = (*((node as *mut u8).add(ancestor::OFFSET_SWITCH_STATEMENT_SCOPE_ID) + as *mut Cell>)) + .get() + .unwrap(); + ctx.set_current_scope_id(current_scope_id); ctx.retag_stack(AncestorType::SwitchStatementCases); for item in (*((node as *mut u8).add(ancestor::OFFSET_SWITCH_STATEMENT_CASES) as *mut Vec)) @@ -2036,12 +2034,11 @@ pub(crate) unsafe fn walk_catch_clause<'a, Tr: Traverse<'a>>( ) { traverser.enter_catch_clause(&mut *node, ctx); let previous_scope_id = ctx.current_scope_id(); - ctx.set_current_scope_id( - (*((node as *mut u8).add(ancestor::OFFSET_CATCH_CLAUSE_SCOPE_ID) - as *mut Cell>)) - .get() - .unwrap(), - ); + let current_scope_id = (*((node as *mut u8).add(ancestor::OFFSET_CATCH_CLAUSE_SCOPE_ID) + as *mut Cell>)) + .get() + .unwrap(); + ctx.set_current_scope_id(current_scope_id); let pop_token = ctx.push_stack(Ancestor::CatchClauseParam(ancestor::CatchClauseWithoutParam( node, PhantomData, @@ -2263,12 +2260,13 @@ pub(crate) unsafe fn walk_function<'a, Tr: Traverse<'a>>( ) { traverser.enter_function(&mut *node, ctx); let previous_scope_id = ctx.current_scope_id(); - ctx.set_current_scope_id( - (*((node as *mut u8).add(ancestor::OFFSET_FUNCTION_SCOPE_ID) - as *mut Cell>)) - .get() - .unwrap(), - ); + let current_scope_id = (*((node as *mut u8).add(ancestor::OFFSET_FUNCTION_SCOPE_ID) + as *mut Cell>)) + .get() + .unwrap(); + ctx.set_current_scope_id(current_scope_id); + let previous_hoist_scope_id = ctx.current_hoist_scope_id(); + ctx.set_current_hoist_scope_id(current_scope_id); let pop_token = ctx.push_stack(Ancestor::FunctionId(ancestor::FunctionWithoutId(node, PhantomData))); if let Some(field) = &mut *((node as *mut u8).add(ancestor::OFFSET_FUNCTION_ID) @@ -2309,6 +2307,7 @@ pub(crate) unsafe fn walk_function<'a, Tr: Traverse<'a>>( } ctx.pop_stack(pop_token); ctx.set_current_scope_id(previous_scope_id); + ctx.set_current_hoist_scope_id(previous_hoist_scope_id); traverser.exit_function(&mut *node, ctx); } @@ -2394,12 +2393,14 @@ pub(crate) unsafe fn walk_arrow_function_expression<'a, Tr: Traverse<'a>>( ) { traverser.enter_arrow_function_expression(&mut *node, ctx); let previous_scope_id = ctx.current_scope_id(); - ctx.set_current_scope_id( - (*((node as *mut u8).add(ancestor::OFFSET_ARROW_FUNCTION_EXPRESSION_SCOPE_ID) - as *mut Cell>)) - .get() - .unwrap(), - ); + let current_scope_id = (*((node as *mut u8) + .add(ancestor::OFFSET_ARROW_FUNCTION_EXPRESSION_SCOPE_ID) + as *mut Cell>)) + .get() + .unwrap(); + ctx.set_current_scope_id(current_scope_id); + let previous_hoist_scope_id = ctx.current_hoist_scope_id(); + ctx.set_current_hoist_scope_id(current_scope_id); let pop_token = ctx.push_stack(Ancestor::ArrowFunctionExpressionTypeParameters( ancestor::ArrowFunctionExpressionWithoutTypeParameters(node, PhantomData), )); @@ -2432,6 +2433,7 @@ pub(crate) unsafe fn walk_arrow_function_expression<'a, Tr: Traverse<'a>>( ); ctx.pop_stack(pop_token); ctx.set_current_scope_id(previous_scope_id); + ctx.set_current_hoist_scope_id(previous_hoist_scope_id); traverser.exit_arrow_function_expression(&mut *node, ctx); } @@ -2473,11 +2475,11 @@ pub(crate) unsafe fn walk_class<'a, Tr: Traverse<'a>>( walk_binding_identifier(traverser, field as *mut _, ctx); } let previous_scope_id = ctx.current_scope_id(); - ctx.set_current_scope_id( - (*((node as *mut u8).add(ancestor::OFFSET_CLASS_SCOPE_ID) as *mut Cell>)) - .get() - .unwrap(), - ); + let current_scope_id = (*((node as *mut u8).add(ancestor::OFFSET_CLASS_SCOPE_ID) + as *mut Cell>)) + .get() + .unwrap(); + ctx.set_current_scope_id(current_scope_id); if let Some(field) = &mut *((node as *mut u8).add(ancestor::OFFSET_CLASS_TYPE_PARAMETERS) as *mut Option>) { @@ -2646,12 +2648,13 @@ pub(crate) unsafe fn walk_static_block<'a, Tr: Traverse<'a>>( ) { traverser.enter_static_block(&mut *node, ctx); let previous_scope_id = ctx.current_scope_id(); - ctx.set_current_scope_id( - (*((node as *mut u8).add(ancestor::OFFSET_STATIC_BLOCK_SCOPE_ID) - as *mut Cell>)) - .get() - .unwrap(), - ); + let current_scope_id = (*((node as *mut u8).add(ancestor::OFFSET_STATIC_BLOCK_SCOPE_ID) + as *mut Cell>)) + .get() + .unwrap(); + ctx.set_current_scope_id(current_scope_id); + let previous_hoist_scope_id = ctx.current_hoist_scope_id(); + ctx.set_current_hoist_scope_id(current_scope_id); let pop_token = ctx .push_stack(Ancestor::StaticBlockBody(ancestor::StaticBlockWithoutBody(node, PhantomData))); walk_statements( @@ -2661,6 +2664,7 @@ pub(crate) unsafe fn walk_static_block<'a, Tr: Traverse<'a>>( ); ctx.pop_stack(pop_token); ctx.set_current_scope_id(previous_scope_id); + ctx.set_current_hoist_scope_id(previous_hoist_scope_id); traverser.exit_static_block(&mut *node, ctx); } @@ -3670,12 +3674,11 @@ pub(crate) unsafe fn walk_ts_enum_declaration<'a, Tr: Traverse<'a>>( ctx, ); let previous_scope_id = ctx.current_scope_id(); - ctx.set_current_scope_id( - (*((node as *mut u8).add(ancestor::OFFSET_TS_ENUM_DECLARATION_SCOPE_ID) - as *mut Cell>)) - .get() - .unwrap(), - ); + let current_scope_id = (*((node as *mut u8).add(ancestor::OFFSET_TS_ENUM_DECLARATION_SCOPE_ID) + as *mut Cell>)) + .get() + .unwrap(); + ctx.set_current_scope_id(current_scope_id); ctx.retag_stack(AncestorType::TSEnumDeclarationMembers); for item in (*((node as *mut u8).add(ancestor::OFFSET_TS_ENUM_DECLARATION_MEMBERS) as *mut Vec)) @@ -3919,12 +3922,11 @@ pub(crate) unsafe fn walk_ts_conditional_type<'a, Tr: Traverse<'a>>( ctx, ); let previous_scope_id = ctx.current_scope_id(); - ctx.set_current_scope_id( - (*((node as *mut u8).add(ancestor::OFFSET_TS_CONDITIONAL_TYPE_SCOPE_ID) - as *mut Cell>)) - .get() - .unwrap(), - ); + let current_scope_id = (*((node as *mut u8).add(ancestor::OFFSET_TS_CONDITIONAL_TYPE_SCOPE_ID) + as *mut Cell>)) + .get() + .unwrap(); + ctx.set_current_scope_id(current_scope_id); ctx.retag_stack(AncestorType::TSConditionalTypeExtendsType); walk_ts_type( traverser, @@ -4476,12 +4478,12 @@ pub(crate) unsafe fn walk_ts_type_alias_declaration<'a, Tr: Traverse<'a>>( ctx, ); let previous_scope_id = ctx.current_scope_id(); - ctx.set_current_scope_id( - (*((node as *mut u8).add(ancestor::OFFSET_TS_TYPE_ALIAS_DECLARATION_SCOPE_ID) - as *mut Cell>)) - .get() - .unwrap(), - ); + let current_scope_id = (*((node as *mut u8) + .add(ancestor::OFFSET_TS_TYPE_ALIAS_DECLARATION_SCOPE_ID) + as *mut Cell>)) + .get() + .unwrap(); + ctx.set_current_scope_id(current_scope_id); if let Some(field) = &mut *((node as *mut u8) .add(ancestor::OFFSET_TS_TYPE_ALIAS_DECLARATION_TYPE_PARAMETERS) as *mut Option>) @@ -4542,12 +4544,12 @@ pub(crate) unsafe fn walk_ts_interface_declaration<'a, Tr: Traverse<'a>>( ctx, ); let previous_scope_id = ctx.current_scope_id(); - ctx.set_current_scope_id( - (*((node as *mut u8).add(ancestor::OFFSET_TS_INTERFACE_DECLARATION_SCOPE_ID) - as *mut Cell>)) - .get() - .unwrap(), - ); + let current_scope_id = (*((node as *mut u8) + .add(ancestor::OFFSET_TS_INTERFACE_DECLARATION_SCOPE_ID) + as *mut Cell>)) + .get() + .unwrap(); + ctx.set_current_scope_id(current_scope_id); if let Some(field) = &mut *((node as *mut u8) .add(ancestor::OFFSET_TS_INTERFACE_DECLARATION_EXTENDS) as *mut Option>) @@ -4719,12 +4721,11 @@ pub(crate) unsafe fn walk_ts_method_signature<'a, Tr: Traverse<'a>>( ) { traverser.enter_ts_method_signature(&mut *node, ctx); let previous_scope_id = ctx.current_scope_id(); - ctx.set_current_scope_id( - (*((node as *mut u8).add(ancestor::OFFSET_TS_METHOD_SIGNATURE_SCOPE_ID) - as *mut Cell>)) - .get() - .unwrap(), - ); + let current_scope_id = (*((node as *mut u8).add(ancestor::OFFSET_TS_METHOD_SIGNATURE_SCOPE_ID) + as *mut Cell>)) + .get() + .unwrap(); + ctx.set_current_scope_id(current_scope_id); let pop_token = ctx.push_stack(Ancestor::TSMethodSignatureKey( ancestor::TSMethodSignatureWithoutKey(node, PhantomData), )); @@ -4773,12 +4774,12 @@ pub(crate) unsafe fn walk_ts_construct_signature_declaration<'a, Tr: Traverse<'a ) { traverser.enter_ts_construct_signature_declaration(&mut *node, ctx); let previous_scope_id = ctx.current_scope_id(); - ctx.set_current_scope_id( - (*((node as *mut u8).add(ancestor::OFFSET_TS_CONSTRUCT_SIGNATURE_DECLARATION_SCOPE_ID) - as *mut Cell>)) - .get() - .unwrap(), - ); + let current_scope_id = (*((node as *mut u8) + .add(ancestor::OFFSET_TS_CONSTRUCT_SIGNATURE_DECLARATION_SCOPE_ID) + as *mut Cell>)) + .get() + .unwrap(); + ctx.set_current_scope_id(current_scope_id); let pop_token = ctx.push_stack(Ancestor::TSConstructSignatureDeclarationTypeParameters( ancestor::TSConstructSignatureDeclarationWithoutTypeParameters(node, PhantomData), )); @@ -4908,12 +4909,14 @@ pub(crate) unsafe fn walk_ts_module_declaration<'a, Tr: Traverse<'a>>( ctx, ); let previous_scope_id = ctx.current_scope_id(); - ctx.set_current_scope_id( + let current_scope_id = (*((node as *mut u8).add(ancestor::OFFSET_TS_MODULE_DECLARATION_SCOPE_ID) as *mut Cell>)) .get() - .unwrap(), - ); + .unwrap(); + ctx.set_current_scope_id(current_scope_id); + let previous_hoist_scope_id = ctx.current_hoist_scope_id(); + ctx.set_current_hoist_scope_id(current_scope_id); if let Some(field) = &mut *((node as *mut u8).add(ancestor::OFFSET_TS_MODULE_DECLARATION_BODY) as *mut Option) { @@ -4922,6 +4925,7 @@ pub(crate) unsafe fn walk_ts_module_declaration<'a, Tr: Traverse<'a>>( } ctx.pop_stack(pop_token); ctx.set_current_scope_id(previous_scope_id); + ctx.set_current_hoist_scope_id(previous_hoist_scope_id); traverser.exit_ts_module_declaration(&mut *node, ctx); } @@ -5248,12 +5252,11 @@ pub(crate) unsafe fn walk_ts_mapped_type<'a, Tr: Traverse<'a>>( ) { traverser.enter_ts_mapped_type(&mut *node, ctx); let previous_scope_id = ctx.current_scope_id(); - ctx.set_current_scope_id( - (*((node as *mut u8).add(ancestor::OFFSET_TS_MAPPED_TYPE_SCOPE_ID) - as *mut Cell>)) - .get() - .unwrap(), - ); + let current_scope_id = (*((node as *mut u8).add(ancestor::OFFSET_TS_MAPPED_TYPE_SCOPE_ID) + as *mut Cell>)) + .get() + .unwrap(); + ctx.set_current_scope_id(current_scope_id); let pop_token = ctx.push_stack(Ancestor::TSMappedTypeTypeParameter( ancestor::TSMappedTypeWithoutTypeParameter(node, PhantomData), ));