From f870278795259b0777632ff577ae90858e23a9ad Mon Sep 17 00:00:00 2001 From: pjh456 <147148383@qq.com> Date: Sat, 19 Sep 2026 13:17:23 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20in=20=E6=8C=87=E4=BB=A4=E5=88=87=20HasPr?= =?UTF-8?q?operty=20=E5=AF=B9=E9=BD=90=E6=95=B4=E6=95=B0=E7=B4=A2=E5=BC=95?= =?UTF-8?q?=E4=B8=8E=E9=93=BE=E4=B8=8A=E5=85=83=E7=B4=A0=E5=8C=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/oxide_vm/src/vm_dispatch_misc.rs | 4 +- .../tests/builtins_typed_array_tests.rs | 38 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/crates/oxide_vm/src/vm_dispatch_misc.rs b/crates/oxide_vm/src/vm_dispatch_misc.rs index 2072fe47..893e7e42 100644 --- a/crates/oxide_vm/src/vm_dispatch_misc.rs +++ b/crates/oxide_vm/src/vm_dispatch_misc.rs @@ -381,7 +381,9 @@ impl Vm { } let obj = unsafe { &*obj_ptr }; let prop_name_si = self.property_key_si(key_val)?; - let found = self.resolve_property(obj, prop_name_si).is_some(); + // `in` 即 HasProperty:原型链各层都要看数组元素区与 TypedArray 整数索引, + // 读值解析不覆盖这两处。 + let found = self.has_property(obj, prop_name_si); self.regs[rd] = JsValue::bool(found); Ok(()) } diff --git a/crates/oxide_vm/tests/builtins_typed_array_tests.rs b/crates/oxide_vm/tests/builtins_typed_array_tests.rs index ef1ead0e..bf5dfd8e 100644 --- a/crates/oxide_vm/tests/builtins_typed_array_tests.rs +++ b/crates/oxide_vm/tests/builtins_typed_array_tests.rs @@ -314,6 +314,44 @@ fn typed_array_bigint_sort_uses_bigint_compare() { assert!(result.as_bool()); } +#[test] +fn typed_array_in_operator_uses_has_property_semantics() { + // `in` 按 HasProperty 判定:TypedArray 整数索引按视图长度判在界, + // 越界索引判不存在。 + let mut vm = Vm::new(); + let result = eval( + &mut vm, + "var ta = new Int8Array(2); \ + (0 in ta) && (1 in ta) && !(2 in ta) && !(3 in ta) && \ + ('length' in ta) && !('foo' in ta)", + ) + .unwrap(); + assert!(result.as_bool()); +} + +#[test] +fn in_operator_finds_array_elements_on_proto_chain() { + // 原型链上的数组元素区索引判存在:Object.create([1,2]) 的 0/1 在界、2 越界。 + let mut vm = Vm::new(); + let result = eval(&mut vm, "var o = Object.create([1, 2]); (0 in o) && (1 in o) && !(2 in o)").unwrap(); + assert!(result.as_bool()); +} + +#[test] +fn in_operator_ordinary_object_zero_drift() { + // 普通对象 `in` 既有行为零漂移:自有属性在、未定义键不在、原型链属性在、 + // 无整型键的对象不判索引存在。 + let mut vm = Vm::new(); + let result = eval( + &mut vm, + "var base = { x: 1 }; var o = Object.create(base); \ + ('x' in o) && !('y' in o) && ('toString' in o) && \ + !(0 in Object.create({}))", + ) + .unwrap(); + assert!(result.as_bool()); +} + #[test] fn typed_array_bigint_methods_receive_bigint_values() { let mut vm = Vm::new();