Add new Window globals as debuggees

Signed-off-by: Delan Azabani <dazabani@igalia.com>
Co-authored-by: atbrakhi <atbrakhi@igalia.com>
This commit is contained in:
Delan Azabani 2025-07-18 21:51:13 +08:00
parent c59ee57b5d
commit e2eabd41c9
7 changed files with 107 additions and 1 deletions

View file

@ -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<GlobalScope>,
}
impl DebuggerEvent {
pub(crate) fn new(
debugger_global: &GlobalScope,
global: &GlobalScope,
can_gc: CanGc,
) -> DomRoot<Self> {
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<crate::DomTypeHolder> for DebuggerEvent {
// check-tidy: no specs after this line
fn Global(&self, r#cx: script_bindings::script_runtime::JSContext) -> NonNull<JSObject> {
// Convert the debuggee globals 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()
}
}

View file

@ -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::<Event>(DebuggerEvent::new(self.upcast(), global, can_gc));
assert_eq!(
event.fire(self.upcast(), can_gc),
EventStatus::NotCanceled,
"Guaranteed by DebuggerEvent::new"
);
}
}

View file

@ -1105,7 +1105,7 @@ pub(crate) enum EventDefault {
Handled,
}
#[derive(PartialEq)]
#[derive(Debug, PartialEq)]
pub(crate) enum EventStatus {
Canceled,
NotCanceled,

View file

@ -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;

View file

@ -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);

View file

@ -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;
};

View file

@ -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);
});