Commit 2f205f5a authored by Johannes Henkel's avatar Johannes Henkel Committed by Commit Bot

[DevTools] Roll inspector_protocol (V8)

New revision: 726836d7317a4031f48af9960bab51d7a2ab2867

The gist is that serialization is direct from
protocol objects to CBOR, no more detour via
protocol::Value.

Upstream PRs:
https://chromium-review.googlesource.com/c/deps/inspector_protocol/+/1956388
https://chromium-review.googlesource.com/c/deps/inspector_protocol/+/1966418

Also:
https://chromium-review.googlesource.com/c/deps/inspector_protocol/+/1941035

Change-Id: I89f742a4fd47b5eb8ebd98ce6e10ecba0501cf66
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1958956Reviewed-by: 's avatarYang Guo <yangguo@chromium.org>
Commit-Queue: Johannes Henkel <johannes@chromium.org>
Cr-Commit-Position: refs/heads/master@{#65448}
parent 5785e0b7
......@@ -12,6 +12,7 @@
#include <limits>
#include <string>
#include "../../third_party/inspector_protocol/crdtp/cbor.h"
#include "src/base/platform/platform.h"
#include "src/inspector/v8-string-conversions.h"
#include "src/numbers/conversions.h"
......@@ -229,3 +230,13 @@ std::string String16::utf8() const {
}
} // namespace v8_inspector
namespace v8_crdtp {
void SerializerTraits<v8_inspector::String16>::Serialize(
const v8_inspector::String16& str, std::vector<uint8_t>* out) {
cbor::EncodeFromUTF16(
span<uint16_t>(reinterpret_cast<const uint16_t*>(str.characters16()),
str.length()),
out);
}
} // namespace v8_crdtp
......@@ -12,6 +12,7 @@
#include <string>
#include <vector>
#include "../../third_party/inspector_protocol/crdtp/serializer_traits.h"
#include "src/base/compiler-specific.h"
namespace v8_inspector {
......@@ -164,4 +165,13 @@ struct hash<v8_inspector::String16> {
#endif // !defined(__APPLE__) || defined(_LIBCPP_VERSION)
// See third_party/inspector_protocol/crdtp/serializer_traits.h.
namespace v8_crdtp {
template <>
struct SerializerTraits<v8_inspector::String16> {
static void Serialize(const v8_inspector::String16& str,
std::vector<uint8_t>* out);
};
} // namespace v8_crdtp
#endif // V8_INSPECTOR_STRING_16_H_
......@@ -21,6 +21,7 @@ v8_source_set("crdtp") {
"crdtp/parser_handler.h",
"crdtp/serializable.cc",
"crdtp/serializable.h",
"crdtp/serializer_traits.h",
"crdtp/span.h",
"crdtp/status.cc",
"crdtp/status.h",
......@@ -51,6 +52,7 @@ v8_source_set("crdtp_test") {
"crdtp/glue_test.cc",
"crdtp/json_test.cc",
"crdtp/serializable_test.cc",
"crdtp/serializer_traits_test.cc",
"crdtp/span_test.cc",
"crdtp/status_test.cc",
]
......
......@@ -2,7 +2,7 @@ Name: inspector protocol
Short Name: inspector_protocol
URL: https://chromium.googlesource.com/deps/inspector_protocol/
Version: 0
Revision: 8aa01855258db2ff1324d39a95d8da4dd8cfa868
Revision: 726836d7317a4031f48af9960bab51d7a2ab2867
License: BSD
License File: LICENSE
Security Critical: no
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_CRDTP_SERIALIZER_TRAITS_H_
#define V8_CRDTP_SERIALIZER_TRAITS_H_
#include <memory>
#include <string>
#include <vector>
#include "cbor.h"
#include "glue.h"
#include "serializable.h"
#include "span.h"
namespace v8_crdtp {
// =============================================================================
// SerializerTraits - Encodes field values of protocol objects in CBOR.
// =============================================================================
//
// A family of serialization functions which are used by FieldSerializerTraits
// (below) to encode field values in CBOR. Conceptually, it's this:
//
// Serialize(bool value, std::vector<uint8_t>* out);
// Serialize(int32_t value, std::vector<uint8_t>* out);
// Serialize(double value, std::vector<uint8_t>* out);
// ...
//
// However, if this was to use straight-forward overloading, implicit
// type conversions would lead to ambiguity - e.g., a bool could be
// represented as an int32_t, but it should really be encoded as a bool.
// The template parameterized / specialized structs accomplish this.
//
// SerializerTraits<bool>::Serialize(bool value, std::vector<uint8_t>* out);
// SerializerTraits<int32>::Serialize(int32_t value, std::vector<uint8_t>* out);
// SerializerTraits<double>::Serialize(double value, std::vector<uint8_t>* out);
template <typename T>
struct SerializerTraits {
// |Serializable| (defined in serializable.h) already knows how to serialize
// to CBOR, so we can just delegate. This covers domain specific types,
// protocol::Binary, etc.
static void Serialize(const Serializable& value, std::vector<uint8_t>* out) {
value.AppendSerialized(out);
}
// This method covers the Exported types, e.g. from V8 into Chromium.
// TODO(johannes): Change Exported signature to AppendSerialized
// for consistency with Serializable; this is why we explicitly
// disable this template for Serializable here.
template <typename Exported,
typename std::enable_if_t<
std::is_member_pointer<decltype(&Exported::writeBinary)>{} &&
!std::is_same<Serializable, T>{},
int> = 0>
static void Serialize(const Exported& value, std::vector<uint8_t>* out) {
value.writeBinary(out);
}
};
// This covers std::string, which is assumed to be UTF-8.
// The two other string implementations that are used in the protocol bindings:
// - WTF::String, for which the SerializerTraits specialization is located
// in third_party/blink/renderer/core/inspector/v8-inspector-string.h.
// - v8_inspector::String16, implemented in v8/src/inspector/string-16.h
// along with its SerializerTraits specialization.
template <>
struct SerializerTraits<std::string> {
static void Serialize(const std::string& str, std::vector<uint8_t>* out) {
cbor::EncodeString8(SpanFrom(str), out);
}
};
template <>
struct SerializerTraits<bool> {
static void Serialize(bool value, std::vector<uint8_t>* out) {
out->push_back(value ? cbor::EncodeTrue() : cbor::EncodeFalse());
}
};
template <>
struct SerializerTraits<int32_t> {
static void Serialize(int32_t value, std::vector<uint8_t>* out) {
cbor::EncodeInt32(value, out);
}
};
template <>
struct SerializerTraits<double> {
static void Serialize(double value, std::vector<uint8_t>* out) {
cbor::EncodeDouble(value, out);
}
};
template <typename T>
struct SerializerTraits<std::vector<T>> {
static void Serialize(const std::vector<T>& value,
std::vector<uint8_t>* out) {
out->push_back(cbor::EncodeIndefiniteLengthArrayStart());
for (const T& element : value)
SerializerTraits<T>::Serialize(element, out);
out->push_back(cbor::EncodeStop());
}
};
template <typename T>
struct SerializerTraits<std::unique_ptr<T>> {
static void Serialize(const std::unique_ptr<T>& value,
std::vector<uint8_t>* out) {
SerializerTraits<T>::Serialize(*value, out);
}
};
// =============================================================================
// FieldSerializerTraits - Encodes fields of protocol objects in CBOR
// =============================================================================
//
// The generated code (see TypeBuilder_cpp.template) invokes SerializeField,
// which then instantiates the FieldSerializerTraits to emit the appropriate
// existence checks / dereference for the field value. This avoids emitting
// the field name if the value for an optional field isn't set.
template <typename T>
struct FieldSerializerTraits {
static void Serialize(span<uint8_t> field_name,
const T& field_value,
std::vector<uint8_t>* out) {
cbor::EncodeString8(field_name, out);
SerializerTraits<T>::Serialize(field_value, out);
}
};
template <typename T>
struct FieldSerializerTraits<glue::detail::PtrMaybe<T>> {
static void Serialize(span<uint8_t> field_name,
const glue::detail::PtrMaybe<T>& field_value,
std::vector<uint8_t>* out) {
if (!field_value.isJust())
return;
cbor::EncodeString8(field_name, out);
SerializerTraits<T>::Serialize(*field_value.fromJust(), out);
}
};
template <typename T>
struct FieldSerializerTraits<glue::detail::ValueMaybe<T>> {
static void Serialize(span<uint8_t> field_name,
const glue::detail::ValueMaybe<T>& field_value,
std::vector<uint8_t>* out) {
if (!field_value.isJust())
return;
cbor::EncodeString8(field_name, out);
SerializerTraits<T>::Serialize(field_value.fromJust(), out);
}
};
template <typename T>
void SerializeField(span<uint8_t> field_name,
const T& field_value,
std::vector<uint8_t>* out) {
FieldSerializerTraits<T>::Serialize(field_name, field_value, out);
}
} // namespace v8_crdtp
#endif // V8_CRDTP_SERIALIZER_TRAITS_H_
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "serializer_traits.h"
#include <array>
#include "test_platform.h"
// The purpose of this test is to ensure that the
// {Field}SerializerTraits<X>::Serialize methods invoke the appropriate
// functions from cbor.h; so, it's usually sufficient to compare with what
// cbor.h function invocations would produce, rather than making assertions on
// the specific bytes emitted by the SerializerTraits code.
namespace v8_crdtp {
namespace {
// =============================================================================
// SerializerTraits - Encodes field values of protocol objects in CBOR.
// =============================================================================
TEST(SerializerTraits, Bool) {
std::vector<uint8_t> out;
SerializerTraits<bool>::Serialize(true, &out);
SerializerTraits<bool>::Serialize(false, &out);
EXPECT_THAT(out,
testing::ElementsAre(cbor::EncodeTrue(), cbor::EncodeFalse()));
}
TEST(SerializerTraits, Double) {
std::vector<uint8_t> out;
SerializerTraits<double>::Serialize(1.00001, &out);
std::vector<uint8_t> expected;
cbor::EncodeDouble(1.00001, &expected);
EXPECT_THAT(out, testing::ElementsAreArray(expected));
}
TEST(SerializerTraits, Int32) {
std::vector<uint8_t> out;
SerializerTraits<int32_t>::Serialize(42, &out);
std::vector<uint8_t> expected;
cbor::EncodeInt32(42, &expected);
EXPECT_THAT(out, testing::ElementsAreArray(expected));
}
TEST(SerializerTraits, VectorOfInt32) {
std::vector<int32_t> ints = {1, 2, 3};
std::vector<uint8_t> out;
SerializerTraits<std::vector<int32_t>>::Serialize(ints, &out);
std::vector<uint8_t> expected;
expected.push_back(cbor::EncodeIndefiniteLengthArrayStart());
for (int32_t v : ints)
cbor::EncodeInt32(v, &expected);
expected.push_back(cbor::EncodeStop());
EXPECT_THAT(out, testing::ElementsAreArray(expected));
}
// Foo is an example for a domain specific type.
class Foo : public Serializable {
public:
Foo(int32_t value) : value(value) {}
int32_t value;
void AppendSerialized(std::vector<uint8_t>* out) const override {
// In production, this would be generated code which emits a
// CBOR map that has STRING8 keys corresponding to the field names
// and field values encoded using SerializerTraits::Serialize.
//
// For the test we simplify this drastically and just emit the field
// value, for conveniently testing std::vector<std::unique_ptr<Foo>>,
// as well as the convenience methods for raw pointer and unique_ptr.
SerializerTraits<int32_t>::Serialize(value, out);
}
};
TEST(SerializerTraits, VectorOfDomainSpecificType) {
std::vector<std::unique_ptr<Foo>> foos;
foos.push_back(std::make_unique<Foo>(1));
foos.push_back(std::make_unique<Foo>(2));
foos.push_back(std::make_unique<Foo>(3));
std::vector<uint8_t> out;
SerializerTraits<std::vector<std::unique_ptr<Foo>>>::Serialize(foos, &out);
std::vector<uint8_t> expected;
expected.push_back(cbor::EncodeIndefiniteLengthArrayStart());
for (int32_t v : {1, 2, 3})
cbor::EncodeInt32(v, &expected);
expected.push_back(cbor::EncodeStop());
EXPECT_THAT(out, testing::ElementsAreArray(expected));
}
TEST(SerializerTraits, ConstRefAndUniquePtr) {
// Shows that SerializerTraits<Foo> allows unique_ptr.
Foo foo(42);
auto bar = std::make_unique<Foo>(21);
std::vector<uint8_t> out;
// In this case, |foo| is taken as a const Foo&.
SerializerTraits<Foo>::Serialize(foo, &out);
// In this case, |bar| is taken as a const std::unique_ptr<Foo>&.
SerializerTraits<std::unique_ptr<Foo>>::Serialize(bar, &out);
std::vector<uint8_t> expected;
cbor::EncodeInt32(42, &expected);
cbor::EncodeInt32(21, &expected);
EXPECT_THAT(out, testing::ElementsAreArray(expected));
}
TEST(SerializerTraits, UTF8String) {
std::string msg = "Hello, 🌎.";
std::vector<uint8_t> out;
SerializerTraits<std::string>::Serialize(msg, &out);
std::vector<uint8_t> expected;
cbor::EncodeString8(SpanFrom(msg), &expected);
EXPECT_THAT(out, testing::ElementsAreArray(expected));
}
// A trivial model of Exported.
// (see
// https://cs.chromium.org/chromium/src/out/Debug/gen/v8/include/inspector/Debugger.h).
struct Exported {
std::string msg;
void writeBinary(std::vector<uint8_t>* out) {
cbor::EncodeString8(SpanFrom(msg), out);
}
};
TEST(SerializerTraits, Exported) {
Exported exported;
exported.msg = "Hello, world.";
std::vector<uint8_t> out;
SerializerTraits<std::string>::Serialize(exported.msg, &out);
std::vector<uint8_t> expected;
cbor::EncodeString8(SpanFrom(exported.msg), &expected);
EXPECT_THAT(out, testing::ElementsAreArray(expected));
}
// =============================================================================
// FieldSerializerTraits - Encodes fields of protocol objects in CBOR
// =============================================================================
TEST(FieldSerializerTraits, RequiredField) {
std::string value = "Hello, world.";
std::vector<uint8_t> out;
SerializeField(SpanFrom("msg"), value, &out);
std::vector<uint8_t> expected;
cbor::EncodeString8(SpanFrom("msg"), &expected);
cbor::EncodeString8(SpanFrom(value), &expected);
EXPECT_THAT(out, testing::ElementsAreArray(expected));
}
template <typename T>
class FieldSerializerTraits_MaybeTest : public ::testing::Test {};
using MaybeTypes =
::testing::Types<glue::detail::ValueMaybe<bool>,
glue::detail::ValueMaybe<double>,
glue::detail::ValueMaybe<int32_t>,
glue::detail::ValueMaybe<std::string>,
glue::detail::PtrMaybe<Foo>,
glue::detail::PtrMaybe<std::vector<std::unique_ptr<Foo>>>>;
TYPED_TEST_SUITE(FieldSerializerTraits_MaybeTest, MaybeTypes);
TYPED_TEST(FieldSerializerTraits_MaybeTest, NoOutputForFieldsIfNotJust) {
std::vector<uint8_t> out;
SerializeField(SpanFrom("maybe"), TypeParam(), &out);
EXPECT_THAT(out, testing::ElementsAreArray(std::vector<uint8_t>()));
}
TEST(FieldSerializerTraits, MaybeBool) {
std::vector<uint8_t> out;
SerializeField(SpanFrom("true"), glue::detail::ValueMaybe<bool>(true), &out);
SerializeField(SpanFrom("false"), glue::detail::ValueMaybe<bool>(false),
&out);
std::vector<uint8_t> expected;
cbor::EncodeString8(SpanFrom("true"), &expected);
expected.push_back(cbor::EncodeTrue());
cbor::EncodeString8(SpanFrom("false"), &expected);
expected.push_back(cbor::EncodeFalse());
EXPECT_THAT(out, testing::ElementsAreArray(expected));
}
TEST(FieldSerializerTraits, MaybeDouble) {
std::vector<uint8_t> out;
SerializeField(SpanFrom("dbl"), glue::detail::ValueMaybe<double>(3.14), &out);
std::vector<uint8_t> expected;
cbor::EncodeString8(SpanFrom("dbl"), &expected);
cbor::EncodeDouble(3.14, &expected);
EXPECT_THAT(out, testing::ElementsAreArray(expected));
}
TEST(FieldSerializerTraits, MaybePtrFoo) {
std::vector<uint8_t> out;
SerializeField(SpanFrom("foo"),
glue::detail::PtrMaybe<Foo>(std::make_unique<Foo>(42)), &out);
std::vector<uint8_t> expected;
cbor::EncodeString8(SpanFrom("foo"), &expected);
cbor::EncodeInt32(42, &expected); // Simplified relative to production.
EXPECT_THAT(out, testing::ElementsAreArray(expected));
}
} // namespace
} // namespace v8_crdtp
......@@ -21,6 +21,11 @@ std::unique_ptr<Object> Object::fromValue(protocol::Value* value, ErrorSupport*
return std::unique_ptr<Object>(new Object(std::unique_ptr<DictionaryValue>(dictionary)));
}
// Implements Serializable.
void Object::AppendSerialized(std::vector<uint8_t>* out) const {
m_object->AppendSerialized(out);
}
std::unique_ptr<protocol::DictionaryValue> Object::toValue() const
{
return DictionaryValue::cast(m_object->clone());
......
......@@ -11,16 +11,21 @@
//#include "Forward.h"
//#include "Values.h"
#include "{{config.crdtp.dir}}/serializable.h"
{% for namespace in config.protocol.namespace %}
namespace {{namespace}} {
{% endfor %}
class {{config.lib.export_macro}} Object {
class {{config.lib.export_macro}} Object : public {{config.crdtp.namespace}}::Serializable {
public:
static std::unique_ptr<Object> fromValue(protocol::Value*, ErrorSupport*);
explicit Object(std::unique_ptr<protocol::DictionaryValue>);
~Object();
// Implements Serializable.
void AppendSerialized(std::vector<uint8_t>* out) const override;
std::unique_ptr<protocol::DictionaryValue> toValue() const;
std::unique_ptr<Object> clone() const;
private:
......
......@@ -15,6 +15,7 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "{{config.crdtp.dir}}/cbor.h"
{% for namespace in config.protocol.namespace %}
namespace {{namespace}} {
......@@ -128,18 +129,6 @@ std::unique_ptr<base::Value> toBaseValue(Value* value, int depth) {
return nullptr;
}
// static
std::unique_ptr<Value> StringUtil::parseMessage(
const std::string& message, bool binary) {
if (binary) {
return Value::parseBinary(
reinterpret_cast<const uint8_t*>(message.data()),
message.length());
}
std::unique_ptr<base::Value> value = base::JSONReader::ReadDeprecated(message);
return toProtocolValue(value.get(), 1000);
}
StringBuilder::StringBuilder() {}
StringBuilder::~StringBuilder() {}
......@@ -188,6 +177,10 @@ Binary::Binary(const Binary& binary) : bytes_(binary.bytes_) {}
Binary::Binary(scoped_refptr<base::RefCountedMemory> bytes) : bytes_(bytes) {}
Binary::~Binary() {}
void Binary::AppendSerialized(std::vector<uint8_t>* out) const {
crdtp::cbor::EncodeBinary(crdtp::span<uint8_t>(data(), size()), out);
}
String Binary::toBase64() const {
std::string encoded;
base::Base64Encode(
......
......@@ -15,6 +15,8 @@
#include "base/macros.h"
#include "base/memory/ref_counted_memory.h"
#include "base/strings/string_number_conversions.h"
#include "{{config.crdtp.dir}}/serializable.h"
{% if config.lib.export_header %}
#include "{{config.lib.export_header}}"
{% endif %}
......@@ -91,8 +93,6 @@ class {{config.lib.export_macro}} StringUtil {
return builder.toString();
}
static std::unique_ptr<Value> parseMessage(const std::string& message, bool binary);
static String fromUTF8(const uint8_t* data, size_t length) {
return std::string(reinterpret_cast<const char*>(data), length);
}
......@@ -108,12 +108,15 @@ class {{config.lib.export_macro}} StringUtil {
};
// A read-only sequence of uninterpreted bytes with reference-counted storage.
class {{config.lib.export_macro}} Binary {
class {{config.lib.export_macro}} Binary : public {{config.crdtp.namespace}}::Serializable {
public:
Binary(const Binary&);
Binary();
~Binary();
// Implements Serializable.
void AppendSerialized(std::vector<uint8_t>* out) const override;
const uint8_t* data() const { return bytes_->front(); }
size_t size() const { return bytes_->size(); }
scoped_refptr<base::RefCountedMemory> bytes() const { return bytes_; }
......
#!/usr/bin/env python
# Copyright 2019 The Chromium Authors. All rights reserved.
# Copcright 2019 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
......@@ -31,6 +31,8 @@ FILES_TO_SYNC = [
'crdtp/serializable.h',
'crdtp/serializable.cc',
'crdtp/serializable_test.cc',
'crdtp/serializer_traits.h',
'crdtp/serializer_traits_test.cc',
'crdtp/span.h',
'crdtp/span_test.cc',
'crdtp/status.cc',
......
......@@ -8,6 +8,9 @@
#include {{format_include(config.protocol.package, "Protocol")}}
#include "{{config.crdtp.dir}}/cbor.h"
#include "{{config.crdtp.dir}}/serializer_traits.h"
{% for namespace in config.protocol.namespace %}
namespace {{namespace}} {
{% endfor %}
......@@ -92,6 +95,18 @@ std::unique_ptr<protocol::DictionaryValue> {{type.id}}::toValue() const
return result;
}
void {{type.id}}::AppendSerialized(std::vector<uint8_t>* out) const {
{{config.crdtp.namespace}}::cbor::EnvelopeEncoder envelope_encoder;
envelope_encoder.EncodeStart(out);
out->push_back({{config.crdtp.namespace}}::cbor::EncodeIndefiniteLengthMapStart());
{% for property in type.properties %}
{% set property_field = "m_" + property.name %}
{{config.crdtp.namespace}}::SerializeField({{config.crdtp.namespace}}::SpanFrom("{{property.name}}"), {{property_field}}, out);
{% endfor %}
out->push_back({{config.crdtp.namespace}}::cbor::EncodeStop());
envelope_encoder.EncodeStop(out);
}
std::unique_ptr<{{type.id}}> {{type.id}}::clone() const
{
ErrorSupport errors;
......
......@@ -100,9 +100,7 @@ public:
{% endfor %}
std::unique_ptr<protocol::DictionaryValue> toValue() const;
void AppendSerialized(std::vector<uint8_t>* out) const override {
toValue()->AppendSerialized(out);
}
void AppendSerialized(std::vector<uint8_t>* out) const override;
String toJSON() const { return toValue()->toJSONString(); }
std::unique_ptr<{{type.id}}> clone() const;
{% if protocol.is_exported(domain.domain, type.id) %}
......
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