devtools/actors/
frame.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5// TODO: Remove once the actor is used
6#![allow(dead_code)]
7
8use serde::Serialize;
9use serde_json::{Map, Value};
10
11use crate::StreamId;
12use crate::actor::{Actor, ActorError, ActorRegistry};
13use crate::actors::environment::{EnvironmentActor, EnvironmentActorMsg, EnvironmentToProtocol};
14use crate::protocol::ClientRequest;
15
16#[derive(Serialize)]
17struct FrameEnvironmentReply {
18    from: String,
19    #[serde(flatten)]
20    environment: EnvironmentActorMsg,
21}
22
23#[derive(Serialize)]
24#[serde(rename_all = "kebab-case")]
25pub enum FrameState {
26    OnStack,
27    Suspended,
28    Dead,
29}
30
31#[derive(Serialize)]
32pub struct FrameWhere {
33    actor: String,
34    line: u32,
35    column: u32,
36}
37
38#[derive(Serialize)]
39#[serde(rename_all = "camelCase")]
40pub struct FrameActorMsg {
41    actor: String,
42    #[serde(rename = "type")]
43    type_: String,
44    arguments: Vec<Value>,
45    async_cause: Option<String>,
46    display_name: String,
47    oldest: bool,
48    state: FrameState,
49    #[serde(rename = "where")]
50    where_: FrameWhere,
51}
52
53/// Represents an stack frame. Used by `ThreadActor` when replying to interrupt messages.
54/// <https://searchfox.org/firefox-main/source/devtools/server/actors/frame.js>
55pub struct FrameActor {
56    pub name: String,
57    pub source_actor: String,
58}
59
60impl Actor for FrameActor {
61    fn name(&self) -> String {
62        self.name.clone()
63    }
64
65    // https://searchfox.org/firefox-main/source/devtools/shared/specs/frame.js
66    fn handle_message(
67        &self,
68        request: ClientRequest,
69        registry: &ActorRegistry,
70        msg_type: &str,
71        _msg: &Map<String, Value>,
72        _id: StreamId,
73    ) -> Result<(), ActorError> {
74        match msg_type {
75            "getEnvironment" => {
76                let environment = EnvironmentActor {
77                    name: registry.new_name("environment"),
78                    parent: None,
79                };
80                let msg = FrameEnvironmentReply {
81                    from: self.name(),
82                    environment: environment.encode(registry),
83                };
84                registry.register_later(Box::new(environment));
85                request.reply_final(&msg)?
86            },
87            _ => return Err(ActorError::UnrecognizedPacketType),
88        };
89        Ok(())
90    }
91}
92
93pub trait FrameToProtocol {
94    fn encode(self) -> FrameActorMsg;
95}
96
97impl FrameToProtocol for FrameActor {
98    fn encode(self) -> FrameActorMsg {
99        // TODO: Handle other states
100        let state = FrameState::OnStack;
101        let async_cause = if let FrameState::OnStack = state {
102            None
103        } else {
104            Some("await".into())
105        };
106        FrameActorMsg {
107            actor: self.name,
108            type_: "call".into(),
109            arguments: vec![],
110            async_cause,
111            display_name: "".into(), // TODO: get display name
112            oldest: true,
113            state,
114            where_: FrameWhere {
115                actor: self.source_actor,
116                line: 1, // TODO: get from breakpoint?
117                column: 1,
118            },
119        }
120    }
121}