From b6219188e759acb0ed54db120cc42c8c3a2deabf Mon Sep 17 00:00:00 2001 From: pjh456 <147148383@qq.com> Date: Sat, 10 Oct 2026 00:12:44 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20DefineOwnProperty=20=E8=87=82=E5=86=99?= =?UTF-8?q?=E5=8F=82=E6=95=B0=E5=AF=84=E5=AD=98=E5=99=A8=E8=A1=A5=E9=A1=B6?= =?UTF-8?q?=E5=B8=A7=E5=AE=88=E5=8D=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 38 ++++++++++++------------ Cargo.toml | 2 +- crates/oxide_builtins/src/object.rs | 14 ++++++--- crates/oxide_runtime_api/src/host.rs | 5 ++++ crates/oxide_vm/src/vm/vmhost.rs | 3 ++ crates/oxide_vm/src/vm_props.rs | 8 +++++ crates/oxide_vm/tests/arguments_tests.rs | 25 ++++++++++++++++ 7 files changed, 71 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 16598d11..308ecbb2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1160,7 +1160,7 @@ dependencies = [ [[package]] name = "oxide_builtins" -version = "0.13.23" +version = "0.13.24" dependencies = [ "chrono", "fast-float", @@ -1185,7 +1185,7 @@ dependencies = [ [[package]] name = "oxide_bytecode" -version = "0.13.23" +version = "0.13.24" dependencies = [ "num-bigint", "oxide_log", @@ -1193,7 +1193,7 @@ dependencies = [ [[package]] name = "oxide_cfg" -version = "0.13.23" +version = "0.13.24" dependencies = [ "oxide_bytecode", "oxide_emit", @@ -1204,7 +1204,7 @@ dependencies = [ [[package]] name = "oxide_cli" -version = "0.13.23" +version = "0.13.24" dependencies = [ "ansi_term", "bumpalo", @@ -1226,7 +1226,7 @@ dependencies = [ [[package]] name = "oxide_code_cache" -version = "0.13.23" +version = "0.13.24" dependencies = [ "lru", "oxide_bytecode", @@ -1235,7 +1235,7 @@ dependencies = [ [[package]] name = "oxide_compiler" -version = "0.13.23" +version = "0.13.24" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1255,7 +1255,7 @@ dependencies = [ [[package]] name = "oxide_dce" -version = "0.13.23" +version = "0.13.24" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1269,7 +1269,7 @@ dependencies = [ [[package]] name = "oxide_emit" -version = "0.13.23" +version = "0.13.24" dependencies = [ "num-bigint", "oxc_allocator", @@ -1284,7 +1284,7 @@ dependencies = [ [[package]] name = "oxide_engine" -version = "0.13.23" +version = "0.13.24" dependencies = [ "oxide_bytecode", "oxide_compiler", @@ -1296,7 +1296,7 @@ dependencies = [ [[package]] name = "oxide_ir" -version = "0.13.23" +version = "0.13.24" dependencies = [ "oxide_bytecode", "oxide_log", @@ -1305,7 +1305,7 @@ dependencies = [ [[package]] name = "oxide_kernel" -version = "0.13.23" +version = "0.13.24" dependencies = [ "bumpalo", "dashmap", @@ -1319,7 +1319,7 @@ dependencies = [ [[package]] name = "oxide_liveness" -version = "0.13.23" +version = "0.13.24" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1331,7 +1331,7 @@ dependencies = [ [[package]] name = "oxide_log" -version = "0.13.23" +version = "0.13.24" dependencies = [ "tracing", "tracing-appender", @@ -1340,7 +1340,7 @@ dependencies = [ [[package]] name = "oxide_parser" -version = "0.13.23" +version = "0.13.24" dependencies = [ "oxc_allocator", "oxc_ast", @@ -1355,7 +1355,7 @@ dependencies = [ [[package]] name = "oxide_regalloc" -version = "0.13.23" +version = "0.13.24" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1371,7 +1371,7 @@ dependencies = [ [[package]] name = "oxide_runtime_api" -version = "0.13.23" +version = "0.13.24" dependencies = [ "num-bigint", "num-traits", @@ -1384,7 +1384,7 @@ dependencies = [ [[package]] name = "oxide_test262" -version = "0.13.23" +version = "0.13.24" dependencies = [ "oxide_bytecode", "oxide_compiler", @@ -1402,7 +1402,7 @@ dependencies = [ [[package]] name = "oxide_types" -version = "0.13.23" +version = "0.13.24" dependencies = [ "bumpalo", "dashmap", @@ -1415,7 +1415,7 @@ dependencies = [ [[package]] name = "oxide_vm" -version = "0.13.23" +version = "0.13.24" dependencies = [ "bumpalo", "chrono", diff --git a/Cargo.toml b/Cargo.toml index c12803bf..b28c0c5a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ members = [ ] [workspace.package] -version = "0.13.23" +version = "0.13.24" edition = "2021" license = "MIT" rust-version = "1.80" diff --git a/crates/oxide_builtins/src/object.rs b/crates/oxide_builtins/src/object.rs index e4750724..22ee121e 100644 --- a/crates/oxide_builtins/src/object.rs +++ b/crates/oxide_builtins/src/object.rs @@ -984,8 +984,9 @@ pub(crate) fn define_from_descriptor( } // mapped arguments exotic [[DefineOwnProperty]]:整数索引且映射存活时,旧描述符 - // 可写且新描述符不可写则移除映射,新描述符含 value 则写参数寄存器;随后落穿 - // 普通 define 路径(描述符收窄校验由 define_data_property 承担)。 + // 可写且新描述符不可写则移除映射,新描述符含 value 且创建帧为顶帧时写参数 + // 寄存器;随后落穿普通 define 路径(描述符收窄校验由 define_data_property + // 承担)。 if unsafe { &*obj_ptr }.is_arguments_obj() { let state_ptr = unsafe { &*obj_ptr }.native_data() as *mut ArgumentsMapState; if !state_ptr.is_null() { @@ -1006,8 +1007,13 @@ pub(crate) fn define_from_descriptor( state.unmap(index as u16); } if let Some(v) = value_field { - let reg = (state.param_base as u16 + index as u16) as u8; - vm.set_reg(reg, v); + // 参数寄存器仅创建帧为顶帧时写——嵌套调用期寄存器被被调方 + // 占用,写之串值,参数值在 save_stack,存储值仍为权威 + // 读源(与 [[Set]] 臂同口径)。 + if vm.is_top_frame(state.frame_depth) { + let reg = (state.param_base as u16 + index as u16) as u8; + vm.set_reg(reg, v); + } } } } diff --git a/crates/oxide_runtime_api/src/host.rs b/crates/oxide_runtime_api/src/host.rs index b1054bf0..b74003df 100644 --- a/crates/oxide_runtime_api/src/host.rs +++ b/crates/oxide_runtime_api/src/host.rs @@ -259,6 +259,11 @@ pub trait VmHost { /// - `state` 为 arguments 对象 `native_data` 中的同步状态盒;`frame_depth` /// 为创建帧下标,帧弹出后映射失效。 fn arguments_mapping_alive(&self, state: &oxide_types::arguments_map::ArgumentsMapState) -> bool; + /// 判定帧栈下标 `frame_depth` 处的帧是否为顶帧(当前帧)。 + /// + /// # 边界与前提 + /// - `frame_depth` 为创建帧在帧栈中的下标;帧弹出后下标越界返回 `false`。 + fn is_top_frame(&self, frame_depth: u32) -> bool; // 属性访问 fn ordinary_get(&mut self, obj: &JsObject, prop_name_si: u32, receiver: JsValue) -> Result; diff --git a/crates/oxide_vm/src/vm/vmhost.rs b/crates/oxide_vm/src/vm/vmhost.rs index c93c0886..313cbdba 100644 --- a/crates/oxide_vm/src/vm/vmhost.rs +++ b/crates/oxide_vm/src/vm/vmhost.rs @@ -218,6 +218,9 @@ impl oxide_runtime_api::VmHost for Vm { fn arguments_mapping_alive(&self, state: &oxide_types::arguments_map::ArgumentsMapState) -> bool { self.arguments_mapping_alive(state) } + fn is_top_frame(&self, frame_depth: u32) -> bool { + self.is_top_frame(frame_depth) + } fn ordinary_get(&mut self, obj: &JsObject, prop_name_si: u32, receiver: JsValue) -> Result { self.ordinary_get(obj, prop_name_si, receiver) } diff --git a/crates/oxide_vm/src/vm_props.rs b/crates/oxide_vm/src/vm_props.rs index 76a70e09..5a13172c 100644 --- a/crates/oxide_vm/src/vm_props.rs +++ b/crates/oxide_vm/src/vm_props.rs @@ -20,6 +20,14 @@ impl Vm { self.frames.len() > depth && self.frames[depth].frame_id == state.frame_id } + /// 判定帧栈下标 `frame_depth` 处的帧是否为顶帧(当前帧)。 + /// + /// # 边界与前提 + /// - `frame_depth` 为创建帧在帧栈中的下标;帧弹出后下标越界返回 `false`。 + pub(crate) fn is_top_frame(&self, frame_depth: u32) -> bool { + self.frames.len() == frame_depth as usize + 1 + } + /// 属性读入口:解析 `obj[prop_name_si]`,依次尝试数组 length 虚拟属性、 /// 数组元素区、TypedArray 整数索引、命名属性槽,最后沿原型链查找。 /// diff --git a/crates/oxide_vm/tests/arguments_tests.rs b/crates/oxide_vm/tests/arguments_tests.rs index 965f6818..3e1f8410 100644 --- a/crates/oxide_vm/tests/arguments_tests.rs +++ b/crates/oxide_vm/tests/arguments_tests.rs @@ -204,3 +204,28 @@ fn global_self_decrement_preserves_arguments() { let result = eval(&mut vm, "var c=1; function f(a){c--; return arguments.length} f(1)").unwrap(); assert_eq!(result.as_int(), 1); } + +#[test] +fn define_property_nested_call_does_not_clobber_callee_param() { + // 嵌套调用期对外层函数 arguments 索引属性 defineProperty 不写被调方帧的 + // 参数寄存器(顶帧守卫):被调方形参值不被串改。 + let mut vm = Vm::new(); + let result = eval( + &mut vm, + "function a(x){function b(y){Object.defineProperty(a.arguments,0,{value:5}); return y} return b(7)} a(1)", + ) + .unwrap(); + assert_eq!(result.as_int(), 7); +} + +#[test] +fn define_property_nested_call_updates_stored_value() { + // 嵌套调用期 defineProperty 更新存储值(读路径权威源):回到顶帧后读为新值。 + let mut vm = Vm::new(); + let result = eval( + &mut vm, + "function a(x){function b(){Object.defineProperty(a.arguments,0,{value:5})} b(); return a.arguments[0]} a(1)", + ) + .unwrap(); + assert_eq!(result.as_int(), 5); +}