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..6eb6db0e025fd9fd9be1be34f61c6fc2d4da9dc9 100644 |
--- a/third_party/WebKit/Source/platform/v8_inspector/V8RuntimeAgentImpl.cpp |
+++ b/third_party/WebKit/Source/platform/v8_inspector/V8RuntimeAgentImpl.cpp |
@@ -136,6 +136,152 @@ void V8RuntimeAgentImpl::evaluate( |
exceptionDetails); |
} |
+namespace { |
+ |
+class ProtocolPromiseHandler { |
dgozman
2016/07/28 20:16:07
Let's move this to separate file.
kozy
2016/07/28 22:54:09
Rewritten.
|
+ PROTOCOL_DISALLOW_COPY(ProtocolPromiseHandler); |
+public: |
+ ProtocolPromiseHandler(V8DebuggerImpl* debugger, int contextGroupId, const String16& promiseObjectId, std::unique_ptr<V8RuntimeAgentImpl::PromiseThenCallback> callback, bool returnByValue, bool generatePreview) |
dgozman
2016/07/28 20:16:07
protocol::Runtime::Backend::PromiseThenCallback
kozy
2016/07/28 22:54:09
Rewritten.
|
+ : m_debugger(debugger) |
+ , m_contextGroupId(contextGroupId) |
+ , m_promiseObjectId(promiseObjectId) |
+ , m_callback(std::move(callback)) |
+ , m_returnByValue(returnByValue) |
+ , m_generatePreview(generatePreview) |
+ , m_wasCalled(false) |
+ { |
+ } |
+ |
+ ~ProtocolPromiseHandler() |
+ { |
+ if (!m_wasCalled) |
+ m_callback->sendFailure("Promise was collected"); |
+ } |
+ |
+ void handleThen(v8::Local<v8::Value> value) |
+ { |
+ if (m_wasCalled) |
+ return; |
+ m_wasCalled = true; |
+ |
+ std::unique_ptr<protocol::Runtime::RemoteObject> resolvedValue = wrapObject(value); |
+ if (!resolvedValue) |
+ return; |
+ m_callback->sendSuccess(std::move(resolvedValue), Maybe<protocol::Runtime::RemoteObject>()); |
+ } |
+ |
+ void handleCatch(v8::Local<v8::Value> value) |
+ { |
+ if (m_wasCalled) |
+ return; |
+ m_wasCalled = true; |
+ |
+ std::unique_ptr<protocol::Runtime::RemoteObject> rejectedValue = wrapObject(value); |
+ if (!rejectedValue) |
+ return; |
+ m_callback->sendSuccess(Maybe<protocol::Runtime::RemoteObject>(), std::move(rejectedValue)); |
+ } |
+ |
+ void sendFailure(const ErrorString& errorString) |
+ { |
+ if (m_wasCalled) |
+ return; |
+ |
+ m_callback->sendFailure(errorString); |
+ m_wasCalled = true; |
+ } |
+ |
+private: |
+ 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::PromiseThenCallback> m_callback; |
+ bool m_returnByValue; |
+ bool m_generatePreview; |
+ bool m_wasCalled; |
+}; |
+ |
+void thenCallback(const v8::FunctionCallbackInfo<v8::Value>& info) |
+{ |
+ ProtocolPromiseHandler* handler = static_cast<ProtocolPromiseHandler*>(info.Data().As<v8::External>()->Value()); |
+ DCHECK(handler); |
+ handler->handleThen(info.Length() > 0 ? info[0] : v8::Local<v8::Value>::Cast(v8::Undefined(info.GetIsolate()))); |
+} |
+ |
+void catchCallback(const v8::FunctionCallbackInfo<v8::Value>& info) |
+{ |
+ ProtocolPromiseHandler* handler = static_cast<ProtocolPromiseHandler*>(info.Data().As<v8::External>()->Value()); |
+ DCHECK(handler); |
+ handler->handleCatch(info.Length() > 0 ? info[0] : v8::Local<v8::Value>::Cast(v8::Undefined(info.GetIsolate()))); |
+} |
+ |
+template<typename T> |
+void deletePointer(const v8::WeakCallbackInfo<std::pair<v8::Global<v8::External>, T*>>& data) |
+{ |
+ data.GetParameter()->first.Reset(); |
+ delete data.GetParameter()->second; |
+ delete data.GetParameter(); |
+} |
+ |
+template<typename T> |
+v8::Local<v8::External> makeExternal(v8::Isolate* isolate, T* pointer) |
+{ |
+ v8::Local<v8::External> external = v8::External::New(isolate, pointer); |
+ v8::Global<v8::External> externalGlobal(isolate, external); |
+ std::pair<v8::Global<v8::External>, T*>* data = new std::pair<v8::Global<v8::External>, T*>(externalGlobal.Pass(), pointer); |
+ data->first.SetWeak(data, deletePointer, v8::WeakCallbackType::kParameter); |
+ return external; |
+} |
+ |
+} // namespace |
+ |
+void V8RuntimeAgentImpl::promiseThen(ErrorString* errorString, |
+ const String16& promiseObjectId, |
+ const Maybe<bool>& returnByValue, |
+ const Maybe<bool>& generatePreview, |
+ std::unique_ptr<PromiseThenCallback> callback) |
+{ |
+ InjectedScript::ObjectScope scope(errorString, m_debugger, m_session->contextGroupId(), promiseObjectId); |
+ if (!scope.initialize()) |
+ return; |
+ v8::Local<v8::Value> value = scope.object(); |
+ if (!value->IsPromise()) { |
+ callback->sendFailure("Could not find promise with given id"); |
+ return; |
+ } |
+ |
+ v8::Local<v8::Promise> promise = value.As<v8::Promise>(); |
+ ProtocolPromiseHandler* handler = new ProtocolPromiseHandler(m_debugger, m_session->contextGroupId(), promiseObjectId, std::move(callback), returnByValue.fromMaybe(false), generatePreview.fromMaybe(false)); |
+ v8::Local<v8::External> wrappedCallback = makeExternal(m_debugger->isolate(), handler); |
dgozman
2016/07/28 20:16:07
wrappedHandler
kozy
2016/07/28 22:54:09
Rewritten.
|
+ |
+ v8::Local<v8::Function> thenCallbackFunction = v8::Function::New(scope.context(), thenCallback, wrappedCallback, 0, v8::ConstructorBehavior::kThrow).ToLocalChecked(); |
+ if (promise->Then(scope.context(), thenCallbackFunction).IsEmpty()) { |
+ handler->sendFailure("Internal error"); |
+ return; |
+ } |
+ v8::Local<v8::Function> catchCallbackFunction = v8::Function::New(scope.context(), catchCallback, wrappedCallback, 0, v8::ConstructorBehavior::kThrow).ToLocalChecked(); |
+ if (promise->Catch(scope.context(), catchCallbackFunction).IsEmpty()) { |
+ handler->sendFailure("Internal error"); |
+ return; |
+ } |
+} |
+ |
void V8RuntimeAgentImpl::callFunctionOn(ErrorString* errorString, |
const String16& objectId, |
const String16& expression, |