feat: Event 体系内核接线九 P 字段加 BuiltinId 加脏位加 ProtoKind

This commit is contained in:
2026-10-10 08:02:05 +00:00
parent ab16e9ce79
commit 9ecd573526
11 changed files with 224 additions and 28 deletions
Generated
+19 -19
View File
@@ -1160,7 +1160,7 @@ dependencies = [
[[package]]
name = "oxide_builtins"
version = "0.14.6"
version = "0.14.7"
dependencies = [
"chrono",
"fast-float",
@@ -1185,7 +1185,7 @@ dependencies = [
[[package]]
name = "oxide_bytecode"
version = "0.14.6"
version = "0.14.7"
dependencies = [
"num-bigint",
"oxide_log",
@@ -1193,7 +1193,7 @@ dependencies = [
[[package]]
name = "oxide_cfg"
version = "0.14.6"
version = "0.14.7"
dependencies = [
"oxide_bytecode",
"oxide_emit",
@@ -1204,7 +1204,7 @@ dependencies = [
[[package]]
name = "oxide_cli"
version = "0.14.6"
version = "0.14.7"
dependencies = [
"ansi_term",
"bumpalo",
@@ -1226,7 +1226,7 @@ dependencies = [
[[package]]
name = "oxide_code_cache"
version = "0.14.6"
version = "0.14.7"
dependencies = [
"lru",
"oxide_bytecode",
@@ -1235,7 +1235,7 @@ dependencies = [
[[package]]
name = "oxide_compiler"
version = "0.14.6"
version = "0.14.7"
dependencies = [
"oxide_bytecode",
"oxide_cfg",
@@ -1255,7 +1255,7 @@ dependencies = [
[[package]]
name = "oxide_dce"
version = "0.14.6"
version = "0.14.7"
dependencies = [
"oxide_bytecode",
"oxide_cfg",
@@ -1269,7 +1269,7 @@ dependencies = [
[[package]]
name = "oxide_emit"
version = "0.14.6"
version = "0.14.7"
dependencies = [
"num-bigint",
"oxc_allocator",
@@ -1284,7 +1284,7 @@ dependencies = [
[[package]]
name = "oxide_engine"
version = "0.14.6"
version = "0.14.7"
dependencies = [
"oxide_bytecode",
"oxide_compiler",
@@ -1296,7 +1296,7 @@ dependencies = [
[[package]]
name = "oxide_ir"
version = "0.14.6"
version = "0.14.7"
dependencies = [
"oxide_bytecode",
"oxide_log",
@@ -1305,7 +1305,7 @@ dependencies = [
[[package]]
name = "oxide_kernel"
version = "0.14.6"
version = "0.14.7"
dependencies = [
"bumpalo",
"dashmap",
@@ -1319,7 +1319,7 @@ dependencies = [
[[package]]
name = "oxide_liveness"
version = "0.14.6"
version = "0.14.7"
dependencies = [
"oxide_bytecode",
"oxide_cfg",
@@ -1331,7 +1331,7 @@ dependencies = [
[[package]]
name = "oxide_log"
version = "0.14.6"
version = "0.14.7"
dependencies = [
"tracing",
"tracing-appender",
@@ -1340,7 +1340,7 @@ dependencies = [
[[package]]
name = "oxide_parser"
version = "0.14.6"
version = "0.14.7"
dependencies = [
"oxc_allocator",
"oxc_ast",
@@ -1355,7 +1355,7 @@ dependencies = [
[[package]]
name = "oxide_regalloc"
version = "0.14.6"
version = "0.14.7"
dependencies = [
"oxide_bytecode",
"oxide_cfg",
@@ -1371,7 +1371,7 @@ dependencies = [
[[package]]
name = "oxide_runtime_api"
version = "0.14.6"
version = "0.14.7"
dependencies = [
"num-bigint",
"num-traits",
@@ -1384,7 +1384,7 @@ dependencies = [
[[package]]
name = "oxide_test262"
version = "0.14.6"
version = "0.14.7"
dependencies = [
"oxide_bytecode",
"oxide_compiler",
@@ -1402,7 +1402,7 @@ dependencies = [
[[package]]
name = "oxide_types"
version = "0.14.6"
version = "0.14.7"
dependencies = [
"bumpalo",
"dashmap",
@@ -1415,7 +1415,7 @@ dependencies = [
[[package]]
name = "oxide_vm"
version = "0.14.6"
version = "0.14.7"
dependencies = [
"bumpalo",
"chrono",
+1 -1
View File
@@ -23,7 +23,7 @@ members = [
]
[workspace.package]
version = "0.14.6"
version = "0.14.7"
edition = "2021"
license = "MIT"
rust-version = "1.80"
@@ -514,6 +514,20 @@ impl BuiltinWorld {
let broadcast_channel_proto = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
let broadcast_channel_constructor = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
// Event 体系九个内核接线占位(空对象):Event / MessageEvent /
// ErrorEvent / CustomEvent 四枚原型与构造器对加 EventTarget 原型,
// 真实本体与原型链连线由绑定层后续任务填充,本处只预留槽位使快照/
// 脏检查/收尾枚举覆盖到这九枚 P 字段。
let event_proto = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
let event_constructor = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
let message_event_proto = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
let message_event_constructor = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
let error_event_proto = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
let error_event_constructor = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
let custom_event_proto = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
let custom_event_constructor = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
let event_target_proto = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
let (date_proto, date_constructor) = make_named_pair(string_forge, shape_forge, labels, "Date");
let (set_proto, set_constructor) = make_named_pair(string_forge, shape_forge, labels, "Set");
let (map_proto, map_constructor) = make_named_pair(string_forge, shape_forge, labels, "Map");
@@ -665,6 +679,15 @@ impl BuiltinWorld {
message_channel_constructor,
broadcast_channel_proto,
broadcast_channel_constructor,
event_proto,
event_constructor,
message_event_proto,
message_event_constructor,
error_event_proto,
error_event_constructor,
custom_event_proto,
custom_event_constructor,
event_target_proto,
leaked_objects: std::cell::RefCell::new(Vec::new()),
};
wire_builtin_world_links(&world);
@@ -418,6 +418,43 @@ impl BuiltinWorld {
(current.broadcast_channel_proto.clone(), current.broadcast_channel_constructor.clone())
};
// Event 体系九个占位:脏则换新空对象(与全量构造同形),未脏沿用旧指针。
let (
event_proto,
event_constructor,
message_event_proto,
message_event_constructor,
error_event_proto,
error_event_constructor,
custom_event_proto,
custom_event_constructor,
event_target_proto,
) = if dirty.event {
(
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())),
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())),
P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
)
} else {
(
current.event_proto.clone(),
current.event_constructor.clone(),
current.message_event_proto.clone(),
current.message_event_constructor.clone(),
current.error_event_proto.clone(),
current.error_event_constructor.clone(),
current.custom_event_proto.clone(),
current.custom_event_constructor.clone(),
current.event_target_proto.clone(),
)
};
// 迭代器原型与资源栈原型依赖 Object.prototype(链到其上):object 家族重建时
// 一并重建,否则旧原型链指向已释放的 object_proto。
let (
@@ -572,6 +609,15 @@ impl BuiltinWorld {
message_channel_constructor,
broadcast_channel_proto,
broadcast_channel_constructor,
event_proto,
event_constructor,
message_event_proto,
message_event_constructor,
error_event_proto,
error_event_constructor,
custom_event_proto,
custom_event_constructor,
event_target_proto,
leaked_objects: std::cell::RefCell::new(Vec::new()),
};
wire_builtin_world_links(&world);
+48 -3
View File
@@ -1,5 +1,5 @@
//! 注册表职责:BuiltinWorld 结构(99 固定 P 字段 + stub 族 + Box::into_raw
//! 登记表)、get_by_id 派发、all_p_fields 99 元组枚举(新增 P 字段四处同步
//! 注册表职责:BuiltinWorld 结构(108 固定 P 字段 + stub 族 + Box::into_raw
//! 登记表)、get_by_id 派发、all_p_fields 108 元组枚举(新增 P 字段四处同步
//! 约束载体)与登记表 track/find/inherit/teardown。
use oxide_types::mem::P;
@@ -150,6 +150,33 @@ pub struct BuiltinWorld {
/// `BroadcastChannel` 构造器槽位:纯内核接线占位(空对象),真实构造器
/// 本体由绑定层后续任务填充。
pub broadcast_channel_constructor: P<JsObject>,
/// `Event.prototype` 槽位:纯内核接线占位(空对象),真实原型本体
/// 与构造器对由绑定层后续任务填充;脏家族位为 `event`。
pub event_proto: P<JsObject>,
/// `Event` 构造器槽位:纯内核接线占位(空对象),真实构造器本体由
/// 绑定层后续任务填充。
pub event_constructor: P<JsObject>,
/// `MessageEvent.prototype` 槽位:纯内核接线占位(空对象),真实原型
/// 本体与构造器对由绑定层后续任务填充。
pub message_event_proto: P<JsObject>,
/// `MessageEvent` 构造器槽位:纯内核接线占位(空对象),真实构造器
/// 本体由绑定层后续任务填充。
pub message_event_constructor: P<JsObject>,
/// `ErrorEvent.prototype` 槽位:纯内核接线占位(空对象),真实原型
/// 本体与构造器对由绑定层后续任务填充。
pub error_event_proto: P<JsObject>,
/// `ErrorEvent` 构造器槽位:纯内核接线占位(空对象),真实构造器
/// 本体由绑定层后续任务填充。
pub error_event_constructor: P<JsObject>,
/// `CustomEvent.prototype` 槽位:纯内核接线占位(空对象),真实原型
/// 本体与构造器对由绑定层后续任务填充。
pub custom_event_proto: P<JsObject>,
/// `CustomEvent` 构造器槽位:纯内核接线占位(空对象),真实构造器
/// 本体由绑定层后续任务填充。
pub custom_event_constructor: P<JsObject>,
/// `EventTarget.prototype` 槽位:纯内核接线占位(空对象),真实原型
/// 本体由绑定层后续任务填充(EventTarget 无构造器,仅暴露原型)。
pub event_target_proto: P<JsObject>,
/// 释放登记表(`Box::into_raw` 对象的清单,session 收尾统一释放,非内存泄漏):
/// 绑定层经 `Box::into_raw` 持有的函数/宿主对象(方法 wrapper、访问器、
/// 错误构造器、Reflect/Iterator、内建原型构造器、`$262` 宿主等)。
@@ -380,7 +407,7 @@ impl BuiltinWorld {
/// session 收尾(`teardown_heap_data`)与选择性重建收尾(`retire_replaced`)
/// 的 P 字段枚举唯一入口:`BuiltinWorld` 新增 P 字段须在此同步补一行,否则
/// 收尾时该字段属性区无法释放、重建原型槽改写/释放漏掉该字段。
pub(crate) fn all_p_fields(&self) -> [&P<JsObject>; 99] {
pub(crate) fn all_p_fields(&self) -> [&P<JsObject>; 108] {
[
&self.object_proto,
&self.array_proto,
@@ -481,6 +508,15 @@ impl BuiltinWorld {
&self.message_channel_constructor,
&self.broadcast_channel_proto,
&self.broadcast_channel_constructor,
&self.event_proto,
&self.event_constructor,
&self.message_event_proto,
&self.message_event_constructor,
&self.error_event_proto,
&self.error_event_constructor,
&self.custom_event_proto,
&self.custom_event_constructor,
&self.event_target_proto,
]
}
@@ -618,6 +654,15 @@ impl BuiltinWorld {
BuiltinId::MessageChannelCtor => &self.message_channel_constructor,
BuiltinId::BroadcastChannelProto => &self.broadcast_channel_proto,
BuiltinId::BroadcastChannelCtor => &self.broadcast_channel_constructor,
BuiltinId::EventProto => &self.event_proto,
BuiltinId::EventCtor => &self.event_constructor,
BuiltinId::MessageEventProto => &self.message_event_proto,
BuiltinId::MessageEventCtor => &self.message_event_constructor,
BuiltinId::ErrorEventProto => &self.error_event_proto,
BuiltinId::ErrorEventCtor => &self.error_event_constructor,
BuiltinId::CustomEventProto => &self.custom_event_proto,
BuiltinId::CustomEventCtor => &self.custom_event_constructor,
BuiltinId::EventTargetProto => &self.event_target_proto,
}
}
}
+35 -5
View File
@@ -1,4 +1,4 @@
//! 内置对象 id 枚举(`BuiltinId` 89 变体 + `ALL` 顺序钉表)、世代快照
//! 内置对象 id 枚举(`BuiltinId` 98 变体 + `ALL` 顺序钉表)、世代快照
//! (`BuiltinSnapshot`)与按家族划分的脏标记位集(`BuiltinDirtySet`);
//! `NUM_BUILTINS` 文档承载"新增 BuiltinWorld 字段须同步"四处约束注记。
@@ -11,7 +11,7 @@ use crate::builtin::BuiltinWorld;
/// 维护注意:每个新增的 `BuiltinWorld` 对象字段都必须加到这里以及
/// `KernelSession::dirty_since_snapshot()`,以便选择性重置重建正确的
/// builtin 家族。
pub const NUM_BUILTINS: usize = 89;
pub const NUM_BUILTINS: usize = 98;
/// 内置对象枚举 id,与 `BuiltinWorld` 中的存储槽一一对应。
///
@@ -109,6 +109,15 @@ pub enum BuiltinId {
MessageChannelCtor = 86,
BroadcastChannelProto = 87,
BroadcastChannelCtor = 88,
EventProto = 89,
EventCtor = 90,
MessageEventProto = 91,
MessageEventCtor = 92,
ErrorEventProto = 93,
ErrorEventCtor = 94,
CustomEventProto = 95,
CustomEventCtor = 96,
EventTargetProto = 97,
}
impl BuiltinId {
@@ -205,6 +214,15 @@ impl BuiltinId {
BuiltinId::MessageChannelCtor,
BuiltinId::BroadcastChannelProto,
BuiltinId::BroadcastChannelCtor,
BuiltinId::EventProto,
BuiltinId::EventCtor,
BuiltinId::MessageEventProto,
BuiltinId::MessageEventCtor,
BuiltinId::ErrorEventProto,
BuiltinId::ErrorEventCtor,
BuiltinId::CustomEventProto,
BuiltinId::CustomEventCtor,
BuiltinId::EventTargetProto,
];
}
@@ -282,6 +300,7 @@ pub struct BuiltinDirtySet {
pub console: bool,
pub message_channel: bool,
pub broadcast_channel: bool,
pub event: bool,
}
impl BuiltinDirtySet {
@@ -317,6 +336,7 @@ impl BuiltinDirtySet {
console: true,
message_channel: true,
broadcast_channel: true,
event: true,
}
}
@@ -346,6 +366,7 @@ impl BuiltinDirtySet {
|| self.console
|| self.message_channel
|| self.broadcast_channel
|| self.event
}
/// 是否存在任何污染(builtin world 或 global object)。
@@ -358,13 +379,13 @@ impl BuiltinDirtySet {
mod tests {
use super::*;
/// 槽对齐面:ALL 表与判别值 0..88 严格同序,快照数组随 NUM_BUILTINS
/// 槽对齐面:ALL 表与判别值 0..97 严格同序,快照数组随 NUM_BUILTINS
/// 自动扩维、逐槽对齐。
#[test]
fn builtin_snapshot_all_slots_aligned() {
assert_eq!(NUM_BUILTINS, 89);
assert_eq!(NUM_BUILTINS, 98);
assert_eq!(BuiltinId::ALL.len(), NUM_BUILTINS);
for i in 0..88usize {
for i in 0..97usize {
assert_eq!(BuiltinId::ALL[i] as usize, i);
}
assert_eq!(BuiltinId::ALL[81], BuiltinId::SharedArrayBufferProto);
@@ -375,6 +396,15 @@ mod tests {
assert_eq!(BuiltinId::ALL[86], BuiltinId::MessageChannelCtor);
assert_eq!(BuiltinId::ALL[87], BuiltinId::BroadcastChannelProto);
assert_eq!(BuiltinId::ALL[88], BuiltinId::BroadcastChannelCtor);
assert_eq!(BuiltinId::ALL[89], BuiltinId::EventProto);
assert_eq!(BuiltinId::ALL[90], BuiltinId::EventCtor);
assert_eq!(BuiltinId::ALL[91], BuiltinId::MessageEventProto);
assert_eq!(BuiltinId::ALL[92], BuiltinId::MessageEventCtor);
assert_eq!(BuiltinId::ALL[93], BuiltinId::ErrorEventProto);
assert_eq!(BuiltinId::ALL[94], BuiltinId::ErrorEventCtor);
assert_eq!(BuiltinId::ALL[95], BuiltinId::CustomEventProto);
assert_eq!(BuiltinId::ALL[96], BuiltinId::CustomEventCtor);
assert_eq!(BuiltinId::ALL[97], BuiltinId::EventTargetProto);
// 快照经 session 全量构造路径采集,generations 数组维度 = 槽数。
use crate::kernel::{KernelConfig, KernelCore, KernelSession};
@@ -200,6 +200,15 @@ impl KernelSession {
|| gen(BuiltinId::MessageChannelCtor) != snap(BuiltinId::MessageChannelCtor),
broadcast_channel: gen(BuiltinId::BroadcastChannelProto) != snap(BuiltinId::BroadcastChannelProto)
|| gen(BuiltinId::BroadcastChannelCtor) != snap(BuiltinId::BroadcastChannelCtor),
event: gen(BuiltinId::EventProto) != snap(BuiltinId::EventProto)
|| gen(BuiltinId::EventCtor) != snap(BuiltinId::EventCtor)
|| gen(BuiltinId::MessageEventProto) != snap(BuiltinId::MessageEventProto)
|| gen(BuiltinId::MessageEventCtor) != snap(BuiltinId::MessageEventCtor)
|| gen(BuiltinId::ErrorEventProto) != snap(BuiltinId::ErrorEventProto)
|| gen(BuiltinId::ErrorEventCtor) != snap(BuiltinId::ErrorEventCtor)
|| gen(BuiltinId::CustomEventProto) != snap(BuiltinId::CustomEventProto)
|| gen(BuiltinId::CustomEventCtor) != snap(BuiltinId::CustomEventCtor)
|| gen(BuiltinId::EventTargetProto) != snap(BuiltinId::EventTargetProto),
};
// wrapper 本体被写不落在任何家族位上(写的是 wrapper 自身而非所属 P
// 对象):收缩为全脏,强制重建全部家族与 global,使被写的可复用
+6
View File
@@ -104,6 +104,12 @@ pub enum ProtoKind {
MessagePortProto,
// 广播通道原型
BroadcastChannelProto,
// 事件体系原型(EventTarget 原型不占 ProtoKind:builtins 不读它,
// 绑定层直接访问 world 的 event_target_proto 槽)
EventProto,
MessageEventProto,
ErrorEventProto,
CustomEventProto,
}
/// builtins 依赖的 `Vm` 能力集合。
@@ -0,0 +1,28 @@
//! Event 体系绑定:本文件是内核接线占位(零行为变化)。九枚 P 字段
//! (Event / MessageEvent / ErrorEvent / CustomEvent 四枚原型与构造器对加
//! EventTarget 原型)当前是空对象,本函数为它们的绑定入口预留,真实构造器 /
//! 原型方法 / 原型链连线由后续任务就地填充(不新建对象——P 字段本身就是槽位,
//! 快照 / 脏检查 / 收尾枚举已覆盖)。
use std::sync::Arc;
use oxide_kernel::kernel::{KernelCore, KernelSession};
use oxide_types::object::JsObject;
/// Event 体系绑定入口(当前为空占位)。
///
/// # 幂等
/// 本函数从三条路径到达:`init_kernel_builtins`(占位是空对象)、
/// `rebind_dirty_builtins` 的 `event` 分支(占位是重建后的空对象)、
/// global-dirty 路径(占位可能已填满)。本函数当前不写任何槽位,空操作天然
/// 幂等;后续任务就地填充时,各槽写须沿用 `lookup_position` 前置守卫
/// (有槽即跳过),保持与 `bind_broadcast_channel` 同型的幂等契约。
///
/// # 边界
/// 九枚 P 字段是空对象占位,本函数不读不写,行为与未调用一致;
/// EventTarget 原型不占 ProtoKind(builtins 不读它),绑定层后续直接访问
/// `world.event_target_proto` 槽。
///
/// `core` / `session` / `global` / `realm_id` 当前未使用,保留签名与其他
/// 绑定函数一致,供后续任务就地填充时直接取用。
pub fn bind_event(_core: &Arc<KernelCore>, _session: &KernelSession, _global: &mut JsObject, _realm_id: u32) {}
+5
View File
@@ -26,6 +26,8 @@ pub mod bind_date;
pub mod bind_disposable_stack;
/// Error 家族构造器与原型的 native 方法绑定(含各子类型构造器创建)。
pub mod bind_error;
/// Event 体系绑定入口(当前为空占位,九枚 P 字段由后续任务就地填充)。
pub mod bind_event;
/// Function 构造器与原型的 native 方法绑定。
pub mod bind_function;
/// global 对象上的普通全局函数(parseInt、isNaN 等)绑定。
@@ -1343,6 +1345,9 @@ pub fn rebind_dirty_builtins(
if dirty.map_or(true, |d| d.broadcast_channel) {
bind_broadcast_channel::bind_broadcast_channel(core, session, global, realm_id);
}
if dirty.map_or(true, |d| d.event) {
bind_event::bind_event(core, session, global, realm_id);
}
if dirty.map_or(true, |d| d.console) {
bind_console::bind_console(core, session, global);
}
+4
View File
@@ -144,6 +144,10 @@ impl oxide_runtime_api::VmHost for Vm {
ProtoKind::BigUint64ArrayConstructor => &world.biguint64array_constructor,
ProtoKind::MessagePortProto => &world.message_port_proto,
ProtoKind::BroadcastChannelProto => &world.broadcast_channel_proto,
ProtoKind::EventProto => &world.event_proto,
ProtoKind::MessageEventProto => &world.message_event_proto,
ProtoKind::ErrorEventProto => &world.error_event_proto,
ProtoKind::CustomEventProto => &world.custom_event_proto,
};
P::as_ptr(p) as *mut JsObject
}