Chromium Code Reviews| 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, |