OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "bindings/core/v8/RejectedPromises.h" | 5 #include "bindings/core/v8/RejectedPromises.h" |
6 | 6 |
7 #include "bindings/core/v8/ScopedPersistent.h" | 7 #include "bindings/core/v8/ScopedPersistent.h" |
8 #include "bindings/core/v8/ScriptState.h" | 8 #include "bindings/core/v8/ScriptState.h" |
9 #include "bindings/core/v8/ScriptValue.h" | 9 #include "bindings/core/v8/ScriptValue.h" |
10 #include "bindings/core/v8/V8Binding.h" | 10 #include "bindings/core/v8/V8Binding.h" |
11 #include "core/dom/ExecutionContext.h" | 11 #include "core/dom/ExecutionContext.h" |
12 #include "core/events/EventTarget.h" | 12 #include "core/events/EventTarget.h" |
13 #include "core/events/PromiseRejectionEvent.h" | 13 #include "core/events/PromiseRejectionEvent.h" |
14 #include "core/inspector/ConsoleMessage.h" | 14 #include "core/inspector/ConsoleMessage.h" |
15 #include "core/inspector/ScriptArguments.h" | 15 #include "core/inspector/ScriptArguments.h" |
16 #include "platform/RuntimeEnabledFeatures.h" | 16 #include "platform/RuntimeEnabledFeatures.h" |
17 #include "public/platform/Platform.h" | 17 #include "public/platform/Platform.h" |
18 #include "public/platform/WebScheduler.h" | 18 #include "public/platform/WebScheduler.h" |
19 #include "public/platform/WebTaskRunner.h" | 19 #include "public/platform/WebTaskRunner.h" |
20 #include "public/platform/WebThread.h" | 20 #include "public/platform/WebThread.h" |
21 #include "wtf/Functional.h" | 21 #include "wtf/Functional.h" |
22 #include "wtf/PtrUtil.h" | |
23 #include <memory> | |
24 | 22 |
25 namespace blink { | 23 namespace blink { |
26 | 24 |
27 static const unsigned maxReportedHandlersPendingResolution = 1000; | 25 static const unsigned maxReportedHandlersPendingResolution = 1000; |
28 | 26 |
29 class RejectedPromises::Message final { | 27 class RejectedPromises::Message final { |
30 public: | 28 public: |
31 static std::unique_ptr<Message> create(ScriptState* scriptState, v8::Local<v
8::Promise> promise, v8::Local<v8::Value> exception, const String& errorMessage,
std::unique_ptr<SourceLocation> location, AccessControlStatus corsStatus) | 29 static PassOwnPtr<Message> create(ScriptState* scriptState, v8::Local<v8::Pr
omise> promise, v8::Local<v8::Value> exception, const String& errorMessage, Pass
OwnPtr<SourceLocation> location, AccessControlStatus corsStatus) |
32 { | 30 { |
33 return wrapUnique(new Message(scriptState, promise, exception, errorMess
age, std::move(location), corsStatus)); | 31 return adoptPtr(new Message(scriptState, promise, exception, errorMessag
e, std::move(location), corsStatus)); |
34 } | 32 } |
35 | 33 |
36 bool isCollected() | 34 bool isCollected() |
37 { | 35 { |
38 return m_collected || !m_scriptState->contextIsValid(); | 36 return m_collected || !m_scriptState->contextIsValid(); |
39 } | 37 } |
40 | 38 |
41 bool hasPromise(v8::Local<v8::Value> promise) | 39 bool hasPromise(v8::Local<v8::Value> promise) |
42 { | 40 { |
43 ScriptState::Scope scope(m_scriptState); | 41 ScriptState::Scope scope(m_scriptState); |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
140 | 138 |
141 bool hasHandler() | 139 bool hasHandler() |
142 { | 140 { |
143 ASSERT(!isCollected()); | 141 ASSERT(!isCollected()); |
144 ScriptState::Scope scope(m_scriptState); | 142 ScriptState::Scope scope(m_scriptState); |
145 v8::Local<v8::Value> value = m_promise.newLocal(m_scriptState->isolate()
); | 143 v8::Local<v8::Value> value = m_promise.newLocal(m_scriptState->isolate()
); |
146 return v8::Local<v8::Promise>::Cast(value)->HasHandler(); | 144 return v8::Local<v8::Promise>::Cast(value)->HasHandler(); |
147 } | 145 } |
148 | 146 |
149 private: | 147 private: |
150 Message(ScriptState* scriptState, v8::Local<v8::Promise> promise, v8::Local<
v8::Value> exception, const String& errorMessage, std::unique_ptr<SourceLocation
> location, AccessControlStatus corsStatus) | 148 Message(ScriptState* scriptState, v8::Local<v8::Promise> promise, v8::Local<
v8::Value> exception, const String& errorMessage, PassOwnPtr<SourceLocation> loc
ation, AccessControlStatus corsStatus) |
151 : m_scriptState(scriptState) | 149 : m_scriptState(scriptState) |
152 , m_promise(scriptState->isolate(), promise) | 150 , m_promise(scriptState->isolate(), promise) |
153 , m_exception(scriptState->isolate(), exception) | 151 , m_exception(scriptState->isolate(), exception) |
154 , m_errorMessage(errorMessage) | 152 , m_errorMessage(errorMessage) |
155 , m_resourceName(location->url()) | 153 , m_resourceName(location->url()) |
156 , m_location(std::move(location)) | 154 , m_location(std::move(location)) |
157 , m_consoleMessageId(0) | 155 , m_consoleMessageId(0) |
158 , m_collected(false) | 156 , m_collected(false) |
159 , m_shouldLogToConsole(true) | 157 , m_shouldLogToConsole(true) |
160 , m_corsStatus(corsStatus) | 158 , m_corsStatus(corsStatus) |
161 { | 159 { |
162 } | 160 } |
163 | 161 |
164 static void didCollectPromise(const v8::WeakCallbackInfo<Message>& data) | 162 static void didCollectPromise(const v8::WeakCallbackInfo<Message>& data) |
165 { | 163 { |
166 data.GetParameter()->m_collected = true; | 164 data.GetParameter()->m_collected = true; |
167 data.GetParameter()->m_promise.clear(); | 165 data.GetParameter()->m_promise.clear(); |
168 } | 166 } |
169 | 167 |
170 static void didCollectException(const v8::WeakCallbackInfo<Message>& data) | 168 static void didCollectException(const v8::WeakCallbackInfo<Message>& data) |
171 { | 169 { |
172 data.GetParameter()->m_exception.clear(); | 170 data.GetParameter()->m_exception.clear(); |
173 } | 171 } |
174 | 172 |
175 ScriptState* m_scriptState; | 173 ScriptState* m_scriptState; |
176 ScopedPersistent<v8::Promise> m_promise; | 174 ScopedPersistent<v8::Promise> m_promise; |
177 ScopedPersistent<v8::Value> m_exception; | 175 ScopedPersistent<v8::Value> m_exception; |
178 String m_errorMessage; | 176 String m_errorMessage; |
179 String m_resourceName; | 177 String m_resourceName; |
180 std::unique_ptr<SourceLocation> m_location; | 178 OwnPtr<SourceLocation> m_location; |
181 unsigned m_consoleMessageId; | 179 unsigned m_consoleMessageId; |
182 bool m_collected; | 180 bool m_collected; |
183 bool m_shouldLogToConsole; | 181 bool m_shouldLogToConsole; |
184 AccessControlStatus m_corsStatus; | 182 AccessControlStatus m_corsStatus; |
185 }; | 183 }; |
186 | 184 |
187 RejectedPromises::RejectedPromises() | 185 RejectedPromises::RejectedPromises() |
188 { | 186 { |
189 } | 187 } |
190 | 188 |
191 RejectedPromises::~RejectedPromises() | 189 RejectedPromises::~RejectedPromises() |
192 { | 190 { |
193 } | 191 } |
194 | 192 |
195 void RejectedPromises::rejectedWithNoHandler(ScriptState* scriptState, v8::Promi
seRejectMessage data, const String& errorMessage, std::unique_ptr<SourceLocation
> location, AccessControlStatus corsStatus) | 193 void RejectedPromises::rejectedWithNoHandler(ScriptState* scriptState, v8::Promi
seRejectMessage data, const String& errorMessage, PassOwnPtr<SourceLocation> loc
ation, AccessControlStatus corsStatus) |
196 { | 194 { |
197 m_queue.append(Message::create(scriptState, data.GetPromise(), data.GetValue
(), errorMessage, std::move(location), corsStatus)); | 195 m_queue.append(Message::create(scriptState, data.GetPromise(), data.GetValue
(), errorMessage, std::move(location), corsStatus)); |
198 } | 196 } |
199 | 197 |
200 void RejectedPromises::handlerAdded(v8::PromiseRejectMessage data) | 198 void RejectedPromises::handlerAdded(v8::PromiseRejectMessage data) |
201 { | 199 { |
202 // First look it up in the pending messages and fast return, it'll be covere
d by processQueue(). | 200 // First look it up in the pending messages and fast return, it'll be covere
d by processQueue(). |
203 for (auto it = m_queue.begin(); it != m_queue.end(); ++it) { | 201 for (auto it = m_queue.begin(); it != m_queue.end(); ++it) { |
204 if (!(*it)->isCollected() && (*it)->hasPromise(data.GetPromise())) { | 202 if (!(*it)->isCollected() && (*it)->hasPromise(data.GetPromise())) { |
205 m_queue.remove(it); | 203 m_queue.remove(it); |
206 return; | 204 return; |
207 } | 205 } |
208 } | 206 } |
209 | 207 |
210 // Then look it up in the reported errors. | 208 // Then look it up in the reported errors. |
211 for (size_t i = 0; i < m_reportedAsErrors.size(); ++i) { | 209 for (size_t i = 0; i < m_reportedAsErrors.size(); ++i) { |
212 std::unique_ptr<Message>& message = m_reportedAsErrors.at(i); | 210 OwnPtr<Message>& message = m_reportedAsErrors.at(i); |
213 if (!message->isCollected() && message->hasPromise(data.GetPromise())) { | 211 if (!message->isCollected() && message->hasPromise(data.GetPromise())) { |
214 message->makePromiseStrong(); | 212 message->makePromiseStrong(); |
215 Platform::current()->currentThread()->scheduler()->timerTaskRunner()
->postTask(BLINK_FROM_HERE, WTF::bind(&RejectedPromises::revokeNow, this, passed
(std::move(message)))); | 213 Platform::current()->currentThread()->scheduler()->timerTaskRunner()
->postTask(BLINK_FROM_HERE, bind(&RejectedPromises::revokeNow, this, passed(std:
:move(message)))); |
216 m_reportedAsErrors.remove(i); | 214 m_reportedAsErrors.remove(i); |
217 return; | 215 return; |
218 } | 216 } |
219 } | 217 } |
220 } | 218 } |
221 | 219 |
222 std::unique_ptr<RejectedPromises::MessageQueue> RejectedPromises::createMessageQ
ueue() | 220 PassOwnPtr<RejectedPromises::MessageQueue> RejectedPromises::createMessageQueue(
) |
223 { | 221 { |
224 return wrapUnique(new MessageQueue()); | 222 return adoptPtr(new MessageQueue()); |
225 } | 223 } |
226 | 224 |
227 void RejectedPromises::dispose() | 225 void RejectedPromises::dispose() |
228 { | 226 { |
229 if (m_queue.isEmpty()) | 227 if (m_queue.isEmpty()) |
230 return; | 228 return; |
231 | 229 |
232 std::unique_ptr<MessageQueue> queue = createMessageQueue(); | 230 OwnPtr<MessageQueue> queue = createMessageQueue(); |
233 queue->swap(m_queue); | 231 queue->swap(m_queue); |
234 processQueueNow(std::move(queue)); | 232 processQueueNow(std::move(queue)); |
235 } | 233 } |
236 | 234 |
237 void RejectedPromises::processQueue() | 235 void RejectedPromises::processQueue() |
238 { | 236 { |
239 if (m_queue.isEmpty()) | 237 if (m_queue.isEmpty()) |
240 return; | 238 return; |
241 | 239 |
242 std::unique_ptr<MessageQueue> queue = createMessageQueue(); | 240 OwnPtr<MessageQueue> queue = createMessageQueue(); |
243 queue->swap(m_queue); | 241 queue->swap(m_queue); |
244 Platform::current()->currentThread()->scheduler()->timerTaskRunner()->postTa
sk(BLINK_FROM_HERE, WTF::bind(&RejectedPromises::processQueueNow, PassRefPtr<Rej
ectedPromises>(this), passed(std::move(queue)))); | 242 Platform::current()->currentThread()->scheduler()->timerTaskRunner()->postTa
sk(BLINK_FROM_HERE, bind(&RejectedPromises::processQueueNow, PassRefPtr<Rejected
Promises>(this), passed(std::move(queue)))); |
245 } | 243 } |
246 | 244 |
247 void RejectedPromises::processQueueNow(std::unique_ptr<MessageQueue> queue) | 245 void RejectedPromises::processQueueNow(PassOwnPtr<MessageQueue> queue) |
248 { | 246 { |
249 // Remove collected handlers. | 247 // Remove collected handlers. |
250 for (size_t i = 0; i < m_reportedAsErrors.size();) { | 248 for (size_t i = 0; i < m_reportedAsErrors.size();) { |
251 if (m_reportedAsErrors.at(i)->isCollected()) | 249 if (m_reportedAsErrors.at(i)->isCollected()) |
252 m_reportedAsErrors.remove(i); | 250 m_reportedAsErrors.remove(i); |
253 else | 251 else |
254 ++i; | 252 ++i; |
255 } | 253 } |
256 | 254 |
257 while (!queue->isEmpty()) { | 255 while (!queue->isEmpty()) { |
258 std::unique_ptr<Message> message = queue->takeFirst(); | 256 OwnPtr<Message> message = queue->takeFirst(); |
259 if (message->isCollected()) | 257 if (message->isCollected()) |
260 continue; | 258 continue; |
261 if (!message->hasHandler()) { | 259 if (!message->hasHandler()) { |
262 message->report(); | 260 message->report(); |
263 message->makePromiseWeak(); | 261 message->makePromiseWeak(); |
264 m_reportedAsErrors.append(std::move(message)); | 262 m_reportedAsErrors.append(std::move(message)); |
265 if (m_reportedAsErrors.size() > maxReportedHandlersPendingResolution
) | 263 if (m_reportedAsErrors.size() > maxReportedHandlersPendingResolution
) |
266 m_reportedAsErrors.remove(0, maxReportedHandlersPendingResolutio
n / 10); | 264 m_reportedAsErrors.remove(0, maxReportedHandlersPendingResolutio
n / 10); |
267 } | 265 } |
268 } | 266 } |
269 } | 267 } |
270 | 268 |
271 void RejectedPromises::revokeNow(std::unique_ptr<Message> message) | 269 void RejectedPromises::revokeNow(PassOwnPtr<Message> message) |
272 { | 270 { |
273 message->revoke(); | 271 message->revoke(); |
274 } | 272 } |
275 | 273 |
276 } // namespace blink | 274 } // namespace blink |
OLD | NEW |