Skip to content
Permalink
Browse files
2010-07-19 Yury Semikhatsky <yurys@chromium.org>
        Reviewed by Pavel Feldman.

        Web Inspector: show stack trace for uncaught exceptions when Web Inspector is open.
        https://bugs.webkit.org/show_bug.cgi?id=42560

        * bindings/js/ScriptController.cpp:
        (WebCore::ScriptController::setCaptureCallStackForUncaughtExceptions):
        * bindings/js/ScriptController.h:
        * bindings/v8/ScriptController.cpp:
        (WebCore::ScriptController::setCaptureCallStackForUncaughtExceptions):
        * bindings/v8/ScriptController.h:
        * bindings/v8/V8ConsoleMessage.cpp:
        (WebCore::V8ConsoleMessage::dispatchNow):
        (WebCore::V8ConsoleMessage::handler):
        * bindings/v8/V8ConsoleMessage.h:
        * inspector/ConsoleMessage.cpp:
        (WebCore::ConsoleMessage::ConsoleMessage):
        * inspector/ConsoleMessage.h:
        * inspector/InspectorController.cpp:
        (WebCore::InspectorController::addMessageToConsole):
        (WebCore::InspectorController::startGroup):
        (WebCore::InspectorController::connectFrontend):
        (WebCore::InspectorController::disconnectFrontend):
        * inspector/InspectorController.h:
        * inspector/front-end/ConsoleView.js:
        (WebInspector.ConsoleMessage.prototype._formatMessage):
        (WebInspector.ConsoleMessage.prototype.toMessageElement):
        (WebInspector.ConsoleMessage.prototype._populateStackTraceTreeElement):
        (WebInspector.ConsoleMessage.prototype._addMessageHeader):
        (WebInspector.ConsoleMessage.prototype.toString):
        * inspector/front-end/inspector.css:
        (.console-message.repeated-message > ol.stack-trace):
        (.section .properties ol, .event-properties ol, .stack-trace ol, ol.stack-trace):
        (ol.stack-trace):
        (.section .properties ol.expanded, .event-properties ol.expanded, .stack-trace ol, ol.stack-trace):
        * page/Console.cpp:
        (WebCore::Console::addMessage):
        * page/Console.h:
        (WebCore::):

Canonical link: https://commits.webkit.org/54502@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@63662 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
yury-s committed Jul 19, 2010
1 parent 395cd08 commit d6c5c271168b99281ba6def0a65a381d3cb89016
@@ -1,3 +1,45 @@
2010-07-19 Yury Semikhatsky <yurys@chromium.org>

Reviewed by Pavel Feldman.

Web Inspector: show stack trace for uncaught exceptions when Web Inspector is open.
https://bugs.webkit.org/show_bug.cgi?id=42560

* bindings/js/ScriptController.cpp:
(WebCore::ScriptController::setCaptureCallStackForUncaughtExceptions):
* bindings/js/ScriptController.h:
* bindings/v8/ScriptController.cpp:
(WebCore::ScriptController::setCaptureCallStackForUncaughtExceptions):
* bindings/v8/ScriptController.h:
* bindings/v8/V8ConsoleMessage.cpp:
(WebCore::V8ConsoleMessage::dispatchNow):
(WebCore::V8ConsoleMessage::handler):
* bindings/v8/V8ConsoleMessage.h:
* inspector/ConsoleMessage.cpp:
(WebCore::ConsoleMessage::ConsoleMessage):
* inspector/ConsoleMessage.h:
* inspector/InspectorController.cpp:
(WebCore::InspectorController::addMessageToConsole):
(WebCore::InspectorController::startGroup):
(WebCore::InspectorController::connectFrontend):
(WebCore::InspectorController::disconnectFrontend):
* inspector/InspectorController.h:
* inspector/front-end/ConsoleView.js:
(WebInspector.ConsoleMessage.prototype._formatMessage):
(WebInspector.ConsoleMessage.prototype.toMessageElement):
(WebInspector.ConsoleMessage.prototype._populateStackTraceTreeElement):
(WebInspector.ConsoleMessage.prototype._addMessageHeader):
(WebInspector.ConsoleMessage.prototype.toString):
* inspector/front-end/inspector.css:
(.console-message.repeated-message > ol.stack-trace):
(.section .properties ol, .event-properties ol, .stack-trace ol, ol.stack-trace):
(ol.stack-trace):
(.section .properties ol.expanded, .event-properties ol.expanded, .stack-trace ol, ol.stack-trace):
* page/Console.cpp:
(WebCore::Console::addMessage):
* page/Console.h:
(WebCore::):

2010-07-19 Robin Burchell <robin.burchell@collabora.co.uk>

