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

[DevTools] Roll inspector_protocol (V8)

Upstream PR:
"Implement crdtp::ErrorSupport, replacing the jinja2 template."
https://chromium-review.googlesource.com/c/deps/inspector_protocol/+/2036608

In addition; this PR includes removal of now unused routines
in string-util.h (StringBuilder and number conversions).

New Rev: e4ffb7288a17b2bbe2f7b7cd62abcb1d1e55681a

Change-Id: Iae14c001c1f468466a42cb1b842c0ded766fccc9
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2037959Reviewed-by: 's avatarDmitry Gozman <dgozman@chromium.org>
Commit-Queue: Johannes Henkel <johannes@chromium.org>
Cr-Commit-Position: refs/heads/master@{#66165}
parent 1f7861c8
......@@ -95,18 +95,6 @@ bool stringViewStartsWith(const StringView& string, const char* prefix) {
return true;
}
namespace protocol {
// static
double StringUtil::toDouble(const char* s, size_t len, bool* isOk) {
int flags = v8::internal::ALLOW_HEX | v8::internal::ALLOW_OCTAL |
v8::internal::ALLOW_BINARY;
double result = v8::internal::StringToDouble(s, flags);
*isOk = !std::isnan(result);
return result;
}
} // namespace protocol
namespace {
// An empty string buffer doesn't own any string data; its ::string() returns a
// default-constructed StringView instance.
......
......@@ -21,19 +21,12 @@ namespace protocol {
class Value;
using String = v8_inspector::String16;
using StringBuilder = v8_inspector::String16Builder;
class StringUtil {
public:
static String substring(const String& s, size_t pos, size_t len) {
return s.substring(pos, len);
}
static String fromInteger(int number) { return String::fromInteger(number); }
static String fromInteger(size_t number) {
return String::fromInteger(number);
}
static String fromDouble(double number) { return String::fromDouble(number); }
static double toDouble(const char* s, size_t len, bool* isOk);
static size_t find(const String& s, const char* needle) {
return s.find(needle);
}
......@@ -41,30 +34,6 @@ class StringUtil {
return s.find(needle);
}
static const size_t kNotFound = String::kNotFound;
static void builderAppend(
StringBuilder& builder, // NOLINT(runtime/references)
const String& s) {
builder.append(s);
}
static void builderAppend(
StringBuilder& builder, // NOLINT(runtime/references)
UChar c) {
builder.append(c);
}
static void builderAppend(
StringBuilder& builder, // NOLINT(runtime/references)
const char* s, size_t len) {
builder.append(s, len);
}
static void builderReserve(
StringBuilder& builder, // NOLINT(runtime/references)
size_t capacity) {
builder.reserveCapacity(capacity);
}
static String builderToString(
StringBuilder& builder) { // NOLINT(runtime/references)
return builder.toString();
}
static String fromUTF8(const uint8_t* data, size_t length) {
return String16::fromUTF8(reinterpret_cast<const char*>(data), length);
......
......@@ -14,6 +14,8 @@ v8_source_set("crdtp") {
sources = [
"crdtp/cbor.cc",
"crdtp/cbor.h",
"crdtp/error_support.cc",
"crdtp/error_support.h",
"crdtp/export.h",
"crdtp/glue.h",
"crdtp/json.cc",
......@@ -27,9 +29,7 @@ v8_source_set("crdtp") {
"crdtp/status.h",
]
configs = [ ":crdtp_config" ]
deps = [
":crdtp_platform",
]
deps = [ ":crdtp_platform" ]
}
# A small adapter library which only :crdtp may depend on.
......@@ -39,9 +39,7 @@ v8_source_set("crdtp_platform") {
"crdtp/json_platform.h",
"crdtp/json_platform_v8.cc",
]
public_deps = [
"../..:v8_libbase",
]
public_deps = [ "../..:v8_libbase" ]
configs = [ ":crdtp_config" ]
}
......@@ -49,6 +47,7 @@ v8_source_set("crdtp_platform") {
v8_source_set("crdtp_test") {
sources = [
"crdtp/cbor_test.cc",
"crdtp/error_support_test.cc",
"crdtp/glue_test.cc",
"crdtp/json_test.cc",
"crdtp/serializable_test.cc",
......@@ -59,9 +58,7 @@ v8_source_set("crdtp_test") {
"crdtp/status_test_support.h",
]
configs = [ ":crdtp_config" ]
deps = [
":crdtp_test_platform",
]
deps = [ ":crdtp_test_platform" ]
testonly = true
}
......
......@@ -2,7 +2,7 @@ Name: inspector protocol
Short Name: inspector_protocol
URL: https://chromium.googlesource.com/deps/inspector_protocol/
Version: 0
Revision: 9fd0f91cc4331f931b7ac4040ceaa36de43937d0
Revision: e4ffb7288a17b2bbe2f7b7cd62abcb1d1e55681a
License: BSD
License File: LICENSE
Security Critical: no
......
// Copyright 2020 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 "error_support.h"
#include <cassert>
namespace v8_crdtp {
void ErrorSupport::Push() {
stack_.emplace_back();
}
void ErrorSupport::Pop() {
stack_.pop_back();
}
void ErrorSupport::SetName(const char* name) {
assert(!stack_.empty());
stack_.back().type = NAME;
stack_.back().name = name;
}
void ErrorSupport::SetIndex(size_t index) {
assert(!stack_.empty());
stack_.back().type = INDEX;
stack_.back().index = index;
}
void ErrorSupport::AddError(const char* error) {
assert(!stack_.empty());
if (!errors_.empty())
errors_ += "; ";
for (size_t ii = 0; ii < stack_.size(); ++ii) {
if (ii)
errors_ += ".";
const Segment& s = stack_[ii];
switch (s.type) {
case NAME:
errors_ += s.name;
continue;
case INDEX:
errors_ += std::to_string(s.index);
continue;
default:
assert(s.type != EMPTY);
continue;
}
}
errors_ += ": ";
errors_ += error;
}
span<uint8_t> ErrorSupport::Errors() const {
return SpanFrom(errors_);
}
} // namespace v8_crdtp
// Copyright 2020 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_ERROR_SUPPORT_H_
#define V8_CRDTP_ERROR_SUPPORT_H_
#include <cstdint>
#include <string>
#include "export.h"
#include "span.h"
namespace v8_crdtp {
// =============================================================================
// ErrorSupport - For tracking errors in tree structures.
// =============================================================================
// This abstraction is used when converting between Values and inspector
// objects, e.g. in lib/ValueConversions_{h,cc}.template. As the processing
// enters and exits a branch, we call Push / Pop. Within the branch,
// we either set the name or an index (in case we're processing the element of a
// list/vector). Only once an error is seen, the path which is now on the
// stack is materialized and prefixes the error message. E.g.,
// "foo.bar.2: some error". After error collection, ::Errors() is used to
// access the message.
class ErrorSupport {
public:
// Push / Pop operations for the path segments; after Push, either SetName or
// SetIndex must be called exactly once.
void Push();
void Pop();
// Sets the name of the current segment on the stack; e.g. a field name.
// |name| must be a C++ string literal in 7 bit US-ASCII.
void SetName(const char* name);
// Sets the index of the current segment on the stack; e.g. an array index.
void SetIndex(size_t index);
// Materializes the error internally. |error| must be a C++ string literal
// in 7 bit US-ASCII.
void AddError(const char* error);
// Returns the semicolon-separated list of errors as in 7 bit ASCII.
span<uint8_t> Errors() const;
private:
enum SegmentType { EMPTY, NAME, INDEX };
struct Segment {
SegmentType type = EMPTY;
union {
const char* name;
size_t index;
};
};
std::vector<Segment> stack_;
std::string errors_;
};
} // namespace v8_crdtp
#endif // V8_CRDTP_ERROR_SUPPORT_H_
// Copyright 2020 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 "error_support.h"
#include <string>
#include <vector>
#include "test_platform.h"
namespace v8_crdtp {
TEST(ErrorSupportTest, Empty) {
ErrorSupport errors;
EXPECT_TRUE(errors.Errors().empty());
}
TEST(ErrorSupportTest, Nesting) {
ErrorSupport errors;
// Enter field foo, inter element at index 42, enter field bar, and encounter
// an error there ("something wrong").
errors.Push();
errors.SetName("foo");
errors.Push();
errors.SetIndex(42);
errors.Push();
errors.SetName("bar_sibling");
errors.SetName("bar");
errors.AddError("something wrong");
errors.Pop(); // bar
errors.Pop(); // 42
// The common case is actually that we'll enter some field, set the name
// or index, and leave without ever producing an error.
errors.Push();
errors.SetName("no_error_here");
errors.Pop(); // no_error_here
errors.Push();
errors.SetName("bang");
errors.AddError("one last error");
errors.Pop(); // bang
errors.Pop(); // foo
std::string out(errors.Errors().begin(), errors.Errors().end());
EXPECT_EQ("foo.42.bar: something wrong; foo.bang: one last error", out);
}
} // namespace v8_crdtp
......@@ -132,8 +132,10 @@ public:
std::unique_ptr<ProtocolError> protocolError(new ProtocolError(code, errorMessage));
protocolError->m_callId = callId;
protocolError->m_hasCallId = true;
if (errors && errors->hasErrors())
protocolError->m_data = errors->errors();
if (errors && !errors->Errors().empty()) {
protocolError->m_data =
StringUtil::fromUTF8(errors->Errors().data(), errors->Errors().size());
}
return protocolError;
}
......
......@@ -4,70 +4,4 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//#include "ErrorSupport.h"
{% for namespace in config.protocol.namespace %}
namespace {{namespace}} {
{% endfor %}
ErrorSupport::ErrorSupport() { }
ErrorSupport::~ErrorSupport() { }
void ErrorSupport::setName(const char* name)
{
setName(String(name));
}
void ErrorSupport::setName(const String& name)
{
DCHECK(m_path.size());
m_path[m_path.size() - 1] = name;
}
void ErrorSupport::push()
{
m_path.push_back(String());
}
void ErrorSupport::pop()
{
m_path.pop_back();
}
void ErrorSupport::addError(const char* error)
{
addError(String(error));
}
void ErrorSupport::addError(const String& error)
{
StringBuilder builder;
for (size_t i = 0; i < m_path.size(); ++i) {
if (i)
StringUtil::builderAppend(builder, '.');
StringUtil::builderAppend(builder, m_path[i]);
}
StringUtil::builderAppend(builder, ": ");
StringUtil::builderAppend(builder, error);
m_errors.push_back(StringUtil::builderToString(builder));
}
bool ErrorSupport::hasErrors()
{
return !!m_errors.size();
}
String ErrorSupport::errors()
{
StringBuilder builder;
for (size_t i = 0; i < m_errors.size(); ++i) {
if (i)
StringUtil::builderAppend(builder, "; ");
StringUtil::builderAppend(builder, m_errors[i]);
}
return StringUtil::builderToString(builder);
}
{% for namespace in config.protocol.namespace %}
} // namespace {{namespace}}
{% endfor %}
// TODO(johannes): Remove this template.
......@@ -4,36 +4,4 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef {{"_".join(config.protocol.namespace)}}_ErrorSupport_h
#define {{"_".join(config.protocol.namespace)}}_ErrorSupport_h
#include {{format_include(config.protocol.package, "Forward")}}
{% for namespace in config.protocol.namespace %}
namespace {{namespace}} {
{% endfor %}
class {{config.lib.export_macro}} ErrorSupport {
public:
ErrorSupport();
~ErrorSupport();
void push();
void setName(const char*);
void setName(const String&);
void pop();
void addError(const char*);
void addError(const String&);
bool hasErrors();
String errors();
private:
std::vector<String> m_path;
std::vector<String> m_errors;
};
{% for namespace in config.protocol.namespace %}
} // namespace {{namespace}}
{% endfor %}
#endif // !defined({{"_".join(config.protocol.namespace)}}_ErrorSupport_h)
// TODO(johannes): Remove this template.
......@@ -18,6 +18,7 @@
#include <unordered_map>
#include <unordered_set>
#include "{{config.crdtp.dir}}/error_support.h"
#include "{{config.crdtp.dir}}/glue.h"
{% for namespace in config.protocol.namespace %}
......@@ -26,7 +27,7 @@ namespace {{namespace}} {
class DictionaryValue;
class DispatchResponse;
class ErrorSupport;
using ErrorSupport = {{config.crdtp.namespace}}::ErrorSupport;
class FundamentalValue;
class ListValue;
class Object;
......
......@@ -14,7 +14,7 @@ std::unique_ptr<Object> Object::fromValue(protocol::Value* value, ErrorSupport*
{
protocol::DictionaryValue* dictionary = DictionaryValue::cast(value);
if (!dictionary) {
errors->addError("object expected");
errors->AddError("object expected");
return nullptr;
}
dictionary = static_cast<protocol::DictionaryValue*>(dictionary->clone().release());
......
......@@ -40,7 +40,7 @@ struct ValueConversions<bool> {
bool result = false;
bool success = value ? value->asBoolean(&result) : false;
if (!success)
errors->addError("boolean value expected");
errors->AddError("boolean value expected");
return result;
}
......@@ -57,7 +57,7 @@ struct ValueConversions<int> {
int result = 0;
bool success = value ? value->asInteger(&result) : false;
if (!success)
errors->addError("integer value expected");
errors->AddError("integer value expected");
return result;
}
......@@ -74,7 +74,7 @@ struct ValueConversions<double> {
double result = 0;
bool success = value ? value->asDouble(&result) : false;
if (!success)
errors->addError("double value expected");
errors->AddError("double value expected");
return result;
}
......@@ -91,7 +91,7 @@ struct ValueConversions<String> {
String result;
bool success = value ? value->asString(&result) : false;
if (!success)
errors->addError("string value expected");
errors->AddError("string value expected");
return result;
}
......@@ -107,7 +107,7 @@ struct ValueConversions<Binary> {
{
if (!value ||
(value->type() != Value::TypeBinary && value->type() != Value::TypeString)) {
errors->addError("Either string base64 or binary value expected");
errors->AddError("Either string base64 or binary value expected");
return Binary();
}
Binary binary;
......@@ -118,7 +118,7 @@ struct ValueConversions<Binary> {
bool success;
Binary out = Binary::fromBase64(result, &success);
if (!success)
errors->addError("base64 decoding error");
errors->AddError("base64 decoding error");
return out;
}
......@@ -133,20 +133,20 @@ struct ValueConversions<std::vector<std::unique_ptr<T>>> {
static std::unique_ptr<std::vector<std::unique_ptr<T>>> fromValue(protocol::Value* value, ErrorSupport* errors) {
protocol::ListValue* array = ListValue::cast(value);
if (!array) {
errors->addError("array expected");
errors->AddError("array expected");
return nullptr;
}
errors->push();
errors->Push();
std::unique_ptr<std::vector<std::unique_ptr<T>>> result(
new std::vector<std::unique_ptr<T>>());
result->reserve(array->size());
for (size_t i = 0; i < array->size(); ++i) {
errors->setName(StringUtil::fromInteger(i));
errors->SetIndex(i);
auto item = ValueConversions<T>::fromValue(array->at(i), errors);
result->emplace_back(std::move(item));
}
errors->pop();
if (errors->hasErrors())
errors->Pop();
if (!errors->Errors().empty())
return nullptr;
return result;
}
......@@ -167,19 +167,19 @@ struct ValueConversions<std::vector<T>> {
static std::unique_ptr<std::vector<T>> fromValue(protocol::Value* value, ErrorSupport* errors) {
protocol::ListValue* array = ListValue::cast(value);
if (!array) {
errors->addError("array expected");
errors->AddError("array expected");
return nullptr;
}
errors->push();
errors->Push();
std::unique_ptr<std::vector<T>> result(new std::vector<T>());
result->reserve(array->size());
for (size_t i = 0; i < array->size(); ++i) {
errors->setName(StringUtil::fromInteger(i));
errors->SetIndex(i);
auto item = ValueConversions<T>::fromValue(array->at(i), errors);
result->emplace_back(std::move(item));
}
errors->pop();
if (errors->hasErrors())
errors->Pop();
if (!errors->Errors().empty())
return nullptr;
return result;
}
......@@ -200,7 +200,7 @@ struct ValueConversions<Value> {
{
bool success = !!value;
if (!success) {
errors->addError("value expected");
errors->AddError("value expected");
return nullptr;
}
return value->clone();
......@@ -223,7 +223,7 @@ struct ValueConversions<DictionaryValue> {
{
bool success = value && value->type() == protocol::Value::TypeObject;
if (!success)
errors->addError("object expected");
errors->AddError("object expected");
return DictionaryValue::cast(value->clone());
}
......@@ -244,7 +244,7 @@ struct ValueConversions<ListValue> {
{
bool success = value && value->type() == protocol::Value::TypeArray;
if (!success)
errors->addError("list expected");
errors->AddError("list expected");
return ListValue::cast(value->clone());
}
......
......@@ -10,6 +10,8 @@
//#include "Allocator.h"
//#include "Forward.h"
#include {{format_include(config.protocol.package, "Forward")}}
{% for namespace in config.protocol.namespace %}
namespace {{namespace}} {
{% endfor %}
......
......@@ -129,30 +129,6 @@ std::unique_ptr<base::Value> toBaseValue(Value* value, int depth) {
return nullptr;
}
StringBuilder::StringBuilder() {}
StringBuilder::~StringBuilder() {}
void StringBuilder::append(const std::string& s) {
string_ += s;
}
void StringBuilder::append(char c) {
string_ += c;
}
void StringBuilder::append(const char* characters, size_t length) {
string_.append(characters, length);
}
std::string StringBuilder::toString() {
return string_;
}
void StringBuilder::reserveCapacity(size_t capacity) {
string_.reserve(capacity);
}
// In Chromium, we do not support big endian architectures, so no conversion is needed
// to interpret UTF16LE.
// static
......
......@@ -14,7 +14,6 @@
#include "base/logging.h"
#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 %}
......@@ -33,41 +32,11 @@ class Value;
using String = std::string;
class {{config.lib.export_macro}} StringBuilder {
public:
StringBuilder();
~StringBuilder();
void append(const String&);
void append(char);
void append(const char*, size_t);
String toString();
void reserveCapacity(size_t);
private:
std::string string_;
};
class {{config.lib.export_macro}} StringUtil {
public:
static String substring(const String& s, unsigned pos, unsigned len) {
return s.substr(pos, len);
}
static String fromInteger(int number) { return base::NumberToString(number); }
static String fromDouble(double number) {
String s = base::NumberToString(number);
if (!s.empty()) { // .123 -> 0.123; -.123 -> -0.123 for valid JSON.
if (s[0] == '.')
s.insert(/*index=*/ 0, /*count=*/ 1, /*ch=*/ '0');
else if (s[0] == '-' && s.size() >= 2 && s[1] == '.')
s.insert(/*index=*/ 1, /*count=*/ 1, /*ch=*/ '0');
}
return s;
}
static double toDouble(const char* s, size_t len, bool* ok) {
double v = 0.0;
*ok = base::StringToDouble(std::string(s, len), &v);
return *ok ? v : 0.0;
}
static size_t find(const String& s, const char* needle) {
return s.find(needle);
}
......@@ -75,21 +44,6 @@ class {{config.lib.export_macro}} StringUtil {
return s.find(needle);
}
static const size_t kNotFound = static_cast<size_t>(-1);
static void builderAppend(StringBuilder& builder, const String& s) {
builder.append(s);
}
static void builderAppend(StringBuilder& builder, char c) {
builder.append(c);
}
static void builderAppend(StringBuilder& builder, const char* s, size_t len) {
builder.append(s, len);
}
static void builderReserve(StringBuilder& builder, unsigned capacity) {
builder.reserveCapacity(capacity);
}
static String builderToString(StringBuilder& builder) {
return builder.toString();
}
static String fromUTF8(const uint8_t* data, size_t length) {
return std::string(reinterpret_cast<const char*>(data), length);
......
......@@ -21,6 +21,9 @@ FILES_TO_SYNC = [
'crdtp/cbor.cc',
'crdtp/cbor.h',
'crdtp/cbor_test.cc',
'crdtp/error_support.cc',
'crdtp/error_support.h',
'crdtp/error_support_test.cc',
'crdtp/glue.h',
'crdtp/glue_test.cc',
'crdtp/json.cc',
......
......@@ -52,7 +52,7 @@ struct ValueConversions<{{"::".join(config.imported.namespace)}}::{{domain.domai
static std::unique_ptr<{{"::".join(config.imported.namespace)}}::{{domain.domain}}::API::{{type.id}}> fromValue(protocol::Value* value, ErrorSupport* errors)
{
if (!value) {
errors->addError("value expected");
errors->AddError("value expected");
return nullptr;
}
......@@ -60,7 +60,7 @@ struct ValueConversions<{{"::".join(config.imported.namespace)}}::{{domain.domai
value->AppendSerialized(&binary);
auto result = {{"::".join(config.imported.namespace)}}::{{domain.domain}}::API::{{type.id}}::fromBinary(binary.data(), binary.size());
if (!result)
errors->addError("cannot parse");
errors->AddError("cannot parse");
return result;
}
......
......@@ -54,27 +54,27 @@ const char* {{type.id}}::{{property.name | to_title_case}}Enum::{{literal | dash
std::unique_ptr<{{type.id}}> {{type.id}}::fromValue(protocol::Value* value, ErrorSupport* errors)
{
if (!value || value->type() != protocol::Value::TypeObject) {
errors->addError("object expected");
errors->AddError("object expected");
return nullptr;
}
std::unique_ptr<{{type.id}}> result(new {{type.id}}());
protocol::DictionaryValue* object = DictionaryValue::cast(value);
errors->push();
errors->Push();
{% for property in type.properties %}
protocol::Value* {{property.name}}Value = object->get("{{property.name}}");
{% if property.optional %}
if ({{property.name}}Value) {
errors->setName("{{property.name}}");
errors->SetName("{{property.name}}");
result->m_{{property.name}} = ValueConversions<{{protocol.resolve_type(property).raw_type}}>::fromValue({{property.name}}Value, errors);
}
{% else %}
errors->setName("{{property.name}}");
errors->SetName("{{property.name}}");
result->m_{{property.name}} = ValueConversions<{{protocol.resolve_type(property).raw_type}}>::fromValue({{property.name}}Value, errors);
{% endif %}
{% endfor %}
errors->pop();
if (errors->hasErrors())
errors->Pop();
if (!errors->Errors().empty())
return nullptr;
return result;
}
......@@ -301,23 +301,23 @@ void DispatcherImpl::{{command.name}}(int callId, const String& method, {{config
{% if "parameters" in command %}
// Prepare input parameters.
protocol::DictionaryValue* object = DictionaryValue::cast(requestMessageObject->get("params"));
errors->push();
errors->Push();
{% for parameter in command.parameters %}
{% set parameter_type = protocol.resolve_type(parameter) %}
protocol::Value* {{parameter.name}}Value = object ? object->get("{{parameter.name}}") : nullptr;
{% if parameter.optional %}
Maybe<{{parameter_type.raw_type}}> in_{{parameter.name}};
if ({{parameter.name}}Value) {
errors->setName("{{parameter.name}}");
errors->SetName("{{parameter.name}}");
in_{{parameter.name}} = ValueConversions<{{parameter_type.raw_type}}>::fromValue({{parameter.name}}Value, errors);
}
{% else %}
errors->setName("{{parameter.name}}");
errors->SetName("{{parameter.name}}");
{{parameter_type.type}} in_{{parameter.name}} = ValueConversions<{{parameter_type.raw_type}}>::fromValue({{parameter.name}}Value, errors);
{% endif %}
{% endfor %}
errors->pop();
if (errors->hasErrors()) {
errors->Pop();
if (!errors->Errors().empty()) {
reportProtocolError(callId, DispatchResponse::kInvalidParams, kInvalidParamsString, errors);
return;
}
......
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