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..ab1cc6afaa958b1db5ecc97a1eb1e432f3794c30 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,61 @@ 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()) |
pfeldman
2014/10/06 19:40:13
That's a really bad name. Lets swap the semantics
Jens Widell
2014/10/07 05:22:23
https://codereview.chromium.org/622333002/
aandrey
2014/10/07 10:03:37
Acknowledged.
|
+ 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; |
+ |
+ 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); |
+ scriptState->executionContext()->addConsoleMessage(consoleMessage.release()); |
yurys
2014/10/07 05:32:44
We should be careful not to call this on ScriptSta
aandrey
2014/10/07 10:03:37
Added a test, this case does not repro.
Seems like
|
+ } |
+} |
+ |
+static void promiseRejectHandlerInMainThread(v8::Handle<v8::Promise> promise, v8::Handle<v8::Value> /*value*/, v8::PromiseRejectEvent event) |
+{ |
+ ASSERT(isMainThread()); |
+ |
+ if (event != 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; |
+ |
+ ScriptState* scriptState = ScriptState::current(promise->GetIsolate()); |
+ 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 +276,7 @@ void V8Initializer::initializeMainThreadIfNeeded() |
v8::V8::SetAllowCodeGenerationFromStringsCallback(codeGenerationCheckCallbackInMainThread); |
isolate->SetEventLogger(timerTraceProfilerInMainThread); |
+ isolate->SetPromiseRejectCallback(promiseRejectHandlerInMainThread); |
ScriptProfiler::initialize(); |
} |