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

This commit is contained in:
爱特每羊队
2026-06-07 19:47:49 +08:00
parent 77bf00233b
commit 3f41fe9d71
2 changed files with 35 additions and 16 deletions
+26 -16
View File
@@ -2333,28 +2333,38 @@ 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();
while let Some(id) = cursor { let mut current = obj_val;
if id == oxide_kernel::shape_forge::EMPTY_SHAPE_ID {
loop {
if !current.is_object() {
break; break;
} }
if let Some(shape) = self.kernel.shape_forge().get_shape(id) { let cur = unsafe { &*current.as_js_object_ptr() };
if shape.property_name != u32::MAX { let mut cursor = Some(cur.shape_id());
let hash = self while let Some(id) = cursor {
.kernel if id == EMPTY_SHAPE_ID {
.string_forge() break;
.get_hash(shape.property_name) }
.unwrap_or(0); if let Some(shape) = self.kernel.shape_forge().get_shape(id) {
keys_vec.push(JsValue::string(shape.property_name, hash)); if shape.property_name != u32::MAX
&& seen.insert(shape.property_name)
{
let hash = self
.kernel
.string_forge()
.get_hash(shape.property_name)
.unwrap_or(0);
keys_vec.push(JsValue::string(shape.property_name, hash));
}
cursor = shape.parent;
} else {
break;
} }
cursor = shape.parent;
} else {
break;
} }
current = cur.proto();
} }
let iter = self.epoch.alloc(ForInIter { let iter = self.epoch.alloc(ForInIter {
@@ -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"
);
}