Run a script in a new DebuggerGlobalScope

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 186558ca08
commit 23c166fcf1
7 changed files with 123 additions and 3 deletions

View file

@ -0,0 +1,88 @@
/* 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::sync::Arc;
use base::id::PipelineId;
use constellation_traits::ScriptToConstellationChan;
use dom_struct::dom_struct;
use js::jsval::UndefinedValue;
use js::rust::Runtime;
use net_traits::ResourceThreads;
use profile_traits::{mem, time};
use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl};
use crate::dom::bindings::codegen::Bindings::DebuggerGlobalScopeBinding;
use crate::dom::bindings::root::DomRoot;
use crate::dom::globalscope::GlobalScope;
#[cfg(feature = "testbinding")]
#[cfg(feature = "webgpu")]
use crate::dom::webgpu::identityhub::IdentityHub;
use crate::script_module::ScriptFetchOptions;
use crate::script_runtime::{CanGc, JSContext};
#[dom_struct]
/// Global scope for interacting with the devtools Debugger API.
///
/// <https://firefox-source-docs.mozilla.org/js/Debugger/>
pub(crate) struct DebuggerGlobalScope {
global_scope: GlobalScope,
}
impl DebuggerGlobalScope {
/// Create a new heap-allocated `DebuggerGlobalScope`.
#[allow(unsafe_code)]
pub(crate) fn new(
runtime: &Runtime,
mem_profiler_chan: mem::ProfilerChan,
time_profiler_chan: time::ProfilerChan,
script_to_constellation_chan: ScriptToConstellationChan,
resource_threads: ResourceThreads,
#[cfg(feature = "webgpu")] gpu_id_hub: Arc<IdentityHub>,
) -> DomRoot<Self> {
let global = Box::new(Self {
global_scope: GlobalScope::new_inherited(
PipelineId::new(), // ??? or TEST_PIPELINE_ID, but that seems worse
None, // ? if needed, see script_thread:745
mem_profiler_chan,
time_profiler_chan,
script_to_constellation_chan, // wrap it in a ScriptToConstellationChan
resource_threads,
MutableOrigin::new(ImmutableOrigin::new_opaque()),
ServoUrl::parse_with_base(None, "about:internal/debugger")
.expect("Guaranteed by argument"), // ???
None,
Default::default(),
gpu_id_hub,
None, // ? if needed, see script_thread:745
false,
),
});
unsafe {
DebuggerGlobalScopeBinding::Wrap::<crate::DomTypeHolder>(
JSContext::from_ptr(runtime.cx()),
global,
)
}
}
/// Get the JS context.
pub(crate) fn get_cx() -> JSContext {
GlobalScope::get_cx()
}
/// Evaluate a JS script in this global.
pub(crate) fn evaluate_js(&self, script: &str, can_gc: CanGc) -> bool {
debug!("Evaluating Dom in a worklet.");
rooted!(in (*GlobalScope::get_cx()) let mut rval = UndefinedValue());
self.global_scope.evaluate_js_on_global_with_result(
script,
rval.handle_mut(),
ScriptFetchOptions::default_classic_script(&self.global_scope),
self.global_scope.api_base_url(),
can_gc,
)
}
}

View file

@ -114,7 +114,7 @@ use crate::dom::reportingobserver::ReportingObserver;
use crate::dom::serviceworker::ServiceWorker;
use crate::dom::serviceworkerregistration::ServiceWorkerRegistration;
use crate::dom::trustedtypepolicyfactory::TrustedTypePolicyFactory;
use crate::dom::types::MessageEvent;
use crate::dom::types::{DebuggerGlobalScope, MessageEvent};
use crate::dom::underlyingsourcecontainer::UnderlyingSourceType;
#[cfg(feature = "webgpu")]
use crate::dom::webgpu::gpudevice::GPUDevice;
@ -2530,6 +2530,9 @@ impl GlobalScope {
// https://drafts.css-houdini.org/worklets/#script-settings-for-worklets
return worklet.base_url();
}
if let Some(_debugger_global) = self.downcast::<DebuggerGlobalScope>() {
return self.creation_url.clone();
}
unreachable!();
}
@ -2545,6 +2548,9 @@ impl GlobalScope {
// TODO: is this the right URL to return?
return worklet.base_url();
}
if let Some(_debugger_global) = self.downcast::<DebuggerGlobalScope>() {
return self.creation_url.clone();
}
unreachable!();
}

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 debuggerglobalscope;
pub(crate) mod dedicatedworkerglobalscope;
pub(crate) mod defaultteereadrequest;
pub(crate) mod defaultteeunderlyingsource;

View file

@ -133,6 +133,7 @@ use crate::dom::htmlslotelement::HTMLSlotElement;
use crate::dom::mutationobserver::MutationObserver;
use crate::dom::node::{Node, NodeTraits, ShadowIncluding};
use crate::dom::servoparser::{ParserContext, ServoParser};
use crate::dom::types::DebuggerGlobalScope;
#[cfg(feature = "webgpu")]
use crate::dom::webgpu::identityhub::IdentityHub;
use crate::dom::window::Window;
@ -1004,6 +1005,23 @@ impl ScriptThread {
/// messages on its port.
pub(crate) fn start(&self, can_gc: CanGc) {
debug!("Starting script thread.");
let pipeline_id = PipelineId::new();
let script_to_constellation_chan = ScriptToConstellationChan {
sender: self.senders.pipeline_to_constellation_sender.clone(),
pipeline_id,
};
let debugger_global = DebuggerGlobalScope::new(
&self.js_runtime,
self.senders.memory_profiler_sender.clone(),
self.senders.time_profiler_sender.clone(),
script_to_constellation_chan,
self.resource_threads.clone(),
#[cfg(feature = "webgpu")]
self.gpu_id_hub.clone(),
);
debugger_global.evaluate_js("console.log('hello world')", can_gc);
while self.handle_msgs(can_gc) {
// Go on...
debug!("Running script thread.");

View file

@ -0,0 +1,7 @@
/* 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/. */
[Global=DebuggerGlobalScope, Exposed=DebuggerGlobalScope]
interface DebuggerGlobalScope: GlobalScope {
};

View file

@ -5,7 +5,7 @@
* https://dom.spec.whatwg.org/#interface-eventtarget
*/
[Exposed=(Window,Worker,Worklet,DissimilarOriginWindow)]
[Exposed=(Window,Worker,Worklet,DissimilarOriginWindow,DebuggerGlobalScope)]
interface EventTarget {
[Throws] constructor();
undefined addEventListener(

View file

@ -5,6 +5,6 @@
// This interface is entirely internal to Servo, and should not be accessible to
// web pages.
[Exposed=(Window,Worker,Worklet,DissimilarOriginWindow),
[Exposed=(Window,Worker,Worklet,DissimilarOriginWindow,DebuggerGlobalScope),
Inline]
interface GlobalScope : EventTarget {};