| 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 "config.h" | 5 #include "config.h" |
| 6 #include "bindings/core/v8/RejectedPromises.h" | 6 #include "bindings/core/v8/RejectedPromises.h" |
| 7 | 7 |
| 8 #include "bindings/core/v8/ScopedPersistent.h" | 8 #include "bindings/core/v8/ScopedPersistent.h" |
| 9 #include "bindings/core/v8/ScriptState.h" | 9 #include "bindings/core/v8/ScriptState.h" |
| 10 #include "bindings/core/v8/ScriptValue.h" | 10 #include "bindings/core/v8/ScriptValue.h" |
| 11 #include "bindings/core/v8/V8Binding.h" | 11 #include "bindings/core/v8/V8Binding.h" |
| 12 #include "core/dom/ExecutionContext.h" | 12 #include "core/dom/ExecutionContext.h" |
| 13 #include "core/events/EventTarget.h" | 13 #include "core/events/EventTarget.h" |
| 14 #include "core/events/PromiseRejectionEvent.h" | 14 #include "core/events/PromiseRejectionEvent.h" |
| 15 #include "core/inspector/ConsoleMessage.h" | 15 #include "core/inspector/ConsoleMessage.h" |
| 16 #include "core/inspector/ScriptArguments.h" | 16 #include "core/inspector/ScriptArguments.h" |
| 17 #include "platform/RuntimeEnabledFeatures.h" | 17 #include "platform/RuntimeEnabledFeatures.h" |
| 18 #include "platform/Task.h" |
| 19 #include "public/platform/Platform.h" |
| 20 #include "public/platform/WebScheduler.h" |
| 21 #include "public/platform/WebTaskRunner.h" |
| 22 #include "public/platform/WebThread.h" |
| 23 #include "wtf/Functional.h" |
| 18 | 24 |
| 19 namespace blink { | 25 namespace blink { |
| 20 | 26 |
| 21 static const unsigned maxReportedHandlersPendingResolution = 1000; | 27 static const unsigned maxReportedHandlersPendingResolution = 1000; |
| 22 | 28 |
| 23 class RejectedPromises::Message final : public NoBaseWillBeGarbageCollectedFinal
ized<RejectedPromises::Message> { | 29 class RejectedPromises::Message final : public NoBaseWillBeGarbageCollectedFinal
ized<RejectedPromises::Message> { |
| 24 public: | 30 public: |
| 25 static PassOwnPtrWillBeRawPtr<Message> create(ScriptState* scriptState, v8::
Local<v8::Promise> promise, const ScriptValue& exception, const String& errorMes
sage, const String& resourceName, int scriptId, int lineNumber, int columnNumber
, PassRefPtrWillBeRawPtr<ScriptCallStack> callStack) | 31 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) |
| 26 { | 32 { |
| 27 return adoptPtrWillBeNoop(new Message(scriptState, promise, exception, e
rrorMessage, resourceName, scriptId, lineNumber, columnNumber, callStack)); | 33 return adoptPtrWillBeNoop(new Message(scriptState, promise, exception, e
rrorMessage, resourceName, scriptId, lineNumber, columnNumber, callStack)); |
| 28 } | 34 } |
| 29 | 35 |
| 30 DEFINE_INLINE_TRACE() | 36 DEFINE_INLINE_TRACE() |
| 31 { | 37 { |
| 32 visitor->trace(m_callStack); | 38 visitor->trace(m_callStack); |
| 33 } | 39 } |
| 34 | 40 |
| 35 bool isCollected() | 41 bool isCollected() |
| (...skipping 13 matching lines...) Expand all Loading... |
| 49 return; | 55 return; |
| 50 // If execution termination has been triggered, quietly bail out. | 56 // If execution termination has been triggered, quietly bail out. |
| 51 if (v8::V8::IsExecutionTerminating(m_scriptState->isolate())) | 57 if (v8::V8::IsExecutionTerminating(m_scriptState->isolate())) |
| 52 return; | 58 return; |
| 53 ExecutionContext* executionContext = m_scriptState->executionContext(); | 59 ExecutionContext* executionContext = m_scriptState->executionContext(); |
| 54 if (!executionContext) | 60 if (!executionContext) |
| 55 return; | 61 return; |
| 56 | 62 |
| 57 ScriptState::Scope scope(m_scriptState); | 63 ScriptState::Scope scope(m_scriptState); |
| 58 v8::Local<v8::Value> value = m_promise.newLocal(m_scriptState->isolate()
); | 64 v8::Local<v8::Value> value = m_promise.newLocal(m_scriptState->isolate()
); |
| 65 v8::Local<v8::Value> reason = m_exception.newLocal(m_scriptState->isolat
e()); |
| 59 // Either collected or https://crbug.com/450330 | 66 // Either collected or https://crbug.com/450330 |
| 60 if (value.IsEmpty() || !value->IsPromise()) | 67 if (value.IsEmpty() || !value->IsPromise()) |
| 61 return; | 68 return; |
| 62 ASSERT(!v8::Local<v8::Promise>::Cast(value)->HasHandler()); | 69 ASSERT(!hasHandler()); |
| 63 | 70 |
| 64 EventTarget* target = executionContext->errorEventTarget(); | 71 EventTarget* target = executionContext->errorEventTarget(); |
| 65 if (RuntimeEnabledFeatures::promiseRejectionEventEnabled() && target) { | 72 if (RuntimeEnabledFeatures::promiseRejectionEventEnabled() && target) { |
| 66 PromiseRejectionEventInit init; | 73 PromiseRejectionEventInit init; |
| 67 init.setPromise(ScriptPromise(m_scriptState, value)); | 74 init.setPromise(ScriptPromise(m_scriptState, value)); |
| 68 init.setReason(m_exception); | 75 init.setReason(ScriptValue(m_scriptState, reason)); |
| 69 init.setCancelable(true); | 76 init.setCancelable(true); |
| 70 RefPtrWillBeRawPtr<PromiseRejectionEvent> event = PromiseRejectionEv
ent::create(m_scriptState, EventTypeNames::unhandledrejection, init); | 77 RefPtrWillBeRawPtr<PromiseRejectionEvent> event = PromiseRejectionEv
ent::create(m_scriptState, EventTypeNames::unhandledrejection, init); |
| 71 // Log to console if event was not preventDefault()'ed. | 78 // Log to console if event was not preventDefault()'ed. |
| 72 m_shouldLogToConsole = target->dispatchEvent(event); | 79 m_shouldLogToConsole = target->dispatchEvent(event); |
| 73 } | 80 } |
| 74 | 81 |
| 75 if (m_shouldLogToConsole) { | 82 if (m_shouldLogToConsole) { |
| 76 const String errorMessage = "Uncaught (in promise)"; | 83 const String errorMessage = "Uncaught (in promise)"; |
| 77 Vector<ScriptValue> args; | 84 Vector<ScriptValue> args; |
| 78 args.append(ScriptValue(m_scriptState, v8String(m_scriptState->isola
te(), errorMessage))); | 85 args.append(ScriptValue(m_scriptState, v8String(m_scriptState->isola
te(), errorMessage))); |
| 79 args.append(m_exception); | 86 args.append(ScriptValue(m_scriptState, reason)); |
| 80 RefPtrWillBeRawPtr<ScriptArguments> arguments = ScriptArguments::cre
ate(m_scriptState, args); | 87 RefPtrWillBeRawPtr<ScriptArguments> arguments = ScriptArguments::cre
ate(m_scriptState, args); |
| 81 | 88 |
| 82 String embedderErrorMessage = m_errorMessage; | 89 String embedderErrorMessage = m_errorMessage; |
| 83 if (embedderErrorMessage.isEmpty()) | 90 if (embedderErrorMessage.isEmpty()) |
| 84 embedderErrorMessage = errorMessage; | 91 embedderErrorMessage = errorMessage; |
| 85 else if (embedderErrorMessage.startsWith("Uncaught ")) | 92 else if (embedderErrorMessage.startsWith("Uncaught ")) |
| 86 embedderErrorMessage.insert(" (in promise)", 8); | 93 embedderErrorMessage.insert(" (in promise)", 8); |
| 87 | 94 |
| 88 RefPtrWillBeRawPtr<ConsoleMessage> consoleMessage = ConsoleMessage::
create(JSMessageSource, ErrorMessageLevel, embedderErrorMessage, m_resourceName,
m_lineNumber, m_columnNumber); | 95 RefPtrWillBeRawPtr<ConsoleMessage> consoleMessage = ConsoleMessage::
create(JSMessageSource, ErrorMessageLevel, embedderErrorMessage, m_resourceName,
m_lineNumber, m_columnNumber); |
| 89 consoleMessage->setScriptArguments(arguments); | 96 consoleMessage->setScriptArguments(arguments); |
| 90 consoleMessage->setCallStack(m_callStack); | 97 consoleMessage->setCallStack(m_callStack); |
| 91 consoleMessage->setScriptId(m_scriptId); | 98 consoleMessage->setScriptId(m_scriptId); |
| 92 m_consoleMessageId = consoleMessage->assignMessageId(); | 99 m_consoleMessageId = consoleMessage->assignMessageId(); |
| 93 executionContext->addConsoleMessage(consoleMessage.release()); | 100 executionContext->addConsoleMessage(consoleMessage.release()); |
| 94 } | 101 } |
| 95 | 102 |
| 96 m_callStack.clear(); | 103 m_callStack.clear(); |
| 97 } | 104 } |
| 98 | 105 |
| 99 void revoke() | 106 void revoke() |
| 100 { | 107 { |
| 101 ExecutionContext* executionContext = m_scriptState->executionContext(); | 108 ExecutionContext* executionContext = m_scriptState->executionContext(); |
| 102 if (!executionContext) | 109 if (!executionContext) |
| 103 return; | 110 return; |
| 104 | 111 |
| 105 ScriptState::Scope scope(m_scriptState); | 112 ScriptState::Scope scope(m_scriptState); |
| 106 v8::Local<v8::Value> value = m_promise.newLocal(m_scriptState->isolate()
); | 113 v8::Local<v8::Value> value = m_promise.newLocal(m_scriptState->isolate()
); |
| 114 v8::Local<v8::Value> reason = m_exception.newLocal(m_scriptState->isolat
e()); |
| 107 // Either collected or https://crbug.com/450330 | 115 // Either collected or https://crbug.com/450330 |
| 108 if (value.IsEmpty() || !value->IsPromise()) | 116 if (value.IsEmpty() || !value->IsPromise()) |
| 109 return; | 117 return; |
| 110 | 118 |
| 111 EventTarget* target = executionContext->errorEventTarget(); | 119 EventTarget* target = executionContext->errorEventTarget(); |
| 112 if (RuntimeEnabledFeatures::promiseRejectionEventEnabled() && target) { | 120 if (RuntimeEnabledFeatures::promiseRejectionEventEnabled() && target) { |
| 113 PromiseRejectionEventInit init; | 121 PromiseRejectionEventInit init; |
| 114 init.setPromise(ScriptPromise(m_scriptState, value)); | 122 init.setPromise(ScriptPromise(m_scriptState, value)); |
| 115 init.setReason(m_exception); | 123 init.setReason(ScriptValue(m_scriptState, reason)); |
| 116 RefPtrWillBeRawPtr<PromiseRejectionEvent> event = PromiseRejectionEv
ent::create(m_scriptState, EventTypeNames::rejectionhandled, init); | 124 RefPtrWillBeRawPtr<PromiseRejectionEvent> event = PromiseRejectionEv
ent::create(m_scriptState, EventTypeNames::rejectionhandled, init); |
| 117 target->dispatchEvent(event); | 125 target->dispatchEvent(event); |
| 118 } | 126 } |
| 119 | 127 |
| 120 if (m_shouldLogToConsole) { | 128 if (m_shouldLogToConsole) { |
| 121 RefPtrWillBeRawPtr<ConsoleMessage> consoleMessage = ConsoleMessage::
create(JSMessageSource, RevokedErrorMessageLevel, "Handler added to rejected pro
mise"); | 129 RefPtrWillBeRawPtr<ConsoleMessage> consoleMessage = ConsoleMessage::
create(JSMessageSource, RevokedErrorMessageLevel, "Handler added to rejected pro
mise"); |
| 122 consoleMessage->setRelatedMessageId(m_consoleMessageId); | 130 consoleMessage->setRelatedMessageId(m_consoleMessageId); |
| 123 executionContext->addConsoleMessage(consoleMessage.release()); | 131 executionContext->addConsoleMessage(consoleMessage.release()); |
| 124 } | 132 } |
| 125 } | 133 } |
| 126 | 134 |
| 135 void makePromiseWeak() |
| 136 { |
| 137 ASSERT(!m_promise.isEmpty() && !m_promise.isWeak()); |
| 138 m_promise.setWeak(this, &Message::didCollectPromise); |
| 139 m_exception.setWeak(this, &Message::didCollectException); |
| 140 } |
| 141 |
| 142 void makePromiseStrong() |
| 143 { |
| 144 ASSERT(!m_promise.isEmpty() && m_promise.isWeak()); |
| 145 m_promise.clearWeak(); |
| 146 m_exception.clearWeak(); |
| 147 } |
| 148 |
| 149 bool hasHandler() |
| 150 { |
| 151 if (isCollected()) |
| 152 return false; |
| 153 ScriptState::Scope scope(m_scriptState); |
| 154 v8::Local<v8::Value> value = m_promise.newLocal(m_scriptState->isolate()
); |
| 155 return v8::Local<v8::Promise>::Cast(value)->HasHandler(); |
| 156 } |
| 157 |
| 127 private: | 158 private: |
| 128 Message(ScriptState* scriptState, v8::Local<v8::Promise> promise, const Scri
ptValue& exception, const String& errorMessage, const String& resourceName, int
scriptId, int lineNumber, int columnNumber, PassRefPtrWillBeRawPtr<ScriptCallSta
ck> callStack) | 159 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) |
| 129 : m_scriptState(scriptState) | 160 : m_scriptState(scriptState) |
| 130 , m_promise(scriptState->isolate(), promise) | 161 , m_promise(scriptState->isolate(), promise) |
| 131 , m_exception(exception) | 162 , m_exception(scriptState->isolate(), exception) |
| 132 , m_errorMessage(errorMessage) | 163 , m_errorMessage(errorMessage) |
| 133 , m_resourceName(resourceName) | 164 , m_resourceName(resourceName) |
| 134 , m_scriptId(scriptId) | 165 , m_scriptId(scriptId) |
| 135 , m_lineNumber(lineNumber) | 166 , m_lineNumber(lineNumber) |
| 136 , m_columnNumber(columnNumber) | 167 , m_columnNumber(columnNumber) |
| 137 , m_callStack(callStack) | 168 , m_callStack(callStack) |
| 138 , m_consoleMessageId(0) | 169 , m_consoleMessageId(0) |
| 139 , m_collected(false) | 170 , m_collected(false) |
| 140 , m_shouldLogToConsole(true) | 171 , m_shouldLogToConsole(true) |
| 141 { | 172 { |
| 142 m_promise.setWeak(this, &Message::didCollectPromise); | |
| 143 } | 173 } |
| 144 | 174 |
| 145 static void didCollectPromise(const v8::WeakCallbackInfo<Message>& data) | 175 static void didCollectPromise(const v8::WeakCallbackInfo<Message>& data) |
| 146 { | 176 { |
| 147 data.GetParameter()->m_collected = true; | 177 data.GetParameter()->m_collected = true; |
| 148 data.GetParameter()->m_promise.clear(); | 178 data.GetParameter()->m_promise.clear(); |
| 149 } | 179 } |
| 150 | 180 |
| 181 static void didCollectException(const v8::WeakCallbackInfo<Message>& data) |
| 182 { |
| 183 data.GetParameter()->m_exception.clear(); |
| 184 } |
| 185 |
| 151 ScriptState* m_scriptState; | 186 ScriptState* m_scriptState; |
| 152 ScopedPersistent<v8::Promise> m_promise; | 187 ScopedPersistent<v8::Promise> m_promise; |
| 153 ScriptValue m_exception; | 188 ScopedPersistent<v8::Value> m_exception; |
| 154 String m_errorMessage; | 189 String m_errorMessage; |
| 155 String m_resourceName; | 190 String m_resourceName; |
| 156 int m_scriptId; | 191 int m_scriptId; |
| 157 int m_lineNumber; | 192 int m_lineNumber; |
| 158 int m_columnNumber; | 193 int m_columnNumber; |
| 159 RefPtrWillBeMember<ScriptCallStack> m_callStack; | 194 RefPtrWillBeMember<ScriptCallStack> m_callStack; |
| 160 unsigned m_consoleMessageId; | 195 unsigned m_consoleMessageId; |
| 161 bool m_collected; | 196 bool m_collected; |
| 162 bool m_shouldLogToConsole; | 197 bool m_shouldLogToConsole; |
| 163 }; | 198 }; |
| 164 | 199 |
| 165 RejectedPromises::RejectedPromises() | 200 RejectedPromises::RejectedPromises() |
| 166 { | 201 { |
| 167 } | 202 } |
| 168 | 203 |
| 169 DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(RejectedPromises); | 204 DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(RejectedPromises); |
| 170 | 205 |
| 171 DEFINE_TRACE(RejectedPromises) | 206 DEFINE_TRACE(RejectedPromises) |
| 172 { | 207 { |
| 173 visitor->trace(m_queue); | 208 visitor->trace(m_queue); |
| 174 visitor->trace(m_reportedAsErrors); | 209 visitor->trace(m_reportedAsErrors); |
| 175 } | 210 } |
| 176 | 211 |
| 177 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) | 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) |
| 178 { | 213 { |
| 179 m_queue.append(Message::create(scriptState, data.GetPromise(), ScriptValue(s
criptState, data.GetValue()), errorMessage, resourceName, scriptId, lineNumber,
columnNumber, callStack)); | 214 m_queue.append(Message::create(scriptState, data.GetPromise(), data.GetValue
(), errorMessage, resourceName, scriptId, lineNumber, columnNumber, callStack)); |
| 180 } | 215 } |
| 181 | 216 |
| 182 void RejectedPromises::handlerAdded(v8::PromiseRejectMessage data) | 217 void RejectedPromises::handlerAdded(v8::PromiseRejectMessage data) |
| 183 { | 218 { |
| 184 // First look it up in the pending messages and fast return, it'll be covere
d by processQueue(). | 219 // First look it up in the pending messages and fast return, it'll be covere
d by processQueue(). |
| 185 for (auto it = m_queue.begin(); it != m_queue.end(); ++it) { | 220 for (auto it = m_queue.begin(); it != m_queue.end(); ++it) { |
| 186 if (!(*it)->isCollected() && (*it)->hasPromise(data.GetPromise())) { | 221 if (!(*it)->isCollected() && (*it)->hasPromise(data.GetPromise())) { |
| 187 m_queue.remove(it); | 222 m_queue.remove(it); |
| 188 return; | 223 return; |
| 189 } | 224 } |
| 190 } | 225 } |
| 191 | 226 |
| 192 // Then look it up in the reported errors. | 227 // Then look it up in the reported errors. |
| 193 for (size_t i = 0; i < m_reportedAsErrors.size(); ++i) { | 228 for (size_t i = 0; i < m_reportedAsErrors.size(); ++i) { |
| 194 auto& message = m_reportedAsErrors.at(i); | 229 auto& message = m_reportedAsErrors.at(i); |
| 195 if (!message->isCollected() && message->hasPromise(data.GetPromise())) { | 230 if (!message->isCollected() && message->hasPromise(data.GetPromise())) { |
| 196 message->revoke(); | 231 message->makePromiseStrong(); |
| 232 Platform::current()->currentThread()->scheduler()->timerTaskRunner()
->postTask(BLINK_FROM_HERE, new Task(bind(&RejectedPromises::revokeNow, PassRefP
trWillBeRawPtr<RejectedPromises>(this), message.release()))); |
| 197 m_reportedAsErrors.remove(i); | 233 m_reportedAsErrors.remove(i); |
| 198 return; | 234 return; |
| 199 } | 235 } |
| 200 } | 236 } |
| 201 } | 237 } |
| 202 | 238 |
| 239 PassOwnPtrWillBeRawPtr<RejectedPromises::MessageQueue> RejectedPromises::createM
essageQueue() |
| 240 { |
| 241 return adoptPtrWillBeNoop(new MessageQueue()); |
| 242 } |
| 243 |
| 203 void RejectedPromises::dispose() | 244 void RejectedPromises::dispose() |
| 204 { | 245 { |
| 205 processQueue(); | 246 if (m_queue.isEmpty()) |
| 247 return; |
| 248 |
| 249 OwnPtrWillBeRawPtr<MessageQueue> queue = createMessageQueue(); |
| 250 queue->swap(m_queue); |
| 251 processQueueNow(queue.release()); |
| 206 } | 252 } |
| 207 | 253 |
| 208 void RejectedPromises::processQueue() | 254 void RejectedPromises::processQueue() |
| 209 { | 255 { |
| 256 if (m_queue.isEmpty()) |
| 257 return; |
| 258 |
| 259 OwnPtrWillBeRawPtr<MessageQueue> queue = createMessageQueue(); |
| 260 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()))); |
| 262 } |
| 263 |
| 264 void RejectedPromises::processQueueNow(PassOwnPtrWillBeRawPtr<MessageQueue> queu
e) |
| 265 { |
| 210 // Remove collected handlers. | 266 // Remove collected handlers. |
| 211 for (size_t i = 0; i < m_reportedAsErrors.size();) { | 267 for (size_t i = 0; i < m_reportedAsErrors.size();) { |
| 212 if (m_reportedAsErrors.at(i)->isCollected()) | 268 if (m_reportedAsErrors.at(i)->isCollected()) |
| 213 m_reportedAsErrors.remove(i); | 269 m_reportedAsErrors.remove(i); |
| 214 else | 270 else |
| 215 ++i; | 271 ++i; |
| 216 } | 272 } |
| 217 | 273 |
| 218 while (!m_queue.isEmpty()) { | 274 while (!queue->isEmpty()) { |
| 219 OwnPtrWillBeRawPtr<Message> message = m_queue.takeFirst(); | 275 OwnPtrWillBeRawPtr<Message> message = queue->takeFirst(); |
| 220 if (message->isCollected()) | 276 if (!message->hasHandler()) { |
| 221 continue; | 277 message->report(); |
| 222 | 278 message->makePromiseWeak(); |
| 223 message->report(); | 279 m_reportedAsErrors.append(message.release()); |
| 224 m_reportedAsErrors.append(message.release()); | 280 if (m_reportedAsErrors.size() > maxReportedHandlersPendingResolution
) |
| 225 if (m_reportedAsErrors.size() > maxReportedHandlersPendingResolution) | 281 m_reportedAsErrors.remove(0, maxReportedHandlersPendingResolutio
n / 10); |
| 226 m_reportedAsErrors.remove(0, maxReportedHandlersPendingResolution /
10); | 282 } |
| 227 } | 283 } |
| 228 } | 284 } |
| 229 | 285 |
| 286 void RejectedPromises::revokeNow(PassOwnPtrWillBeRawPtr<Message> message) |
| 287 { |
| 288 message->revoke(); |
| 289 } |
| 290 |
| 230 } // namespace blink | 291 } // namespace blink |
| OLD | NEW |