Commit d7f82c11 authored by kozyatinskiy's avatar kozyatinskiy Committed by Commit bot

[inspector] migrate Runtime to new style

BUG=none
R=dgozman@chromium.org
CQ_INCLUDE_TRYBOTS=master.tryserver.blink:linux_precise_blink_rel

Review-Url: https://codereview.chromium.org/2467853003
Cr-Commit-Position: refs/heads/master@{#40744}
parent 5df5a28f
......@@ -259,18 +259,6 @@ InjectedScript.prototype = {
}
},
/**
* @param {!Array<*>} array
* @param {string} groupName
* @param {boolean} forceValueType
* @param {boolean} generatePreview
*/
wrapObjectsInArray: function(array, groupName, forceValueType, generatePreview)
{
for (var i = 0; i < array.length; ++i)
array[i] = this.wrapObject(array[i], groupName, forceValueType, generatePreview);
},
/**
* @param {!Object} table
* @param {!Array.<string>|string|boolean} columns
......
......@@ -54,11 +54,6 @@ using protocol::Runtime::InternalPropertyDescriptor;
using protocol::Runtime::RemoteObject;
using protocol::Maybe;
static bool hasInternalError(ErrorString* errorString, bool hasError) {
if (hasError) *errorString = "Internal error";
return hasError;
}
std::unique_ptr<InjectedScript> InjectedScript::create(
InspectedContext* inspectedContext) {
v8::Isolate* isolate = inspectedContext->isolate();
......@@ -124,10 +119,9 @@ InjectedScript::InjectedScript(
InjectedScript::~InjectedScript() {}
void InjectedScript::getProperties(
ErrorString* errorString, v8::Local<v8::Object> object,
const String16& groupName, bool ownProperties, bool accessorPropertiesOnly,
bool generatePreview,
Response InjectedScript::getProperties(
v8::Local<v8::Object> object, const String16& groupName, bool ownProperties,
bool accessorPropertiesOnly, bool generatePreview,
std::unique_ptr<Array<PropertyDescriptor>>* properties,
Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) {
v8::HandleScope handles(m_context->isolate());
......@@ -143,21 +137,23 @@ void InjectedScript::getProperties(
v8::TryCatch tryCatch(m_context->isolate());
v8::Local<v8::Value> resultValue = function.callWithoutExceptionHandling();
if (tryCatch.HasCaught()) {
*exceptionDetails = createExceptionDetails(errorString, tryCatch, groupName,
generatePreview);
Response response = createExceptionDetails(
tryCatch, groupName, generatePreview, exceptionDetails);
if (!response.isSuccess()) return response;
// FIXME: make properties optional
*properties = Array<PropertyDescriptor>::create();
return;
return Response::OK();
}
if (hasInternalError(errorString, resultValue.IsEmpty())) return;
std::unique_ptr<protocol::Value> protocolValue =
toProtocolValue(errorString, context, resultValue);
if (!protocolValue) return;
protocol::ErrorSupport errors(errorString);
if (resultValue.IsEmpty()) return Response::InternalError();
std::unique_ptr<protocol::Value> protocolValue;
Response response = toProtocolValue(context, resultValue, &protocolValue);
if (!response.isSuccess()) return response;
protocol::ErrorSupport errors;
std::unique_ptr<Array<PropertyDescriptor>> result =
Array<PropertyDescriptor>::parse(protocolValue.get(), &errors);
if (!hasInternalError(errorString, errors.hasErrors()))
*properties = std::move(result);
if (errors.hasErrors()) return Response::Error(errors.errors());
*properties = std::move(result);
return Response::OK();
}
void InjectedScript::releaseObject(const String16& objectId) {
......@@ -172,55 +168,52 @@ void InjectedScript::releaseObject(const String16& objectId) {
m_native->unbind(boundId);
}
std::unique_ptr<protocol::Runtime::RemoteObject> InjectedScript::wrapObject(
ErrorString* errorString, v8::Local<v8::Value> value,
const String16& groupName, bool forceValueType,
bool generatePreview) const {
Response InjectedScript::wrapObject(
v8::Local<v8::Value> value, const String16& groupName, bool forceValueType,
bool generatePreview,
std::unique_ptr<protocol::Runtime::RemoteObject>* result) const {
v8::HandleScope handles(m_context->isolate());
v8::Local<v8::Value> wrappedObject;
v8::Local<v8::Context> context = m_context->context();
if (!wrapValue(errorString, value, groupName, forceValueType, generatePreview)
.ToLocal(&wrappedObject))
return nullptr;
Response response = wrapValue(value, groupName, forceValueType,
generatePreview, &wrappedObject);
if (!response.isSuccess()) return response;
protocol::ErrorSupport errors;
std::unique_ptr<protocol::Value> protocolValue =
toProtocolValue(errorString, context, wrappedObject);
if (!protocolValue) return nullptr;
std::unique_ptr<protocol::Runtime::RemoteObject> remoteObject =
std::unique_ptr<protocol::Value> protocolValue;
response = toProtocolValue(context, wrappedObject, &protocolValue);
if (!response.isSuccess()) return response;
*result =
protocol::Runtime::RemoteObject::parse(protocolValue.get(), &errors);
if (!remoteObject) *errorString = errors.errors();
return remoteObject;
if (!result->get()) return Response::Error(errors.errors());
return Response::OK();
}
bool InjectedScript::wrapObjectProperty(ErrorString* errorString,
v8::Local<v8::Object> object,
v8::Local<v8::Name> key,
const String16& groupName,
bool forceValueType,
bool generatePreview) const {
Response InjectedScript::wrapObjectProperty(v8::Local<v8::Object> object,
v8::Local<v8::Name> key,
const String16& groupName,
bool forceValueType,
bool generatePreview) const {
v8::Local<v8::Value> property;
v8::Local<v8::Context> context = m_context->context();
if (hasInternalError(errorString,
!object->Get(context, key).ToLocal(&property)))
return false;
if (!object->Get(context, key).ToLocal(&property))
return Response::InternalError();
v8::Local<v8::Value> wrappedProperty;
if (!wrapValue(errorString, property, groupName, forceValueType,
generatePreview)
.ToLocal(&wrappedProperty))
return false;
Response response = wrapValue(property, groupName, forceValueType,
generatePreview, &wrappedProperty);
if (!response.isSuccess()) return response;
v8::Maybe<bool> success =
createDataProperty(context, object, key, wrappedProperty);
if (hasInternalError(errorString, success.IsNothing() || !success.FromJust()))
return false;
return true;
if (success.IsNothing() || !success.FromJust())
return Response::InternalError();
return Response::OK();
}
bool InjectedScript::wrapPropertyInArray(ErrorString* errorString,
v8::Local<v8::Array> array,
v8::Local<v8::String> property,
const String16& groupName,
bool forceValueType,
bool generatePreview) const {
Response InjectedScript::wrapPropertyInArray(v8::Local<v8::Array> array,
v8::Local<v8::String> property,
const String16& groupName,
bool forceValueType,
bool generatePreview) const {
V8FunctionCall function(m_context->inspector(), m_context->context(),
v8Value(), "wrapPropertyInArray");
function.appendArgument(array);
......@@ -230,29 +223,13 @@ bool InjectedScript::wrapPropertyInArray(ErrorString* errorString,
function.appendArgument(generatePreview);
bool hadException = false;
function.call(hadException);
return !hasInternalError(errorString, hadException);
return hadException ? Response::InternalError() : Response::OK();
}
bool InjectedScript::wrapObjectsInArray(ErrorString* errorString,
v8::Local<v8::Array> array,
const String16& groupName,
bool forceValueType,
bool generatePreview) const {
V8FunctionCall function(m_context->inspector(), m_context->context(),
v8Value(), "wrapObjectsInArray");
function.appendArgument(array);
function.appendArgument(groupName);
function.appendArgument(forceValueType);
function.appendArgument(generatePreview);
bool hadException = false;
function.call(hadException);
return !hasInternalError(errorString, hadException);
}
v8::MaybeLocal<v8::Value> InjectedScript::wrapValue(
ErrorString* errorString, v8::Local<v8::Value> value,
const String16& groupName, bool forceValueType,
bool generatePreview) const {
Response InjectedScript::wrapValue(v8::Local<v8::Value> value,
const String16& groupName,
bool forceValueType, bool generatePreview,
v8::Local<v8::Value>* result) const {
V8FunctionCall function(m_context->inspector(), m_context->context(),
v8Value(), "wrapObject");
function.appendArgument(value);
......@@ -260,10 +237,9 @@ v8::MaybeLocal<v8::Value> InjectedScript::wrapValue(
function.appendArgument(forceValueType);
function.appendArgument(generatePreview);
bool hadException = false;
v8::Local<v8::Value> r = function.call(hadException);
if (hasInternalError(errorString, hadException || r.IsEmpty()))
return v8::MaybeLocal<v8::Value>();
return r;
*result = function.call(hadException);
if (hadException || result->IsEmpty()) return Response::InternalError();
return Response::OK();
}
std::unique_ptr<protocol::Runtime::RemoteObject> InjectedScript::wrapTable(
......@@ -280,21 +256,19 @@ std::unique_ptr<protocol::Runtime::RemoteObject> InjectedScript::wrapTable(
bool hadException = false;
v8::Local<v8::Value> r = function.call(hadException);
if (hadException || r.IsEmpty()) return nullptr;
protocol::ErrorString errorString;
std::unique_ptr<protocol::Value> protocolValue =
toProtocolValue(&errorString, context, r);
if (!protocolValue) return nullptr;
std::unique_ptr<protocol::Value> protocolValue;
Response response = toProtocolValue(context, r, &protocolValue);
if (!response.isSuccess()) return nullptr;
protocol::ErrorSupport errors;
return protocol::Runtime::RemoteObject::parse(protocolValue.get(), &errors);
}
bool InjectedScript::findObject(ErrorString* errorString,
const RemoteObjectId& objectId,
v8::Local<v8::Value>* outObject) const {
Response InjectedScript::findObject(const RemoteObjectId& objectId,
v8::Local<v8::Value>* outObject) const {
*outObject = m_native->objectForId(objectId.id());
if (outObject->IsEmpty())
*errorString = "Could not find object with given id";
return !outObject->IsEmpty();
return Response::Error("Could not find object with given id");
return Response::OK();
}
String16 InjectedScript::objectGroupName(const RemoteObjectId& objectId) const {
......@@ -326,47 +300,41 @@ v8::Local<v8::Value> InjectedScript::lastEvaluationResult() const {
return m_lastEvaluationResult.Get(m_context->isolate());
}
v8::MaybeLocal<v8::Value> InjectedScript::resolveCallArgument(
ErrorString* errorString, protocol::Runtime::CallArgument* callArgument) {
Response InjectedScript::resolveCallArgument(
protocol::Runtime::CallArgument* callArgument,
v8::Local<v8::Value>* result) {
if (callArgument->hasObjectId()) {
std::unique_ptr<RemoteObjectId> remoteObjectId =
RemoteObjectId::parse(errorString, callArgument->getObjectId(""));
if (!remoteObjectId) return v8::MaybeLocal<v8::Value>();
if (remoteObjectId->contextId() != m_context->contextId()) {
*errorString =
std::unique_ptr<RemoteObjectId> remoteObjectId;
Response response =
RemoteObjectId::parse(callArgument->getObjectId(""), &remoteObjectId);
if (!response.isSuccess()) return response;
if (remoteObjectId->contextId() != m_context->contextId())
return Response::Error(
"Argument should belong to the same JavaScript world as target "
"object";
return v8::MaybeLocal<v8::Value>();
}
v8::Local<v8::Value> object;
if (!findObject(errorString, *remoteObjectId, &object))
return v8::MaybeLocal<v8::Value>();
return object;
"object");
return findObject(*remoteObjectId, result);
}
if (callArgument->hasValue() || callArgument->hasUnserializableValue()) {
String16 value =
callArgument->hasValue()
? callArgument->getValue(nullptr)->toJSONString()
: "Number(\"" + callArgument->getUnserializableValue("") + "\")";
v8::Local<v8::Value> object;
if (!m_context->inspector()
->compileAndRunInternalScript(
m_context->context(), toV8String(m_context->isolate(), value))
.ToLocal(&object)) {
*errorString = "Couldn't parse value object in call argument";
return v8::MaybeLocal<v8::Value>();
.ToLocal(result)) {
return Response::Error("Couldn't parse value object in call argument");
}
return object;
return Response::OK();
}
return v8::Undefined(m_context->isolate());
*result = v8::Undefined(m_context->isolate());
return Response::OK();
}
std::unique_ptr<protocol::Runtime::ExceptionDetails>
InjectedScript::createExceptionDetails(ErrorString* errorString,
const v8::TryCatch& tryCatch,
const String16& objectGroup,
bool generatePreview) {
if (!tryCatch.HasCaught()) return nullptr;
Response InjectedScript::createExceptionDetails(
const v8::TryCatch& tryCatch, const String16& objectGroup,
bool generatePreview, Maybe<protocol::Runtime::ExceptionDetails>* result) {
if (!tryCatch.HasCaught()) return Response::InternalError();
v8::Local<v8::Message> message = tryCatch.Message();
v8::Local<v8::Value> exception = tryCatch.Exception();
String16 messageText =
......@@ -396,43 +364,44 @@ InjectedScript::createExceptionDetails(ErrorString* errorString,
->buildInspectorObjectImpl());
}
if (!exception.IsEmpty()) {
std::unique_ptr<protocol::Runtime::RemoteObject> wrapped = wrapObject(
errorString, exception, objectGroup, false /* forceValueType */,
generatePreview && !exception->IsNativeError());
if (!wrapped) return nullptr;
std::unique_ptr<protocol::Runtime::RemoteObject> wrapped;
Response response =
wrapObject(exception, objectGroup, false /* forceValueType */,
generatePreview && !exception->IsNativeError(), &wrapped);
if (!response.isSuccess()) return response;
exceptionDetails->setException(std::move(wrapped));
}
return exceptionDetails;
*result = std::move(exceptionDetails);
return Response::OK();
}
void InjectedScript::wrapEvaluateResult(
ErrorString* errorString, v8::MaybeLocal<v8::Value> maybeResultValue,
const v8::TryCatch& tryCatch, const String16& objectGroup,
bool returnByValue, bool generatePreview,
Response InjectedScript::wrapEvaluateResult(
v8::MaybeLocal<v8::Value> maybeResultValue, const v8::TryCatch& tryCatch,
const String16& objectGroup, bool returnByValue, bool generatePreview,
std::unique_ptr<protocol::Runtime::RemoteObject>* result,
Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) {
v8::Local<v8::Value> resultValue;
if (!tryCatch.HasCaught()) {
if (hasInternalError(errorString, !maybeResultValue.ToLocal(&resultValue)))
return;
std::unique_ptr<RemoteObject> remoteObject = wrapObject(
errorString, resultValue, objectGroup, returnByValue, generatePreview);
if (!remoteObject) return;
if (!maybeResultValue.ToLocal(&resultValue))
return Response::InternalError();
Response response = wrapObject(resultValue, objectGroup, returnByValue,
generatePreview, result);
if (!response.isSuccess()) return response;
if (objectGroup == "console")
m_lastEvaluationResult.Reset(m_context->isolate(), resultValue);
*result = std::move(remoteObject);
} else {
v8::Local<v8::Value> exception = tryCatch.Exception();
std::unique_ptr<RemoteObject> remoteObject =
wrapObject(errorString, exception, objectGroup, false,
generatePreview && !exception->IsNativeError());
if (!remoteObject) return;
Response response =
wrapObject(exception, objectGroup, false,
generatePreview && !exception->IsNativeError(), result);
if (!response.isSuccess()) return response;
// We send exception in result for compatibility reasons, even though it's
// accessible through exceptionDetails.exception.
*result = std::move(remoteObject);
*exceptionDetails = createExceptionDetails(errorString, tryCatch,
objectGroup, generatePreview);
response = createExceptionDetails(tryCatch, objectGroup, generatePreview,
exceptionDetails);
if (!response.isSuccess()) return response;
}
return Response::OK();
}
v8::Local<v8::Object> InjectedScript::commandLineAPI() {
......@@ -442,10 +411,8 @@ v8::Local<v8::Object> InjectedScript::commandLineAPI() {
return m_commandLineAPI.Get(m_context->isolate());
}
InjectedScript::Scope::Scope(ErrorString* errorString,
V8InspectorImpl* inspector, int contextGroupId)
: m_errorString(errorString),
m_inspector(inspector),
InjectedScript::Scope::Scope(V8InspectorImpl* inspector, int contextGroupId)
: m_inspector(inspector),
m_contextGroupId(contextGroupId),
m_injectedScript(nullptr),
m_handleScope(inspector->isolate()),
......@@ -454,29 +421,25 @@ InjectedScript::Scope::Scope(ErrorString* errorString,
m_previousPauseOnExceptionsState(v8::DebugInterface::NoBreakOnException),
m_userGesture(false) {}
bool InjectedScript::Scope::initialize() {
Response InjectedScript::Scope::initialize() {
cleanup();
// TODO(dgozman): what if we reattach to the same context group during
// evaluate? Introduce a session id?
V8InspectorSessionImpl* session =
m_inspector->sessionForContextGroup(m_contextGroupId);
if (!session) {
*m_errorString = "Internal error";
return false;
}
findInjectedScript(session);
if (!m_injectedScript) return false;
if (!session) return Response::InternalError();
Response response = findInjectedScript(session);
if (!response.isSuccess()) return response;
m_context = m_injectedScript->context()->context();
m_context->Enter();
return true;
return Response::OK();
}
bool InjectedScript::Scope::installCommandLineAPI() {
void InjectedScript::Scope::installCommandLineAPI() {
DCHECK(m_injectedScript && !m_context.IsEmpty() &&
!m_commandLineAPIScope.get());
m_commandLineAPIScope.reset(new V8Console::CommandLineAPIScope(
m_context, m_injectedScript->commandLineAPI(), m_context->Global()));
return true;
}
void InjectedScript::Scope::ignoreExceptionsAndMuteConsole() {
......@@ -523,59 +486,57 @@ InjectedScript::Scope::~Scope() {
cleanup();
}
InjectedScript::ContextScope::ContextScope(ErrorString* errorString,
V8InspectorImpl* inspector,
InjectedScript::ContextScope::ContextScope(V8InspectorImpl* inspector,
int contextGroupId,
int executionContextId)
: InjectedScript::Scope(errorString, inspector, contextGroupId),
: InjectedScript::Scope(inspector, contextGroupId),
m_executionContextId(executionContextId) {}
InjectedScript::ContextScope::~ContextScope() {}
void InjectedScript::ContextScope::findInjectedScript(
Response InjectedScript::ContextScope::findInjectedScript(
V8InspectorSessionImpl* session) {
m_injectedScript =
session->findInjectedScript(m_errorString, m_executionContextId);
return session->findInjectedScript(m_executionContextId, m_injectedScript);
}
InjectedScript::ObjectScope::ObjectScope(ErrorString* errorString,
V8InspectorImpl* inspector,
InjectedScript::ObjectScope::ObjectScope(V8InspectorImpl* inspector,
int contextGroupId,
const String16& remoteObjectId)
: InjectedScript::Scope(errorString, inspector, contextGroupId),
: InjectedScript::Scope(inspector, contextGroupId),
m_remoteObjectId(remoteObjectId) {}
InjectedScript::ObjectScope::~ObjectScope() {}
void InjectedScript::ObjectScope::findInjectedScript(
Response InjectedScript::ObjectScope::findInjectedScript(
V8InspectorSessionImpl* session) {
std::unique_ptr<RemoteObjectId> remoteId =
RemoteObjectId::parse(m_errorString, m_remoteObjectId);
if (!remoteId) return;
InjectedScript* injectedScript =
session->findInjectedScript(m_errorString, remoteId.get());
if (!injectedScript) return;
std::unique_ptr<RemoteObjectId> remoteId;
Response response = RemoteObjectId::parse(m_remoteObjectId, &remoteId);
if (!response.isSuccess()) return response;
InjectedScript* injectedScript = nullptr;
response = session->findInjectedScript(remoteId.get(), injectedScript);
if (!response.isSuccess()) return response;
m_objectGroupName = injectedScript->objectGroupName(*remoteId);
if (!injectedScript->findObject(m_errorString, *remoteId, &m_object)) return;
response = injectedScript->findObject(*remoteId, &m_object);
if (!response.isSuccess()) return response;
m_injectedScript = injectedScript;
return Response::OK();
}
InjectedScript::CallFrameScope::CallFrameScope(ErrorString* errorString,
V8InspectorImpl* inspector,
InjectedScript::CallFrameScope::CallFrameScope(V8InspectorImpl* inspector,
int contextGroupId,
const String16& remoteObjectId)
: InjectedScript::Scope(errorString, inspector, contextGroupId),
: InjectedScript::Scope(inspector, contextGroupId),
m_remoteCallFrameId(remoteObjectId) {}
InjectedScript::CallFrameScope::~CallFrameScope() {}
void InjectedScript::CallFrameScope::findInjectedScript(
Response InjectedScript::CallFrameScope::findInjectedScript(
V8InspectorSessionImpl* session) {
std::unique_ptr<RemoteCallFrameId> remoteId =
RemoteCallFrameId::parse(m_errorString, m_remoteCallFrameId);
if (!remoteId) return;
std::unique_ptr<RemoteCallFrameId> remoteId;
Response response = RemoteCallFrameId::parse(m_remoteCallFrameId, &remoteId);
if (!response.isSuccess()) return response;
m_frameOrdinal = static_cast<size_t>(remoteId->frameOrdinal());
m_injectedScript = session->findInjectedScript(m_errorString, remoteId.get());
return session->findInjectedScript(remoteId.get(), m_injectedScript);
}
} // namespace v8_inspector
......@@ -48,8 +48,8 @@ class V8FunctionCall;
class V8InspectorImpl;
class V8InspectorSessionImpl;
using protocol::ErrorString;
using protocol::Maybe;
using protocol::Response;
class InjectedScript final {
public:
......@@ -58,56 +58,51 @@ class InjectedScript final {
InspectedContext* context() const { return m_context; }
void getProperties(
ErrorString*, v8::Local<v8::Object>, const String16& groupName,
bool ownProperties, bool accessorPropertiesOnly, bool generatePreview,
Response getProperties(
v8::Local<v8::Object>, const String16& groupName, bool ownProperties,
bool accessorPropertiesOnly, bool generatePreview,
std::unique_ptr<protocol::Array<protocol::Runtime::PropertyDescriptor>>*
result,
Maybe<protocol::Runtime::ExceptionDetails>*);
void releaseObject(const String16& objectId);
std::unique_ptr<protocol::Runtime::RemoteObject> wrapObject(
ErrorString*, v8::Local<v8::Value>, const String16& groupName,
bool forceValueType = false, bool generatePreview = false) const;
bool wrapObjectProperty(ErrorString*, v8::Local<v8::Object>,
v8::Local<v8::Name> key, const String16& groupName,
bool forceValueType = false,
bool generatePreview = false) const;
bool wrapPropertyInArray(ErrorString*, v8::Local<v8::Array>,
v8::Local<v8::String> property,
const String16& groupName,
bool forceValueType = false,
bool generatePreview = false) const;
bool wrapObjectsInArray(ErrorString*, v8::Local<v8::Array>,
const String16& groupName,
bool forceValueType = false,
bool generatePreview = false) const;
Response wrapObject(
v8::Local<v8::Value>, const String16& groupName, bool forceValueType,
bool generatePreview,
std::unique_ptr<protocol::Runtime::RemoteObject>* result) const;
Response wrapObjectProperty(v8::Local<v8::Object>, v8::Local<v8::Name> key,
const String16& groupName,
bool forceValueType = false,
bool generatePreview = false) const;
Response wrapPropertyInArray(v8::Local<v8::Array>,
v8::Local<v8::String> property,
const String16& groupName,
bool forceValueType = false,
bool generatePreview = false) const;
std::unique_ptr<protocol::Runtime::RemoteObject> wrapTable(
v8::Local<v8::Value> table, v8::Local<v8::Value> columns) const;
bool findObject(ErrorString*, const RemoteObjectId&,
v8::Local<v8::Value>*) const;
Response findObject(const RemoteObjectId&, v8::Local<v8::Value>*) const;
String16 objectGroupName(const RemoteObjectId&) const;
void releaseObjectGroup(const String16&);
void setCustomObjectFormatterEnabled(bool);
v8::MaybeLocal<v8::Value> resolveCallArgument(
ErrorString*, protocol::Runtime::CallArgument*);
std::unique_ptr<protocol::Runtime::ExceptionDetails> createExceptionDetails(
ErrorString*, const v8::TryCatch&, const String16& groupName,
bool generatePreview);
void wrapEvaluateResult(
ErrorString*, v8::MaybeLocal<v8::Value> maybeResultValue,
const v8::TryCatch&, const String16& objectGroup, bool returnByValue,
bool generatePreview,
Response resolveCallArgument(protocol::Runtime::CallArgument*,
v8::Local<v8::Value>* result);
Response createExceptionDetails(
const v8::TryCatch&, const String16& groupName, bool generatePreview,
Maybe<protocol::Runtime::ExceptionDetails>* result);
Response wrapEvaluateResult(
v8::MaybeLocal<v8::Value> maybeResultValue, const v8::TryCatch&,
const String16& objectGroup, bool returnByValue, bool generatePreview,
std::unique_ptr<protocol::Runtime::RemoteObject>* result,
Maybe<protocol::Runtime::ExceptionDetails>*);
v8::Local<v8::Value> lastEvaluationResult() const;
class Scope {
public:
bool initialize();
bool installCommandLineAPI();
Response initialize();
void installCommandLineAPI();
void ignoreExceptionsAndMuteConsole();
void pretendUserGesture();
v8::Local<v8::Context> context() const { return m_context; }
......@@ -115,11 +110,10 @@ class InjectedScript final {
const v8::TryCatch& tryCatch() const { return m_tryCatch; }
protected:
Scope(ErrorString*, V8InspectorImpl*, int contextGroupId);
Scope(V8InspectorImpl*, int contextGroupId);
virtual ~Scope();
virtual void findInjectedScript(V8InspectorSessionImpl*) = 0;
virtual Response findInjectedScript(V8InspectorSessionImpl*) = 0;
ErrorString* m_errorString;
V8InspectorImpl* m_inspector;
int m_contextGroupId;
InjectedScript* m_injectedScript;
......@@ -140,12 +134,11 @@ class InjectedScript final {
class ContextScope : public Scope {
public:
ContextScope(ErrorString*, V8InspectorImpl*, int contextGroupId,
int executionContextId);
ContextScope(V8InspectorImpl*, int contextGroupId, int executionContextId);
~ContextScope();
private:
void findInjectedScript(V8InspectorSessionImpl*) override;
Response findInjectedScript(V8InspectorSessionImpl*) override;
int m_executionContextId;
DISALLOW_COPY_AND_ASSIGN(ContextScope);
......@@ -153,14 +146,14 @@ class InjectedScript final {
class ObjectScope : public Scope {
public:
ObjectScope(ErrorString*, V8InspectorImpl*, int contextGroupId,
ObjectScope(V8InspectorImpl*, int contextGroupId,
const String16& remoteObjectId);
~ObjectScope();
const String16& objectGroupName() const { return m_objectGroupName; }
v8::Local<v8::Value> object() const { return m_object; }
private:
void findInjectedScript(V8InspectorSessionImpl*) override;
Response findInjectedScript(V8InspectorSessionImpl*) override;
String16 m_remoteObjectId;
String16 m_objectGroupName;
v8::Local<v8::Value> m_object;
......@@ -170,13 +163,13 @@ class InjectedScript final {
class CallFrameScope : public Scope {
public:
CallFrameScope(ErrorString*, V8InspectorImpl*, int contextGroupId,
CallFrameScope(V8InspectorImpl*, int contextGroupId,
const String16& remoteCallFrameId);
~CallFrameScope();
size_t frameOrdinal() const { return m_frameOrdinal; }
private:
void findInjectedScript(V8InspectorSessionImpl*) override;
Response findInjectedScript(V8InspectorSessionImpl*) override;
String16 m_remoteCallFrameId;
size_t m_frameOrdinal;
......@@ -187,10 +180,9 @@ class InjectedScript final {
InjectedScript(InspectedContext*, v8::Local<v8::Object>,
std::unique_ptr<InjectedScriptNative>);
v8::Local<v8::Value> v8Value() const;
v8::MaybeLocal<v8::Value> wrapValue(ErrorString*, v8::Local<v8::Value>,
const String16& groupName,
bool forceValueType,
bool generatePreview) const;
Response wrapValue(v8::Local<v8::Value>, const String16& groupName,
bool forceValueType, bool generatePreview,
v8::Local<v8::Value>* result) const;
v8::Local<v8::Object> commandLineAPI();
InspectedContext* m_context;
......
......@@ -27,44 +27,34 @@ RemoteObjectIdBase::parseInjectedScriptId(const String16& objectId) {
RemoteObjectId::RemoteObjectId() : RemoteObjectIdBase(), m_id(0) {}
std::unique_ptr<RemoteObjectId> RemoteObjectId::parse(
ErrorString* errorString, const String16& objectId) {
std::unique_ptr<RemoteObjectId> result(new RemoteObjectId());
Response RemoteObjectId::parse(const String16& objectId,
std::unique_ptr<RemoteObjectId>* result) {
std::unique_ptr<RemoteObjectId> remoteObjectId(new RemoteObjectId());
std::unique_ptr<protocol::DictionaryValue> parsedObjectId =
result->parseInjectedScriptId(objectId);
if (!parsedObjectId) {
*errorString = "Invalid remote object id";
return nullptr;
}
remoteObjectId->parseInjectedScriptId(objectId);
if (!parsedObjectId) return Response::Error("Invalid remote object id");
bool success = parsedObjectId->getInteger("id", &result->m_id);
if (!success) {
*errorString = "Invalid remote object id";
return nullptr;
}
return result;
bool success = parsedObjectId->getInteger("id", &remoteObjectId->m_id);
if (!success) return Response::Error("Invalid remote object id");
*result = std::move(remoteObjectId);
return Response::OK();
}
RemoteCallFrameId::RemoteCallFrameId()
: RemoteObjectIdBase(), m_frameOrdinal(0) {}
std::unique_ptr<RemoteCallFrameId> RemoteCallFrameId::parse(
ErrorString* errorString, const String16& objectId) {
std::unique_ptr<RemoteCallFrameId> result(new RemoteCallFrameId());
Response RemoteCallFrameId::parse(const String16& objectId,
std::unique_ptr<RemoteCallFrameId>* result) {
std::unique_ptr<RemoteCallFrameId> remoteCallFrameId(new RemoteCallFrameId());
std::unique_ptr<protocol::DictionaryValue> parsedObjectId =
result->parseInjectedScriptId(objectId);
if (!parsedObjectId) {
*errorString = "Invalid call frame id";
return nullptr;
}
remoteCallFrameId->parseInjectedScriptId(objectId);
if (!parsedObjectId) return Response::Error("Invalid call frame id");
bool success = parsedObjectId->getInteger("ordinal", &result->m_frameOrdinal);
if (!success) {
*errorString = "Invalid call frame id";
return nullptr;
}
return result;
bool success =
parsedObjectId->getInteger("ordinal", &remoteCallFrameId->m_frameOrdinal);
if (!success) return Response::Error("Invalid call frame id");
*result = std::move(remoteCallFrameId);
return Response::OK();
}
String16 RemoteCallFrameId::serialize(int injectedScriptId, int frameOrdinal) {
......
......@@ -9,7 +9,7 @@
namespace v8_inspector {
using protocol::ErrorString;
using protocol::Response;
class RemoteObjectIdBase {
public:
......@@ -27,7 +27,7 @@ class RemoteObjectIdBase {
class RemoteObjectId final : public RemoteObjectIdBase {
public:
static std::unique_ptr<RemoteObjectId> parse(ErrorString*, const String16&);
static Response parse(const String16&, std::unique_ptr<RemoteObjectId>*);
~RemoteObjectId() {}
int id() const { return m_id; }
......@@ -39,8 +39,7 @@ class RemoteObjectId final : public RemoteObjectIdBase {
class RemoteCallFrameId final : public RemoteObjectIdBase {
public:
static std::unique_ptr<RemoteCallFrameId> parse(ErrorString*,
const String16&);
static Response parse(const String16&, std::unique_ptr<RemoteCallFrameId>*);
~RemoteCallFrameId() {}
int frameOrdinal() const { return m_frameOrdinal; }
......
......@@ -111,94 +111,6 @@ std::unique_ptr<protocol::Value> parseJSON(const String16& string) {
} // namespace protocol
std::unique_ptr<protocol::Value> toProtocolValue(protocol::String* errorString,
v8::Local<v8::Context> context,
v8::Local<v8::Value> value,
int maxDepth) {
if (value.IsEmpty()) {
UNREACHABLE();
return nullptr;
}
if (!maxDepth) {
*errorString = "Object reference chain is too long";
return nullptr;
}
maxDepth--;
if (value->IsNull() || value->IsUndefined()) return protocol::Value::null();
if (value->IsBoolean())
return protocol::FundamentalValue::create(value.As<v8::Boolean>()->Value());
if (value->IsNumber()) {
double doubleValue = value.As<v8::Number>()->Value();
int intValue = static_cast<int>(doubleValue);
if (intValue == doubleValue)
return protocol::FundamentalValue::create(intValue);
return protocol::FundamentalValue::create(doubleValue);
}
if (value->IsString())
return protocol::StringValue::create(
toProtocolString(value.As<v8::String>()));
if (value->IsArray()) {
v8::Local<v8::Array> array = value.As<v8::Array>();
std::unique_ptr<protocol::ListValue> inspectorArray =
protocol::ListValue::create();
uint32_t length = array->Length();
for (uint32_t i = 0; i < length; i++) {
v8::Local<v8::Value> value;
if (!array->Get(context, i).ToLocal(&value)) {
*errorString = "Internal error";
return nullptr;
}
std::unique_ptr<protocol::Value> element =
toProtocolValue(errorString, context, value, maxDepth);
if (!element) return nullptr;
inspectorArray->pushValue(std::move(element));
}
return std::move(inspectorArray);
}
if (value->IsObject()) {
std::unique_ptr<protocol::DictionaryValue> jsonObject =
protocol::DictionaryValue::create();
v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(value);
v8::Local<v8::Array> propertyNames;
if (!object->GetPropertyNames(context).ToLocal(&propertyNames)) {
*errorString = "Internal error";
return nullptr;
}
uint32_t length = propertyNames->Length();
for (uint32_t i = 0; i < length; i++) {
v8::Local<v8::Value> name;
if (!propertyNames->Get(context, i).ToLocal(&name)) {
*errorString = "Internal error";
return nullptr;
}
// FIXME(yurys): v8::Object should support GetOwnPropertyNames
if (name->IsString()) {
v8::Maybe<bool> hasRealNamedProperty = object->HasRealNamedProperty(
context, v8::Local<v8::String>::Cast(name));
if (!hasRealNamedProperty.IsJust() || !hasRealNamedProperty.FromJust())
continue;
}
v8::Local<v8::String> propertyName;
if (!name->ToString(context).ToLocal(&propertyName)) continue;
v8::Local<v8::Value> property;
if (!object->Get(context, name).ToLocal(&property)) {
*errorString = "Internal error";
return nullptr;
}
std::unique_ptr<protocol::Value> propertyValue =
toProtocolValue(errorString, context, property, maxDepth);
if (!propertyValue) return nullptr;
jsonObject->setValue(toProtocolString(propertyName),
std::move(propertyValue));
}
return std::move(jsonObject);
}
*errorString = "Object couldn't be returned by value";
return nullptr;
}
// static
std::unique_ptr<StringBuffer> StringBuffer::create(const StringView& string) {
String16 owner = toString16(string);
......
......@@ -40,11 +40,6 @@ std::unique_ptr<protocol::Value> parseJSON(const String16& json);
} // namespace protocol
std::unique_ptr<protocol::Value> toProtocolValue(protocol::String* errorString,
v8::Local<v8::Context>,
v8::Local<v8::Value>,
int maxDepth = 1000);
v8::Local<v8::String> toV8String(v8::Isolate*, const String16&);
v8::Local<v8::String> toV8StringInternalized(v8::Isolate*, const String16&);
v8::Local<v8::String> toV8StringInternalized(v8::Isolate*, const char*);
......
......@@ -618,12 +618,11 @@ static void inspectImpl(const v8::FunctionCallbackInfo<v8::Value>& info,
if (!context) return;
InjectedScript* injectedScript = context->getInjectedScript();
if (!injectedScript) return;
ErrorString errorString;
std::unique_ptr<protocol::Runtime::RemoteObject> wrappedObject =
injectedScript->wrapObject(&errorString, info[0], "",
false /** forceValueType */,
false /** generatePreview */);
if (!wrappedObject || !errorString.isEmpty()) return;
std::unique_ptr<protocol::Runtime::RemoteObject> wrappedObject;
protocol::Response response =
injectedScript->wrapObject(info[0], "", false /** forceValueType */,
false /** generatePreview */, &wrappedObject);
if (!response.isSuccess()) return;
std::unique_ptr<protocol::DictionaryValue> hints =
protocol::DictionaryValue::create();
......
......@@ -22,6 +22,7 @@
#include "src/inspector/v8-regex.h"
#include "src/inspector/v8-runtime-agent-impl.h"
#include "src/inspector/v8-stack-trace-impl.h"
#include "src/inspector/v8-value-copier.h"
#include "include/v8-inspector.h"
......@@ -560,9 +561,13 @@ void V8DebuggerAgentImpl::restartFrame(
std::unique_ptr<Array<CallFrame>>* newCallFrames,
Maybe<StackTrace>* asyncStackTrace) {
if (!assertPaused(errorString)) return;
InjectedScript::CallFrameScope scope(
errorString, m_inspector, m_session->contextGroupId(), callFrameId);
if (!scope.initialize()) return;
InjectedScript::CallFrameScope scope(m_inspector, m_session->contextGroupId(),
callFrameId);
Response response = scope.initialize();
if (!response.isSuccess()) {
*errorString = response.errorMessage();
return;
}
if (scope.frameOrdinal() >= m_pausedCallFrames.size()) {
*errorString = "Could not find call frame with given id";
return;
......@@ -715,16 +720,19 @@ void V8DebuggerAgentImpl::evaluateOnCallFrame(
std::unique_ptr<RemoteObject>* result,
Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) {
if (!assertPaused(errorString)) return;
InjectedScript::CallFrameScope scope(
errorString, m_inspector, m_session->contextGroupId(), callFrameId);
if (!scope.initialize()) return;
InjectedScript::CallFrameScope scope(m_inspector, m_session->contextGroupId(),
callFrameId);
Response response = scope.initialize();
if (!response.isSuccess()) {
*errorString = response.errorMessage();
return;
}
if (scope.frameOrdinal() >= m_pausedCallFrames.size()) {
*errorString = "Could not find call frame with given id";
return;
}
if (includeCommandLineAPI.fromMaybe(false) && !scope.installCommandLineAPI())
return;
if (includeCommandLineAPI.fromMaybe(false)) scope.installCommandLineAPI();
if (silent.fromMaybe(false)) scope.ignoreExceptionsAndMuteConsole();
v8::MaybeLocal<v8::Value> maybeResultValue =
......@@ -733,11 +741,16 @@ void V8DebuggerAgentImpl::evaluateOnCallFrame(
// Re-initialize after running client's code, as it could have destroyed
// context or session.
if (!scope.initialize()) return;
scope.injectedScript()->wrapEvaluateResult(
errorString, maybeResultValue, scope.tryCatch(),
objectGroup.fromMaybe(""), returnByValue.fromMaybe(false),
generatePreview.fromMaybe(false), result, exceptionDetails);
response = scope.initialize();
if (!response.isSuccess()) {
*errorString = response.errorMessage();
return;
}
response = scope.injectedScript()->wrapEvaluateResult(
maybeResultValue, scope.tryCatch(), objectGroup.fromMaybe(""),
returnByValue.fromMaybe(false), generatePreview.fromMaybe(false), result,
exceptionDetails);
if (!response.isSuccess()) *errorString = response.errorMessage();
}
void V8DebuggerAgentImpl::setVariableValue(
......@@ -746,15 +759,20 @@ void V8DebuggerAgentImpl::setVariableValue(
const String16& callFrameId) {
if (!checkEnabled(errorString)) return;
if (!assertPaused(errorString)) return;
InjectedScript::CallFrameScope scope(
errorString, m_inspector, m_session->contextGroupId(), callFrameId);
if (!scope.initialize()) return;
InjectedScript::CallFrameScope scope(m_inspector, m_session->contextGroupId(),
callFrameId);
Response response = scope.initialize();
if (!response.isSuccess()) {
*errorString = response.errorMessage();
return;
}
v8::Local<v8::Value> newValue;
if (!scope.injectedScript()
->resolveCallArgument(errorString, newValueArgument.get())
.ToLocal(&newValue))
response = scope.injectedScript()->resolveCallArgument(newValueArgument.get(),
&newValue);
if (!response.isSuccess()) {
*errorString = response.errorMessage();
return;
}
if (scope.frameOrdinal() >= m_pausedCallFrames.size()) {
*errorString = "Could not find call frame with given id";
......@@ -907,7 +925,6 @@ std::unique_ptr<Array<CallFrame>> V8DebuggerAgentImpl::currentCallFrames(
ErrorString* errorString) {
if (m_pausedContext.IsEmpty() || !m_pausedCallFrames.size())
return Array<CallFrame>::create();
ErrorString ignored;
v8::HandleScope handles(m_isolate);
v8::Local<v8::Context> debuggerContext =
v8::DebugInterface::GetDebugContext(m_isolate);
......@@ -925,9 +942,9 @@ std::unique_ptr<Array<CallFrame>> V8DebuggerAgentImpl::currentCallFrames(
return Array<CallFrame>::create();
int contextId = currentCallFrame->contextId();
InjectedScript* injectedScript =
contextId ? m_session->findInjectedScript(&ignored, contextId)
: nullptr;
InjectedScript* injectedScript = nullptr;
if (contextId) m_session->findInjectedScript(contextId, injectedScript);
String16 callFrameId =
RemoteCallFrameId::serialize(contextId, static_cast<int>(frameOrdinal));
......@@ -950,24 +967,31 @@ std::unique_ptr<Array<CallFrame>> V8DebuggerAgentImpl::currentCallFrames(
!scopeChain->IsArray()))
return Array<CallFrame>::create();
v8::Local<v8::Array> scopeChainArray = scopeChain.As<v8::Array>();
if (!injectedScript->wrapPropertyInArray(
errorString, scopeChainArray,
toV8StringInternalized(m_isolate, "object"),
backtraceObjectGroup))
Response response = injectedScript->wrapPropertyInArray(
scopeChainArray, toV8StringInternalized(m_isolate, "object"),
backtraceObjectGroup);
if (!response.isSuccess()) {
*errorString = response.errorMessage();
return Array<CallFrame>::create();
if (!injectedScript->wrapObjectProperty(
errorString, details, toV8StringInternalized(m_isolate, "this"),
backtraceObjectGroup))
}
response = injectedScript->wrapObjectProperty(
details, toV8StringInternalized(m_isolate, "this"),
backtraceObjectGroup);
if (!response.isSuccess()) {
*errorString = response.errorMessage();
return Array<CallFrame>::create();
}
if (details
->Has(debuggerContext,
toV8StringInternalized(m_isolate, "returnValue"))
.FromMaybe(false)) {
if (!injectedScript->wrapObjectProperty(
errorString, details,
toV8StringInternalized(m_isolate, "returnValue"),
backtraceObjectGroup))
response = injectedScript->wrapObjectProperty(
details, toV8StringInternalized(m_isolate, "returnValue"),
backtraceObjectGroup);
if (!response.isSuccess()) {
*errorString = response.errorMessage();
return Array<CallFrame>::create();
}
}
} else {
if (hasInternalError(errorString, !details
......@@ -1010,9 +1034,9 @@ std::unique_ptr<Array<CallFrame>> V8DebuggerAgentImpl::currentCallFrames(
return Array<CallFrame>::create();
}
std::unique_ptr<protocol::Value> protocolValue =
toProtocolValue(errorString, debuggerContext, objects);
if (!protocolValue) return Array<CallFrame>::create();
std::unique_ptr<protocol::Value> protocolValue;
Response response = toProtocolValue(debuggerContext, objects, &protocolValue);
if (!response.isSuccess()) return Array<CallFrame>::create();
protocol::ErrorSupport errorSupport;
std::unique_ptr<Array<CallFrame>> callFrames =
Array<CallFrame>::parse(protocolValue.get(), &errorSupport);
......@@ -1127,17 +1151,17 @@ V8DebuggerAgentImpl::SkipPauseRequest V8DebuggerAgentImpl::didPause(
v8::HandleScope handles(m_isolate);
if (!exception.IsEmpty()) {
ErrorString ignored;
InjectedScript* injectedScript =
m_session->findInjectedScript(&ignored, V8Debugger::contextId(context));
InjectedScript* injectedScript = nullptr;
m_session->findInjectedScript(V8Debugger::contextId(context),
injectedScript);
if (injectedScript) {
m_breakReason =
isPromiseRejection
? protocol::Debugger::Paused::ReasonEnum::PromiseRejection
: protocol::Debugger::Paused::ReasonEnum::Exception;
ErrorString errorString;
auto obj = injectedScript->wrapObject(&errorString, exception,
backtraceObjectGroup);
std::unique_ptr<protocol::Runtime::RemoteObject> obj;
injectedScript->wrapObject(exception, backtraceObjectGroup, false, false,
&obj);
m_breakAuxData = obj ? obj->serialize() : nullptr;
// m_breakAuxData might be null after this.
}
......
......@@ -269,11 +269,10 @@ Response V8HeapProfilerAgentImpl::getHeapObjectId(
v8::HandleScope handles(m_isolate);
v8::Local<v8::Value> value;
v8::Local<v8::Context> context;
protocol::ErrorString errorString;
if (!m_session->unwrapObject(&errorString, objectId, &value, &context,
nullptr) ||
value->IsUndefined())
return Response::Error(errorString);
Response response =
m_session->unwrapObject(objectId, &value, &context, nullptr);
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));
......
......@@ -104,12 +104,12 @@ V8InspectorSessionImpl::V8InspectorSessionImpl(V8InspectorImpl* inspector,
}
V8InspectorSessionImpl::~V8InspectorSessionImpl() {
ErrorString errorString;
protocol::ErrorString errorString;
m_consoleAgent->disable();
m_profilerAgent->disable();
m_heapProfilerAgent->disable();
m_debuggerAgent->disable(&errorString);
m_runtimeAgent->disable(&errorString);
m_runtimeAgent->disable();
discardInjectedScripts();
m_inspector->disconnect(this);
......@@ -165,42 +165,35 @@ void V8InspectorSessionImpl::discardInjectedScripts() {
}
}
InjectedScript* V8InspectorSessionImpl::findInjectedScript(
ErrorString* errorString, int contextId) {
if (!contextId) {
*errorString = "Cannot find context with specified id";
return nullptr;
}
Response V8InspectorSessionImpl::findInjectedScript(
int contextId, InjectedScript*& injectedScript) {
injectedScript = nullptr;
if (!contextId)
return Response::Error("Cannot find context with specified id");
const V8InspectorImpl::ContextByIdMap* contexts =
m_inspector->contextGroup(m_contextGroupId);
if (!contexts) {
*errorString = "Cannot find context with specified id";
return nullptr;
}
if (!contexts)
return Response::Error("Cannot find context with specified id");
auto contextsIt = contexts->find(contextId);
if (contextsIt == contexts->end()) {
*errorString = "Cannot find context with specified id";
return nullptr;
}
if (contextsIt == contexts->end())
return Response::Error("Cannot find context with specified id");
const std::unique_ptr<InspectedContext>& context = contextsIt->second;
if (!context->getInjectedScript()) {
if (!context->createInjectedScript()) {
*errorString = "Cannot access specified execution context";
return nullptr;
}
if (!context->createInjectedScript())
return Response::Error("Cannot access specified execution context");
if (m_customObjectFormatterEnabled)
context->getInjectedScript()->setCustomObjectFormatterEnabled(true);
}
return context->getInjectedScript();
injectedScript = context->getInjectedScript();
return Response::OK();
}
InjectedScript* V8InspectorSessionImpl::findInjectedScript(
ErrorString* errorString, RemoteObjectIdBase* objectId) {
return objectId ? findInjectedScript(errorString, objectId->contextId())
: nullptr;
Response V8InspectorSessionImpl::findInjectedScript(
RemoteObjectIdBase* objectId, InjectedScript*& injectedScript) {
return findInjectedScript(objectId->contextId(), injectedScript);
}
void V8InspectorSessionImpl::releaseObjectGroup(const StringView& objectGroup) {
......@@ -230,31 +223,35 @@ bool V8InspectorSessionImpl::unwrapObject(
std::unique_ptr<StringBuffer>* error, const StringView& objectId,
v8::Local<v8::Value>* object, v8::Local<v8::Context>* context,
std::unique_ptr<StringBuffer>* objectGroup) {
ErrorString errorString;
String16 objectGroupString;
bool result =
unwrapObject(&errorString, toString16(objectId), object, context,
objectGroup ? &objectGroupString : nullptr);
if (error) *error = StringBufferImpl::adopt(errorString);
Response response = unwrapObject(toString16(objectId), object, context,
objectGroup ? &objectGroupString : nullptr);
if (!response.isSuccess()) {
if (error) {
String16 errorMessage = response.errorMessage();
*error = StringBufferImpl::adopt(errorMessage);
}
return false;
}
if (objectGroup) *objectGroup = StringBufferImpl::adopt(objectGroupString);
return result;
return true;
}
bool V8InspectorSessionImpl::unwrapObject(ErrorString* errorString,
const String16& objectId,
v8::Local<v8::Value>* object,
v8::Local<v8::Context>* context,
String16* objectGroup) {
std::unique_ptr<RemoteObjectId> remoteId =
RemoteObjectId::parse(errorString, objectId);
if (!remoteId) return false;
InjectedScript* injectedScript =
findInjectedScript(errorString, remoteId.get());
if (!injectedScript) return false;
if (!injectedScript->findObject(errorString, *remoteId, object)) return false;
Response V8InspectorSessionImpl::unwrapObject(const String16& objectId,
v8::Local<v8::Value>* object,
v8::Local<v8::Context>* context,
String16* objectGroup) {
std::unique_ptr<RemoteObjectId> remoteId;
Response response = RemoteObjectId::parse(objectId, &remoteId);
if (!response.isSuccess()) return response;
InjectedScript* injectedScript = nullptr;
response = findInjectedScript(remoteId.get(), injectedScript);
if (!response.isSuccess()) return response;
response = injectedScript->findObject(*remoteId, object);
if (!response.isSuccess()) return response;
*context = injectedScript->context()->context();
if (objectGroup) *objectGroup = injectedScript->objectGroupName(*remoteId);
return true;
return Response::OK();
}
std::unique_ptr<protocol::Runtime::API::RemoteObject>
......@@ -269,21 +266,20 @@ V8InspectorSessionImpl::wrapObject(v8::Local<v8::Context> context,
v8::Local<v8::Value> value,
const String16& groupName,
bool generatePreview) {
ErrorString errorString;
InjectedScript* injectedScript =
findInjectedScript(&errorString, V8Debugger::contextId(context));
InjectedScript* injectedScript = nullptr;
findInjectedScript(V8Debugger::contextId(context), injectedScript);
if (!injectedScript) return nullptr;
return injectedScript->wrapObject(&errorString, value, groupName, false,
generatePreview);
std::unique_ptr<protocol::Runtime::RemoteObject> result;
injectedScript->wrapObject(value, groupName, false, generatePreview, &result);
return result;
}
std::unique_ptr<protocol::Runtime::RemoteObject>
V8InspectorSessionImpl::wrapTable(v8::Local<v8::Context> context,
v8::Local<v8::Value> table,
v8::Local<v8::Value> columns) {
ErrorString errorString;
InjectedScript* injectedScript =
findInjectedScript(&errorString, V8Debugger::contextId(context));
InjectedScript* injectedScript = nullptr;
findInjectedScript(V8Debugger::contextId(context), injectedScript);
if (!injectedScript) return nullptr;
return injectedScript->wrapTable(table, columns);
}
......@@ -386,17 +382,17 @@ void V8InspectorSessionImpl::breakProgram(const StringView& breakReason,
}
void V8InspectorSessionImpl::setSkipAllPauses(bool skip) {
ErrorString errorString;
protocol::ErrorString errorString;
m_debuggerAgent->setSkipAllPauses(&errorString, skip);
}
void V8InspectorSessionImpl::resume() {
ErrorString errorString;
protocol::ErrorString errorString;
m_debuggerAgent->resume(&errorString);
}
void V8InspectorSessionImpl::stepOver() {
ErrorString errorString;
protocol::ErrorString errorString;
m_debuggerAgent->stepOver(&errorString);
}
......
......@@ -26,7 +26,7 @@ class V8ProfilerAgentImpl;
class V8RuntimeAgentImpl;
class V8SchemaAgentImpl;
using protocol::ErrorString;
using protocol::Response;
class V8InspectorSessionImpl : public V8InspectorSession,
public protocol::FrontendChannel {
......@@ -44,8 +44,8 @@ class V8InspectorSessionImpl : public V8InspectorSession,
V8RuntimeAgentImpl* runtimeAgent() { return m_runtimeAgent.get(); }
int contextGroupId() const { return m_contextGroupId; }
InjectedScript* findInjectedScript(ErrorString*, int contextId);
InjectedScript* findInjectedScript(ErrorString*, RemoteObjectIdBase*);
Response findInjectedScript(int contextId, InjectedScript*&);
Response findInjectedScript(RemoteObjectIdBase*, InjectedScript*&);
void reset();
void discardInjectedScripts();
void reportAllContexts(V8RuntimeAgentImpl*);
......@@ -57,9 +57,8 @@ class V8InspectorSessionImpl : public V8InspectorSession,
v8::Local<v8::Context>, v8::Local<v8::Value> table,
v8::Local<v8::Value> columns);
std::vector<std::unique_ptr<protocol::Schema::Domain>> supportedDomainsImpl();
bool unwrapObject(ErrorString*, const String16& objectId,
v8::Local<v8::Value>*, v8::Local<v8::Context>*,
String16* objectGroup);
Response unwrapObject(const String16& objectId, v8::Local<v8::Value>*,
v8::Local<v8::Context>*, String16* objectGroup);
void releaseObjectGroup(const String16& objectGroup);
// V8InspectorSession implementation.
......
......@@ -55,11 +55,6 @@ static const char runtimeEnabled[] = "runtimeEnabled";
using protocol::Runtime::RemoteObject;
static bool hasInternalError(ErrorString* errorString, bool hasError) {
if (hasError) *errorString = "Internal error";
return hasError;
}
namespace {
template <typename Callback>
......@@ -72,11 +67,11 @@ class ProtocolPromiseHandler {
bool returnByValue, bool generatePreview,
std::unique_ptr<Callback> callback) {
if (value.IsEmpty()) {
callback->sendFailure("Internal error");
callback->sendFailure(Response::InternalError());
return;
}
if (!value.ToLocalChecked()->IsPromise()) {
callback->sendFailure(notPromiseError);
callback->sendFailure(Response::Error(notPromiseError));
return;
}
v8::MicrotasksScope microtasks_scope(inspector->isolate(),
......@@ -94,7 +89,7 @@ class ProtocolPromiseHandler {
v8::ConstructorBehavior::kThrow)
.ToLocalChecked();
if (promise->Then(context, thenCallbackFunction).IsEmpty()) {
rawCallback->sendFailure("Internal error");
rawCallback->sendFailure(Response::InternalError());
return;
}
v8::Local<v8::Function> catchCallbackFunction =
......@@ -102,7 +97,7 @@ class ProtocolPromiseHandler {
v8::ConstructorBehavior::kThrow)
.ToLocalChecked();
if (promise->Catch(context, catchCallbackFunction).IsEmpty()) {
rawCallback->sendFailure("Internal error");
rawCallback->sendFailure(Response::InternalError());
return;
}
}
......@@ -180,25 +175,27 @@ class ProtocolPromiseHandler {
data.GetParameter()->m_wrapper.Reset();
data.SetSecondPassCallback(cleanup);
} else {
data.GetParameter()->m_callback->sendFailure("Promise was collected");
data.GetParameter()->m_callback->sendFailure(
Response::Error("Promise was collected"));
delete data.GetParameter();
}
}
std::unique_ptr<protocol::Runtime::RemoteObject> wrapObject(
v8::Local<v8::Value> value) {
ErrorString errorString;
InjectedScript::ContextScope scope(&errorString, m_inspector,
m_contextGroupId, m_executionContextId);
if (!scope.initialize()) {
m_callback->sendFailure(errorString);
InjectedScript::ContextScope scope(m_inspector, m_contextGroupId,
m_executionContextId);
Response response = scope.initialize();
if (!response.isSuccess()) {
m_callback->sendFailure(response);
return nullptr;
}
std::unique_ptr<protocol::Runtime::RemoteObject> wrappedValue =
scope.injectedScript()->wrapObject(&errorString, value, m_objectGroup,
m_returnByValue, m_generatePreview);
if (!wrappedValue) {
m_callback->sendFailure(errorString);
std::unique_ptr<protocol::Runtime::RemoteObject> wrappedValue;
response = scope.injectedScript()->wrapObject(
value, m_objectGroup, m_returnByValue, m_generatePreview,
&wrappedValue);
if (!response.isSuccess()) {
m_callback->sendFailure(response);
return nullptr;
}
return wrappedValue;
......@@ -223,34 +220,30 @@ bool wrapEvaluateResultAsync(InjectedScript* injectedScript,
std::unique_ptr<RemoteObject> result;
Maybe<protocol::Runtime::ExceptionDetails> exceptionDetails;
ErrorString errorString;
injectedScript->wrapEvaluateResult(
&errorString, maybeResultValue, tryCatch, objectGroup, returnByValue,
generatePreview, &result, &exceptionDetails);
if (errorString.isEmpty()) {
callback->sendSuccess(std::move(result), exceptionDetails);
Response response = injectedScript->wrapEvaluateResult(
maybeResultValue, tryCatch, objectGroup, returnByValue, generatePreview,
&result, &exceptionDetails);
if (response.isSuccess()) {
callback->sendSuccess(std::move(result), std::move(exceptionDetails));
return true;
}
callback->sendFailure(errorString);
callback->sendFailure(response);
return false;
}
int ensureContext(ErrorString* errorString, V8InspectorImpl* inspector,
int contextGroupId, const Maybe<int>& executionContextId) {
int contextId;
Response ensureContext(V8InspectorImpl* inspector, int contextGroupId,
Maybe<int> executionContextId, int* contextId) {
if (executionContextId.isJust()) {
contextId = executionContextId.fromJust();
*contextId = executionContextId.fromJust();
} else {
v8::HandleScope handles(inspector->isolate());
v8::Local<v8::Context> defaultContext =
inspector->client()->ensureDefaultContextInGroup(contextGroupId);
if (defaultContext.IsEmpty()) {
*errorString = "Cannot find default execution context";
return 0;
}
contextId = V8Debugger::contextId(defaultContext);
if (defaultContext.IsEmpty())
return Response::Error("Cannot find default execution context");
*contextId = V8Debugger::contextId(defaultContext);
}
return contextId;
return Response::OK();
}
} // namespace
......@@ -267,38 +260,33 @@ V8RuntimeAgentImpl::V8RuntimeAgentImpl(
V8RuntimeAgentImpl::~V8RuntimeAgentImpl() {}
void V8RuntimeAgentImpl::evaluate(
const String16& expression, const Maybe<String16>& objectGroup,
const Maybe<bool>& includeCommandLineAPI, const Maybe<bool>& silent,
const Maybe<int>& executionContextId, const Maybe<bool>& returnByValue,
const Maybe<bool>& generatePreview, const Maybe<bool>& userGesture,
const Maybe<bool>& awaitPromise,
std::unique_ptr<EvaluateCallback> callback) {
const String16& expression, Maybe<String16> objectGroup,
Maybe<bool> includeCommandLineAPI, Maybe<bool> silent,
Maybe<int> executionContextId, Maybe<bool> returnByValue,
Maybe<bool> generatePreview, Maybe<bool> userGesture,
Maybe<bool> awaitPromise, std::unique_ptr<EvaluateCallback> callback) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"),
"EvaluateScript");
ErrorString errorString;
int contextId =
ensureContext(&errorString, m_inspector, m_session->contextGroupId(),
executionContextId);
if (!errorString.isEmpty()) {
callback->sendFailure(errorString);
int contextId = 0;
Response response = ensureContext(m_inspector, m_session->contextGroupId(),
std::move(executionContextId), &contextId);
if (!response.isSuccess()) {
callback->sendFailure(response);
return;
}
InjectedScript::ContextScope scope(&errorString, m_inspector,
m_session->contextGroupId(), contextId);
if (!scope.initialize()) {
callback->sendFailure(errorString);
InjectedScript::ContextScope scope(m_inspector, m_session->contextGroupId(),
contextId);
response = scope.initialize();
if (!response.isSuccess()) {
callback->sendFailure(response);
return;
}
if (silent.fromMaybe(false)) scope.ignoreExceptionsAndMuteConsole();
if (userGesture.fromMaybe(false)) scope.pretendUserGesture();
if (includeCommandLineAPI.fromMaybe(false) &&
!scope.installCommandLineAPI()) {
callback->sendFailure(errorString);
return;
}
if (includeCommandLineAPI.fromMaybe(false)) scope.installCommandLineAPI();
bool evalIsDisabled = !scope.context()->IsCodeGenerationFromStringsAllowed();
// Temporarily enable allow evals for inspector.
......@@ -315,8 +303,9 @@ void V8RuntimeAgentImpl::evaluate(
// Re-initialize after running client's code, as it could have destroyed
// context or session.
if (!scope.initialize()) {
callback->sendFailure(errorString);
response = scope.initialize();
if (!response.isSuccess()) {
callback->sendFailure(response);
return;
}
......@@ -336,14 +325,14 @@ void V8RuntimeAgentImpl::evaluate(
}
void V8RuntimeAgentImpl::awaitPromise(
const String16& promiseObjectId, const Maybe<bool>& returnByValue,
const Maybe<bool>& generatePreview,
const String16& promiseObjectId, Maybe<bool> returnByValue,
Maybe<bool> generatePreview,
std::unique_ptr<AwaitPromiseCallback> callback) {
ErrorString errorString;
InjectedScript::ObjectScope scope(
&errorString, m_inspector, m_session->contextGroupId(), promiseObjectId);
if (!scope.initialize()) {
callback->sendFailure(errorString);
InjectedScript::ObjectScope scope(m_inspector, m_session->contextGroupId(),
promiseObjectId);
Response response = scope.initialize();
if (!response.isSuccess()) {
callback->sendFailure(response);
return;
}
ProtocolPromiseHandler<AwaitPromiseCallback>::add(
......@@ -356,17 +345,15 @@ void V8RuntimeAgentImpl::awaitPromise(
void V8RuntimeAgentImpl::callFunctionOn(
const String16& objectId, const String16& expression,
const Maybe<protocol::Array<protocol::Runtime::CallArgument>>&
optionalArguments,
const Maybe<bool>& silent, const Maybe<bool>& returnByValue,
const Maybe<bool>& generatePreview, const Maybe<bool>& userGesture,
const Maybe<bool>& awaitPromise,
Maybe<protocol::Array<protocol::Runtime::CallArgument>> optionalArguments,
Maybe<bool> silent, Maybe<bool> returnByValue, Maybe<bool> generatePreview,
Maybe<bool> userGesture, Maybe<bool> awaitPromise,
std::unique_ptr<CallFunctionOnCallback> callback) {
ErrorString errorString;
InjectedScript::ObjectScope scope(&errorString, m_inspector,
m_session->contextGroupId(), objectId);
if (!scope.initialize()) {
callback->sendFailure(errorString);
InjectedScript::ObjectScope scope(m_inspector, m_session->contextGroupId(),
objectId);
Response response = scope.initialize();
if (!response.isSuccess()) {
callback->sendFailure(response);
return;
}
......@@ -379,10 +366,10 @@ void V8RuntimeAgentImpl::callFunctionOn(
argv.reset(new v8::Local<v8::Value>[argc]);
for (int i = 0; i < argc; ++i) {
v8::Local<v8::Value> argumentValue;
if (!scope.injectedScript()
->resolveCallArgument(&errorString, arguments->get(i))
.ToLocal(&argumentValue)) {
callback->sendFailure(errorString);
response = scope.injectedScript()->resolveCallArgument(arguments->get(i),
&argumentValue);
if (!response.isSuccess()) {
callback->sendFailure(response);
return;
}
argv[i] = argumentValue;
......@@ -398,8 +385,9 @@ void V8RuntimeAgentImpl::callFunctionOn(
toV8String(m_inspector->isolate(), "(" + expression + ")"));
// Re-initialize after running client's code, as it could have destroyed
// context or session.
if (!scope.initialize()) {
callback->sendFailure(errorString);
response = scope.initialize();
if (!response.isSuccess()) {
callback->sendFailure(response);
return;
}
......@@ -413,7 +401,8 @@ void V8RuntimeAgentImpl::callFunctionOn(
v8::Local<v8::Value> functionValue;
if (!maybeFunctionValue.ToLocal(&functionValue) ||
!functionValue->IsFunction()) {
callback->sendFailure("Given expression does not evaluate to a function");
callback->sendFailure(
Response::Error("Given expression does not evaluate to a function"));
return;
}
......@@ -422,8 +411,9 @@ void V8RuntimeAgentImpl::callFunctionOn(
argv.get());
// Re-initialize after running client's code, as it could have destroyed
// context or session.
if (!scope.initialize()) {
callback->sendFailure(errorString);
response = scope.initialize();
if (!response.isSuccess()) {
callback->sendFailure(response);
return;
}
......@@ -444,10 +434,9 @@ void V8RuntimeAgentImpl::callFunctionOn(
std::move(callback));
}
void V8RuntimeAgentImpl::getProperties(
ErrorString* errorString, const String16& objectId,
const Maybe<bool>& ownProperties, const Maybe<bool>& accessorPropertiesOnly,
const Maybe<bool>& generatePreview,
Response V8RuntimeAgentImpl::getProperties(
const String16& objectId, Maybe<bool> ownProperties,
Maybe<bool> accessorPropertiesOnly, Maybe<bool> generatePreview,
std::unique_ptr<protocol::Array<protocol::Runtime::PropertyDescriptor>>*
result,
Maybe<protocol::Array<protocol::Runtime::InternalPropertyDescriptor>>*
......@@ -455,105 +444,103 @@ void V8RuntimeAgentImpl::getProperties(
Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) {
using protocol::Runtime::InternalPropertyDescriptor;
InjectedScript::ObjectScope scope(errorString, m_inspector,
m_session->contextGroupId(), objectId);
if (!scope.initialize()) return;
InjectedScript::ObjectScope scope(m_inspector, m_session->contextGroupId(),
objectId);
Response response = scope.initialize();
if (!response.isSuccess()) return response;
scope.ignoreExceptionsAndMuteConsole();
if (!scope.object()->IsObject()) {
*errorString = "Value with given id is not an object";
return;
}
if (!scope.object()->IsObject())
return Response::Error("Value with given id is not an object");
v8::Local<v8::Object> object = scope.object().As<v8::Object>();
scope.injectedScript()->getProperties(
errorString, object, scope.objectGroupName(),
ownProperties.fromMaybe(false), accessorPropertiesOnly.fromMaybe(false),
generatePreview.fromMaybe(false), result, exceptionDetails);
if (!errorString->isEmpty() || exceptionDetails->isJust() ||
accessorPropertiesOnly.fromMaybe(false))
return;
response = scope.injectedScript()->getProperties(
object, scope.objectGroupName(), ownProperties.fromMaybe(false),
accessorPropertiesOnly.fromMaybe(false), generatePreview.fromMaybe(false),
result, exceptionDetails);
if (!response.isSuccess()) return response;
if (exceptionDetails->isJust() || accessorPropertiesOnly.fromMaybe(false))
return Response::OK();
v8::Local<v8::Array> propertiesArray;
if (hasInternalError(errorString, !m_inspector->debugger()
->internalProperties(scope.context(),
scope.object())
.ToLocal(&propertiesArray)))
return;
if (!m_inspector->debugger()
->internalProperties(scope.context(), scope.object())
.ToLocal(&propertiesArray)) {
return Response::InternalError();
}
std::unique_ptr<protocol::Array<InternalPropertyDescriptor>>
propertiesProtocolArray =
protocol::Array<InternalPropertyDescriptor>::create();
for (uint32_t i = 0; i < propertiesArray->Length(); i += 2) {
v8::Local<v8::Value> name;
if (hasInternalError(
errorString,
!propertiesArray->Get(scope.context(), i).ToLocal(&name)) ||
!name->IsString())
return;
if (!propertiesArray->Get(scope.context(), i).ToLocal(&name) ||
!name->IsString()) {
return Response::InternalError();
}
v8::Local<v8::Value> value;
if (hasInternalError(
errorString,
!propertiesArray->Get(scope.context(), i + 1).ToLocal(&value)))
return;
std::unique_ptr<RemoteObject> wrappedValue =
scope.injectedScript()->wrapObject(errorString, value,
scope.objectGroupName());
if (!wrappedValue) return;
if (!propertiesArray->Get(scope.context(), i + 1).ToLocal(&value))
return Response::InternalError();
std::unique_ptr<RemoteObject> wrappedValue;
protocol::Response response = scope.injectedScript()->wrapObject(
value, scope.objectGroupName(), false, false, &wrappedValue);
if (!response.isSuccess()) return response;
propertiesProtocolArray->addItem(
InternalPropertyDescriptor::create()
.setName(toProtocolString(name.As<v8::String>()))
.setValue(std::move(wrappedValue))
.build());
}
if (!propertiesProtocolArray->length()) return;
*internalProperties = std::move(propertiesProtocolArray);
if (propertiesProtocolArray->length())
*internalProperties = std::move(propertiesProtocolArray);
return Response::OK();
}
void V8RuntimeAgentImpl::releaseObject(ErrorString* errorString,
const String16& objectId) {
InjectedScript::ObjectScope scope(errorString, m_inspector,
m_session->contextGroupId(), objectId);
if (!scope.initialize()) return;
Response V8RuntimeAgentImpl::releaseObject(const String16& objectId) {
InjectedScript::ObjectScope scope(m_inspector, m_session->contextGroupId(),
objectId);
Response response = scope.initialize();
if (!response.isSuccess()) return response;
scope.injectedScript()->releaseObject(objectId);
return Response::OK();
}
void V8RuntimeAgentImpl::releaseObjectGroup(ErrorString*,
const String16& objectGroup) {
Response V8RuntimeAgentImpl::releaseObjectGroup(const String16& objectGroup) {
m_session->releaseObjectGroup(objectGroup);
return Response::OK();
}
void V8RuntimeAgentImpl::runIfWaitingForDebugger(ErrorString* errorString) {
Response V8RuntimeAgentImpl::runIfWaitingForDebugger() {
m_inspector->client()->runIfWaitingForDebugger(m_session->contextGroupId());
return Response::OK();
}
void V8RuntimeAgentImpl::setCustomObjectFormatterEnabled(ErrorString*,
bool enabled) {
Response V8RuntimeAgentImpl::setCustomObjectFormatterEnabled(bool enabled) {
m_state->setBoolean(V8RuntimeAgentImplState::customObjectFormatterEnabled,
enabled);
m_session->setCustomObjectFormatterEnabled(enabled);
return Response::OK();
}
void V8RuntimeAgentImpl::discardConsoleEntries(ErrorString*) {
Response V8RuntimeAgentImpl::discardConsoleEntries() {
V8ConsoleMessageStorage* storage =
m_inspector->ensureConsoleMessageStorage(m_session->contextGroupId());
storage->clear();
return Response::OK();
}
void V8RuntimeAgentImpl::compileScript(
ErrorString* errorString, const String16& expression,
const String16& sourceURL, bool persistScript,
const Maybe<int>& executionContextId, Maybe<String16>* scriptId,
Response V8RuntimeAgentImpl::compileScript(
const String16& expression, const String16& sourceURL, bool persistScript,
Maybe<int> executionContextId, Maybe<String16>* scriptId,
Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) {
if (!m_enabled) {
*errorString = "Runtime agent is not enabled";
return;
}
int contextId =
ensureContext(errorString, m_inspector, m_session->contextGroupId(),
executionContextId);
if (!errorString->isEmpty()) return;
InjectedScript::ContextScope scope(errorString, m_inspector,
m_session->contextGroupId(), contextId);
if (!scope.initialize()) return;
if (!m_enabled) return Response::Error("Runtime agent is not enabled");
int contextId = 0;
Response response = ensureContext(m_inspector, m_session->contextGroupId(),
std::move(executionContextId), &contextId);
if (!response.isSuccess()) return response;
InjectedScript::ContextScope scope(m_inspector, m_session->contextGroupId(),
contextId);
response = scope.initialize();
if (!response.isSuccess()) return response;
if (!persistScript) m_inspector->debugger()->muteScriptParsedEvents();
v8::Local<v8::Script> script = m_inspector->compileScript(
......@@ -561,15 +548,17 @@ void V8RuntimeAgentImpl::compileScript(
sourceURL, false);
if (!persistScript) m_inspector->debugger()->unmuteScriptParsedEvents();
if (script.IsEmpty()) {
if (scope.tryCatch().HasCaught())
*exceptionDetails = scope.injectedScript()->createExceptionDetails(
errorString, scope.tryCatch(), String16(), false);
else
*errorString = "Script compilation failed";
return;
if (scope.tryCatch().HasCaught()) {
response = scope.injectedScript()->createExceptionDetails(
scope.tryCatch(), String16(), false, exceptionDetails);
if (!response.isSuccess()) return response;
return Response::OK();
} else {
return Response::Error("Script compilation failed");
}
}
if (!persistScript) return;
if (!persistScript) return Response::OK();
String16 scriptValueId =
String16::fromInteger(script->GetUnboundScript()->GetId());
......@@ -577,38 +566,39 @@ void V8RuntimeAgentImpl::compileScript(
new v8::Global<v8::Script>(m_inspector->isolate(), script));
m_compiledScripts[scriptValueId] = std::move(global);
*scriptId = scriptValueId;
return Response::OK();
}
void V8RuntimeAgentImpl::runScript(
const String16& scriptId, const Maybe<int>& executionContextId,
const Maybe<String16>& objectGroup, const Maybe<bool>& silent,
const Maybe<bool>& includeCommandLineAPI, const Maybe<bool>& returnByValue,
const Maybe<bool>& generatePreview, const Maybe<bool>& awaitPromise,
const String16& scriptId, Maybe<int> executionContextId,
Maybe<String16> objectGroup, Maybe<bool> silent,
Maybe<bool> includeCommandLineAPI, Maybe<bool> returnByValue,
Maybe<bool> generatePreview, Maybe<bool> awaitPromise,
std::unique_ptr<RunScriptCallback> callback) {
if (!m_enabled) {
callback->sendFailure("Runtime agent is not enabled");
callback->sendFailure(Response::Error("Runtime agent is not enabled"));
return;
}
auto it = m_compiledScripts.find(scriptId);
if (it == m_compiledScripts.end()) {
callback->sendFailure("No script with given id");
callback->sendFailure(Response::Error("No script with given id"));
return;
}
ErrorString errorString;
int contextId =
ensureContext(&errorString, m_inspector, m_session->contextGroupId(),
executionContextId);
if (!errorString.isEmpty()) {
callback->sendFailure(errorString);
int contextId = 0;
Response response = ensureContext(m_inspector, m_session->contextGroupId(),
std::move(executionContextId), &contextId);
if (!response.isSuccess()) {
callback->sendFailure(response);
return;
}
InjectedScript::ContextScope scope(&errorString, m_inspector,
m_session->contextGroupId(), contextId);
if (!scope.initialize()) {
callback->sendFailure(errorString);
InjectedScript::ContextScope scope(m_inspector, m_session->contextGroupId(),
contextId);
response = scope.initialize();
if (!response.isSuccess()) {
callback->sendFailure(response);
return;
}
......@@ -618,19 +608,22 @@ void V8RuntimeAgentImpl::runScript(
m_compiledScripts.erase(it);
v8::Local<v8::Script> script = scriptWrapper->Get(m_inspector->isolate());
if (script.IsEmpty()) {
callback->sendFailure("Script execution failed");
callback->sendFailure(Response::Error("Script execution failed"));
return;
}
if (includeCommandLineAPI.fromMaybe(false) && !scope.installCommandLineAPI())
return;
if (includeCommandLineAPI.fromMaybe(false)) scope.installCommandLineAPI();
v8::MaybeLocal<v8::Value> maybeResultValue =
m_inspector->runCompiledScript(scope.context(), script);
// Re-initialize after running client's code, as it could have destroyed
// context or session.
if (!scope.initialize()) return;
response = scope.initialize();
if (!response.isSuccess()) {
callback->sendFailure(response);
return;
}
if (!awaitPromise.fromMaybe(false) || scope.tryCatch().HasCaught()) {
wrapEvaluateResultAsync(scope.injectedScript(), maybeResultValue,
......@@ -652,15 +645,14 @@ void V8RuntimeAgentImpl::restore() {
if (!m_state->booleanProperty(V8RuntimeAgentImplState::runtimeEnabled, false))
return;
m_frontend.executionContextsCleared();
ErrorString error;
enable(&error);
enable();
if (m_state->booleanProperty(
V8RuntimeAgentImplState::customObjectFormatterEnabled, false))
m_session->setCustomObjectFormatterEnabled(true);
}
void V8RuntimeAgentImpl::enable(ErrorString* errorString) {
if (m_enabled) return;
Response V8RuntimeAgentImpl::enable() {
if (m_enabled) return Response::OK();
m_inspector->client()->beginEnsureAllContextsInGroup(
m_session->contextGroupId());
m_enabled = true;
......@@ -670,12 +662,13 @@ void V8RuntimeAgentImpl::enable(ErrorString* errorString) {
V8ConsoleMessageStorage* storage =
m_inspector->ensureConsoleMessageStorage(m_session->contextGroupId());
for (const auto& message : storage->messages()) {
if (!reportMessage(message.get(), false)) return;
if (!reportMessage(message.get(), false)) break;
}
return Response::OK();
}
void V8RuntimeAgentImpl::disable(ErrorString* errorString) {
if (!m_enabled) return;
Response V8RuntimeAgentImpl::disable() {
if (!m_enabled) return Response::OK();
m_enabled = false;
m_state->setBoolean(V8RuntimeAgentImplState::runtimeEnabled, false);
m_inspector->disableStackCapturingIfNeeded();
......@@ -683,6 +676,7 @@ void V8RuntimeAgentImpl::disable(ErrorString* errorString) {
reset();
m_inspector->client()->endEnsureAllContextsInGroup(
m_session->contextGroupId());
return Response::OK();
}
void V8RuntimeAgentImpl::reset() {
......
......@@ -46,7 +46,7 @@ class V8ConsoleMessage;
class V8InspectorImpl;
class V8InspectorSessionImpl;
using protocol::ErrorString;
using protocol::Response;
using protocol::Maybe;
class V8RuntimeAgentImpl : public protocol::Runtime::Backend {
......@@ -57,51 +57,45 @@ class V8RuntimeAgentImpl : public protocol::Runtime::Backend {
void restore();
// Part of the protocol.
void enable(ErrorString*) override;
void disable(ErrorString*) override;
void evaluate(const String16& expression, const Maybe<String16>& objectGroup,
const Maybe<bool>& includeCommandLineAPI,
const Maybe<bool>& silent, const Maybe<int>& executionContextId,
const Maybe<bool>& returnByValue,
const Maybe<bool>& generatePreview,
const Maybe<bool>& userGesture, const Maybe<bool>& awaitPromise,
Response enable() override;
Response disable() override;
void evaluate(const String16& expression, Maybe<String16> objectGroup,
Maybe<bool> includeCommandLineAPI, Maybe<bool> silent,
Maybe<int> executionContextId, Maybe<bool> returnByValue,
Maybe<bool> generatePreview, Maybe<bool> userGesture,
Maybe<bool> awaitPromise,
std::unique_ptr<EvaluateCallback>) override;
void awaitPromise(const String16& promiseObjectId,
const Maybe<bool>& returnByValue,
const Maybe<bool>& generatePreview,
void awaitPromise(const String16& promiseObjectId, Maybe<bool> returnByValue,
Maybe<bool> generatePreview,
std::unique_ptr<AwaitPromiseCallback>) override;
void callFunctionOn(
const String16& objectId, const String16& expression,
const Maybe<protocol::Array<protocol::Runtime::CallArgument>>&
optionalArguments,
const Maybe<bool>& silent, const Maybe<bool>& returnByValue,
const Maybe<bool>& generatePreview, const Maybe<bool>& userGesture,
const Maybe<bool>& awaitPromise,
Maybe<protocol::Array<protocol::Runtime::CallArgument>> optionalArguments,
Maybe<bool> silent, Maybe<bool> returnByValue,
Maybe<bool> generatePreview, Maybe<bool> userGesture,
Maybe<bool> awaitPromise,
std::unique_ptr<CallFunctionOnCallback>) override;
void releaseObject(ErrorString*, const String16& objectId) override;
void getProperties(
ErrorString*, const String16& objectId, const Maybe<bool>& ownProperties,
const Maybe<bool>& accessorPropertiesOnly,
const Maybe<bool>& generatePreview,
Response releaseObject(const String16& objectId) override;
Response getProperties(
const String16& objectId, Maybe<bool> ownProperties,
Maybe<bool> accessorPropertiesOnly, Maybe<bool> generatePreview,
std::unique_ptr<protocol::Array<protocol::Runtime::PropertyDescriptor>>*
result,
Maybe<protocol::Array<protocol::Runtime::InternalPropertyDescriptor>>*
internalProperties,
Maybe<protocol::Runtime::ExceptionDetails>*) override;
void releaseObjectGroup(ErrorString*, const String16& objectGroup) override;
void runIfWaitingForDebugger(ErrorString*) override;
void setCustomObjectFormatterEnabled(ErrorString*, bool) override;
void discardConsoleEntries(ErrorString*) override;
void compileScript(ErrorString*, const String16& expression,
const String16& sourceURL, bool persistScript,
const Maybe<int>& executionContextId, Maybe<String16>*,
Maybe<protocol::Runtime::ExceptionDetails>*) override;
void runScript(const String16&, const Maybe<int>& executionContextId,
const Maybe<String16>& objectGroup, const Maybe<bool>& silent,
const Maybe<bool>& includeCommandLineAPI,
const Maybe<bool>& returnByValue,
const Maybe<bool>& generatePreview,
const Maybe<bool>& awaitPromise,
Response releaseObjectGroup(const String16& objectGroup) override;
Response runIfWaitingForDebugger() override;
Response setCustomObjectFormatterEnabled(bool) override;
Response discardConsoleEntries() override;
Response compileScript(const String16& expression, const String16& sourceURL,
bool persistScript, Maybe<int> executionContextId,
Maybe<String16>*,
Maybe<protocol::Runtime::ExceptionDetails>*) override;
void runScript(const String16&, Maybe<int> executionContextId,
Maybe<String16> objectGroup, Maybe<bool> silent,
Maybe<bool> includeCommandLineAPI, Maybe<bool> returnByValue,
Maybe<bool> generatePreview, Maybe<bool> awaitPromise,
std::unique_ptr<RunScriptCallback>) override;
void reset();
......
......@@ -73,6 +73,96 @@ class V8ValueCopier {
int m_calls;
};
protocol::Response toProtocolValue(v8::Local<v8::Context> context,
v8::Local<v8::Value> value, int maxDepth,
std::unique_ptr<protocol::Value>* result) {
using protocol::Response;
if (value.IsEmpty()) {
UNREACHABLE();
return Response::InternalError();
}
if (!maxDepth) return Response::Error("Object reference chain is too long");
maxDepth--;
if (value->IsNull() || value->IsUndefined()) {
*result = protocol::Value::null();
return Response::OK();
}
if (value->IsBoolean()) {
*result =
protocol::FundamentalValue::create(value.As<v8::Boolean>()->Value());
return Response::OK();
}
if (value->IsNumber()) {
double doubleValue = value.As<v8::Number>()->Value();
int intValue = static_cast<int>(doubleValue);
if (intValue == doubleValue) {
*result = protocol::FundamentalValue::create(intValue);
return Response::OK();
}
*result = protocol::FundamentalValue::create(doubleValue);
return Response::OK();
}
if (value->IsString()) {
*result =
protocol::StringValue::create(toProtocolString(value.As<v8::String>()));
return Response::OK();
}
if (value->IsArray()) {
v8::Local<v8::Array> array = value.As<v8::Array>();
std::unique_ptr<protocol::ListValue> inspectorArray =
protocol::ListValue::create();
uint32_t length = array->Length();
for (uint32_t i = 0; i < length; i++) {
v8::Local<v8::Value> value;
if (!array->Get(context, i).ToLocal(&value))
return Response::InternalError();
std::unique_ptr<protocol::Value> element;
Response response = toProtocolValue(context, value, maxDepth, &element);
if (!response.isSuccess()) return response;
inspectorArray->pushValue(std::move(element));
}
*result = std::move(inspectorArray);
return Response::OK();
}
if (value->IsObject()) {
std::unique_ptr<protocol::DictionaryValue> jsonObject =
protocol::DictionaryValue::create();
v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(value);
v8::Local<v8::Array> propertyNames;
if (!object->GetPropertyNames(context).ToLocal(&propertyNames))
return Response::InternalError();
uint32_t length = propertyNames->Length();
for (uint32_t i = 0; i < length; i++) {
v8::Local<v8::Value> name;
if (!propertyNames->Get(context, i).ToLocal(&name))
return Response::InternalError();
// FIXME(yurys): v8::Object should support GetOwnPropertyNames
if (name->IsString()) {
v8::Maybe<bool> hasRealNamedProperty = object->HasRealNamedProperty(
context, v8::Local<v8::String>::Cast(name));
if (!hasRealNamedProperty.IsJust() || !hasRealNamedProperty.FromJust())
continue;
}
v8::Local<v8::String> propertyName;
if (!name->ToString(context).ToLocal(&propertyName)) continue;
v8::Local<v8::Value> property;
if (!object->Get(context, name).ToLocal(&property))
return Response::InternalError();
std::unique_ptr<protocol::Value> propertyValue;
Response response =
toProtocolValue(context, property, maxDepth, &propertyValue);
if (!response.isSuccess()) return response;
jsonObject->setValue(toProtocolString(propertyName),
std::move(propertyValue));
}
*result = std::move(jsonObject);
return Response::OK();
}
return Response::Error("Object couldn't be returned by value");
}
} // namespace
v8::MaybeLocal<v8::Value> copyValueFromDebuggerContext(
......@@ -107,4 +197,10 @@ v8::Maybe<bool> createDataProperty(v8::Local<v8::Context> context,
return array->CreateDataProperty(context, index, value);
}
protocol::Response toProtocolValue(v8::Local<v8::Context> context,
v8::Local<v8::Value> value,
std::unique_ptr<protocol::Value>* result) {
return toProtocolValue(context, value, 1000, result);
}
} // namespace v8_inspector
......@@ -5,6 +5,8 @@
#ifndef V8_INSPECTOR_V8VALUECOPIER_H_
#define V8_INSPECTOR_V8VALUECOPIER_H_
#include "src/inspector/protocol/Protocol.h"
#include "include/v8.h"
namespace v8_inspector {
......@@ -19,6 +21,9 @@ v8::Maybe<bool> createDataProperty(v8::Local<v8::Context>,
v8::Maybe<bool> createDataProperty(v8::Local<v8::Context>, v8::Local<v8::Array>,
int index, v8::Local<v8::Value>);
protocol::Response toProtocolValue(v8::Local<v8::Context>, v8::Local<v8::Value>,
std::unique_ptr<protocol::Value>* result);
} // namespace v8_inspector
#endif // V8_INSPECTOR_V8VALUECOPIER_H_
......@@ -330,7 +330,7 @@ def resolve_type(protocol, prop):
def new_style(domain):
domains = [ "Schema", "Console", "Profiler", "HeapProfiler" ]
domains = [ "Schema", "Console", "Profiler", "HeapProfiler", "Runtime" ]
return domain["domain"] in domains
......
......@@ -14,5 +14,5 @@ description.
Local modifications:
- This only includes the lib/ and templates/ directories, scripts, build
and the LICENSE files.
- New style domains [ "Schema", "Console", "Profiler", "HeapProfiler" ] are
added in CodeGenerator.py.
\ No newline at end of file
- New style domains [ "Schema", "Console", "Profiler", "HeapProfiler",
"Runtime" ] are added in CodeGenerator.py.
\ No newline at end of file
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