| 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" |
| 14 #include "core/events/PromiseRejectionEvent.h" |
| 13 #include "core/inspector/ConsoleMessage.h" | 15 #include "core/inspector/ConsoleMessage.h" |
| 14 #include "core/inspector/ScriptArguments.h" | 16 #include "core/inspector/ScriptArguments.h" |
| 17 #include "platform/RuntimeEnabledFeatures.h" |
| 15 | 18 |
| 16 namespace blink { | 19 namespace blink { |
| 17 | 20 |
| 18 static const unsigned maxReportedHandlersPendingResolution = 1000; | 21 static const unsigned maxReportedHandlersPendingResolution = 1000; |
| 19 | 22 |
| 20 class RejectedPromises::Message final : public NoBaseWillBeGarbageCollectedFinal
ized<RejectedPromises::Message> { | 23 class RejectedPromises::Message final : public NoBaseWillBeGarbageCollectedFinal
ized<RejectedPromises::Message> { |
| 21 public: | 24 public: |
| 22 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) | 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) |
| 23 { | 26 { |
| 24 return adoptPtrWillBeNoop(new Message(scriptState, promise, exception, e
rrorMessage, resourceName, scriptId, lineNumber, columnNumber, callStack)); | 27 return adoptPtrWillBeNoop(new Message(scriptState, promise, exception, e
rrorMessage, resourceName, scriptId, lineNumber, columnNumber, callStack)); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 51 if (!executionContext) | 54 if (!executionContext) |
| 52 return; | 55 return; |
| 53 | 56 |
| 54 ScriptState::Scope scope(m_scriptState); | 57 ScriptState::Scope scope(m_scriptState); |
| 55 v8::Local<v8::Value> value = m_promise.newLocal(m_scriptState->isolate()
); | 58 v8::Local<v8::Value> value = m_promise.newLocal(m_scriptState->isolate()
); |
| 56 // Either collected or https://crbug.com/450330 | 59 // Either collected or https://crbug.com/450330 |
| 57 if (value.IsEmpty() || !value->IsPromise()) | 60 if (value.IsEmpty() || !value->IsPromise()) |
| 58 return; | 61 return; |
| 59 ASSERT(!v8::Local<v8::Promise>::Cast(value)->HasHandler()); | 62 ASSERT(!v8::Local<v8::Promise>::Cast(value)->HasHandler()); |
| 60 | 63 |
| 61 const String errorMessage = "Uncaught (in promise)"; | 64 EventTarget* target = executionContext->errorEventTarget(); |
| 62 Vector<ScriptValue> args; | 65 if (RuntimeEnabledFeatures::promiseRejectionEventEnabled() && target) { |
| 63 args.append(ScriptValue(m_scriptState, v8String(m_scriptState->isolate()
, errorMessage))); | 66 PromiseRejectionEventInit init; |
| 64 args.append(m_exception); | 67 init.setPromise(ScriptPromise(m_scriptState, value)); |
| 65 RefPtrWillBeRawPtr<ScriptArguments> arguments = ScriptArguments::create(
m_scriptState, args); | 68 init.setReason(m_exception); |
| 69 init.setCancelable(true); |
| 70 RefPtrWillBeRawPtr<PromiseRejectionEvent> event = PromiseRejectionEv
ent::create(EventTypeNames::unhandledrejection, init); |
| 71 // Log to console if event was not preventDefault()'ed. |
| 72 m_shouldLogToConsole = target->dispatchEvent(event); |
| 73 } |
| 66 | 74 |
| 67 String embedderErrorMessage = m_errorMessage; | 75 if (m_shouldLogToConsole) { |
| 68 if (embedderErrorMessage.isEmpty()) | 76 const String errorMessage = "Uncaught (in promise)"; |
| 69 embedderErrorMessage = errorMessage; | 77 Vector<ScriptValue> args; |
| 70 else if (embedderErrorMessage.startsWith("Uncaught ")) | 78 args.append(ScriptValue(m_scriptState, v8String(m_scriptState->isola
te(), errorMessage))); |
| 71 embedderErrorMessage.insert(" (in promise)", 8); | 79 args.append(m_exception); |
| 80 RefPtrWillBeRawPtr<ScriptArguments> arguments = ScriptArguments::cre
ate(m_scriptState, args); |
| 72 | 81 |
| 73 RefPtrWillBeRawPtr<ConsoleMessage> consoleMessage = ConsoleMessage::crea
te(JSMessageSource, ErrorMessageLevel, embedderErrorMessage, m_resourceName, m_l
ineNumber, m_columnNumber); | 82 String embedderErrorMessage = m_errorMessage; |
| 74 consoleMessage->setScriptArguments(arguments); | 83 if (embedderErrorMessage.isEmpty()) |
| 75 consoleMessage->setCallStack(m_callStack); | 84 embedderErrorMessage = errorMessage; |
| 76 consoleMessage->setScriptId(m_scriptId); | 85 else if (embedderErrorMessage.startsWith("Uncaught ")) |
| 77 m_consoleMessageId = consoleMessage->assignMessageId(); | 86 embedderErrorMessage.insert(" (in promise)", 8); |
| 78 executionContext->addConsoleMessage(consoleMessage.release()); | 87 |
| 88 RefPtrWillBeRawPtr<ConsoleMessage> consoleMessage = ConsoleMessage::
create(JSMessageSource, ErrorMessageLevel, embedderErrorMessage, m_resourceName,
m_lineNumber, m_columnNumber); |
| 89 consoleMessage->setScriptArguments(arguments); |
| 90 consoleMessage->setCallStack(m_callStack); |
| 91 consoleMessage->setScriptId(m_scriptId); |
| 92 m_consoleMessageId = consoleMessage->assignMessageId(); |
| 93 executionContext->addConsoleMessage(consoleMessage.release()); |
| 94 } |
| 79 | 95 |
| 80 m_callStack.clear(); | 96 m_callStack.clear(); |
| 81 m_exception.clear(); | |
| 82 } | 97 } |
| 83 | 98 |
| 84 void revoke() | 99 void revoke() |
| 85 { | 100 { |
| 86 ExecutionContext* executionContext = m_scriptState->executionContext(); | 101 ExecutionContext* executionContext = m_scriptState->executionContext(); |
| 87 if (!executionContext) | 102 if (!executionContext) |
| 88 return; | 103 return; |
| 89 | 104 |
| 90 RefPtrWillBeRawPtr<ConsoleMessage> consoleMessage = ConsoleMessage::crea
te(JSMessageSource, RevokedErrorMessageLevel, "Handler added to rejected promise
"); | 105 ScriptState::Scope scope(m_scriptState); |
| 91 consoleMessage->setRelatedMessageId(m_consoleMessageId); | 106 v8::Local<v8::Value> value = m_promise.newLocal(m_scriptState->isolate()
); |
| 92 executionContext->addConsoleMessage(consoleMessage.release()); | 107 // Either collected or https://crbug.com/450330 |
| 108 if (value.IsEmpty() || !value->IsPromise()) |
| 109 return; |
| 110 |
| 111 EventTarget* target = executionContext->errorEventTarget(); |
| 112 if (RuntimeEnabledFeatures::promiseRejectionEventEnabled() && target) { |
| 113 PromiseRejectionEventInit init; |
| 114 init.setPromise(ScriptPromise(m_scriptState, value)); |
| 115 init.setReason(m_exception); |
| 116 RefPtrWillBeRawPtr<PromiseRejectionEvent> event = PromiseRejectionEv
ent::create(EventTypeNames::rejectionhandled, init); |
| 117 m_shouldLogToConsole &= target->dispatchEvent(event); |
| 118 } |
| 119 |
| 120 if (m_shouldLogToConsole) { |
| 121 RefPtrWillBeRawPtr<ConsoleMessage> consoleMessage = ConsoleMessage::
create(JSMessageSource, RevokedErrorMessageLevel, "Handler added to rejected pro
mise"); |
| 122 consoleMessage->setRelatedMessageId(m_consoleMessageId); |
| 123 executionContext->addConsoleMessage(consoleMessage.release()); |
| 124 } |
| 93 } | 125 } |
| 94 | 126 |
| 95 private: | 127 private: |
| 96 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) | 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) |
| 97 : m_scriptState(scriptState) | 129 : m_scriptState(scriptState) |
| 98 , m_promise(scriptState->isolate(), promise) | 130 , m_promise(scriptState->isolate(), promise) |
| 99 , m_exception(exception) | 131 , m_exception(exception) |
| 100 , m_errorMessage(errorMessage) | 132 , m_errorMessage(errorMessage) |
| 101 , m_resourceName(resourceName) | 133 , m_resourceName(resourceName) |
| 102 , m_scriptId(scriptId) | 134 , m_scriptId(scriptId) |
| 103 , m_lineNumber(lineNumber) | 135 , m_lineNumber(lineNumber) |
| 104 , m_columnNumber(columnNumber) | 136 , m_columnNumber(columnNumber) |
| 105 , m_callStack(callStack) | 137 , m_callStack(callStack) |
| 106 , m_consoleMessageId(0) | 138 , m_consoleMessageId(0) |
| 107 , m_collected(false) | 139 , m_collected(false) |
| 140 , m_shouldLogToConsole(true) |
| 108 { | 141 { |
| 109 m_promise.setWeak(this, &Message::didCollectPromise); | 142 m_promise.setWeak(this, &Message::didCollectPromise); |
| 110 } | 143 } |
| 111 | 144 |
| 112 static void didCollectPromise(const v8::WeakCallbackInfo<Message>& data) | 145 static void didCollectPromise(const v8::WeakCallbackInfo<Message>& data) |
| 113 { | 146 { |
| 114 data.GetParameter()->m_collected = true; | 147 data.GetParameter()->m_collected = true; |
| 115 data.GetParameter()->m_promise.clear(); | 148 data.GetParameter()->m_promise.clear(); |
| 116 } | 149 } |
| 117 | 150 |
| 118 ScriptState* m_scriptState; | 151 ScriptState* m_scriptState; |
| 119 ScopedPersistent<v8::Promise> m_promise; | 152 ScopedPersistent<v8::Promise> m_promise; |
| 120 ScriptValue m_exception; | 153 ScriptValue m_exception; |
| 121 String m_errorMessage; | 154 String m_errorMessage; |
| 122 String m_resourceName; | 155 String m_resourceName; |
| 123 int m_scriptId; | 156 int m_scriptId; |
| 124 int m_lineNumber; | 157 int m_lineNumber; |
| 125 int m_columnNumber; | 158 int m_columnNumber; |
| 126 RefPtrWillBeMember<ScriptCallStack> m_callStack; | 159 RefPtrWillBeMember<ScriptCallStack> m_callStack; |
| 127 unsigned m_consoleMessageId; | 160 unsigned m_consoleMessageId; |
| 128 bool m_collected; | 161 bool m_collected; |
| 162 bool m_shouldLogToConsole; |
| 129 }; | 163 }; |
| 130 | 164 |
| 131 RejectedPromises::RejectedPromises() | 165 RejectedPromises::RejectedPromises() |
| 132 { | 166 { |
| 133 } | 167 } |
| 134 | 168 |
| 135 DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(RejectedPromises); | 169 DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(RejectedPromises); |
| 136 | 170 |
| 137 DEFINE_TRACE(RejectedPromises) | 171 DEFINE_TRACE(RejectedPromises) |
| 138 { | 172 { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 187 continue; | 221 continue; |
| 188 | 222 |
| 189 message->report(); | 223 message->report(); |
| 190 m_reportedAsErrors.append(message.release()); | 224 m_reportedAsErrors.append(message.release()); |
| 191 if (m_reportedAsErrors.size() > maxReportedHandlersPendingResolution) | 225 if (m_reportedAsErrors.size() > maxReportedHandlersPendingResolution) |
| 192 m_reportedAsErrors.remove(0, maxReportedHandlersPendingResolution /
10); | 226 m_reportedAsErrors.remove(0, maxReportedHandlersPendingResolution /
10); |
| 193 } | 227 } |
| 194 } | 228 } |
| 195 | 229 |
| 196 } // namespace blink | 230 } // namespace blink |
| OLD | NEW |