From 089179daab4a2cc9e5c41d39ded7c57d7d07b771 Mon Sep 17 00:00:00 2001 From: pjh456 <147148383@qq.com> Date: Sun, 16 Aug 2026 16:46:33 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E5=87=BD=E6=95=B0=20strict=20?= =?UTF-8?q?=E6=A0=87=E5=BF=97=E5=85=A5=20IR/=E7=BC=96=E8=AF=91/=E7=BC=93?= =?UTF-8?q?=E5=AD=98=E9=93=BE=EF=BC=88=E9=9B=B6=E8=A1=8C=E4=B8=BA=E5=9C=B0?= =?UTF-8?q?=E5=9F=BA=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/oxide_bytecode/src/module.rs | 4 ++ crates/oxide_compiler/src/hash/mod.rs | 6 +++ crates/oxide_emit/src/class/emit.rs | 10 +++++ crates/oxide_emit/src/class/method.rs | 1 + crates/oxide_emit/src/emit.rs | 44 ++++++++++++++----- crates/oxide_emit/src/expr/function/mod.rs | 27 +++++++++--- crates/oxide_emit/src/module.rs | 4 ++ .../src/stmt/declaration/function_decl.rs | 9 ++-- crates/oxide_ir/src/lib.rs | 3 ++ crates/oxide_ir/src/lower.rs | 1 + 10 files changed, 89 insertions(+), 20 deletions(-) diff --git a/crates/oxide_bytecode/src/module.rs b/crates/oxide_bytecode/src/module.rs index ffac0733..0241a70c 100644 --- a/crates/oxide_bytecode/src/module.rs +++ b/crates/oxide_bytecode/src/module.rs @@ -58,6 +58,8 @@ pub struct CompiledModule { pub sub_modules: Vec>, /// 是否为箭头函数体(箭头函数从外围作用域词法捕获 `this`)。 pub is_arrow: bool, + /// 是否为严格模式函数体:VM 帧入口据其判定 sloppy `this` 替换。 + pub is_strict: bool, /// 捕获 `this` 的 JsValue 在常量池中的下标;0 表示未捕获,使用标准 this 绑定。 pub captured_this_const_idx: u16, /// 由赋值上下文推断的函数名,在变量声明 / 对象属性赋值点设置。 @@ -96,6 +98,7 @@ impl CompiledModule { builtin_reg_map: Vec::new(), sub_modules: Vec::new(), is_arrow: false, + is_strict: false, captured_this_const_idx: 0, function_name: None, function_length: 0, @@ -129,6 +132,7 @@ impl Clone for CompiledModule { builtin_reg_map: self.builtin_reg_map.clone(), sub_modules: self.sub_modules.clone(), is_arrow: self.is_arrow, + is_strict: self.is_strict, captured_this_const_idx: self.captured_this_const_idx, function_name: self.function_name.clone(), function_length: self.function_length, diff --git a/crates/oxide_compiler/src/hash/mod.rs b/crates/oxide_compiler/src/hash/mod.rs index 0cf37347..ca36e5e9 100644 --- a/crates/oxide_compiler/src/hash/mod.rs +++ b/crates/oxide_compiler/src/hash/mod.rs @@ -56,6 +56,12 @@ fn hash_program(program: &oxide_parser::Program, include_binding_names: bool) -> statement::hash_statement(stmt, &mut h, include_binding_names); } + // directives 决定脚本/函数严格模式:不纳入 hash 时 `"use strict"; f()` + // 与 `f()` 缓存键相同,复用错误字节码(严格标志随缓存命中错配)。 + for directive in &program.directives { + directive.directive.as_str().hash(&mut h); + } + h.finish() } diff --git a/crates/oxide_emit/src/class/emit.rs b/crates/oxide_emit/src/class/emit.rs index e2949816..aad80b13 100644 --- a/crates/oxide_emit/src/class/emit.rs +++ b/crates/oxide_emit/src/class/emit.rs @@ -26,6 +26,10 @@ impl Emitter { pub(crate) fn emit_class_with_binding( &self, class: &Class, ctx: &mut CompileCtx, binding_reg: Option, ) -> Result { + // 类定义体是严格模式代码:字段初始化/静态块/extends 表达式内嵌套函数以 + // 本 ctx 为父 ctx,类编译期间强制 strict(函数末尾恢复外层标志)。 + let saved_strict = ctx.is_strict; + ctx.is_strict = true; let ctor_name = class.id.as_ref().map(|id| id.name.to_string()); // 类声明由调用方提供外层绑定槽(binding_reg=Some),类表达式无外部槽 // (None,类名是类体内独立 const 绑定)。真实名 cell 仅声明路径指向 @@ -264,6 +268,7 @@ impl Emitter { is_derived, &field_value_exprs, &extra_upvalue_names, + true, )? } else { let mut module = self.compile_function_body_with_field_hooks( @@ -277,6 +282,7 @@ impl Emitter { is_derived, &field_value_exprs, &extra_upvalue_names, + true, )?; if is_derived { module.insts.clear(); @@ -288,6 +294,8 @@ impl Emitter { module.insts.push(Inst::super_call_spread(Operand::Reg(0), &[0x8000_0000 | 1])); // 字段初始化直接重发:构造器 upvalue/内置槽引用须与首轮编译产物对齐。 let mut field_ctx = CompileCtx::new(); + // 字段表达式运行于构造器帧,构造器恒 strict,字段 ctx 同步置位。 + field_ctx.is_strict = true; field_ctx.scopes.private_name_map = private_names.iter().map(|(n, id, _, _)| (n.clone(), *id)).collect(); field_ctx.scopes.builtin_reg_map = module.builtin_reg_map.clone(); @@ -427,6 +435,8 @@ impl Emitter { ctx.scopes.private_name_map = saved_private_names; ctx.scopes.private_element_kinds = saved_private_kinds; ctx.scopes.private_brand_id = saved_brand_id; + // 类编译结束恢复外层 strict 标志:类在 sloppy 上下文时不得泄漏 strict 到类后代码。 + ctx.is_strict = saved_strict; Ok(ctor_reg) } } diff --git a/crates/oxide_emit/src/class/method.rs b/crates/oxide_emit/src/class/method.rs index 76820866..49cb8343 100644 --- a/crates/oxide_emit/src/class/method.rs +++ b/crates/oxide_emit/src/class/method.rs @@ -128,6 +128,7 @@ impl Emitter { &extra_uv, method_value.generator, method_value.r#async, + true, )?; ctx.in_instance_method = saved_instance; ctx.in_static_method = saved_static; diff --git a/crates/oxide_emit/src/emit.rs b/crates/oxide_emit/src/emit.rs index d11d1c20..c2e48dee 100644 --- a/crates/oxide_emit/src/emit.rs +++ b/crates/oxide_emit/src/emit.rs @@ -172,6 +172,9 @@ pub struct CompileCtx { pub(crate) is_generator: bool, /// 本函数是否为异步函数体(`async function` / async 箭头),`assemble_ir` 回写到 IR。 pub(crate) is_async: bool, + /// 本函数是否为严格模式函数体:自身 directive ‖ 外层严格继承(编译入口设置 + + /// 嵌套继承,见 compile_function_body_with_field_hooks_gen),`assemble_ir` 回写到 IR。 + pub(crate) is_strict: bool, /// 是否为脚本顶层模块(emit_program 的根上下文)。顶层 var/function 声明需 /// 同步写全局对象属性(脚本环境记录的 var 可经 globalThis 反射);函数体为 false。 pub(crate) is_global_scope: bool, @@ -306,6 +309,7 @@ impl CompileCtx { in_static_method: false, is_generator: false, is_async: false, + is_strict: false, is_global_scope: false, static_block_this_reg: None, field_buffer: None, @@ -701,6 +705,7 @@ impl CompileCtx { needs_home_object: false, is_generator: self.is_generator, is_async: self.is_async, + is_strict: self.is_strict, captured_this_const_idx: 0, function_name: None, function_length: self.function_length, @@ -874,7 +879,7 @@ impl Emitter { /// 继承外层 super,普通函数重置 super 作用域。 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, + is_expression_body: bool, is_arrow: bool, own_strict: bool, ) -> Result { self.compile_function_body_with_flags( param_specs, @@ -884,30 +889,40 @@ impl Emitter { is_arrow, false, false, + own_strict, ) } /// 编译函数体并显式指定生成器标志(`function*` 走此入口)。 pub(crate) fn compile_generator_body<'a>( - &self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx, + &self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx, own_strict: bool, ) -> Result { - self.compile_function_body_with_flags(param_specs, body_stmts, parent_ctx, false, false, true, false) + self.compile_function_body_with_flags( + param_specs, + body_stmts, + parent_ctx, + false, + false, + true, + false, + own_strict, + ) } /// 编译异步生成器函数体(`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, + &self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx, own_strict: bool, ) -> Result { - self.compile_function_body_with_flags(param_specs, body_stmts, parent_ctx, false, false, true, true) + self.compile_function_body_with_flags(param_specs, body_stmts, parent_ctx, false, false, true, true, own_strict) } /// 编译异步函数体(`async function` / async 箭头走此入口):`is_async` 使 /// `assemble_ir` 标记模块,VM 调用时按异步函数协议执行。 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, + is_expression_body: bool, is_arrow: bool, own_strict: bool, ) -> Result { self.compile_function_body_with_flags( param_specs, @@ -917,13 +932,14 @@ impl Emitter { is_arrow, false, true, + own_strict, ) } #[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, + is_expression_body: bool, is_arrow: bool, is_generator: bool, is_async: bool, own_strict: bool, ) -> Result { let body_context = if is_arrow { FunctionBodyContext::Arrow @@ -939,6 +955,7 @@ impl Emitter { body_context, is_generator, is_async, + own_strict, ) } @@ -946,7 +963,7 @@ impl Emitter { 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, + is_generator: bool, is_async: bool, own_strict: bool, ) -> Result { self.compile_function_body_with_field_hooks_gen( param_specs, @@ -961,6 +978,7 @@ impl Emitter { &[], is_generator, is_async, + own_strict, ) } @@ -976,7 +994,7 @@ impl Emitter { &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: &[(&str, u8)], + extra_upvalue_names: &[(&str, u8)], own_strict: bool, ) -> Result where E: FnMut(&Emitter, &mut CompileCtx) -> Result<(), String>, @@ -994,6 +1012,7 @@ impl Emitter { extra_upvalue_names, false, false, + own_strict, ) } @@ -1002,7 +1021,7 @@ impl Emitter { &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: &[(&str, u8)], is_generator: bool, is_async: bool, + extra_upvalue_names: &[(&str, u8)], is_generator: bool, is_async: bool, own_strict: bool, ) -> Result where E: FnMut(&Emitter, &mut CompileCtx) -> Result<(), String>, @@ -1010,6 +1029,9 @@ impl Emitter { let mut ctx = CompileCtx::new(); ctx.is_generator = is_generator; ctx.is_async = is_async; + // 函数 strict = 自身 directive ‖ 外层严格(规范不可解除); + // 类元素方法/构造器恒 strict(ClassBody 是严格模式代码)。 + ctx.is_strict = own_strict || matches!(body_context, FunctionBodyContext::ClassElement) || parent_ctx.is_strict; // length = 第一个带默认值形参之前的形参数(解构默认与标识符默认同规则); // rest 参数不计入 length(以 0 结尾即止)。 @@ -1475,6 +1497,8 @@ impl Emitter { let mut ctx = CompileCtx::new(); // 脚本顶层:var/function 声明需落到全局对象,let/const/class 不进全局。 ctx.is_global_scope = true; + // 脚本顶层严格模式由源码 "use strict" directive 决定(嵌套函数经父 ctx 继承)。 + ctx.is_strict = program.has_use_strict_directive(); self.predeclare_function_declarations(&program.body, &mut ctx); // 预注册 builtin 引用(先于任何临时寄存器),builtin 槽不进入临时寄存器池。 diff --git a/crates/oxide_emit/src/expr/function/mod.rs b/crates/oxide_emit/src/expr/function/mod.rs index 712a5e48..4d2db5c7 100644 --- a/crates/oxide_emit/src/expr/function/mod.rs +++ b/crates/oxide_emit/src/expr/function/mod.rs @@ -40,9 +40,23 @@ impl Emitter { 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)? + self.compile_async_body( + ¶m_names, + body_stmts, + ctx, + is_expr_body, + true, + arrow.has_use_strict_directive(), + )? } else { - self.compile_function_body(¶m_names, body_stmts, ctx, is_expr_body, true)? + self.compile_function_body( + ¶m_names, + body_stmts, + ctx, + is_expr_body, + true, + arrow.has_use_strict_directive(), + )? }; sub_module.is_arrow = true; @@ -83,14 +97,15 @@ impl Emitter { let body_stmts: &[Statement] = if let Some(body) = &fe.body { &body.statements } else { &[] }; + let own_strict = fe.has_use_strict_directive(); let mut sub_module = if fe.generator && fe.r#async { - self.compile_async_generator_body(¶m_names, body_stmts, ctx)? + self.compile_async_generator_body(¶m_names, body_stmts, ctx, own_strict)? } else if fe.generator { - self.compile_generator_body(¶m_names, body_stmts, ctx)? + self.compile_generator_body(¶m_names, body_stmts, ctx, own_strict)? } else if fe.r#async { - self.compile_async_body(¶m_names, body_stmts, ctx, false, false)? + self.compile_async_body(¶m_names, body_stmts, ctx, false, false, own_strict)? } else { - self.compile_function_body(¶m_names, body_stmts, ctx, false, false)? + self.compile_function_body(¶m_names, body_stmts, ctx, false, false, own_strict)? }; if let Some(id) = &fe.id { sub_module.function_name = Some(id.name.to_string()); diff --git a/crates/oxide_emit/src/module.rs b/crates/oxide_emit/src/module.rs index 7d882e33..c437bd22 100644 --- a/crates/oxide_emit/src/module.rs +++ b/crates/oxide_emit/src/module.rs @@ -136,6 +136,8 @@ impl Emitter { let mut ctx = CompileCtx::new(); // 模块顶层 var/function 不写全局对象(模块作用域绑定)。 ctx.is_global_scope = false; + // ES module 顶层恒严格模式(模块代码是严格模式代码,嵌套函数经父 ctx 继承)。 + ctx.is_strict = true; let mut path_stack = vec![module_path.to_string()]; self.emit_module_into_ctx(program, module_path, loader, &mut path_stack, &mut ctx)?; Ok(ctx.assemble_ir(ParamLayout { base: 0, count: 0 }, None)) @@ -387,6 +389,8 @@ impl Emitter { })?; let mut ctx = CompileCtx::new(); ctx.is_global_scope = false; + // 依赖模块经 parse_module 解析,顶层恒严格模式。 + ctx.is_strict = true; self.emit_module_into_ctx(&program, &resolved.path, loader, path_stack, &mut ctx)?; Ok(ctx.assemble_ir(ParamLayout { base: 0, count: 0 }, None)) } diff --git a/crates/oxide_emit/src/stmt/declaration/function_decl.rs b/crates/oxide_emit/src/stmt/declaration/function_decl.rs index 3f9e164f..f668bb62 100644 --- a/crates/oxide_emit/src/stmt/declaration/function_decl.rs +++ b/crates/oxide_emit/src/stmt/declaration/function_decl.rs @@ -43,14 +43,15 @@ impl Emitter { self.push_rest_param(&rest.rest.argument, &mut param_names)?; } 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)? + self.compile_async_generator_body(¶m_names, body_stmts, ctx, own_strict)? } else if fd.generator { - self.compile_generator_body(¶m_names, body_stmts, ctx)? + self.compile_generator_body(¶m_names, body_stmts, ctx, own_strict)? } else if fd.r#async { - self.compile_async_body(¶m_names, body_stmts, ctx, false, false)? + self.compile_async_body(¶m_names, body_stmts, ctx, false, false, own_strict)? } else { - self.compile_function_body(¶m_names, body_stmts, ctx, false, false)? + self.compile_function_body(¶m_names, body_stmts, ctx, false, false, own_strict)? }; sub_module.function_name = Some(name.clone()); ctx.nested.push(sub_module); diff --git a/crates/oxide_ir/src/lib.rs b/crates/oxide_ir/src/lib.rs index c6200873..def2f310 100644 --- a/crates/oxide_ir/src/lib.rs +++ b/crates/oxide_ir/src/lib.rs @@ -55,6 +55,8 @@ pub struct IRFunction { pub is_generator: bool, /// 是否为异步函数体(`async function` / async 箭头)。 pub is_async: bool, + /// 是否为严格模式函数体(自身 "use strict" directive 或外层严格继承,不可解除)。 + pub is_strict: bool, pub captured_this_const_idx: u16, pub function_name: Option, /// 函数 `length` 属性值:第一个带默认值/解构默认的形参之前的形参数(rest 不计)。 @@ -87,6 +89,7 @@ impl IRFunction { needs_home_object: false, is_generator: false, is_async: false, + is_strict: false, captured_this_const_idx: 0, function_name: None, function_length: 0, diff --git a/crates/oxide_ir/src/lower.rs b/crates/oxide_ir/src/lower.rs index 14eaac42..58fff790 100644 --- a/crates/oxide_ir/src/lower.rs +++ b/crates/oxide_ir/src/lower.rs @@ -86,6 +86,7 @@ pub fn lower(f: &IRFunction) -> Result { builtin_reg_map: f.builtin_reg_map.clone(), sub_modules, is_arrow: f.is_arrow, + is_strict: f.is_strict, captured_this_const_idx: f.captured_this_const_idx, function_name: f.function_name.clone(), function_length: f.function_length,