feat: 事件目标弱引用注册表加三方法加原型链

This commit is contained in:
2026-10-10 09:06:08 +00:00
parent 8a8c3e9b9c
commit 6ecd3aed89
20 changed files with 890 additions and 123 deletions
@@ -0,0 +1,29 @@
//! EventTarget 监听器注册表的数据类型:`ListenerEntry`(单条监听器登记)与
//! `EventTargetState`(一个目标的监听器集合,注册表值)。
//!
//! 本类型落 `oxide_runtime_api`(`VmHost` trait 所在层):`et_register` /
//! `et_lookup` 的签名引用 `ListenerEntry`,而 trait 不依赖 `oxide_builtins`
//! (依赖方向 `runtime_api ← builtins`),故类型须落在 trait 可引用的层。
use oxide_types::value::JsValue;
/// 单条监听器登记:事件类型 si、回调函数、捕获标志、once 标志、属性 handler 标志。
///
/// `type_si` 是事件类型串的 perm intern 下标(同型同回调同 capture 的重复登记为
/// no-op)。`callback` 是回调函数(GC 对象边)。`is_attribute` 区分属性 handler
/// (`onmessage` 等)与 `addEventListener` 登记(首版恒 false,属性 handler 由后续
/// 任务接入)。
#[derive(Clone, Debug)]
pub struct ListenerEntry {
pub type_si: u32,
pub callback: JsValue,
pub capture: bool,
pub once: bool,
pub is_attribute: bool,
}
/// 一个 EventTarget 的监听器集合(per-realm 弱引用注册表的值)。
#[derive(Clone, Debug, Default)]
pub struct EventTargetState {
pub listeners: Vec<ListenerEntry>,
}
+24
View File
@@ -8,6 +8,8 @@ use oxide_types::mem::P;
use oxide_types::object::{Cell, JsObject, PropAttributes};
use oxide_types::value::JsValue;
use super::event_target::ListenerEntry;
/// shape 节点只读投影:shape forge 节点字段的中立镜像(免跨 crate 引用具体类型)。
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct ShapeNode {
@@ -473,4 +475,26 @@ pub trait VmHost {
/// - 列表元素为弱引用裸指针,调用方不得跨用户调用持有(GC 可释放
/// 通道对象,须在下一次使用前重新查表校验)。
fn bc_lookup(&self, name: &str) -> Vec<*mut JsObject>;
// EventTarget 监听器注册表(per-realm 弱引用,目标对象裸指针为键)
/// 把一条监听器登记追加到目标对象的注册表条目(无条目时新建)。
///
/// # 边界与前提
/// - `target` 为登记时刻的目标对象指针(弱引用,不保活);重复登记
/// (同 type + callback + capture)由调用方保证不发生。
/// # 副作用
/// - 写注册表(内部可变);`entry` 的 callback 是 GC 对象边,mark 期经根枚举标活。
fn et_register(&self, target: *mut JsObject, entry: ListenerEntry);
/// 从目标对象的注册表移除同 type + callback + capture 的监听器条目;
/// 不存在时 no-op。空集合条目随移除删除(不留空壳)。
///
/// # 副作用
/// - 写注册表(内部可变);幂等,重复移除不报错。
fn et_unregister(&self, target: *mut JsObject, type_si: u32, callback: JsValue, capture: bool);
/// 查目标对象的监听器条目列表(返回克隆;无条目为空列表)。
///
/// # 边界与前提
/// - 列表元素含 callback 的 GC 对象边,调用方不得跨用户调用持有
/// (GC 可回收目标对象,须在下一次使用前重新查表校验)。
fn et_lookup(&self, target: *mut JsObject) -> Vec<ListenerEntry>;
}
+3
View File
@@ -14,6 +14,8 @@
mod coercion;
/// 动态编译服务接口(`Vm` 经它解耦对编译器的直接依赖)。
pub mod compiler_service;
/// EventTarget 监听器注册表数据类型(`ListenerEntry` / `EventTargetState`)。
pub mod event_target;
/// builtins 依赖的 `VmHost` 能力面。
mod host;
/// builtin native 函数的三态返回值。
@@ -29,5 +31,6 @@ pub use coercion::{
ToPrimitiveHint,
};
pub use compiler_service::CompilerService;
pub use event_target::{EventTargetState, ListenerEntry};
pub use host::{ProtoKind, ShapeNode, VmHost};
pub use native_result::NativeResult;