feat: 对象字面量 spread({...obj} 展开可枚举自有属性)

This commit is contained in:
爱特每羊队
2026-08-08 11:24:09 +08:00
parent 2777b00c82
commit 6c7b10d6c5
10 changed files with 251 additions and 63 deletions
+4 -1
View File
@@ -36,6 +36,9 @@ pub(super) fn hash_object_property_kind(
hash_property_key(&p.key, h, include_binding_names);
expression::hash_expression(&p.value, h, include_binding_names);
}
ObjectPropertyKind::SpreadProperty(_) => {}
ObjectPropertyKind::SpreadProperty(spread) => {
// spread 的源表达式计入哈希:`{...a}` 与 `{...b}` 结构不同,避免缓存碰撞。
expression::hash_expression(&spread.argument, h, include_binding_names);
}
});
}
@@ -167,6 +167,19 @@ fn structural_hash_distinguishes_optional_chain_shape() {
assert_ne!(optional_c, plain_b);
}
#[test]
fn object_spread_source_shapes_differ() {
// 编译模块哈希含绑定名:{...a} 与 {...b} 展开源不同,缓存键必须不同。
let spread_a = parse_to_compiled_hash("var o = { ...a };");
let spread_b = parse_to_compiled_hash("var o = { ...b };");
assert_ne!(spread_a, spread_b, "different spread sources must produce different hashes");
// 结构哈希区分 spread 与非 spread 的对象字面量。
let plain = parse_to_hash("var o = { a: 1 };");
let spread_after = parse_to_hash("var o = { a: 1, ...x };");
assert_ne!(plain, spread_after, "spread vs non-spread object must hash differently");
}
#[test]
fn compiled_module_rejects_optional_chain_assignment_target() {
let allocator = Allocator::default();