mirror of
https://github.com/servo/servo.git
synced 2025-08-14 18:05:36 +01:00
devtools: Show clients where they can set breakpoints (#37667)
devtools clients query source actors to determine where the user can set breakpoints in a source. there are two relevant requests here: `getBreakableLines` controls which line numbers can be clicked in the margin, and once a line number is clicked, `getBreakpointPositionsCompressed` controls where to show breakpoint buttons within that line. this patch handles those requests by querying the [SpiderMonkey Debugger API](https://firefox-source-docs.mozilla.org/js/Debugger/) for that information: - devtools sends its script thread a GetPossibleBreakpoints message for the source’s [`spidermonkey_id`](https://firefox-source-docs.mozilla.org/js/Debugger/Debugger.Source.html#id) - the script thread fires a `getPossibleBreakpoints` event into its debugger global - the debugger script looks up the [root](https://firefox-source-docs.mozilla.org/js/Debugger/Debugger.html#onnewscript-script-global) [Debugger.Script](https://firefox-source-docs.mozilla.org/js/Debugger/Debugger.Script.html#getpossiblebreakpoints-query) for that source, calls [getPossibleBreakpoints()](https://firefox-source-docs.mozilla.org/js/Debugger/Debugger.Script.html#getpossiblebreakpoints-query), and returns the result via DebuggerGlobalScope#getPossibleBreakpointsResult() - that method takes the pending result sender, and sends the result back to devtools - devtools massages the result into the format required by the request, and replies to the client as a result, users of the Firefox devtools client can now set breakpoints, though they don’t have any effect. Testing: this patch adds new devtools tests Fixes: part of #36027 <img width="1433" height="1328" alt="image" src="https://github.com/user-attachments/assets/f0cd31e0-742f-44d3-8c5d-ceedd9a2706d" /> --------- Signed-off-by: Delan Azabani <dazabani@igalia.com> Co-authored-by: atbrakhi <atbrakhi@igalia.com>
This commit is contained in:
parent
1995e22e19
commit
f5b631e270
14 changed files with 340 additions and 8 deletions
|
@ -31,6 +31,9 @@ impl Actor for BreakpointListActor {
|
|||
_stream_id: crate::StreamId,
|
||||
) -> Result<(), ActorError> {
|
||||
match msg_type {
|
||||
// Client wants to set a breakpoint.
|
||||
// Seems to be infallible, unlike the thread actor’s `setBreakpoint`.
|
||||
// <https://firefox-source-docs.mozilla.org/devtools/backend/protocol.html#breakpoints>
|
||||
"setBreakpoint" => {
|
||||
let msg = EmptyReplyMsg { from: self.name() };
|
||||
request.reply_final(&msg)?
|
||||
|
|
|
@ -3,9 +3,11 @@
|
|||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::BTreeSet;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
|
||||
use base::id::PipelineId;
|
||||
use devtools_traits::DevtoolScriptControlMsg;
|
||||
use ipc_channel::ipc::{IpcSender, channel};
|
||||
use serde::Serialize;
|
||||
use serde_json::{Map, Value};
|
||||
use servo_url::ServoUrl;
|
||||
|
@ -61,6 +63,8 @@ pub struct SourceActor {
|
|||
pub spidermonkey_id: u32,
|
||||
/// `introductionType` in SpiderMonkey `CompileOptionsWrapper`.
|
||||
pub introduction_type: String,
|
||||
|
||||
script_sender: IpcSender<DevtoolScriptControlMsg>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
|
@ -71,6 +75,24 @@ struct SourceContentReply {
|
|||
source: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct GetBreakableLinesReply {
|
||||
from: String,
|
||||
// Line numbers are one-based.
|
||||
// <https://firefox-source-docs.mozilla.org/devtools/backend/protocol.html#source-locations>
|
||||
lines: BTreeSet<u32>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct GetBreakpointPositionsCompressedReply {
|
||||
from: String,
|
||||
// Column numbers are in UTF-16 code units, not Unicode scalar values or grapheme clusters.
|
||||
// Line number are one-based. Column numbers are zero-based.
|
||||
// FIXME: the docs say column numbers are one-based, but this appears to be incorrect.
|
||||
// <https://firefox-source-docs.mozilla.org/devtools/backend/protocol.html#source-locations>
|
||||
positions: BTreeMap<u32, BTreeSet<u32>>,
|
||||
}
|
||||
|
||||
impl SourceManager {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
|
@ -101,6 +123,7 @@ impl SourceActor {
|
|||
content_type: Option<String>,
|
||||
spidermonkey_id: u32,
|
||||
introduction_type: String,
|
||||
script_sender: IpcSender<DevtoolScriptControlMsg>,
|
||||
) -> SourceActor {
|
||||
SourceActor {
|
||||
name,
|
||||
|
@ -110,9 +133,11 @@ impl SourceActor {
|
|||
is_black_boxed: false,
|
||||
spidermonkey_id,
|
||||
introduction_type,
|
||||
script_sender,
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new_registered(
|
||||
actors: &mut ActorRegistry,
|
||||
pipeline_id: PipelineId,
|
||||
|
@ -121,6 +146,7 @@ impl SourceActor {
|
|||
content_type: Option<String>,
|
||||
spidermonkey_id: u32,
|
||||
introduction_type: String,
|
||||
script_sender: IpcSender<DevtoolScriptControlMsg>,
|
||||
) -> &SourceActor {
|
||||
let source_actor_name = actors.new_name("source");
|
||||
|
||||
|
@ -131,6 +157,7 @@ impl SourceActor {
|
|||
content_type,
|
||||
spidermonkey_id,
|
||||
introduction_type,
|
||||
script_sender,
|
||||
);
|
||||
actors.register(Box::new(source_actor));
|
||||
actors.register_source_actor(pipeline_id, &source_actor_name);
|
||||
|
@ -181,6 +208,54 @@ impl Actor for SourceActor {
|
|||
};
|
||||
request.reply_final(&reply)?
|
||||
},
|
||||
// Client wants to know which lines can have breakpoints.
|
||||
// Sent when opening a source in the Sources panel, and controls whether the line numbers can be clicked.
|
||||
"getBreakableLines" => {
|
||||
let (tx, rx) = channel().map_err(|_| ActorError::Internal)?;
|
||||
self.script_sender
|
||||
.send(DevtoolScriptControlMsg::GetPossibleBreakpoints(
|
||||
self.spidermonkey_id,
|
||||
tx,
|
||||
))
|
||||
.map_err(|_| ActorError::Internal)?;
|
||||
let result = rx.recv().map_err(|_| ActorError::Internal)?;
|
||||
let lines = result
|
||||
.into_iter()
|
||||
.map(|entry| entry.line_number)
|
||||
.collect::<BTreeSet<_>>();
|
||||
let reply = GetBreakableLinesReply {
|
||||
from: self.name(),
|
||||
lines,
|
||||
};
|
||||
request.reply_final(&reply)?
|
||||
},
|
||||
// Client wants to know which columns in the line can have breakpoints.
|
||||
// Sent when the user tries to set a breakpoint by clicking a line number in a source.
|
||||
"getBreakpointPositionsCompressed" => {
|
||||
let (tx, rx) = channel().map_err(|_| ActorError::Internal)?;
|
||||
self.script_sender
|
||||
.send(DevtoolScriptControlMsg::GetPossibleBreakpoints(
|
||||
self.spidermonkey_id,
|
||||
tx,
|
||||
))
|
||||
.map_err(|_| ActorError::Internal)?;
|
||||
let result = rx.recv().map_err(|_| ActorError::Internal)?;
|
||||
let mut positions: BTreeMap<u32, BTreeSet<u32>> = BTreeMap::default();
|
||||
for entry in result {
|
||||
// Line number are one-based. Column numbers are zero-based.
|
||||
// FIXME: the docs say column numbers are one-based, but this appears to be incorrect.
|
||||
// <https://firefox-source-docs.mozilla.org/devtools/backend/protocol.html#source-locations>
|
||||
positions
|
||||
.entry(entry.line_number)
|
||||
.or_default()
|
||||
.insert(entry.column_number - 1);
|
||||
}
|
||||
let reply = GetBreakpointPositionsCompressedReply {
|
||||
from: self.name(),
|
||||
positions,
|
||||
};
|
||||
request.reply_final(&reply)?
|
||||
},
|
||||
_ => return Err(ActorError::UnrecognizedPacketType),
|
||||
};
|
||||
Ok(())
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue