Index: third_party/WebKit/Source/platform/v8_inspector/V8RuntimeAgentImpl.cpp |
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8RuntimeAgentImpl.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8RuntimeAgentImpl.cpp |
index 1f203b094f63583d6ef537fb1f0eac25169c334b..65cdc4e106e7188bffac7e4d55538fad40e6eb10 100644 |
--- a/third_party/WebKit/Source/platform/v8_inspector/V8RuntimeAgentImpl.cpp |
+++ b/third_party/WebKit/Source/platform/v8_inspector/V8RuntimeAgentImpl.cpp |
@@ -37,6 +37,7 @@ |
#include "platform/v8_inspector/V8ConsoleMessage.h" |
#include "platform/v8_inspector/V8DebuggerImpl.h" |
#include "platform/v8_inspector/V8InspectorSessionImpl.h" |
+#include "platform/v8_inspector/V8StackTraceImpl.h" |
#include "platform/v8_inspector/V8StringUtil.h" |
#include "platform/v8_inspector/public/V8DebuggerClient.h" |
@@ -57,6 +58,119 @@ static bool hasInternalError(ErrorString* errorString, bool hasError) |
return hasError; |
} |
+namespace { |
+ |
+class ProtocolPromiseHandler { |
+public: |
+ static void add(V8DebuggerImpl* debugger, int contextGroupId, const String16& promiseObjectId, std::unique_ptr<protocol::Runtime::Backend::AwaitPromiseCallback> callback, bool returnByValue, bool generatePreview) |
+ { |
+ ErrorString errorString; |
+ InjectedScript::ObjectScope scope(&errorString, debugger, contextGroupId, promiseObjectId); |
+ if (!scope.initialize()) { |
+ callback->sendFailure(errorString); |
+ return; |
+ } |
+ if (!scope.object()->IsPromise()) { |
+ callback->sendFailure("Could not find promise with given id"); |
+ return; |
+ } |
+ |
+ protocol::Runtime::Backend::AwaitPromiseCallback* rawCallback = callback.get(); |
+ ProtocolPromiseHandler* handler = new ProtocolPromiseHandler(debugger, contextGroupId, promiseObjectId, std::move(callback), returnByValue, generatePreview); |
+ v8::Local<v8::Value> wrapper = handler->m_wrapper.Get(debugger->isolate()); |
+ v8::Local<v8::Promise> promise = v8::Local<v8::Promise>::Cast(scope.object()); |
+ |
+ v8::Local<v8::Function> thenCallbackFunction = v8::Function::New(scope.context(), thenCallback, wrapper, 0, v8::ConstructorBehavior::kThrow).ToLocalChecked(); |
+ if (promise->Then(scope.context(), thenCallbackFunction).IsEmpty()) { |
+ rawCallback->sendFailure("Internal error"); |
+ return; |
+ } |
+ v8::Local<v8::Function> catchCallbackFunction = v8::Function::New(scope.context(), catchCallback, wrapper, 0, v8::ConstructorBehavior::kThrow).ToLocalChecked(); |
+ if (promise->Catch(scope.context(), catchCallbackFunction).IsEmpty()) { |
+ rawCallback->sendFailure("Internal error"); |
+ return; |
+ } |
+ } |
+ |
+private: |
+ static void thenCallback(const v8::FunctionCallbackInfo<v8::Value>& info) |
+ { |
+ ProtocolPromiseHandler* handler = static_cast<ProtocolPromiseHandler*>(info.Data().As<v8::External>()->Value()); |
+ DCHECK(handler); |
+ v8::Local<v8::Value> value = info.Length() > 0 ? info[0] : v8::Local<v8::Value>::Cast(v8::Undefined(info.GetIsolate())); |
+ handler->m_callback->sendSuccess(handler->wrapObject(value), Maybe<bool>(), Maybe<protocol::Runtime::ExceptionDetails>()); |
+ } |
+ |
+ static void catchCallback(const v8::FunctionCallbackInfo<v8::Value>& info) |
+ { |
+ ProtocolPromiseHandler* handler = static_cast<ProtocolPromiseHandler*>(info.Data().As<v8::External>()->Value()); |
+ DCHECK(handler); |
+ v8::Local<v8::Value> value = info.Length() > 0 ? info[0] : v8::Local<v8::Value>::Cast(v8::Undefined(info.GetIsolate())); |
+ |
+ std::unique_ptr<protocol::Runtime::ExceptionDetails> exceptionDetails; |
+ std::unique_ptr<V8StackTraceImpl> stack = handler->m_debugger->captureStackTraceImpl(true); |
+ if (stack) { |
+ exceptionDetails = protocol::Runtime::ExceptionDetails::create() |
+ .setText("Promise was rejected") |
+ .setLineNumber(!stack->isEmpty() ? stack->topLineNumber() : 0) |
+ .setColumnNumber(!stack->isEmpty() ? stack->topColumnNumber() : 0) |
+ .setScriptId(!stack->isEmpty() ? stack->topScriptId() : String16()) |
+ .setStackTrace(stack->buildInspectorObjectImpl()) |
+ .build(); |
+ } |
+ handler->m_callback->sendSuccess(handler->wrapObject(value), true, std::move(exceptionDetails)); |
+ } |
+ |
+ ProtocolPromiseHandler(V8DebuggerImpl* debugger, int contextGroupId, const String16& promiseObjectId, std::unique_ptr<V8RuntimeAgentImpl::AwaitPromiseCallback> callback, bool returnByValue, bool generatePreview) |
+ : m_debugger(debugger) |
+ , m_contextGroupId(contextGroupId) |
+ , m_promiseObjectId(promiseObjectId) |
+ , m_callback(std::move(callback)) |
+ , m_returnByValue(returnByValue) |
+ , m_generatePreview(generatePreview) |
+ , m_wrapper(debugger->isolate(), v8::External::New(debugger->isolate(), this)) |
+ { |
+ m_wrapper.SetWeak(this, cleanup, v8::WeakCallbackType::kParameter); |
+ } |
+ |
+ static void cleanup(const v8::WeakCallbackInfo<ProtocolPromiseHandler>& data) |
+ { |
+ if (!data.GetParameter()->m_wrapper.IsEmpty()) { |
+ data.GetParameter()->m_wrapper.Reset(); |
+ data.SetSecondPassCallback(cleanup); |
+ } else { |
+ data.GetParameter()->m_callback->sendFailure("Promise was collected"); |
+ delete data.GetParameter(); |
+ } |
+ } |
+ |
+ std::unique_ptr<protocol::Runtime::RemoteObject> wrapObject(v8::Local<v8::Value> value) |
+ { |
+ ErrorString errorString; |
+ InjectedScript::ObjectScope scope(&errorString, m_debugger, m_contextGroupId, m_promiseObjectId); |
+ if (!scope.initialize()) { |
+ m_callback->sendFailure(errorString); |
+ return nullptr; |
+ } |
+ std::unique_ptr<protocol::Runtime::RemoteObject> wrappedValue = scope.injectedScript()->wrapObject(&errorString, value, scope.objectGroupName(), m_returnByValue, m_generatePreview); |
+ if (!wrappedValue) { |
+ m_callback->sendFailure(errorString); |
+ return nullptr; |
+ } |
+ return wrappedValue; |
+ } |
+ |
+ V8DebuggerImpl* m_debugger; |
+ int m_contextGroupId; |
+ String16 m_promiseObjectId; |
+ std::unique_ptr<V8RuntimeAgentImpl::AwaitPromiseCallback> m_callback; |
+ bool m_returnByValue; |
+ bool m_generatePreview; |
+ v8::Global<v8::External> m_wrapper; |
+}; |
+ |
+} // namespace |
+ |
V8RuntimeAgentImpl::V8RuntimeAgentImpl(V8InspectorSessionImpl* session, protocol::FrontendChannel* FrontendChannel, protocol::DictionaryValue* state) |
: m_session(session) |
, m_state(state) |
@@ -136,6 +250,15 @@ void V8RuntimeAgentImpl::evaluate( |
exceptionDetails); |
} |
+void V8RuntimeAgentImpl::awaitPromise(ErrorString* errorString, |
+ const String16& promiseObjectId, |
+ const Maybe<bool>& returnByValue, |
+ const Maybe<bool>& generatePreview, |
+ std::unique_ptr<AwaitPromiseCallback> callback) |
+{ |
+ ProtocolPromiseHandler::add(m_debugger, m_session->contextGroupId(), promiseObjectId, std::move(callback), returnByValue.fromMaybe(false), generatePreview.fromMaybe(false)); |
+} |
+ |
void V8RuntimeAgentImpl::callFunctionOn(ErrorString* errorString, |
const String16& objectId, |
const String16& expression, |