From 99224b88b36a96ce0ffcca1fd4602aa4077fc711 Mon Sep 17 00:00:00 2001 From: pjh456 <147148383@qq.com> Date: Wed, 23 Sep 2026 11:31:33 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20TA=20=E5=88=A0=E9=99=A4=E8=87=AA?= =?UTF-8?q?=E8=BA=AB=E4=B8=B2=E9=94=AE=E9=87=8D=E5=BB=BA=E6=8E=92=E9=99=A4?= =?UTF-8?q?=E5=93=A8=E5=85=B5=E5=85=83=E7=B4=A0=E9=94=AE=E9=98=B2=E5=BD=A2?= =?UTF-8?q?=E7=8A=B6=E9=93=BE=E7=89=A9=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/oxide_builtins/src/object.rs | 10 +++- .../tests/builtins_typed_array_tests.rs | 58 ++++++++++++++++++- 2 files changed, 63 insertions(+), 5 deletions(-) diff --git a/crates/oxide_builtins/src/object.rs b/crates/oxide_builtins/src/object.rs index e04af4e5..40de67e4 100644 --- a/crates/oxide_builtins/src/object.rs +++ b/crates/oxide_builtins/src/object.rs @@ -419,8 +419,14 @@ pub fn delete_own_property_outcome(vm: &mut H, obj: &mut JsObject, ke let retained: Vec<(u32, JsValue, Option)> = all_keys .into_iter() - // 数组元素区由下方独立保存/恢复,此处只重建命名属性(元素键绝对下标 < 元素数)。 - .filter(|(_, pos)| *pos != delete_pos && !(obj.is_array() && *pos < obj.array_prop_count)) + // 数组元素区由下方独立保存/恢复,此处只重建命名属性(元素键绝对下标 < + // 元素数);TA 元素键(0..live 长)元素住 buffer 不占形状链,同样排除出 + // 重建,防经空 meta 取值 undefined 物化成 shape 链真 own 属性。 + .filter(|(si, pos)| { + *pos != delete_pos + && !(obj.is_array() && *pos < obj.array_prop_count) + && !(obj.is_typed_array_obj() && is_int_key(*si)) + }) .map(|(si, pos)| (si, obj.get_prop_at(pos), obj.prop_meta_at(pos))) .collect(); diff --git a/crates/oxide_vm/tests/builtins_typed_array_tests.rs b/crates/oxide_vm/tests/builtins_typed_array_tests.rs index 46bc9efc..30163baf 100644 --- a/crates/oxide_vm/tests/builtins_typed_array_tests.rs +++ b/crates/oxide_vm/tests/builtins_typed_array_tests.rs @@ -2039,9 +2039,61 @@ fn ta_keys_int_index_2pow32_boundary() { let result = eval( &mut vm, "(function () { var ks1 = Object.keys({ a: 1, '4294967295': 2 }); \ - if (ks1.join(',') !== '4294967295,a') return false; \ - var ks2 = Object.keys({ b: 1, '4294967296': 2 }); \ - return ks2.join(',') === 'b,4294967296'; })()", + if (ks1.join(',') !== '4294967295,a') return false; \ + var ks2 = Object.keys({ b: 1, '4294967296': 2 }); \ + return ks2.join(',') === 'b,4294967296'; })()", + ) + .unwrap(); + assert!(result.as_bool()); +} + +#[test] +fn ta_ownkeys_stable_after_delete_str_prop() { + // 删 own 串键后枚举键集稳定:元素键住 buffer 不占形状链,删除重建命名属性 + // 不得把元素键物化为形状节点——ownKeys/keys/gOPN 均无重复整数键。 + let mut vm = Vm::new(); + let result = eval( + &mut vm, + "(function () { var ta = new Uint8Array([1, 2]); \ + ta.foo = 1; \ + if (!delete ta.foo) return false; \ + if (Reflect.ownKeys(ta).join(',') !== '0,1') return false; \ + if (Object.keys(ta).join(',') !== '0,1') return false; \ + return Object.getOwnPropertyNames(ta).join(',') === '0,1'; })()", + ) + .unwrap(); + assert!(result.as_bool()); +} + +#[test] +fn ta_gopd_no_phantom_after_delete_str_prop() { + // 删 own 串键后元素位描述符不变(value + w/e/c 全真)、被删键无残留 + // 幻影 own 属性、元素值不动。 + let mut vm = Vm::new(); + let result = eval( + &mut vm, + "(function () { var ta = new Uint8Array([1, 2]); \ + ta.foo = 1; delete ta.foo; \ + var d = Object.getOwnPropertyDescriptor(ta, '0'); \ + if (!d || d.value !== 1 || d.writable !== true \ + || d.enumerable !== true || d.configurable !== true) return false; \ + if (Object.getOwnPropertyDescriptor(ta, 'foo') !== undefined) return false; \ + return ta[0] === 1 && ta[1] === 2 && ta.foo === undefined; })()", + ) + .unwrap(); + assert!(result.as_bool()); +} + +#[test] +fn ta_for_in_stable_after_delete_str_prop() { + // 删 own 串键后 for-in 出元素键升序 + 无重复、无被删键残留。 + let mut vm = Vm::new(); + let result = eval( + &mut vm, + "(function () { var ta = new Uint8Array([1, 2]); \ + ta.foo = 1; delete ta.foo; \ + var ks = []; for (var k in ta) ks.push(k); \ + return ks.length === 2 && ks[0] === '0' && ks[1] === '1'; })()", ) .unwrap(); assert!(result.as_bool());