Commit fa3aada5 authored by Johannes Henkel's avatar Johannes Henkel Committed by Commit Bot

[DevTools] Roll inspector_protocol (V8)

Upstream PR:
"Introduce a crdtp/dispatch.{h,cc} library."
https://chromium-review.googlesource.com/c/deps/inspector_protocol/+/1974680
"For the shallow parse of a DevTools message, allow "params": null."
https://chromium-review.googlesource.com/c/deps/inspector_protocol/+/2109466

New Revision: c69cdc36200992d21a17bf4e5c2f3a95b8860ddf

Change-Id: Icc447ff9ce408b24f5245c643dd2f1843da9255f
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2076215
Commit-Queue: Johannes Henkel <johannes@chromium.org>
Reviewed-by: 's avatarYang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#66813}
parent 1e40c682
......@@ -116,7 +116,7 @@ bool substituteObjectTags(int sessionId, const String16& groupName,
protocol::Response response =
injectedScript->wrapObject(originValue, groupName, WrapMode::kNoPreview,
configValue, maxDepth - 1, &wrapper);
if (!response.isSuccess() || !wrapper) {
if (!response.IsSuccess() || !wrapper) {
reportError(context, tryCatch, "cannot wrap value");
return false;
}
......
This diff is collapsed.
......@@ -38,12 +38,12 @@ Response RemoteObjectId::parse(const String16& objectId,
std::unique_ptr<RemoteObjectId> remoteObjectId(new RemoteObjectId());
std::unique_ptr<protocol::DictionaryValue> parsedObjectId =
remoteObjectId->parseInjectedScriptId(objectId);
if (!parsedObjectId) return Response::Error("Invalid remote object id");
if (!parsedObjectId) return Response::ServerError("Invalid remote object id");
bool success = parsedObjectId->getInteger("id", &remoteObjectId->m_id);
if (!success) return Response::Error("Invalid remote object id");
if (!success) return Response::ServerError("Invalid remote object id");
*result = std::move(remoteObjectId);
return Response::OK();
return Response::Success();
}
RemoteCallFrameId::RemoteCallFrameId()
......@@ -54,13 +54,13 @@ Response RemoteCallFrameId::parse(const String16& objectId,
std::unique_ptr<RemoteCallFrameId> remoteCallFrameId(new RemoteCallFrameId());
std::unique_ptr<protocol::DictionaryValue> parsedObjectId =
remoteCallFrameId->parseInjectedScriptId(objectId);
if (!parsedObjectId) return Response::Error("Invalid call frame id");
if (!parsedObjectId) return Response::ServerError("Invalid call frame id");
bool success =
parsedObjectId->getInteger("ordinal", &remoteCallFrameId->m_frameOrdinal);
if (!success) return Response::Error("Invalid call frame id");
if (!success) return Response::ServerError("Invalid call frame id");
*result = std::move(remoteCallFrameId);
return Response::OK();
return Response::Success();
}
String16 RemoteCallFrameId::serialize(int injectedScriptId, int frameOrdinal) {
......
......@@ -161,3 +161,10 @@ String16 stackTraceIdToString(uintptr_t id) {
}
} // namespace v8_inspector
namespace v8_crdtp {
void SerializerTraits<v8_inspector::protocol::Binary>::Serialize(
const v8_inspector::protocol::Binary& binary, std::vector<uint8_t>* out) {
cbor::EncodeBinary(span<uint8_t>(binary.data(), binary.size()), out);
}
} // namespace v8_crdtp
......@@ -24,17 +24,6 @@ using String = v8_inspector::String16;
class StringUtil {
public:
static String substring(const String& s, size_t pos, size_t len) {
return s.substring(pos, len);
}
static size_t find(const String& s, const char* needle) {
return s.find(needle);
}
static size_t find(const String& s, const String& needle) {
return s.find(needle);
}
static const size_t kNotFound = String::kNotFound;
static String fromUTF8(const uint8_t* data, size_t length) {
return String16::fromUTF8(reinterpret_cast<const char*>(data), length);
}
......@@ -100,4 +89,13 @@ String16 stackTraceIdToString(uintptr_t id);
} // namespace v8_inspector
// See third_party/inspector_protocol/crdtp/serializer_traits.h.
namespace v8_crdtp {
template <>
struct SerializerTraits<v8_inspector::protocol::Binary> {
static void Serialize(const v8_inspector::protocol::Binary& binary,
std::vector<uint8_t>* out);
};
} // namespace v8_crdtp
#endif // V8_INSPECTOR_STRING_UTIL_H_
......@@ -27,23 +27,23 @@ V8ConsoleAgentImpl::V8ConsoleAgentImpl(
V8ConsoleAgentImpl::~V8ConsoleAgentImpl() = default;
Response V8ConsoleAgentImpl::enable() {
if (m_enabled) return Response::OK();
if (m_enabled) return Response::Success();
m_state->setBoolean(ConsoleAgentState::consoleEnabled, true);
m_enabled = true;
m_session->inspector()->enableStackCapturingIfNeeded();
reportAllMessages();
return Response::OK();
return Response::Success();
}
Response V8ConsoleAgentImpl::disable() {
if (!m_enabled) return Response::OK();
if (!m_enabled) return Response::Success();
m_session->inspector()->disableStackCapturingIfNeeded();
m_state->setBoolean(ConsoleAgentState::consoleEnabled, false);
m_enabled = false;
return Response::OK();
return Response::Success();
}
Response V8ConsoleAgentImpl::clearMessages() { return Response::OK(); }
Response V8ConsoleAgentImpl::clearMessages() { return Response::Success(); }
void V8ConsoleAgentImpl::restore() {
if (!m_state->booleanProperty(ConsoleAgentState::consoleEnabled, false))
......
......@@ -595,7 +595,7 @@ static void inspectImpl(const v8::FunctionCallbackInfo<v8::Value>& info,
std::unique_ptr<protocol::Runtime::RemoteObject> wrappedObject;
protocol::Response response = injectedScript->wrapObject(
value, "", WrapMode::kNoPreview, &wrappedObject);
if (!response.isSuccess()) return;
if (!response.IsSuccess()) return;
std::unique_ptr<protocol::DictionaryValue> hints =
protocol::DictionaryValue::create();
......
This diff is collapsed.
......@@ -339,8 +339,8 @@ void V8Debugger::terminateExecution(
std::unique_ptr<TerminateExecutionCallback> callback) {
if (m_terminateExecutionCallback) {
if (callback) {
callback->sendFailure(
Response::Error("There is current termination request in progress"));
callback->sendFailure(Response::ServerError(
"There is current termination request in progress"));
}
return;
}
......@@ -394,9 +394,9 @@ Response V8Debugger::continueToLocation(
}
continueProgram(targetContextGroupId);
// TODO(kozyatinskiy): Return actual line and column number.
return Response::OK();
return Response::Success();
} else {
return Response::Error("Cannot continue to specified location");
return Response::ServerError("Cannot continue to specified location");
}
}
......
......@@ -173,7 +173,7 @@ void V8HeapProfilerAgentImpl::restore() {
Response V8HeapProfilerAgentImpl::collectGarbage() {
m_isolate->LowMemoryNotification();
return Response::OK();
return Response::Success();
}
Response V8HeapProfilerAgentImpl::startTrackingHeapObjects(
......@@ -183,7 +183,7 @@ Response V8HeapProfilerAgentImpl::startTrackingHeapObjects(
m_state->setBoolean(HeapProfilerAgentState::allocationTrackingEnabled,
allocationTrackingEnabled);
startTrackingHeapObjectsInternal(allocationTrackingEnabled);
return Response::OK();
return Response::Success();
}
Response V8HeapProfilerAgentImpl::stopTrackingHeapObjects(
......@@ -192,12 +192,12 @@ Response V8HeapProfilerAgentImpl::stopTrackingHeapObjects(
takeHeapSnapshot(std::move(reportProgress),
std::move(treatGlobalObjectsAsRoots));
stopTrackingHeapObjectsInternal();
return Response::OK();
return Response::Success();
}
Response V8HeapProfilerAgentImpl::enable() {
m_state->setBoolean(HeapProfilerAgentState::heapProfilerEnabled, true);
return Response::OK();
return Response::Success();
}
Response V8HeapProfilerAgentImpl::disable() {
......@@ -209,13 +209,13 @@ Response V8HeapProfilerAgentImpl::disable() {
}
m_isolate->GetHeapProfiler()->ClearObjectIds();
m_state->setBoolean(HeapProfilerAgentState::heapProfilerEnabled, false);
return Response::OK();
return Response::Success();
}
Response V8HeapProfilerAgentImpl::takeHeapSnapshot(
Maybe<bool> reportProgress, Maybe<bool> treatGlobalObjectsAsRoots) {
v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler();
if (!profiler) return Response::Error("Cannot access v8 heap profiler");
if (!profiler) return Response::ServerError("Cannot access v8 heap profiler");
std::unique_ptr<HeapSnapshotProgress> progress;
if (reportProgress.fromMaybe(false))
progress.reset(new HeapSnapshotProgress(&m_frontend));
......@@ -223,11 +223,11 @@ Response V8HeapProfilerAgentImpl::takeHeapSnapshot(
GlobalObjectNameResolver resolver(m_session);
const v8::HeapSnapshot* snapshot = profiler->TakeHeapSnapshot(
progress.get(), &resolver, treatGlobalObjectsAsRoots.fromMaybe(true));
if (!snapshot) return Response::Error("Failed to take heap snapshot");
if (!snapshot) return Response::ServerError("Failed to take heap snapshot");
HeapSnapshotOutputStream stream(&m_frontend);
snapshot->Serialize(&stream);
const_cast<v8::HeapSnapshot*>(snapshot)->Delete();
return Response::OK();
return Response::Success();
}
Response V8HeapProfilerAgentImpl::getObjectByHeapObjectId(
......@@ -235,36 +235,38 @@ Response V8HeapProfilerAgentImpl::getObjectByHeapObjectId(
std::unique_ptr<protocol::Runtime::RemoteObject>* result) {
bool ok;
int id = heapSnapshotObjectId.toInteger(&ok);
if (!ok) return Response::Error("Invalid heap snapshot object id");
if (!ok) return Response::ServerError("Invalid heap snapshot object id");
v8::HandleScope handles(m_isolate);
v8::Local<v8::Object> heapObject = objectByHeapObjectId(m_isolate, id);
if (heapObject.IsEmpty()) return Response::Error("Object is not available");
if (heapObject.IsEmpty())
return Response::ServerError("Object is not available");
if (!m_session->inspector()->client()->isInspectableHeapObject(heapObject))
return Response::Error("Object is not available");
return Response::ServerError("Object is not available");
*result = m_session->wrapObject(heapObject->CreationContext(), heapObject,
objectGroup.fromMaybe(""), false);
if (!*result) return Response::Error("Object is not available");
return Response::OK();
if (!*result) return Response::ServerError("Object is not available");
return Response::Success();
}
Response V8HeapProfilerAgentImpl::addInspectedHeapObject(
const String16& inspectedHeapObjectId) {
bool ok;
int id = inspectedHeapObjectId.toInteger(&ok);
if (!ok) return Response::Error("Invalid heap snapshot object id");
if (!ok) return Response::ServerError("Invalid heap snapshot object id");
v8::HandleScope handles(m_isolate);
v8::Local<v8::Object> heapObject = objectByHeapObjectId(m_isolate, id);
if (heapObject.IsEmpty()) return Response::Error("Object is not available");
if (heapObject.IsEmpty())
return Response::ServerError("Object is not available");
if (!m_session->inspector()->client()->isInspectableHeapObject(heapObject))
return Response::Error("Object is not available");
return Response::ServerError("Object is not available");
m_session->addInspectedObject(
std::unique_ptr<InspectableHeapObject>(new InspectableHeapObject(id)));
return Response::OK();
return Response::Success();
}
Response V8HeapProfilerAgentImpl::getHeapObjectId(
......@@ -274,12 +276,12 @@ Response V8HeapProfilerAgentImpl::getHeapObjectId(
v8::Local<v8::Context> context;
Response response =
m_session->unwrapObject(objectId, &value, &context, nullptr);
if (!response.isSuccess()) return response;
if (!response.IsSuccess()) return response;
if (value->IsUndefined()) return Response::InternalError();
v8::SnapshotObjectId id = m_isolate->GetHeapProfiler()->GetObjectId(value);
*heapSnapshotObjectId = String16::fromInteger(static_cast<size_t>(id));
return Response::OK();
return Response::Success();
}
void V8HeapProfilerAgentImpl::requestHeapStatsUpdate() {
......@@ -320,7 +322,7 @@ void V8HeapProfilerAgentImpl::stopTrackingHeapObjectsInternal() {
Response V8HeapProfilerAgentImpl::startSampling(
Maybe<double> samplingInterval) {
v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler();
if (!profiler) return Response::Error("Cannot access v8 heap profiler");
if (!profiler) return Response::ServerError("Cannot access v8 heap profiler");
const unsigned defaultSamplingInterval = 1 << 15;
double samplingIntervalValue =
samplingInterval.fromMaybe(defaultSamplingInterval);
......@@ -331,7 +333,7 @@ Response V8HeapProfilerAgentImpl::startSampling(
profiler->StartSamplingHeapProfiler(
static_cast<uint64_t>(samplingIntervalValue), 128,
v8::HeapProfiler::kSamplingForceGC);
return Response::OK();
return Response::Success();
}
namespace {
......@@ -367,7 +369,7 @@ buildSampingHeapProfileNode(v8::Isolate* isolate,
Response V8HeapProfilerAgentImpl::stopSampling(
std::unique_ptr<protocol::HeapProfiler::SamplingHeapProfile>* profile) {
Response result = getSamplingProfile(profile);
if (result.isSuccess()) {
if (result.IsSuccess()) {
m_isolate->GetHeapProfiler()->StopSamplingHeapProfiler();
m_state->setBoolean(HeapProfilerAgentState::samplingHeapProfilerEnabled,
false);
......@@ -383,7 +385,7 @@ Response V8HeapProfilerAgentImpl::getSamplingProfile(
std::unique_ptr<v8::AllocationProfile> v8Profile(
profiler->GetAllocationProfile());
if (!v8Profile)
return Response::Error("V8 sampling heap profiler was not started.");
return Response::ServerError("V8 sampling heap profiler was not started.");
v8::AllocationProfile::Node* root = v8Profile->GetRootNode();
auto samples = std::make_unique<
protocol::Array<protocol::HeapProfiler::SamplingHeapProfileSample>>();
......@@ -399,7 +401,7 @@ Response V8HeapProfilerAgentImpl::getSamplingProfile(
.setHead(buildSampingHeapProfileNode(m_isolate, root))
.setSamples(std::move(samples))
.build();
return Response::OK();
return Response::Success();
}
} // namespace v8_inspector
......@@ -467,12 +467,12 @@ class V8InspectorImpl::EvaluateScope::TerminateTask : public v8::Task {
protocol::Response V8InspectorImpl::EvaluateScope::setTimeout(double timeout) {
if (m_isolate->IsExecutionTerminating()) {
return protocol::Response::Error("Execution was terminated");
return protocol::Response::ServerError("Execution was terminated");
}
m_cancelToken.reset(new CancelToken());
v8::debug::GetCurrentPlatform()->CallDelayedOnWorkerThread(
std::make_unique<TerminateTask>(m_isolate, m_cancelToken), timeout);
return protocol::Response::OK();
return protocol::Response::Success();
}
} // namespace v8_inspector
......@@ -5,6 +5,7 @@
#include "src/inspector/v8-inspector-session-impl.h"
#include "../../third_party/inspector_protocol/crdtp/cbor.h"
#include "../../third_party/inspector_protocol/crdtp/dispatch.h"
#include "../../third_party/inspector_protocol/crdtp/json.h"
#include "src/base/logging.h"
#include "src/base/macros.h"
......@@ -184,23 +185,24 @@ std::unique_ptr<StringBuffer> V8InspectorSessionImpl::serializeForFrontend(
return StringBufferFrom(std::move(string16));
}
void V8InspectorSessionImpl::sendProtocolResponse(
void V8InspectorSessionImpl::SendProtocolResponse(
int callId, std::unique_ptr<protocol::Serializable> message) {
m_channel->sendResponse(callId, serializeForFrontend(std::move(message)));
}
void V8InspectorSessionImpl::sendProtocolNotification(
void V8InspectorSessionImpl::SendProtocolNotification(
std::unique_ptr<protocol::Serializable> message) {
m_channel->sendNotification(serializeForFrontend(std::move(message)));
}
void V8InspectorSessionImpl::fallThrough(int callId, const String16& method,
void V8InspectorSessionImpl::FallThrough(int callId,
const v8_crdtp::span<uint8_t> method,
v8_crdtp::span<uint8_t> message) {
// There's no other layer to handle the command.
UNREACHABLE();
}
void V8InspectorSessionImpl::flushProtocolNotifications() {
void V8InspectorSessionImpl::FlushProtocolNotifications() {
m_channel->flushProtocolNotifications();
}
......@@ -224,14 +226,15 @@ Response V8InspectorSessionImpl::findInjectedScript(
injectedScript = nullptr;
InspectedContext* context =
m_inspector->getContext(m_contextGroupId, contextId);
if (!context) return Response::Error("Cannot find context with specified id");
if (!context)
return Response::ServerError("Cannot find context with specified id");
injectedScript = context->getInjectedScript(m_sessionId);
if (!injectedScript) {
injectedScript = context->createInjectedScript(m_sessionId);
if (m_customObjectFormatterEnabled)
injectedScript->setCustomObjectFormatterEnabled(true);
}
return Response::OK();
return Response::Success();
}
Response V8InspectorSessionImpl::findInjectedScript(
......@@ -259,8 +262,11 @@ bool V8InspectorSessionImpl::unwrapObject(
String16 objectGroupString;
Response response = unwrapObject(toString16(objectId), object, context,
objectGroup ? &objectGroupString : nullptr);
if (!response.isSuccess()) {
if (error) *error = StringBufferFrom(response.errorMessage());
if (response.IsError()) {
if (error) {
const std::string& msg = response.Message();
*error = StringBufferFrom(String16::fromUTF8(msg.data(), msg.size()));
}
return false;
}
if (objectGroup)
......@@ -274,15 +280,15 @@ Response V8InspectorSessionImpl::unwrapObject(const String16& objectId,
String16* objectGroup) {
std::unique_ptr<RemoteObjectId> remoteId;
Response response = RemoteObjectId::parse(objectId, &remoteId);
if (!response.isSuccess()) return response;
if (!response.IsSuccess()) return response;
InjectedScript* injectedScript = nullptr;
response = findInjectedScript(remoteId.get(), injectedScript);
if (!response.isSuccess()) return response;
if (!response.IsSuccess()) return response;
response = injectedScript->findObject(*remoteId, object);
if (!response.isSuccess()) return response;
if (!response.IsSuccess()) return response;
*context = injectedScript->context()->context();
if (objectGroup) *objectGroup = injectedScript->objectGroupName(*remoteId);
return Response::OK();
return Response::Success();
}
std::unique_ptr<protocol::Runtime::API::RemoteObject>
......@@ -349,19 +355,29 @@ void V8InspectorSessionImpl::dispatchProtocolMessage(
} else {
// We're ignoring the return value of the conversion function
// intentionally. It means the |parsed_message| below will be nullptr.
ConvertToCBOR(message, &converted_cbor);
auto status = ConvertToCBOR(message, &converted_cbor);
if (!status.ok()) {
m_channel->sendNotification(
serializeForFrontend(v8_crdtp::CreateErrorNotification(
v8_crdtp::DispatchResponse::ParseError(status.ToASCIIString()))));
return;
}
cbor = SpanFrom(converted_cbor);
}
int callId;
std::unique_ptr<protocol::Value> parsed_message =
protocol::Value::parseBinary(cbor.data(), cbor.size());
String16 method;
if (m_dispatcher.parseCommand(parsed_message.get(), &callId, &method)) {
// Pass empty string instead of the actual message to save on a conversion.
// We're allowed to do so because fall-through is not implemented.
m_dispatcher.dispatch(callId, method, std::move(parsed_message),
v8_crdtp::span<uint8_t>());
v8_crdtp::Dispatchable dispatchable(cbor);
if (!dispatchable.ok()) {
if (dispatchable.HasCallId()) {
m_channel->sendNotification(serializeForFrontend(
v8_crdtp::CreateErrorNotification(dispatchable.DispatchError())));
} else {
m_channel->sendResponse(
dispatchable.CallId(),
serializeForFrontend(v8_crdtp::CreateErrorResponse(
dispatchable.CallId(), dispatchable.DispatchError())));
}
return;
}
m_dispatcher.Dispatch(dispatchable).Run();
}
std::vector<uint8_t> V8InspectorSessionImpl::state() {
......
......@@ -100,13 +100,13 @@ class V8InspectorSessionImpl : public V8InspectorSession,
protocol::DictionaryValue* agentState(const String16& name);
// protocol::FrontendChannel implementation.
void sendProtocolResponse(
void SendProtocolResponse(
int callId, std::unique_ptr<protocol::Serializable> message) override;
void sendProtocolNotification(
void SendProtocolNotification(
std::unique_ptr<protocol::Serializable> message) override;
void fallThrough(int callId, const String16& method,
void FallThrough(int callId, v8_crdtp::span<uint8_t> method,
v8_crdtp::span<uint8_t> message) override;
void flushProtocolNotifications() override;
void FlushProtocolNotifications() override;
std::unique_ptr<StringBuffer> serializeForFrontend(
std::unique_ptr<protocol::Serializable> message);
......
......@@ -220,14 +220,14 @@ void V8ProfilerAgentImpl::consoleProfileEnd(const String16& title) {
}
Response V8ProfilerAgentImpl::enable() {
if (m_enabled) return Response::OK();
if (m_enabled) return Response::Success();
m_enabled = true;
m_state->setBoolean(ProfilerAgentState::profilerEnabled, true);
return Response::OK();
return Response::Success();
}
Response V8ProfilerAgentImpl::disable() {
if (!m_enabled) return Response::OK();
if (!m_enabled) return Response::Success();
for (size_t i = m_startedProfiles.size(); i > 0; --i)
stopProfiling(m_startedProfiles[i - 1].m_id, false);
m_startedProfiles.clear();
......@@ -236,15 +236,16 @@ Response V8ProfilerAgentImpl::disable() {
DCHECK(!m_profiler);
m_enabled = false;
m_state->setBoolean(ProfilerAgentState::profilerEnabled, false);
return Response::OK();
return Response::Success();
}
Response V8ProfilerAgentImpl::setSamplingInterval(int interval) {
if (m_profiler) {
return Response::Error("Cannot change sampling interval when profiling.");
return Response::ServerError(
"Cannot change sampling interval when profiling.");
}
m_state->setInteger(ProfilerAgentState::samplingInterval, interval);
return Response::OK();
return Response::Success();
}
void V8ProfilerAgentImpl::restore() {
......@@ -272,36 +273,36 @@ void V8ProfilerAgentImpl::restore() {
}
Response V8ProfilerAgentImpl::start() {
if (m_recordingCPUProfile) return Response::OK();
if (!m_enabled) return Response::Error("Profiler is not enabled");
if (m_recordingCPUProfile) return Response::Success();
if (!m_enabled) return Response::ServerError("Profiler is not enabled");
m_recordingCPUProfile = true;
m_frontendInitiatedProfileId = nextProfileId();
startProfiling(m_frontendInitiatedProfileId);
m_state->setBoolean(ProfilerAgentState::userInitiatedProfiling, true);
return Response::OK();
return Response::Success();
}
Response V8ProfilerAgentImpl::stop(
std::unique_ptr<protocol::Profiler::Profile>* profile) {
if (!m_recordingCPUProfile) {
return Response::Error("No recording profiles found");
return Response::ServerError("No recording profiles found");
}
m_recordingCPUProfile = false;
std::unique_ptr<protocol::Profiler::Profile> cpuProfile =
stopProfiling(m_frontendInitiatedProfileId, !!profile);
if (profile) {
*profile = std::move(cpuProfile);
if (!profile->get()) return Response::Error("Profile is not found");
if (!profile->get()) return Response::ServerError("Profile is not found");
}
m_frontendInitiatedProfileId = String16();
m_state->setBoolean(ProfilerAgentState::userInitiatedProfiling, false);
return Response::OK();
return Response::Success();
}
Response V8ProfilerAgentImpl::startPreciseCoverage(
Maybe<bool> callCount, Maybe<bool> detailed,
Maybe<bool> allowTriggeredUpdates, double* out_timestamp) {
if (!m_enabled) return Response::Error("Profiler is not enabled");
if (!m_enabled) return Response::ServerError("Profiler is not enabled");
*out_timestamp =
v8::base::TimeTicks::HighResolutionNow().since_origin().InSecondsF();
bool callCountValue = callCount.fromMaybe(false);
......@@ -324,17 +325,17 @@ Response V8ProfilerAgentImpl::startPreciseCoverage(
? (detailedValue ? Mode::kBlockCount : Mode::kPreciseCount)
: (detailedValue ? Mode::kBlockBinary : Mode::kPreciseBinary);
C::SelectMode(m_isolate, mode);
return Response::OK();
return Response::Success();
}
Response V8ProfilerAgentImpl::stopPreciseCoverage() {
if (!m_enabled) return Response::Error("Profiler is not enabled");
if (!m_enabled) return Response::ServerError("Profiler is not enabled");
m_state->setBoolean(ProfilerAgentState::preciseCoverageStarted, false);
m_state->setBoolean(ProfilerAgentState::preciseCoverageCallCount, false);
m_state->setBoolean(ProfilerAgentState::preciseCoverageDetailed, false);
v8::debug::Coverage::SelectMode(m_isolate,
v8::debug::CoverageMode::kBestEffort);
return Response::OK();
return Response::Success();
}
namespace {
......@@ -402,7 +403,7 @@ Response coverageToProtocol(
.build());
}
*out_result = std::move(result);
return Response::OK();
return Response::Success();
}
} // anonymous namespace
......@@ -412,7 +413,7 @@ Response V8ProfilerAgentImpl::takePreciseCoverage(
double* out_timestamp) {
if (!m_state->booleanProperty(ProfilerAgentState::preciseCoverageStarted,
false)) {
return Response::Error("Precise coverage has not been started.");
return Response::ServerError("Precise coverage has not been started.");
}
v8::HandleScope handle_scope(m_isolate);
v8::debug::Coverage coverage = v8::debug::Coverage::CollectPrecise(m_isolate);
......@@ -500,14 +501,14 @@ Response V8ProfilerAgentImpl::startTypeProfile() {
m_state->setBoolean(ProfilerAgentState::typeProfileStarted, true);
v8::debug::TypeProfile::SelectMode(m_isolate,
v8::debug::TypeProfileMode::kCollect);
return Response::OK();
return Response::Success();
}
Response V8ProfilerAgentImpl::stopTypeProfile() {
m_state->setBoolean(ProfilerAgentState::typeProfileStarted, false);
v8::debug::TypeProfile::SelectMode(m_isolate,
v8::debug::TypeProfileMode::kNone);
return Response::OK();
return Response::Success();
}
Response V8ProfilerAgentImpl::takeTypeProfile(
......@@ -515,37 +516,38 @@ Response V8ProfilerAgentImpl::takeTypeProfile(
out_result) {
if (!m_state->booleanProperty(ProfilerAgentState::typeProfileStarted,
false)) {
return Response::Error("Type profile has not been started.");
return Response::ServerError("Type profile has not been started.");
}
v8::HandleScope handle_scope(m_isolate);
v8::debug::TypeProfile type_profile =
v8::debug::TypeProfile::Collect(m_isolate);
*out_result = typeProfileToProtocol(m_session->inspector(), type_profile);
return Response::OK();
return Response::Success();
}
Response V8ProfilerAgentImpl::enableRuntimeCallStats() {
if (m_counters)
return Response::Error("RuntimeCallStats collection already enabled.");
return Response::ServerError(
"RuntimeCallStats collection already enabled.");
if (V8Inspector* inspector = v8::debug::GetInspector(m_isolate))
m_counters = inspector->enableCounters();
else
return Response::Error("No inspector found.");
return Response::ServerError("No inspector found.");
return Response::OK();
return Response::Success();
}
Response V8ProfilerAgentImpl::disableRuntimeCallStats() {
if (m_counters) m_counters.reset();
return Response::OK();
return Response::Success();
}
Response V8ProfilerAgentImpl::getRuntimeCallStats(
std::unique_ptr<protocol::Array<protocol::Profiler::CounterInfo>>*
out_result) {
if (!m_counters)
return Response::Error("RuntimeCallStats collection is not enabled.");
return Response::ServerError("RuntimeCallStats collection is not enabled.");
*out_result =
std::make_unique<protocol::Array<protocol::Profiler::CounterInfo>>();
......@@ -559,7 +561,7 @@ Response V8ProfilerAgentImpl::getRuntimeCallStats(
.build());
}
return Response::OK();
return Response::Success();
}
String16 V8ProfilerAgentImpl::nextProfileId() {
......
This diff is collapsed.
......@@ -21,7 +21,7 @@ Response V8SchemaAgentImpl::getDomains(
*result =
std::make_unique<std::vector<std::unique_ptr<protocol::Schema::Domain>>>(
m_session->supportedDomainsImpl());
return Response::OK();
return Response::Success();
}
} // namespace v8_inspector
......@@ -42,17 +42,18 @@ V8InternalValueType v8InternalValueTypeFrom(v8::Local<v8::Context> context,
Response toProtocolValue(v8::Local<v8::Context> context,
v8::Local<v8::Value> value, int maxDepth,
std::unique_ptr<protocol::Value>* result) {
if (!maxDepth) return Response::Error("Object reference chain is too long");
if (!maxDepth)
return Response::ServerError("Object reference chain is too long");
maxDepth--;
if (value->IsNull() || value->IsUndefined()) {
*result = protocol::Value::null();
return Response::OK();
return Response::Success();
}
if (value->IsBoolean()) {
*result =
protocol::FundamentalValue::create(value.As<v8::Boolean>()->Value());
return Response::OK();
return Response::Success();
}
if (value->IsNumber()) {
double doubleValue = value.As<v8::Number>()->Value();
......@@ -62,16 +63,16 @@ Response toProtocolValue(v8::Local<v8::Context> context,
int intValue = static_cast<int>(doubleValue);
if (intValue == doubleValue) {
*result = protocol::FundamentalValue::create(intValue);
return Response::OK();
return Response::Success();
}
}
*result = protocol::FundamentalValue::create(doubleValue);
return Response::OK();
return Response::Success();
}
if (value->IsString()) {
*result = protocol::StringValue::create(
toProtocolString(context->GetIsolate(), value.As<v8::String>()));
return Response::OK();
return Response::Success();
}
if (value->IsArray()) {
v8::Local<v8::Array> array = value.As<v8::Array>();
......@@ -84,11 +85,11 @@ Response toProtocolValue(v8::Local<v8::Context> context,
return Response::InternalError();
std::unique_ptr<protocol::Value> element;
Response response = toProtocolValue(context, value, maxDepth, &element);
if (!response.isSuccess()) return response;
if (!response.IsSuccess()) return response;
inspectorArray->pushValue(std::move(element));
}
*result = std::move(inspectorArray);
return Response::OK();
return Response::Success();
}
if (value->IsObject()) {
std::unique_ptr<protocol::DictionaryValue> jsonObject =
......@@ -119,21 +120,21 @@ Response toProtocolValue(v8::Local<v8::Context> context,
std::unique_ptr<protocol::Value> propertyValue;
Response response =
toProtocolValue(context, property, maxDepth, &propertyValue);
if (!response.isSuccess()) return response;
if (!response.IsSuccess()) return response;
jsonObject->setValue(
toProtocolString(context->GetIsolate(), propertyName),
std::move(propertyValue));
}
*result = std::move(jsonObject);
return Response::OK();
return Response::Success();
}
return Response::Error("Object couldn't be returned by value");
return Response::ServerError("Object couldn't be returned by value");
}
Response toProtocolValue(v8::Local<v8::Context> context,
v8::Local<v8::Value> value,
std::unique_ptr<protocol::Value>* result) {
if (value->IsUndefined()) return Response::OK();
if (value->IsUndefined()) return Response::Success();
return toProtocolValue(context, value, 1000, result);
}
......@@ -361,7 +362,7 @@ class PrimitiveValueMirror final : public ValueMirror {
.build();
if (m_value->IsNull())
(*result)->setSubtype(RemoteObject::SubtypeEnum::Null);
return Response::OK();
return Response::Success();
}
void buildEntryPreview(
......@@ -416,7 +417,7 @@ class NumberMirror final : public ValueMirror {
} else {
(*result)->setValue(protocol::FundamentalValue::create(m_value->Value()));
}
return Response::OK();
return Response::Success();
}
void buildPropertyPreview(
v8::Local<v8::Context> context, const String16& name,
......@@ -470,7 +471,7 @@ class BigIntMirror final : public ValueMirror {
.setUnserializableValue(description)
.setDescription(description)
.build();
return Response::OK();
return Response::Success();
}
void buildPropertyPreview(v8::Local<v8::Context> context,
......@@ -513,13 +514,13 @@ class SymbolMirror final : public ValueMirror {
v8::Local<v8::Context> context, WrapMode mode,
std::unique_ptr<RemoteObject>* result) const override {
if (mode == WrapMode::kForceValue) {
return Response::Error("Object couldn't be returned by value");
return Response::ServerError("Object couldn't be returned by value");
}
*result = RemoteObject::create()
.setType(RemoteObject::TypeEnum::Symbol)
.setDescription(descriptionForSymbol(context, m_symbol))
.build();
return Response::OK();
return Response::Success();
}
void buildPropertyPreview(v8::Local<v8::Context> context,
......@@ -576,7 +577,7 @@ class LocationMirror final : public ValueMirror {
.setDescription("Object")
.setValue(std::move(location))
.build();
return Response::OK();
return Response::Success();
}
v8::Local<v8::Value> v8Value() const override { return m_value; }
......@@ -620,7 +621,7 @@ class FunctionMirror final : public ValueMirror {
if (mode == WrapMode::kForceValue) {
std::unique_ptr<protocol::Value> protocolValue;
Response response = toProtocolValue(context, m_value, &protocolValue);
if (!response.isSuccess()) return response;
if (!response.IsSuccess()) return response;
*result = RemoteObject::create()
.setType(RemoteObject::TypeEnum::Function)
.setValue(std::move(protocolValue))
......@@ -633,7 +634,7 @@ class FunctionMirror final : public ValueMirror {
.setDescription(descriptionForFunction(context, m_value))
.build();
}
return Response::OK();
return Response::Success();
}
void buildPropertyPreview(
......@@ -881,7 +882,7 @@ class ObjectMirror final : public ValueMirror {
if (mode == WrapMode::kForceValue) {
std::unique_ptr<protocol::Value> protocolValue;
Response response = toProtocolValue(context, m_value, &protocolValue);
if (!response.isSuccess()) return response;
if (!response.IsSuccess()) return response;
*result = RemoteObject::create()
.setType(RemoteObject::TypeEnum::Object)
.setValue(std::move(protocolValue))
......@@ -904,7 +905,7 @@ class ObjectMirror final : public ValueMirror {
(*result)->setPreview(std::move(previewValue));
}
}
return Response::OK();
return Response::Success();
}
void buildObjectPreview(
......
......@@ -14,9 +14,12 @@ v8_source_set("crdtp") {
sources = [
"crdtp/cbor.cc",
"crdtp/cbor.h",
"crdtp/dispatch.cc",
"crdtp/dispatch.h",
"crdtp/error_support.cc",
"crdtp/error_support.h",
"crdtp/export.h",
"crdtp/find_by_first.h",
"crdtp/glue.h",
"crdtp/json.cc",
"crdtp/json.h",
......@@ -24,6 +27,7 @@ v8_source_set("crdtp") {
"crdtp/serializable.cc",
"crdtp/serializable.h",
"crdtp/serializer_traits.h",
"crdtp/span.cc",
"crdtp/span.h",
"crdtp/status.cc",
"crdtp/status.h",
......@@ -47,7 +51,9 @@ v8_source_set("crdtp_platform") {
v8_source_set("crdtp_test") {
sources = [
"crdtp/cbor_test.cc",
"crdtp/dispatch_test.cc",
"crdtp/error_support_test.cc",
"crdtp/find_by_first_test.cc",
"crdtp/glue_test.cc",
"crdtp/json_test.cc",
"crdtp/serializable_test.cc",
......
......@@ -2,7 +2,7 @@ Name: inspector protocol
Short Name: inspector_protocol
URL: https://chromium.googlesource.com/deps/inspector_protocol/
Version: 0
Revision: 81ef742ba3587767fc08652d299df9e9b7051407
Revision: c69cdc36200992d21a17bf4e5c2f3a95b8860ddf
License: BSD
License File: LICENSE
Security Critical: no
......
......@@ -658,19 +658,16 @@ def main():
"Values_h.template",
"Object_h.template",
"ValueConversions_h.template",
"DispatcherBase_h.template",
]
protocol_cpp_templates = [
"Protocol_cpp.template",
"Values_cpp.template",
"Object_cpp.template",
"DispatcherBase_cpp.template",
]
forward_h_templates = [
"Forward_h.template",
"FrontendChannel_h.template",
]
base_string_adapter_h_templates = [
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -7,6 +7,7 @@
#include <cstdint>
#include <string>
#include <vector>
#include "export.h"
#include "span.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.
#ifndef V8_CRDTP_FIND_BY_FIRST_H_
#define V8_CRDTP_FIND_BY_FIRST_H_
#include <algorithm>
#include <cstdint>
#include <memory>
#include <vector>
#include "export.h"
#include "span.h"
namespace v8_crdtp {
// =============================================================================
// FindByFirst - Retrieval from a sorted vector that's keyed by span<uint8_t>.
// =============================================================================
// Given a vector of pairs sorted by the first element of each pair, find
// the corresponding value given a key to be compared to the first element.
// Together with std::inplace_merge and pre-sorting or std::sort, this can
// be used to implement a minimalistic equivalent of Chromium's flat_map.
// In this variant, the template parameter |T| is a value type and a
// |default_value| is provided.
template <typename T>
T FindByFirst(const std::vector<std::pair<span<uint8_t>, T>>& sorted_by_first,
span<uint8_t> key,
T default_value) {
auto it = std::lower_bound(
sorted_by_first.begin(), sorted_by_first.end(), key,
[](const std::pair<span<uint8_t>, T>& left, span<uint8_t> right) {
return SpanLessThan(left.first, right);
});
return (it != sorted_by_first.end() && SpanEquals(it->first, key))
? it->second
: default_value;
}
// In this variant, the template parameter |T| is a class or struct that's
// instantiated in std::unique_ptr, and we return either a T* or a nullptr.
template <typename T>
T* FindByFirst(const std::vector<std::pair<span<uint8_t>, std::unique_ptr<T>>>&
sorted_by_first,
span<uint8_t> key) {
auto it = std::lower_bound(
sorted_by_first.begin(), sorted_by_first.end(), key,
[](const std::pair<span<uint8_t>, std::unique_ptr<T>>& left,
span<uint8_t> right) { return SpanLessThan(left.first, right); });
return (it != sorted_by_first.end() && SpanEquals(it->first, key))
? it->second.get()
: nullptr;
}
} // namespace v8_crdtp
#endif // V8_CRDTP_FIND_BY_FIRST_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 <string>
#include "find_by_first.h"
#include "test_platform.h"
namespace v8_crdtp {
// =============================================================================
// FindByFirst - Efficient retrieval from a sorted vector.
// =============================================================================
TEST(FindByFirst, SpanBySpan) {
std::vector<std::pair<span<uint8_t>, span<uint8_t>>> sorted_span_by_span = {
{SpanFrom("foo1"), SpanFrom("bar1")},
{SpanFrom("foo2"), SpanFrom("bar2")},
{SpanFrom("foo3"), SpanFrom("bar3")},
};
{
auto result = FindByFirst(sorted_span_by_span, SpanFrom("foo1"),
SpanFrom("not_found"));
EXPECT_EQ("bar1", std::string(result.begin(), result.end()));
}
{
auto result = FindByFirst(sorted_span_by_span, SpanFrom("foo3"),
SpanFrom("not_found"));
EXPECT_EQ("bar3", std::string(result.begin(), result.end()));
}
{
auto result = FindByFirst(sorted_span_by_span, SpanFrom("baz"),
SpanFrom("not_found"));
EXPECT_EQ("not_found", std::string(result.begin(), result.end()));
}
}
namespace {
class TestObject {
public:
explicit TestObject(const std::string& message) : message_(message) {}
const std::string& message() const { return message_; }
private:
std::string message_;
};
} // namespace
TEST(FindByFirst, ObjectBySpan) {
std::vector<std::pair<span<uint8_t>, std::unique_ptr<TestObject>>>
sorted_object_by_span;
sorted_object_by_span.push_back(
std::make_pair(SpanFrom("foo1"), std::make_unique<TestObject>("bar1")));
sorted_object_by_span.push_back(
std::make_pair(SpanFrom("foo2"), std::make_unique<TestObject>("bar2")));
sorted_object_by_span.push_back(
std::make_pair(SpanFrom("foo3"), std::make_unique<TestObject>("bar3")));
{
TestObject* result =
FindByFirst<TestObject>(sorted_object_by_span, SpanFrom("foo1"));
ASSERT_TRUE(result);
ASSERT_EQ("bar1", result->message());
}
{
TestObject* result =
FindByFirst<TestObject>(sorted_object_by_span, SpanFrom("foo3"));
ASSERT_TRUE(result);
ASSERT_EQ("bar3", result->message());
}
{
TestObject* result =
FindByFirst<TestObject>(sorted_object_by_span, SpanFrom("baz"));
ASSERT_FALSE(result);
}
}
} // 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_FRONTEND_CHANNEL_H_
#define V8_CRDTP_FRONTEND_CHANNEL_H_
#include <cstdint>
#include <memory>
#include "export.h"
#include "serializable.h"
#include "span.h"
namespace v8_crdtp {
// =============================================================================
// FrontendChannel - For sending notifications and responses to protocol clients
// =============================================================================
class FrontendChannel {
public:
virtual ~FrontendChannel() = default;
// Sends protocol responses and notifications. The |call_id| parameter is
// seemingly redundant because it's also included in the message, but
// responses may be sent from an untrusted source to a trusted process (e.g.
// from Chromium's renderer (blink) to the browser process), which needs
// to be able to match the response to an earlier request without parsing the
// messsage.
virtual void SendProtocolResponse(int call_id,
std::unique_ptr<Serializable> message) = 0;
virtual void SendProtocolNotification(
std::unique_ptr<Serializable> message) = 0;
// FallThrough indicates that |message| should be handled in another layer.
// Usually this means the layer responding to the message didn't handle it,
// but in some cases messages are handled by multiple layers (e.g. both
// the embedder and the content layer in Chromium).
virtual void FallThrough(int call_id,
span<uint8_t> method,
span<uint8_t> message) = 0;
// Session implementations may queue notifications for performance or
// other considerations; this is a hook for domain handlers to manually flush.
virtual void FlushProtocolNotifications() = 0;
};
} // namespace v8_crdtp
#endif // V8_CRDTP_FRONTEND_CHANNEL_H_
......@@ -6,6 +6,7 @@
#define V8_CRDTP_JSON_H_
#include <memory>
#include <vector>
#include "export.h"
#include "parser_handler.h"
......
......@@ -14,4 +14,23 @@ std::vector<uint8_t> Serializable::Serialize() const {
AppendSerialized(&out);
return out;
}
namespace {
class PreSerialized : public Serializable {
public:
explicit PreSerialized(std::vector<uint8_t> bytes) : bytes_(bytes) {}
void AppendSerialized(std::vector<uint8_t>* out) const override {
out->insert(out->end(), bytes_.begin(), bytes_.end());
}
private:
std::vector<uint8_t> bytes_;
};
} // namespace
// static
std::unique_ptr<Serializable> Serializable::From(std::vector<uint8_t> bytes) {
return std::make_unique<PreSerialized>(std::move(bytes));
}
} // namespace v8_crdtp
......@@ -6,6 +6,7 @@
#define V8_CRDTP_SERIALIZABLE_H_
#include <cstdint>
#include <memory>
#include <vector>
#include "export.h"
......@@ -13,7 +14,6 @@ namespace v8_crdtp {
// =============================================================================
// Serializable - An object to be emitted as a sequence of bytes.
// =============================================================================
class Serializable {
public:
// Convenience: Invokes |AppendSerialized| on an empty vector.
......@@ -22,6 +22,10 @@ class Serializable {
virtual void AppendSerialized(std::vector<uint8_t>* out) const = 0;
virtual ~Serializable() = default;
// Wraps a vector of |bytes| into a Serializable for situations in which we
// eagerly serialize a structure.
static std::unique_ptr<Serializable> From(std::vector<uint8_t> bytes);
};
} // 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.
#include "span.h"
#include <algorithm>
namespace v8_crdtp {
bool SpanLessThan(span<uint8_t> x, span<uint8_t> y) noexcept {
auto min_size = std::min(x.size(), y.size());
const int r = min_size == 0 ? 0 : memcmp(x.data(), y.data(), min_size);
return (r < 0) || (r == 0 && x.size() < y.size());
}
bool SpanEquals(span<uint8_t> x, span<uint8_t> y) noexcept {
auto len = x.size();
if (len != y.size())
return false;
return x.data() == y.data() || len == 0 ||
std::memcmp(x.data(), y.data(), len) == 0;
}
} // namespace v8_crdtp
......@@ -5,11 +5,11 @@
#ifndef V8_CRDTP_SPAN_H_
#define V8_CRDTP_SPAN_H_
#include <algorithm>
#include <cstdint>
#include <cstring>
#include <string>
#include <vector>
#include "export.h"
namespace v8_crdtp {
// =============================================================================
......@@ -76,19 +76,15 @@ inline span<typename C::value_type> SpanFrom(const C& v) {
// Less than / equality comparison functions for sorting / searching for byte
// spans. These are similar to absl::string_view's < and == operators.
constexpr inline bool SpanLessThan(span<uint8_t> x, span<uint8_t> y) noexcept {
auto min_size = std::min(x.size(), y.size());
const int r = min_size == 0 ? 0 : memcmp(x.data(), y.data(), min_size);
return (r < 0) || (r == 0 && x.size() < y.size());
}
bool SpanLessThan(span<uint8_t> x, span<uint8_t> y) noexcept;
constexpr inline bool SpanEquals(span<uint8_t> x, span<uint8_t> y) noexcept {
auto len = x.size();
if (len != y.size())
return false;
return x.data() == y.data() || len == 0 ||
std::memcmp(x.data(), y.data(), len) == 0;
}
bool SpanEquals(span<uint8_t> x, span<uint8_t> y) noexcept;
struct SpanLt {
bool operator()(span<uint8_t> l, span<uint8_t> r) const {
return SpanLessThan(l, r);
}
};
} // namespace v8_crdtp
#endif // V8_CRDTP_SPAN_H_
......@@ -4,7 +4,6 @@
#include <cstdlib>
#include <string>
#include <unordered_map>
#include "span.h"
#include "test_platform.h"
......@@ -13,7 +12,6 @@ namespace v8_crdtp {
// =============================================================================
// span - sequence of bytes
// =============================================================================
template <typename T>
class SpanTest : public ::testing::Test {};
......@@ -108,41 +106,4 @@ TEST(SpanComparisons, ByteWiseLexicographicalOrder) {
EXPECT_FALSE(SpanLessThan(SpanFrom(msg), SpanFrom(lesser_msg)));
EXPECT_FALSE(SpanEquals(SpanFrom(msg), SpanFrom(lesser_msg)));
}
// TODO(johannes): The following shows how the span can be used in an
// std::unordered_map as a key. Once we have a production usage, we'll move
// SpanHash, SpanEq, SpanHasher into the header.
// A simple hash code, inspired by http://stackoverflow.com/q/1646807.
constexpr inline size_t SpanHash(span<uint8_t> s) noexcept {
size_t hash = 17;
for (uint8_t c : s)
hash = 31 * hash + c;
return hash;
}
// Structs for making std::unordered_map with std::span<uint8_t> keys.
struct SpanEq {
constexpr inline bool operator()(span<uint8_t> l, span<uint8_t> r) const {
return SpanEquals(l, r);
}
};
struct SpanHasher {
constexpr inline size_t operator()(span<uint8_t> s) const {
return SpanHash(s);
}
};
TEST(SpanHasherAndSpanEq, SpanAsKeyInUnorderedMap) {
// A very simple smoke test for unordered_map, storing three key/value pairs.
std::unordered_map<span<uint8_t>, int32_t, SpanHasher, SpanEq> a_map;
a_map[SpanFrom("foo")] = 1;
a_map[SpanFrom("bar")] = 2;
a_map[SpanFrom("baz")] = 3;
EXPECT_EQ(3u, a_map.size());
EXPECT_EQ(1, a_map[SpanFrom("foo")]);
EXPECT_EQ(2, a_map[SpanFrom("bar")]);
EXPECT_EQ(3, a_map[SpanFrom("baz")]);
}
} // namespace v8_crdtp
......@@ -9,100 +9,118 @@ namespace v8_crdtp {
// Status and Error codes
// =============================================================================
std::string Status::ToASCIIString() const {
std::string Status::Message() const {
switch (error) {
case Error::OK:
return "OK";
case Error::JSON_PARSER_UNPROCESSED_INPUT_REMAINS:
return ToASCIIString("JSON: unprocessed input remains");
return "JSON: unprocessed input remains";
case Error::JSON_PARSER_STACK_LIMIT_EXCEEDED:
return ToASCIIString("JSON: stack limit exceeded");
return "JSON: stack limit exceeded";
case Error::JSON_PARSER_NO_INPUT:
return ToASCIIString("JSON: no input");
return "JSON: no input";
case Error::JSON_PARSER_INVALID_TOKEN:
return ToASCIIString("JSON: invalid token");
return "JSON: invalid token";
case Error::JSON_PARSER_INVALID_NUMBER:
return ToASCIIString("JSON: invalid number");
return "JSON: invalid number";
case Error::JSON_PARSER_INVALID_STRING:
return ToASCIIString("JSON: invalid string");
return "JSON: invalid string";
case Error::JSON_PARSER_UNEXPECTED_ARRAY_END:
return ToASCIIString("JSON: unexpected array end");
return "JSON: unexpected array end";
case Error::JSON_PARSER_COMMA_OR_ARRAY_END_EXPECTED:
return ToASCIIString("JSON: comma or array end expected");
return "JSON: comma or array end expected";
case Error::JSON_PARSER_STRING_LITERAL_EXPECTED:
return ToASCIIString("JSON: string literal expected");
return "JSON: string literal expected";
case Error::JSON_PARSER_COLON_EXPECTED:
return ToASCIIString("JSON: colon expected");
return "JSON: colon expected";
case Error::JSON_PARSER_UNEXPECTED_MAP_END:
return ToASCIIString("JSON: unexpected map end");
return "JSON: unexpected map end";
case Error::JSON_PARSER_COMMA_OR_MAP_END_EXPECTED:
return ToASCIIString("JSON: comma or map end expected");
return "JSON: comma or map end expected";
case Error::JSON_PARSER_VALUE_EXPECTED:
return ToASCIIString("JSON: value expected");
return "JSON: value expected";
case Error::CBOR_INVALID_INT32:
return ToASCIIString("CBOR: invalid int32");
return "CBOR: invalid int32";
case Error::CBOR_INVALID_DOUBLE:
return ToASCIIString("CBOR: invalid double");
return "CBOR: invalid double";
case Error::CBOR_INVALID_ENVELOPE:
return ToASCIIString("CBOR: invalid envelope");
return "CBOR: invalid envelope";
case Error::CBOR_ENVELOPE_CONTENTS_LENGTH_MISMATCH:
return ToASCIIString("CBOR: envelope contents length mismatch");
return "CBOR: envelope contents length mismatch";
case Error::CBOR_MAP_OR_ARRAY_EXPECTED_IN_ENVELOPE:
return ToASCIIString("CBOR: map or array expected in envelope");
return "CBOR: map or array expected in envelope";
case Error::CBOR_INVALID_STRING8:
return ToASCIIString("CBOR: invalid string8");
return "CBOR: invalid string8";
case Error::CBOR_INVALID_STRING16:
return ToASCIIString("CBOR: invalid string16");
return "CBOR: invalid string16";
case Error::CBOR_INVALID_BINARY:
return ToASCIIString("CBOR: invalid binary");
return "CBOR: invalid binary";
case Error::CBOR_UNSUPPORTED_VALUE:
return ToASCIIString("CBOR: unsupported value");
return "CBOR: unsupported value";
case Error::CBOR_NO_INPUT:
return ToASCIIString("CBOR: no input");
return "CBOR: no input";
case Error::CBOR_INVALID_START_BYTE:
return ToASCIIString("CBOR: invalid start byte");
return "CBOR: invalid start byte";
case Error::CBOR_UNEXPECTED_EOF_EXPECTED_VALUE:
return ToASCIIString("CBOR: unexpected eof expected value");
return "CBOR: unexpected eof expected value";
case Error::CBOR_UNEXPECTED_EOF_IN_ARRAY:
return ToASCIIString("CBOR: unexpected eof in array");
return "CBOR: unexpected eof in array";
case Error::CBOR_UNEXPECTED_EOF_IN_MAP:
return ToASCIIString("CBOR: unexpected eof in map");
return "CBOR: unexpected eof in map";
case Error::CBOR_INVALID_MAP_KEY:
return ToASCIIString("CBOR: invalid map key");
return "CBOR: invalid map key";
case Error::CBOR_DUPLICATE_MAP_KEY:
return "CBOR: duplicate map key";
case Error::CBOR_STACK_LIMIT_EXCEEDED:
return ToASCIIString("CBOR: stack limit exceeded");
return "CBOR: stack limit exceeded";
case Error::CBOR_TRAILING_JUNK:
return ToASCIIString("CBOR: trailing junk");
return "CBOR: trailing junk";
case Error::CBOR_MAP_START_EXPECTED:
return ToASCIIString("CBOR: map start expected");
return "CBOR: map start expected";
case Error::CBOR_MAP_STOP_EXPECTED:
return ToASCIIString("CBOR: map stop expected");
return "CBOR: map stop expected";
case Error::CBOR_ARRAY_START_EXPECTED:
return ToASCIIString("CBOR: array start expected");
return "CBOR: array start expected";
case Error::CBOR_ENVELOPE_SIZE_LIMIT_EXCEEDED:
return ToASCIIString("CBOR: envelope size limit exceeded");
return "CBOR: envelope size limit exceeded";
case Error::MESSAGE_MUST_BE_AN_OBJECT:
return "Message must be an object";
case Error::MESSAGE_MUST_HAVE_INTEGER_ID_PROPERTY:
return "Message must have integer 'id' property";
case Error::MESSAGE_MUST_HAVE_STRING_METHOD_PROPERTY:
return "Message must have string 'method' property";
case Error::MESSAGE_MAY_HAVE_STRING_SESSION_ID_PROPERTY:
return "Message may have string 'sessionId' property";
case Error::MESSAGE_MAY_HAVE_OBJECT_PARAMS_PROPERTY:
return "Message may have object 'params' property";
case Error::MESSAGE_HAS_UNKNOWN_PROPERTY:
return "Message has property other than "
"'id', 'method', 'sessionId', 'params'";
case Error::BINDINGS_MANDATORY_FIELD_MISSING:
return ToASCIIString("BINDINGS: mandatory field missing");
return "BINDINGS: mandatory field missing";
case Error::BINDINGS_BOOL_VALUE_EXPECTED:
return ToASCIIString("BINDINGS: bool value expected");
return "BINDINGS: bool value expected";
case Error::BINDINGS_INT32_VALUE_EXPECTED:
return ToASCIIString("BINDINGS: int32 value expected");
return "BINDINGS: int32 value expected";
case Error::BINDINGS_DOUBLE_VALUE_EXPECTED:
return ToASCIIString("BINDINGS: double value expected");
return "BINDINGS: double value expected";
case Error::BINDINGS_STRING_VALUE_EXPECTED:
return ToASCIIString("BINDINGS: string value expected");
return "BINDINGS: string value expected";
case Error::BINDINGS_STRING8_VALUE_EXPECTED:
return ToASCIIString("BINDINGS: string8 value expected");
return "BINDINGS: string8 value expected";
case Error::BINDINGS_BINARY_VALUE_EXPECTED:
return ToASCIIString("BINDINGS: binary value expected");
return "BINDINGS: binary value expected";
}
// Some compilers can't figure out that we can't get here.
return "INVALID ERROR CODE";
}
std::string Status::ToASCIIString(const char* msg) const {
return std::string(msg) + " at position " + std::to_string(pos);
std::string Status::ToASCIIString() const {
if (ok())
return "OK";
return Message() + " at position " + std::to_string(pos);
}
} // namespace v8_crdtp
......@@ -18,7 +18,9 @@ namespace v8_crdtp {
enum class Error {
OK = 0,
// JSON parsing errors - json_parser.{h,cc}.
// JSON parsing errors; checked when parsing / converting from JSON.
// See json.{h,cc}.
JSON_PARSER_UNPROCESSED_INPUT_REMAINS = 0x01,
JSON_PARSER_STACK_LIMIT_EXCEEDED = 0x02,
JSON_PARSER_NO_INPUT = 0x03,
......@@ -33,6 +35,7 @@ enum class Error {
JSON_PARSER_COMMA_OR_MAP_END_EXPECTED = 0x0c,
JSON_PARSER_VALUE_EXPECTED = 0x0d,
// CBOR parsing errors; checked when parsing / converting from CBOR.
CBOR_INVALID_INT32 = 0x0e,
CBOR_INVALID_DOUBLE = 0x0f,
CBOR_INVALID_ENVELOPE = 0x10,
......@@ -48,20 +51,31 @@ enum class Error {
CBOR_UNEXPECTED_EOF_IN_ARRAY = 0x1a,
CBOR_UNEXPECTED_EOF_IN_MAP = 0x1b,
CBOR_INVALID_MAP_KEY = 0x1c,
CBOR_STACK_LIMIT_EXCEEDED = 0x1d,
CBOR_TRAILING_JUNK = 0x1e,
CBOR_MAP_START_EXPECTED = 0x1f,
CBOR_MAP_STOP_EXPECTED = 0x20,
CBOR_ARRAY_START_EXPECTED = 0x21,
CBOR_ENVELOPE_SIZE_LIMIT_EXCEEDED = 0x22,
BINDINGS_MANDATORY_FIELD_MISSING = 0x23,
BINDINGS_BOOL_VALUE_EXPECTED = 0x24,
BINDINGS_INT32_VALUE_EXPECTED = 0x25,
BINDINGS_DOUBLE_VALUE_EXPECTED = 0x26,
BINDINGS_STRING_VALUE_EXPECTED = 0x27,
BINDINGS_STRING8_VALUE_EXPECTED = 0x28,
BINDINGS_BINARY_VALUE_EXPECTED = 0x29,
CBOR_DUPLICATE_MAP_KEY = 0x1d,
CBOR_STACK_LIMIT_EXCEEDED = 0x1e,
CBOR_TRAILING_JUNK = 0x1f,
CBOR_MAP_START_EXPECTED = 0x20,
CBOR_MAP_STOP_EXPECTED = 0x21,
CBOR_ARRAY_START_EXPECTED = 0x22,
CBOR_ENVELOPE_SIZE_LIMIT_EXCEEDED = 0x23,
// Message errors are constraints we place on protocol messages coming
// from a protocol client; these are checked in crdtp::Dispatchable
// (see dispatch.h) as it performs a shallow parse.
MESSAGE_MUST_BE_AN_OBJECT = 0x24,
MESSAGE_MUST_HAVE_INTEGER_ID_PROPERTY = 0x25,
MESSAGE_MUST_HAVE_STRING_METHOD_PROPERTY = 0x26,
MESSAGE_MAY_HAVE_STRING_SESSION_ID_PROPERTY = 0x27,
MESSAGE_MAY_HAVE_OBJECT_PARAMS_PROPERTY = 0x28,
MESSAGE_HAS_UNKNOWN_PROPERTY = 0x29,
BINDINGS_MANDATORY_FIELD_MISSING = 0x30,
BINDINGS_BOOL_VALUE_EXPECTED = 0x31,
BINDINGS_INT32_VALUE_EXPECTED = 0x32,
BINDINGS_DOUBLE_VALUE_EXPECTED = 0x33,
BINDINGS_STRING_VALUE_EXPECTED = 0x34,
BINDINGS_STRING8_VALUE_EXPECTED = 0x35,
BINDINGS_BINARY_VALUE_EXPECTED = 0x36,
};
// A status value with position that can be copied. The default status
......@@ -76,12 +90,18 @@ struct Status {
Status(Error error, size_t pos) : error(error), pos(pos) {}
Status() = default;
// Returns a 7 bit US-ASCII string, either "OK" or an error message
// that includes the position.
std::string ToASCIIString() const;
bool IsMessageError() const {
return error >= Error::MESSAGE_MUST_BE_AN_OBJECT &&
error <= Error::MESSAGE_HAS_UNKNOWN_PROPERTY;
}
// Returns 7 bit US-ASCII string, either "OK" or an error message without
// position.
std::string Message() const;
private:
std::string ToASCIIString(const char* msg) const;
// Returns a 7 bit US-ASCII string, either "OK" or an error message that
// includes the position.
std::string ToASCIIString() const;
};
} // namespace v8_crdtp
......
......@@ -33,10 +33,7 @@ template("inspector_protocol_generate") {
invoker.config_file,
"$inspector_protocol_dir/lib/base_string_adapter_cc.template",
"$inspector_protocol_dir/lib/base_string_adapter_h.template",
"$inspector_protocol_dir/lib/DispatcherBase_cpp.template",
"$inspector_protocol_dir/lib/DispatcherBase_h.template",
"$inspector_protocol_dir/lib/Forward_h.template",
"$inspector_protocol_dir/lib/FrontendChannel_h.template",
"$inspector_protocol_dir/lib/Object_cpp.template",
"$inspector_protocol_dir/lib/Object_h.template",
"$inspector_protocol_dir/lib/Protocol_cpp.template",
......@@ -56,6 +53,7 @@ template("inspector_protocol_generate") {
"--jinja_dir",
rebase_path("//third_party/", root_build_dir), # jinja is in chromium's
# third_party
"--output_base",
rebase_path(invoker.out_dir, root_build_dir),
"--config",
......
// This file is generated by DispatcherBase_h.template.
// Copyright 2016 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 {{"_".join(config.protocol.namespace)}}_DispatcherBase_h
#define {{"_".join(config.protocol.namespace)}}_DispatcherBase_h
//#include "Forward.h"
//#include "ErrorSupport.h"
//#include "Values.h"
#include "{{config.crdtp.dir}}/span.h"
{% for namespace in config.protocol.namespace %}
namespace {{namespace}} {
{% endfor %}
class WeakPtr;
class {{config.lib.export_macro}} DispatchResponse {
public:
enum Status {
kSuccess = 0,
kError = 1,
kFallThrough = 2,
};
// For historical reasons, these error codes correspond to commonly used
// XMLRPC codes (e.g. see METHOD_NOT_FOUND in
// https://github.com/python/cpython/blob/master/Lib/xmlrpc/client.py).
enum ErrorCode {
kParseError = -32700,
kInvalidRequest = -32600,
kMethodNotFound = -32601,
kInvalidParams = -32602,
kInternalError = -32603,
kServerError = -32000,
};
Status status() const { return m_status; }
const String& errorMessage() const { return m_errorMessage; }
ErrorCode errorCode() const { return m_errorCode; }
bool isSuccess() const { return m_status == kSuccess; }
static DispatchResponse OK();
static DispatchResponse Error(const String&);
static DispatchResponse InternalError();
static DispatchResponse InvalidParams(const String&);
static DispatchResponse FallThrough();
private:
Status m_status;
String m_errorMessage;
ErrorCode m_errorCode;
};
class {{config.lib.export_macro}} DispatcherBase {
PROTOCOL_DISALLOW_COPY(DispatcherBase);
public:
static const char kInvalidParamsString[];
class {{config.lib.export_macro}} WeakPtr {
public:
explicit WeakPtr(DispatcherBase*);
~WeakPtr();
DispatcherBase* get() { return m_dispatcher; }
void dispose() { m_dispatcher = nullptr; }
private:
DispatcherBase* m_dispatcher;
};
class {{config.lib.export_macro}} Callback {
public:
Callback(std::unique_ptr<WeakPtr> backendImpl, int callId, const String& method, {{config.crdtp.namespace}}::span<uint8_t> message);
virtual ~Callback();
void dispose();
protected:
void sendIfActive(std::unique_ptr<protocol::DictionaryValue> partialMessage, const DispatchResponse& response);
void fallThroughIfActive();
private:
std::unique_ptr<WeakPtr> m_backendImpl;
int m_callId;
String m_method;
std::vector<uint8_t> m_message;
};
explicit DispatcherBase(FrontendChannel*);
virtual ~DispatcherBase();
virtual bool canDispatch(const String& method) = 0;
virtual void dispatch(int callId, const String& method, {{config.crdtp.namespace}}::span<uint8_t> rawMessage, std::unique_ptr<protocol::DictionaryValue> messageObject) = 0;
FrontendChannel* channel() { return m_frontendChannel; }
void sendResponse(int callId, const DispatchResponse&, std::unique_ptr<protocol::DictionaryValue> result);
void sendResponse(int callId, const DispatchResponse&);
void reportProtocolError(int callId, DispatchResponse::ErrorCode, const String& errorMessage, ErrorSupport* errors);
void clearFrontend();
std::unique_ptr<WeakPtr> weakPtr();
private:
FrontendChannel* m_frontendChannel;
std::unordered_set<WeakPtr*> m_weakPtrs;
};
class {{config.lib.export_macro}} UberDispatcher {
PROTOCOL_DISALLOW_COPY(UberDispatcher);
public:
explicit UberDispatcher(FrontendChannel*);
void registerBackend(const String& name, std::unique_ptr<protocol::DispatcherBase>);
void setupRedirects(const std::unordered_map<String, String>&);
bool parseCommand(Value* message, int* callId, String* method);
bool canDispatch(const String& method);
void dispatch(int callId, const String& method, std::unique_ptr<Value> message, {{config.crdtp.namespace}}::span<uint8_t> rawMessage);
FrontendChannel* channel() { return m_frontendChannel; }
virtual ~UberDispatcher();
private:
protocol::DispatcherBase* findDispatcher(const String& method);
FrontendChannel* m_frontendChannel;
std::unordered_map<String, String> m_redirects;
std::unordered_map<String, std::unique_ptr<protocol::DispatcherBase>> m_dispatchers;
};
class InternalResponse : public Serializable {
PROTOCOL_DISALLOW_COPY(InternalResponse);
public:
static std::unique_ptr<Serializable> createResponse(int callId, std::unique_ptr<Serializable> params);
static std::unique_ptr<Serializable> createNotification(const char* method, std::unique_ptr<Serializable> params = nullptr);
static std::unique_ptr<Serializable> createErrorResponse(int callId, DispatchResponse::ErrorCode code, const String& message);
void AppendSerialized(std::vector<uint8_t>* out) const override;
~InternalResponse() override {}
private:
InternalResponse(int callId, const char* method, std::unique_ptr<Serializable> params);
int m_callId;
const char* m_method = nullptr;
std::unique_ptr<Serializable> m_params;
};
{% for namespace in config.protocol.namespace %}
} // namespace {{namespace}}
{% endfor %}
#endif // !defined({{"_".join(config.protocol.namespace)}}_DispatcherBase_h)
......@@ -19,6 +19,8 @@
#include <unordered_set>
#include "{{config.crdtp.dir}}/error_support.h"
#include "{{config.crdtp.dir}}/dispatch.h"
#include "{{config.crdtp.dir}}/frontend_channel.h"
#include "{{config.crdtp.dir}}/glue.h"
{% for namespace in config.protocol.namespace %}
......@@ -26,15 +28,18 @@ namespace {{namespace}} {
{% endfor %}
class DictionaryValue;
class DispatchResponse;
using DispatchResponse = {{config.crdtp.namespace}}::DispatchResponse;
using ErrorSupport = {{config.crdtp.namespace}}::ErrorSupport;
using Serializable = {{config.crdtp.namespace}}::Serializable;
using FrontendChannel = {{config.crdtp.namespace}}::FrontendChannel;
using DomainDispatcher = {{config.crdtp.namespace}}::DomainDispatcher;
using UberDispatcher = {{config.crdtp.namespace}}::UberDispatcher;
class FundamentalValue;
class ListValue;
class Object;
using Response = DispatchResponse;
class SerializedValue;
class StringValue;
class UberDispatcher;
class Value;
namespace detail {
......
// This file is generated by FrontendChannel_h.template.
// Copyright 2016 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 {{"_".join(config.protocol.namespace)}}_FrontendChannel_h
#define {{"_".join(config.protocol.namespace)}}_FrontendChannel_h
#include "{{config.crdtp.dir}}/serializable.h"
#include "{{config.crdtp.dir}}/span.h"
{% for namespace in config.protocol.namespace %}
namespace {{namespace}} {
{% endfor %}
using {{config.crdtp.namespace}}::Serializable;
class {{config.lib.export_macro}} FrontendChannel {
public:
virtual ~FrontendChannel() { }
virtual void sendProtocolResponse(int callId, std::unique_ptr<Serializable> message) = 0;
virtual void sendProtocolNotification(std::unique_ptr<Serializable> message) = 0;
virtual void fallThrough(int callId, const String& method, {{config.crdtp.namespace}}::span<uint8_t> message) = 0;
virtual void flushProtocolNotifications() = 0;
};
{% for namespace in config.protocol.namespace %}
} // namespace {{namespace}}
{% endfor %}
#endif // !defined({{"_".join(config.protocol.namespace)}}_FrontendChannel_h)
......@@ -34,17 +34,6 @@ using String = std::string;
class {{config.lib.export_macro}} StringUtil {
public:
static String substring(const String& s, unsigned pos, unsigned len) {
return s.substr(pos, len);
}
static size_t find(const String& s, const char* needle) {
return s.find(needle);
}
static size_t find(const String& s, const String& needle) {
return s.find(needle);
}
static const size_t kNotFound = static_cast<size_t>(-1);
static String fromUTF8(const uint8_t* data, size_t length) {
return std::string(reinterpret_cast<const char*>(data), length);
}
......
This diff is collapsed.
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