From dcc7db25754a2d0a9ab8d73b6005e905fc51dfec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=88=B1=E7=89=B9=E6=AF=8F=E7=BE=8A=E9=98=9F?= Date: Sat, 13 Jun 2026 19:00:54 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E7=BC=96=E8=AF=91=20c?= =?UTF-8?q?lass=20=E6=96=B9=E6=B3=95=E4=B8=8E=E6=9E=84=E9=80=A0=E5=99=A8?= =?UTF-8?q?=E6=97=B6=E4=B8=A2=E5=A4=B1=20super=20=E4=B8=8A=E4=B8=8B?= =?UTF-8?q?=E6=96=87=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/oxide_compiler/src/compiler.rs | 28 ++++++++++++--- crates/oxide_compiler/src/emitter.rs | 50 ++++++++++++++++++++++----- 2 files changed, 65 insertions(+), 13 deletions(-) diff --git a/crates/oxide_compiler/src/compiler.rs b/crates/oxide_compiler/src/compiler.rs index 7aaebc2..8438f66 100644 --- a/crates/oxide_compiler/src/compiler.rs +++ b/crates/oxide_compiler/src/compiler.rs @@ -78,6 +78,13 @@ pub(crate) struct CompileCtx { pub(crate) reg_overflow: bool, } +#[derive(Clone, Copy)] +pub(crate) enum FunctionBodyContext { + Ordinary, + Arrow, + ClassElement, +} + impl CompileCtx { pub(crate) fn new() -> Self { Self { @@ -315,12 +322,24 @@ impl Compiler { &self, param_names: &[String], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx, is_expression_body: bool, is_arrow: bool, ) -> Result { - self.compile_function_body_with_bindings(param_names, body_stmts, parent_ctx, is_expression_body, &[], is_arrow) + let body_context = if is_arrow { + FunctionBodyContext::Arrow + } else { + FunctionBodyContext::Ordinary + }; + self.compile_function_body_with_bindings( + param_names, + body_stmts, + parent_ctx, + is_expression_body, + &[], + body_context, + ) } pub(crate) fn compile_function_body_with_bindings<'a>( &self, param_names: &[String], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx, is_expression_body: bool, - extra_bindings: &[(&str, u8)], is_arrow: bool, + extra_bindings: &[(&str, u8)], body_context: FunctionBodyContext, ) -> Result { let mut ctx = CompileCtx::new(); @@ -330,8 +349,9 @@ impl Compiler { // Propagate enclosing_this_reg so nested arrow functions capture the correct `this`. ctx.enclosing_this_reg = parent_ctx.enclosing_this_reg; - // Only arrow functions have lexical super; regular functions create a new super scope. - if is_arrow { + // Arrow functions inherit lexical super. Class method bodies also need the + // class-provided super context for their top-level body compilation. + if matches!(body_context, FunctionBodyContext::Arrow | FunctionBodyContext::ClassElement) { ctx.in_derived_constructor = parent_ctx.in_derived_constructor; ctx.in_instance_method = parent_ctx.in_instance_method; ctx.in_static_method = parent_ctx.in_static_method; diff --git a/crates/oxide_compiler/src/emitter.rs b/crates/oxide_compiler/src/emitter.rs index 0759300..3f6615b 100644 --- a/crates/oxide_compiler/src/emitter.rs +++ b/crates/oxide_compiler/src/emitter.rs @@ -6,7 +6,7 @@ use oxide_parser::{ VariableDeclarationKind, }; -use crate::compiler::{is_int_literal, is_side_effect_free, BinaryOperator, CompileCtx, Compiler}; +use crate::compiler::{is_int_literal, is_side_effect_free, BinaryOperator, CompileCtx, Compiler, FunctionBodyContext}; use crate::module::Constant; impl Compiler { @@ -77,9 +77,23 @@ impl Compiler { let mut ctor_module = if let Some(method) = constructor_method { let (param_names, body_stmts) = self.extract_function_parts(method.value.as_ref())?; - self.compile_function_body_with_bindings(¶m_names, body_stmts, ctx, false, &self_binding, false)? + self.compile_function_body_with_bindings( + ¶m_names, + body_stmts, + ctx, + false, + &self_binding, + FunctionBodyContext::ClassElement, + )? } else { - let mut module = self.compile_function_body_with_bindings(&[], &[], ctx, false, &self_binding, false)?; + let mut module = self.compile_function_body_with_bindings( + &[], + &[], + ctx, + false, + &self_binding, + FunctionBodyContext::ClassElement, + )?; if is_derived { module.bytecode.clear(); module.constants.clear(); @@ -118,8 +132,14 @@ impl Compiler { let (param_names, body_stmts) = self.extract_function_parts(method.value.as_ref())?; let saved_method = ctx.in_instance_method; ctx.in_instance_method = true; - let mut method_module = - self.compile_function_body_with_bindings(¶m_names, body_stmts, ctx, false, &self_binding, false)?; + let mut method_module = self.compile_function_body_with_bindings( + ¶m_names, + body_stmts, + ctx, + false, + &self_binding, + FunctionBodyContext::ClassElement, + )?; ctx.in_instance_method = saved_method; method_module.function_name = Some(method_name.clone()); method_module.needs_home_object = true; @@ -153,8 +173,14 @@ impl Compiler { let (param_names, body_stmts) = self.extract_function_parts(method.value.as_ref())?; let saved_static = ctx.in_static_method; ctx.in_static_method = true; - let mut method_module = - self.compile_function_body_with_bindings(¶m_names, body_stmts, ctx, false, &self_binding, false)?; + let mut method_module = self.compile_function_body_with_bindings( + ¶m_names, + body_stmts, + ctx, + false, + &self_binding, + FunctionBodyContext::ClassElement, + )?; ctx.in_static_method = saved_static; method_module.function_name = Some(method_name.clone()); method_module.needs_home_object = true; @@ -213,8 +239,14 @@ impl Compiler { let saved_static = ctx.in_static_method; ctx.in_instance_method = !method.r#static; ctx.in_static_method = method.r#static; - let mut method_module = - self.compile_function_body_with_bindings(¶m_names, body_stmts, ctx, false, self_binding, false)?; + let mut method_module = self.compile_function_body_with_bindings( + ¶m_names, + body_stmts, + ctx, + false, + self_binding, + FunctionBodyContext::ClassElement, + )?; ctx.in_instance_method = saved_instance; ctx.in_static_method = saved_static; method_module.function_name = Some(method_name.to_string());