devtools/actors/
environment.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
5use std::collections::HashMap;
6
7use devtools_traits::EnvironmentInfo;
8use malloc_size_of_derive::MallocSizeOf;
9use serde::Serialize;
10use serde_json::Value;
11
12use crate::actor::{Actor, ActorEncode, ActorRegistry};
13use crate::actors::object::{ObjectActorMsg, ObjectPropertyDescriptor};
14
15#[derive(Serialize)]
16struct EnvironmentBindings {
17    arguments: Vec<Value>,
18    variables: HashMap<String, ObjectPropertyDescriptor>,
19}
20
21#[derive(Serialize)]
22#[serde(rename_all = "camelCase")]
23struct EnvironmentFunction {
24    display_name: String,
25}
26
27#[derive(Serialize)]
28#[serde(rename_all = "camelCase")]
29pub(crate) struct EnvironmentActorMsg {
30    actor: String,
31    #[serde(rename = "type")]
32    type_: Option<String>,
33    scope_kind: Option<String>,
34    #[serde(skip_serializing_if = "Option::is_none")]
35    parent: Option<Box<EnvironmentActorMsg>>,
36    #[serde(skip_serializing_if = "Option::is_none")]
37    bindings: Option<EnvironmentBindings>,
38    /// Should be set if `type_` is `EnvironmentType::Function`
39    #[serde(skip_serializing_if = "Option::is_none")]
40    function: Option<EnvironmentFunction>,
41    /// Should be set if `type_` is `EnvironmentType::Object`
42    #[serde(skip_serializing_if = "Option::is_none")]
43    object: Option<ObjectActorMsg>,
44}
45
46/// Resposible for listing the bindings in an environment and assigning new values to them.
47/// Referenced by `FrameActor` when replying to `getEnvironment` messages.
48/// <https://searchfox.org/firefox-main/source/devtools/server/actors/environment.js>
49#[derive(MallocSizeOf)]
50pub(crate) struct EnvironmentActor {
51    name: String,
52    environment: EnvironmentInfo,
53    parent_name: Option<String>,
54}
55
56impl Actor for EnvironmentActor {
57    fn name(&self) -> String {
58        self.name.clone()
59    }
60}
61
62impl EnvironmentActor {
63    pub fn register(
64        registry: &ActorRegistry,
65        environment: EnvironmentInfo,
66        parent_name: Option<String>,
67    ) -> String {
68        let environment_name = registry.new_name::<Self>();
69        let environment_actor = Self {
70            name: environment_name.clone(),
71            parent_name,
72            environment,
73        };
74        registry.register(environment_actor);
75        environment_name
76    }
77}
78
79impl ActorEncode<EnvironmentActorMsg> for EnvironmentActor {
80    fn encode(&self, registry: &ActorRegistry) -> EnvironmentActorMsg {
81        let parent = self
82            .parent_name
83            .as_ref()
84            .map(|p| registry.find::<EnvironmentActor>(p))
85            .map(|p| Box::new(p.encode(registry)));
86        // TODO: Change hardcoded values.
87        EnvironmentActorMsg {
88            actor: self.name(),
89            type_: self.environment.type_.clone(),
90            scope_kind: self.environment.scope_kind.clone(),
91            parent,
92            function: self
93                .environment
94                .function_display_name
95                .clone()
96                .map(|display_name| EnvironmentFunction { display_name }),
97            object: None,
98            bindings: Some(EnvironmentBindings {
99                arguments: [].to_vec(),
100                variables: self
101                    .environment
102                    .binding_variables
103                    .clone()
104                    .into_iter()
105                    .map(|ref property_descriptor| {
106                        (
107                            property_descriptor.name.clone(),
108                            ObjectPropertyDescriptor::from_property_descriptor(
109                                registry,
110                                property_descriptor,
111                            ),
112                        )
113                    })
114                    .collect(),
115            }),
116        }
117    }
118}