fix: 对象建键入口统一走 property_key_si 规范化,数字键不再分裂

Object.fromEntries/JSON.parse/new Map 对象 entry/rest 解构静态 excluded
四处直接 intern 动态字符串键绕过整数键区间映射,规范数字键分裂为
字符串键与整数键两个键。统一经 string_key_si 规范化:规范数字串映射
整数键,其余 intern 字符串键,与 property_key_si 字符串分支口径一致。
make_int_key 增加 debug 断言兜底索引越界。
This commit is contained in:
2026-08-14 22:37:46 +08:00
parent 540153030b
commit b82fe9af32
12 changed files with 145 additions and 9 deletions
+7
View File
@@ -1911,6 +1911,13 @@ impl oxide_runtime_api::VmHost for Vm {
self.property_key_si(val)
.unwrap_or_else(|_| self.kernel_core.perm_interner().intern("").0)
}
fn string_key_si(&mut self, s: &str) -> u32 {
if let Some(i) = canonical_index_of(s) {
make_int_key(i)
} else {
self.kernel_core.perm_interner().intern(s).0
}
}
fn resolve_property(&self, obj: &JsObject, prop_name_si: u32) -> Option<JsValue> {
self.resolve_property(obj, prop_name_si)
}
+8 -2
View File
@@ -768,7 +768,7 @@ impl Vm {
let mut excluded: std::collections::HashSet<u32> = excluded_const
.split('\0')
.filter(|s| !s.is_empty())
.map(|s| self.kernel_core.perm_interner().intern(s).0)
.map(|s| self.string_key_si(s))
.collect();
// 运行时 excluded:b 槽数组(computed key 求值结果)的元素 ToPropertyKey 后排除。
if b != 0 {
@@ -798,6 +798,9 @@ impl Vm {
let code_units: Vec<u16> = s.encode_utf16().collect();
for (i, unit) in code_units.iter().enumerate() {
let si = make_int_key(i as u32);
if excluded.contains(&si) {
continue;
}
let ch_val = match char::from_u32(*unit as u32) {
Some(c) => match self.single_char(c) {
Some(v) => v,
@@ -809,7 +812,7 @@ impl Vm {
}
}
// 数组元素区:整数下标可枚举元素(hole 跳过)。
// 数组元素区:整数下标可枚举元素(hole 跳过),排除 pattern 已绑定的键。
if src_obj.is_array() {
for i in 0..src_obj.array_prop_count {
if src_obj.prop_meta_at(i).is_some_and(|m| m.is_hole()) {
@@ -821,6 +824,9 @@ impl Vm {
.unwrap_or(PropAttributes::DEFAULT_DATA.enumerable());
if enumerable {
let si = make_int_key(i);
if excluded.contains(&si) {
continue;
}
let val = match self.ordinary_get(src_obj, si, src) {
Ok(v) => v,
Err(e) => return self.raise_call_error(&e).map(|_| ()),