Skip to content

Commit 92a9d24

Browse files
delanatbrakhi
andauthored
script: Add new Window globals as debuggees (servo#38333)
to debug the scripts in a page with the [SpiderMonkey Debugger API](https://firefox-source-docs.mozilla.org/js/Debugger/), we need to pass the page’s global object to [Debugger.prototype.**addDebuggee()**](https://firefox-source-docs.mozilla.org/js/Debugger/Debugger.html#adddebuggee-global). we could pick up the global via the [onNewGlobalObject() hook](https://firefox-source-docs.mozilla.org/js/Debugger/Debugger.html#onnewglobalobject-global), but if our script system passes the global to the debugger script instead, we can later add details like the PipelineId that will help servo identify debuggees that the API is notifying us about (servo#38334). this patch plumbs new Window globals from script into addDebuggee() via the debugger script. to call into the debugger script with structured input, we create a new DOM event type, DebuggerEvent, that the debugger script listens for as the “addDebuggee” event. Testing: no testable effects yet, but will be used in servo#37667 Fixes: part of servo#36027 --------- Signed-off-by: Delan Azabani <[email protected]> Co-authored-by: atbrakhi <[email protected]>
1 parent 77ff351 commit 92a9d24

File tree

7 files changed

+101
-1
lines changed

7 files changed

+101
-1
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4+
5+
use std::ptr::NonNull;
6+
7+
use dom_struct::dom_struct;
8+
use js::jsapi::{JSObject, Value};
9+
use script_bindings::conversions::SafeToJSValConvertible;
10+
use script_bindings::reflector::DomObject;
11+
12+
use crate::dom::bindings::codegen::Bindings::DebuggerEventBinding::DebuggerEventMethods;
13+
use crate::dom::bindings::codegen::Bindings::EventBinding::Event_Binding::EventMethods;
14+
use crate::dom::bindings::reflector::reflect_dom_object;
15+
use crate::dom::bindings::root::{Dom, DomRoot};
16+
use crate::dom::event::Event;
17+
use crate::dom::types::GlobalScope;
18+
use crate::script_runtime::CanGc;
19+
20+
#[dom_struct]
21+
/// Event for Rust → JS calls in [`crate::dom::DebuggerGlobalScope`].
22+
pub(crate) struct DebuggerEvent {
23+
event: Event,
24+
global: Dom<GlobalScope>,
25+
}
26+
27+
impl DebuggerEvent {
28+
pub(crate) fn new(
29+
debugger_global: &GlobalScope,
30+
global: &GlobalScope,
31+
can_gc: CanGc,
32+
) -> DomRoot<Self> {
33+
let result = Box::new(Self {
34+
event: Event::new_inherited(),
35+
global: Dom::from_ref(global),
36+
});
37+
let result = reflect_dom_object(result, debugger_global, can_gc);
38+
result.event.init_event("addDebuggee".into(), false, false);
39+
40+
result
41+
}
42+
}
43+
44+
impl DebuggerEventMethods<crate::DomTypeHolder> for DebuggerEvent {
45+
// check-tidy: no specs after this line
46+
fn Global(&self, cx: script_bindings::script_runtime::JSContext) -> NonNull<JSObject> {
47+
// Convert the debuggee global’s reflector to a Value, wrapping it from its originating realm (debuggee realm)
48+
// into the active realm (debugger realm) so that it can be passed across compartments.
49+
rooted!(in(*cx) let mut result: Value);
50+
self.global
51+
.reflector()
52+
.safe_to_jsval(cx, result.handle_mut());
53+
NonNull::new(result.to_object()).unwrap()
54+
}
55+
56+
fn IsTrusted(&self) -> bool {
57+
self.event.IsTrusted()
58+
}
59+
}

components/script/dom/debuggerglobalscope.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ use crate::dom::bindings::inheritance::Castable;
2424
use crate::dom::bindings::root::DomRoot;
2525
use crate::dom::bindings::trace::CustomTraceable;
2626
use crate::dom::bindings::utils::define_all_exposed_interfaces;
27+
use crate::dom::event::EventStatus;
2728
use crate::dom::globalscope::GlobalScope;
29+
use crate::dom::types::{DebuggerEvent, Event};
2830
#[cfg(feature = "testbinding")]
2931
#[cfg(feature = "webgpu")]
3032
use crate::dom::webgpu::identityhub::IdentityHub;
@@ -119,4 +121,13 @@ impl DebuggerGlobalScope {
119121
report_pending_exception(Self::get_cx(), true, InRealm::Entered(&ar), can_gc);
120122
}
121123
}
124+
125+
pub(crate) fn fire_add_debuggee(&self, can_gc: CanGc, global: &GlobalScope) {
126+
assert_eq!(
127+
DomRoot::upcast::<Event>(DebuggerEvent::new(self.upcast(), global, can_gc))
128+
.fire(self.upcast(), can_gc),
129+
EventStatus::NotCanceled,
130+
"Guaranteed by DebuggerEvent::new"
131+
);
132+
}
122133
}

components/script/dom/event.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1105,7 +1105,7 @@ pub(crate) enum EventDefault {
11051105
Handled,
11061106
}
11071107

1108-
#[derive(PartialEq)]
1108+
#[derive(Debug, PartialEq)]
11091109
pub(crate) enum EventStatus {
11101110
Canceled,
11111111
NotCanceled,

components/script/dom/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,7 @@ pub(crate) mod customevent;
289289
pub(crate) mod datatransfer;
290290
pub(crate) mod datatransferitem;
291291
pub(crate) mod datatransferitemlist;
292+
pub(crate) mod debuggerevent;
292293
pub(crate) mod debuggerglobalscope;
293294
pub(crate) mod dedicatedworkerglobalscope;
294295
pub(crate) mod defaultteereadrequest;

components/script/script_thread.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3435,6 +3435,8 @@ impl ScriptThread {
34353435
incomplete.load_data.inherited_secure_context,
34363436
incomplete.theme,
34373437
);
3438+
self.debugger_global
3439+
.fire_add_debuggee(can_gc, window.upcast());
34383440

34393441
let _realm = enter_realm(&*window);
34403442

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4+
5+
// This interface is entirely internal to Servo, and should not be accessible to
6+
// web pages.
7+
[Exposed=DebuggerGlobalScope]
8+
interface DebuggerEvent : Event {
9+
readonly attribute object global;
10+
};

resources/debugger.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
11
if (!("dbg" in this)) {
22
dbg = new Debugger;
3+
4+
dbg.onNewGlobalObject = function(global) {
5+
console.log("[debugger] onNewGlobalObject");
6+
console.log(this, global);
7+
};
8+
9+
dbg.onNewScript = function(script, global) {
10+
console.log("[debugger] onNewScript");
11+
console.log(this, script, global);
12+
};
313
}
14+
15+
addEventListener("addDebuggee", event => {
16+
const {global} = event;
17+
console.log("[debugger] Adding debuggee");
18+
dbg.addDebuggee(global);
19+
console.log("[debugger] getDebuggees().length =", dbg.getDebuggees().length);
20+
});

0 commit comments

Comments
 (0)