devtools/actors/
environment.rs1use std::collections::HashMap;
6
7use atomic_refcell::AtomicRefCell;
8use devtools_traits::{DebuggerValue, EnvironmentInfo};
9use malloc_size_of_derive::MallocSizeOf;
10use serde::Serialize;
11use serde_json::Value;
12
13use crate::actor::{Actor, ActorEncode, ActorRegistry, new_actor_name};
14use crate::actors::console::ConsoleActor;
15use crate::actors::object::ObjectPropertyDescriptor;
16use crate::debugger_value_to_json;
17
18#[derive(Serialize)]
19struct EnvironmentBindings {
20 arguments: Vec<Value>,
21 variables: HashMap<String, ObjectPropertyDescriptor>,
22}
23
24#[derive(Serialize)]
25#[serde(rename_all = "camelCase")]
26struct EnvironmentFunction {
27 display_name: String,
28}
29
30#[derive(Serialize)]
31#[serde(rename_all = "camelCase")]
32pub(crate) struct EnvironmentActorMsg {
33 actor: String,
34 #[serde(rename = "type")]
35 type_: Option<String>,
36 scope_kind: Option<String>,
37 #[serde(skip_serializing_if = "Option::is_none")]
38 parent: Option<Box<EnvironmentActorMsg>>,
39 #[serde(skip_serializing_if = "Option::is_none")]
40 bindings: Option<EnvironmentBindings>,
41 #[serde(skip_serializing_if = "Option::is_none")]
43 function: Option<EnvironmentFunction>,
44 #[serde(skip_serializing_if = "Option::is_none")]
46 object: Option<Value>,
47}
48
49#[derive(MallocSizeOf)]
53pub(crate) struct EnvironmentActor {
54 name: String,
55 environment: AtomicRefCell<EnvironmentInfo>,
56 parent_name: Option<String>,
57}
58
59impl Actor for EnvironmentActor {
60 fn name(&self) -> &str {
61 &self.name
62 }
63}
64
65impl EnvironmentActor {
66 pub fn register_or_update(
67 registry: &ActorRegistry,
68 environment: EnvironmentInfo,
69 parent_name: Option<String>,
70 actor_name: Option<String>,
71 ) -> String {
72 if let Some(actor_name) = actor_name {
73 let environment_actor = registry.find::<Self>(&actor_name);
74 *environment_actor.environment.borrow_mut() = environment;
75 return actor_name;
76 }
77
78 let environment_name = new_actor_name::<Self>();
79 let environment_actor = Self {
80 name: environment_name.clone(),
81 parent_name,
82 environment: environment.into(),
83 };
84 registry.register(environment_actor);
85 environment_name
86 }
87
88 pub(crate) fn search_identifiers_recursive(
91 &self,
92 registry: &ActorRegistry,
93 prefix: &str,
94 ) -> Vec<String> {
95 let mut names: Vec<String> = vec![];
96 self.recurse_identifiers(registry, prefix, &mut names);
97
98 names.sort_unstable();
99 names.dedup();
100 names
101 }
102
103 fn recurse_identifiers(&self, registry: &ActorRegistry, prefix: &str, names: &mut Vec<String>) {
104 let environment = self.environment.borrow();
105 names.extend(
106 environment
107 .binding_variables
108 .iter()
109 .map(|bind| &bind.name)
110 .filter(|name| ConsoleActor::autocomplete_match(prefix, name))
111 .cloned(),
112 );
113
114 if let Some(DebuggerValue::ObjectValue {
115 preview: Some(preview),
116 ..
117 }) = &environment.object &&
118 let Some(props) = &preview.own_properties
119 {
120 names.extend(
121 props
122 .iter()
123 .map(|p| &p.name)
124 .filter(|name| ConsoleActor::autocomplete_match(prefix, name))
125 .cloned(),
126 );
127 }
128
129 if let Some(parent_name) = &self.parent_name {
130 registry
131 .find::<EnvironmentActor>(parent_name)
132 .recurse_identifiers(registry, prefix, names);
133 }
134 }
135}
136
137impl ActorEncode<EnvironmentActorMsg> for EnvironmentActor {
138 fn encode(&self, registry: &ActorRegistry) -> EnvironmentActorMsg {
139 let parent = self
140 .parent_name
141 .as_ref()
142 .map(|p| registry.find::<EnvironmentActor>(p))
143 .map(|p| Box::new(p.encode(registry)));
144 let environment = self.environment.borrow();
145 let bindings = match environment.type_.as_deref() {
146 Some("object") | Some("with") => None,
147 _ => Some(EnvironmentBindings {
148 arguments: [].to_vec(),
149 variables: environment
150 .binding_variables
151 .clone()
152 .into_iter()
153 .map(|ref property_descriptor| {
154 (
155 property_descriptor.name.clone(),
156 ObjectPropertyDescriptor::from_property_descriptor(
157 registry,
158 property_descriptor,
159 ),
160 )
161 })
162 .collect(),
163 }),
164 };
165
166 EnvironmentActorMsg {
167 actor: self.name().to_string(),
168 type_: environment.type_.clone(),
169 scope_kind: environment.scope_kind.clone(),
170 parent,
171 function: environment
172 .function_display_name
173 .clone()
174 .map(|display_name| EnvironmentFunction { display_name }),
175 object: environment
176 .object
177 .clone()
178 .map(|object| debugger_value_to_json(registry, object)),
179 bindings,
180 }
181 }
182}