1use atomic_refcell::AtomicRefCell;
6use devtools_traits::{DevtoolScriptControlMsg, FrameInfo};
7use malloc_size_of_derive::MallocSizeOf;
8use serde::Serialize;
9use serde_json::{Map, Value};
10use servo_base::generic_channel::channel;
11
12use crate::StreamId;
13use crate::actor::{Actor, ActorEncode, ActorError, ActorRegistry};
14use crate::actors::environment::{EnvironmentActor, EnvironmentActorMsg};
15use crate::actors::object::ObjectActor;
16use crate::actors::source::SourceActor;
17use crate::protocol::{ClientRequest, JsonPacketStream};
18
19#[derive(Serialize)]
20struct FrameEnvironmentReply {
21 from: String,
22 #[serde(flatten)]
23 environment: EnvironmentActorMsg,
24}
25
26#[derive(Serialize)]
27#[serde(rename_all = "kebab-case")]
28pub enum FrameState {
29 OnStack,
30 _Suspended,
31 _Dead,
32}
33
34#[derive(Serialize)]
35pub(crate) struct FrameWhere {
36 actor: String,
37 line: u32,
38 column: u32,
39}
40
41#[derive(Serialize)]
42#[serde(rename_all = "camelCase")]
43pub(crate) struct FrameActorMsg {
44 actor: String,
45 #[serde(rename = "type")]
46 type_: String,
47 arguments: Vec<Value>,
48 async_cause: Option<String>,
49 display_name: String,
50 oldest: bool,
51 state: FrameState,
52 this: Value,
53 #[serde(rename = "where")]
54 where_: FrameWhere,
55}
56
57#[derive(MallocSizeOf)]
60pub(crate) struct FrameActor {
61 name: String,
62 object_actor: String,
63 source_actor: String,
64 frame_result: FrameInfo,
65 current_offset: AtomicRefCell<(u32, u32)>,
66}
67
68impl Actor for FrameActor {
69 fn name(&self) -> String {
70 self.name.clone()
71 }
72
73 fn handle_message(
75 &self,
76 mut request: ClientRequest,
77 registry: &ActorRegistry,
78 msg_type: &str,
79 _msg: &Map<String, Value>,
80 _id: StreamId,
81 ) -> Result<(), ActorError> {
82 match msg_type {
83 "getEnvironment" => {
84 let Some((tx, rx)) = channel() else {
85 return Err(ActorError::Internal);
86 };
87 let source = registry.find::<SourceActor>(&self.source_actor);
88 source
89 .script_sender
90 .send(DevtoolScriptControlMsg::GetEnvironment(self.name(), tx))
91 .map_err(|_| ActorError::Internal)?;
92 let environment_name = rx.recv().map_err(|_| ActorError::Internal)?;
93
94 let msg = FrameEnvironmentReply {
95 from: self.name(),
96 environment: registry.encode::<EnvironmentActor, _>(&environment_name),
97 };
98 request.write_json_packet(&msg)?;
101 request.mark_handled();
102 },
103 _ => return Err(ActorError::UnrecognizedPacketType),
104 };
105 Ok(())
106 }
107}
108
109impl FrameActor {
110 pub fn register(
111 registry: &ActorRegistry,
112 source_actor: String,
113 frame_result: FrameInfo,
114 ) -> String {
115 let object_name = ObjectActor::register(registry, None, "Object".to_owned(), None);
116
117 let name = registry.new_name::<Self>();
118 let actor = Self {
119 name: name.clone(),
120 object_actor: object_name,
121 source_actor,
122 frame_result,
123 current_offset: Default::default(),
124 };
125 registry.register::<Self>(actor);
126 name
127 }
128
129 pub(crate) fn set_offset(&self, column: u32, line: u32) {
130 *self.current_offset.borrow_mut() = (column, line);
131 }
132}
133
134impl ActorEncode<FrameActorMsg> for FrameActor {
135 fn encode(&self, registry: &ActorRegistry) -> FrameActorMsg {
136 let state = FrameState::OnStack;
138 let async_cause = if let FrameState::OnStack = state {
139 None
140 } else {
141 Some("await".into())
142 };
143 let (column, line) = *self.current_offset.borrow();
144 FrameActorMsg {
146 actor: self.name(),
147 type_: self.frame_result.type_.clone(),
148 arguments: vec![],
149 async_cause,
150 display_name: self.frame_result.display_name.clone(),
152 this: registry.encode::<ObjectActor, _>(&self.object_actor),
153 oldest: self.frame_result.oldest,
154 state,
155 where_: FrameWhere {
156 actor: self.source_actor.clone(),
157 line,
158 column,
159 },
160 }
161 }
162}