Files
servo/components/devtools/actors/worker.rs
Narfinger 870576f948 devtools: Implement MallocSizeOf for DevtoolsInstance (#42478)
This implements MallocSizeOf for DevtoolsInstance. Major changes:
- Newtype for ActorRegistry because AtomicRefCell<HashMap<String,
Arc<dyn Actor>>> did not like mallocsizeof (even with trait bound on
Actor)
- Implement MallocSizeOf for BTreeSet.
- Implement MallocSizeOf of 0 for AtomicU32 and TcpStream
- Ignore a couple of MallocSizeof for http::Method, http::HeaderMap and
json::Value

Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>

Testing: Compilation is the test.
Fixes: Part of addressing https://github.com/servo/servo/issues/42453

---------

Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>
2026-02-10 17:32:47 +00:00

179 lines
5.2 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 std::collections::HashMap;
use std::net::TcpStream;
use atomic_refcell::AtomicRefCell;
use base::generic_channel::GenericSender;
use base::id::TEST_PIPELINE_ID;
use devtools_traits::DevtoolScriptControlMsg::WantsLiveNotifications;
use devtools_traits::{DevtoolScriptControlMsg, WorkerId};
use malloc_size_of_derive::MallocSizeOf;
use serde::Serialize;
use serde_json::{Map, Value};
use servo_url::ServoUrl;
use crate::StreamId;
use crate::actor::{Actor, ActorEncode, ActorError, ActorRegistry};
use crate::protocol::{ClientRequest, JsonPacketStream};
use crate::resource::ResourceAvailable;
#[derive(Clone, Copy, MallocSizeOf)]
#[expect(dead_code)]
pub enum WorkerType {
Dedicated = 0,
Shared = 1,
Service = 2,
}
#[derive(MallocSizeOf)]
pub(crate) struct WorkerActor {
pub name: String,
pub console: String,
pub thread: String,
pub worker_id: WorkerId,
pub url: ServoUrl,
pub type_: WorkerType,
pub script_chan: GenericSender<DevtoolScriptControlMsg>,
pub streams: AtomicRefCell<HashMap<StreamId, TcpStream>>,
}
impl ResourceAvailable for WorkerActor {
fn actor_name(&self) -> String {
self.name.clone()
}
}
impl Actor for WorkerActor {
fn name(&self) -> String {
self.name.clone()
}
fn handle_message(
&self,
mut request: ClientRequest,
_registry: &ActorRegistry,
msg_type: &str,
_msg: &Map<String, Value>,
stream_id: StreamId,
) -> Result<(), ActorError> {
match msg_type {
"attach" => {
let msg = AttachedReply {
from: self.name(),
type_: "attached".to_owned(),
url: self.url.as_str().to_owned(),
};
// FIXME: we dont send an actual reply (message without type), which seems to be a bug?
request.write_json_packet(&msg)?;
self.streams
.borrow_mut()
.insert(stream_id, request.try_clone_stream().unwrap());
// FIXME: fix messages to not require forging a pipeline for worker messages
self.script_chan
.send(WantsLiveNotifications(TEST_PIPELINE_ID, true))
.unwrap();
},
"connect" => {
let msg = ConnectReply {
from: self.name(),
type_: "connected".to_owned(),
thread_actor: self.thread.clone(),
console_actor: self.console.clone(),
};
// FIXME: we dont send an actual reply (message without type), which seems to be a bug?
request.write_json_packet(&msg)?;
},
"detach" => {
let msg = DetachedReply {
from: self.name(),
type_: "detached".to_string(),
};
self.cleanup(stream_id);
// FIXME: we dont send an actual reply (message without type), which seems to be a bug?
request.write_json_packet(&msg)?;
},
_ => return Err(ActorError::UnrecognizedPacketType),
};
Ok(())
}
fn cleanup(&self, stream_id: StreamId) {
self.streams.borrow_mut().remove(&stream_id);
if self.streams.borrow().is_empty() {
self.script_chan
.send(WantsLiveNotifications(TEST_PIPELINE_ID, false))
.unwrap();
}
}
}
#[derive(Serialize)]
struct DetachedReply {
from: String,
#[serde(rename = "type")]
type_: String,
}
#[derive(Serialize)]
struct AttachedReply {
from: String,
#[serde(rename = "type")]
type_: String,
url: String,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct ConnectReply {
from: String,
#[serde(rename = "type")]
type_: String,
thread_actor: String,
console_actor: String,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct WorkerTraits {
is_parent_intercept_enabled: bool,
supports_top_level_target_flag: bool,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct WorkerActorMsg {
actor: String,
console_actor: String,
thread_actor: String,
id: String,
url: String,
traits: WorkerTraits,
#[serde(rename = "type")]
type_: u32,
#[serde(rename = "targetType")]
target_type: String,
}
impl ActorEncode<WorkerActorMsg> for WorkerActor {
fn encode(&self, _: &ActorRegistry) -> WorkerActorMsg {
WorkerActorMsg {
actor: self.name(),
console_actor: self.console.clone(),
thread_actor: self.thread.clone(),
id: self.worker_id.0.to_string(),
url: self.url.to_string(),
traits: WorkerTraits {
is_parent_intercept_enabled: false,
supports_top_level_target_flag: false,
},
type_: self.type_ as u32,
target_type: "worker".to_string(),
}
}
}