mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
349 lines
16 KiB
Rust
349 lines
16 KiB
Rust
//! Event 体系绑定:就地填充 `event_constructor` / `event_proto` 两枚 P 字段
|
||
//! 占位(构造器本体、原型方法、原型 getter 与 Event 常量),并绑全局 `Event`;
|
||
//! 就地填充 `message_event_constructor` / `message_event_proto` 两枚 P 字段
|
||
//! 占位(构造器本体与原型 getter),并绑全局 `MessageEvent`;就地填充
|
||
//! `error_event_constructor` / `error_event_proto` 两枚 P 字段占位(构造器
|
||
//! 本体与原型 getter),并绑全局 `ErrorEvent`。
|
||
//!
|
||
//! 九枚 P 字段中其余两枚(CustomEvent 一对)由后续子任务就地填充,本函数
|
||
//! 不读不写。
|
||
|
||
use std::sync::Arc;
|
||
|
||
use crate::bind_constructor;
|
||
use crate::bindings::{apply_binding_table, bind_accessor_getter, configure_native_constructor};
|
||
use oxide_kernel::kernel::{KernelCore, KernelSession};
|
||
use oxide_types::object::{JsObject, PropAttributes};
|
||
use oxide_types::value::JsValue;
|
||
|
||
/// 把 Event / MessageEvent / ErrorEvent 构造器及原型方法绑定到 global。
|
||
///
|
||
/// `event_constructor` / `event_proto`、`message_event_constructor` /
|
||
/// `message_event_proto` 与 `error_event_constructor` / `error_event_proto`
|
||
/// 六枚 P 字段是空对象占位,本函数就地填充(不新建对象——P 字段本身就是
|
||
/// 槽位,快照/脏检查/收尾枚举已覆盖)。
|
||
///
|
||
/// # 幂等
|
||
/// 本函数从三条路径到达:`init_kernel_builtins`(占位是空对象)、
|
||
/// `rebind_dirty_builtins` 的 `event` 分支(占位是重建后的空对象)、global-dirty
|
||
/// 路径(占位可能已填满)。全部槽写经 `lookup_position` 前置守卫,有槽即跳过;
|
||
/// `bind_constructor!` 的全局槽臂自带既有槽原位更新,天然幂等。
|
||
///
|
||
/// `realm_id` 未使用(Event 无 well-known 符号键),保留签名与其他绑定函数一致。
|
||
pub fn bind_event(core: &Arc<KernelCore>, session: &KernelSession, global: &mut JsObject, _realm_id: u32) {
|
||
let world = session.builtin_world();
|
||
let ctor_ptr = world.event_constructor.as_ptr() as *mut JsObject;
|
||
let ctor = unsafe { &mut *ctor_ptr };
|
||
let proto_ptr = world.event_proto.as_ptr() as *mut JsObject;
|
||
let proto = unsafe { &mut *proto_ptr };
|
||
|
||
let sf = core.perm_interner().as_ref();
|
||
let sh = core.shape_forge().as_ref();
|
||
|
||
// ---- 填构造器占位 ----
|
||
ctor.set_function(true);
|
||
|
||
// prototype 槽 → 原型对象(描述符 {f,f,f})。
|
||
let si_prototype = sf.intern("prototype").0;
|
||
if sh.lookup_position(ctor.shape_id(), si_prototype).is_none() {
|
||
let shape = sh.make_shape(ctor.shape_id(), si_prototype);
|
||
ctor.set_shape_id(shape);
|
||
let pos = ctor.push_prop(JsValue::from_js_object(proto_ptr));
|
||
ctor.set_data_meta(pos, PropAttributes::new(false, false, false));
|
||
ctor.bump_generation();
|
||
}
|
||
|
||
// name 槽 → "Event"(描述符 {f,f,t})。
|
||
let si_name = sf.intern("name").0;
|
||
if sh.lookup_position(ctor.shape_id(), si_name).is_none() {
|
||
let shape = sh.make_shape(ctor.shape_id(), si_name);
|
||
ctor.set_shape_id(shape);
|
||
ctor.ensure_hash_props()
|
||
.push(JsValue::perm_string(sf.string_ptr(sf.intern("Event").0)));
|
||
let pos = ctor.hash_props_vec().map_or(0, |v| v.len() as u32).saturating_sub(1);
|
||
ctor.set_data_meta(pos, PropAttributes::new(false, false, true));
|
||
ctor.bump_generation();
|
||
}
|
||
|
||
// [[Prototype]] → Function.prototype(幂等,裸写槽)。
|
||
let fn_proto_val = JsValue::from_js_object(world.function_proto.as_ptr() as *mut JsObject);
|
||
let _ = ctor.set_proto(fn_proto_val);
|
||
|
||
configure_native_constructor(ctor, oxide_builtins::event::event_constructor::<crate::vm::Vm> as *const (), 2);
|
||
bind_constructor!(
|
||
core,
|
||
global,
|
||
"Event",
|
||
ctor_ptr,
|
||
oxide_builtins::event::event_constructor::<crate::vm::Vm>,
|
||
2,
|
||
hash: true
|
||
);
|
||
|
||
// Event 常量:CAPTURING_PHASE / AT_TARGET / BUBBLING_PHASE(绑构造器,
|
||
// 描述符 {t,f,t})。
|
||
let constants: [(&str, i32); 3] = [("CAPTURING_PHASE", 1), ("AT_TARGET", 2), ("BUBBLING_PHASE", 3)];
|
||
for (name, value) in constants {
|
||
let si = sf.intern(name).0;
|
||
if sh.lookup_position(ctor.shape_id(), si).is_none() {
|
||
let shape = sh.make_shape(ctor.shape_id(), si);
|
||
ctor.set_shape_id(shape);
|
||
let pos = ctor.push_prop(JsValue::int(value));
|
||
ctor.set_data_meta(pos, PropAttributes::new(true, false, true));
|
||
ctor.bump_generation();
|
||
}
|
||
}
|
||
|
||
// ---- 填原型占位 ----
|
||
// constructor 槽 → 构造器对象(描述符 {t,f,t})。
|
||
let si_constructor = sf.intern("constructor").0;
|
||
if sh.lookup_position(proto.shape_id(), si_constructor).is_none() {
|
||
let shape = sh.make_shape(proto.shape_id(), si_constructor);
|
||
proto.set_shape_id(shape);
|
||
let pos = proto.push_prop(JsValue::from_js_object(ctor_ptr));
|
||
proto.set_data_meta(pos, PropAttributes::new(true, false, true));
|
||
proto.bump_generation();
|
||
}
|
||
|
||
// [[Prototype]] → Object.prototype(幂等,裸写槽)。
|
||
let object_proto_val = JsValue::from_js_object(world.object_proto.as_ptr() as *mut JsObject);
|
||
let _ = proto.set_proto(object_proto_val);
|
||
|
||
// 原型方法:preventDefault / stopPropagation / stopImmediatePropagation /
|
||
// composedPath(每方法先 lookup_position 守卫)。
|
||
let si_prevent_default = sf.intern("preventDefault").0;
|
||
if sh.lookup_position(proto.shape_id(), si_prevent_default).is_none() {
|
||
apply_binding_table(
|
||
world,
|
||
proto,
|
||
core,
|
||
&[
|
||
(
|
||
"preventDefault",
|
||
oxide_builtins::event::event_prevent_default::<crate::vm::Vm> as *const (),
|
||
0,
|
||
),
|
||
(
|
||
"stopPropagation",
|
||
oxide_builtins::event::event_stop_propagation::<crate::vm::Vm> as *const (),
|
||
0,
|
||
),
|
||
(
|
||
"stopImmediatePropagation",
|
||
oxide_builtins::event::event_stop_immediate_propagation::<crate::vm::Vm> as *const (),
|
||
0,
|
||
),
|
||
(
|
||
"composedPath",
|
||
oxide_builtins::event::event_composed_path::<crate::vm::Vm> as *const (),
|
||
0,
|
||
),
|
||
],
|
||
);
|
||
}
|
||
|
||
// 原型 getter:type / target / currentTarget / eventPhase / isTrusted /
|
||
// bubbles / cancelable / defaultPrevented / composed(每 getter 先
|
||
// lookup_position 守卫)。
|
||
let getter_fns: [(&str, *const ()); 9] = [
|
||
("type", oxide_builtins::event::event_type_getter::<crate::vm::Vm> as *const ()),
|
||
("target", oxide_builtins::event::event_target_getter::<crate::vm::Vm> as *const ()),
|
||
(
|
||
"currentTarget",
|
||
oxide_builtins::event::event_current_target_getter::<crate::vm::Vm> as *const (),
|
||
),
|
||
("eventPhase", oxide_builtins::event::event_phase_getter::<crate::vm::Vm> as *const ()),
|
||
("isTrusted", oxide_builtins::event::event_is_trusted_getter::<crate::vm::Vm> as *const ()),
|
||
("bubbles", oxide_builtins::event::event_bubbles_getter::<crate::vm::Vm> as *const ()),
|
||
("cancelable", oxide_builtins::event::event_cancelable_getter::<crate::vm::Vm> as *const ()),
|
||
(
|
||
"defaultPrevented",
|
||
oxide_builtins::event::event_default_prevented_getter::<crate::vm::Vm> as *const (),
|
||
),
|
||
("composed", oxide_builtins::event::event_composed_getter::<crate::vm::Vm> as *const ()),
|
||
];
|
||
for (name, fn_ptr) in getter_fns {
|
||
let si = sf.intern(name).0;
|
||
if sh.lookup_position(proto.shape_id(), si).is_none() {
|
||
bind_accessor_getter(core, session, proto, name, fn_ptr);
|
||
}
|
||
}
|
||
|
||
// ---- 填 MessageEvent 构造器与原型占位 ----
|
||
let me_ctor_ptr = world.message_event_constructor.as_ptr() as *mut JsObject;
|
||
let me_ctor = unsafe { &mut *me_ctor_ptr };
|
||
let me_proto_ptr = world.message_event_proto.as_ptr() as *mut JsObject;
|
||
let me_proto = unsafe { &mut *me_proto_ptr };
|
||
|
||
// 构造器:function 标志、prototype 槽、name 槽、[[Prototype]] →
|
||
// Function.prototype(幂等,裸写槽)。
|
||
me_ctor.set_function(true);
|
||
if sh.lookup_position(me_ctor.shape_id(), si_prototype).is_none() {
|
||
let shape = sh.make_shape(me_ctor.shape_id(), si_prototype);
|
||
me_ctor.set_shape_id(shape);
|
||
let pos = me_ctor.push_prop(JsValue::from_js_object(me_proto_ptr));
|
||
me_ctor.set_data_meta(pos, PropAttributes::new(false, false, false));
|
||
me_ctor.bump_generation();
|
||
}
|
||
if sh.lookup_position(me_ctor.shape_id(), si_name).is_none() {
|
||
let shape = sh.make_shape(me_ctor.shape_id(), si_name);
|
||
me_ctor.set_shape_id(shape);
|
||
me_ctor
|
||
.ensure_hash_props()
|
||
.push(JsValue::perm_string(sf.string_ptr(sf.intern("MessageEvent").0)));
|
||
let pos = me_ctor.hash_props_vec().map_or(0, |v| v.len() as u32).saturating_sub(1);
|
||
me_ctor.set_data_meta(pos, PropAttributes::new(false, false, true));
|
||
me_ctor.bump_generation();
|
||
}
|
||
let _ = me_ctor.set_proto(fn_proto_val);
|
||
|
||
configure_native_constructor(
|
||
me_ctor,
|
||
oxide_builtins::event::message_event_constructor::<crate::vm::Vm> as *const (),
|
||
2,
|
||
);
|
||
bind_constructor!(
|
||
core,
|
||
global,
|
||
"MessageEvent",
|
||
me_ctor_ptr,
|
||
oxide_builtins::event::message_event_constructor::<crate::vm::Vm>,
|
||
2,
|
||
hash: true
|
||
);
|
||
|
||
// 原型:constructor 槽、[[Prototype]] → Event.prototype、五个 getter
|
||
// (data / origin / lastEpoch / source / ports,每 getter 先 lookup_position
|
||
// 守卫)。
|
||
if sh.lookup_position(me_proto.shape_id(), si_constructor).is_none() {
|
||
let shape = sh.make_shape(me_proto.shape_id(), si_constructor);
|
||
me_proto.set_shape_id(shape);
|
||
let pos = me_proto.push_prop(JsValue::from_js_object(me_ctor_ptr));
|
||
me_proto.set_data_meta(pos, PropAttributes::new(true, false, true));
|
||
me_proto.bump_generation();
|
||
}
|
||
let event_proto_val = JsValue::from_js_object(world.event_proto.as_ptr() as *mut JsObject);
|
||
let _ = me_proto.set_proto(event_proto_val);
|
||
|
||
let me_getter_fns: [(&str, *const ()); 5] = [
|
||
("data", oxide_builtins::event::message_event_data_getter::<crate::vm::Vm> as *const ()),
|
||
("origin", oxide_builtins::event::message_event_origin_getter::<crate::vm::Vm> as *const ()),
|
||
(
|
||
"lastEpoch",
|
||
oxide_builtins::event::message_event_last_epoch_getter::<crate::vm::Vm> as *const (),
|
||
),
|
||
("source", oxide_builtins::event::message_event_source_getter::<crate::vm::Vm> as *const ()),
|
||
("ports", oxide_builtins::event::message_event_ports_getter::<crate::vm::Vm> as *const ()),
|
||
];
|
||
for (name, fn_ptr) in me_getter_fns {
|
||
let si = sf.intern(name).0;
|
||
if sh.lookup_position(me_proto.shape_id(), si).is_none() {
|
||
bind_accessor_getter(core, session, me_proto, name, fn_ptr);
|
||
}
|
||
}
|
||
|
||
// ---- 填 ErrorEvent 构造器与原型占位 ----
|
||
let ee_ctor_ptr = world.error_event_constructor.as_ptr() as *mut JsObject;
|
||
let ee_ctor = unsafe { &mut *ee_ctor_ptr };
|
||
let ee_proto_ptr = world.error_event_proto.as_ptr() as *mut JsObject;
|
||
let ee_proto = unsafe { &mut *ee_proto_ptr };
|
||
|
||
// 构造器:function 标志、prototype 槽、name 槽、[[Prototype]] →
|
||
// Function.prototype(幂等,裸写槽)。
|
||
ee_ctor.set_function(true);
|
||
if sh.lookup_position(ee_ctor.shape_id(), si_prototype).is_none() {
|
||
let shape = sh.make_shape(ee_ctor.shape_id(), si_prototype);
|
||
ee_ctor.set_shape_id(shape);
|
||
let pos = ee_ctor.push_prop(JsValue::from_js_object(ee_proto_ptr));
|
||
ee_ctor.set_data_meta(pos, PropAttributes::new(false, false, false));
|
||
ee_ctor.bump_generation();
|
||
}
|
||
if sh.lookup_position(ee_ctor.shape_id(), si_name).is_none() {
|
||
let shape = sh.make_shape(ee_ctor.shape_id(), si_name);
|
||
ee_ctor.set_shape_id(shape);
|
||
ee_ctor
|
||
.ensure_hash_props()
|
||
.push(JsValue::perm_string(sf.string_ptr(sf.intern("ErrorEvent").0)));
|
||
let pos = ee_ctor.hash_props_vec().map_or(0, |v| v.len() as u32).saturating_sub(1);
|
||
ee_ctor.set_data_meta(pos, PropAttributes::new(false, false, true));
|
||
ee_ctor.bump_generation();
|
||
}
|
||
let _ = ee_ctor.set_proto(fn_proto_val);
|
||
|
||
configure_native_constructor(
|
||
ee_ctor,
|
||
oxide_builtins::event::error_event_constructor::<crate::vm::Vm> as *const (),
|
||
2,
|
||
);
|
||
bind_constructor!(
|
||
core,
|
||
global,
|
||
"ErrorEvent",
|
||
ee_ctor_ptr,
|
||
oxide_builtins::event::error_event_constructor::<crate::vm::Vm>,
|
||
2,
|
||
hash: true
|
||
);
|
||
|
||
// 原型:constructor 槽、[[Prototype]] → Event.prototype、五个 getter
|
||
// (message / filename / lineno / colno / error,每 getter 先
|
||
// lookup_position 守卫)。
|
||
if sh.lookup_position(ee_proto.shape_id(), si_constructor).is_none() {
|
||
let shape = sh.make_shape(ee_proto.shape_id(), si_constructor);
|
||
ee_proto.set_shape_id(shape);
|
||
let pos = ee_proto.push_prop(JsValue::from_js_object(ee_ctor_ptr));
|
||
ee_proto.set_data_meta(pos, PropAttributes::new(true, false, true));
|
||
ee_proto.bump_generation();
|
||
}
|
||
let _ = ee_proto.set_proto(event_proto_val);
|
||
|
||
let ee_getter_fns: [(&str, *const ()); 5] = [
|
||
("message", oxide_builtins::event::error_event_message_getter::<crate::vm::Vm> as *const ()),
|
||
("filename", oxide_builtins::event::error_event_filename_getter::<crate::vm::Vm> as *const ()),
|
||
("lineno", oxide_builtins::event::error_event_lineno_getter::<crate::vm::Vm> as *const ()),
|
||
("colno", oxide_builtins::event::error_event_colno_getter::<crate::vm::Vm> as *const ()),
|
||
("error", oxide_builtins::event::error_event_error_getter::<crate::vm::Vm> as *const ()),
|
||
];
|
||
for (name, fn_ptr) in ee_getter_fns {
|
||
let si = sf.intern(name).0;
|
||
if sh.lookup_position(ee_proto.shape_id(), si).is_none() {
|
||
bind_accessor_getter(core, session, ee_proto, name, fn_ptr);
|
||
}
|
||
}
|
||
|
||
// ---- 填 EventTarget 原型占位(无构造器,仅暴露原型与三方法)----
|
||
// 幂等:三方法经 lookup_position 守卫,[[Prototype]] 裸写槽幂等。
|
||
let et_proto_ptr = world.event_target_proto.as_ptr() as *mut JsObject;
|
||
let et_proto = unsafe { &mut *et_proto_ptr };
|
||
// [[Prototype]] → Object.prototype(幂等,裸写槽)。
|
||
let object_proto_val = JsValue::from_js_object(world.object_proto.as_ptr() as *mut JsObject);
|
||
let _ = et_proto.set_proto(object_proto_val);
|
||
// 三方法:addEventListener / removeEventListener / dispatchEvent(每方法先
|
||
// lookup_position 守卫)。
|
||
let si_add = sf.intern("addEventListener").0;
|
||
if sh.lookup_position(et_proto.shape_id(), si_add).is_none() {
|
||
apply_binding_table(
|
||
world,
|
||
et_proto,
|
||
core,
|
||
&[
|
||
(
|
||
"addEventListener",
|
||
oxide_builtins::event_target::event_target_add_event_listener::<crate::vm::Vm> as *const (),
|
||
3,
|
||
),
|
||
(
|
||
"removeEventListener",
|
||
oxide_builtins::event_target::event_target_remove_event_listener::<crate::vm::Vm> as *const (),
|
||
3,
|
||
),
|
||
(
|
||
"dispatchEvent",
|
||
oxide_builtins::event_target::event_target_dispatch_event::<crate::vm::Vm> as *const (),
|
||
1,
|
||
),
|
||
],
|
||
);
|
||
}
|
||
}
|