diff --git a/Cargo.lock b/Cargo.lock index ed9e7afa..ac8994ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1160,7 +1160,7 @@ dependencies = [ [[package]] name = "oxide_builtins" -version = "0.17.0" +version = "0.17.1" dependencies = [ "chrono", "fast-float", @@ -1185,7 +1185,7 @@ dependencies = [ [[package]] name = "oxide_bytecode" -version = "0.17.0" +version = "0.17.1" dependencies = [ "num-bigint", "oxide_log", @@ -1193,7 +1193,7 @@ dependencies = [ [[package]] name = "oxide_cfg" -version = "0.17.0" +version = "0.17.1" dependencies = [ "oxide_bytecode", "oxide_emit", @@ -1204,7 +1204,7 @@ dependencies = [ [[package]] name = "oxide_cli" -version = "0.17.0" +version = "0.17.1" dependencies = [ "ansi_term", "bumpalo", @@ -1228,7 +1228,7 @@ dependencies = [ [[package]] name = "oxide_code_cache" -version = "0.17.0" +version = "0.17.1" dependencies = [ "lru", "oxide_bytecode", @@ -1237,7 +1237,7 @@ dependencies = [ [[package]] name = "oxide_compiler" -version = "0.17.0" +version = "0.17.1" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1258,7 +1258,7 @@ dependencies = [ [[package]] name = "oxide_dce" -version = "0.17.0" +version = "0.17.1" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1272,7 +1272,7 @@ dependencies = [ [[package]] name = "oxide_emit" -version = "0.17.0" +version = "0.17.1" dependencies = [ "num-bigint", "oxc_allocator", @@ -1288,7 +1288,7 @@ dependencies = [ [[package]] name = "oxide_engine" -version = "0.17.0" +version = "0.17.1" dependencies = [ "oxide_bytecode", "oxide_compiler", @@ -1300,7 +1300,7 @@ dependencies = [ [[package]] name = "oxide_fold" -version = "0.17.0" +version = "0.17.1" dependencies = [ "num-bigint", "oxide_bytecode", @@ -1312,7 +1312,7 @@ dependencies = [ [[package]] name = "oxide_ir" -version = "0.17.0" +version = "0.17.1" dependencies = [ "oxide_bytecode", "oxide_log", @@ -1321,7 +1321,7 @@ dependencies = [ [[package]] name = "oxide_kernel" -version = "0.17.0" +version = "0.17.1" dependencies = [ "bumpalo", "dashmap", @@ -1335,7 +1335,7 @@ dependencies = [ [[package]] name = "oxide_liveness" -version = "0.17.0" +version = "0.17.1" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1347,7 +1347,7 @@ dependencies = [ [[package]] name = "oxide_log" -version = "0.17.0" +version = "0.17.1" dependencies = [ "tracing", "tracing-appender", @@ -1356,11 +1356,11 @@ dependencies = [ [[package]] name = "oxide_net" -version = "0.17.0" +version = "0.17.1" [[package]] name = "oxide_parser" -version = "0.17.0" +version = "0.17.1" dependencies = [ "oxc_allocator", "oxc_ast", @@ -1375,7 +1375,7 @@ dependencies = [ [[package]] name = "oxide_regalloc" -version = "0.17.0" +version = "0.17.1" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1391,7 +1391,7 @@ dependencies = [ [[package]] name = "oxide_runtime_api" -version = "0.17.0" +version = "0.17.1" dependencies = [ "num-bigint", "num-traits", @@ -1404,7 +1404,7 @@ dependencies = [ [[package]] name = "oxide_test262" -version = "0.17.0" +version = "0.17.1" dependencies = [ "oxide_bytecode", "oxide_compiler", @@ -1424,7 +1424,7 @@ dependencies = [ [[package]] name = "oxide_types" -version = "0.17.0" +version = "0.17.1" dependencies = [ "bumpalo", "dashmap", @@ -1437,7 +1437,7 @@ dependencies = [ [[package]] name = "oxide_vm" -version = "0.17.0" +version = "0.17.1" dependencies = [ "bumpalo", "chrono", diff --git a/Cargo.toml b/Cargo.toml index 9dbc1496..1c8940ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ members = [ ] [workspace.package] -version = "0.17.0" +version = "0.17.1" edition = "2021" license = "MIT" rust-version = "1.80" diff --git a/crates/oxide_emit/src/class/emit.rs b/crates/oxide_emit/src/class/emit.rs index 77a1bc40..d7849c12 100644 --- a/crates/oxide_emit/src/class/emit.rs +++ b/crates/oxide_emit/src/class/emit.rs @@ -2,7 +2,9 @@ //! //! 函数:`emit_class`。 -use crate::{symbol_table::ScopeKind, CompileCtx, Emitter, FunctionBodyContext}; +use crate::{ + symbol_table::ScopeKind, ClassElementHooks, CompileCtx, Emitter, FunctionBodyContext, FunctionFlags, +}; use oxide_bytecode::module::Constant; use oxide_bytecode::opcode::OpCode; use oxide_ir::inst::Inst; @@ -270,36 +272,40 @@ impl Emitter { Ok(()) }; + // 构造器(显式与隐式派生)共用同一组标志与钩子:恒 strict、无表达式体、 + // 字段发射钩子按派生与否在 super() 前后执行。 + let ctor_flags = FunctionFlags { + is_expression_body: false, + is_generator: false, + is_async: false, + own_strict: true, + name: None, + }; + let ctor_hooks = ClassElementHooks { + extra_bindings: &self_binding, + emit_fields: Some(emit_instance_fields), + fields_after_super: is_derived, + extra_capture_exprs: &field_value_exprs, + extra_upvalue_names: &extra_upvalue_names, + }; 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_field_hooks( + self.compile_function_body( ¶m_names, body_stmts, ctx, - false, - &self_binding, FunctionBodyContext::ClassElement, - Some(&emit_instance_fields), - is_derived, - &field_value_exprs, - &extra_upvalue_names, - true, - None, + ctor_flags, + ctor_hooks, )? } else { - let mut module = self.compile_function_body_with_field_hooks( + let mut module = self.compile_function_body( &[], &[], ctx, - false, - &self_binding, FunctionBodyContext::ClassElement, - Some(&emit_instance_fields), - is_derived, - &field_value_exprs, - &extra_upvalue_names, - true, - None, + ctor_flags, + ctor_hooks, )?; if is_derived { module.insts.clear(); diff --git a/crates/oxide_emit/src/class/method.rs b/crates/oxide_emit/src/class/method.rs index 7eab2fd0..1ab20446 100644 --- a/crates/oxide_emit/src/class/method.rs +++ b/crates/oxide_emit/src/class/method.rs @@ -1,7 +1,7 @@ //! 类方法 emit:`emit_class_methods` 逐方法构造,`emit_class_method_function` //! 负责单个方法函数体(含 `super` 与 home object)。 -use crate::{CompileCtx, Emitter, FunctionBodyContext}; +use crate::{ClassElementHooks, CompileCtx, Emitter, FunctionBodyContext, FunctionFlags}; use oxide_bytecode::module::Constant; use oxide_bytecode::opcode::OpCode; use oxide_ir::inst::Inst; @@ -125,21 +125,23 @@ impl Emitter { // 生成器/异步/异步生成器方法与普通方法统一走带标志入口:`*m` 置 is_generator, // `async *m` 同时置 is_generator 与 is_async,VM 据此按生成器协议创建对象并 // 处理 body 内 SUSPEND/YIELD/异常边界。 - let mut method_module = self.compile_function_body_with_field_hooks_gen( + // 方法无字段发射钩子:以空钩子为基底,注入类名自绑定与 brand upvalue。 + let mut hooks = ClassElementHooks::none(); + hooks.extra_bindings = self_binding; + hooks.extra_upvalue_names = &extra_uv; + let mut method_module = self.compile_function_body( ¶m_names, body_stmts, ctx, - false, - self_binding, FunctionBodyContext::ClassElement, - None:: Result<(), String>>, - false, - &[], - &extra_uv, - method_value.generator, - method_value.r#async, - true, - None, + FunctionFlags { + is_expression_body: false, + is_generator: method_value.generator, + is_async: method_value.r#async, + own_strict: true, + name: None, + }, + hooks, )?; ctx.in_instance_method = saved_instance; ctx.in_static_method = saved_static; diff --git a/crates/oxide_emit/src/compile_ctx.rs b/crates/oxide_emit/src/compile_ctx.rs index f40abea1..9d07b146 100644 --- a/crates/oxide_emit/src/compile_ctx.rs +++ b/crates/oxide_emit/src/compile_ctx.rs @@ -47,7 +47,7 @@ pub struct CompileCtx { /// 本函数是否为异步函数体(`async function` / async 箭头),`assemble_ir` 回写到 IR。 pub(crate) is_async: bool, /// 本函数是否为严格模式函数体:自身 directive ‖ 外层严格继承(编译入口设置 + - /// 嵌套继承,见 compile_function_body_with_field_hooks_gen),`assemble_ir` 回写到 IR。 + /// 嵌套继承,见 compile_function_body),`assemble_ir` 回写到 IR。 pub(crate) is_strict: bool, /// 是否为脚本顶层模块(emit_program 的根上下文)。顶层 var/function 声明需 /// 同步写全局对象属性(脚本环境记录的 var 可经 globalThis 反射);函数体为 false。 diff --git a/crates/oxide_emit/src/expr/function/mod.rs b/crates/oxide_emit/src/expr/function/mod.rs index acdff31d..de9c8ac1 100644 --- a/crates/oxide_emit/src/expr/function/mod.rs +++ b/crates/oxide_emit/src/expr/function/mod.rs @@ -3,7 +3,7 @@ //! `emit_class_expression`、`emit_new_expression`、`emit_function_domain`。 use crate::expr::call::pack_arg_regs; -use crate::{CompileCtx, Emitter, ParamSpec}; +use crate::{CompileCtx, Emitter, FunctionBodyContext, FunctionFlags, ParamSpec}; use oxide_ir::inst::Inst; use oxide_ir::operand::Operand; use oxide_parser::{Class, Expression, Statement}; @@ -39,27 +39,15 @@ impl Emitter { let body_stmts = &arrow.body.statements; let is_expr_body = arrow.expression; - let mut sub_module = if arrow.r#async { - self.compile_async_body( - ¶m_names, - body_stmts, - ctx, - is_expr_body, - true, - arrow.has_use_strict_directive(), - None, - )? - } else { - self.compile_function_body( - ¶m_names, - body_stmts, - ctx, - is_expr_body, - true, - arrow.has_use_strict_directive(), - None, - )? + let flags = FunctionFlags { + is_expression_body: is_expr_body, + is_generator: false, + is_async: arrow.r#async, + own_strict: arrow.has_use_strict_directive(), + name: None, }; + let mut sub_module = + self.compile_simple_function_body(¶m_names, body_stmts, ctx, FunctionBodyContext::Arrow, flags)?; sub_module.is_arrow = true; // 箭头函数词法继承 super 上下文:父带任一 super 标志时,本箭头须挂 // home object(运行期从外层函数继承,见 CREATE_CLOSURE 分发)。 @@ -106,15 +94,15 @@ impl Emitter { let own_strict = fe.has_use_strict_directive(); let fn_name = fe.id.as_ref().map(|id| id.name.as_str()); - let mut sub_module = if fe.generator && fe.r#async { - self.compile_async_generator_body(¶m_names, body_stmts, ctx, own_strict, fn_name)? - } else if fe.generator { - self.compile_generator_body(¶m_names, body_stmts, ctx, own_strict, fn_name)? - } else if fe.r#async { - self.compile_async_body(¶m_names, body_stmts, ctx, false, false, own_strict, fn_name)? - } else { - self.compile_function_body(¶m_names, body_stmts, ctx, false, false, own_strict, fn_name)? + let flags = FunctionFlags { + is_expression_body: false, + is_generator: fe.generator, + is_async: fe.r#async, + own_strict, + name: fn_name, }; + let mut sub_module = + self.compile_simple_function_body(¶m_names, body_stmts, ctx, FunctionBodyContext::Ordinary, flags)?; if let Some(id) = &fe.id { sub_module.function_name = Some(id.name.to_string()); } diff --git a/crates/oxide_emit/src/function_body.rs b/crates/oxide_emit/src/function_body.rs index b12dd7fb..d6fcf0e4 100644 --- a/crates/oxide_emit/src/function_body.rs +++ b/crates/oxide_emit/src/function_body.rs @@ -1,8 +1,10 @@ -//! 函数体编译域:`FunctionBodyContext` / `ParamSpec` 类型与函数体编译链 -//! (参数 prologue、参数默认值与闭包捕获分析、双 sub-pass 语句发射)。 +//! 函数体编译域:`FunctionBodyContext` / `ParamSpec` / `FunctionFlags` / +//! `ClassElementHooks` 类型与函数体编译链(参数 prologue、参数默认值与闭包 +//! 捕获分析、双 sub-pass 语句发射)。 //! -//! 两类型经 lib.rs 重导出供各语法域构造实参;编译链为 `Emitter` 方法, -//! 捕获分析经自由函数调用 capture 族,与所在文件无关。 +//! 上下文与参数规格两类型经 lib.rs 重导出供各语法域构造实参;标志与钩子结构体 +//! 供 crate 内各语法域整体传参;编译链为 `Emitter` 方法,捕获分析经自由函数 +//! 调用 capture 族,与所在文件无关。 use std::collections::{BTreeMap, HashSet}; @@ -58,6 +60,57 @@ impl ParamSpec<'_> { } } +/// 函数体编译标志:函数体种类与严格性,随函数体编译核心入口整体传入。 +#[derive(Clone, Copy)] +pub struct FunctionFlags<'a> { + /// 表达式体(箭头表达式体):体返回最后一个表达式的值,否则返回 undefined。 + pub is_expression_body: bool, + /// 生成器函数(`function*`):VM 按生成器协议创建对象并执行。 + pub is_generator: bool, + /// 异步函数(`async function`):VM 按异步函数协议执行。 + pub is_async: bool, + /// 本函数自身的 strict 指令(类元素恒 strict,不在此传递)。 + pub own_strict: bool, + /// 函数名(具名函数声明/表达式传名,箭头与匿名传 `None`),用于函数名不可写绑定登记。 + pub name: Option<&'a str>, +} + +/// 类元素钩子:类元素函数(构造器/方法/字段)的额外绑定、字段发射与捕获组, +/// 非类元素函数传 `ClassElementHooks::none()`。 +/// +/// `E` 为字段发射闭包类型(`FnMut(&Emitter, &mut CompileCtx) -> Result<(), String>`), +/// 非类元素函数用 `NoFieldsHook` 占位(`emit_fields` 恒为 `None`,永不被调用)。 +#[derive(Clone, Copy)] +pub struct ClassElementHooks<'a, E> { + /// 注入函数作用域的额外绑定(类名自绑定等)。 + pub extra_bindings: &'a [(&'a str, u32)], + /// 字段发射钩子(非类元素函数为 `None`)。 + pub emit_fields: Option, + /// 字段在 `super()` 之后发射(派生构造器)。 + pub fields_after_super: bool, + /// 额外捕获表达式(字段值表达式等)。 + pub extra_capture_exprs: &'a [&'a Expression<'a>], + /// 额外 upvalue 名(`@@field_keys` 等合成捕获)。 + pub extra_upvalue_names: &'a [(String, u8)], +} + +/// 无字段发射钩子的占位类型:仅用于 `ClassElementHooks::none()`,`emit_fields` +/// 恒为 `None`,永不被调用。 +type NoFieldsHook = Box Result<(), String>>; + +impl<'a> ClassElementHooks<'a, NoFieldsHook> { + /// 非类元素函数的空钩子。 + pub(crate) fn none() -> Self { + Self { + extra_bindings: &[], + emit_fields: None, + fields_after_super: false, + extra_capture_exprs: &[], + extra_upvalue_names: &[], + } + } +} + impl Emitter { /// 遍历解构 pattern 收集内嵌默认值表达式(AssignmentPattern.right)与 /// 计算键表达式(`{[k]: a}` 的键,运行时求值)——二者都会在参数绑定期被 @@ -136,188 +189,38 @@ impl Emitter { Ok((param_specs, body_stmts)) } - /// 编译函数体(函数声明/函数表达式/箭头函数共用),单 pass 完成发码。 + /// 编译函数体(函数声明/函数表达式/箭头函数/类元素共用核心入口),单 pass 完成发码。 /// - /// `is_expression_body` 为 true(箭头表达式体)时返回最后一个表达式的值, - /// 否则返回 undefined。`is_arrow` 控制 super 相关标志的继承:箭头函数词法 - /// 继承外层 super,普通函数重置 super 作用域。`name` 为函数名(具名函数 - /// 声明/表达式传名,箭头与匿名传 `None`),用于函数名不可写绑定登记。 - #[allow(clippy::too_many_arguments)] - pub(crate) fn compile_function_body<'a>( - &self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx, - is_expression_body: bool, is_arrow: bool, own_strict: bool, name: Option<&str>, - ) -> Result { - self.compile_function_body_with_flags( - param_specs, - body_stmts, - parent_ctx, - is_expression_body, - is_arrow, - false, - false, - own_strict, - name, - ) - } - - /// 编译函数体并显式指定生成器标志(`function*` 走此入口)。 - pub(crate) fn compile_generator_body<'a>( - &self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx, own_strict: bool, - name: Option<&str>, - ) -> Result { - self.compile_function_body_with_flags( - param_specs, - body_stmts, - parent_ctx, - false, - false, - true, - false, - own_strict, - name, - ) - } - - /// 编译异步生成器函数体(`async function*` / async 生成器表达式走此入口): - /// 同时标记 `is_generator` 与 `is_async`,VM 调用时按异步生成器协议执行 - /// (next 返回 Promise,yield 挂起与 await 挂起共存)。 - pub(crate) fn compile_async_generator_body<'a>( - &self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx, own_strict: bool, - name: Option<&str>, - ) -> Result { - self.compile_function_body_with_flags( - param_specs, - body_stmts, - parent_ctx, - false, - false, - true, - true, - own_strict, - name, - ) - } - - /// 编译异步函数体(`async function` / async 箭头走此入口):`is_async` 使 - /// `assemble_ir` 标记模块,VM 调用时按异步函数协议执行。 - #[allow(clippy::too_many_arguments)] - pub(crate) fn compile_async_body<'a>( - &self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx, - is_expression_body: bool, is_arrow: bool, own_strict: bool, name: Option<&str>, - ) -> Result { - self.compile_function_body_with_flags( - param_specs, - body_stmts, - parent_ctx, - is_expression_body, - is_arrow, - false, - true, - own_strict, - name, - ) - } - - #[allow(clippy::too_many_arguments)] - fn compile_function_body_with_flags<'a>( - &self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx, - is_expression_body: bool, is_arrow: bool, is_generator: bool, is_async: bool, own_strict: bool, - name: Option<&str>, - ) -> Result { - let body_context = if is_arrow { - FunctionBodyContext::Arrow - } else { - FunctionBodyContext::Ordinary - }; - self.compile_function_body_with_bindings_gen( - param_specs, - body_stmts, - parent_ctx, - is_expression_body, - &[], - body_context, - is_generator, - is_async, - own_strict, - name, - ) - } - - #[allow(clippy::too_many_arguments)] - pub(crate) fn compile_function_body_with_bindings_gen<'a>( - &self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx, - is_expression_body: bool, extra_bindings: &[(&str, u32)], body_context: FunctionBodyContext, - is_generator: bool, is_async: bool, own_strict: bool, name: Option<&str>, - ) -> Result { - self.compile_function_body_with_field_hooks_gen( - param_specs, - body_stmts, - parent_ctx, - is_expression_body, - extra_bindings, - body_context, - None:: Result<(), String>>, - false, - &[], - &[], - is_generator, - is_async, - own_strict, - name, - ) - } - - /// 预注册 builtin 引用并编译函数体(普通/箭头/类元素方法共用入口)。 + /// `flags` 携带函数体种类与严格性(表达式体、生成器、异步、自身 strict、函数名); + /// `hooks` 携带类元素钩子(额外绑定、字段发射、捕获组),非类元素函数传 + /// `ClassElementHooks::none()`。`body_context` 决定 `this`/`super` 绑定与参数 + /// 前导形态:箭头词法继承外层 super,普通函数重置 super 作用域,类元素按类语义。 /// /// 本函数体内任意位置(表达式、成员对象、调用实参、类字段等)引用的内置全局 /// 标识符,其寄存器槽都先于任何临时寄存器登记。 /// /// vreg 化后临时值不复用(独立 vreg),但 builtin 槽预注册仍保证分配序稳定: /// builtin 槽先于临时值池,嵌套函数继承边界不受扰。 - #[allow(clippy::too_many_arguments)] - pub(crate) fn compile_function_body_with_field_hooks<'a, E>( - &self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx, - is_expression_body: bool, extra_bindings: &[(&str, u32)], body_context: FunctionBodyContext, - emit_fields: Option, fields_after_super: bool, extra_capture_exprs: &[&'a Expression<'a>], - extra_upvalue_names: &[(String, u8)], own_strict: bool, name: Option<&str>, - ) -> Result - where - E: FnMut(&Emitter, &mut CompileCtx) -> Result<(), String>, - { - self.compile_function_body_with_field_hooks_gen( - param_specs, - body_stmts, - parent_ctx, - is_expression_body, - extra_bindings, - body_context, - emit_fields, - fields_after_super, - extra_capture_exprs, - extra_upvalue_names, - false, - false, - own_strict, - name, - ) - } - - #[allow(clippy::too_many_arguments)] - pub(crate) fn compile_function_body_with_field_hooks_gen<'a, E>( - &self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx, - is_expression_body: bool, extra_bindings: &[(&str, u32)], body_context: FunctionBodyContext, - mut emit_fields: Option, fields_after_super: bool, extra_capture_exprs: &[&'a Expression<'a>], - extra_upvalue_names: &[(String, u8)], is_generator: bool, is_async: bool, own_strict: bool, name: Option<&str>, + pub(crate) fn compile_function_body<'a, E>( + &self, + param_specs: &[ParamSpec<'a>], + body_stmts: &[Statement<'a>], + parent_ctx: &CompileCtx, + body_context: FunctionBodyContext, + flags: FunctionFlags<'a>, + hooks: ClassElementHooks<'a, E>, ) -> Result where E: FnMut(&Emitter, &mut CompileCtx) -> Result<(), String>, { let mut ctx = CompileCtx::new(); - ctx.is_generator = is_generator; - ctx.is_async = is_async; + ctx.is_generator = flags.is_generator; + ctx.is_async = flags.is_async; // 函数 strict = 自身 directive ‖ 外层严格(规范不可解除); // 类元素方法/构造器恒 strict(ClassBody 是严格模式代码)。 - ctx.is_strict = own_strict || matches!(body_context, FunctionBodyContext::ClassElement) || parent_ctx.is_strict; + ctx.is_strict = flags.own_strict + || matches!(body_context, FunctionBodyContext::ClassElement) + || parent_ctx.is_strict; // 形参名集(含解构叶子与 rest):块级函数名同名的 web-compat 守卫查此集。 let mut param_names = HashSet::new(); @@ -412,7 +315,7 @@ impl Emitter { // eval 起源随作用域继承:eval 顶层 var/函数名在嵌套函数内同样可删(物化 // c:true 全局属性),delete 分类判定读此标志。 ctx.is_eval_origin = parent_ctx.is_eval_origin; - for (name, reg) in extra_bindings { + for (name, reg) in hooks.extra_bindings { ctx.scopes.symbols.scopes[0].bindings.insert( (*name).to_string(), Binding { @@ -452,9 +355,9 @@ impl Emitter { parent_ctx, &mut ctx, body_context, - extra_capture_exprs, - extra_upvalue_names, - name, + hooks.extra_capture_exprs, + hooks.extra_upvalue_names, + flags.name, &scope_names, )?; // 实例字段 computed key 数组所在 upvalue 下标,供字段初始化 emit 定位。 @@ -524,7 +427,7 @@ impl Emitter { let has_using = Self::scope_contains_using(body_stmts); // 生成器:body 起点标记——调用时参数初始化(emit_params_prologue)结束后挂起于此, // 参数副作用/异常在 `g()` 调用时刻生效,首次 next() 从这继续执行 body。 - if is_generator { + if flags.is_generator { ctx.inst(Inst::suspend_body()); // 生成器体环境在 `g()` 调用时建立、首次 next() 从挂起点后继续:水位登记 // 在挂起点之后,体声明的资源只在体尾(生成器完成)释放。 @@ -536,8 +439,8 @@ impl Emitter { ctx.emit_dispose_mark(); } - if let Some(emit) = emit_fields.as_mut() { - if fields_after_super { + if let Some(mut emit) = hooks.emit_fields { + if hooks.fields_after_super { let mut parent_insts = Vec::new(); let mut parent_label_pos = Vec::new(); std::mem::swap(&mut ctx.insts, &mut parent_insts); @@ -568,7 +471,7 @@ impl Emitter { if has_using { ctx.emit_dispose_pop(); } - if is_expression_body { + if flags.is_expression_body { if let Some(reg) = last_result_reg { ctx.inst(Inst::ret(Operand::Reg(reg), 0, 0, 0)); } else { @@ -599,6 +502,25 @@ impl Emitter { Ok(ir) } + /// 非类元素函数体便捷入口:空钩子,等价于核心入口传 `ClassElementHooks::none()`。 + pub(crate) fn compile_simple_function_body<'a>( + &self, + param_specs: &[ParamSpec<'a>], + body_stmts: &[Statement<'a>], + parent_ctx: &CompileCtx, + body_context: FunctionBodyContext, + flags: FunctionFlags<'a>, + ) -> Result { + self.compile_function_body( + param_specs, + body_stmts, + parent_ctx, + body_context, + flags, + ClassElementHooks::none(), + ) + } + /// 规范 `argumentsObjNeeded` 的引擎判据:函数作用域是否声明 `arguments` /// 从而抑制自动 arguments 对象。 /// diff --git a/crates/oxide_emit/src/lib.rs b/crates/oxide_emit/src/lib.rs index 64f11463..c3ba7efd 100644 --- a/crates/oxide_emit/src/lib.rs +++ b/crates/oxide_emit/src/lib.rs @@ -25,6 +25,6 @@ pub use compile_ctx::CompileCtx; pub use emit::Emitter; pub use emit::{is_anonymous_function_definition, is_int_literal, is_side_effect_free}; pub use emit_ctx::LabelScope; -pub use function_body::{FunctionBodyContext, ParamSpec}; +pub use function_body::{ClassElementHooks, FunctionBodyContext, FunctionFlags, ParamSpec}; pub use oxide_bytecode::module::Constant; pub use oxide_parser::{AssignmentOperator, BinaryOperator, UnaryOperator}; diff --git a/crates/oxide_emit/src/stmt/declaration/function_decl.rs b/crates/oxide_emit/src/stmt/declaration/function_decl.rs index 2a860c27..e8223483 100644 --- a/crates/oxide_emit/src/stmt/declaration/function_decl.rs +++ b/crates/oxide_emit/src/stmt/declaration/function_decl.rs @@ -1,7 +1,7 @@ //! 函数声明语句 emit:`emit_function_declaration_statement` 创建闭包并绑定函数名。 use crate::symbol_table::ScopeKind; -use crate::{CompileCtx, Emitter, ParamSpec}; +use crate::{CompileCtx, Emitter, FunctionBodyContext, FunctionFlags, ParamSpec}; use oxide_bytecode::opcode::OpCode; use oxide_ir::inst::Inst; use oxide_ir::operand::Operand; @@ -151,15 +151,15 @@ impl Emitter { } let body_stmts: &[Statement] = if let Some(body) = &fd.body { &body.statements } else { &[] }; let own_strict = fd.has_use_strict_directive(); - let mut sub_module = if fd.generator && fd.r#async { - self.compile_async_generator_body(¶m_names, body_stmts, ctx, own_strict, Some(name))? - } else if fd.generator { - self.compile_generator_body(¶m_names, body_stmts, ctx, own_strict, Some(name))? - } else if fd.r#async { - self.compile_async_body(¶m_names, body_stmts, ctx, false, false, own_strict, Some(name))? - } else { - self.compile_function_body(¶m_names, body_stmts, ctx, false, false, own_strict, Some(name))? + let flags = FunctionFlags { + is_expression_body: false, + is_generator: fd.generator, + is_async: fd.r#async, + own_strict, + name: Some(name), }; + let mut sub_module = + self.compile_simple_function_body(¶m_names, body_stmts, ctx, FunctionBodyContext::Ordinary, flags)?; sub_module.function_name = Some(name.to_string()); ctx.nested.push(sub_module); ctx.inst(Inst::create_closure(Operand::Reg(reg), ctx.nested.len() as u16));