fix: 修复 for-in 语法原型链丢失属性问题

This commit is contained in:
2026-06-07 19:47:49 +08:00
parent 3c641313cd
commit ad1b1f8575
2 changed files with 35 additions and 16 deletions
+15 -5
View File
@@ -2333,17 +2333,25 @@ impl Vm {
if !obj_val.is_object() { if !obj_val.is_object() {
return Err("TypeError: for-in right-hand side is not an object".into()); return Err("TypeError: for-in right-hand side is not an object".into());
} }
let obj = unsafe { &*obj_val.as_js_object_ptr() };
let shape_id = obj.shape_id();
let mut keys_vec = bumpalo::collections::Vec::new_in(self.epoch.bump()); let mut keys_vec = bumpalo::collections::Vec::new_in(self.epoch.bump());
let mut cursor = Some(shape_id); let mut seen = std::collections::HashSet::new();
let mut current = obj_val;
loop {
if !current.is_object() {
break;
}
let cur = unsafe { &*current.as_js_object_ptr() };
let mut cursor = Some(cur.shape_id());
while let Some(id) = cursor { while let Some(id) = cursor {
if id == oxide_kernel::shape_forge::EMPTY_SHAPE_ID { if id == EMPTY_SHAPE_ID {
break; break;
} }
if let Some(shape) = self.kernel.shape_forge().get_shape(id) { if let Some(shape) = self.kernel.shape_forge().get_shape(id) {
if shape.property_name != u32::MAX { if shape.property_name != u32::MAX
&& seen.insert(shape.property_name)
{
let hash = self let hash = self
.kernel .kernel
.string_forge() .string_forge()
@@ -2356,6 +2364,8 @@ impl Vm {
break; break;
} }
} }
current = cur.proto();
}
let iter = self.epoch.alloc(ForInIter { let iter = self.epoch.alloc(ForInIter {
keys: keys_vec, keys: keys_vec,
@@ -64,3 +64,12 @@ fn regression_throw_statement_errors() {
"compile error: throw statement not supported" "compile error: throw statement not supported"
); );
} }
#[test]
fn regression_for_in_prototype_chain() {
assert_eq!(
eval("var c=0;for(var k in {a:1}){c=c+1;}c"),
"2",
"for-in should include inherited constructor from prototype"
);
}