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/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/inspector/ConsoleMessage.h" | 12 #include "core/inspector/ConsoleMessage.h" |
13 #include "core/inspector/ScriptArguments.h" | 13 #include "core/inspector/ScriptArguments.h" |
14 | 14 |
15 namespace blink { | 15 namespace blink { |
16 | 16 |
| 17 static const unsigned maxReportedHandlersPendingResolution = 1000; |
| 18 |
17 class RejectedPromises::Message final : public NoBaseWillBeGarbageCollectedFinal
ized<RejectedPromises::Message> { | 19 class RejectedPromises::Message final : public NoBaseWillBeGarbageCollectedFinal
ized<RejectedPromises::Message> { |
18 public: | 20 public: |
19 static PassOwnPtrWillBeRawPtr<Message> create(const ScriptValue& promise, co
nst ScriptValue& exception, const String& errorMessage, const String& resourceNa
me, int scriptId, int lineNumber, int columnNumber, PassRefPtrWillBeRawPtr<Scrip
tCallStack> callStack) | 21 static PassOwnPtrWillBeRawPtr<Message> create(const ScriptValue& promise, co
nst ScriptValue& exception, const String& errorMessage, const String& resourceNa
me, int scriptId, int lineNumber, int columnNumber, PassRefPtrWillBeRawPtr<Scrip
tCallStack> callStack) |
20 { | 22 { |
21 return adoptPtrWillBeNoop(new Message(promise, exception, errorMessage,
resourceName, scriptId, lineNumber, columnNumber, callStack)); | 23 return adoptPtrWillBeNoop(new Message(promise, exception, errorMessage,
resourceName, scriptId, lineNumber, columnNumber, callStack)); |
22 } | 24 } |
23 | 25 |
24 DEFINE_INLINE_TRACE() | 26 DEFINE_INLINE_TRACE() |
25 { | 27 { |
26 visitor->trace(m_callStack); | 28 visitor->trace(m_callStack); |
27 } | 29 } |
28 | 30 |
29 private: | 31 private: |
30 Message(const ScriptValue& promise, const ScriptValue& exception, const Stri
ng& errorMessage, const String& resourceName, int scriptId, int lineNumber, int
columnNumber, PassRefPtrWillBeRawPtr<ScriptCallStack> callStack) | 32 Message(const ScriptValue& promise, const ScriptValue& exception, const Stri
ng& errorMessage, const String& resourceName, int scriptId, int lineNumber, int
columnNumber, PassRefPtrWillBeRawPtr<ScriptCallStack> callStack) |
31 : m_promise(promise) | 33 : m_promise(promise) |
32 , m_exception(exception) | 34 , m_exception(exception) |
33 , m_errorMessage(errorMessage) | 35 , m_errorMessage(errorMessage) |
34 , m_resourceName(resourceName) | 36 , m_resourceName(resourceName) |
35 , m_scriptId(scriptId) | 37 , m_scriptId(scriptId) |
36 , m_lineNumber(lineNumber) | 38 , m_lineNumber(lineNumber) |
37 , m_columnNumber(columnNumber) | 39 , m_columnNumber(columnNumber) |
38 , m_callStack(callStack) | 40 , m_callStack(callStack) |
| 41 , m_consoleMessageId(0) |
39 { | 42 { |
40 } | 43 } |
41 | 44 |
42 friend class RejectedPromises; | 45 friend class RejectedPromises; |
43 | 46 |
44 const ScriptValue m_promise; | 47 const ScriptValue m_promise; |
45 const ScriptValue m_exception; | 48 const ScriptValue m_exception; |
46 const String m_errorMessage; | 49 const String m_errorMessage; |
47 const String m_resourceName; | 50 const String m_resourceName; |
48 const int m_scriptId; | 51 const int m_scriptId; |
49 const int m_lineNumber; | 52 const int m_lineNumber; |
50 const int m_columnNumber; | 53 const int m_columnNumber; |
51 const RefPtrWillBeMember<ScriptCallStack> m_callStack; | 54 const RefPtrWillBeMember<ScriptCallStack> m_callStack; |
| 55 unsigned m_consoleMessageId; |
52 }; | 56 }; |
53 | 57 |
54 RejectedPromises::RejectedPromises() | 58 RejectedPromises::RejectedPromises() |
55 { | 59 { |
56 } | 60 } |
57 | 61 |
58 DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(RejectedPromises); | 62 DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(RejectedPromises); |
59 | 63 |
60 DEFINE_TRACE(RejectedPromises) | 64 DEFINE_TRACE(RejectedPromises) |
61 { | 65 { |
62 visitor->trace(m_queue); | 66 visitor->trace(m_queue); |
63 } | 67 } |
64 | 68 |
65 void RejectedPromises::add(ScriptState* scriptState, v8::PromiseRejectMessage da
ta, const String& errorMessage, const String& resourceName, int scriptId, int li
neNumber, int columnNumber, PassRefPtrWillBeRawPtr<ScriptCallStack> callStack) | 69 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) |
66 { | 70 { |
67 v8::Handle<v8::Promise> promise = data.GetPromise(); | 71 v8::Handle<v8::Promise> promise = data.GetPromise(); |
68 OwnPtrWillBeRawPtr<Message> message = Message::create(ScriptValue(scriptStat
e, promise), ScriptValue(scriptState, data.GetValue()), errorMessage, resourceNa
me, scriptId, lineNumber, columnNumber, callStack); | 72 OwnPtrWillBeRawPtr<Message> message = Message::create(ScriptValue(scriptStat
e, promise), ScriptValue(scriptState, data.GetValue()), errorMessage, resourceNa
me, scriptId, lineNumber, columnNumber, callStack); |
69 | 73 |
70 m_queue.append(message.release()); | 74 m_queue.append(message.release()); |
71 } | 75 } |
72 | 76 |
| 77 void RejectedPromises::handlerAdded(v8::PromiseRejectMessage data) |
| 78 { |
| 79 // First look it up in the pending messages and fast return, it'll be covere
d by processQueue(). |
| 80 for (auto it = m_queue.begin(); it != m_queue.end(); ++it) { |
| 81 ScriptState* scriptState = (*it)->m_promise.scriptState(); |
| 82 if (!scriptState->contextIsValid()) |
| 83 continue; |
| 84 |
| 85 ScriptState::Scope scope(scriptState); |
| 86 v8::Handle<v8::Value> promise = (*it)->m_promise.v8Value(); |
| 87 if (promise == data.GetPromise()) |
| 88 return; |
| 89 } |
| 90 |
| 91 // Then look it up in the reported errors. |
| 92 for (auto it = m_reportedAsErrors.begin(); it != m_reportedAsErrors.end(); +
+it) { |
| 93 ScriptState* scriptState = (*it)->m_promise.scriptState(); |
| 94 if (!scriptState->contextIsValid()) |
| 95 continue; |
| 96 |
| 97 ScriptState::Scope scope(scriptState); |
| 98 v8::Handle<v8::Value> promise = (*it)->m_promise.v8Value(); |
| 99 if (promise != data.GetPromise()) |
| 100 continue; |
| 101 |
| 102 // If execution termination has been triggered, quietly bail out. |
| 103 if (v8::V8::IsExecutionTerminating(scriptState->isolate())) |
| 104 continue; |
| 105 ExecutionContext* executionContext = scriptState->executionContext(); |
| 106 if (!executionContext) |
| 107 continue; |
| 108 |
| 109 RefPtrWillBeRawPtr<ConsoleMessage> consoleMessage = ConsoleMessage::crea
te(JSMessageSource, RevokedErrorMessageLevel, "Handler added to rejected promise
"); |
| 110 consoleMessage->setRelatedMessageId((*it)->m_consoleMessageId); |
| 111 executionContext->addConsoleMessage(consoleMessage.release()); |
| 112 m_reportedAsErrors.remove(it); |
| 113 break; |
| 114 } |
| 115 } |
| 116 |
73 void RejectedPromises::dispose() | 117 void RejectedPromises::dispose() |
74 { | 118 { |
75 processQueue(); | 119 processQueue(); |
76 } | 120 } |
77 | 121 |
78 void RejectedPromises::processQueue() | 122 void RejectedPromises::processQueue() |
79 { | 123 { |
80 while (!m_queue.isEmpty()) { | 124 while (!m_queue.isEmpty()) { |
81 OwnPtrWillBeRawPtr<Message> message = m_queue.takeFirst(); | 125 OwnPtrWillBeRawPtr<Message> message = m_queue.takeFirst(); |
82 ScriptState* scriptState = message->m_promise.scriptState(); | 126 ScriptState* scriptState = message->m_promise.scriptState(); |
(...skipping 25 matching lines...) Expand all Loading... |
108 String embedderErrorMessage = message->m_errorMessage; | 152 String embedderErrorMessage = message->m_errorMessage; |
109 if (embedderErrorMessage.isEmpty()) | 153 if (embedderErrorMessage.isEmpty()) |
110 embedderErrorMessage = errorMessage; | 154 embedderErrorMessage = errorMessage; |
111 else if (embedderErrorMessage.startsWith("Uncaught ")) | 155 else if (embedderErrorMessage.startsWith("Uncaught ")) |
112 embedderErrorMessage.insert(" (in promise)", 8); | 156 embedderErrorMessage.insert(" (in promise)", 8); |
113 | 157 |
114 RefPtrWillBeRawPtr<ConsoleMessage> consoleMessage = ConsoleMessage::crea
te(JSMessageSource, ErrorMessageLevel, embedderErrorMessage, message->m_resource
Name, message->m_lineNumber, message->m_columnNumber); | 158 RefPtrWillBeRawPtr<ConsoleMessage> consoleMessage = ConsoleMessage::crea
te(JSMessageSource, ErrorMessageLevel, embedderErrorMessage, message->m_resource
Name, message->m_lineNumber, message->m_columnNumber); |
115 consoleMessage->setScriptArguments(arguments); | 159 consoleMessage->setScriptArguments(arguments); |
116 consoleMessage->setCallStack(message->m_callStack); | 160 consoleMessage->setCallStack(message->m_callStack); |
117 consoleMessage->setScriptId(message->m_scriptId); | 161 consoleMessage->setScriptId(message->m_scriptId); |
| 162 message->m_consoleMessageId = consoleMessage->assignMessageId(); |
118 executionContext->addConsoleMessage(consoleMessage.release()); | 163 executionContext->addConsoleMessage(consoleMessage.release()); |
| 164 |
| 165 m_reportedAsErrors.append(message.release()); |
| 166 if (m_reportedAsErrors.size() > maxReportedHandlersPendingResolution) |
| 167 m_reportedAsErrors.removeFirst(); |
119 } | 168 } |
120 } | 169 } |
121 | 170 |
122 } // namespace blink | 171 } // namespace blink |
OLD | NEW |