| 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
|
|
|