diff --git a/crates/oxc_ast/src/ast/js.rs b/crates/oxc_ast/src/ast/js.rs index a9d3fd4a0c162..f03d81f49d4b5 100644 --- a/crates/oxc_ast/src/ast/js.rs +++ b/crates/oxc_ast/src/ast/js.rs @@ -1439,7 +1439,7 @@ pub struct BindingRestElement<'a> { #[scope( // TODO: `ScopeFlags::Function` is not correct if this is a `MethodDefinition` flags(flags.unwrap_or(ScopeFlags::empty()) | ScopeFlags::Function), - strict_if(self.body.as_ref().is_some_and(|body| body.has_use_strict_directive())), + strict_if(self.is_strict()), )] #[derive(Debug)] #[cfg_attr(feature = "serialize", derive(Serialize, Tsify))] @@ -1470,8 +1470,8 @@ pub struct Function<'a> { /// ``` pub this_param: Option>, pub params: Box<'a, FormalParameters<'a>>, - pub body: Option>>, pub return_type: Option>>, + pub body: Option>>, pub scope_id: Cell>, } diff --git a/crates/oxc_ast/src/ast_builder_impl.rs b/crates/oxc_ast/src/ast_builder_impl.rs index a56b6ab61ac74..373cb7dccb20e 100644 --- a/crates/oxc_ast/src/ast_builder_impl.rs +++ b/crates/oxc_ast/src/ast_builder_impl.rs @@ -150,8 +150,8 @@ impl<'a> AstBuilder<'a> { Option::::None, None, params, - body, Option::::None, + body, )) } diff --git a/crates/oxc_ast/src/generated/ast_builder.rs b/crates/oxc_ast/src/generated/ast_builder.rs index 5034aef8b361a..4f1d7fa9ce379 100644 --- a/crates/oxc_ast/src/generated/ast_builder.rs +++ b/crates/oxc_ast/src/generated/ast_builder.rs @@ -554,14 +554,14 @@ impl<'a> AstBuilder<'a> { type_parameters: T1, this_param: Option>, params: T2, - body: T3, - return_type: T4, + return_type: T3, + body: T4, ) -> Expression<'a> where T1: IntoIn<'a, Option>>>, T2: IntoIn<'a, Box<'a, FormalParameters<'a>>>, - T3: IntoIn<'a, Option>>>, - T4: IntoIn<'a, Option>>>, + T3: IntoIn<'a, Option>>>, + T4: IntoIn<'a, Option>>>, { Expression::FunctionExpression(self.alloc(self.function( r#type, @@ -573,8 +573,8 @@ impl<'a> AstBuilder<'a> { type_parameters, this_param, params, - body, return_type, + body, ))) } @@ -2689,14 +2689,14 @@ impl<'a> AstBuilder<'a> { type_parameters: T1, this_param: Option>, params: T2, - body: T3, - return_type: T4, + return_type: T3, + body: T4, ) -> Declaration<'a> where T1: IntoIn<'a, Option>>>, T2: IntoIn<'a, Box<'a, FormalParameters<'a>>>, - T3: IntoIn<'a, Option>>>, - T4: IntoIn<'a, Option>>>, + T3: IntoIn<'a, Option>>>, + T4: IntoIn<'a, Option>>>, { Declaration::FunctionDeclaration(self.alloc(self.function( r#type, @@ -2708,8 +2708,8 @@ impl<'a> AstBuilder<'a> { type_parameters, this_param, params, - body, return_type, + body, ))) } @@ -3720,14 +3720,14 @@ impl<'a> AstBuilder<'a> { type_parameters: T1, this_param: Option>, params: T2, - body: T3, - return_type: T4, + return_type: T3, + body: T4, ) -> Function<'a> where T1: IntoIn<'a, Option>>>, T2: IntoIn<'a, Box<'a, FormalParameters<'a>>>, - T3: IntoIn<'a, Option>>>, - T4: IntoIn<'a, Option>>>, + T3: IntoIn<'a, Option>>>, + T4: IntoIn<'a, Option>>>, { Function { r#type, @@ -3739,8 +3739,8 @@ impl<'a> AstBuilder<'a> { type_parameters: type_parameters.into_in(self.allocator), this_param, params: params.into_in(self.allocator), - body: body.into_in(self.allocator), return_type: return_type.into_in(self.allocator), + body: body.into_in(self.allocator), scope_id: Default::default(), } } @@ -3757,14 +3757,14 @@ impl<'a> AstBuilder<'a> { type_parameters: T1, this_param: Option>, params: T2, - body: T3, - return_type: T4, + return_type: T3, + body: T4, ) -> Box<'a, Function<'a>> where T1: IntoIn<'a, Option>>>, T2: IntoIn<'a, Box<'a, FormalParameters<'a>>>, - T3: IntoIn<'a, Option>>>, - T4: IntoIn<'a, Option>>>, + T3: IntoIn<'a, Option>>>, + T4: IntoIn<'a, Option>>>, { self.function( r#type, @@ -3776,8 +3776,8 @@ impl<'a> AstBuilder<'a> { type_parameters, this_param, params, - body, return_type, + body, ) .into_in(self.allocator) } @@ -4901,14 +4901,14 @@ impl<'a> AstBuilder<'a> { type_parameters: T1, this_param: Option>, params: T2, - body: T3, - return_type: T4, + return_type: T3, + body: T4, ) -> ExportDefaultDeclarationKind<'a> where T1: IntoIn<'a, Option>>>, T2: IntoIn<'a, Box<'a, FormalParameters<'a>>>, - T3: IntoIn<'a, Option>>>, - T4: IntoIn<'a, Option>>>, + T3: IntoIn<'a, Option>>>, + T4: IntoIn<'a, Option>>>, { ExportDefaultDeclarationKind::FunctionDeclaration(self.alloc(self.function( r#type, @@ -4920,8 +4920,8 @@ impl<'a> AstBuilder<'a> { type_parameters, this_param, params, - body, return_type, + body, ))) } diff --git a/crates/oxc_ast/src/generated/visit.rs b/crates/oxc_ast/src/generated/visit.rs index 3b7a57c1bd63d..83851a4a9b056 100644 --- a/crates/oxc_ast/src/generated/visit.rs +++ b/crates/oxc_ast/src/generated/visit.rs @@ -3038,7 +3038,7 @@ pub mod walk { visitor.enter_scope( { let mut flags = flags.unwrap_or(ScopeFlags::empty()) | ScopeFlags::Function; - if it.body.as_ref().is_some_and(|body| body.has_use_strict_directive()) { + if it.is_strict() { flags |= ScopeFlags::StrictMode; } flags @@ -3055,12 +3055,12 @@ pub mod walk { visitor.visit_ts_this_parameter(this_param); } visitor.visit_formal_parameters(&it.params); - if let Some(body) = &it.body { - visitor.visit_function_body(body); - } if let Some(return_type) = &it.return_type { visitor.visit_ts_type_annotation(return_type); } + if let Some(body) = &it.body { + visitor.visit_function_body(body); + } visitor.leave_scope(); visitor.leave_node(kind); } diff --git a/crates/oxc_ast/src/generated/visit_mut.rs b/crates/oxc_ast/src/generated/visit_mut.rs index 72d7f11f4545d..edf86e2771ca7 100644 --- a/crates/oxc_ast/src/generated/visit_mut.rs +++ b/crates/oxc_ast/src/generated/visit_mut.rs @@ -3171,7 +3171,7 @@ pub mod walk_mut { visitor.enter_scope( { let mut flags = flags.unwrap_or(ScopeFlags::empty()) | ScopeFlags::Function; - if it.body.as_ref().is_some_and(|body| body.has_use_strict_directive()) { + if it.is_strict() { flags |= ScopeFlags::StrictMode; } flags @@ -3188,12 +3188,12 @@ pub mod walk_mut { visitor.visit_ts_this_parameter(this_param); } visitor.visit_formal_parameters(&mut it.params); - if let Some(body) = &mut it.body { - visitor.visit_function_body(body); - } if let Some(return_type) = &mut it.return_type { visitor.visit_ts_type_annotation(return_type); } + if let Some(body) = &mut it.body { + visitor.visit_function_body(body); + } visitor.leave_scope(); visitor.leave_node(kind); } diff --git a/crates/oxc_isolated_declarations/src/class.rs b/crates/oxc_isolated_declarations/src/class.rs index 20ef7f00915d8..d7f6862c6c4d8 100644 --- a/crates/oxc_isolated_declarations/src/class.rs +++ b/crates/oxc_isolated_declarations/src/class.rs @@ -123,8 +123,8 @@ impl<'a> IsolatedDeclarations<'a> { self.ast.copy(&function.type_parameters), self.ast.copy(&function.this_param), params, - Option::::None, return_type, + Option::::None, ); self.ast.class_element_method_definition( diff --git a/crates/oxc_isolated_declarations/src/function.rs b/crates/oxc_isolated_declarations/src/function.rs index b5d59835a703b..4f8956e1edb58 100644 --- a/crates/oxc_isolated_declarations/src/function.rs +++ b/crates/oxc_isolated_declarations/src/function.rs @@ -37,8 +37,8 @@ impl<'a> IsolatedDeclarations<'a> { self.ast.copy(&func.type_parameters), self.ast.copy(&func.this_param), params, - Option::::None, return_type, + Option::::None, )) } } diff --git a/crates/oxc_linter/src/snapshots/ban_types.snap b/crates/oxc_linter/src/snapshots/ban_types.snap index a8e4839260bac..241168cb006a6 100644 --- a/crates/oxc_linter/src/snapshots/ban_types.snap +++ b/crates/oxc_linter/src/snapshots/ban_types.snap @@ -209,27 +209,27 @@ source: crates/oxc_linter/src/tester.rs help: The `Function` type accepts any function-like value ⚠ typescript-eslint(ban-types): Do not use "String" as a type. Use "string" instead - ╭─[ban_types.tsx:6:24] + ╭─[ban_types.tsx:5:24] + 4 │ 5 │ arg(): Array { - 6 │ const foo: String = 1 as String; · ────── - 7 │ } + 6 │ const foo: String = 1 as String; ╰──── ⚠ typescript-eslint(ban-types): Do not use "String" as a type. Use "string" instead - ╭─[ban_types.tsx:6:38] + ╭─[ban_types.tsx:6:24] 5 │ arg(): Array { 6 │ const foo: String = 1 as String; - · ────── + · ────── 7 │ } ╰──── ⚠ typescript-eslint(ban-types): Do not use "String" as a type. Use "string" instead - ╭─[ban_types.tsx:5:24] - 4 │ + ╭─[ban_types.tsx:6:38] 5 │ arg(): Array { - · ────── 6 │ const foo: String = 1 as String; + · ────── + 7 │ } ╰──── ⚠ typescript-eslint(ban-types): Don't use `Function` as a type diff --git a/crates/oxc_parser/src/js/function.rs b/crates/oxc_parser/src/js/function.rs index d642232c72826..93505b653c9c2 100644 --- a/crates/oxc_parser/src/js/function.rs +++ b/crates/oxc_parser/src/js/function.rs @@ -181,8 +181,8 @@ impl<'a> ParserImpl<'a> { type_parameters, this_param, params, - body, return_type, + body, )) } diff --git a/crates/oxc_semantic/src/binder.rs b/crates/oxc_semantic/src/binder.rs index a5b67627ee1c3..fcd661500f680 100644 --- a/crates/oxc_semantic/src/binder.rs +++ b/crates/oxc_semantic/src/binder.rs @@ -106,8 +106,9 @@ fn function_as_var(flags: ScopeFlags, source_type: SourceType) -> bool { impl<'a> Binder for Function<'a> { fn bind(&self, builder: &mut SemanticBuilder) { let current_scope_id = builder.current_scope_id; + let scope_flags = builder.current_scope_flags(); if let Some(ident) = &self.id { - if !builder.current_scope_flags().is_strict_mode() + if !scope_flags.is_strict_mode() && matches!( builder.nodes.parent_kind(builder.current_node_id), Some(AstKind::IfStatement(_)) @@ -118,12 +119,10 @@ impl<'a> Binder for Function<'a> { } else if self.r#type == FunctionType::FunctionDeclaration { // The visitor is already inside the function scope, // retrieve the parent scope for the function id to bind to. - let parent_scope_id = builder.scope.get_parent_id(current_scope_id).unwrap(); - let parent_flags = builder.scope.get_flags(parent_scope_id); let (includes, excludes) = - if (parent_flags.is_strict_mode() || self.r#async || self.generator) - && !function_as_var(parent_flags, builder.source_type) + if (scope_flags.is_strict_mode() || self.r#async || self.generator) + && !function_as_var(scope_flags, builder.source_type) { ( SymbolFlags::Function | SymbolFlags::BlockScopedVariable, @@ -136,13 +135,7 @@ impl<'a> Binder for Function<'a> { ) }; - let symbol_id = builder.declare_symbol_on_scope( - ident.span, - &ident.name, - parent_scope_id, - includes, - excludes, - ); + let symbol_id = builder.declare_symbol(ident.span, &ident.name, includes, excludes); ident.symbol_id.set(Some(symbol_id)); } else if self.r#type == FunctionType::FunctionExpression { // https://tc39.es/ecma262/#sec-runtime-semantics-instantiateordinaryfunctionexpression @@ -158,7 +151,6 @@ impl<'a> Binder for Function<'a> { } // bind scope flags: Constructor | GetAccessor | SetAccessor - debug_assert!(builder.current_scope_flags().contains(ScopeFlags::Function)); if let Some(kind) = builder.nodes.parent_kind(builder.current_node_id) { match kind { AstKind::MethodDefinition(def) => { diff --git a/crates/oxc_semantic/src/builder.rs b/crates/oxc_semantic/src/builder.rs index f448ccd15e84b..ef2d5d9afd102 100644 --- a/crates/oxc_semantic/src/builder.rs +++ b/crates/oxc_semantic/src/builder.rs @@ -414,13 +414,21 @@ impl<'a> SemanticBuilder<'a> { } } - fn bind_class_expression(&mut self) { - if let AstKind::Class(class) = self.nodes.kind(self.current_node_id) { - if class.is_expression() { - // We must to bind class expression when enter BindingIdentifier, - // because we should add binding to current scope - class.bind(self); + fn bind_function_or_class_expression(&mut self) { + match self.nodes.kind(self.current_node_id) { + AstKind::Class(class) => { + if class.is_expression() { + // We need to bind class expression in the class scope, + class.bind(self); + } + } + AstKind::Function(func) => { + if func.is_expression() { + // We need to bind function expression in the function scope, + func.bind(self); + } } + _ => {} } } } @@ -461,8 +469,10 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> { } if !flags.is_top() { - self.bind_class_expression(); + self.bind_function_or_class_expression(); } + + self.add_current_node_id_to_current_scope(); } fn leave_scope(&mut self) { @@ -1408,18 +1418,6 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> { } fn visit_function(&mut self, func: &Function<'a>, flags: Option) { - let kind = AstKind::Function(self.alloc(func)); - self.enter_scope( - { - let mut flags = flags.unwrap_or(ScopeFlags::empty()) | ScopeFlags::Function; - if func.is_strict() { - flags |= ScopeFlags::StrictMode; - } - flags - }, - &func.scope_id, - ); - /* cfg */ let (before_function_graph_ix, error_harness, function_graph_ix) = control_flow!(|self, cfg| { @@ -1434,7 +1432,22 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> { // We add a new basic block to the cfg before entering the node // so that the correct cfg_ix is associated with the ast node. + let kind = AstKind::Function(self.alloc(func)); self.enter_node(kind); + self.enter_scope( + { + let mut flags = flags.unwrap_or(ScopeFlags::empty()) | ScopeFlags::Function; + if func.is_strict() { + flags |= ScopeFlags::StrictMode; + } + flags + }, + &func.scope_id, + ); + + if let Some(id) = &func.id { + self.visit_binding_identifier(id); + } /* cfg */ control_flow!(|self, cfg| cfg.add_edge( @@ -1444,10 +1457,16 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> { )); /* cfg */ - if let Some(ident) = &func.id { - self.visit_binding_identifier(ident); + if let Some(type_parameters) = &func.type_parameters { + self.visit_ts_type_parameter_declaration(type_parameters); + } + if let Some(this_param) = &func.this_param { + self.visit_ts_this_parameter(this_param); } self.visit_formal_parameters(&func.params); + if let Some(return_type) = &func.return_type { + self.visit_ts_type_annotation(return_type); + } if let Some(body) = &func.body { self.visit_function_body(body); } @@ -1462,20 +1481,11 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> { }); /* cfg */ - if let Some(parameters) = &func.type_parameters { - self.visit_ts_type_parameter_declaration(parameters); - } - if let Some(annotation) = &func.return_type { - self.visit_ts_type_annotation(annotation); - } - self.leave_node(kind); self.leave_scope(); + self.leave_node(kind); } fn visit_arrow_function_expression(&mut self, expr: &ArrowFunctionExpression<'a>) { - let kind = AstKind::ArrowFunctionExpression(self.alloc(expr)); - self.enter_scope(ScopeFlags::Function | ScopeFlags::Arrow, &expr.scope_id); - /* cfg */ let (current_node_ix, error_harness, function_graph_ix) = control_flow!(|self, cfg| { let current_node_ix = cfg.current_node_ix; @@ -1489,7 +1499,9 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> { // We add a new basic block to the cfg before entering the node // so that the correct cfg_ix is associated with the ast node. + let kind = AstKind::ArrowFunctionExpression(self.alloc(expr)); self.enter_node(kind); + self.enter_scope(ScopeFlags::Function | ScopeFlags::Arrow, &expr.scope_id); self.visit_formal_parameters(&expr.params); @@ -1582,14 +1594,14 @@ impl<'a> SemanticBuilder<'a> { AstKind::StaticBlock(_) => self.label_builder.enter_function_or_static_block(), AstKind::Function(func) => { self.function_stack.push(self.current_node_id); - func.bind(self); + if func.is_declaration() { + func.bind(self); + } self.label_builder.enter_function_or_static_block(); - self.add_current_node_id_to_current_scope(); self.make_all_namespaces_valuelike(); } AstKind::ArrowFunctionExpression(_) => { self.function_stack.push(self.current_node_id); - self.add_current_node_id_to_current_scope(); self.make_all_namespaces_valuelike(); } AstKind::Class(class) => { diff --git a/crates/oxc_traverse/src/ancestor.rs b/crates/oxc_traverse/src/ancestor.rs index e79b91ef385d1..8ba65a30260c6 100644 --- a/crates/oxc_traverse/src/ancestor.rs +++ b/crates/oxc_traverse/src/ancestor.rs @@ -143,8 +143,8 @@ pub(crate) enum AncestorType { FunctionTypeParameters = 111, FunctionThisParam = 112, FunctionParams = 113, - FunctionBody = 114, - FunctionReturnType = 115, + FunctionReturnType = 114, + FunctionBody = 115, FormalParametersItems = 116, FormalParametersRest = 117, FormalParameterDecorators = 118, @@ -531,8 +531,8 @@ pub enum Ancestor<'a> { AncestorType::FunctionTypeParameters as u16, FunctionThisParam(FunctionWithoutThisParam<'a>) = AncestorType::FunctionThisParam as u16, FunctionParams(FunctionWithoutParams<'a>) = AncestorType::FunctionParams as u16, - FunctionBody(FunctionWithoutBody<'a>) = AncestorType::FunctionBody as u16, FunctionReturnType(FunctionWithoutReturnType<'a>) = AncestorType::FunctionReturnType as u16, + FunctionBody(FunctionWithoutBody<'a>) = AncestorType::FunctionBody as u16, FormalParametersItems(FormalParametersWithoutItems<'a>) = AncestorType::FormalParametersItems as u16, FormalParametersRest(FormalParametersWithoutRest<'a>) = @@ -1242,8 +1242,8 @@ impl<'a> Ancestor<'a> { | Self::FunctionTypeParameters(_) | Self::FunctionThisParam(_) | Self::FunctionParams(_) - | Self::FunctionBody(_) | Self::FunctionReturnType(_) + | Self::FunctionBody(_) ) } @@ -5194,8 +5194,8 @@ pub(crate) const OFFSET_FUNCTION_DECLARE: usize = offset_of!(Function, declare); pub(crate) const OFFSET_FUNCTION_TYPE_PARAMETERS: usize = offset_of!(Function, type_parameters); pub(crate) const OFFSET_FUNCTION_THIS_PARAM: usize = offset_of!(Function, this_param); pub(crate) const OFFSET_FUNCTION_PARAMS: usize = offset_of!(Function, params); -pub(crate) const OFFSET_FUNCTION_BODY: usize = offset_of!(Function, body); pub(crate) const OFFSET_FUNCTION_RETURN_TYPE: usize = offset_of!(Function, return_type); +pub(crate) const OFFSET_FUNCTION_BODY: usize = offset_of!(Function, body); pub(crate) const OFFSET_FUNCTION_SCOPE_ID: usize = offset_of!(Function, scope_id); #[repr(transparent)] @@ -5253,18 +5253,18 @@ impl<'a> FunctionWithoutId<'a> { } #[inline] - pub fn body(&self) -> &Option>> { + pub fn return_type(&self) -> &Option>> { unsafe { - &*((self.0 as *const u8).add(OFFSET_FUNCTION_BODY) - as *const Option>>) + &*((self.0 as *const u8).add(OFFSET_FUNCTION_RETURN_TYPE) + as *const Option>>) } } #[inline] - pub fn return_type(&self) -> &Option>> { + pub fn body(&self) -> &Option>> { unsafe { - &*((self.0 as *const u8).add(OFFSET_FUNCTION_RETURN_TYPE) - as *const Option>>) + &*((self.0 as *const u8).add(OFFSET_FUNCTION_BODY) + as *const Option>>) } } @@ -5331,18 +5331,18 @@ impl<'a> FunctionWithoutTypeParameters<'a> { } #[inline] - pub fn body(&self) -> &Option>> { + pub fn return_type(&self) -> &Option>> { unsafe { - &*((self.0 as *const u8).add(OFFSET_FUNCTION_BODY) - as *const Option>>) + &*((self.0 as *const u8).add(OFFSET_FUNCTION_RETURN_TYPE) + as *const Option>>) } } #[inline] - pub fn return_type(&self) -> &Option>> { + pub fn body(&self) -> &Option>> { unsafe { - &*((self.0 as *const u8).add(OFFSET_FUNCTION_RETURN_TYPE) - as *const Option>>) + &*((self.0 as *const u8).add(OFFSET_FUNCTION_BODY) + as *const Option>>) } } @@ -5409,18 +5409,18 @@ impl<'a> FunctionWithoutThisParam<'a> { } #[inline] - pub fn body(&self) -> &Option>> { + pub fn return_type(&self) -> &Option>> { unsafe { - &*((self.0 as *const u8).add(OFFSET_FUNCTION_BODY) - as *const Option>>) + &*((self.0 as *const u8).add(OFFSET_FUNCTION_RETURN_TYPE) + as *const Option>>) } } #[inline] - pub fn return_type(&self) -> &Option>> { + pub fn body(&self) -> &Option>> { unsafe { - &*((self.0 as *const u8).add(OFFSET_FUNCTION_RETURN_TYPE) - as *const Option>>) + &*((self.0 as *const u8).add(OFFSET_FUNCTION_BODY) + as *const Option>>) } } @@ -5487,18 +5487,18 @@ impl<'a> FunctionWithoutParams<'a> { } #[inline] - pub fn body(&self) -> &Option>> { + pub fn return_type(&self) -> &Option>> { unsafe { - &*((self.0 as *const u8).add(OFFSET_FUNCTION_BODY) - as *const Option>>) + &*((self.0 as *const u8).add(OFFSET_FUNCTION_RETURN_TYPE) + as *const Option>>) } } #[inline] - pub fn return_type(&self) -> &Option>> { + pub fn body(&self) -> &Option>> { unsafe { - &*((self.0 as *const u8).add(OFFSET_FUNCTION_RETURN_TYPE) - as *const Option>>) + &*((self.0 as *const u8).add(OFFSET_FUNCTION_BODY) + as *const Option>>) } } @@ -5512,9 +5512,9 @@ impl<'a> FunctionWithoutParams<'a> { #[repr(transparent)] #[derive(Debug)] -pub struct FunctionWithoutBody<'a>(pub(crate) *const Function<'a>); +pub struct FunctionWithoutReturnType<'a>(pub(crate) *const Function<'a>); -impl<'a> FunctionWithoutBody<'a> { +impl<'a> FunctionWithoutReturnType<'a> { #[inline] pub fn r#type(&self) -> &FunctionType { unsafe { &*((self.0 as *const u8).add(OFFSET_FUNCTION_TYPE) as *const FunctionType) } @@ -5573,10 +5573,10 @@ impl<'a> FunctionWithoutBody<'a> { } #[inline] - pub fn return_type(&self) -> &Option>> { + pub fn body(&self) -> &Option>> { unsafe { - &*((self.0 as *const u8).add(OFFSET_FUNCTION_RETURN_TYPE) - as *const Option>>) + &*((self.0 as *const u8).add(OFFSET_FUNCTION_BODY) + as *const Option>>) } } @@ -5590,9 +5590,9 @@ impl<'a> FunctionWithoutBody<'a> { #[repr(transparent)] #[derive(Debug)] -pub struct FunctionWithoutReturnType<'a>(pub(crate) *const Function<'a>); +pub struct FunctionWithoutBody<'a>(pub(crate) *const Function<'a>); -impl<'a> FunctionWithoutReturnType<'a> { +impl<'a> FunctionWithoutBody<'a> { #[inline] pub fn r#type(&self) -> &FunctionType { unsafe { &*((self.0 as *const u8).add(OFFSET_FUNCTION_TYPE) as *const FunctionType) } @@ -5651,10 +5651,10 @@ impl<'a> FunctionWithoutReturnType<'a> { } #[inline] - pub fn body(&self) -> &Option>> { + pub fn return_type(&self) -> &Option>> { unsafe { - &*((self.0 as *const u8).add(OFFSET_FUNCTION_BODY) - as *const Option>>) + &*((self.0 as *const u8).add(OFFSET_FUNCTION_RETURN_TYPE) + as *const Option>>) } } diff --git a/crates/oxc_traverse/src/walk.rs b/crates/oxc_traverse/src/walk.rs index 8f6f9174a0fc8..89280fa248900 100644 --- a/crates/oxc_traverse/src/walk.rs +++ b/crates/oxc_traverse/src/walk.rs @@ -2287,18 +2287,18 @@ pub(crate) unsafe fn walk_function<'a, Tr: Traverse<'a>>( as *mut Box)) as *mut _, ctx, ); - if let Some(field) = &mut *((node as *mut u8).add(ancestor::OFFSET_FUNCTION_BODY) - as *mut Option>) - { - ctx.retag_stack(AncestorType::FunctionBody); - walk_function_body(traverser, (&mut **field) as *mut _, ctx); - } if let Some(field) = &mut *((node as *mut u8).add(ancestor::OFFSET_FUNCTION_RETURN_TYPE) as *mut Option>) { ctx.retag_stack(AncestorType::FunctionReturnType); walk_ts_type_annotation(traverser, (&mut **field) as *mut _, ctx); } + if let Some(field) = &mut *((node as *mut u8).add(ancestor::OFFSET_FUNCTION_BODY) + as *mut Option>) + { + ctx.retag_stack(AncestorType::FunctionBody); + walk_function_body(traverser, (&mut **field) as *mut _, ctx); + } ctx.pop_stack(); traverser.exit_function(&mut *node, ctx); if let Some(previous_scope_id) = previous_scope_id { diff --git a/tasks/coverage/parser_typescript.snap b/tasks/coverage/parser_typescript.snap index eeaa6aeee9807..e2da562dc2f62 100644 --- a/tasks/coverage/parser_typescript.snap +++ b/tasks/coverage/parser_typescript.snap @@ -20872,10 +20872,10 @@ Expect to Parse: "conformance/types/typeRelationships/typeAndMemberIdentity/obje 17 │ // Type parameters and top-level local types are in same declaration space 18 │ function f() { · ┬ - · ╰── It can not be redeclared here + · ╰── `T` has already been declared here 19 │ interface T { } · ┬ - · ╰── `T` has already been declared here + · ╰── It can not be redeclared here 20 │ return undefined; ╰────