From a18a6323e68fe078d7d6f52990b6e6a1e82bbee2 Mon Sep 17 00:00:00 2001 From: pjh456 <147148383@qq.com> Date: Wed, 23 Sep 2026 15:27:47 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20bind=5Fconstructor=20=E5=AE=8F=E8=A1=A5?= =?UTF-8?q?=20length=20=E6=8F=8F=E8=BF=B0=E7=AC=A6=20meta?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/oxide_vm/src/bindings/bind_date.rs | 9 ++++++++- crates/oxide_vm/src/bindings/bind_map.rs | 2 +- crates/oxide_vm/src/bindings/bind_set.rs | 2 +- crates/oxide_vm/src/bindings/bind_string.rs | 7 +++++++ crates/oxide_vm/src/bindings/bind_symbol.rs | 2 +- crates/oxide_vm/src/bindings/mod.rs | 4 ++++ crates/oxide_vm/tests/builtins_array_tests.rs | 12 ++++++++++++ crates/oxide_vm/tests/builtins_date_tests.rs | 13 +++++++++++++ crates/oxide_vm/tests/builtins_map_tests.rs | 13 +++++++++++++ crates/oxide_vm/tests/builtins_set_tests.rs | 13 +++++++++++++ crates/oxide_vm/tests/builtins_string_tests.rs | 13 +++++++++++++ crates/oxide_vm/tests/builtins_symbol_tests.rs | 13 +++++++++++++ 12 files changed, 99 insertions(+), 4 deletions(-) diff --git a/crates/oxide_vm/src/bindings/bind_date.rs b/crates/oxide_vm/src/bindings/bind_date.rs index 1e83eae0..3864455b 100644 --- a/crates/oxide_vm/src/bindings/bind_date.rs +++ b/crates/oxide_vm/src/bindings/bind_date.rs @@ -2,7 +2,7 @@ use std::sync::Arc; use crate::bindings::{apply_binding_table, bind_global_value, configure_native_constructor}; use oxide_kernel::kernel::{KernelCore, KernelSession}; -use oxide_types::object::JsObject; +use oxide_types::object::{JsObject, PropAttributes}; use oxide_types::value::JsValue; /// 把 Date 构造器与原型方法绑定到 global。 @@ -13,6 +13,13 @@ pub fn bind_date(core: &Arc, session: &KernelSession, global: &mut J let proto = unsafe { &mut *proto_ptr }; configure_native_constructor(ctor, oxide_builtins::date::date_constructor:: as *const (), 7); + // Date.length = 7,描述符 { writable:false, enumerable:false, configurable:true }。 + let length_si = core.perm_interner().intern("length").0; + let length_shape = core.shape_forge().make_shape(ctor.shape_id(), length_si); + ctor.set_shape_id(length_shape); + ctor.ensure_hash_props().push(JsValue::int(7)); + let length_pos = ctor.hash_props_vec().map_or(0, |v| v.len() as u32).saturating_sub(1); + ctor.set_data_meta(length_pos, PropAttributes::new(false, false, true)); apply_binding_table( session.builtin_world(), diff --git a/crates/oxide_vm/src/bindings/bind_map.rs b/crates/oxide_vm/src/bindings/bind_map.rs index 0dc79adb..d511a381 100644 --- a/crates/oxide_vm/src/bindings/bind_map.rs +++ b/crates/oxide_vm/src/bindings/bind_map.rs @@ -59,5 +59,5 @@ pub fn bind_map(core: &Arc, session: &KernelSession, global: &mut Js &[("groupBy", oxide_builtins::map::map_group_by:: as *const (), 2)], ); - bind_constructor!(core, global, "Map", ctor_ptr, oxide_builtins::map::map_constructor::, 1, hash: true); + bind_constructor!(core, global, "Map", ctor_ptr, oxide_builtins::map::map_constructor::, 0, hash: true); } diff --git a/crates/oxide_vm/src/bindings/bind_set.rs b/crates/oxide_vm/src/bindings/bind_set.rs index fa841105..e9a809c7 100644 --- a/crates/oxide_vm/src/bindings/bind_set.rs +++ b/crates/oxide_vm/src/bindings/bind_set.rs @@ -64,5 +64,5 @@ pub fn bind_set(core: &Arc, session: &KernelSession, global: &mut Js oxide_builtins::array::array_species_get:: as *const (), ); - bind_constructor!(core, global, "Set", ctor_ptr, oxide_builtins::set::set_constructor::, 1, hash: true); + bind_constructor!(core, global, "Set", ctor_ptr, oxide_builtins::set::set_constructor::, 0, hash: true); } diff --git a/crates/oxide_vm/src/bindings/bind_string.rs b/crates/oxide_vm/src/bindings/bind_string.rs index ce73c18c..b1ba9387 100644 --- a/crates/oxide_vm/src/bindings/bind_string.rs +++ b/crates/oxide_vm/src/bindings/bind_string.rs @@ -56,6 +56,13 @@ pub fn bind_string(core: &Arc, session: &KernelSession, global: &mut let ctor_ptr = session.builtin_world().string_constructor.as_ptr() as *mut JsObject; let ctor = unsafe { &mut *ctor_ptr }; configure_native_constructor(ctor, oxide_builtins::string::string_constructor:: as *const (), 1); + // String.length = 1,描述符 { writable:false, enumerable:false, configurable:true }。 + let length_si = core.perm_interner().intern("length").0; + let length_shape = core.shape_forge().make_shape(ctor.shape_id(), length_si); + ctor.set_shape_id(length_shape); + ctor.ensure_hash_props().push(JsValue::int(1)); + let length_pos = ctor.hash_props_vec().map_or(0, |v| v.len() as u32).saturating_sub(1); + ctor.set_data_meta(length_pos, PropAttributes::new(false, false, true)); let proto_ptr = session.builtin_world().string_proto.as_ptr() as *mut JsObject; let proto = unsafe { &mut *proto_ptr }; diff --git a/crates/oxide_vm/src/bindings/bind_symbol.rs b/crates/oxide_vm/src/bindings/bind_symbol.rs index f2941859..ecc36910 100644 --- a/crates/oxide_vm/src/bindings/bind_symbol.rs +++ b/crates/oxide_vm/src/bindings/bind_symbol.rs @@ -52,7 +52,7 @@ pub fn bind_symbol(core: &Arc, session: &KernelSession, global: &mut bind_well_known_symbol(core, ctor, name, JsValue::symbol(id as u32)); } - bind_constructor!(core, global, "Symbol", ctor_ptr, oxide_builtins::symbol::symbol_constructor::, 1, hash: true); + bind_constructor!(core, global, "Symbol", ctor_ptr, oxide_builtins::symbol::symbol_constructor::, 0, hash: true); } fn bind_well_known_symbol(core: &Arc, ctor: &mut JsObject, name: &str, val: JsValue) { diff --git a/crates/oxide_vm/src/bindings/mod.rs b/crates/oxide_vm/src/bindings/mod.rs index 7b58ef57..3f1ebc61 100644 --- a/crates/oxide_vm/src/bindings/mod.rs +++ b/crates/oxide_vm/src/bindings/mod.rs @@ -101,6 +101,10 @@ macro_rules! bind_constructor { let length_shape = $core.shape_forge().make_shape(ctor.shape_id(), length_si); ctor.set_shape_id(length_shape); ctor.ensure_hash_props().push($crate::JsValue::int($nargs as i32)); + // length 描述符 { writable:false, enumerable:false, configurable:true } + // (规范构造器通用面;不写 meta 缺省全枚举会泄漏进 Object.keys)。 + let length_pos = ctor.hash_props_vec().map_or(0, |v| v.len() as u32).saturating_sub(1); + ctor.set_data_meta(length_pos, oxide_types::object::PropAttributes::new(false, false, true)); }}; } diff --git a/crates/oxide_vm/tests/builtins_array_tests.rs b/crates/oxide_vm/tests/builtins_array_tests.rs index 556c94f1..61fe4464 100644 --- a/crates/oxide_vm/tests/builtins_array_tests.rs +++ b/crates/oxide_vm/tests/builtins_array_tests.rs @@ -458,3 +458,15 @@ fn array_is_array_rejects_prototype_inherited_object() { let (_vm, result) = eval("Array.isArray([])").unwrap(); assert_eq!(result, JsValue::bool(true)); } + +#[test] +fn array_length_descriptor() { + // Array.length = 1,描述符 { writable:false, enumerable:false, configurable:true }。 + let (vm, r) = eval( + "var d = Object.getOwnPropertyDescriptor(Array, 'length'); \ + d.value === 1 && d.writable === false && d.enumerable === false && d.configurable === true", + ) + .unwrap(); + let _ = vm; + assert!(r.as_bool()); +} diff --git a/crates/oxide_vm/tests/builtins_date_tests.rs b/crates/oxide_vm/tests/builtins_date_tests.rs index 117713d0..6e059b9d 100644 --- a/crates/oxide_vm/tests/builtins_date_tests.rs +++ b/crates/oxide_vm/tests/builtins_date_tests.rs @@ -580,3 +580,16 @@ fn date_set_utc_hours_valid_kept() { let r = eval(&mut vm, "var d = new Date(0); d.setUTCHours(13); d.getUTCHours()").unwrap(); assert_eq!(r.as_double() as i64, 13); } + +#[test] +fn date_length_descriptor() { + // Date.length = 7,描述符 { writable:false, enumerable:false, configurable:true }。 + let mut vm = Vm::new(); + let r = eval( + &mut vm, + "var d = Object.getOwnPropertyDescriptor(Date, 'length'); \ + d.value === 7 && d.writable === false && d.enumerable === false && d.configurable === true", + ) + .unwrap(); + assert!(r.as_bool()); +} diff --git a/crates/oxide_vm/tests/builtins_map_tests.rs b/crates/oxide_vm/tests/builtins_map_tests.rs index 777f0933..84ac213b 100644 --- a/crates/oxide_vm/tests/builtins_map_tests.rs +++ b/crates/oxide_vm/tests/builtins_map_tests.rs @@ -268,3 +268,16 @@ fn map_get_or_insert_length_and_name() { .unwrap(); assert!(r.as_bool()); } + +#[test] +fn map_length_descriptor() { + // Map.length = 0,描述符 { writable:false, enumerable:false, configurable:true }。 + let mut vm = Vm::new(); + let r = eval( + &mut vm, + "var d = Object.getOwnPropertyDescriptor(Map, 'length'); \ + d.value === 0 && d.writable === false && d.enumerable === false && d.configurable === true", + ) + .unwrap(); + assert!(r.as_bool()); +} diff --git a/crates/oxide_vm/tests/builtins_set_tests.rs b/crates/oxide_vm/tests/builtins_set_tests.rs index 6306cbf7..40978867 100644 --- a/crates/oxide_vm/tests/builtins_set_tests.rs +++ b/crates/oxide_vm/tests/builtins_set_tests.rs @@ -226,3 +226,16 @@ fn set_object_key_identity() { let r = eval(&mut vm, "var o = { a: 1 }; var s = new Set(); s.add(o); s.has(o) && !s.has({ a: 1 })").unwrap(); assert!(r.as_bool()); } + +#[test] +fn set_length_descriptor() { + // Set.length = 0,描述符 { writable:false, enumerable:false, configurable:true }。 + let mut vm = Vm::new(); + let r = eval( + &mut vm, + "var d = Object.getOwnPropertyDescriptor(Set, 'length'); \ + d.value === 0 && d.writable === false && d.enumerable === false && d.configurable === true", + ) + .unwrap(); + assert!(r.as_bool()); +} diff --git a/crates/oxide_vm/tests/builtins_string_tests.rs b/crates/oxide_vm/tests/builtins_string_tests.rs index e1f40754..aa287248 100644 --- a/crates/oxide_vm/tests/builtins_string_tests.rs +++ b/crates/oxide_vm/tests/builtins_string_tests.rs @@ -1672,3 +1672,16 @@ fn string_repeat_count_range_error() { let err = eval(&mut vm, "'ab'.repeat(Infinity)").unwrap_err(); assert!(err.contains("RangeError"), "got: {}", err); } + +#[test] +fn string_length_descriptor() { + // String.length = 1,描述符 { writable:false, enumerable:false, configurable:true }。 + let mut vm = Vm::new(); + let r = eval( + &mut vm, + "var d = Object.getOwnPropertyDescriptor(String, 'length'); \ + d.value === 1 && d.writable === false && d.enumerable === false && d.configurable === true", + ) + .unwrap(); + assert!(r.as_bool()); +} diff --git a/crates/oxide_vm/tests/builtins_symbol_tests.rs b/crates/oxide_vm/tests/builtins_symbol_tests.rs index 7184a949..96c863a6 100644 --- a/crates/oxide_vm/tests/builtins_symbol_tests.rs +++ b/crates/oxide_vm/tests/builtins_symbol_tests.rs @@ -356,3 +356,16 @@ fn symbol_proto_direct_description_access_throws_type_error() { .unwrap(); assert!(result.as_bool()); } + +#[test] +fn symbol_length_descriptor() { + // Symbol.length = 0,描述符 { writable:false, enumerable:false, configurable:true }。 + let mut vm = Vm::new(); + let r = eval( + &mut vm, + "var d = Object.getOwnPropertyDescriptor(Symbol, 'length'); \ + d.value === 0 && d.writable === false && d.enumerable === false && d.configurable === true", + ) + .unwrap(); + assert!(r.as_bool()); +}