Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(106)

Unified Diff: third_party/WebKit/Source/bindings/core/v8/RejectedPromises.cpp

Issue 1416163003: Reland "Don't report promise rejection events during the microtask checkpoint" (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: updates Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/bindings/core/v8/RejectedPromises.cpp
diff --git a/third_party/WebKit/Source/bindings/core/v8/RejectedPromises.cpp b/third_party/WebKit/Source/bindings/core/v8/RejectedPromises.cpp
index 3ed8d247ee5d1659fbe25554de1e4a079984cff1..55193ae26f66552eddc55e010af7a682e37e6c7b 100644
--- a/third_party/WebKit/Source/bindings/core/v8/RejectedPromises.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/RejectedPromises.cpp
@@ -15,6 +15,12 @@
#include "core/inspector/ConsoleMessage.h"
#include "core/inspector/ScriptArguments.h"
#include "platform/RuntimeEnabledFeatures.h"
+#include "platform/Task.h"
+#include "public/platform/Platform.h"
+#include "public/platform/WebScheduler.h"
+#include "public/platform/WebTaskRunner.h"
+#include "public/platform/WebThread.h"
+#include "wtf/Functional.h"
namespace blink {
@@ -22,7 +28,7 @@ static const unsigned maxReportedHandlersPendingResolution = 1000;
class RejectedPromises::Message final : public NoBaseWillBeGarbageCollectedFinalized<RejectedPromises::Message> {
public:
- static PassOwnPtrWillBeRawPtr<Message> create(ScriptState* scriptState, v8::Local<v8::Promise> promise, const ScriptValue& exception, const String& errorMessage, const String& resourceName, int scriptId, int lineNumber, int columnNumber, PassRefPtrWillBeRawPtr<ScriptCallStack> callStack)
+ static PassOwnPtrWillBeRawPtr<Message> create(ScriptState* scriptState, v8::Local<v8::Promise> promise, v8::Local<v8::Value> exception, const String& errorMessage, const String& resourceName, int scriptId, int lineNumber, int columnNumber, PassRefPtrWillBeRawPtr<ScriptCallStack> callStack)
{
return adoptPtrWillBeNoop(new Message(scriptState, promise, exception, errorMessage, resourceName, scriptId, lineNumber, columnNumber, callStack));
}
@@ -56,16 +62,17 @@ public:
ScriptState::Scope scope(m_scriptState);
v8::Local<v8::Value> value = m_promise.newLocal(m_scriptState->isolate());
+ v8::Local<v8::Value> reason = m_exception.newLocal(m_scriptState->isolate());
// Either collected or https://crbug.com/450330
if (value.IsEmpty() || !value->IsPromise())
return;
- ASSERT(!v8::Local<v8::Promise>::Cast(value)->HasHandler());
+ ASSERT(!hasHandler());
EventTarget* target = executionContext->errorEventTarget();
if (RuntimeEnabledFeatures::promiseRejectionEventEnabled() && target) {
PromiseRejectionEventInit init;
init.setPromise(ScriptPromise(m_scriptState, value));
- init.setReason(m_exception);
+ init.setReason(ScriptValue(m_scriptState, reason));
init.setCancelable(true);
RefPtrWillBeRawPtr<PromiseRejectionEvent> event = PromiseRejectionEvent::create(m_scriptState, EventTypeNames::unhandledrejection, init);
// Log to console if event was not preventDefault()'ed.
@@ -76,7 +83,7 @@ public:
const String errorMessage = "Uncaught (in promise)";
Vector<ScriptValue> args;
args.append(ScriptValue(m_scriptState, v8String(m_scriptState->isolate(), errorMessage)));
- args.append(m_exception);
+ args.append(ScriptValue(m_scriptState, reason));
RefPtrWillBeRawPtr<ScriptArguments> arguments = ScriptArguments::create(m_scriptState, args);
String embedderErrorMessage = m_errorMessage;
@@ -104,6 +111,7 @@ public:
ScriptState::Scope scope(m_scriptState);
v8::Local<v8::Value> value = m_promise.newLocal(m_scriptState->isolate());
+ v8::Local<v8::Value> reason = m_exception.newLocal(m_scriptState->isolate());
// Either collected or https://crbug.com/450330
if (value.IsEmpty() || !value->IsPromise())
return;
@@ -112,7 +120,7 @@ public:
if (RuntimeEnabledFeatures::promiseRejectionEventEnabled() && target) {
PromiseRejectionEventInit init;
init.setPromise(ScriptPromise(m_scriptState, value));
- init.setReason(m_exception);
+ init.setReason(ScriptValue(m_scriptState, reason));
RefPtrWillBeRawPtr<PromiseRejectionEvent> event = PromiseRejectionEvent::create(m_scriptState, EventTypeNames::rejectionhandled, init);
target->dispatchEvent(event);
}
@@ -124,11 +132,34 @@ public:
}
}
+ void makePromiseWeak()
+ {
+ ASSERT(!m_promise.isEmpty() && !m_promise.isWeak());
+ m_promise.setWeak(this, &Message::didCollectPromise);
+ m_exception.setWeak(this, &Message::didCollectException);
+ }
+
+ void makePromiseStrong()
+ {
+ ASSERT(!m_promise.isEmpty() && m_promise.isWeak());
+ m_promise.clearWeak();
+ m_exception.clearWeak();
+ }
+
+ bool hasHandler()
+ {
+ if (isCollected())
+ return false;
+ ScriptState::Scope scope(m_scriptState);
+ v8::Local<v8::Value> value = m_promise.newLocal(m_scriptState->isolate());
+ return v8::Local<v8::Promise>::Cast(value)->HasHandler();
+ }
+
private:
- Message(ScriptState* scriptState, v8::Local<v8::Promise> promise, const ScriptValue& exception, const String& errorMessage, const String& resourceName, int scriptId, int lineNumber, int columnNumber, PassRefPtrWillBeRawPtr<ScriptCallStack> callStack)
+ Message(ScriptState* scriptState, v8::Local<v8::Promise> promise, v8::Local<v8::Value> exception, const String& errorMessage, const String& resourceName, int scriptId, int lineNumber, int columnNumber, PassRefPtrWillBeRawPtr<ScriptCallStack> callStack)
: m_scriptState(scriptState)
, m_promise(scriptState->isolate(), promise)
- , m_exception(exception)
+ , m_exception(scriptState->isolate(), exception)
, m_errorMessage(errorMessage)
, m_resourceName(resourceName)
, m_scriptId(scriptId)
@@ -139,7 +170,6 @@ private:
, m_collected(false)
, m_shouldLogToConsole(true)
{
- m_promise.setWeak(this, &Message::didCollectPromise);
}
static void didCollectPromise(const v8::WeakCallbackInfo<Message>& data)
@@ -148,9 +178,14 @@ private:
data.GetParameter()->m_promise.clear();
}
+ static void didCollectException(const v8::WeakCallbackInfo<Message>& data)
+ {
+ data.GetParameter()->m_exception.clear();
+ }
+
ScriptState* m_scriptState;
ScopedPersistent<v8::Promise> m_promise;
- ScriptValue m_exception;
+ ScopedPersistent<v8::Value> m_exception;
String m_errorMessage;
String m_resourceName;
int m_scriptId;
@@ -176,7 +211,7 @@ DEFINE_TRACE(RejectedPromises)
void RejectedPromises::rejectedWithNoHandler(ScriptState* scriptState, v8::PromiseRejectMessage data, const String& errorMessage, const String& resourceName, int scriptId, int lineNumber, int columnNumber, PassRefPtrWillBeRawPtr<ScriptCallStack> callStack)
{
- m_queue.append(Message::create(scriptState, data.GetPromise(), ScriptValue(scriptState, data.GetValue()), errorMessage, resourceName, scriptId, lineNumber, columnNumber, callStack));
+ m_queue.append(Message::create(scriptState, data.GetPromise(), data.GetValue(), errorMessage, resourceName, scriptId, lineNumber, columnNumber, callStack));
}
void RejectedPromises::handlerAdded(v8::PromiseRejectMessage data)
@@ -193,20 +228,41 @@ void RejectedPromises::handlerAdded(v8::PromiseRejectMessage data)
for (size_t i = 0; i < m_reportedAsErrors.size(); ++i) {
auto& message = m_reportedAsErrors.at(i);
if (!message->isCollected() && message->hasPromise(data.GetPromise())) {
- message->revoke();
+ message->makePromiseStrong();
+ Platform::current()->currentThread()->scheduler()->timerTaskRunner()->postTask(BLINK_FROM_HERE, new Task(bind(&RejectedPromises::revokeNow, PassRefPtrWillBeRawPtr<RejectedPromises>(this), message.release())));
m_reportedAsErrors.remove(i);
return;
}
}
}
+PassOwnPtrWillBeRawPtr<RejectedPromises::MessageQueue> RejectedPromises::createMessageQueue()
+{
+ return adoptPtrWillBeNoop(new MessageQueue());
+}
+
void RejectedPromises::dispose()
{
- processQueue();
+ if (m_queue.isEmpty())
+ return;
+
+ OwnPtrWillBeRawPtr<MessageQueue> queue = createMessageQueue();
+ queue->swap(m_queue);
+ processQueueNow(queue.release());
}
void RejectedPromises::processQueue()
{
+ if (m_queue.isEmpty())
+ return;
+
+ OwnPtrWillBeRawPtr<MessageQueue> queue = createMessageQueue();
+ queue->swap(m_queue);
+ Platform::current()->currentThread()->scheduler()->timerTaskRunner()->postTask(BLINK_FROM_HERE, new Task(bind(&RejectedPromises::processQueueNow, PassRefPtrWillBeRawPtr<RejectedPromises>(this), queue.release())));
+}
+
+void RejectedPromises::processQueueNow(PassOwnPtrWillBeRawPtr<MessageQueue> queue)
+{
// Remove collected handlers.
for (size_t i = 0; i < m_reportedAsErrors.size();) {
if (m_reportedAsErrors.at(i)->isCollected())
@@ -215,16 +271,21 @@ void RejectedPromises::processQueue()
++i;
}
- while (!m_queue.isEmpty()) {
- OwnPtrWillBeRawPtr<Message> message = m_queue.takeFirst();
- if (message->isCollected())
- continue;
-
- message->report();
- m_reportedAsErrors.append(message.release());
- if (m_reportedAsErrors.size() > maxReportedHandlersPendingResolution)
- m_reportedAsErrors.remove(0, maxReportedHandlersPendingResolution / 10);
+ while (!queue->isEmpty()) {
+ OwnPtrWillBeRawPtr<Message> message = queue->takeFirst();
+ if (!message->hasHandler()) {
+ message->report();
+ message->makePromiseWeak();
+ m_reportedAsErrors.append(message.release());
+ if (m_reportedAsErrors.size() > maxReportedHandlersPendingResolution)
+ m_reportedAsErrors.remove(0, maxReportedHandlersPendingResolution / 10);
+ }
}
}
+void RejectedPromises::revokeNow(PassOwnPtrWillBeRawPtr<Message> message)
+{
+ message->revoke();
+}
+
} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698