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:
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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(|_| ()),
|
||||
|
||||
Reference in New Issue
Block a user