OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "config.h" | 5 #include "config.h" |
6 #include "core/inspector/PromiseTracker.h" | 6 #include "core/inspector/PromiseTracker.h" |
7 | 7 |
8 #include "bindings/core/v8/ScopedPersistent.h" | 8 #include "bindings/core/v8/ScopedPersistent.h" |
9 #include "bindings/core/v8/ScriptCallStackFactory.h" | 9 #include "bindings/core/v8/ScriptCallStackFactory.h" |
10 #include "bindings/core/v8/ScriptState.h" | 10 #include "bindings/core/v8/ScriptState.h" |
11 #include "wtf/PassOwnPtr.h" | 11 #include "wtf/PassOwnPtr.h" |
12 #include "wtf/WeakPtr.h" | 12 #include "wtf/WeakPtr.h" |
13 | 13 |
14 using blink::TypeBuilder::Array; | 14 using blink::TypeBuilder::Array; |
15 using blink::TypeBuilder::Console::CallFrame; | 15 using blink::TypeBuilder::Console::CallFrame; |
16 using blink::TypeBuilder::Debugger::PromiseDetails; | 16 using blink::TypeBuilder::Debugger::PromiseDetails; |
17 | 17 |
18 namespace blink { | 18 namespace blink { |
19 | 19 |
20 class PromiseTracker::PromiseData : public RefCounted<PromiseData> { | 20 class PromiseTracker::PromiseData FINAL : public RefCountedWillBeGarbageCollecte dFinalized<PromiseData> { |
21 public: | 21 public: |
22 static PassRefPtrWillBeRawPtr<PromiseData> create(v8::Isolate* isolate, int promiseHash, int promiseId, v8::Handle<v8::Object> promise) | |
23 { | |
24 return adoptRefWillBeNoop(new PromiseData(isolate, promiseHash, promiseI d, promise)); | |
25 } | |
26 | |
27 int promiseHash() const { return m_promiseHash; } | |
28 ScopedPersistent<v8::Object>& promise() { return m_promise; } | |
29 | |
30 void trace(Visitor* visitor) | |
31 { | |
32 visitor->trace(m_callStack); | |
33 } | |
34 | |
35 private: | |
36 friend class PromiseTracker; | |
37 | |
22 PromiseData(v8::Isolate* isolate, int promiseHash, int promiseId, v8::Handle <v8::Object> promise) | 38 PromiseData(v8::Isolate* isolate, int promiseHash, int promiseId, v8::Handle <v8::Object> promise) |
23 : m_promiseHash(promiseHash) | 39 : m_promiseHash(promiseHash) |
24 , m_promiseId(promiseId) | 40 , m_promiseId(promiseId) |
25 , m_promise(isolate, promise) | 41 , m_promise(isolate, promise) |
26 , m_parentPromiseId(0) | 42 , m_parentPromiseId(0) |
27 , m_status(0) | 43 , m_status(0) |
44 #if !ENABLE(OILPAN) | |
28 , m_weakPtrFactory(this) | 45 , m_weakPtrFactory(this) |
46 #endif | |
29 { | 47 { |
30 } | 48 } |
31 | 49 |
32 int promiseHash() const { return m_promiseHash; } | |
33 ScopedPersistent<v8::Object>& promise() { return m_promise; } | |
34 | |
35 private: | |
36 friend class PromiseTracker; | |
37 | |
38 int m_promiseHash; | 50 int m_promiseHash; |
39 int m_promiseId; | 51 int m_promiseId; |
40 ScopedPersistent<v8::Object> m_promise; | 52 ScopedPersistent<v8::Object> m_promise; |
41 int m_parentPromiseId; | 53 int m_parentPromiseId; |
42 int m_status; | 54 int m_status; |
55 RefPtrWillBeMember<ScriptCallStack> m_callStack; | |
56 ScopedPersistent<v8::Object> m_parentPromise; | |
57 #if !ENABLE(OILPAN) | |
43 WeakPtrFactory<PromiseData> m_weakPtrFactory; | 58 WeakPtrFactory<PromiseData> m_weakPtrFactory; |
44 RefPtr<ScriptCallStack> m_callStack; | 59 #endif |
45 ScopedPersistent<v8::Object> m_parentPromise; | |
46 }; | 60 }; |
47 | 61 |
48 static int indexOf(PromiseTracker::PromiseDataVector* vector, const ScopedPersis tent<v8::Object>& promise) | 62 static int indexOf(PromiseTracker::PromiseDataVector* vector, const ScopedPersis tent<v8::Object>& promise) |
49 { | 63 { |
50 for (size_t index = 0; index < vector->size(); ++index) { | 64 for (size_t index = 0; index < vector->size(); ++index) { |
51 if (vector->at(index)->promise() == promise) | 65 if (vector->at(index)->promise() == promise) |
52 return index; | 66 return index; |
53 } | 67 } |
54 return -1; | 68 return -1; |
55 } | 69 } |
56 | 70 |
57 namespace { | 71 namespace { |
58 | 72 |
59 class PromiseDataWrapper { | 73 class PromiseDataWrapper FINAL : public NoBaseWillBeGarbageCollected<PromiseData Wrapper> { |
60 public: | 74 public: |
61 PromiseDataWrapper(WeakPtr<PromiseTracker::PromiseData> data, PromiseTracker ::PromiseDataMap* map) | 75 static PassOwnPtrWillBeRawPtr<PromiseDataWrapper> create(PromiseTracker::Pro miseData* data, PromiseTracker::PromiseDataMap* map) |
62 : m_data(data) | |
63 , m_promiseDataMap(map) | |
64 { | 76 { |
77 #if ENABLE(OILPAN) | |
78 return new PromiseDataWrapper(data, map); | |
79 #else | |
80 return adoptPtr(new PromiseDataWrapper(data->m_weakPtrFactory.createWeak Ptr(), map)); | |
81 #endif | |
65 } | 82 } |
66 | 83 |
67 static void didRemovePromise(const v8::WeakCallbackData<v8::Object, PromiseD ataWrapper>& data) | 84 static void didRemovePromise(const v8::WeakCallbackData<v8::Object, PromiseD ataWrapper>& data) |
68 { | 85 { |
69 OwnPtr<PromiseDataWrapper> wrapper = adoptPtr(data.GetParameter()); | 86 OwnPtrWillBeRawPtr<PromiseDataWrapper> wrapper = adoptPtrWillBeNoop(data .GetParameter()); |
70 WeakPtr<PromiseTracker::PromiseData> promiseData = wrapper->m_data; | 87 WeakPtrWillBeRawPtr<PromiseTracker::PromiseData> promiseData = wrapper-> m_data; |
71 if (!promiseData) | 88 if (!promiseData) |
72 return; | 89 return; |
73 PromiseTracker::PromiseDataMap* map = wrapper->m_promiseDataMap; | 90 PromiseTracker::PromiseDataMap* map = wrapper->m_promiseDataMap; |
74 int promiseHash = promiseData->promiseHash(); | 91 int promiseHash = promiseData->promiseHash(); |
75 PromiseTracker::PromiseDataVector* vector = &map->find(promiseHash)->val ue; | 92 PromiseTracker::PromiseDataVector* vector = &map->find(promiseHash)->val ue; |
76 int index = indexOf(vector, promiseData->promise()); | 93 int index = indexOf(vector, promiseData->promise()); |
77 ASSERT(index >= 0); | 94 ASSERT(index >= 0); |
78 vector->remove(index); | 95 vector->remove(index); |
79 if (vector->size() == 0) | 96 if (vector->size() == 0) |
80 map->remove(promiseHash); | 97 map->remove(promiseHash); |
81 } | 98 } |
82 | 99 |
100 void trace(Visitor* visitor) | |
101 { | |
102 visitor->trace(m_data); | |
103 visitor->trace(m_promiseDataMap); | |
104 } | |
105 | |
83 private: | 106 private: |
84 WeakPtr<PromiseTracker::PromiseData> m_data; | 107 PromiseDataWrapper(WeakPtrWillBeRawPtr<PromiseTracker::PromiseData> data, Pr omiseTracker::PromiseDataMap* map) |
85 PromiseTracker::PromiseDataMap* m_promiseDataMap; | 108 : m_data(data) |
109 , m_promiseDataMap(map) | |
110 { | |
111 } | |
112 | |
113 WeakPtrWillBeMember<PromiseTracker::PromiseData> m_data; | |
114 RawPtrWillBeMember<PromiseTracker::PromiseDataMap> m_promiseDataMap; | |
86 }; | 115 }; |
87 | 116 |
88 } | 117 } |
89 | 118 |
90 PromiseTracker::PromiseTracker() | 119 PromiseTracker::PromiseTracker() |
91 : m_isEnabled(false) | 120 : m_isEnabled(false) |
92 , m_circularSequentialId(0) | 121 , m_circularSequentialId(0) |
93 { | 122 { |
94 } | 123 } |
95 | 124 |
96 PromiseTracker::~PromiseTracker() | 125 DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(PromiseTracker); |
126 | |
127 void PromiseTracker::trace(Visitor* visitor) | |
97 { | 128 { |
129 visitor->trace(m_promiseDataMap); | |
98 } | 130 } |
99 | 131 |
100 void PromiseTracker::setEnabled(bool enabled) | 132 void PromiseTracker::setEnabled(bool enabled) |
101 { | 133 { |
102 m_isEnabled = enabled; | 134 m_isEnabled = enabled; |
103 if (!enabled) | 135 if (!enabled) |
104 clear(); | 136 clear(); |
105 } | 137 } |
106 | 138 |
107 void PromiseTracker::clear() | 139 void PromiseTracker::clear() |
108 { | 140 { |
109 m_promiseDataMap.clear(); | 141 m_promiseDataMap.clear(); |
110 } | 142 } |
111 | 143 |
112 int PromiseTracker::circularSequentialId() | 144 int PromiseTracker::circularSequentialId() |
113 { | 145 { |
114 ++m_circularSequentialId; | 146 ++m_circularSequentialId; |
115 if (m_circularSequentialId <= 0) | 147 if (m_circularSequentialId <= 0) |
116 m_circularSequentialId = 1; | 148 m_circularSequentialId = 1; |
117 return m_circularSequentialId; | 149 return m_circularSequentialId; |
118 } | 150 } |
119 | 151 |
120 PassRefPtr<PromiseTracker::PromiseData> PromiseTracker::createPromiseDataIfNeede d(v8::Isolate* isolate, v8::Handle<v8::Object> promise) | 152 PassRefPtrWillBeRawPtr<PromiseTracker::PromiseData> PromiseTracker::createPromis eDataIfNeeded(v8::Isolate* isolate, v8::Handle<v8::Object> promise) |
121 { | 153 { |
122 int promiseHash = promise->GetIdentityHash(); | 154 int promiseHash = promise->GetIdentityHash(); |
123 PromiseDataVector* vector; | 155 RawPtr<PromiseDataVector> vector = nullptr; |
124 PromiseDataMap::iterator it = m_promiseDataMap.find(promiseHash); | 156 PromiseDataMap::iterator it = m_promiseDataMap.find(promiseHash); |
125 if (it != m_promiseDataMap.end()) | 157 if (it != m_promiseDataMap.end()) |
126 vector = &it->value; | 158 vector = &it->value; |
127 else | 159 else |
128 vector = &m_promiseDataMap.add(promiseHash, PromiseDataVector()).storedV alue->value; | 160 vector = &m_promiseDataMap.add(promiseHash, PromiseDataVector()).storedV alue->value; |
129 | 161 |
130 RefPtr<PromiseData> data; | 162 RefPtrWillBeRawPtr<PromiseData> data = nullptr; |
131 int index = indexOf(vector, ScopedPersistent<v8::Object>(isolate, promise)); | 163 int index = indexOf(vector, ScopedPersistent<v8::Object>(isolate, promise)); |
132 if (index == -1) { | 164 if (index == -1) { |
133 data = adoptRef(new PromiseData(isolate, promiseHash, circularSequential Id(), promise)); | 165 data = PromiseData::create(isolate, promiseHash, circularSequentialId(), promise); |
134 OwnPtr<PromiseDataWrapper> wrapper = adoptPtr(new PromiseDataWrapper(dat a->m_weakPtrFactory.createWeakPtr(), &m_promiseDataMap)); | 166 OwnPtrWillBeRawPtr<PromiseDataWrapper> wrapper = PromiseDataWrapper::cre ate(data, &m_promiseDataMap); |
135 data->m_promise.setWeak(wrapper.leakPtr(), &PromiseDataWrapper::didRemov ePromise); | 167 data->m_promise.setWeak(wrapper.leakPtr(), &PromiseDataWrapper::didRemov ePromise); |
sof
2014/09/09 15:37:39
I doubt this is correct, but thought I'd put up th
sof
2014/09/09 18:21:45
It seems consistent with how GCObservation assigns
| |
136 vector->append(data); | 168 vector->append(data); |
137 } else { | 169 } else { |
138 data = vector->at(index); | 170 data = vector->at(index); |
139 } | 171 } |
140 | 172 |
141 return data.release(); | 173 return data.release(); |
142 } | 174 } |
143 | 175 |
144 void PromiseTracker::didReceiveV8PromiseEvent(ScriptState* scriptState, v8::Hand le<v8::Object> promise, v8::Handle<v8::Value> parentPromise, int status) | 176 void PromiseTracker::didReceiveV8PromiseEvent(ScriptState* scriptState, v8::Hand le<v8::Object> promise, v8::Handle<v8::Value> parentPromise, int status) |
145 { | 177 { |
146 ASSERT(isEnabled()); | 178 ASSERT(isEnabled()); |
147 | 179 |
148 v8::Isolate* isolate = scriptState->isolate(); | 180 v8::Isolate* isolate = scriptState->isolate(); |
149 RefPtr<PromiseData> data = createPromiseDataIfNeeded(isolate, promise); | 181 RefPtrWillBeRawPtr<PromiseData> data = createPromiseDataIfNeeded(isolate, pr omise); |
150 if (!parentPromise.IsEmpty() && parentPromise->IsObject()) { | 182 if (!parentPromise.IsEmpty() && parentPromise->IsObject()) { |
151 v8::Handle<v8::Object> handle = parentPromise->ToObject(); | 183 v8::Handle<v8::Object> handle = parentPromise->ToObject(); |
152 RefPtr<PromiseData> parentData = createPromiseDataIfNeeded(isolate, hand le); | 184 RefPtrWillBeRawPtr<PromiseData> parentData = createPromiseDataIfNeeded(i solate, handle); |
153 data->m_parentPromiseId = parentData->m_promiseId; | 185 data->m_parentPromiseId = parentData->m_promiseId; |
154 data->m_parentPromise.set(isolate, handle); | 186 data->m_parentPromise.set(isolate, handle); |
155 } else { | 187 } else { |
156 data->m_status = status; | 188 data->m_status = status; |
157 if (!status && !data->m_callStack) { | 189 if (!status && !data->m_callStack) { |
158 v8::Handle<v8::StackTrace> stackTrace(v8::StackTrace::CurrentStackTr ace(isolate, 1)); | 190 v8::Handle<v8::StackTrace> stackTrace(v8::StackTrace::CurrentStackTr ace(isolate, 1)); |
159 RefPtrWillBeRawPtr<ScriptCallStack> stack = createScriptCallStack(st ackTrace, 1, isolate); | 191 RefPtrWillBeRawPtr<ScriptCallStack> stack = createScriptCallStack(st ackTrace, 1, isolate); |
160 if (stack->size()) | 192 if (stack->size()) |
161 data->m_callStack = stack; | 193 data->m_callStack = stack; |
162 } | 194 } |
163 } | 195 } |
164 } | 196 } |
165 | 197 |
166 PassRefPtr<Array<PromiseDetails> > PromiseTracker::promises() | 198 PassRefPtr<Array<PromiseDetails> > PromiseTracker::promises() |
167 { | 199 { |
168 ASSERT(isEnabled()); | 200 ASSERT(isEnabled()); |
169 | 201 |
170 RefPtr<Array<PromiseDetails> > result = Array<PromiseDetails>::create(); | 202 RefPtr<Array<PromiseDetails> > result = Array<PromiseDetails>::create(); |
171 for (PromiseDataMap::iterator it = m_promiseDataMap.begin(); it != m_promise DataMap.end(); ++it) { | 203 for (PromiseDataMap::iterator it = m_promiseDataMap.begin(); it != m_promise DataMap.end(); ++it) { |
172 PromiseDataVector* vector = &it->value; | 204 PromiseDataVector* vector = &it->value; |
173 for (size_t index = 0; index < vector->size(); ++index) { | 205 for (size_t index = 0; index < vector->size(); ++index) { |
174 RefPtr<PromiseData> data = vector->at(index); | 206 RefPtrWillBeRawPtr<PromiseData> data = vector->at(index); |
175 PromiseDetails::Status::Enum status; | 207 PromiseDetails::Status::Enum status; |
176 if (!data->m_status) | 208 if (!data->m_status) |
177 status = PromiseDetails::Status::Pending; | 209 status = PromiseDetails::Status::Pending; |
178 else if (data->m_status == 1) | 210 else if (data->m_status == 1) |
179 status = PromiseDetails::Status::Resolved; | 211 status = PromiseDetails::Status::Resolved; |
180 else | 212 else |
181 status = PromiseDetails::Status::Rejected; | 213 status = PromiseDetails::Status::Rejected; |
182 RefPtr<PromiseDetails> promiseDetails = PromiseDetails::create() | 214 RefPtr<PromiseDetails> promiseDetails = PromiseDetails::create() |
183 .setId(data->m_promiseId) | 215 .setId(data->m_promiseId) |
184 .setStatus(status); | 216 .setStatus(status); |
185 if (data->m_parentPromiseId) | 217 if (data->m_parentPromiseId) |
186 promiseDetails->setParentId(data->m_parentPromiseId); | 218 promiseDetails->setParentId(data->m_parentPromiseId); |
187 if (data->m_callStack) | 219 if (data->m_callStack) |
188 promiseDetails->setCallFrame(data->m_callStack->at(0).buildInspe ctorObject()); | 220 promiseDetails->setCallFrame(data->m_callStack->at(0).buildInspe ctorObject()); |
189 result->addItem(promiseDetails); | 221 result->addItem(promiseDetails); |
190 } | 222 } |
191 } | 223 } |
192 | 224 |
193 return result.release(); | 225 return result.release(); |
194 } | 226 } |
195 | 227 |
196 } // namespace blink | 228 } // namespace blink |
OLD | NEW |