v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
v8-deep-serializer.cc
Go to the documentation of this file.
1// Copyright 2022 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
7#include <memory>
8
10#include "include/v8-context.h"
11#include "include/v8-date.h"
13#include "include/v8-regexp.h"
14#include "src/inspector/protocol/Runtime.h"
17
18namespace v8_inspector {
19
20namespace {
21using protocol::Response;
22std::unique_ptr<protocol::Value> DescriptionForDate(
24 v8::Isolate* isolate = context->GetIsolate();
25 v8::TryCatch tryCatch(isolate);
26
27 v8::Local<v8::String> dateISOString = date->ToISOString();
28 return protocol::StringValue::create(
29 toProtocolString(isolate, dateISOString));
30}
31
32String16 DescriptionForRegExpFlags(v8::Local<v8::RegExp> value) {
33 String16Builder resultStringBuilder;
34 v8::RegExp::Flags flags = value->GetFlags();
35 if (flags & v8::RegExp::Flags::kHasIndices) resultStringBuilder.append('d');
36 if (flags & v8::RegExp::Flags::kGlobal) resultStringBuilder.append('g');
37 if (flags & v8::RegExp::Flags::kIgnoreCase) resultStringBuilder.append('i');
38 if (flags & v8::RegExp::Flags::kLinear) resultStringBuilder.append('l');
39 if (flags & v8::RegExp::Flags::kMultiline) resultStringBuilder.append('m');
40 if (flags & v8::RegExp::Flags::kDotAll) resultStringBuilder.append('s');
41 if (flags & v8::RegExp::Flags::kUnicode) resultStringBuilder.append('u');
43 resultStringBuilder.append('v');
44 }
45 if (flags & v8::RegExp::Flags::kSticky) resultStringBuilder.append('y');
46 return resultStringBuilder.toString();
47}
48
49Response SerializeRegexp(v8::Local<v8::RegExp> value,
51 V8SerializationDuplicateTracker& duplicateTracker,
52 protocol::DictionaryValue& result) {
53 result.setString("type",
54 protocol::Runtime::DeepSerializedValue::TypeEnum::Regexp);
55
56 std::unique_ptr<protocol::DictionaryValue> resultValue =
57 protocol::DictionaryValue::create();
58
59 resultValue->setValue(protocol::String("pattern"),
60 protocol::StringValue::create(toProtocolString(
61 context->GetIsolate(), value->GetSource())));
62
63 String16 flags = DescriptionForRegExpFlags(value);
64 if (!flags.isEmpty()) {
65 resultValue->setValue(protocol::String("flags"),
66 protocol::StringValue::create(flags));
67 }
68
69 result.setValue("value", std::move(resultValue));
70 return Response::Success();
71}
72
73Response SerializeDate(v8::Local<v8::Date> value,
75 V8SerializationDuplicateTracker& duplicateTracker,
76 protocol::DictionaryValue& result) {
77 result.setString("type",
78 protocol::Runtime::DeepSerializedValue::TypeEnum::Date);
79 std::unique_ptr<protocol::Value> dateDescription =
80 DescriptionForDate(context, value.As<v8::Date>());
81
82 result.setValue("value", std::move(dateDescription));
83 return Response::Success();
84}
85
86Response SerializeArrayValue(v8::Local<v8::Array> value,
87 v8::Local<v8::Context> context, int maxDepth,
88 v8::Local<v8::Object> additionalParameters,
89 V8SerializationDuplicateTracker& duplicateTracker,
90 std::unique_ptr<protocol::ListValue>* result) {
91 std::unique_ptr<protocol::ListValue> serializedValue =
92 protocol::ListValue::create();
93 uint32_t length = value->Length();
94 serializedValue->reserve(length);
95 for (uint32_t i = 0; i < length; i++) {
96 v8::Local<v8::Value> elementValue;
97 bool success = value->Get(context, i).ToLocal(&elementValue);
98 CHECK(success);
99 USE(success);
100
101 std::unique_ptr<protocol::DictionaryValue> elementProtocolValue;
102 Response response = ValueMirror::create(context, elementValue)
103 ->buildDeepSerializedValue(
104 context, maxDepth - 1, additionalParameters,
105 duplicateTracker, &elementProtocolValue);
106 if (!response.IsSuccess()) return response;
107 serializedValue->pushValue(std::move(elementProtocolValue));
108 }
109 *result = std::move(serializedValue);
110 return Response::Success();
111}
112
113Response SerializeArray(v8::Local<v8::Array> value,
114 v8::Local<v8::Context> context, int maxDepth,
115 v8::Local<v8::Object> additionalParameters,
116 V8SerializationDuplicateTracker& duplicateTracker,
117 protocol::DictionaryValue& result) {
118 result.setString("type",
119 protocol::Runtime::DeepSerializedValue::TypeEnum::Array);
120
121 if (maxDepth > 0) {
122 std::unique_ptr<protocol::ListValue> serializedValue;
123 Response response =
124 SerializeArrayValue(value, context, maxDepth, additionalParameters,
125 duplicateTracker, &serializedValue);
126 if (!response.IsSuccess()) return response;
127
128 result.setValue("value", std::move(serializedValue));
129 }
130
131 return Response::Success();
132}
133
134Response SerializeMap(v8::Local<v8::Map> value, v8::Local<v8::Context> context,
135 int maxDepth, v8::Local<v8::Object> additionalParameters,
136 V8SerializationDuplicateTracker& duplicateTracker,
137 protocol::DictionaryValue& result) {
138 result.setString("type",
139 protocol::Runtime::DeepSerializedValue::TypeEnum::Map);
140
141 if (maxDepth > 0) {
142 std::unique_ptr<protocol::ListValue> serializedValue =
143 protocol::ListValue::create();
144
145 v8::Local<v8::Array> propertiesAndValues = value->AsArray();
146
147 uint32_t length = propertiesAndValues->Length();
148 serializedValue->reserve(length);
149 for (uint32_t i = 0; i < length; i += 2) {
150 v8::Local<v8::Value> keyV8Value, propertyV8Value;
151 std::unique_ptr<protocol::Value> keyProtocolValue;
152 std::unique_ptr<protocol::DictionaryValue> propertyProtocolValue;
153
154 bool success = propertiesAndValues->Get(context, i).ToLocal(&keyV8Value);
155 CHECK(success);
156 success =
157 propertiesAndValues->Get(context, i + 1).ToLocal(&propertyV8Value);
158 CHECK(success);
159 USE(success);
160
161 if (keyV8Value->IsString()) {
162 keyProtocolValue = protocol::StringValue::create(toProtocolString(
163 context->GetIsolate(), keyV8Value.As<v8::String>()));
164 } else {
165 std::unique_ptr<protocol::DictionaryValue> keyDictionaryProtocolValue;
166 Response response =
167 ValueMirror::create(context, keyV8Value)
168 ->buildDeepSerializedValue(
169 context, maxDepth - 1, additionalParameters,
170 duplicateTracker, &keyDictionaryProtocolValue);
171 if (!response.IsSuccess()) return response;
172 keyProtocolValue = std::move(keyDictionaryProtocolValue);
173 }
174
175 Response response = ValueMirror::create(context, propertyV8Value)
176 ->buildDeepSerializedValue(
177 context, maxDepth - 1, additionalParameters,
178 duplicateTracker, &propertyProtocolValue);
179 if (!response.IsSuccess()) return response;
180
181 std::unique_ptr<protocol::ListValue> keyValueList =
182 protocol::ListValue::create();
183
184 keyValueList->pushValue(std::move(keyProtocolValue));
185 keyValueList->pushValue(std::move(propertyProtocolValue));
186
187 serializedValue->pushValue(std::move(keyValueList));
188 }
189 result.setValue("value", std::move(serializedValue));
190 }
191
192 return Response::Success();
193}
194
195Response SerializeSet(v8::Local<v8::Set> value, v8::Local<v8::Context> context,
196 int maxDepth, v8::Local<v8::Object> additionalParameters,
197 V8SerializationDuplicateTracker& duplicateTracker,
198 protocol::DictionaryValue& result) {
199 result.setString("type",
200 protocol::Runtime::DeepSerializedValue::TypeEnum::Set);
201
202 if (maxDepth > 0) {
203 std::unique_ptr<protocol::ListValue> serializedValue;
204 Response response = SerializeArrayValue(value->AsArray(), context, maxDepth,
205 additionalParameters,
206
207 duplicateTracker, &serializedValue);
208 result.setValue("value", std::move(serializedValue));
209 }
210 return Response::Success();
211}
212
213Response SerializeObjectValue(v8::Local<v8::Object> value,
214 v8::Local<v8::Context> context, int maxDepth,
215 v8::Local<v8::Object> additionalParameters,
216 V8SerializationDuplicateTracker& duplicateTracker,
217 std::unique_ptr<protocol::ListValue>* result) {
218 std::unique_ptr<protocol::ListValue> serializedValue =
219 protocol::ListValue::create();
220 // Iterate through object's enumerable properties ignoring symbols.
221 v8::Local<v8::Array> propertyNames;
222 bool success =
223 value
224 ->GetOwnPropertyNames(context,
225 static_cast<v8::PropertyFilter>(
229 .ToLocal(&propertyNames);
230 CHECK(success);
231
232 uint32_t length = propertyNames->Length();
233 serializedValue->reserve(length);
234 for (uint32_t i = 0; i < length; i++) {
235 v8::Local<v8::Value> keyV8Value, propertyV8Value;
236 std::unique_ptr<protocol::Value> keyProtocolValue;
237 std::unique_ptr<protocol::DictionaryValue> propertyProtocolValue;
238
239 success = propertyNames->Get(context, i).ToLocal(&keyV8Value);
240 CHECK(success);
241 CHECK(keyV8Value->IsString());
242
243 v8::Maybe<bool> hasRealNamedProperty =
244 value->HasRealNamedProperty(context, keyV8Value.As<v8::String>());
245 // Don't access properties with interceptors.
246 if (hasRealNamedProperty.IsNothing() || !hasRealNamedProperty.FromJust()) {
247 continue;
248 }
249 keyProtocolValue = protocol::StringValue::create(
250 toProtocolString(context->GetIsolate(), keyV8Value.As<v8::String>()));
251
252 success = value->Get(context, keyV8Value).ToLocal(&propertyV8Value);
253 CHECK(success);
254 USE(success);
255
256 Response response = ValueMirror::create(context, propertyV8Value)
257 ->buildDeepSerializedValue(
258 context, maxDepth - 1, additionalParameters,
259 duplicateTracker, &propertyProtocolValue);
260 if (!response.IsSuccess()) return response;
261
262 std::unique_ptr<protocol::ListValue> keyValueList =
263 protocol::ListValue::create();
264
265 keyValueList->pushValue(std::move(keyProtocolValue));
266 keyValueList->pushValue(std::move(propertyProtocolValue));
267
268 serializedValue->pushValue(std::move(keyValueList));
269 }
270 *result = std::move(serializedValue);
271 return Response::Success();
272}
273
274Response SerializeObject(v8::Local<v8::Object> value,
275 v8::Local<v8::Context> context, int maxDepth,
276 v8::Local<v8::Object> additionalParameters,
277 V8SerializationDuplicateTracker& duplicateTracker,
278 protocol::DictionaryValue& result) {
279 result.setString("type",
280 protocol::Runtime::DeepSerializedValue::TypeEnum::Object);
281
282 if (maxDepth > 0) {
283 std::unique_ptr<protocol::ListValue> serializedValue;
284 Response response = SerializeObjectValue(
285 value.As<v8::Object>(), context, maxDepth, additionalParameters,
286 duplicateTracker, &serializedValue);
287 if (!response.IsSuccess()) return response;
288 result.setValue("value", std::move(serializedValue));
289 }
290 return Response::Success();
291}
292} // namespace
293
295 v8::Local<v8::Object> value, v8::Local<v8::Context> context, int maxDepth,
296 v8::Local<v8::Object> additionalParameters,
297 V8SerializationDuplicateTracker& duplicateTracker,
298 protocol::DictionaryValue& result) {
299 if (value->IsArray()) {
300 return SerializeArray(value.As<v8::Array>(), context, maxDepth,
301 additionalParameters, duplicateTracker, result);
302 }
303 if (value->IsRegExp()) {
304 return SerializeRegexp(value.As<v8::RegExp>(), context, duplicateTracker,
305 result);
306 }
307 if (value->IsDate()) {
308 return SerializeDate(value.As<v8::Date>(), context, duplicateTracker,
309 result);
310 }
311 if (value->IsMap()) {
312 return SerializeMap(value.As<v8::Map>(), context, maxDepth,
313 additionalParameters, duplicateTracker, result);
314 }
315 if (value->IsSet()) {
316 return SerializeSet(value.As<v8::Set>(), context, maxDepth,
317 additionalParameters, duplicateTracker, result);
318 }
319 if (value->IsWeakMap()) {
320 result.setString("type",
321 protocol::Runtime::DeepSerializedValue::TypeEnum::Weakmap);
322 return Response::Success();
323 }
324 if (value->IsWeakSet()) {
325 result.setString("type",
326 protocol::Runtime::DeepSerializedValue::TypeEnum::Weakset);
327 return Response::Success();
328 }
329 if (value->IsNativeError()) {
330 result.setString("type",
331 protocol::Runtime::DeepSerializedValue::TypeEnum::Error);
332 return Response::Success();
333 }
334 if (value->IsProxy()) {
335 result.setString("type",
336 protocol::Runtime::DeepSerializedValue::TypeEnum::Proxy);
337 return Response::Success();
338 }
339 if (value->IsPromise()) {
340 result.setString("type",
341 protocol::Runtime::DeepSerializedValue::TypeEnum::Promise);
342 return Response::Success();
343 }
344 if (value->IsTypedArray()) {
345 result.setString(
346 "type", protocol::Runtime::DeepSerializedValue::TypeEnum::Typedarray);
347 return Response::Success();
348 }
349 if (value->IsArrayBuffer()) {
350 result.setString(
351 "type", protocol::Runtime::DeepSerializedValue::TypeEnum::Arraybuffer);
352 return Response::Success();
353 }
354 if (value->IsFunction()) {
355 result.setString(
356 "type", protocol::Runtime::DeepSerializedValue::TypeEnum::Function);
357 return Response::Success();
358 }
359 if (value->IsGeneratorObject()) {
360 result.setString(
361 "type", protocol::Runtime::DeepSerializedValue::TypeEnum::Generator);
362 return Response::Success();
363 }
364
365 // Serialize as an Object.
366 return SerializeObject(value.As<v8::Object>(), context, maxDepth,
367 additionalParameters, duplicateTracker, result);
368}
369
370} // namespace v8_inspector
V8_INLINE Local< S > As() const
V8_INLINE T FromJust() const &
Definition v8-maybe.h:64
V8_INLINE bool IsNothing() const
Definition v8-maybe.h:35
static protocol::Response serializeV8Value(v8::Local< v8::Object > value, v8::Local< v8::Context > context, int maxDepth, v8::Local< v8::Object > additionalParameters, V8SerializationDuplicateTracker &duplicateTracker, protocol::DictionaryValue &result)
static std::unique_ptr< ValueMirror > create(v8::Local< v8::Context > context, v8::Local< v8::Value > value)
DateRecord date
ZoneVector< RpoNumber > & result
v8_inspector::String16 String
Definition string-util.h:26
String16 toProtocolString(v8::Isolate *isolate, v8::Local< v8::String > value)
PropertyFilter
Definition v8-object.h:179
@ SKIP_SYMBOLS
Definition v8-object.h:185
@ ONLY_ENUMERABLE
Definition v8-object.h:182
#define CHECK(condition)
Definition logging.h:124
#define USE(...)
Definition macros.h:293