| 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 "platform/Task.h" | 17 #include "platform/Task.h" |
| 18 #include "public/platform/Platform.h" | 18 #include "public/platform/Platform.h" |
| 19 #include "public/platform/WebScheduler.h" | 19 #include "public/platform/WebScheduler.h" |
| 20 #include "public/platform/WebTaskRunner.h" | 20 #include "public/platform/WebTaskRunner.h" |
| 21 #include "public/platform/WebThread.h" | 21 #include "public/platform/WebThread.h" |
| 22 #include "wtf/Functional.h" | 22 #include "wtf/Functional.h" |
| 23 | 23 |
| 24 namespace blink { | 24 namespace blink { |
| 25 | 25 |
| 26 static const unsigned maxReportedHandlersPendingResolution = 1000; | 26 static const unsigned maxReportedHandlersPendingResolution = 1000; |
| 27 | 27 |
| 28 class RejectedPromises::Message final : public NoBaseWillBeGarbageCollectedFinal
ized<RejectedPromises::Message> { | 28 class RejectedPromises::Message final { |
| 29 public: | 29 public: |
| 30 static PassOwnPtrWillBeRawPtr<Message> create(ScriptState* scriptState, v8::
Local<v8::Promise> promise, v8::Local<v8::Value> exception, const String& errorM
essage, const String& resourceName, int scriptId, int lineNumber, int columnNumb
er, PassRefPtrWillBeRawPtr<ScriptCallStack> callStack, AccessControlStatus corsS
tatus) | 30 static PassOwnPtr<Message> create(ScriptState* scriptState, v8::Local<v8::Pr
omise> promise, v8::Local<v8::Value> exception, const String& errorMessage, cons
t String& resourceName, int scriptId, int lineNumber, int columnNumber, PassRefP
tr<ScriptCallStack> callStack, AccessControlStatus corsStatus) |
| 31 { | 31 { |
| 32 return adoptPtrWillBeNoop(new Message(scriptState, promise, exception, e
rrorMessage, resourceName, scriptId, lineNumber, columnNumber, callStack, corsSt
atus)); | 32 return adoptPtr(new Message(scriptState, promise, exception, errorMessag
e, resourceName, scriptId, lineNumber, columnNumber, callStack, corsStatus)); |
| 33 } | |
| 34 | |
| 35 DEFINE_INLINE_TRACE() | |
| 36 { | |
| 37 visitor->trace(m_callStack); | |
| 38 } | 33 } |
| 39 | 34 |
| 40 bool isCollected() | 35 bool isCollected() |
| 41 { | 36 { |
| 42 return m_collected || !m_scriptState->contextIsValid(); | 37 return m_collected || !m_scriptState->contextIsValid(); |
| 43 } | 38 } |
| 44 | 39 |
| 45 bool hasPromise(v8::Local<v8::Value> promise) | 40 bool hasPromise(v8::Local<v8::Value> promise) |
| 46 { | 41 { |
| 47 ScriptState::Scope scope(m_scriptState); | 42 ScriptState::Scope scope(m_scriptState); |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 147 | 142 |
| 148 bool hasHandler() | 143 bool hasHandler() |
| 149 { | 144 { |
| 150 ASSERT(!isCollected()); | 145 ASSERT(!isCollected()); |
| 151 ScriptState::Scope scope(m_scriptState); | 146 ScriptState::Scope scope(m_scriptState); |
| 152 v8::Local<v8::Value> value = m_promise.newLocal(m_scriptState->isolate()
); | 147 v8::Local<v8::Value> value = m_promise.newLocal(m_scriptState->isolate()
); |
| 153 return v8::Local<v8::Promise>::Cast(value)->HasHandler(); | 148 return v8::Local<v8::Promise>::Cast(value)->HasHandler(); |
| 154 } | 149 } |
| 155 | 150 |
| 156 private: | 151 private: |
| 157 Message(ScriptState* scriptState, v8::Local<v8::Promise> promise, v8::Local<
v8::Value> exception, const String& errorMessage, const String& resourceName, in
t scriptId, int lineNumber, int columnNumber, PassRefPtrWillBeRawPtr<ScriptCallS
tack> callStack, AccessControlStatus corsStatus) | 152 Message(ScriptState* scriptState, v8::Local<v8::Promise> promise, v8::Local<
v8::Value> exception, const String& errorMessage, const String& resourceName, in
t scriptId, int lineNumber, int columnNumber, PassRefPtr<ScriptCallStack> callSt
ack, AccessControlStatus corsStatus) |
| 158 : m_scriptState(scriptState) | 153 : m_scriptState(scriptState) |
| 159 , m_promise(scriptState->isolate(), promise) | 154 , m_promise(scriptState->isolate(), promise) |
| 160 , m_exception(scriptState->isolate(), exception) | 155 , m_exception(scriptState->isolate(), exception) |
| 161 , m_errorMessage(errorMessage) | 156 , m_errorMessage(errorMessage) |
| 162 , m_resourceName(resourceName) | 157 , m_resourceName(resourceName) |
| 163 , m_scriptId(scriptId) | 158 , m_scriptId(scriptId) |
| 164 , m_lineNumber(lineNumber) | 159 , m_lineNumber(lineNumber) |
| 165 , m_columnNumber(columnNumber) | 160 , m_columnNumber(columnNumber) |
| 166 , m_callStack(callStack) | 161 , m_callStack(callStack) |
| 167 , m_consoleMessageId(0) | 162 , m_consoleMessageId(0) |
| (...skipping 15 matching lines...) Expand all Loading... |
| 183 } | 178 } |
| 184 | 179 |
| 185 ScriptState* m_scriptState; | 180 ScriptState* m_scriptState; |
| 186 ScopedPersistent<v8::Promise> m_promise; | 181 ScopedPersistent<v8::Promise> m_promise; |
| 187 ScopedPersistent<v8::Value> m_exception; | 182 ScopedPersistent<v8::Value> m_exception; |
| 188 String m_errorMessage; | 183 String m_errorMessage; |
| 189 String m_resourceName; | 184 String m_resourceName; |
| 190 int m_scriptId; | 185 int m_scriptId; |
| 191 int m_lineNumber; | 186 int m_lineNumber; |
| 192 int m_columnNumber; | 187 int m_columnNumber; |
| 193 RefPtrWillBeMember<ScriptCallStack> m_callStack; | 188 RefPtr<ScriptCallStack> m_callStack; |
| 194 unsigned m_consoleMessageId; | 189 unsigned m_consoleMessageId; |
| 195 bool m_collected; | 190 bool m_collected; |
| 196 bool m_shouldLogToConsole; | 191 bool m_shouldLogToConsole; |
| 197 AccessControlStatus m_corsStatus; | 192 AccessControlStatus m_corsStatus; |
| 198 }; | 193 }; |
| 199 | 194 |
| 200 RejectedPromises::RejectedPromises() | 195 RejectedPromises::RejectedPromises() |
| 201 { | 196 { |
| 202 } | 197 } |
| 203 | 198 |
| 204 DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(RejectedPromises); | 199 RejectedPromises::~RejectedPromises() |
| 205 | |
| 206 DEFINE_TRACE(RejectedPromises) | |
| 207 { | 200 { |
| 208 visitor->trace(m_queue); | |
| 209 visitor->trace(m_reportedAsErrors); | |
| 210 } | 201 } |
| 211 | 202 |
| 212 void RejectedPromises::rejectedWithNoHandler(ScriptState* scriptState, v8::Promi
seRejectMessage data, const String& errorMessage, const String& resourceName, in
t scriptId, int lineNumber, int columnNumber, PassRefPtrWillBeRawPtr<ScriptCallS
tack> callStack, AccessControlStatus corsStatus) | 203 void RejectedPromises::rejectedWithNoHandler(ScriptState* scriptState, v8::Promi
seRejectMessage data, const String& errorMessage, const String& resourceName, in
t scriptId, int lineNumber, int columnNumber, PassRefPtr<ScriptCallStack> callSt
ack, AccessControlStatus corsStatus) |
| 213 { | 204 { |
| 214 m_queue.append(Message::create(scriptState, data.GetPromise(), data.GetValue
(), errorMessage, resourceName, scriptId, lineNumber, columnNumber, callStack, c
orsStatus)); | 205 m_queue.append(Message::create(scriptState, data.GetPromise(), data.GetValue
(), errorMessage, resourceName, scriptId, lineNumber, columnNumber, callStack, c
orsStatus)); |
| 215 } | 206 } |
| 216 | 207 |
| 217 void RejectedPromises::handlerAdded(v8::PromiseRejectMessage data) | 208 void RejectedPromises::handlerAdded(v8::PromiseRejectMessage data) |
| 218 { | 209 { |
| 219 // First look it up in the pending messages and fast return, it'll be covere
d by processQueue(). | 210 // First look it up in the pending messages and fast return, it'll be covere
d by processQueue(). |
| 220 for (auto it = m_queue.begin(); it != m_queue.end(); ++it) { | 211 for (auto it = m_queue.begin(); it != m_queue.end(); ++it) { |
| 221 if (!(*it)->isCollected() && (*it)->hasPromise(data.GetPromise())) { | 212 if (!(*it)->isCollected() && (*it)->hasPromise(data.GetPromise())) { |
| 222 m_queue.remove(it); | 213 m_queue.remove(it); |
| 223 return; | 214 return; |
| 224 } | 215 } |
| 225 } | 216 } |
| 226 | 217 |
| 227 // Then look it up in the reported errors. | 218 // Then look it up in the reported errors. |
| 228 for (size_t i = 0; i < m_reportedAsErrors.size(); ++i) { | 219 for (size_t i = 0; i < m_reportedAsErrors.size(); ++i) { |
| 229 auto& message = m_reportedAsErrors.at(i); | 220 auto& message = m_reportedAsErrors.at(i); |
| 230 if (!message->isCollected() && message->hasPromise(data.GetPromise())) { | 221 if (!message->isCollected() && message->hasPromise(data.GetPromise())) { |
| 231 message->makePromiseStrong(); | 222 message->makePromiseStrong(); |
| 232 Platform::current()->currentThread()->scheduler()->timerTaskRunner()
->postTask(BLINK_FROM_HERE, new Task(bind(&RejectedPromises::revokeNow, PassRefP
trWillBeRawPtr<RejectedPromises>(this), message.release()))); | 223 Platform::current()->currentThread()->scheduler()->timerTaskRunner()
->postTask(BLINK_FROM_HERE, new Task(bind(&RejectedPromises::revokeNow, PassRefP
trWillBeRawPtr<RejectedPromises>(this), message.release()))); |
| 233 m_reportedAsErrors.remove(i); | 224 m_reportedAsErrors.remove(i); |
| 234 return; | 225 return; |
| 235 } | 226 } |
| 236 } | 227 } |
| 237 } | 228 } |
| 238 | 229 |
| 239 PassOwnPtrWillBeRawPtr<RejectedPromises::MessageQueue> RejectedPromises::createM
essageQueue() | 230 PassOwnPtr<RejectedPromises::MessageQueue> RejectedPromises::createMessageQueue(
) |
| 240 { | 231 { |
| 241 return adoptPtrWillBeNoop(new MessageQueue()); | 232 return adoptPtr(new MessageQueue()); |
| 242 } | 233 } |
| 243 | 234 |
| 244 void RejectedPromises::dispose() | 235 void RejectedPromises::dispose() |
| 245 { | 236 { |
| 246 if (m_queue.isEmpty()) | 237 if (m_queue.isEmpty()) |
| 247 return; | 238 return; |
| 248 | 239 |
| 249 OwnPtrWillBeRawPtr<MessageQueue> queue = createMessageQueue(); | 240 OwnPtr<MessageQueue> queue = createMessageQueue(); |
| 250 queue->swap(m_queue); | 241 queue->swap(m_queue); |
| 251 processQueueNow(queue.release()); | 242 processQueueNow(queue.release()); |
| 252 } | 243 } |
| 253 | 244 |
| 254 void RejectedPromises::processQueue() | 245 void RejectedPromises::processQueue() |
| 255 { | 246 { |
| 256 if (m_queue.isEmpty()) | 247 if (m_queue.isEmpty()) |
| 257 return; | 248 return; |
| 258 | 249 |
| 259 OwnPtrWillBeRawPtr<MessageQueue> queue = createMessageQueue(); | 250 OwnPtr<MessageQueue> queue = createMessageQueue(); |
| 260 queue->swap(m_queue); | 251 queue->swap(m_queue); |
| 261 Platform::current()->currentThread()->scheduler()->timerTaskRunner()->postTa
sk(BLINK_FROM_HERE, new Task(bind(&RejectedPromises::processQueueNow, PassRefPtr
WillBeRawPtr<RejectedPromises>(this), queue.release()))); | 252 Platform::current()->currentThread()->scheduler()->timerTaskRunner()->postTa
sk(BLINK_FROM_HERE, new Task(bind(&RejectedPromises::processQueueNow, PassRefPtr
<RejectedPromises>(this), queue.release()))); |
| 262 } | 253 } |
| 263 | 254 |
| 264 void RejectedPromises::processQueueNow(PassOwnPtrWillBeRawPtr<MessageQueue> queu
e) | 255 void RejectedPromises::processQueueNow(PassOwnPtr<MessageQueue> queue) |
| 265 { | 256 { |
| 266 // Remove collected handlers. | 257 // Remove collected handlers. |
| 267 for (size_t i = 0; i < m_reportedAsErrors.size();) { | 258 for (size_t i = 0; i < m_reportedAsErrors.size();) { |
| 268 if (m_reportedAsErrors.at(i)->isCollected()) | 259 if (m_reportedAsErrors.at(i)->isCollected()) |
| 269 m_reportedAsErrors.remove(i); | 260 m_reportedAsErrors.remove(i); |
| 270 else | 261 else |
| 271 ++i; | 262 ++i; |
| 272 } | 263 } |
| 273 | 264 |
| 274 while (!queue->isEmpty()) { | 265 while (!queue->isEmpty()) { |
| 275 OwnPtrWillBeRawPtr<Message> message = queue->takeFirst(); | 266 OwnPtr<Message> message = queue->takeFirst(); |
| 276 if (message->isCollected()) | 267 if (message->isCollected()) |
| 277 continue; | 268 continue; |
| 278 if (!message->hasHandler()) { | 269 if (!message->hasHandler()) { |
| 279 message->report(); | 270 message->report(); |
| 280 message->makePromiseWeak(); | 271 message->makePromiseWeak(); |
| 281 m_reportedAsErrors.append(message.release()); | 272 m_reportedAsErrors.append(message.release()); |
| 282 if (m_reportedAsErrors.size() > maxReportedHandlersPendingResolution
) | 273 if (m_reportedAsErrors.size() > maxReportedHandlersPendingResolution
) |
| 283 m_reportedAsErrors.remove(0, maxReportedHandlersPendingResolutio
n / 10); | 274 m_reportedAsErrors.remove(0, maxReportedHandlersPendingResolutio
n / 10); |
| 284 } | 275 } |
| 285 } | 276 } |
| 286 } | 277 } |
| 287 | 278 |
| 288 void RejectedPromises::revokeNow(PassOwnPtrWillBeRawPtr<Message> message) | 279 void RejectedPromises::revokeNow(PassOwnPtr<Message> message) |
| 289 { | 280 { |
| 290 message->revoke(); | 281 message->revoke(); |
| 291 } | 282 } |
| 292 | 283 |
| 293 } // namespace blink | 284 } // namespace blink |
| OLD | NEW |