• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "tooling/inspector/types/remote_object.h"
17 
18 #include "macros.h"
19 #include "tooling/inspector/types/property_descriptor.h"
20 #include "utils/json_builder.h"
21 #include "utils/string_helpers.h"
22 
23 #include <cstddef>
24 #include <cstdint>
25 #include <functional>
26 #include <optional>
27 #include <sstream>
28 #include <string>
29 #include <utility>
30 #include <variant>
31 
32 using ark::helpers::string::Format;
33 
34 namespace ark::tooling::inspector {
GeneratePreview(const std::vector<PropertyDescriptor> & properties) const35 void RemoteObject::GeneratePreview(const std::vector<PropertyDescriptor> &properties) const
36 {
37     preview_.clear();
38 
39     for (auto &property : properties) {
40         if (!property.IsEnumerable()) {
41             continue;
42         }
43 
44         if (property.IsAccessor()) {
45             preview_.push_back(PreviewProperty {property.GetName(), Type::Accessor(), {}, property.IsEntry()});
46             continue;
47         }
48 
49         const auto &value = property.GetValue().value_;
50         std::optional<std::string> valuePreview;
51 
52         if (std::holds_alternative<std::nullptr_t>(value)) {
53             valuePreview.emplace("null");
54         } else if (auto boolean = std::get_if<bool>(&value)) {
55             valuePreview.emplace(*boolean ? "true" : "false");
56         } else if (auto number = std::get_if<NumberT>(&value)) {
57             if (auto integer = std::get_if<int32_t>(number)) {
58                 valuePreview.emplace(std::to_string(*integer));
59             } else if (auto floatingPoint = std::get_if<double>(number)) {
60                 valuePreview.emplace(Format("%g", *floatingPoint));  // NOLINT(cppcoreguidelines-pro-type-vararg)
61             } else {
62                 UNREACHABLE();
63             }
64         } else if (auto bigint = std::get_if<BigIntT>(&value)) {
65             valuePreview.emplace(GetDescription(*bigint));
66         } else if (auto string = std::get_if<std::string>(&value)) {
67             valuePreview.emplace(*string);
68         } else if (auto symbol = std::get_if<SymbolT>(&value)) {
69             valuePreview.emplace(symbol->description);
70         } else if (auto object = std::get_if<ObjectT>(&value)) {
71             valuePreview.emplace(GetDescription(*object));
72         } else if (auto array = std::get_if<ArrayT>(&value)) {
73             valuePreview.emplace(GetDescription(*array));
74         } else if (auto function = std::get_if<FunctionT>(&value)) {
75             valuePreview.emplace(function->name);
76         }
77 
78         preview_.push_back(PreviewProperty {property.GetName(), property.GetValue().GetType(), std::move(valuePreview),
79                                             property.IsEntry()});
80     }
81 }
82 
83 template <typename T>
AddElement(std::function<void (JsonArrayBuilder &)> & func,T value)84 static void AddElement(std::function<void(JsonArrayBuilder &)> &func, T value)
85 {
86     func = [func = std::move(func), value = std::move(value)](JsonArrayBuilder &builder) {
87         func(builder);
88         builder.Add(value);
89     };
90 }
91 
92 template <typename T>
AddProperty(std::function<void (JsonObjectBuilder &)> & func,const char * key,T value)93 static void AddProperty(std::function<void(JsonObjectBuilder &)> &func, const char *key, T value)
94 {
95     func = [func = std::move(func), key, value = std::move(value)](JsonObjectBuilder &builder) {
96         func(builder);
97         builder.AddProperty(key, value);
98     };
99 }
100 
GetDescription(const RemoteObject::BigIntT & bigint)101 std::string RemoteObject::GetDescription(const RemoteObject::BigIntT &bigint)
102 {
103     return (bigint.sign >= 0 ? "" : "-") + std::to_string(bigint.value);
104 }
105 
GetDescription(const RemoteObject::ObjectT & object)106 std::string RemoteObject::GetDescription(const RemoteObject::ObjectT &object)
107 {
108     return object.description.value_or(object.className);
109 }
110 
GetDescription(const RemoteObject::ArrayT & array)111 std::string RemoteObject::GetDescription(const RemoteObject::ArrayT &array)
112 {
113     return array.className + "(" + std::to_string(array.length) + ")";
114 }
115 
GetDescription(const RemoteObject::FunctionT & function)116 std::string RemoteObject::GetDescription(const RemoteObject::FunctionT &function)
117 {
118     std::stringstream desc;
119 
120     desc << "function " << function.name << "(";
121 
122     for (auto argIdx = 0U; argIdx < function.length; ++argIdx) {
123         if (argIdx != 0) {
124             desc << ", ";
125         }
126         desc << static_cast<char>('a' + argIdx);
127     }
128 
129     desc << ") { [not available] }";
130 
131     return desc.str();
132 }
133 
GetObjectId() const134 std::optional<RemoteObjectId> RemoteObject::GetObjectId() const
135 {
136     if (auto object = std::get_if<ObjectT>(&value_)) {
137         return object->objectId;
138     }
139     if (auto array = std::get_if<ArrayT>(&value_)) {
140         return array->objectId;
141     }
142     if (auto function = std::get_if<FunctionT>(&value_)) {
143         return function->objectId;
144     }
145     return {};
146 }
147 
GetType() const148 RemoteObject::Type RemoteObject::GetType() const
149 {
150     if (std::holds_alternative<std::monostate>(value_)) {
151         return Type("undefined");
152     }
153     if (std::holds_alternative<std::nullptr_t>(value_)) {
154         return Type("object", "null");
155     }
156     if (std::holds_alternative<bool>(value_)) {
157         return Type("boolean");
158     }
159     if (std::holds_alternative<NumberT>(value_)) {
160         return Type("number");
161     }
162     if (std::holds_alternative<BigIntT>(value_)) {
163         return Type("bigint");
164     }
165     if (std::holds_alternative<std::string>(value_)) {
166         return Type("string");
167     }
168     if (std::holds_alternative<SymbolT>(value_)) {
169         return Type("symbol");
170     }
171     if (std::holds_alternative<ObjectT>(value_)) {
172         return Type("object");
173     }
174     if (std::holds_alternative<ArrayT>(value_)) {
175         return Type("object", "array");
176     }
177     if (std::holds_alternative<FunctionT>(value_)) {
178         return Type("function");
179     }
180 
181     UNREACHABLE();
182 }
183 
PreviewToJson() const184 std::function<void(JsonObjectBuilder &)> RemoteObject::PreviewToJson() const
185 {
186     std::function<void(JsonArrayBuilder &)> properties = [](auto &) {};
187     std::function<void(JsonArrayBuilder &)> entries = [](auto &) {};
188     bool hasEntries = false;
189 
190     for (auto &previewProperty : preview_) {
191         auto property = previewProperty.type.ToJson();
192 
193         if (previewProperty.isEntry) {
194             auto value = property;
195 
196             if (previewProperty.value) {
197                 AddProperty(value, "description", *previewProperty.value);
198             }
199 
200             std::function<void(JsonObjectBuilder &)> entry = [](auto &) {};
201             AddProperty(entry, "value", std::move(value));
202 
203             AddElement(entries, std::move(entry));
204             hasEntries = true;
205         }
206 
207         AddProperty(property, "name", previewProperty.name);
208 
209         if (previewProperty.value) {
210             AddProperty(property, "value", *previewProperty.value);
211         }
212 
213         AddElement(properties, std::move(property));
214     }
215 
216     auto result = GetType().ToJson();
217 
218     AddProperty(result, "overflow", false);
219     AddProperty(result, "properties", std::move(properties));
220 
221     if (hasEntries) {
222         AddProperty(result, "entries", std::move(entries));
223     }
224 
225     return result;
226 }
227 
ToJson() const228 std::function<void(JsonObjectBuilder &)> RemoteObject::ToJson() const
229 {
230     auto result = GetType().ToJson();
231 
232     if (std::holds_alternative<std::nullptr_t>(value_)) {
233         AddProperty(result, "value", nullptr);
234     } else if (auto boolean = std::get_if<bool>(&value_)) {
235         AddProperty(result, "value", *boolean);
236     } else if (auto number = std::get_if<NumberT>(&value_)) {
237         if (auto integer = std::get_if<int32_t>(number)) {
238             AddProperty(result, "value", *integer);
239         } else if (auto floatingPoint = std::get_if<double>(number)) {
240             AddProperty(result, "value", *floatingPoint);
241         } else {
242             UNREACHABLE();
243         }
244     } else if (auto bigint = std::get_if<BigIntT>(&value_)) {
245         AddProperty(result, "unserializableValue", GetDescription(*bigint));
246     } else if (auto string = std::get_if<std::string>(&value_)) {
247         AddProperty(result, "value", *string);
248     } else if (auto symbol = std::get_if<SymbolT>(&value_)) {
249         AddProperty(result, "description", symbol->description);
250     } else if (auto object = std::get_if<ObjectT>(&value_)) {
251         AddProperty(result, "className", object->className);
252         AddProperty(result, "description", GetDescription(*object));
253     } else if (auto array = std::get_if<ArrayT>(&value_)) {
254         AddProperty(result, "className", array->className);
255         AddProperty(result, "description", GetDescription(*array));
256     } else if (auto function = std::get_if<FunctionT>(&value_)) {
257         AddProperty(result, "className", function->className);
258         AddProperty(result, "description", GetDescription(*function));
259     }
260 
261     if (auto objectId = GetObjectId()) {
262         AddProperty(result, "objectId", std::to_string(*objectId));
263     }
264 
265     if (!preview_.empty()) {
266         AddProperty(result, "preview", PreviewToJson());
267     }
268 
269     return result;
270 }
271 
ToJson() const272 std::function<void(JsonObjectBuilder &)> RemoteObject::Type::ToJson() const
273 {
274     std::function<void(JsonObjectBuilder &)> result = [](auto &) {};
275 
276     AddProperty(result, "type", type_);
277 
278     if (subtype_ != nullptr) {
279         AddProperty(result, "subtype", subtype_);
280     }
281 
282     return result;
283 }
284 }  // namespace ark::tooling::inspector
285