Index: Source/bindings/core/v8/V8Initializer.cpp |
diff --git a/Source/bindings/core/v8/V8Initializer.cpp b/Source/bindings/core/v8/V8Initializer.cpp |
index c015f4369ba6bc07caa1c6e6c5cabf3bde7b8558..eedbde6f1e810b2f74fcced568643b7485739254 100644 |
--- a/Source/bindings/core/v8/V8Initializer.cpp |
+++ b/Source/bindings/core/v8/V8Initializer.cpp |
@@ -166,8 +166,12 @@ namespace { |
class PromiseRejectMessage { |
ALLOW_ONLY_INLINE_ALLOCATION(); |
public: |
- PromiseRejectMessage(const ScriptValue& promise, PassRefPtrWillBeRawPtr<ScriptCallStack> callStack) |
+ PromiseRejectMessage(const ScriptValue& promise, const String& resourceURL, int scriptId, unsigned lineNumber, unsigned columnNumber, PassRefPtrWillBeRawPtr<ScriptCallStack> callStack) |
: m_promise(promise) |
+ , m_resourceURL(resourceURL) |
+ , m_scriptId(scriptId) |
+ , m_lineNumber(lineNumber) |
+ , m_columnNumber(columnNumber) |
, m_callStack(callStack) |
{ |
} |
@@ -178,6 +182,10 @@ public: |
} |
const ScriptValue m_promise; |
+ const String m_resourceURL; |
+ const int m_scriptId; |
+ const unsigned m_lineNumber; |
+ const unsigned m_columnNumber; |
const RefPtrWillBeMember<ScriptCallStack> m_callStack; |
}; |
@@ -220,18 +228,19 @@ void V8Initializer::reportRejectedPromises() |
args.append(message.m_promise); |
RefPtrWillBeRawPtr<ScriptArguments> arguments = ScriptArguments::create(scriptState, args); |
- RefPtrWillBeRawPtr<ConsoleMessage> consoleMessage = ConsoleMessage::create(JSMessageSource, ErrorMessageLevel, errorMessage); |
+ RefPtrWillBeRawPtr<ConsoleMessage> consoleMessage = ConsoleMessage::create(JSMessageSource, ErrorMessageLevel, errorMessage, message.m_resourceURL, message.m_lineNumber, message.m_columnNumber); |
consoleMessage->setScriptArguments(arguments); |
consoleMessage->setCallStack(message.m_callStack); |
+ consoleMessage->setScriptId(message.m_scriptId); |
executionContext->addConsoleMessage(consoleMessage.release()); |
} |
} |
-static void promiseRejectHandlerInMainThread(v8::PromiseRejectMessage message) |
+static void promiseRejectHandlerInMainThread(v8::PromiseRejectMessage data) |
{ |
ASSERT(isMainThread()); |
- if (message.GetEvent() != v8::kPromiseRejectWithNoHandler) |
+ if (data.GetEvent() != v8::kPromiseRejectWithNoHandler) |
return; |
// It's possible that promiseRejectHandlerInMainThread() is invoked while we're initializing a window. |
@@ -240,7 +249,7 @@ static void promiseRejectHandlerInMainThread(v8::PromiseRejectMessage message) |
if (DOMWrapperWorld::windowIsBeingInitialized()) |
return; |
- v8::Handle<v8::Promise> promise = message.GetPromise(); |
+ v8::Handle<v8::Promise> promise = data.GetPromise(); |
// Bail out if called during context initialization. |
v8::Isolate* isolate = promise->GetIsolate(); |
@@ -250,35 +259,59 @@ static void promiseRejectHandlerInMainThread(v8::PromiseRejectMessage message) |
v8::Handle<v8::Value> global = V8Window::findInstanceInPrototypeChain(context->Global(), context->GetIsolate()); |
if (global.IsEmpty()) |
return; |
- if (!toFrameIfNotDetached(context)) |
+ |
+ // There is no entered window during microtask callbacks from V8, |
+ // thus we call toDOMWindow() instead of enteredDOMWindow(). |
+ LocalDOMWindow* window = toDOMWindow(context); |
+ if (!window || !window->isCurrentlyDisplayedInFrame()) |
return; |
+ v8::Handle<v8::Value> exception = data.GetValue(); |
+ if (V8DOMWrapper::isDOMWrapper(exception)) { |
+ // Try to get the stack & location from a wrapped exception object (e.g. DOMException). |
+ ASSERT(exception->IsObject()); |
+ v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(exception); |
+ v8::Handle<v8::Value> error = V8HiddenValue::getHiddenValue(isolate, obj, V8HiddenValue::error(isolate)); |
+ if (!error.IsEmpty()) |
+ exception = error; |
+ } |
+ |
+ int scriptId = 0; |
+ unsigned lineNumber = 0; |
+ unsigned columnNumber = 0; |
+ String resourceURL; |
RefPtrWillBeRawPtr<ScriptCallStack> callStack = nullptr; |
- v8::Handle<v8::StackTrace> stackTrace = message.GetStackTrace(); |
- if (!stackTrace.IsEmpty() && stackTrace->GetFrameCount() > 0) |
- callStack = createScriptCallStack(stackTrace, ScriptCallStack::maxCallStackSizeToCapture, isolate); |
- if (!callStack && V8DOMWrapper::isDOMWrapper(message.GetValue())) { |
- // Try to get the stack from a wrapped exception object (e.g. DOMException). |
- v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(message.GetValue()); |
- v8::Handle<v8::Value> error = V8HiddenValue::getHiddenValue(isolate, obj, V8HiddenValue::error(isolate)); |
- if (!error.IsEmpty()) { |
- stackTrace = v8::Exception::GetStackTrace(error); |
- if (!stackTrace.IsEmpty() && stackTrace->GetFrameCount() > 0) |
- callStack = createScriptCallStack(stackTrace, ScriptCallStack::maxCallStackSizeToCapture, isolate); |
+ v8::Handle<v8::Message> message = v8::Exception::GetMessage(exception); |
+ if (!message.IsEmpty()) { |
+ scriptId = message->GetScriptOrigin().ScriptID()->Value(); |
+ lineNumber = static_cast<unsigned>(message->GetLineNumber()); |
+ columnNumber = static_cast<unsigned>(message->GetStartColumn() + 1); |
+ |
+ v8::Handle<v8::Value> resourceName = message->GetScriptOrigin().ResourceName(); |
vsevik
2014/11/07 06:26:38
Looks like a lot of copy-paste here.
Can we at lea
aandrey
2014/11/10 11:44:33
Done.
|
+ bool shouldUseDocumentURL = window->document() && (resourceName.IsEmpty() || !resourceName->IsString()); |
+ resourceURL = shouldUseDocumentURL ? window->document()->url() : toCoreString(resourceName.As<v8::String>()); |
+ |
+ v8::Handle<v8::StackTrace> stackTrace = message->GetStackTrace(); |
vsevik
2014/11/07 06:26:39
extract callStack(stackTrace, isolate)?
aandrey
2014/11/10 11:44:33
Done.
|
+ if (!stackTrace.IsEmpty() && stackTrace->GetFrameCount() > 0) { |
+ callStack = createScriptCallStack(stackTrace, ScriptCallStack::maxCallStackSizeToCapture, isolate); |
+ bool success = false; |
+ int topScriptId = callStack->at(0).scriptId().toInt(&success); |
+ if (success && topScriptId == scriptId) |
+ scriptId = 0; |
vsevik
2014/11/07 06:26:38
extract scriptId(callStack, scriptOrigin)?
aandrey
2014/11/10 11:44:33
Acknowledged.
|
} |
} |
ScriptState* scriptState = ScriptState::from(context); |
- promiseRejectMessageQueue().append(PromiseRejectMessage(ScriptValue(scriptState, promise), callStack)); |
+ promiseRejectMessageQueue().append(PromiseRejectMessage(ScriptValue(scriptState, promise), resourceURL, scriptId, lineNumber, columnNumber, callStack)); |
} |
-static void promiseRejectHandlerInWorker(v8::PromiseRejectMessage message) |
+static void promiseRejectHandlerInWorker(v8::PromiseRejectMessage data) |
{ |
- if (message.GetEvent() != v8::kPromiseRejectWithNoHandler) |
+ if (data.GetEvent() != v8::kPromiseRejectWithNoHandler) |
return; |
- v8::Handle<v8::Promise> promise = message.GetPromise(); |
+ v8::Handle<v8::Promise> promise = data.GetPromise(); |
// Bail out if called during context initialization. |
v8::Isolate* isolate = promise->GetIsolate(); |
@@ -286,13 +319,21 @@ static void promiseRejectHandlerInWorker(v8::PromiseRejectMessage message) |
if (context.IsEmpty()) |
return; |
- RefPtrWillBeRawPtr<ScriptCallStack> callStack = nullptr; |
- v8::Handle<v8::StackTrace> stackTrace = message.GetStackTrace(); |
- if (!stackTrace.IsEmpty() && stackTrace->GetFrameCount() > 0) |
- callStack = createScriptCallStack(stackTrace, ScriptCallStack::maxCallStackSizeToCapture, isolate); |
+ int scriptId = 0; |
+ unsigned lineNumber = 0; |
+ unsigned columnNumber = 0; |
+ String resourceURL; |
+ |
+ v8::Handle<v8::Message> message = v8::Exception::GetMessage(data.GetValue()); |
+ if (!message.IsEmpty()) { |
+ TOSTRING_VOID(V8StringResource<>, resourceURL, message->GetScriptOrigin().ResourceName()); |
+ scriptId = message->GetScriptOrigin().ScriptID()->Value(); |
vsevik
2014/11/07 06:26:38
This is not correct way to use scriptId parameter
yurys
2014/11/07 12:49:27
Can you file a bug on this?
|
+ lineNumber = static_cast<unsigned>(message->GetLineNumber()); |
+ columnNumber = static_cast<unsigned>(message->GetStartColumn() + 1); |
+ } |
ScriptState* scriptState = ScriptState::from(context); |
- promiseRejectMessageQueue().append(PromiseRejectMessage(ScriptValue(scriptState, promise), callStack)); |
+ promiseRejectMessageQueue().append(PromiseRejectMessage(ScriptValue(scriptState, promise), resourceURL, scriptId, lineNumber, columnNumber, nullptr)); |
} |
static void failedAccessCheckCallbackInMainThread(v8::Local<v8::Object> host, v8::AccessType type, v8::Local<v8::Value> data) |