Commit c674a1f6 authored by Maksim Sadym's avatar Maksim Sadym Committed by V8 LUCI CQ

Follow-up after https://crrev.com/c/3472077

1. Use `StringBuffer` instead of `StringView` in `WebDriverValue`.
2. Add some `DCHECK`s.
3. Reserve vector size.
4. Respect properties with `undefined` values.
5. Minor clean-ups.

Change-Id: Ic109acb1e3adf2d950767173c17a9203e3c816dc
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3596173Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Auto-Submit: Maksim Sadym <sadym@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80296}
parent 76751fc3
...@@ -1347,7 +1347,9 @@ domain Runtime ...@@ -1347,7 +1347,9 @@ domain Runtime
optional string objectGroup optional string objectGroup
# Whether to throw an exception if side effect cannot be ruled out during evaluation. # Whether to throw an exception if side effect cannot be ruled out during evaluation.
experimental optional boolean throwOnSideEffect experimental optional boolean throwOnSideEffect
# Whether the result should be serialized according to https://w3c.github.io/webdriver-bidi. # Whether the result should contain `webDriverValue`, serialized according to
# https://w3c.github.io/webdriver-bidi. This is mutually exclusive with `returnByValue`, but
# resulting `objectId` is still provided.
experimental optional boolean generateWebDriverValue experimental optional boolean generateWebDriverValue
returns returns
# Call result. # Call result.
......
...@@ -207,10 +207,10 @@ class V8_EXPORT V8InspectorSession { ...@@ -207,10 +207,10 @@ class V8_EXPORT V8InspectorSession {
class V8_EXPORT WebDriverValue { class V8_EXPORT WebDriverValue {
public: public:
explicit WebDriverValue(StringView type, v8::MaybeLocal<v8::Value> value = {}) explicit WebDriverValue(std::unique_ptr<StringBuffer> type,
: type(type), value(value) {} v8::MaybeLocal<v8::Value> value = {})
: type(std::move(type)), value(value) {}
StringView type; std::unique_ptr<StringBuffer> type;
v8::MaybeLocal<v8::Value> value; v8::MaybeLocal<v8::Value> value;
}; };
......
...@@ -576,8 +576,8 @@ Response InjectedScript::wrapObjectMirror( ...@@ -576,8 +576,8 @@ Response InjectedScript::wrapObjectMirror(
} }
if (wrapMode == WrapMode::kGenerateWebDriverValue) { if (wrapMode == WrapMode::kGenerateWebDriverValue) {
int maxDepth = 1; int maxDepth = 1;
std::unique_ptr<protocol::Runtime::WebDriverValue> webDriverValue; std::unique_ptr<protocol::Runtime::WebDriverValue> webDriverValue =
response = mirror.buildWebDriverValue(context, maxDepth, &webDriverValue); mirror.buildWebDriverValue(context, maxDepth);
if (!response.IsSuccess()) return response; if (!response.IsSuccess()) return response;
(*result)->setWebDriverValue(std::move(webDriverValue)); (*result)->setWebDriverValue(std::move(webDriverValue));
} }
......
...@@ -14,46 +14,38 @@ ...@@ -14,46 +14,38 @@
namespace v8_inspector { namespace v8_inspector {
namespace {
using protocol::Response; using protocol::Response;
// private std::unique_ptr<protocol::Value> SerializeRecursively(
protocol::Response _serializeRecursively( v8::Local<v8::Value> value, v8::Local<v8::Context> context, int max_depth) {
v8::Local<v8::Value> value, v8::Local<v8::Context> context, int max_depth,
std::unique_ptr<protocol::Value>* result) {
std::unique_ptr<ValueMirror> mirror = ValueMirror::create(context, value); std::unique_ptr<ValueMirror> mirror = ValueMirror::create(context, value);
std::unique_ptr<protocol::Runtime::WebDriverValue> webDriver_value; std::unique_ptr<protocol::Runtime::WebDriverValue> web_driver_value =
Response response = mirror->buildWebDriverValue(context, max_depth - 1);
mirror->buildWebDriverValue(context, max_depth - 1, &webDriver_value); DCHECK(web_driver_value);
if (!response.IsSuccess()) return response;
if (!webDriver_value) return Response::InternalError();
std::unique_ptr<protocol::DictionaryValue> result_dict = std::unique_ptr<protocol::DictionaryValue> result_dict =
protocol::DictionaryValue::create(); protocol::DictionaryValue::create();
result_dict->setValue( result_dict->setValue(
protocol::String("type"), protocol::String("type"),
protocol::StringValue::create(webDriver_value->getType())); protocol::StringValue::create(web_driver_value->getType()));
if (webDriver_value->hasValue()) if (web_driver_value->hasValue()) {
result_dict->setValue(protocol::String("value"), result_dict->setValue(protocol::String("value"),
webDriver_value->getValue(nullptr)->clone()); web_driver_value->getValue(nullptr)->clone());
}
(*result) = std::move(result_dict); return result_dict;
return Response::Success();
}
String16 descriptionForObject(v8::Isolate* isolate,
v8::Local<v8::Object> object) {
return toProtocolString(isolate, object->GetConstructorName());
} }
String16 descriptionForDate(v8::Local<v8::Context> context, std::unique_ptr<protocol::Value> DescriptionForDate(
v8::Local<v8::Date> date) { v8::Local<v8::Context> context, v8::Local<v8::Date> date) {
v8::Isolate* isolate = context->GetIsolate(); v8::Isolate* isolate = context->GetIsolate();
v8::TryCatch tryCatch(isolate); v8::TryCatch tryCatch(isolate);
v8::Local<v8::String> description; v8::Local<v8::String> description;
if (!date->ToString(context).ToLocal(&description)) { bool success = date->ToString(context).ToLocal(&description);
return descriptionForObject(isolate, date); DCHECK(success);
} USE(success);
return toProtocolString(isolate, description);
return protocol::StringValue::create(toProtocolString(isolate, description));
} }
String16 _descriptionForRegExpFlags(v8::Local<v8::RegExp> value) { String16 _descriptionForRegExpFlags(v8::Local<v8::RegExp> value) {
...@@ -70,10 +62,10 @@ String16 _descriptionForRegExpFlags(v8::Local<v8::RegExp> value) { ...@@ -70,10 +62,10 @@ String16 _descriptionForRegExpFlags(v8::Local<v8::RegExp> value) {
return result_string_builder.toString(); return result_string_builder.toString();
} }
protocol::Response _serializeRegexp( std::unique_ptr<protocol::Runtime::WebDriverValue> SerializeRegexp(
v8::Local<v8::RegExp> value, v8::Local<v8::Context> context, int max_depth, v8::Local<v8::RegExp> value, v8::Local<v8::Context> context) {
std::unique_ptr<protocol::Runtime::WebDriverValue>* result) { std::unique_ptr<protocol::Runtime::WebDriverValue> result =
*result = protocol::Runtime::WebDriverValue::create() protocol::Runtime::WebDriverValue::create()
.setType(protocol::Runtime::WebDriverValue::TypeEnum::Regexp) .setType(protocol::Runtime::WebDriverValue::TypeEnum::Regexp)
.build(); .build();
...@@ -85,291 +77,255 @@ protocol::Response _serializeRegexp( ...@@ -85,291 +77,255 @@ protocol::Response _serializeRegexp(
context->GetIsolate(), value->GetSource()))); context->GetIsolate(), value->GetSource())));
String16 flags = _descriptionForRegExpFlags(value); String16 flags = _descriptionForRegExpFlags(value);
if (!flags.isEmpty()) if (!flags.isEmpty()) {
result_value->setValue(protocol::String("flags"), result_value->setValue(protocol::String("flags"),
protocol::StringValue::create(flags)); protocol::StringValue::create(flags));
}
(*result)->setValue(std::move(result_value)); result->setValue(std::move(result_value));
return Response::Success(); return result;
} }
protocol::Response _serializeDate( std::unique_ptr<protocol::Runtime::WebDriverValue> SerializeDate(
v8::Local<v8::Date> value, v8::Local<v8::Context> context, int max_depth, v8::Local<v8::Date> value, v8::Local<v8::Context> context) {
std::unique_ptr<protocol::Runtime::WebDriverValue>* result) { std::unique_ptr<protocol::Runtime::WebDriverValue> result =
*result = protocol::Runtime::WebDriverValue::create() protocol::Runtime::WebDriverValue::create()
.setType(protocol::Runtime::WebDriverValue::TypeEnum::Date) .setType(protocol::Runtime::WebDriverValue::TypeEnum::Date)
.build(); .build();
(*result)->setValue(protocol::StringValue::create( std::unique_ptr<protocol::Value> date_description =
descriptionForDate(context, value.As<v8::Date>()))); DescriptionForDate(context, value.As<v8::Date>());
return Response::Success();
result->setValue(std::move(date_description));
return result;
} }
protocol::Response _serializeArrayValue( std::unique_ptr<protocol::Value> SerializeArrayValue(
v8::Local<v8::Array> value, v8::Local<v8::Context> context, int max_depth, v8::Local<v8::Array> value, v8::Local<v8::Context> context, int max_depth) {
std::unique_ptr<protocol::Value>* result) { std::unique_ptr<protocol::ListValue> result = protocol::ListValue::create();
std::unique_ptr<protocol::ListValue> result_value =
protocol::ListValue::create();
uint32_t length = value->Length(); uint32_t length = value->Length();
result->reserve(length);
for (uint32_t i = 0; i < length; i++) { for (uint32_t i = 0; i < length; i++) {
v8::Local<v8::Value> element_value; v8::Local<v8::Value> element_value;
std::unique_ptr<protocol::Value> element_protocol_value; bool success = value->Get(context, i).ToLocal(&element_value);
if (!value->Get(context, i).ToLocal(&element_value)) DCHECK(success);
return Response::InternalError(); USE(success);
Response response = _serializeRecursively(element_value, context, max_depth, std::unique_ptr<protocol::Value> element_protocol_value =
&element_protocol_value); SerializeRecursively(element_value, context, max_depth);
if (!response.IsSuccess()) return response;
result_value->pushValue(std::move(element_protocol_value)); result->pushValue(std::move(element_protocol_value));
} }
*result = std::move(result_value); return result;
return Response::Success();
} }
protocol::Response _serializeArray( std::unique_ptr<protocol::Runtime::WebDriverValue> SerializeArray(
v8::Local<v8::Array> value, v8::Local<v8::Context> context, int max_depth, v8::Local<v8::Array> value, v8::Local<v8::Context> context, int max_depth) {
std::unique_ptr<protocol::Runtime::WebDriverValue>* result) { std::unique_ptr<protocol::Runtime::WebDriverValue> result =
*result = protocol::Runtime::WebDriverValue::create() protocol::Runtime::WebDriverValue::create()
.setType(protocol::Runtime::WebDriverValue::TypeEnum::Array) .setType(protocol::Runtime::WebDriverValue::TypeEnum::Array)
.build(); .build();
if (max_depth > 0) {
result->setValue(SerializeArrayValue(value, context, max_depth));
}
if (max_depth <= 0) return Response::Success(); return result;
std::unique_ptr<protocol::Value> result_value;
Response response =
_serializeArrayValue(value, context, max_depth, &result_value);
if (!response.IsSuccess()) return response;
(*result)->setValue(std::move(result_value));
return Response::Success();
} }
protocol::Response _serializeMap( std::unique_ptr<protocol::Runtime::WebDriverValue> SerializeMap(
v8::Local<v8::Map> value, v8::Local<v8::Context> context, int max_depth, v8::Local<v8::Map> value, v8::Local<v8::Context> context, int max_depth) {
std::unique_ptr<protocol::Runtime::WebDriverValue>* result) { std::unique_ptr<protocol::Runtime::WebDriverValue> result =
*result = protocol::Runtime::WebDriverValue::create() protocol::Runtime::WebDriverValue::create()
.setType(protocol::Runtime::WebDriverValue::TypeEnum::Map) .setType(protocol::Runtime::WebDriverValue::TypeEnum::Map)
.build(); .build();
if (max_depth <= 0) return Response::Success(); if (max_depth > 0) {
std::unique_ptr<protocol::ListValue> result_value = std::unique_ptr<protocol::ListValue> result_value =
protocol::ListValue::create(); protocol::ListValue::create();
v8::Local<v8::Array> properties_and_values = value->AsArray(); v8::Local<v8::Array> properties_and_values = value->AsArray();
uint32_t length = properties_and_values->Length(); uint32_t length = properties_and_values->Length();
result_value->reserve(length);
for (uint32_t i = 0; i < length; i += 2) { for (uint32_t i = 0; i < length; i += 2) {
v8::Local<v8::Value> key_value, property_value; v8::Local<v8::Value> key_value, property_value;
std::unique_ptr<protocol::Value> key_protocol_value, std::unique_ptr<protocol::Value> key_protocol_value,
property_protocol_value; property_protocol_value;
if (!properties_and_values->Get(context, i).ToLocal(&key_value)) bool success = properties_and_values->Get(context, i).ToLocal(&key_value);
return Response::InternalError(); DCHECK(success);
if (!properties_and_values->Get(context, i + 1).ToLocal(&property_value)) success =
return Response::InternalError(); properties_and_values->Get(context, i + 1).ToLocal(&property_value);
if (property_value->IsUndefined()) continue; DCHECK(success);
USE(success);
if (key_value->IsString()) { if (key_value->IsString()) {
key_protocol_value = protocol::StringValue::create( key_protocol_value = protocol::StringValue::create(toProtocolString(
toProtocolString(context->GetIsolate(), key_value.As<v8::String>())); context->GetIsolate(), key_value.As<v8::String>()));
} else { } else {
Response response = _serializeRecursively(key_value, context, max_depth, key_protocol_value =
&key_protocol_value); SerializeRecursively(key_value, context, max_depth);
if (!response.IsSuccess()) return response;
} }
Response response = _serializeRecursively( property_protocol_value =
property_value, context, max_depth, &property_protocol_value); SerializeRecursively(property_value, context, max_depth);
if (!response.IsSuccess()) return response;
std::unique_ptr<protocol::ListValue> value_list = std::unique_ptr<protocol::ListValue> key_value_list =
protocol::ListValue::create(); protocol::ListValue::create();
// command->pushValue(protocol::StringValue::create(method)); key_value_list->pushValue(std::move(key_protocol_value));
value_list->pushValue(std::move(key_protocol_value)); key_value_list->pushValue(std::move(property_protocol_value));
value_list->pushValue(std::move(property_protocol_value));
result_value->pushValue(std::move(value_list)); result_value->pushValue(std::move(key_value_list));
}
result->setValue(std::move(result_value));
} }
(*result)->setValue(std::move(result_value)); return result;
return Response::Success();
} }
protocol::Response _serializeSet( std::unique_ptr<protocol::Runtime::WebDriverValue> SerializeSet(
v8::Local<v8::Set> value, v8::Local<v8::Context> context, int max_depth, v8::Local<v8::Set> value, v8::Local<v8::Context> context, int max_depth) {
std::unique_ptr<protocol::Runtime::WebDriverValue>* result) { std::unique_ptr<protocol::Runtime::WebDriverValue> result =
*result = protocol::Runtime::WebDriverValue::create() protocol::Runtime::WebDriverValue::create()
.setType(protocol::Runtime::WebDriverValue::TypeEnum::Set) .setType(protocol::Runtime::WebDriverValue::TypeEnum::Set)
.build(); .build();
if (max_depth <= 0) return Response::Success(); if (max_depth > 0) {
result->setValue(SerializeArrayValue(value->AsArray(), context, max_depth));
std::unique_ptr<protocol::Value> result_value; }
Response response = return result;
_serializeArrayValue(value->AsArray(), context, max_depth, &result_value);
if (!response.IsSuccess()) return response;
(*result)->setValue(std::move(result_value));
return Response::Success();
} }
protocol::Response _serializeObjectValue( std::unique_ptr<protocol::Value> SerializeObjectValue(
v8::Local<v8::Object> value, v8::Local<v8::Context> context, int max_depth, v8::Local<v8::Object> value, v8::Local<v8::Context> context,
std::unique_ptr<protocol::Value>* result) { int max_depth) {
std::unique_ptr<protocol::ListValue> result_list = std::unique_ptr<protocol::ListValue> result = protocol::ListValue::create();
protocol::ListValue::create();
// Iterate through object's properties. // Iterate through object's properties.
v8::Local<v8::Array> property_names; v8::Local<v8::Array> property_names;
if (!value->GetOwnPropertyNames(context).ToLocal(&property_names)) bool success = value->GetOwnPropertyNames(context).ToLocal(&property_names);
return Response::InternalError(); DCHECK(success);
uint32_t length = property_names->Length(); uint32_t length = property_names->Length();
result->reserve(length);
for (uint32_t i = 0; i < length; i++) { for (uint32_t i = 0; i < length; i++) {
v8::Local<v8::Value> key_value, property_value; v8::Local<v8::Value> key_value, property_value;
std::unique_ptr<protocol::Value> key_protocol_value, std::unique_ptr<protocol::Value> key_protocol_value,
property_protocol_value; property_protocol_value;
if (!property_names->Get(context, i).ToLocal(&key_value)) success = property_names->Get(context, i).ToLocal(&key_value);
return Response::InternalError(); DCHECK(success);
if (key_value->IsString()) { if (key_value->IsString()) {
v8::Maybe<bool> hasRealNamedProperty = v8::Maybe<bool> hasRealNamedProperty =
value->HasRealNamedProperty(context, key_value.As<v8::String>()); value->HasRealNamedProperty(context, key_value.As<v8::String>());
// Don't access properties with interceptors. // Don't access properties with interceptors.
if (hasRealNamedProperty.IsNothing() || !hasRealNamedProperty.FromJust()) if (hasRealNamedProperty.IsNothing() ||
!hasRealNamedProperty.FromJust()) {
continue; continue;
}
key_protocol_value = protocol::StringValue::create( key_protocol_value = protocol::StringValue::create(
toProtocolString(context->GetIsolate(), key_value.As<v8::String>())); toProtocolString(context->GetIsolate(), key_value.As<v8::String>()));
} else { } else {
Response response = _serializeRecursively(key_value, context, max_depth, key_protocol_value = SerializeRecursively(key_value, context, max_depth);
&key_protocol_value);
if (!response.IsSuccess()) return response;
} }
if (!value->Get(context, key_value).ToLocal(&property_value)) success = value->Get(context, key_value).ToLocal(&property_value);
return Response::InternalError(); DCHECK(success);
if (property_value->IsUndefined()) continue; USE(success);
Response response = _serializeRecursively( property_protocol_value =
property_value, context, max_depth, &property_protocol_value); SerializeRecursively(property_value, context, max_depth);
if (!response.IsSuccess()) return response;
std::unique_ptr<protocol::ListValue> value_list = std::unique_ptr<protocol::ListValue> key_value_list =
protocol::ListValue::create(); protocol::ListValue::create();
value_list->pushValue(std::move(key_protocol_value)); key_value_list->pushValue(std::move(key_protocol_value));
value_list->pushValue(std::move(property_protocol_value)); key_value_list->pushValue(std::move(property_protocol_value));
result_list->pushValue(std::move(value_list)); result->pushValue(std::move(key_value_list));
} }
(*result) = std::move(result_list);
return Response::Success(); return result;
} }
protocol::Response _serializeObject( std::unique_ptr<protocol::Runtime::WebDriverValue> SerializeObject(
v8::Local<v8::Object> value, v8::Local<v8::Context> context, int max_depth, v8::Local<v8::Object> value, v8::Local<v8::Context> context,
std::unique_ptr<protocol::Runtime::WebDriverValue>* result) { int max_depth) {
*result = protocol::Runtime::WebDriverValue::create() std::unique_ptr<protocol::Runtime::WebDriverValue> result =
protocol::Runtime::WebDriverValue::create()
.setType(protocol::Runtime::WebDriverValue::TypeEnum::Object) .setType(protocol::Runtime::WebDriverValue::TypeEnum::Object)
.build(); .build();
if (max_depth <= 0) return Response::Success(); if (max_depth > 0) {
result->setValue(
std::unique_ptr<protocol::Value> result_value; SerializeObjectValue(value.As<v8::Object>(), context, max_depth));
Response response = _serializeObjectValue(value.As<v8::Object>(), context, }
max_depth, &result_value); return result;
if (!response.IsSuccess()) return response;
(*result)->setValue(std::move(result_value));
return Response::Success();
} }
} // namespace
protocol::Response V8WebDriverSerializer::serializeV8Value( std::unique_ptr<protocol::Runtime::WebDriverValue>
v8::Local<v8::Object> value, v8::Local<v8::Context> context, int max_depth, V8WebDriverSerializer::serializeV8Value(v8::Local<v8::Object> value,
std::unique_ptr<protocol::Runtime::WebDriverValue>* result) { v8::Local<v8::Context> context,
int max_depth) {
if (value->IsArray()) { if (value->IsArray()) {
Response response = return SerializeArray(value.As<v8::Array>(), context, max_depth);
_serializeArray(value.As<v8::Array>(), context, max_depth, result);
return response;
} }
if (value->IsRegExp()) { if (value->IsRegExp()) {
Response response = return SerializeRegexp(value.As<v8::RegExp>(), context);
_serializeRegexp(value.As<v8::RegExp>(), context, max_depth, result);
return response;
} }
if (value->IsDate()) { if (value->IsDate()) {
Response response = return SerializeDate(value.As<v8::Date>(), context);
_serializeDate(value.As<v8::Date>(), context, max_depth, result);
return response;
} }
if (value->IsMap()) { if (value->IsMap()) {
Response response = return SerializeMap(value.As<v8::Map>(), context, max_depth);
_serializeMap(value.As<v8::Map>(), context, max_depth, result);
return response;
} }
if (value->IsSet()) { if (value->IsSet()) {
Response response = return SerializeSet(value.As<v8::Set>(), context, max_depth);
_serializeSet(value.As<v8::Set>(), context, max_depth, result);
return response;
} }
if (value->IsWeakMap()) { if (value->IsWeakMap()) {
*result = protocol::Runtime::WebDriverValue::create() return protocol::Runtime::WebDriverValue::create()
.setType(protocol::Runtime::WebDriverValue::TypeEnum::Weakmap) .setType(protocol::Runtime::WebDriverValue::TypeEnum::Weakmap)
.build(); .build();
return Response::Success();
} }
if (value->IsWeakSet()) { if (value->IsWeakSet()) {
*result = protocol::Runtime::WebDriverValue::create() return protocol::Runtime::WebDriverValue::create()
.setType(protocol::Runtime::WebDriverValue::TypeEnum::Weakset) .setType(protocol::Runtime::WebDriverValue::TypeEnum::Weakset)
.build(); .build();
return Response::Success();
} }
if (value->IsNativeError()) { if (value->IsNativeError()) {
*result = protocol::Runtime::WebDriverValue::create() return protocol::Runtime::WebDriverValue::create()
.setType(protocol::Runtime::WebDriverValue::TypeEnum::Error) .setType(protocol::Runtime::WebDriverValue::TypeEnum::Error)
.build(); .build();
return Response::Success();
} }
if (value->IsProxy()) { if (value->IsProxy()) {
*result = protocol::Runtime::WebDriverValue::create() return protocol::Runtime::WebDriverValue::create()
.setType(protocol::Runtime::WebDriverValue::TypeEnum::Proxy) .setType(protocol::Runtime::WebDriverValue::TypeEnum::Proxy)
.build(); .build();
return Response::Success();
} }
if (value->IsPromise()) { if (value->IsPromise()) {
*result = protocol::Runtime::WebDriverValue::create() return protocol::Runtime::WebDriverValue::create()
.setType(protocol::Runtime::WebDriverValue::TypeEnum::Promise) .setType(protocol::Runtime::WebDriverValue::TypeEnum::Promise)
.build(); .build();
return Response::Success();
} }
if (value->IsTypedArray()) { if (value->IsTypedArray()) {
*result = return protocol::Runtime::WebDriverValue::create()
protocol::Runtime::WebDriverValue::create()
.setType(protocol::Runtime::WebDriverValue::TypeEnum::Typedarray) .setType(protocol::Runtime::WebDriverValue::TypeEnum::Typedarray)
.build(); .build();
return Response::Success();
} }
if (value->IsArrayBuffer()) { if (value->IsArrayBuffer()) {
*result = return protocol::Runtime::WebDriverValue::create()
protocol::Runtime::WebDriverValue::create()
.setType(protocol::Runtime::WebDriverValue::TypeEnum::Arraybuffer) .setType(protocol::Runtime::WebDriverValue::TypeEnum::Arraybuffer)
.build(); .build();
return Response::Success();
} }
if (value->IsFunction()) { if (value->IsFunction()) {
*result = return protocol::Runtime::WebDriverValue::create()
protocol::Runtime::WebDriverValue::create()
.setType(protocol::Runtime::WebDriverValue::TypeEnum::Function) .setType(protocol::Runtime::WebDriverValue::TypeEnum::Function)
.build(); .build();
return Response::Success();
} }
// Serialize as an Object. // Serialize as an Object.
Response response = return SerializeObject(value.As<v8::Object>(), context, max_depth);
_serializeObject(value.As<v8::Object>(), context, max_depth, result);
return response;
} }
} // namespace v8_inspector } // namespace v8_inspector
...@@ -15,10 +15,9 @@ ...@@ -15,10 +15,9 @@
namespace v8_inspector { namespace v8_inspector {
class V8WebDriverSerializer { class V8WebDriverSerializer {
public: public:
static protocol::Response serializeV8Value( static std::unique_ptr<protocol::Runtime::WebDriverValue> serializeV8Value(
v8::Local<v8::Object> value, v8::Local<v8::Context> context, v8::Local<v8::Object> value, v8::Local<v8::Context> context,
int max_depth, int max_depth);
std::unique_ptr<protocol::Runtime::WebDriverValue>* result);
}; };
} // namespace v8_inspector } // namespace v8_inspector
......
...@@ -439,44 +439,40 @@ class PrimitiveValueMirror final : public ValueMirror { ...@@ -439,44 +439,40 @@ class PrimitiveValueMirror final : public ValueMirror {
(*preview)->setSubtype(RemoteObject::SubtypeEnum::Null); (*preview)->setSubtype(RemoteObject::SubtypeEnum::Null);
} }
protocol::Response buildWebDriverValue( std::unique_ptr<protocol::Runtime::WebDriverValue> buildWebDriverValue(
v8::Local<v8::Context> context, int max_depth, v8::Local<v8::Context> context, int max_depth) const override {
std::unique_ptr<protocol::Runtime::WebDriverValue>* result)
const override {
// https://w3c.github.io/webdriver-bidi/#data-types-protocolValue-primitiveProtocolValue-serialization // https://w3c.github.io/webdriver-bidi/#data-types-protocolValue-primitiveProtocolValue-serialization
if (m_value->IsUndefined()) { if (m_value->IsUndefined()) {
*result = return protocol::Runtime::WebDriverValue::create()
protocol::Runtime::WebDriverValue::create()
.setType(protocol::Runtime::WebDriverValue::TypeEnum::Undefined) .setType(protocol::Runtime::WebDriverValue::TypeEnum::Undefined)
.build(); .build();
return Response::Success();
} }
if (m_value->IsNull()) { if (m_value->IsNull()) {
*result = protocol::Runtime::WebDriverValue::create() return protocol::Runtime::WebDriverValue::create()
.setType(protocol::Runtime::WebDriverValue::TypeEnum::Null) .setType(protocol::Runtime::WebDriverValue::TypeEnum::Null)
.build(); .build();
return Response::Success();
} }
if (m_value->IsString()) { if (m_value->IsString()) {
*result = return protocol::Runtime::WebDriverValue::create()
protocol::Runtime::WebDriverValue::create()
.setType(protocol::Runtime::WebDriverValue::TypeEnum::String) .setType(protocol::Runtime::WebDriverValue::TypeEnum::String)
.setValue(protocol::StringValue::create(toProtocolString( .setValue(protocol::StringValue::create(toProtocolString(
context->GetIsolate(), m_value.As<v8::String>()))) context->GetIsolate(), m_value.As<v8::String>())))
.build(); .build();
return Response::Success();
} }
if (m_value->IsBoolean()) { if (m_value->IsBoolean()) {
*result = return protocol::Runtime::WebDriverValue::create()
protocol::Runtime::WebDriverValue::create()
.setType(protocol::Runtime::WebDriverValue::TypeEnum::Boolean) .setType(protocol::Runtime::WebDriverValue::TypeEnum::Boolean)
.setValue(protocol::FundamentalValue::create( .setValue(protocol::FundamentalValue::create(
m_value.As<v8::Boolean>()->Value())) m_value.As<v8::Boolean>()->Value()))
.build(); .build();
return Response::Success();
} }
return Response::ServerError("unexpected primitive type");
DCHECK(false);
// Fallback.
return protocol::Runtime::WebDriverValue::create()
.setType(protocol::Runtime::WebDriverValue::TypeEnum::Object)
.build();
} }
private: private:
...@@ -529,23 +525,21 @@ class NumberMirror final : public ValueMirror { ...@@ -529,23 +525,21 @@ class NumberMirror final : public ValueMirror {
.build(); .build();
} }
protocol::Response buildWebDriverValue( std::unique_ptr<protocol::Runtime::WebDriverValue> buildWebDriverValue(
v8::Local<v8::Context> context, int max_depth, v8::Local<v8::Context> context, int max_depth) const override {
std::unique_ptr<protocol::Runtime::WebDriverValue>* result)
const override {
// https://w3c.github.io/webdriver-bidi/#data-types-protocolValue-primitiveProtocolValue-serialization // https://w3c.github.io/webdriver-bidi/#data-types-protocolValue-primitiveProtocolValue-serialization
*result = protocol::Runtime::WebDriverValue::create() std::unique_ptr<protocol::Runtime::WebDriverValue> result =
protocol::Runtime::WebDriverValue::create()
.setType(protocol::Runtime::WebDriverValue::TypeEnum::Number) .setType(protocol::Runtime::WebDriverValue::TypeEnum::Number)
.build(); .build();
bool unserializable = false; bool unserializable = false;
String16 descriptionValue = description(&unserializable); String16 descriptionValue = description(&unserializable);
if (unserializable) { if (unserializable) {
(*result)->setValue(protocol::StringValue::create(descriptionValue)); result->setValue(protocol::StringValue::create(descriptionValue));
} else { } else {
(*result)->setValue(toProtocolValue(m_value.As<v8::Number>()->Value())); result->setValue(toProtocolValue(m_value.As<v8::Number>()->Value()));
} }
return Response::Success(); return result;
} }
private: private:
...@@ -608,18 +602,15 @@ class BigIntMirror final : public ValueMirror { ...@@ -608,18 +602,15 @@ class BigIntMirror final : public ValueMirror {
v8::Local<v8::Value> v8Value() const override { return m_value; } v8::Local<v8::Value> v8Value() const override { return m_value; }
protocol::Response buildWebDriverValue( std::unique_ptr<protocol::Runtime::WebDriverValue> buildWebDriverValue(
v8::Local<v8::Context> context, int max_depth, v8::Local<v8::Context> context, int max_depth) const override {
std::unique_ptr<protocol::Runtime::WebDriverValue>* result)
const override {
// https://w3c.github.io/webdriver-bidi/#data-types-protocolValue-primitiveProtocolValue-serialization // https://w3c.github.io/webdriver-bidi/#data-types-protocolValue-primitiveProtocolValue-serialization
*result = protocol::Runtime::WebDriverValue::create() return protocol::Runtime::WebDriverValue::create()
.setType(protocol::Runtime::WebDriverValue::TypeEnum::Bigint) .setType(protocol::Runtime::WebDriverValue::TypeEnum::Bigint)
.setValue(protocol::StringValue::create( .setValue(protocol::StringValue::create(
descriptionForBigInt(context, m_value))) descriptionForBigInt(context, m_value)))
.build(); .build();
return Response::Success();
} }
private: private:
...@@ -658,15 +649,12 @@ class SymbolMirror final : public ValueMirror { ...@@ -658,15 +649,12 @@ class SymbolMirror final : public ValueMirror {
v8::Local<v8::Value> v8Value() const override { return m_symbol; } v8::Local<v8::Value> v8Value() const override { return m_symbol; }
protocol::Response buildWebDriverValue( std::unique_ptr<protocol::Runtime::WebDriverValue> buildWebDriverValue(
v8::Local<v8::Context> context, int max_depth, v8::Local<v8::Context> context, int max_depth) const override {
std::unique_ptr<protocol::Runtime::WebDriverValue>* result)
const override {
// https://w3c.github.io/webdriver-bidi/#data-types-protocolValue-RemoteValue-serialization // https://w3c.github.io/webdriver-bidi/#data-types-protocolValue-RemoteValue-serialization
*result = protocol::Runtime::WebDriverValue::create() return protocol::Runtime::WebDriverValue::create()
.setType(protocol::Runtime::WebDriverValue::TypeEnum::Symbol) .setType(protocol::Runtime::WebDriverValue::TypeEnum::Symbol)
.build(); .build();
return Response::Success();
} }
private: private:
...@@ -713,14 +701,11 @@ class LocationMirror final : public ValueMirror { ...@@ -713,14 +701,11 @@ class LocationMirror final : public ValueMirror {
} }
v8::Local<v8::Value> v8Value() const override { return m_value; } v8::Local<v8::Value> v8Value() const override { return m_value; }
protocol::Response buildWebDriverValue( std::unique_ptr<protocol::Runtime::WebDriverValue> buildWebDriverValue(
v8::Local<v8::Context> context, int max_depth, v8::Local<v8::Context> context, int max_depth) const override {
std::unique_ptr<protocol::Runtime::WebDriverValue>* result) return protocol::Runtime::WebDriverValue::create()
const override {
*result = protocol::Runtime::WebDriverValue::create()
.setType(protocol::Runtime::WebDriverValue::TypeEnum::Object) .setType(protocol::Runtime::WebDriverValue::TypeEnum::Object)
.build(); .build();
return Response::Success();
} }
private: private:
...@@ -800,16 +785,12 @@ class FunctionMirror final : public ValueMirror { ...@@ -800,16 +785,12 @@ class FunctionMirror final : public ValueMirror {
.build(); .build();
} }
protocol::Response buildWebDriverValue( std::unique_ptr<protocol::Runtime::WebDriverValue> buildWebDriverValue(
v8::Local<v8::Context> context, int max_depth, v8::Local<v8::Context> context, int max_depth) const override {
std::unique_ptr<protocol::Runtime::WebDriverValue>* result)
const override {
// https://w3c.github.io/webdriver-bidi/#data-types-protocolValue-RemoteValue-serialization // https://w3c.github.io/webdriver-bidi/#data-types-protocolValue-RemoteValue-serialization
*result = return protocol::Runtime::WebDriverValue::create()
protocol::Runtime::WebDriverValue::create()
.setType(protocol::Runtime::WebDriverValue::TypeEnum::Function) .setType(protocol::Runtime::WebDriverValue::TypeEnum::Function)
.build(); .build();
return Response::Success();
} }
private: private:
...@@ -1097,10 +1078,8 @@ class ObjectMirror final : public ValueMirror { ...@@ -1097,10 +1078,8 @@ class ObjectMirror final : public ValueMirror {
if (m_hasSubtype) (*result)->setSubtype(m_subtype); if (m_hasSubtype) (*result)->setSubtype(m_subtype);
} }
protocol::Response buildWebDriverValue( std::unique_ptr<protocol::Runtime::WebDriverValue> buildWebDriverValue(
v8::Local<v8::Context> context, int max_depth, v8::Local<v8::Context> context, int max_depth) const override {
std::unique_ptr<protocol::Runtime::WebDriverValue>* result)
const override {
// https://w3c.github.io/webdriver-bidi/#data-types-protocolValue-RemoteValue-serialization // https://w3c.github.io/webdriver-bidi/#data-types-protocolValue-RemoteValue-serialization
// Check if embedder implemented custom serialization. // Check if embedder implemented custom serialization.
...@@ -1109,27 +1088,24 @@ class ObjectMirror final : public ValueMirror { ...@@ -1109,27 +1088,24 @@ class ObjectMirror final : public ValueMirror {
if (embedder_serialized_result) { if (embedder_serialized_result) {
// Embedder-implemented serialization. // Embedder-implemented serialization.
*result = protocol::Runtime::WebDriverValue::create() std::unique_ptr<protocol::Runtime::WebDriverValue> result =
.setType(toString16(embedder_serialized_result->type)) protocol::Runtime::WebDriverValue::create()
.setType(toString16(embedder_serialized_result->type->string()))
.build(); .build();
if (!embedder_serialized_result->value.IsEmpty()) { v8::Local<v8::Value> v8_value;
if (embedder_serialized_result->value.ToLocal(&v8_value)) {
// Embedder-implemented serialization has value. // Embedder-implemented serialization has value.
std::unique_ptr<protocol::Value> protocol_value; std::unique_ptr<protocol::Value> protocol_value;
Response response = toProtocolValue( Response response = toProtocolValue(context, v8_value, &protocol_value);
context, embedder_serialized_result->value.ToLocalChecked(), DCHECK(response.IsSuccess());
&protocol_value); result->setValue(std::move(protocol_value));
if (!response.IsSuccess()) return response;
(*result)->setValue(std::move(protocol_value));
} }
return Response::Success(); return result;
} }
// No embedder-implemented serialization. Serialize as V8 Object. // No embedder-implemented serialization. Serialize as V8 Object.
Response response = V8WebDriverSerializer::serializeV8Value( return V8WebDriverSerializer::serializeV8Value(m_value, context, max_depth);
m_value, context, max_depth, result);
return response;
} }
private: private:
......
...@@ -66,9 +66,8 @@ class ValueMirror { ...@@ -66,9 +66,8 @@ class ValueMirror {
v8::Local<v8::Context> context, int* nameLimit, int* indexLimit, v8::Local<v8::Context> context, int* nameLimit, int* indexLimit,
std::unique_ptr<protocol::Runtime::ObjectPreview>*) const {} std::unique_ptr<protocol::Runtime::ObjectPreview>*) const {}
virtual v8::Local<v8::Value> v8Value() const = 0; virtual v8::Local<v8::Value> v8Value() const = 0;
virtual protocol::Response buildWebDriverValue( virtual std::unique_ptr<protocol::Runtime::WebDriverValue>
v8::Local<v8::Context> context, int max_depth, buildWebDriverValue(v8::Local<v8::Context> context, int max_depth) const = 0;
std::unique_ptr<protocol::Runtime::WebDriverValue>* result) const = 0;
class PropertyAccumulator { class PropertyAccumulator {
public: public:
......
...@@ -193,7 +193,7 @@ Runtime.callFunctionOn ...@@ -193,7 +193,7 @@ Runtime.callFunctionOn
} }
Running test: Array Running test: Array
testing expression: [1,2] testing expression: [1,2,undefined]
Runtime.evaluate Runtime.evaluate
{ {
type : array type : array
...@@ -206,6 +206,9 @@ Runtime.evaluate ...@@ -206,6 +206,9 @@ Runtime.evaluate
type : number type : number
value : 2 value : 2
} }
[2] : {
type : undefined
}
] ]
} }
Runtime.callFunctionOn Runtime.callFunctionOn
...@@ -220,9 +223,12 @@ Runtime.callFunctionOn ...@@ -220,9 +223,12 @@ Runtime.callFunctionOn
type : number type : number
value : 2 value : 2
} }
[2] : {
type : undefined
}
] ]
} }
testing expression: new Array(1,2) testing expression: new Array(1,2,undefined)
Runtime.evaluate Runtime.evaluate
{ {
type : array type : array
...@@ -235,6 +241,9 @@ Runtime.evaluate ...@@ -235,6 +241,9 @@ Runtime.evaluate
type : number type : number
value : 2 value : 2
} }
[2] : {
type : undefined
}
] ]
} }
Runtime.callFunctionOn Runtime.callFunctionOn
...@@ -249,6 +258,9 @@ Runtime.callFunctionOn ...@@ -249,6 +258,9 @@ Runtime.callFunctionOn
type : number type : number
value : 2 value : 2
} }
[2] : {
type : undefined
}
] ]
} }
...@@ -399,7 +411,7 @@ Runtime.callFunctionOn ...@@ -399,7 +411,7 @@ Runtime.callFunctionOn
} }
Running test: Set Running test: Set
testing expression: new Set([{valueObject1: 1}, 'valueString2', new Array()]) testing expression: new Set([{valueObject1: 1}, 'valueString2', new Array(), undefined])
Runtime.evaluate Runtime.evaluate
{ {
type : set type : set
...@@ -414,6 +426,9 @@ Runtime.evaluate ...@@ -414,6 +426,9 @@ Runtime.evaluate
[2] : { [2] : {
type : array type : array
} }
[3] : {
type : undefined
}
] ]
} }
Runtime.callFunctionOn Runtime.callFunctionOn
...@@ -430,6 +445,9 @@ Runtime.callFunctionOn ...@@ -430,6 +445,9 @@ Runtime.callFunctionOn
[2] : { [2] : {
type : array type : array
} }
[3] : {
type : undefined
}
] ]
} }
...@@ -489,7 +507,7 @@ Runtime.callFunctionOn ...@@ -489,7 +507,7 @@ Runtime.callFunctionOn
} }
Running test: Object Running test: Object
testing expression: {nullKey: null, stringKey: 'foo',boolKey: true,numberKey: 123,bigintKey: 123n,symbolKey: Symbol('foo'),functionKey: () => {},arrayKey:[1]} testing expression: {nullKey: null, stringKey: 'foo',boolKey: true,numberKey: 123,bigintKey: 123n,symbolKey: Symbol('foo'),functionKey: () => {},arrayKey:[1],undefinedKey:undefined}
Runtime.evaluate Runtime.evaluate
{ {
type : object type : object
...@@ -546,6 +564,12 @@ Runtime.evaluate ...@@ -546,6 +564,12 @@ Runtime.evaluate
type : array type : array
} }
] ]
[8] : [
[0] : undefinedKey
[1] : {
type : undefined
}
]
] ]
} }
Runtime.callFunctionOn Runtime.callFunctionOn
...@@ -604,6 +628,12 @@ Runtime.callFunctionOn ...@@ -604,6 +628,12 @@ Runtime.callFunctionOn
type : array type : array
} }
] ]
[8] : [
[0] : undefinedKey
[1] : {
type : undefined
}
]
] ]
} }
testing expression: {key_level_1: {key_level_2: {key_level_3: 'value_level_3'}}} testing expression: {key_level_1: {key_level_2: {key_level_3: 'value_level_3'}}}
......
// Copyright 2018 the V8 project authors. All rights reserved. // Copyright 2022 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
...@@ -28,8 +28,8 @@ InspectorTest.runAsyncTestSuite([ ...@@ -28,8 +28,8 @@ InspectorTest.runAsyncTestSuite([
await testExpression("[function qwe(){}, ()=>{}]"); await testExpression("[function qwe(){}, ()=>{}]");
}, },
async function Array() { async function Array() {
await testExpression("[1,2]"); await testExpression("[1,2,undefined]");
await testExpression("new Array(1,2)"); await testExpression("new Array(1,2,undefined)");
}, },
async function RegExp() { async function RegExp() {
await testExpression("[new RegExp('ab+c'), new RegExp('ab+c', 'ig')]"); await testExpression("[new RegExp('ab+c'), new RegExp('ab+c', 'ig')]");
...@@ -49,7 +49,7 @@ InspectorTest.runAsyncTestSuite([ ...@@ -49,7 +49,7 @@ InspectorTest.runAsyncTestSuite([
await testExpression("new WeakMap([[{valueObject1: 1}, 'keyString1'],[{valueObject2: 2}, 'keyString2']])"); await testExpression("new WeakMap([[{valueObject1: 1}, 'keyString1'],[{valueObject2: 2}, 'keyString2']])");
}, },
async function Set() { async function Set() {
await testExpression("new Set([{valueObject1: 1}, 'valueString2', new Array()])"); await testExpression("new Set([{valueObject1: 1}, 'valueString2', new Array(), undefined])");
}, },
async function Weakset() { async function Weakset() {
await testExpression("new WeakSet([{valueObject1: 1}, {valueObject2: 2}])"); await testExpression("new WeakSet([{valueObject1: 1}, {valueObject2: 2}])");
...@@ -68,7 +68,7 @@ InspectorTest.runAsyncTestSuite([ ...@@ -68,7 +68,7 @@ InspectorTest.runAsyncTestSuite([
}, },
async function Object() { async function Object() {
// Object. // Object.
await testExpression("{nullKey: null, stringKey: 'foo',boolKey: true,numberKey: 123,bigintKey: 123n,symbolKey: Symbol('foo'),functionKey: () => {},arrayKey:[1]}"); await testExpression("{nullKey: null, stringKey: 'foo',boolKey: true,numberKey: 123,bigintKey: 123n,symbolKey: Symbol('foo'),functionKey: () => {},arrayKey:[1],undefinedKey:undefined}");
// Object in-depth serialization. // Object in-depth serialization.
await testExpression("{key_level_1: {key_level_2: {key_level_3: 'value_level_3'}}}"); await testExpression("{key_level_1: {key_level_2: {key_level_3: 'value_level_3'}}}");
}]); }]);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment