| Index: Source/bindings/core/v8/V8Initializer.cpp
|
| diff --git a/Source/bindings/core/v8/V8Initializer.cpp b/Source/bindings/core/v8/V8Initializer.cpp
|
| index f73978540a245000a78a8a178ab3b90a6fb93a5a..3e3157b30eea1a0a7b7052b561545c2c3e07bf16 100644
|
| --- a/Source/bindings/core/v8/V8Initializer.cpp
|
| +++ b/Source/bindings/core/v8/V8Initializer.cpp
|
| @@ -30,6 +30,7 @@
|
| #include "bindings/core/v8/ScriptCallStackFactory.h"
|
| #include "bindings/core/v8/ScriptController.h"
|
| #include "bindings/core/v8/ScriptProfiler.h"
|
| +#include "bindings/core/v8/ScriptValue.h"
|
| #include "bindings/core/v8/V8Binding.h"
|
| #include "bindings/core/v8/V8DOMException.h"
|
| #include "bindings/core/v8/V8ErrorEvent.h"
|
| @@ -45,6 +46,8 @@
|
| #include "core/frame/LocalDOMWindow.h"
|
| #include "core/frame/LocalFrame.h"
|
| #include "core/frame/csp/ContentSecurityPolicy.h"
|
| +#include "core/inspector/ConsoleMessage.h"
|
| +#include "core/inspector/ScriptArguments.h"
|
| #include "core/inspector/ScriptCallStack.h"
|
| #include "platform/EventDispatchForbiddenScope.h"
|
| #include "platform/TraceEvent.h"
|
| @@ -155,6 +158,78 @@ static void messageHandlerInMainThread(v8::Handle<v8::Message> message, v8::Hand
|
| }
|
| }
|
|
|
| +typedef WillBeHeapDeque<ScriptValue> PromiseRejectMessageQueue;
|
| +
|
| +static PromiseRejectMessageQueue& promiseRejectMessageQueue()
|
| +{
|
| + DEFINE_STATIC_LOCAL(OwnPtrWillBePersistent<PromiseRejectMessageQueue>, queue, (adoptPtrWillBeNoop(new PromiseRejectMessageQueue())));
|
| + return *queue;
|
| +}
|
| +
|
| +void V8Initializer::reportRejectedPromises()
|
| +{
|
| + ASSERT(isMainThread());
|
| +
|
| + PromiseRejectMessageQueue& queue = promiseRejectMessageQueue();
|
| + while (!queue.isEmpty()) {
|
| + ScriptValue promise = queue.takeFirst();
|
| + ScriptState* scriptState = promise.scriptState();
|
| + if (!scriptState->contextIsValid())
|
| + continue;
|
| + ScriptState::Scope scope(scriptState);
|
| +
|
| + ASSERT(!promise.isEmpty());
|
| + v8::Handle<v8::Value> value = promise.v8Value();
|
| + ASSERT(!value.IsEmpty() && value->IsPromise());
|
| + if (v8::Handle<v8::Promise>::Cast(value)->HasHandler())
|
| + continue;
|
| +
|
| + ExecutionContext* executionContext = scriptState->executionContext();
|
| + if (!executionContext)
|
| + continue;
|
| +
|
| + const String errorMessage = "Unhandled promise rejection";
|
| + Vector<ScriptValue> args;
|
| + args.append(ScriptValue(scriptState, v8String(scriptState->isolate(), errorMessage)));
|
| + args.append(promise);
|
| + RefPtrWillBeRawPtr<ScriptArguments> arguments = ScriptArguments::create(scriptState, args);
|
| +
|
| + RefPtrWillBeRawPtr<ConsoleMessage> consoleMessage = ConsoleMessage::create(JSMessageSource, ErrorMessageLevel, errorMessage, "", 0);
|
| + consoleMessage->setScriptArguments(arguments);
|
| + executionContext->addConsoleMessage(consoleMessage.release());
|
| + }
|
| +}
|
| +
|
| +static void promiseRejectHandlerInMainThread(v8::PromiseRejectMessage message)
|
| +{
|
| + ASSERT(isMainThread());
|
| +
|
| + if (message.GetEvent() != v8::kPromiseRejectWithNoHandler)
|
| + return;
|
| +
|
| + // It's possible that promiseRejectHandlerInMainThread() is invoked while we're initializing a window.
|
| + // In that half-baked situation, we don't have a valid context nor a valid world,
|
| + // so just return immediately.
|
| + if (DOMWrapperWorld::windowIsBeingInitialized())
|
| + return;
|
| +
|
| + v8::Handle<v8::Promise> promise = message.GetPromise();
|
| +
|
| + // Bail out if called during context initialization.
|
| + v8::Isolate* isolate = promise->GetIsolate();
|
| + v8::Handle<v8::Context> context = isolate->GetCurrentContext();
|
| + if (context.IsEmpty())
|
| + return;
|
| + v8::Handle<v8::Value> global = V8Window::findInstanceInPrototypeChain(context->Global(), context->GetIsolate());
|
| + if (global.IsEmpty())
|
| + return;
|
| + if (!toFrameIfNotDetached(context))
|
| + return;
|
| +
|
| + ScriptState* scriptState = ScriptState::from(context);
|
| + promiseRejectMessageQueue().append(ScriptValue(scriptState, promise));
|
| +}
|
| +
|
| static void failedAccessCheckCallbackInMainThread(v8::Local<v8::Object> host, v8::AccessType type, v8::Local<v8::Value> data)
|
| {
|
| v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
| @@ -218,6 +293,7 @@ void V8Initializer::initializeMainThreadIfNeeded()
|
| v8::V8::SetAllowCodeGenerationFromStringsCallback(codeGenerationCheckCallbackInMainThread);
|
|
|
| isolate->SetEventLogger(timerTraceProfilerInMainThread);
|
| + isolate->SetPromiseRejectCallback(promiseRejectHandlerInMainThread);
|
|
|
| ScriptProfiler::initialize();
|
| }
|
|
|