diff options
Diffstat (limited to 'WebCore/page/Console.cpp')
-rw-r--r-- | WebCore/page/Console.cpp | 417 |
1 files changed, 400 insertions, 17 deletions
diff --git a/WebCore/page/Console.cpp b/WebCore/page/Console.cpp index d45af62..bfcc478 100644 --- a/WebCore/page/Console.cpp +++ b/WebCore/page/Console.cpp @@ -29,11 +29,24 @@ #include "config.h" #include "Console.h" -#include "Chrome.h" +#include "ChromeClient.h" +#include "CString.h" #include "Frame.h" #include "FrameLoader.h" +#include "FrameTree.h" +#include "InspectorController.h" +#include "JSDOMBinding.h" #include "Page.h" +#include "PageGroup.h" #include "PlatformString.h" +#include <runtime/ArgList.h> +#include <kjs/interpreter.h> +#include <runtime/JSObject.h> +#include <VM/Machine.h> +#include <profiler/Profiler.h> +#include <stdio.h> + +using namespace JSC; namespace WebCore { @@ -47,52 +60,422 @@ void Console::disconnectFrame() m_frame = 0; } -void Console::error(const String& message) +static void printSourceURLAndLine(const String& sourceURL, unsigned lineNumber) { - if (!m_frame) + if (!sourceURL.isEmpty()) { + if (lineNumber > 0) + printf("%s:%d: ", sourceURL.utf8().data(), lineNumber); + else + printf("%s: ", sourceURL.utf8().data()); + } +} + +static void printMessageSourceAndLevelPrefix(MessageSource source, MessageLevel level) +{ + const char* sourceString; + switch (source) { + case HTMLMessageSource: + sourceString = "HTML"; + break; + case XMLMessageSource: + sourceString = "XML"; + break; + case JSMessageSource: + sourceString = "JS"; + break; + case CSSMessageSource: + sourceString = "CSS"; + break; + default: + ASSERT_NOT_REACHED(); + // Fall thru. + case OtherMessageSource: + sourceString = "OTHER"; + break; + } + + const char* levelString; + switch (level) { + case TipMessageLevel: + levelString = "TIP"; + break; + default: + ASSERT_NOT_REACHED(); + // Fall thru. + case LogMessageLevel: + levelString = "LOG"; + break; + case WarningMessageLevel: + levelString = "WARN"; + break; + case ErrorMessageLevel: + levelString = "ERROR"; + break; + } + + printf("%s %s:", sourceString, levelString); +} + +static void printToStandardOut(MessageSource source, MessageLevel level, const String& message, const String& sourceURL, unsigned lineNumber) +{ + if (!Console::shouldPrintExceptions()) return; - Page* page = m_frame->page(); + printSourceURLAndLine(sourceURL, lineNumber); + printMessageSourceAndLevelPrefix(source, level); + + printf(" %s\n", message.utf8().data()); +} + +static void printToStandardOut(MessageLevel level, ExecState* exec, const ArgList& args, const KURL& url) +{ + if (!Console::shouldPrintExceptions()) + return; + + printSourceURLAndLine(url.prettyURL(), 0); + printMessageSourceAndLevelPrefix(JSMessageSource, level); + + for (size_t i = 0; i < args.size(); ++i) { + UString argAsString = args.at(exec, i)->toString(exec); + printf(" %s", argAsString.UTF8String().c_str()); + } + + printf("\n"); +} + +static inline void retrieveLastCaller(ExecState* exec, KURL& url, unsigned& lineNumber) +{ + int signedLineNumber; + intptr_t sourceID; + UString urlString; + JSValue* function; + + exec->machine()->retrieveLastCaller(exec, signedLineNumber, sourceID, urlString, function); + + url = KURL(urlString); + lineNumber = (signedLineNumber >= 0 ? signedLineNumber : 0); +} + +void Console::addMessage(MessageSource source, MessageLevel level, const String& message, unsigned lineNumber, const String& sourceURL) +{ + Page* page = this->page(); if (!page) return; - page->chrome()->addMessageToConsole(JSMessageSource, ErrorMessageLevel, message, 0, m_frame->loader()->url().prettyURL()); + if (source == JSMessageSource) + page->chrome()->client()->addMessageToConsole(message, lineNumber, sourceURL); + + page->inspectorController()->addMessageToConsole(source, level, message, lineNumber, sourceURL); + + printToStandardOut(source, level, message, sourceURL, lineNumber); } -void Console::info(const String& message) +void Console::debug(ExecState* exec, const ArgList& args) { - if (!m_frame) + // In Firebug, console.debug has the same behavior as console.log. So we'll do the same. + log(exec, args); +} + +void Console::error(ExecState* exec, const ArgList& args) +{ + if (args.isEmpty()) return; - Page* page = m_frame->page(); + Page* page = this->page(); if (!page) return; - page->chrome()->addMessageToConsole(JSMessageSource, LogMessageLevel, message, 0, m_frame->loader()->url().prettyURL()); + String message = args.at(exec, 0)->toString(exec); + + KURL url; + unsigned lineNumber; + retrieveLastCaller(exec, url, lineNumber); + + page->chrome()->client()->addMessageToConsole(message, lineNumber, url.prettyURL()); + page->inspectorController()->addMessageToConsole(JSMessageSource, ErrorMessageLevel, exec, args, lineNumber, url.string()); + + printToStandardOut(ErrorMessageLevel, exec, args, url); } -void Console::log(const String& message) +void Console::info(ExecState* exec, const ArgList& args) { - if (!m_frame) + if (args.isEmpty()) return; - Page* page = m_frame->page(); + Page* page = this->page(); if (!page) return; - page->chrome()->addMessageToConsole(JSMessageSource, LogMessageLevel, message, 0, m_frame->loader()->url().prettyURL()); + String message = args.at(exec, 0)->toString(exec); + + KURL url; + unsigned lineNumber; + retrieveLastCaller(exec, url, lineNumber); + + page->chrome()->client()->addMessageToConsole(message, lineNumber, url.prettyURL()); + page->inspectorController()->addMessageToConsole(JSMessageSource, LogMessageLevel, exec, args, lineNumber, url.string()); + + printToStandardOut(LogMessageLevel, exec, args, url); } -void Console::warn(const String& message) +void Console::log(ExecState* exec, const ArgList& args) { - if (!m_frame) + if (args.isEmpty()) return; - Page* page = m_frame->page(); + Page* page = this->page(); if (!page) return; - page->chrome()->addMessageToConsole(JSMessageSource, WarningMessageLevel, message, 0, m_frame->loader()->url().prettyURL()); + String message = args.at(exec, 0)->toString(exec); + + KURL url; + unsigned lineNumber; + retrieveLastCaller(exec, url, lineNumber); + + page->chrome()->client()->addMessageToConsole(message, lineNumber, url.prettyURL()); + page->inspectorController()->addMessageToConsole(JSMessageSource, LogMessageLevel, exec, args, lineNumber, url.string()); + + printToStandardOut(LogMessageLevel, exec, args, url); +} + +void Console::dir(ExecState* exec, const ArgList& args) +{ + if (args.isEmpty()) + return; + + Page* page = this->page(); + if (!page) + return; + + page->inspectorController()->addMessageToConsole(JSMessageSource, ObjectMessageLevel, exec, args, 0, String()); +} + +void Console::dirxml(ExecState* exec, const ArgList& args) +{ + if (args.isEmpty()) + return; + + Page* page = this->page(); + if (!page) + return; + + page->inspectorController()->addMessageToConsole(JSMessageSource, NodeMessageLevel, exec, args, 0, String()); +} + +void Console::trace(ExecState* exec) +{ + Page* page = this->page(); + if (!page) + return; + + int signedLineNumber; + intptr_t sourceID; + UString urlString; + JSValue* func; + + exec->machine()->retrieveLastCaller(exec, signedLineNumber, sourceID, urlString, func); + + ArgList args; + while (!func->isNull()) { + args.append(func); + func = exec->machine()->retrieveCaller(exec, asInternalFunction(func)); + } + + page->inspectorController()->addMessageToConsole(JSMessageSource, TraceMessageLevel, exec, args, 0, String()); +} + +void Console::assertCondition(bool condition, ExecState* exec, const ArgList& args) +{ + if (condition) + return; + + Page* page = this->page(); + if (!page) + return; + + KURL url; + unsigned lineNumber; + retrieveLastCaller(exec, url, lineNumber); + + // FIXME: <https://bugs.webkit.org/show_bug.cgi?id=19135> It would be nice to prefix assertion failures with a message like "Assertion failed: ". + // FIXME: <https://bugs.webkit.org/show_bug.cgi?id=19136> We should print a message even when args.isEmpty() is true. + + page->inspectorController()->addMessageToConsole(JSMessageSource, ErrorMessageLevel, exec, args, lineNumber, url.string()); + + printToStandardOut(ErrorMessageLevel, exec, args, url); +} + +void Console::count(ExecState* exec, const ArgList& args) +{ + Page* page = this->page(); + if (!page) + return; + + KURL url; + unsigned lineNumber; + retrieveLastCaller(exec, url, lineNumber); + + UString title; + if (args.size() >= 1) + title = valueToStringWithUndefinedOrNullCheck(exec, args.at(exec, 0)); + + page->inspectorController()->count(title, lineNumber, url.string()); +} + +void Console::profile(ExecState* exec, const ArgList& args) +{ + Page* page = this->page(); + if (!page) + return; + + // FIXME: log a console message when profiling is disabled. + if (!page->inspectorController()->profilerEnabled()) + return; + + UString title = args.at(exec, 0)->toString(exec); + Profiler::profiler()->startProfiling(exec, title); +} + +void Console::profileEnd(ExecState* exec, const ArgList& args) +{ + Page* page = this->page(); + if (!page) + return; + + if (!page->inspectorController()->profilerEnabled()) + return; + + UString title; + if (args.size() >= 1) + title = valueToStringWithUndefinedOrNullCheck(exec, args.at(exec, 0)); + + RefPtr<Profile> profile = Profiler::profiler()->stopProfiling(exec, title); + if (!profile) + return; + + m_profiles.append(profile); + + if (Page* page = this->page()) { + KURL url; + unsigned lineNumber; + retrieveLastCaller(exec, url, lineNumber); + + page->inspectorController()->addProfile(profile, lineNumber, url); + } +} + +void Console::time(const UString& title) +{ + if (title.isNull()) + return; + + Page* page = this->page(); + if (!page) + return; + + page->inspectorController()->startTiming(title); +} + +void Console::timeEnd(ExecState* exec, const ArgList& args) +{ + UString title; + if (args.size() >= 1) + title = valueToStringWithUndefinedOrNullCheck(exec, args.at(exec, 0)); + if (title.isNull()) + return; + + Page* page = this->page(); + if (!page) + return; + + double elapsed; + if (!page->inspectorController()->stopTiming(title, elapsed)) + return; + + String message = String(title) + String::format(": %.0fms", elapsed); + + KURL url; + unsigned lineNumber; + retrieveLastCaller(exec, url, lineNumber); + + page->inspectorController()->addMessageToConsole(JSMessageSource, LogMessageLevel, message, lineNumber, url.string()); +} + +void Console::group(ExecState* exec, const ArgList& arguments) +{ + Page* page = this->page(); + if (!page) + return; + + page->inspectorController()->startGroup(JSMessageSource, exec, arguments, 0, String()); +} + +void Console::groupEnd() +{ + Page* page = this->page(); + if (!page) + return; + + page->inspectorController()->endGroup(JSMessageSource, 0, String()); +} + +void Console::warn(ExecState* exec, const ArgList& args) +{ + if (args.isEmpty()) + return; + + Page* page = this->page(); + if (!page) + return; + + String message = args.at(exec, 0)->toString(exec); + + KURL url; + unsigned lineNumber; + retrieveLastCaller(exec, url, lineNumber); + + page->chrome()->client()->addMessageToConsole(message, lineNumber, url.prettyURL()); + page->inspectorController()->addMessageToConsole(JSMessageSource, WarningMessageLevel, exec, args, lineNumber, url.string()); + + printToStandardOut(WarningMessageLevel, exec, args, url); +} + +void Console::reportException(ExecState* exec, JSValue* exception) +{ + UString errorMessage = exception->toString(exec); + JSObject* exceptionObject = exception->toObject(exec); + int lineNumber = exceptionObject->get(exec, Identifier(exec, "line"))->toInt32(exec); + UString exceptionSourceURL = exceptionObject->get(exec, Identifier(exec, "sourceURL"))->toString(exec); + addMessage(JSMessageSource, ErrorMessageLevel, errorMessage, lineNumber, exceptionSourceURL); + if (exec->hadException()) + exec->clearException(); +} + +void Console::reportCurrentException(ExecState* exec) +{ + JSValue* exception = exec->exception(); + exec->clearException(); + reportException(exec, exception); +} + +static bool printExceptions = false; + +bool Console::shouldPrintExceptions() +{ + return printExceptions; +} + +void Console::setShouldPrintExceptions(bool print) +{ + printExceptions = print; +} + +Page* Console::page() const +{ + if (!m_frame) + return 0; + return m_frame->page(); } } // namespace WebCore |