Files
servo/components/devtools/actors/breakpoint.rs
atbrakhi e28a0f6d6c devtools: implement clearBreakpoint (#42154)
Add an event listener for `clearBreakpoint` to `debugger.js` and the
necessary glue to access it from the `devtools` crate.

Testing: `./mach test-devtools` and manual testing.
Fixes: Part of: https://github.com/servo/servo/issues/36027

---------

Signed-off-by: atbrakhi <atbrakhi@igalia.com>
Co-authored-by: eri <eri@igalia.com>
2026-01-27 15:46:54 +00:00

137 lines
4.7 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* 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 devtools_traits::DevtoolScriptControlMsg;
use serde::Deserialize;
use serde_json::Map;
use crate::actor::{Actor, ActorEncode, ActorError, ActorRegistry};
use crate::actors::browsing_context::BrowsingContextActor;
use crate::actors::thread::ThreadActor;
use crate::protocol::ClientRequest;
use crate::{ActorMsg, EmptyReplyMsg};
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct BreakpointRequestLocation {
pub line: u32,
pub column: u32,
#[serde(skip_serializing_if = "Option::is_none")]
pub source_url: Option<String>,
}
#[derive(Deserialize)]
struct BreakpointRequest {
location: BreakpointRequestLocation,
}
pub(crate) struct BreakpointListActor {
name: String,
browsing_context: String,
}
impl Actor for BreakpointListActor {
fn name(&self) -> String {
self.name.clone()
}
fn handle_message(
&self,
request: ClientRequest,
registry: &crate::actor::ActorRegistry,
msg_type: &str,
msg: &Map<String, serde_json::Value>,
_stream_id: crate::StreamId,
) -> Result<(), ActorError> {
match msg_type {
// Client wants to set a breakpoint.
// Seems to be infallible, unlike the thread actors `setBreakpoint`.
// <https://firefox-source-docs.mozilla.org/devtools/backend/protocol.html#breakpoints>
"setBreakpoint" => {
let msg: BreakpointRequest =
serde_json::from_value(msg.clone().into()).map_err(|_| ActorError::Internal)?;
let BreakpointRequestLocation {
line,
column,
source_url,
} = msg.location;
let source_url = source_url.ok_or(ActorError::Internal)?;
let browsing_context =
registry.find::<BrowsingContextActor>(&self.browsing_context);
let thread = registry.find::<ThreadActor>(&browsing_context.thread);
let source = thread
.source_manager
.find_source(registry, &source_url)
.ok_or(ActorError::Internal)?;
let (script_id, offset) = source.find_offset(line, column);
source
.script_sender
.send(DevtoolScriptControlMsg::SetBreakpoint(
source.spidermonkey_id,
script_id,
offset,
))
.map_err(|_| ActorError::Internal)?;
let msg = EmptyReplyMsg { from: self.name() };
request.reply_final(&msg)?
},
"setActiveEventBreakpoints" => {
let msg = EmptyReplyMsg { from: self.name() };
request.reply_final(&msg)?
},
"removeBreakpoint" => {
let msg: BreakpointRequest =
serde_json::from_value(msg.clone().into()).map_err(|_| ActorError::Internal)?;
let BreakpointRequestLocation {
line,
column,
source_url,
} = msg.location;
let source_url = source_url.ok_or(ActorError::Internal)?;
let browsing_context =
registry.find::<BrowsingContextActor>(&self.browsing_context);
let thread = registry.find::<ThreadActor>(&browsing_context.thread);
let source = thread
.source_manager
.find_source(registry, &source_url)
.ok_or(ActorError::Internal)?;
let (script_id, offset) = source.find_offset(line, column);
source
.script_sender
.send(DevtoolScriptControlMsg::ClearBreakpoint(
source.spidermonkey_id,
script_id,
offset,
))
.map_err(|_| ActorError::Internal)?;
let msg = EmptyReplyMsg { from: self.name() };
request.reply_final(&msg)?
},
_ => return Err(ActorError::UnrecognizedPacketType),
};
Ok(())
}
}
impl BreakpointListActor {
pub fn new(name: String, browsing_context: String) -> Self {
Self {
name,
browsing_context,
}
}
}
impl ActorEncode<ActorMsg> for BreakpointListActor {
fn encode(&self, _: &ActorRegistry) -> ActorMsg {
ActorMsg { actor: self.name() }
}
}