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 RefPtrWillBeRawPtr<PromiseRejectionEvent> event = PromiseRejectionEv
ent::create(EventTypeNames::unhandledrejection, ScriptPromise(m_scriptState, val
ue), m_exception); |
64 args.append(m_exception); | 67 // Log to console if event was not preventDefault()'ed. |
65 RefPtrWillBeRawPtr<ScriptArguments> arguments = ScriptArguments::create(
m_scriptState, args); | 68 m_shouldLogToConsole = target->dispatchEvent(event); |
| 69 } |
66 | 70 |
67 String embedderErrorMessage = m_errorMessage; | 71 if (m_shouldLogToConsole) { |
68 if (embedderErrorMessage.isEmpty()) | 72 const String errorMessage = "Uncaught (in promise)"; |
69 embedderErrorMessage = errorMessage; | 73 Vector<ScriptValue> args; |
70 else if (embedderErrorMessage.startsWith("Uncaught ")) | 74 args.append(ScriptValue(m_scriptState, v8String(m_scriptState->isola
te(), errorMessage))); |
71 embedderErrorMessage.insert(" (in promise)", 8); | 75 args.append(m_exception); |
| 76 RefPtrWillBeRawPtr<ScriptArguments> arguments = ScriptArguments::cre
ate(m_scriptState, args); |
72 | 77 |
73 RefPtrWillBeRawPtr<ConsoleMessage> consoleMessage = ConsoleMessage::crea
te(JSMessageSource, ErrorMessageLevel, embedderErrorMessage, m_resourceName, m_l
ineNumber, m_columnNumber); | 78 String embedderErrorMessage = m_errorMessage; |
74 consoleMessage->setScriptArguments(arguments); | 79 if (embedderErrorMessage.isEmpty()) |
75 consoleMessage->setCallStack(m_callStack); | 80 embedderErrorMessage = errorMessage; |
76 consoleMessage->setScriptId(m_scriptId); | 81 else if (embedderErrorMessage.startsWith("Uncaught ")) |
77 m_consoleMessageId = consoleMessage->assignMessageId(); | 82 embedderErrorMessage.insert(" (in promise)", 8); |
78 executionContext->addConsoleMessage(consoleMessage.release()); | 83 |
| 84 RefPtrWillBeRawPtr<ConsoleMessage> consoleMessage = ConsoleMessage::
create(JSMessageSource, ErrorMessageLevel, embedderErrorMessage, m_resourceName,
m_lineNumber, m_columnNumber); |
| 85 consoleMessage->setScriptArguments(arguments); |
| 86 consoleMessage->setCallStack(m_callStack); |
| 87 consoleMessage->setScriptId(m_scriptId); |
| 88 m_consoleMessageId = consoleMessage->assignMessageId(); |
| 89 executionContext->addConsoleMessage(consoleMessage.release()); |
| 90 } |
79 | 91 |
80 m_callStack.clear(); | 92 m_callStack.clear(); |
81 m_exception.clear(); | |
82 } | 93 } |
83 | 94 |
84 void revoke() | 95 void revoke() |
85 { | 96 { |
86 ExecutionContext* executionContext = m_scriptState->executionContext(); | 97 ExecutionContext* executionContext = m_scriptState->executionContext(); |
87 if (!executionContext) | 98 if (!executionContext) |
88 return; | 99 return; |
89 | 100 |
90 RefPtrWillBeRawPtr<ConsoleMessage> consoleMessage = ConsoleMessage::crea
te(JSMessageSource, RevokedErrorMessageLevel, "Handler added to rejected promise
"); | 101 ScriptState::Scope scope(m_scriptState); |
91 consoleMessage->setRelatedMessageId(m_consoleMessageId); | 102 v8::Local<v8::Value> value = m_promise.newLocal(m_scriptState->isolate()
); |
92 executionContext->addConsoleMessage(consoleMessage.release()); | 103 // Either collected or https://crbug.com/450330 |
| 104 if (value.IsEmpty() || !value->IsPromise()) |
| 105 return; |
| 106 |
| 107 EventTarget* target = executionContext->errorEventTarget(); |
| 108 if (RuntimeEnabledFeatures::promiseRejectionEventEnabled() && target) { |
| 109 RefPtrWillBeRawPtr<PromiseRejectionEvent> event = PromiseRejectionEv
ent::create(EventTypeNames::rejectionhandled, ScriptPromise(m_scriptState, value
), m_exception); |
| 110 m_shouldLogToConsole &= target->dispatchEvent(event); |
| 111 } |
| 112 |
| 113 if (m_shouldLogToConsole) { |
| 114 RefPtrWillBeRawPtr<ConsoleMessage> consoleMessage = ConsoleMessage::
create(JSMessageSource, RevokedErrorMessageLevel, "Handler added to rejected pro
mise"); |
| 115 consoleMessage->setRelatedMessageId(m_consoleMessageId); |
| 116 executionContext->addConsoleMessage(consoleMessage.release()); |
| 117 } |
93 } | 118 } |
94 | 119 |
95 private: | 120 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) | 121 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) | 122 : m_scriptState(scriptState) |
98 , m_promise(scriptState->isolate(), promise) | 123 , m_promise(scriptState->isolate(), promise) |
99 , m_exception(exception) | 124 , m_exception(exception) |
100 , m_errorMessage(errorMessage) | 125 , m_errorMessage(errorMessage) |
101 , m_resourceName(resourceName) | 126 , m_resourceName(resourceName) |
102 , m_scriptId(scriptId) | 127 , m_scriptId(scriptId) |
103 , m_lineNumber(lineNumber) | 128 , m_lineNumber(lineNumber) |
104 , m_columnNumber(columnNumber) | 129 , m_columnNumber(columnNumber) |
105 , m_callStack(callStack) | 130 , m_callStack(callStack) |
106 , m_consoleMessageId(0) | 131 , m_consoleMessageId(0) |
107 , m_collected(false) | 132 , m_collected(false) |
| 133 , m_shouldLogToConsole(true) |
108 { | 134 { |
109 m_promise.setWeak(this, &Message::didCollectPromise); | 135 m_promise.setWeak(this, &Message::didCollectPromise); |
110 } | 136 } |
111 | 137 |
112 static void didCollectPromise(const v8::WeakCallbackInfo<Message>& data) | 138 static void didCollectPromise(const v8::WeakCallbackInfo<Message>& data) |
113 { | 139 { |
114 data.GetParameter()->m_collected = true; | 140 data.GetParameter()->m_collected = true; |
115 data.GetParameter()->m_promise.clear(); | 141 data.GetParameter()->m_promise.clear(); |
116 } | 142 } |
117 | 143 |
118 ScriptState* m_scriptState; | 144 ScriptState* m_scriptState; |
119 ScopedPersistent<v8::Promise> m_promise; | 145 ScopedPersistent<v8::Promise> m_promise; |
120 ScriptValue m_exception; | 146 ScriptValue m_exception; |
121 String m_errorMessage; | 147 String m_errorMessage; |
122 String m_resourceName; | 148 String m_resourceName; |
123 int m_scriptId; | 149 int m_scriptId; |
124 int m_lineNumber; | 150 int m_lineNumber; |
125 int m_columnNumber; | 151 int m_columnNumber; |
126 RefPtrWillBeMember<ScriptCallStack> m_callStack; | 152 RefPtrWillBeMember<ScriptCallStack> m_callStack; |
127 unsigned m_consoleMessageId; | 153 unsigned m_consoleMessageId; |
128 bool m_collected; | 154 bool m_collected; |
| 155 bool m_shouldLogToConsole; |
129 }; | 156 }; |
130 | 157 |
131 RejectedPromises::RejectedPromises() | 158 RejectedPromises::RejectedPromises() |
132 { | 159 { |
133 } | 160 } |
134 | 161 |
135 DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(RejectedPromises); | 162 DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(RejectedPromises); |
136 | 163 |
137 DEFINE_TRACE(RejectedPromises) | 164 DEFINE_TRACE(RejectedPromises) |
138 { | 165 { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
187 continue; | 214 continue; |
188 | 215 |
189 message->report(); | 216 message->report(); |
190 m_reportedAsErrors.append(message.release()); | 217 m_reportedAsErrors.append(message.release()); |
191 if (m_reportedAsErrors.size() > maxReportedHandlersPendingResolution) | 218 if (m_reportedAsErrors.size() > maxReportedHandlersPendingResolution) |
192 m_reportedAsErrors.remove(0, maxReportedHandlersPendingResolution /
10); | 219 m_reportedAsErrors.remove(0, maxReportedHandlersPendingResolution /
10); |
193 } | 220 } |
194 } | 221 } |
195 | 222 |
196 } // namespace blink | 223 } // namespace blink |
OLD | NEW |