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

Unified Diff: Source/bindings/core/v8/V8Initializer.cpp

Issue 625943002: Catch uncaught promise rejections from V8 and log to console. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 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
« no previous file with comments | « Source/bindings/core/v8/V8Initializer.h ('k') | Source/web/WebKit.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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();
}
« no previous file with comments | « Source/bindings/core/v8/V8Initializer.h ('k') | Source/web/WebKit.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698