mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
fix: 修复编译 class 方法与构造器时丢失 super 上下文的问题
This commit is contained in:
@@ -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<CompiledModule, String> {
|
||||
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<CompiledModule, String> {
|
||||
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;
|
||||
|
||||
@@ -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());
|
||||
|
||||
Reference in New Issue
Block a user