From e2eabd41c90c56571c3bb469ea86998e21d6b9ad Mon Sep 17 00:00:00 2001 From: Delan Azabani Date: Fri, 18 Jul 2025 21:51:13 +0800 Subject: [PATCH] Add new Window globals as debuggees Signed-off-by: Delan Azabani Co-authored-by: atbrakhi --- components/script/dom/debuggerevent.rs | 64 +++++++++++++++++++ components/script/dom/debuggerglobalscope.rs | 12 ++++ components/script/dom/event.rs | 2 +- components/script/dom/mod.rs | 1 + components/script/script_thread.rs | 2 + .../webidls/DebuggerEvent.webidl | 10 +++ resources/debugger.js | 17 +++++ 7 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 components/script/dom/debuggerevent.rs create mode 100644 components/script_bindings/webidls/DebuggerEvent.webidl diff --git a/components/script/dom/debuggerevent.rs b/components/script/dom/debuggerevent.rs new file mode 100644 index 00000000000..18b2bdf33dc --- /dev/null +++ b/components/script/dom/debuggerevent.rs @@ -0,0 +1,64 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use std::default::Default; +use std::ptr::NonNull; + +use dom_struct::dom_struct; +use js::jsapi::{JSObject, Value}; +use script_bindings::conversions::SafeToJSValConvertible; +use script_bindings::reflector::DomObject; + +use crate::dom::bindings::codegen::Bindings::DebuggerEventBinding::DebuggerEventMethods; +use crate::dom::bindings::codegen::Bindings::EventBinding::Event_Binding::EventMethods; +use crate::dom::bindings::reflector::reflect_dom_object; +use crate::dom::bindings::root::{DomRoot, MutNullableDom}; +use crate::dom::event::Event; +use crate::dom::types::GlobalScope; +use crate::script_runtime::CanGc; + +#[dom_struct] +/// Event for Rust → JS calls in [`crate::dom::DebuggerGlobalScope`]. +pub(crate) struct DebuggerEvent { + event: Event, + global: MutNullableDom, +} + +impl DebuggerEvent { + pub(crate) fn new( + debugger_global: &GlobalScope, + global: &GlobalScope, + can_gc: CanGc, + ) -> DomRoot { + let result = Box::new(Self { + event: Event::new_inherited(), + global: Default::default(), + }); + // TODO: make these fields not optional somehow? + result.global.set(Some(global)); + + result.event.init_event("addDebuggee".into(), false, false); + + reflect_dom_object(result, debugger_global, can_gc) + } +} + +impl DebuggerEventMethods for DebuggerEvent { + // check-tidy: no specs after this line + fn Global(&self, r#cx: script_bindings::script_runtime::JSContext) -> NonNull { + // Convert the debuggee global’s reflector to a Value, wrapping it from its originating realm (debuggee realm) + // into the active realm (debugger realm) so that it can be passed across compartments. + rooted!(in(*cx) let mut result: Value); + self.global + .get() + .expect("Guaranteed by new") + .reflector() + .safe_to_jsval(cx, result.handle_mut()); + NonNull::new(result.to_object()).unwrap() + } + + fn IsTrusted(&self) -> bool { + self.event.IsTrusted() + } +} diff --git a/components/script/dom/debuggerglobalscope.rs b/components/script/dom/debuggerglobalscope.rs index 0c69b8106d5..ab55fa0f914 100644 --- a/components/script/dom/debuggerglobalscope.rs +++ b/components/script/dom/debuggerglobalscope.rs @@ -24,7 +24,9 @@ use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::trace::CustomTraceable; use crate::dom::bindings::utils::define_all_exposed_interfaces; +use crate::dom::event::EventStatus; use crate::dom::globalscope::GlobalScope; +use crate::dom::types::{DebuggerEvent, Event}; #[cfg(feature = "testbinding")] #[cfg(feature = "webgpu")] use crate::dom::webgpu::identityhub::IdentityHub; @@ -119,4 +121,14 @@ impl DebuggerGlobalScope { report_pending_exception(Self::get_cx(), true, InRealm::Entered(&ar), can_gc); } } + + #[allow(unsafe_code)] + pub(crate) fn fire_add_debuggee(&self, can_gc: CanGc, global: &GlobalScope) { + let event = DomRoot::upcast::(DebuggerEvent::new(self.upcast(), global, can_gc)); + assert_eq!( + event.fire(self.upcast(), can_gc), + EventStatus::NotCanceled, + "Guaranteed by DebuggerEvent::new" + ); + } } diff --git a/components/script/dom/event.rs b/components/script/dom/event.rs index 345038a08da..6153866ce95 100644 --- a/components/script/dom/event.rs +++ b/components/script/dom/event.rs @@ -1105,7 +1105,7 @@ pub(crate) enum EventDefault { Handled, } -#[derive(PartialEq)] +#[derive(Debug, PartialEq)] pub(crate) enum EventStatus { Canceled, NotCanceled, diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index 57e16ad4941..630ad4f9fb2 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -289,6 +289,7 @@ pub(crate) mod customevent; pub(crate) mod datatransfer; pub(crate) mod datatransferitem; pub(crate) mod datatransferitemlist; +pub(crate) mod debuggerevent; pub(crate) mod debuggerglobalscope; pub(crate) mod dedicatedworkerglobalscope; pub(crate) mod defaultteereadrequest; diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index 28d44487f13..bb16e35b2bf 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -3449,6 +3449,8 @@ impl ScriptThread { incomplete.load_data.inherited_secure_context, incomplete.theme, ); + self.debugger_global + .fire_add_debuggee(can_gc, window.upcast()); let _realm = enter_realm(&*window); diff --git a/components/script_bindings/webidls/DebuggerEvent.webidl b/components/script_bindings/webidls/DebuggerEvent.webidl new file mode 100644 index 00000000000..a0682fc3165 --- /dev/null +++ b/components/script_bindings/webidls/DebuggerEvent.webidl @@ -0,0 +1,10 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +// This interface is entirely internal to Servo, and should not be accessible to +// web pages. +[Exposed=DebuggerGlobalScope] +interface DebuggerEvent : Event { + readonly attribute object global; +}; diff --git a/resources/debugger.js b/resources/debugger.js index 6d1e4b19bc8..d0c6198bfd2 100644 --- a/resources/debugger.js +++ b/resources/debugger.js @@ -1,3 +1,20 @@ if (!("dbg" in this)) { dbg = new Debugger; + + dbg.onNewGlobalObject = function(global) { + console.log("[debugger] onNewGlobalObject"); + console.log(this, global); + }; + + dbg.onNewScript = function(script, global) { + console.log("[debugger] onNewScript"); + console.log(this, script, global); + }; } + +addEventListener("addDebuggee", event => { + const {global} = event; + console.log("[debugger] Adding debuggee"); + dbg.addDebuggee(global); + console.log("[debugger] getDebuggees().length =", dbg.getDebuggees().length); +});