mirror of
https://github.com/servo/servo.git
synced 2025-08-05 21:50:18 +01:00
script: Create a debugger script for the SpiderMonkey Debugger API (#38331)
to use the [SpiderMonkey Debugger API](https://firefox-source-docs.mozilla.org/js/Debugger/), we need to call it from an internal debugger script that we will supply. this script must run in the same runtime as the debuggee(s), but in a separate [compartment](https://udn.realityripple.com/docs/Mozilla/Projects/SpiderMonkey/Compartments) ([more details](https://hacks.mozilla.org/2020/03/future-proofing-firefoxs-javascript-debugger-implementation/)). this patch defines a new DebuggerGlobalScope type and a new debugger script resource. when creating each script thread, we create a debugger global, load the debugger script from resources/debugger.js, and run that script in the global to initialise the Debugger API. subsequent patches will use the debugger script as an RPC mechanism for the Debugger API. Testing: no testable effects yet, but will be used in #37667 Fixes: part of #36027 --------- Signed-off-by: Delan Azabani <dazabani@igalia.com> Co-authored-by: atbrakhi <atbrakhi@igalia.com>
This commit is contained in:
parent
8e27fd48cc
commit
c09e117bfe
11 changed files with 184 additions and 6 deletions
122
components/script/dom/debuggerglobalscope.rs
Normal file
122
components/script/dom/debuggerglobalscope.rs
Normal file
|
@ -0,0 +1,122 @@
|
|||
/* 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 base::id::PipelineId;
|
||||
use constellation_traits::ScriptToConstellationChan;
|
||||
use crossbeam_channel::Sender;
|
||||
use devtools_traits::ScriptToDevtoolsControlMsg;
|
||||
use dom_struct::dom_struct;
|
||||
use embedder_traits::resources::{self, Resource};
|
||||
use ipc_channel::ipc::IpcSender;
|
||||
use js::jsval::UndefinedValue;
|
||||
use js::rust::Runtime;
|
||||
use js::rust::wrappers::JS_DefineDebuggerObject;
|
||||
use net_traits::ResourceThreads;
|
||||
use profile_traits::{mem, time};
|
||||
use script_bindings::realms::InRealm;
|
||||
use script_bindings::reflector::DomObject;
|
||||
use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl};
|
||||
|
||||
use crate::dom::bindings::codegen::Bindings::DebuggerGlobalScopeBinding;
|
||||
use crate::dom::bindings::error::report_pending_exception;
|
||||
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::globalscope::GlobalScope;
|
||||
#[cfg(feature = "testbinding")]
|
||||
#[cfg(feature = "webgpu")]
|
||||
use crate::dom::webgpu::identityhub::IdentityHub;
|
||||
use crate::messaging::MainThreadScriptMsg;
|
||||
use crate::realms::enter_realm;
|
||||
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,
|
||||
script_chan: Sender<MainThreadScriptMsg>,
|
||||
}
|
||||
|
||||
impl DebuggerGlobalScope {
|
||||
/// Create a new heap-allocated `DebuggerGlobalScope`.
|
||||
#[allow(unsafe_code, clippy::too_many_arguments)]
|
||||
pub(crate) fn new(
|
||||
runtime: &Runtime,
|
||||
script_chan: Sender<MainThreadScriptMsg>,
|
||||
devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
|
||||
mem_profiler_chan: mem::ProfilerChan,
|
||||
time_profiler_chan: time::ProfilerChan,
|
||||
script_to_constellation_chan: ScriptToConstellationChan,
|
||||
resource_threads: ResourceThreads,
|
||||
#[cfg(feature = "webgpu")] gpu_id_hub: std::sync::Arc<IdentityHub>,
|
||||
can_gc: CanGc,
|
||||
) -> DomRoot<Self> {
|
||||
let global = Box::new(Self {
|
||||
global_scope: GlobalScope::new_inherited(
|
||||
PipelineId::new(),
|
||||
devtools_chan,
|
||||
mem_profiler_chan,
|
||||
time_profiler_chan,
|
||||
script_to_constellation_chan,
|
||||
resource_threads,
|
||||
MutableOrigin::new(ImmutableOrigin::new_opaque()),
|
||||
ServoUrl::parse_with_base(None, "about:internal/debugger")
|
||||
.expect("Guaranteed by argument"),
|
||||
None,
|
||||
Default::default(),
|
||||
#[cfg(feature = "webgpu")]
|
||||
gpu_id_hub,
|
||||
None,
|
||||
false,
|
||||
),
|
||||
script_chan,
|
||||
});
|
||||
let global = unsafe {
|
||||
DebuggerGlobalScopeBinding::Wrap::<crate::DomTypeHolder>(
|
||||
JSContext::from_ptr(runtime.cx()),
|
||||
global,
|
||||
)
|
||||
};
|
||||
|
||||
let realm = enter_realm(&*global);
|
||||
define_all_exposed_interfaces(global.upcast(), InRealm::entered(&realm), can_gc);
|
||||
assert!(unsafe {
|
||||
// Invariants: `cx` must be a non-null, valid JSContext pointer,
|
||||
// and `obj` must be a handle to a JS global object.
|
||||
JS_DefineDebuggerObject(
|
||||
*Self::get_cx(),
|
||||
global.global_scope.reflector().get_jsobject(),
|
||||
)
|
||||
});
|
||||
|
||||
global
|
||||
}
|
||||
|
||||
/// Get the JS context.
|
||||
pub(crate) fn get_cx() -> JSContext {
|
||||
GlobalScope::get_cx()
|
||||
}
|
||||
|
||||
fn evaluate_js(&self, script: &str, can_gc: CanGc) -> bool {
|
||||
rooted!(in (*Self::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,
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn execute(&self, can_gc: CanGc) {
|
||||
if !self.evaluate_js(&resources::read_string(Resource::DebuggerJS), can_gc) {
|
||||
let ar = enter_realm(self);
|
||||
report_pending_exception(Self::get_cx(), true, InRealm::Entered(&ar), can_gc);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue