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:
@@ -139,7 +139,8 @@ fn value_to_jsvalue<H: VmHost>(vm: &mut H, val: &serde_json::Value) -> JsValue {
|
||||
let object_proto = vm.session().builtin_world().object_proto.as_ptr() as *mut JsObject;
|
||||
let mut obj = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(object_proto));
|
||||
for (key, val) in map {
|
||||
let si = vm.kernel_core().perm_interner().intern(key).0;
|
||||
// 键经字符串规范化:规范数字串("0"/"5")映射整数键,与属性访问统一。
|
||||
let si = vm.string_key_si(key);
|
||||
let jsv = value_to_jsvalue(vm, val);
|
||||
let new_shape = vm.kernel_core().shape_forge().make_shape(obj.shape_id(), si);
|
||||
obj.set_shape_id(new_shape);
|
||||
|
||||
@@ -210,8 +210,10 @@ pub fn map_constructor<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
if !crate::iterator::is_callable(adder) {
|
||||
return NativeResult::Err(crate::error::create_type_error(vm, "Map.set is not callable"));
|
||||
}
|
||||
let key_si = vm.kernel_core().perm_interner().intern("0").0;
|
||||
let value_si = vm.kernel_core().perm_interner().intern("1").0;
|
||||
// entry 读取键按 ToPropertyKey 规范化:数组 entry 的元素区与对象 entry
|
||||
// 的 shape 链都走整数键,保证 `[k,v]` 与 `{0:k,1:v}` 两种形态都命中。
|
||||
let key_si = vm.property_key_si(JsValue::int(0));
|
||||
let value_si = vm.property_key_si(JsValue::int(1));
|
||||
if let Err(err) = crate::iterator::iterate_elements(vm, iterable, |vm, item| {
|
||||
if !item.is_object() {
|
||||
return Err(crate::error::create_type_error(vm, "iterator value is not an entry object"));
|
||||
|
||||
@@ -962,7 +962,8 @@ pub fn object_from_entries<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
JsValue::from_js_object(vm.session().builtin_world().object_proto.as_ptr() as *mut JsObject),
|
||||
));
|
||||
let target_val = JsValue::from_js_object(obj);
|
||||
let n: usize = unsafe { (*entries_ptr).prop_vec_len() };
|
||||
// entry 数组的元素存元素区(元素区之外才是命名属性区),按元素区长度迭代。
|
||||
let n: usize = unsafe { (*entries_ptr).array_prop_count } as usize;
|
||||
for i in 0..n {
|
||||
let pair_val = unsafe { (*entries_ptr).get_prop_at(i) };
|
||||
if !pair_val.is_object() {
|
||||
@@ -975,8 +976,8 @@ pub fn object_from_entries<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||
let pair = unsafe { &*pair_ptr };
|
||||
let key_val = pair.get_prop_at(0);
|
||||
let value_val = pair.get_prop_at(1);
|
||||
let key_str = oxide_runtime_api::to_string(key_val);
|
||||
let si = vm.kernel_core().perm_interner().intern(&key_str).0;
|
||||
// ToPropertyKey 语义建键:int/规范数字串/symbol 统一映射,避免数字键分裂。
|
||||
let si = vm.property_key_si(key_val);
|
||||
let promoted = vm.promote_if_needed_for_write_ptr(obj, value_val);
|
||||
let _ = vm.ordinary_set(unsafe { &mut *obj }, si, promoted, target_val);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user