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

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: added promise.catch in test-helpers.js 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..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();
}
« 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