diff --git a/crates/oxc_traverse/scripts/lib/walk.mjs b/crates/oxc_traverse/scripts/lib/walk.mjs index 03f10795761d9..2fab7dbcfd360 100644 --- a/crates/oxc_traverse/scripts/lib/walk.mjs +++ b/crates/oxc_traverse/scripts/lib/walk.mjs @@ -129,6 +129,23 @@ function generateWalkForStruct(type, types) { `; exitScopeCode += 'ctx.set_current_hoist_scope_id(previous_hoist_scope_id);'; } + + // TODO: Type names shouldn't be hard-coded here. Block scopes should be signalled by attrs in AST. + let isBlockScope = [ + 'Program', + 'BlockStatement', + 'Function', + 'ArrowFunctionExpression', + 'StaticBlock', + 'TSModuleDeclaration', + ].includes(type.name); + if (isBlockScope) { + enterScopeCode += ` + let previous_block_scope_id = ctx.current_block_scope_id(); + ctx.set_current_block_scope_id(current_scope_id); + `; + exitScopeCode += 'ctx.set_current_block_scope_id(previous_block_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 4df72220d5c43..98b62e8d5c0b2 100644 --- a/crates/oxc_traverse/src/context/mod.rs +++ b/crates/oxc_traverse/src/context/mod.rs @@ -188,6 +188,14 @@ impl<'a> TraverseCtx<'a> { self.scoping.current_hoist_scope_id() } + /// Get current block scope ID. + /// + /// Shortcut for `ctx.scoping.current_block_scope_id`. + #[inline] + pub fn current_block_scope_id(&self) -> ScopeId { + self.scoping.current_block_scope_id() + } + /// Get current scope flags. /// /// Shortcut for `ctx.scoping.current_scope_flags`. @@ -659,4 +667,10 @@ impl<'a> TraverseCtx<'a> { pub(crate) fn set_current_hoist_scope_id(&mut self, scope_id: ScopeId) { self.scoping.set_current_hoist_scope_id(scope_id); } + + /// Shortcut for `ctx.scoping.set_current_block_scope_id`, to make `walk_*` methods less verbose. + #[inline] + pub(crate) fn set_current_block_scope_id(&mut self, scope_id: ScopeId) { + self.scoping.set_current_block_scope_id(scope_id); + } } diff --git a/crates/oxc_traverse/src/context/scoping.rs b/crates/oxc_traverse/src/context/scoping.rs index 5ec763a87689d..96825d5bd7da6 100644 --- a/crates/oxc_traverse/src/context/scoping.rs +++ b/crates/oxc_traverse/src/context/scoping.rs @@ -27,6 +27,7 @@ pub struct TraverseScoping { uid_names: Option>, current_scope_id: ScopeId, current_hoist_scope_id: ScopeId, + current_block_scope_id: ScopeId, } // Public methods @@ -43,6 +44,12 @@ impl TraverseScoping { self.current_hoist_scope_id } + /// Get current block scope ID + #[inline] + pub(crate) fn current_block_scope_id(&self) -> ScopeId { + self.current_block_scope_id + } + /// Get current scope flags #[inline] pub fn current_scope_flags(&self) -> ScopeFlags { @@ -390,6 +397,7 @@ impl TraverseScoping { // Dummy values. Both immediately overwritten in `walk_program`. current_scope_id: ScopeId::new(0), current_hoist_scope_id: ScopeId::new(0), + current_block_scope_id: ScopeId::new(0), } } @@ -410,6 +418,12 @@ impl TraverseScoping { self.current_hoist_scope_id = scope_id; } + /// Set current block scope ID + #[inline] + pub(crate) fn set_current_block_scope_id(&mut self, scope_id: ScopeId) { + self.current_block_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 9229e3ac35823..8437b28fb5c73 100644 --- a/crates/oxc_traverse/src/generated/walk.rs +++ b/crates/oxc_traverse/src/generated/walk.rs @@ -39,6 +39,8 @@ pub(crate) unsafe fn walk_program<'a, Tr: Traverse<'a>>( 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 previous_block_scope_id = ctx.current_block_scope_id(); + ctx.set_current_block_scope_id(current_scope_id); let pop_token = ctx .push_stack(Ancestor::ProgramHashbang(ancestor::ProgramWithoutHashbang(node, PhantomData))); if let Some(field) = @@ -62,6 +64,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); + ctx.set_current_block_scope_id(previous_block_scope_id); traverser.exit_program(&mut *node, ctx); } @@ -1425,6 +1428,8 @@ pub(crate) unsafe fn walk_block_statement<'a, Tr: Traverse<'a>>( .get() .unwrap(); ctx.set_current_scope_id(current_scope_id); + let previous_block_scope_id = ctx.current_block_scope_id(); + ctx.set_current_block_scope_id(current_scope_id); let pop_token = ctx.push_stack(Ancestor::BlockStatementBody( ancestor::BlockStatementWithoutBody(node, PhantomData), )); @@ -1435,6 +1440,7 @@ pub(crate) unsafe fn walk_block_statement<'a, Tr: Traverse<'a>>( ); ctx.pop_stack(pop_token); ctx.set_current_scope_id(previous_scope_id); + ctx.set_current_block_scope_id(previous_block_scope_id); traverser.exit_block_statement(&mut *node, ctx); } @@ -2267,6 +2273,8 @@ pub(crate) unsafe fn walk_function<'a, Tr: Traverse<'a>>( 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 previous_block_scope_id = ctx.current_block_scope_id(); + ctx.set_current_block_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) @@ -2308,6 +2316,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); + ctx.set_current_block_scope_id(previous_block_scope_id); traverser.exit_function(&mut *node, ctx); } @@ -2401,6 +2410,8 @@ pub(crate) unsafe fn walk_arrow_function_expression<'a, Tr: Traverse<'a>>( 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 previous_block_scope_id = ctx.current_block_scope_id(); + ctx.set_current_block_scope_id(current_scope_id); let pop_token = ctx.push_stack(Ancestor::ArrowFunctionExpressionTypeParameters( ancestor::ArrowFunctionExpressionWithoutTypeParameters(node, PhantomData), )); @@ -2434,6 +2445,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); + ctx.set_current_block_scope_id(previous_block_scope_id); traverser.exit_arrow_function_expression(&mut *node, ctx); } @@ -2655,6 +2667,8 @@ pub(crate) unsafe fn walk_static_block<'a, Tr: Traverse<'a>>( 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 previous_block_scope_id = ctx.current_block_scope_id(); + ctx.set_current_block_scope_id(current_scope_id); let pop_token = ctx .push_stack(Ancestor::StaticBlockBody(ancestor::StaticBlockWithoutBody(node, PhantomData))); walk_statements( @@ -2665,6 +2679,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); + ctx.set_current_block_scope_id(previous_block_scope_id); traverser.exit_static_block(&mut *node, ctx); } @@ -4917,6 +4932,8 @@ pub(crate) unsafe fn walk_ts_module_declaration<'a, Tr: Traverse<'a>>( 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 previous_block_scope_id = ctx.current_block_scope_id(); + ctx.set_current_block_scope_id(current_scope_id); if let Some(field) = &mut *((node as *mut u8).add(ancestor::OFFSET_TS_MODULE_DECLARATION_BODY) as *mut Option) { @@ -4926,6 +4943,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); + ctx.set_current_block_scope_id(previous_block_scope_id); traverser.exit_ts_module_declaration(&mut *node, ctx); }