From 319f4f0e38efff4f9a314d640554c726a0db6f0f Mon Sep 17 00:00:00 2001 From: shuppy Date: Tue, 12 Aug 2025 20:26:59 +0800 Subject: [PATCH] devtools: Fix `getBreakpointListActor` handler in watcher actor (#38624) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit the Firefox devtools client often sends multiple `getBreakpointListActor` requests to the watcher actor when connecting, and the Firefox devtools server returns the same breakpoint list actor every time, but Servo returns a new breakpoint list actor each time. this patch aligns Servo’s behaviour with Firefox. Testing: this patch adds a devtools test Signed-off-by: Delan Azabani Co-authored-by: atbrakhi --- components/devtools/actors/breakpoint.rs | 4 ++++ components/devtools/actors/watcher.rs | 21 ++++++++------------- python/servo/devtools_tests.py | 12 ++++++++++-- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/components/devtools/actors/breakpoint.rs b/components/devtools/actors/breakpoint.rs index b5168e5ee3a..f25f42b9a76 100644 --- a/components/devtools/actors/breakpoint.rs +++ b/components/devtools/actors/breakpoint.rs @@ -52,4 +52,8 @@ impl BreakpointListActor { pub fn new(name: String) -> Self { Self { name } } + + pub fn encodable(&self) -> BreakpointListActorMsg { + BreakpointListActorMsg { actor: self.name() } + } } diff --git a/components/devtools/actors/watcher.rs b/components/devtools/actors/watcher.rs index 4b904acb368..83596808510 100644 --- a/components/devtools/actors/watcher.rs +++ b/components/devtools/actors/watcher.rs @@ -25,6 +25,7 @@ use super::breakpoint::BreakpointListActor; use super::thread::ThreadActor; use super::worker::WorkerMsg; use crate::actor::{Actor, ActorError, ActorRegistry}; +use crate::actors::breakpoint::BreakpointListActorMsg; use crate::actors::browsing_context::{BrowsingContextActor, BrowsingContextActorMsg}; use crate::actors::root::RootActor; use crate::actors::watcher::target_configuration::{ @@ -151,12 +152,7 @@ struct GetThreadConfigurationActorReply { #[serde(rename_all = "camelCase")] struct GetBreakpointListActorReply { from: String, - breakpoint_list: GetBreakpointListActorReplyInner, -} - -#[derive(Serialize)] -struct GetBreakpointListActorReplyInner { - actor: String, + breakpoint_list: BreakpointListActorMsg, } #[derive(Serialize)] @@ -191,6 +187,7 @@ pub struct WatcherActor { network_parent: String, target_configuration: String, thread_configuration: String, + breakpoint_list: String, session_context: SessionContext, } @@ -376,15 +373,10 @@ impl Actor for WatcherActor { request.reply_final(&msg)? }, "getBreakpointListActor" => { - let breakpoint_list_name = registry.new_name("breakpoint-list"); - let breakpoint_list = BreakpointListActor::new(breakpoint_list_name.clone()); - registry.register_later(Box::new(breakpoint_list)); - + let breakpoint_list = registry.find::(&self.breakpoint_list); request.reply_final(&GetBreakpointListActorReply { from: self.name(), - breakpoint_list: GetBreakpointListActorReplyInner { - actor: breakpoint_list_name, - }, + breakpoint_list: breakpoint_list.encodable(), })? }, _ => return Err(ActorError::UnrecognizedPacketType), @@ -410,6 +402,7 @@ impl WatcherActor { TargetConfigurationActor::new(actors.new_name("target-configuration")); let thread_configuration = ThreadConfigurationActor::new(actors.new_name("thread-configuration")); + let breakpoint_list = BreakpointListActor::new(actors.new_name("breakpoint-list")); let watcher = Self { name: actors.new_name("watcher"), @@ -417,12 +410,14 @@ impl WatcherActor { network_parent: network_parent.name(), target_configuration: target_configuration.name(), thread_configuration: thread_configuration.name(), + breakpoint_list: breakpoint_list.name(), session_context, }; actors.register(Box::new(network_parent)); actors.register(Box::new(target_configuration)); actors.register(Box::new(thread_configuration)); + actors.register(Box::new(breakpoint_list)); watcher } diff --git a/python/servo/devtools_tests.py b/python/servo/devtools_tests.py index e294bdc7c65..c1043ce42df 100644 --- a/python/servo/devtools_tests.py +++ b/python/servo/devtools_tests.py @@ -57,6 +57,16 @@ class DevtoolsTests(unittest.IsolatedAsyncioTestCase): self.web_servers = None self.web_server_threads = None + # Watcher tests + + def test_watcher_returns_same_breakpoint_list_actor_every_time(self): + self.run_servoshell(url="data:text/html,") + devtools = self._setup_devtools_client() + response1 = devtools.watcher.get_breakpoint_list_actor() + response2 = devtools.watcher.get_breakpoint_list_actor() + self.assertEqual(response1["breakpointList"]["actor"], response2["breakpointList"]["actor"]) + + # Sources list # Classic script vs module script: # - # - @@ -66,8 +76,6 @@ class DevtoolsTests(unittest.IsolatedAsyncioTestCase): # Non-worker(?) script sources can be inline, external, or blob. # Worker script sources can be external or blob. - # Sources list - def test_sources_list(self): self.start_web_server(test_dir=os.path.join(DevtoolsTests.script_path, "devtools_tests/sources")) self.run_servoshell()