From 3e61b573db1391fe52c8dfc27a7ae581e534c3d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=88=B1=E7=89=B9=E6=AF=8F=E7=BE=8A=E9=98=9F?= Date: Wed, 12 Aug 2026 12:50:53 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=20Symbol.species=20w?= =?UTF-8?q?ell-known=20symbol=20=E7=BB=91=E5=AE=9A=EF=BC=88Symbol.species?= =?UTF-8?q?=20=E8=A7=A3=E6=9E=90/=E9=94=AE=E6=A7=BD/=E5=86=85=E5=BB=BA?= =?UTF-8?q?=E5=AF=B9=E8=B1=A1=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/oxide_builtins/src/object.rs | 1 + crates/oxide_kernel/src/builtin.rs | 8 ++++++++ crates/oxide_kernel/src/kernel.rs | 7 +++++-- crates/oxide_runtime_api/src/lib.rs | 3 +++ crates/oxide_types/src/private_key.rs | 2 +- crates/oxide_vm/src/bindings/bind_symbol.rs | 4 ++++ 6 files changed, 22 insertions(+), 3 deletions(-) diff --git a/crates/oxide_builtins/src/object.rs b/crates/oxide_builtins/src/object.rs index 100e467..ffe3bb7 100644 --- a/crates/oxide_builtins/src/object.rs +++ b/crates/oxide_builtins/src/object.rs @@ -112,6 +112,7 @@ fn decode_symbol_key(vm: &H, key: u32) -> JsValue { 6 => world.sym_has_instance.as_ptr(), 7 => world.sym_match_all.as_ptr(), 8 => world.sym_async_iterator.as_ptr(), + 10 => world.sym_species.as_ptr(), _ => world.sym_to_string_tag.as_ptr(), }; return JsValue::from_js_object(ptr as *mut JsObject); diff --git a/crates/oxide_kernel/src/builtin.rs b/crates/oxide_kernel/src/builtin.rs index e494864..cf968ea 100644 --- a/crates/oxide_kernel/src/builtin.rs +++ b/crates/oxide_kernel/src/builtin.rs @@ -251,6 +251,7 @@ pub struct BuiltinWorld { pub sym_match_all: P, pub sym_async_iterator: P, pub sym_to_string_tag: P, + pub sym_species: P, pub temporal_object: P, pub temporal_now_object: P, pub instant_constructor: P, @@ -702,6 +703,7 @@ impl BuiltinWorld { BuiltinId::SymMatchAll => &self.sym_match_all, BuiltinId::SymAsyncIterator => &self.sym_async_iterator, BuiltinId::SymToStringTag => &self.sym_to_string_tag, + BuiltinId::SymSpecies => &self.sym_species, BuiltinId::TemporalObject => &self.temporal_object, BuiltinId::TemporalNowObject => &self.temporal_now_object, BuiltinId::InstantConstructor => &self.instant_constructor, @@ -760,6 +762,7 @@ impl BuiltinWorld { let sym_match_all = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())); let sym_async_iterator = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())); let sym_to_string_tag = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())); + let sym_species = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())); let temporal_object = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())); let temporal_now_object = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())); let (instant_proto, instant_constructor) = make_named_pair(string_forge, shape_forge, labels, "Instant"); @@ -846,6 +849,7 @@ impl BuiltinWorld { sym_match_all, sym_async_iterator, sym_to_string_tag, + sym_species, temporal_object, temporal_now_object, instant_constructor, @@ -936,6 +940,7 @@ impl BuiltinWorld { sym_match_all, sym_async_iterator, sym_to_string_tag, + sym_species, ) = if dirty.symbol_family { let (symbol_proto, symbol_constructor) = make_named_pair(string_forge, shape_forge, labels, "Symbol"); ( @@ -951,6 +956,7 @@ impl BuiltinWorld { P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())), P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())), P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())), + P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())), ) } else { ( @@ -966,6 +972,7 @@ impl BuiltinWorld { current.sym_match_all.clone(), current.sym_async_iterator.clone(), current.sym_to_string_tag.clone(), + current.sym_species.clone(), ) }; @@ -1177,6 +1184,7 @@ impl BuiltinWorld { sym_match_all, sym_async_iterator, sym_to_string_tag, + sym_species, temporal_object, temporal_now_object, instant_constructor, diff --git a/crates/oxide_kernel/src/kernel.rs b/crates/oxide_kernel/src/kernel.rs index b646e47..b9cde90 100644 --- a/crates/oxide_kernel/src/kernel.rs +++ b/crates/oxide_kernel/src/kernel.rs @@ -225,7 +225,7 @@ pub struct KernelSession { /// 维护注意:每个新增的 `BuiltinWorld` 对象字段都必须加到这里以及 /// `KernelSession::dirty_since_snapshot()`,以便选择性重置重建正确的 /// builtin 家族。 -pub const NUM_BUILTINS: usize = 85; +pub const NUM_BUILTINS: usize = 86; /// 内置对象枚举 id,与 `BuiltinWorld` 中的存储槽一一对应。 /// @@ -315,6 +315,7 @@ pub enum BuiltinId { DurationConstructor = 78, DurationProto = 79, SymToStringTag = 80, + SymSpecies = 85, ZonedDateTimeConstructor = 81, ZonedDateTimeProto = 82, PlainDateTimeConstructor = 83, @@ -405,6 +406,7 @@ impl BuiltinId { BuiltinId::DurationConstructor, BuiltinId::DurationProto, BuiltinId::SymToStringTag, + BuiltinId::SymSpecies, BuiltinId::ZonedDateTimeConstructor, BuiltinId::ZonedDateTimeProto, BuiltinId::PlainDateTimeConstructor, @@ -597,7 +599,8 @@ impl KernelSession { || gen(BuiltinId::SymHasInstance) != snap(BuiltinId::SymHasInstance) || gen(BuiltinId::SymMatchAll) != snap(BuiltinId::SymMatchAll) || gen(BuiltinId::SymAsyncIterator) != snap(BuiltinId::SymAsyncIterator) - || gen(BuiltinId::SymToStringTag) != snap(BuiltinId::SymToStringTag), + || gen(BuiltinId::SymToStringTag) != snap(BuiltinId::SymToStringTag) + || gen(BuiltinId::SymSpecies) != snap(BuiltinId::SymSpecies), math: gen(BuiltinId::MathObject) != snap(BuiltinId::MathObject), json: gen(BuiltinId::JsonObject) != snap(BuiltinId::JsonObject), date: gen(BuiltinId::DateConstructor) != snap(BuiltinId::DateConstructor) diff --git a/crates/oxide_runtime_api/src/lib.rs b/crates/oxide_runtime_api/src/lib.rs index feeb763..66f52c9 100644 --- a/crates/oxide_runtime_api/src/lib.rs +++ b/crates/oxide_runtime_api/src/lib.rs @@ -949,6 +949,8 @@ pub fn well_known_symbol_id(host: &H, ptr: *mut JsObject) -> Some(8) } else if std::ptr::eq(ptr, world.sym_to_string_tag.as_ptr()) { Some(9) + } else if std::ptr::eq(ptr, world.sym_species.as_ptr()) { + Some(10) } else { None } @@ -967,6 +969,7 @@ pub fn well_known_symbol_name(id: u32) -> Option<&'static str> { 7 => "Symbol.matchAll", 8 => "Symbol.asyncIterator", 9 => "Symbol.toStringTag", + 10 => "Symbol.species", _ => return None, }) } diff --git a/crates/oxide_types/src/private_key.rs b/crates/oxide_types/src/private_key.rs index 2c8f659..12b46c9 100644 --- a/crates/oxide_types/src/private_key.rs +++ b/crates/oxide_types/src/private_key.rs @@ -17,7 +17,7 @@ pub const PRIVATE_NAME_BASE: u32 = 0x8000_0000; pub const SYMBOL_KEY_BASE: u32 = 0xA000_0000; /// 保留给 well-known symbol 的键槽位数(位于 Symbol 键区间最低端)。 -pub const WELL_KNOWN_SYMBOL_COUNT: u32 = 10; +pub const WELL_KNOWN_SYMBOL_COUNT: u32 = 11; /// 用户 symbol 下标的保留位掩码(低 28 位)。 const SYMBOL_INDEX_MASK: u32 = 0x0FFF_FFFF; diff --git a/crates/oxide_vm/src/bindings/bind_symbol.rs b/crates/oxide_vm/src/bindings/bind_symbol.rs index 450c9e7..46c0359 100644 --- a/crates/oxide_vm/src/bindings/bind_symbol.rs +++ b/crates/oxide_vm/src/bindings/bind_symbol.rs @@ -77,6 +77,10 @@ pub fn bind_symbol(core: &Arc, session: &KernelSession, global: &mut "toStringTag", JsValue::from_js_object(session.builtin_world().sym_to_string_tag.as_ptr() as *mut JsObject), ), + ( + "species", + JsValue::from_js_object(session.builtin_world().sym_species.as_ptr() as *mut JsObject), + ), ] { bind_well_known_symbol(core, ctor, name, val); }