//! 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, 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:: as *const (), 2); bind_constructor!( core, global, "Event", ctor_ptr, oxide_builtins::event::event_constructor::, 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:: as *const (), 0, ), ( "stopPropagation", oxide_builtins::event::event_stop_propagation:: as *const (), 0, ), ( "stopImmediatePropagation", oxide_builtins::event::event_stop_immediate_propagation:: as *const (), 0, ), ( "composedPath", oxide_builtins::event::event_composed_path:: 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:: as *const ()), ("target", oxide_builtins::event::event_target_getter:: as *const ()), ( "currentTarget", oxide_builtins::event::event_current_target_getter:: as *const (), ), ("eventPhase", oxide_builtins::event::event_phase_getter:: as *const ()), ("isTrusted", oxide_builtins::event::event_is_trusted_getter:: as *const ()), ("bubbles", oxide_builtins::event::event_bubbles_getter:: as *const ()), ("cancelable", oxide_builtins::event::event_cancelable_getter:: as *const ()), ( "defaultPrevented", oxide_builtins::event::event_default_prevented_getter:: as *const (), ), ("composed", oxide_builtins::event::event_composed_getter:: 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:: as *const (), 2, ); bind_constructor!( core, global, "MessageEvent", me_ctor_ptr, oxide_builtins::event::message_event_constructor::, 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:: as *const ()), ("origin", oxide_builtins::event::message_event_origin_getter:: as *const ()), ( "lastEpoch", oxide_builtins::event::message_event_last_epoch_getter:: as *const (), ), ("source", oxide_builtins::event::message_event_source_getter:: as *const ()), ("ports", oxide_builtins::event::message_event_ports_getter:: 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:: as *const (), 2, ); bind_constructor!( core, global, "ErrorEvent", ee_ctor_ptr, oxide_builtins::event::error_event_constructor::, 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:: as *const ()), ("filename", oxide_builtins::event::error_event_filename_getter:: as *const ()), ("lineno", oxide_builtins::event::error_event_lineno_getter:: as *const ()), ("colno", oxide_builtins::event::error_event_colno_getter:: as *const ()), ("error", oxide_builtins::event::error_event_error_getter:: 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:: as *const (), 3, ), ( "removeEventListener", oxide_builtins::event_target::event_target_remove_event_listener:: as *const (), 3, ), ( "dispatchEvent", oxide_builtins::event_target::event_target_dispatch_event:: as *const (), 1, ), ], ); } }