Reviewed by Antonio Gomes
@@ -379,6 +379,12 @@ PassRefPtr<Bindings::RootObject> ScriptController::createRootObject(void* native
return rootObject.release();
}

#if ENABLE(INSPECTOR)
void ScriptController::setCaptureCallStackForUncaughtExceptions(bool)
{
}
#endif

#if ENABLE(NETSCAPE_PLUGIN_API)

NPObject* ScriptController::windowScriptNPObject()
@@ -151,6 +151,10 @@ class ScriptController {

PassRefPtr<JSC::Bindings::RootObject> createRootObject(void* nativeHandle);

#if ENABLE(INSPECTOR)
static void setCaptureCallStackForUncaughtExceptions(bool);
#endif

#if PLATFORM(MAC)
#if ENABLE(JAVA_BRIDGE)
static void initJavaJSBindings();
@@ -451,6 +451,13 @@ void ScriptController::clearWindowShell(bool)
m_proxy->clearForNavigation();
}

#if ENABLE(INSPECTOR)
void ScriptController::setCaptureCallStackForUncaughtExceptions(bool)
{
v8::V8::SetCaptureStackTraceForUncaughtExceptions(true, 200);
}
#endif

void ScriptController::attachDebugger(void*)
{
notImplemented();
@@ -116,6 +116,10 @@ class ScriptController {

static bool canAccessFromCurrentOrigin(Frame*);

#if ENABLE(INSPECTOR)
static void setCaptureCallStackForUncaughtExceptions(bool);
#endif

bool canExecuteScripts(ReasonForCallingCanExecuteScripts);

// FIXME: void* is a compile hack.
@@ -36,6 +36,7 @@
#include "Frame.h"
#include "OwnPtr.h"
#include "Page.h"
#include "ScriptCallStack.h"
#include "V8Binding.h"
#include "V8Proxy.h"

@@ -52,14 +53,7 @@ V8ConsoleMessage::V8ConsoleMessage(const String& string, const String& sourceID,

void V8ConsoleMessage::dispatchNow(Page* page)
{
ASSERT(page);

// Process any delayed messages to make sure that messages
// appear in the right order in the console.
processDelayed();

Console* console = page->mainFrame()->domWindow()->console();
console->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, m_string, m_lineNumber, m_sourceID);
dispatchNow(page, 0);
}

void V8ConsoleMessage::dispatchLater()
@@ -118,11 +112,33 @@ void V8ConsoleMessage::handler(v8::Handle<v8::Message> message, v8::Handle<v8::V
ASSERT(!errorMessageString.IsEmpty());
String errorMessage = toWebCoreString(errorMessageString);

v8::Handle<v8::StackTrace> stackTrace = message->GetStackTrace();
OwnPtr<ScriptCallStack> callStack;
// Currently stack trace is only collected when inspector is open.
if (!stackTrace.IsEmpty()) {
v8::Local<v8::Context> context = v8::Context::GetEntered();
ScriptState* scriptState = ScriptState::forContext(context);
callStack = ScriptCallStack::create(scriptState, stackTrace);
}

v8::Handle<v8::Value> resourceName = message->GetScriptResourceName();
bool useURL = resourceName.IsEmpty() || !resourceName->IsString();
String resourceNameString = useURL ? frame->document()->url() : toWebCoreString(resourceName);
V8ConsoleMessage consoleMessage(errorMessage, resourceNameString, message->GetLineNumber());
consoleMessage.dispatchNow(page);
consoleMessage.dispatchNow(page, callStack.get());
}

void V8ConsoleMessage::dispatchNow(Page* page, ScriptCallStack* callStack)
{
ASSERT(page);

// Process any delayed messages to make sure that messages
// appear in the right order in the console.
processDelayed();

Console* console = page->mainFrame()->domWindow()->console();
MessageType messageType = callStack ? UncaughtExceptionMessageType : LogMessageType;
console->addMessage(JSMessageSource, messageType, ErrorMessageLevel, m_string, m_lineNumber, m_sourceID, callStack);
}

} // namespace WebCore
@@ -36,8 +36,9 @@
#include <wtf/Vector.h>

namespace WebCore {

class Page;
class ScriptCallStack;

// V8ConsoleMessage encapsulates everything needed to
// log messages originating from JavaScript to the console.
@@ -80,6 +81,8 @@ namespace WebCore {
const String m_sourceID;
const unsigned m_lineNumber;

void dispatchNow(Page*, ScriptCallStack*);

// All delayed messages are stored in this vector. If the vector
// is 0, there are no delayed messages.
static Vector<V8ConsoleMessage>* m_delayedMessages;
@@ -80,10 +80,11 @@ ConsoleMessage::ConsoleMessage(MessageSource s, MessageType t, MessageLevel l, c
{
}

ConsoleMessage::ConsoleMessage(MessageSource s, MessageType t, MessageLevel l, ScriptCallStack* callStack, unsigned g, bool storeTrace)
ConsoleMessage::ConsoleMessage(MessageSource s, MessageType t, MessageLevel l, const String& m, ScriptCallStack* callStack, unsigned g, bool storeTrace)
: m_source(s)
, m_type(t)
, m_level(l)
, m_message(m)
#if ENABLE(INSPECTOR)
, m_arguments(callStack->at(0).argumentCount())
, m_scriptState(callStack->globalState())
@@ -48,7 +48,7 @@ class ScriptString;
class ConsoleMessage : public Noncopyable {
public:
ConsoleMessage(MessageSource, MessageType, MessageLevel, const String& m, unsigned li, const String& u, unsigned g);
ConsoleMessage(MessageSource, MessageType, MessageLevel, ScriptCallStack*, unsigned g, bool storeTrace = false);
ConsoleMessage(MessageSource, MessageType, MessageLevel, const String& m, ScriptCallStack*, unsigned g, bool storeTrace = false);

#if ENABLE(INSPECTOR)
void addToFrontend(InspectorFrontend*, InjectedScriptHost*);
@@ -129,6 +129,8 @@ static const char* const inspectorAttachedHeightName = "inspectorAttachedHeight"
static const char* const lastActivePanelSettingName = "lastActivePanel";
static const char* const monitoringXHRSettingName = "xhrMonitor";

int connectedFrontendCount = 0;

const String& InspectorController::frontendSettingsSettingName()
{
DEFINE_STATIC_LOCAL(String, settingName, ("frontendSettings"));
@@ -336,12 +338,12 @@ bool InspectorController::windowVisible()
return m_frontend;
}

void InspectorController::addMessageToConsole(MessageSource source, MessageType type, MessageLevel level, ScriptCallStack* callStack)
void InspectorController::addMessageToConsole(MessageSource source, MessageType type, MessageLevel level, ScriptCallStack* callStack, const String& message)
{
if (!enabled())
return;

addConsoleMessage(callStack->state(), new ConsoleMessage(source, type, level, callStack, m_groupLevel, type == TraceMessageType));
addConsoleMessage(callStack->state(), new ConsoleMessage(source, type, level, message, callStack, m_groupLevel, type == TraceMessageType || type == UncaughtExceptionMessageType));
}

void InspectorController::addMessageToConsole(MessageSource source, MessageType type, MessageLevel level, const String& message, unsigned lineNumber, const String& sourceID)
@@ -391,7 +393,7 @@ void InspectorController::startGroup(MessageSource source, ScriptCallStack* call
{
++m_groupLevel;

addConsoleMessage(callStack->state(), new ConsoleMessage(source, collapsed ? StartGroupCollapsedMessageType : StartGroupMessageType, LogMessageLevel, callStack, m_groupLevel));
addConsoleMessage(callStack->state(), new ConsoleMessage(source, collapsed ? StartGroupCollapsedMessageType : StartGroupMessageType, LogMessageLevel, String(), callStack, m_groupLevel));
}

void InspectorController::endGroup(MessageSource source, unsigned lineNumber, const String& sourceURL)
@@ -530,6 +532,10 @@ void InspectorController::connectFrontend(const ScriptObject& webInspector)
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
m_applicationCacheAgent = new InspectorApplicationCacheAgent(this, m_frontend.get());
#endif

if (!connectedFrontendCount)
ScriptController::setCaptureCallStackForUncaughtExceptions(true);
connectedFrontendCount++;
}

void InspectorController::show()
@@ -579,6 +585,10 @@ void InspectorController::disconnectFrontend()
return;
m_frontend.clear();

connectedFrontendCount--;
if (!connectedFrontendCount)
ScriptController::setCaptureCallStackForUncaughtExceptions(false);

#if ENABLE(JAVASCRIPT_DEBUGGER)
// If the window is being closed with the debugger enabled,
// remember this state to re-enable debugger on the next window
@@ -151,7 +151,7 @@ class InspectorController
void connectFrontend(const ScriptObject& webInspector);
void disconnectFrontend();

void addMessageToConsole(MessageSource, MessageType, MessageLevel, ScriptCallStack*);
void addMessageToConsole(MessageSource, MessageType, MessageLevel, ScriptCallStack*, const String& message = String());
void addMessageToConsole(MessageSource, MessageType, MessageLevel, const String& message, unsigned lineNumber, const String& sourceID);
void clearConsoleMessages();
const Vector<OwnPtr<ConsoleMessage> >& consoleMessages() const { return m_consoleMessages; }
@@ -673,8 +673,23 @@ WebInspector.ConsoleMessage.prototype = {
{
switch (this.type) {
case WebInspector.ConsoleMessage.MessageType.Trace:
this.formattedMessage = this._createStackTraceElement();
this.formattedMessage.addStyleClass("trace-message");
case WebInspector.ConsoleMessage.MessageType.UncaughtException:
var ol = document.createElement("ol");
ol.addStyleClass("stack-trace");
if (this.type === WebInspector.ConsoleMessage.MessageType.Trace)
ol.addStyleClass("trace-message");
var treeOutline = new TreeOutline(ol);

var root = treeOutline;
if (this.type === WebInspector.ConsoleMessage.MessageType.UncaughtException) {
var li = document.createElement("li");
this._addMessageHeader(li, document.createTextNode(this._messageText));
root = new TreeElement(li.innerHTML, null, true);
treeOutline.appendChild(root);
}

this._populateStackTraceTreeElement(root);
this.formattedMessage = ol;
break;
case WebInspector.ConsoleMessage.MessageType.Object:
var obj = this._parameters ? this._parameters[0] : undefined;
@@ -825,38 +840,20 @@ WebInspector.ConsoleMessage.prototype = {
return element;
}

if (this.type === WebInspector.ConsoleMessage.MessageType.Trace) {
if (this.type === WebInspector.ConsoleMessage.MessageType.Trace ||
this.type === WebInspector.ConsoleMessage.MessageType.UncaughtException)
element.appendChild(this.formattedMessage);
} else {
if (this.url && this.url !== "undefined") {
var urlElement = WebInspector.linkifyResourceAsNode(this.url, "scripts", this.line, "console-message-url");
element.appendChild(urlElement);
}

var messageTextElement = document.createElement("span");
messageTextElement.className = "console-message-text source-code";
if (this.type === WebInspector.ConsoleMessage.MessageType.Assert)
messageTextElement.appendChild(document.createTextNode(WebInspector.UIString("Assertion failed: ")));
messageTextElement.appendChild(this.formattedMessage);
element.appendChild(messageTextElement);

if (this._stackTrace) {
var ol = this._createStackTraceElement();
element.appendChild(ol);
}
}
else
this._addMessageHeader(element, this.formattedMessage);

if (this.repeatCount > 1)
this._updateRepeatCount();

return element;
},

_createStackTraceElement: function()
_populateStackTraceTreeElement: function(parentTreeElement)
{
var ol = document.createElement("ol");
ol.addStyleClass("stack-trace");
var treeOutline = new TreeOutline(ol);
for (var i = 0; i < this._stackTrace.length; i++) {
var frame = this._stackTrace[i];

@@ -870,11 +867,24 @@ WebInspector.ConsoleMessage.prototype = {
var urlElement = WebInspector.linkifyResourceAsNode(frame.sourceURL, "scripts", frame.lineNumber, "console-message-url");
li.appendChild(urlElement);


var treeElement = new TreeElement(li.innerHTML);
treeOutline.appendChild(treeElement);
parentTreeElement.appendChild(treeElement);
}
return ol;
},

_addMessageHeader: function(parentElement, formattedMessage)
{
if (this.url && this.url !== "undefined") {
var urlElement = WebInspector.linkifyResourceAsNode(this.url, "scripts", this.line, "console-message-url");
parentElement.appendChild(urlElement);
}

var messageTextElement = document.createElement("span");
messageTextElement.className = "console-message-text source-code";
if (this.type === WebInspector.ConsoleMessage.MessageType.Assert)
messageTextElement.appendChild(document.createTextNode(WebInspector.UIString("Assertion failed: ")));
messageTextElement.appendChild(formattedMessage);
parentElement.appendChild(messageTextElement);
},

_updateRepeatCount: function() {
@@ -915,6 +925,7 @@ WebInspector.ConsoleMessage.prototype = {
var typeString;
switch (this.type) {
case WebInspector.ConsoleMessage.MessageType.Log:
case WebInspector.ConsoleMessage.MessageType.UncaughtException:
typeString = "Log";
break;
case WebInspector.ConsoleMessage.MessageType.Object:
@@ -994,7 +1005,8 @@ WebInspector.ConsoleMessage.MessageType = {
StartGroupCollapsed: 4,
EndGroup: 5,
Assert: 6,
Result: 7
UncaughtException: 7,
Result: 8
}

WebInspector.ConsoleMessage.MessageLevel = {

0 comments on commit d6c5c27

Please sign in to comment.