Chromium Code Reviews| Index: Source/core/inspector/PromiseTracker.cpp |
| diff --git a/Source/core/inspector/PromiseTracker.cpp b/Source/core/inspector/PromiseTracker.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..0b8979e6b3a1c8cd921d560879a29563656ebdaa |
| --- /dev/null |
| +++ b/Source/core/inspector/PromiseTracker.cpp |
| @@ -0,0 +1,153 @@ |
| +// Copyright 2014 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "config.h" |
| +#include "core/inspector/PromiseTracker.h" |
| + |
| +#include "bindings/core/v8/ScriptCallStackFactory.h" |
| +#include "bindings/core/v8/ScriptState.h" |
| + |
| +namespace blink { |
| + |
| +struct PromiseTracker::PromiseDataWrapper { |
|
aandrey
2014/08/04 16:58:47
wrap into an anonymous namespace
Alexandra Mikhaylova
2014/08/06 13:28:39
How can it be compliant with the private method Pr
|
| + WTF_MAKE_NONCOPYABLE(PromiseDataWrapper); |
| +public: |
| + PromiseDataWrapper(WeakPtr<PromiseData> data) |
| + : m_data(data) |
| + { |
| + } |
| + |
| + WeakPtr<PromiseData> m_data; |
| + |
| + static void didRemovePromise(const v8::WeakCallbackData<v8::Object, PromiseDataWrapper>& data) |
| + { |
| + OwnPtr<PromiseDataWrapper> wrapper = adoptPtr(data.GetParameter()); |
| + WeakPtr<PromiseData> promiseData = wrapper->m_data; |
| + if (!(promiseData.get() && promiseData->m_promiseTracker->isEnabled())) |
|
aandrey
2014/08/04 16:58:48
if (!promiseData)
return;
PromiseTracker* trac
Alexandra Mikhaylova
2014/08/06 13:28:39
Done.
|
| + return; |
| + |
| + promiseData->m_promiseTracker->didRemovePromise(promiseData->m_scriptState.get(), promiseData->m_promise); |
| + } |
| +}; |
| + |
| +PromiseTracker::PromiseData::PromiseData(const ScopedPersistent<v8::Object>& promise, const ScopedPersistent<v8::Object>& parentPromise, int status, ScriptState* scriptState, PromiseTracker* tracker, bool captureStack) |
| + : m_scriptState(scriptState) |
| + , m_promiseTracker(tracker) |
| + , m_promise(scriptState->isolate(), promise.newLocal(scriptState->isolate())) |
|
aandrey
2014/08/04 16:58:48
make copy constructor on ScopedPersistent
Alexandra Mikhaylova
2014/08/06 13:28:39
Switched back to v8::Handle instead.
|
| + , m_parentPromise(scriptState->isolate(), parentPromise.newLocal(scriptState->isolate())) |
| + , m_status(status) |
| + , m_weakPtrFactory(this) |
| +{ |
| + if (captureStack) { |
| + v8::Isolate* isolate = scriptState->isolate(); |
| + v8::Handle<v8::StackTrace> stackTrace(v8::StackTrace::CurrentStackTrace(isolate, 1)); |
| + RefPtrWillBeRawPtr<ScriptCallStack> stack = createScriptCallStack(stackTrace, 1, isolate); |
| + if (stack->size()) |
| + m_callFrame = stack->at(0); |
| + } |
| + PromiseDataWrapper* wrapper = new PromiseDataWrapper(m_weakPtrFactory.createWeakPtr()); |
| + m_promise.setWeak(wrapper, &PromiseTracker::PromiseDataWrapper::didRemovePromise); |
| +} |
| + |
| +void PromiseTracker::enable() |
| +{ |
| + m_isEnabled = true; |
| +} |
| + |
| +void PromiseTracker::disable() |
| +{ |
| + m_isEnabled = false; |
| + clear(); |
| +} |
| + |
| +void PromiseTracker::clear() |
| +{ |
| + m_promiseDataMap.clear(); |
| +} |
| + |
| +PromiseTracker::PromiseDataVector* PromiseTracker::promiseVector(ScriptState* scriptState, const ScopedPersistent<v8::Object>& promise) |
| +{ |
| + ASSERT(isEnabled()); |
| + |
| + int promiseHash = promise.newLocal(scriptState->isolate())->GetIdentityHash(); |
| + PromiseDataMap::iterator it = m_promiseDataMap.find(promiseHash); |
| + if (it != m_promiseDataMap.end()) |
| + return &it->value; |
| + return &m_promiseDataMap.add(promiseHash, PromiseDataVector()).storedValue->value; |
| +} |
| + |
| +void PromiseTracker::didReceiveV8PromiseEvent(ScriptState* scriptState, const ScopedPersistent<v8::Object>& promise, const ScopedPersistent<v8::Object>& parentPromise, int status) |
| +{ |
| + ASSERT(isEnabled()); |
| + |
| + if (status != 0) { |
| + didUpdatePromiseStatus(scriptState, promise, status); |
| + } else if (!parentPromise.isEmpty()) { |
| + didUpdatePromiseParent(scriptState, promise, parentPromise); |
| + } else { |
| + didCreatePromise(scriptState, promise); |
| + } |
| +} |
| + |
| +void PromiseTracker::didCreatePromise(ScriptState* scriptState, const ScopedPersistent<v8::Object>& promise) |
| +{ |
| + PromiseDataVector* vector = promiseVector(scriptState, promise); |
| + vector->append(adoptRef(new PromiseData(promise, ScopedPersistent<v8::Object>(), 0, scriptState, this, true))); |
| +} |
| + |
| +void PromiseTracker::didUpdatePromiseParent(ScriptState* scriptState, const ScopedPersistent<v8::Object>& promise, const ScopedPersistent<v8::Object>& parentPromise) |
| +{ |
| + PromiseDataVector* vector = promiseVector(scriptState, promise); |
| + bool found = false; |
| + for (size_t index = 0; index < vector->size(); ++index) { |
| + RefPtr<PromiseData> data = (*vector)[index]; |
|
aandrey
2014/08/04 16:58:48
vector->at(index)
Alexandra Mikhaylova
2014/08/06 13:28:39
Done.
|
| + if (data->m_promise == promise) { |
| + found = true; |
| + v8::Isolate* isolate = scriptState->isolate(); |
| + data->m_parentPromise.set(isolate, parentPromise.newLocal(isolate)); |
|
aandrey
2014/08/04 16:58:48
should be no newLocal() call
Alexandra Mikhaylova
2014/08/06 13:28:39
Done.
|
| + break; |
| + } |
| + } |
| + if (!found) |
| + vector->append(adoptRef(new PromiseData(promise, parentPromise, 0, scriptState, this))); |
| +} |
| + |
| +void PromiseTracker::didUpdatePromiseStatus(ScriptState* scriptState, const ScopedPersistent<v8::Object>& promise, int status) |
| +{ |
| + PromiseDataVector* vector = promiseVector(scriptState, promise); |
| + bool found = false; |
| + for (size_t index = 0; index < vector->size(); ++index) { |
| + RefPtr<PromiseData> data = (*vector)[index]; |
| + if (data->m_promise == promise) { |
| + found = true; |
| + data->m_status = status; |
| + break; |
| + } |
| + } |
| + if (!found) |
| + vector->append(adoptRef(new PromiseData(promise, ScopedPersistent<v8::Object>(), status, scriptState, this))); |
| +} |
| + |
| +void PromiseTracker::didRemovePromise(ScriptState* scriptState, ScopedPersistent<v8::Object>& promise) |
| +{ |
| + ASSERT(isEnabled()); |
| + |
| + int promiseHash = promise.newLocal(scriptState->isolate())->GetIdentityHash(); |
|
aandrey
2014/08/04 16:58:48
we can remove m_scriptState if we cache the identi
Alexandra Mikhaylova
2014/08/06 13:28:39
Done.
|
| + |
| + PromiseDataVector* vector = promiseVector(scriptState, promise); |
| + ASSERT(vector->size() >= 1); |
| + bool found = false; |
| + for (size_t index = 0; index < vector->size(); ++index) { |
| + RefPtr<PromiseData> data = (*vector)[index]; |
| + if (data->m_promise == promise) { |
| + found = true; |
| + vector->remove(index); |
|
aandrey
2014/08/04 16:58:48
too much code duplication
|
| + break; |
| + } |
| + } |
| + if (vector->size() == 0) |
| + m_promiseDataMap.remove(promiseHash); |
| +} |
| + |
| +} // namespace blink |