+2008-12-09 Dimitri Glazkov <dglazkov@chromium.org>
+
+ Reviewed by Timothy Hatcher.
+
+ https://bugs.webkit.org/show_bug.cgi?id=22631
+ Allow ScriptCallFrame query names of functions in the call stack.
+
+ * JavaScriptCore.exp: added InternalFunction::name and
+ UString operator==() as exported symbol
+
2008-12-08 Judit Jasz <jasy@inf.u-szeged.hu>
Reviewed and tweaked by Cameron Zwarich.
__ZN3JSC10Identifier3addEPNS_9ExecStateEPKc
__ZN3JSC10Identifier5equalEPKNS_7UString3RepEPKc
__ZN3JSC10JSFunction4infoE
+__ZN3JSC16InternalFunction4nameEPNS_12JSGlobalDataE
__ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeE
__ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeEPKc
__ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeERKNS_7UStringE
__ZN3JSC9StructureD1Ev
__ZN3JSC9constructEPNS_9ExecStateEPNS_7JSValueENS_13ConstructTypeERKNS_13ConstructDataERKNS_7ArgListE
__ZN3JSCeqERKNS_7UStringEPKc
+__ZN3JSCeqERKNS_7UStringES2_
__ZN3JSCgtERKNS_7UStringES2_
__ZN3JSCltERKNS_7UStringES2_
__ZN3WTF10fastCallocEmm
+2008-12-09 Dimitri Glazkov <dglazkov@chromium.org>
+
+ Reviewed by Timothy Hatcher.
+
+ https://bugs.webkit.org/show_bug.cgi?id=22631
+ Streamline Console.cpp, abstract out the use of JSC::ExecState and
+ JSC::ArgList by introducing ScriptCallFrame and ScriptCallStack
+ abstractions.
+
+ * GNUmakefile.am: Added ScriptCallFrame and ScriptCallStack to build
+ * WebCore.pro: Added ScriptCallFrame and ScriptCallStack to build
+ * WebCore.vcproj/WebCore.vcproj: Added ScriptCallFrame and
+ ScriptCallStack to project
+ * WebCore.xcodeproj/project.pbxproj: Added ScriptCallFrame and
+ ScriptCallStack to project
+ * bindings/js/JSConsoleCustom.cpp: Remove custom bindings.
+ * bindings/js/ScriptCallFrame.cpp: Added.
+ (WebCore::ScriptCallFrame::ScriptCallFrame):
+ (WebCore::ScriptCallFrame::~ScriptCallFrame):
+ (WebCore::ScriptCallFrame::argumentAt):
+ * bindings/js/ScriptCallFrame.h: Added.
+ (WebCore::ScriptCallFrame::functionName):
+ (WebCore::ScriptCallFrame::sourceURL):
+ (WebCore::ScriptCallFrame::lineNumber):
+ (WebCore::ScriptCallFrame::argumentCount):
+ * bindings/js/ScriptCallStack.cpp: Added.
+ (WebCore::ScriptCallStack::ScriptCallStack):
+ (WebCore::ScriptCallStack::~ScriptCallStack):
+ (WebCore::ScriptCallStack::at):
+ (WebCore::ScriptCallStack::size):
+ (WebCore::ScriptCallStack::initialize):
+ * bindings/js/ScriptCallStack.h: Added.
+ (WebCore::ScriptCallStack::ScriptCallStack):
+ (WebCore::ScriptCallStack::~ScriptCallStack):
+ (WebCore::ScriptCallStack::state):
+ (WebCore::ScriptCallStack::at):
+ (WebCore::ScriptCallStack::size):
+ (WebCore::ScriptCallStack::initialize):
+ * bindings/js/ScriptString.h: Added missing PlatformString include.
+ (WebCore::ScriptString::ScriptString): Added default constructor.
+ (WebCore::ScriptString::operator==): Added equality operator.
+ (WebCore::ScriptString::operator!=):
+ * bindings/js/ScriptValue.cpp: Added isNull and isUndefined.
+ (WebCore::ScriptValue::isNull):
+ (WebCore::ScriptValue::isUndefined):
+ * bindings/js/ScriptValue.h: Added isNull and isUndefined
+ * bindings/scripts/CodeGeneratorJS.pm: Add handling for
+ CustomArgumentHandling attribute.
+ * inspector/InspectorController.cpp: Refactored to use
+ ScriptCallFrame and ScriptCallStack.
+ (WebCore::ConsoleMessage::ConsoleMessage):
+ (WebCore::InspectorController::addMessageToConsole):
+ (WebCore::InspectorController::startGroup):
+ (WebCore::InspectorController::addScriptConsoleMessage):
+ (WebCore::InspectorController::count):
+ (WebCore::InspectorController::startTiming):
+ (WebCore::InspectorController::stopTiming):
+ * inspector/InspectorController.h: Refactored to use ScriptCallFrame and
+ ScriptCallStack.
+ * inspector/front-end/Console.js: Modified to use argument value itself
+ rather than f.name for stack trace.
+ * page/Console.cpp: Refactored to use ScriptCallFrame and
+ ScriptCallStack.
+ (WebCore::getFirstArgumentAsString):
+ (WebCore::Console::addMessage):
+ (WebCore::Console::debug):
+ (WebCore::Console::error):
+ (WebCore::Console::info):
+ (WebCore::Console::log):
+ (WebCore::Console::dir):
+ (WebCore::Console::dirxml):
+ (WebCore::Console::trace):
+ (WebCore::Console::assertCondition):
+ (WebCore::Console::count):
+ (WebCore::Console::profile):
+ (WebCore::Console::profileEnd):
+ (WebCore::Console::time):
+ (WebCore::Console::timeEnd):
+ (WebCore::Console::group):
+ (WebCore::Console::warn):
+ * page/Console.h:
+ * page/Console.idl: Removed Custom attributes, added
+ CustomArgumentHandling attributes, and tweaked argument defs.
+
2008-12-09 Darin Adler <darin@apple.com>
Try to fix non-Mac builds.
WebCore/bindings/js/JSXSLTProcessorCustom.cpp \
WebCore/bindings/js/ScheduledAction.cpp \
WebCore/bindings/js/ScheduledAction.h \
+ WebCore/bindings/js/ScriptCallFrame.cpp \
+ WebCore/bindings/js/ScriptCallFrame.h \
+ WebCore/bindings/js/ScriptCallStack.cpp \
+ WebCore/bindings/js/ScriptCallStack.h \
WebCore/bindings/js/ScriptController.cpp \
WebCore/bindings/js/ScriptController.h \
WebCore/bindings/js/ScriptInstance.h \
bindings/js/JSDOMBinding.cpp \
bindings/js/JSEventListener.cpp \
bindings/js/JSPluginElementFunctions.cpp \
+ bindings/js/ScriptCallFrame.cpp \
+ bindings/js/ScriptCallStack.cpp \
bindings/js/ScriptController.cpp \
bindings/js/ScriptValue.cpp \
bindings/js/ScheduledAction.cpp \
"bindings/js/JSXSLTProcessorConstructor.cpp",
"bindings/js/JSXSLTProcessorCustom.cpp",
"bindings/js/ScheduledAction.cpp",
+ "bindings/js/ScriptCallFrame.cpp",
+ "bindings/js/ScriptCallStack.cpp",
"bindings/js/ScriptController.cpp",
"bindings/js/ScriptValue.cpp",
"bindings/js/WorkerScriptController.cpp",
RelativePath="..\bindings\js\ScheduledAction.h"\r
>\r
</File>\r
+ <File\r
+ RelativePath="..\bindings\js\ScriptCallFrame.cpp"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath="..\bindings\js\ScriptCallFrame.h"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath="..\bindings\js\ScriptCallStack.cpp"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath="..\bindings\js\ScriptCallStack.h"\r
+ >\r
+ </File>\r
<File\r
RelativePath="..\bindings\js\ScriptController.cpp"\r
>\r
37ACCF690DA414E70089E602 /* FontDescription.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 37ACCE620DA2AA960089E602 /* FontDescription.cpp */; };
37F818FD0D657606005E1F05 /* WebCoreURLResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 37F818FB0D657606005E1F05 /* WebCoreURLResponse.h */; settings = {ATTRIBUTES = (Private, ); }; };
37F818FE0D657606005E1F05 /* WebCoreURLResponse.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37F818FC0D657606005E1F05 /* WebCoreURLResponse.mm */; };
+ 416E75BE0EDF8FD700360E1D /* ScriptCallStack.h in Headers */ = {isa = PBXBuildFile; fileRef = 416E75BC0EDF8FD700360E1D /* ScriptCallStack.h */; };
+ 416E75BF0EDF8FD700360E1D /* ScriptCallStack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 416E75BD0EDF8FD700360E1D /* ScriptCallStack.cpp */; };
+ 416E75CB0EDF90C700360E1D /* ScriptCallFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 416E75C90EDF90C700360E1D /* ScriptCallFrame.h */; };
+ 416E75CC0EDF90C700360E1D /* ScriptCallFrame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 416E75CA0EDF90C700360E1D /* ScriptCallFrame.cpp */; };
416F45F00ED7B311008215B6 /* ScriptString.h in Headers */ = {isa = PBXBuildFile; fileRef = 416F45EF0ED7B311008215B6 /* ScriptString.h */; };
41C760B10EDE03D300C1655F /* ScriptState.h in Headers */ = {isa = PBXBuildFile; fileRef = 41C760B00EDE03D300C1655F /* ScriptState.h */; settings = {ATTRIBUTES = (Private, ); }; };
4415292E0E1AE8A000C4A2D0 /* HTMLPlugInImageElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 4415292C0E1AE8A000C4A2D0 /* HTMLPlugInImageElement.h */; };
37ACCE620DA2AA960089E602 /* FontDescription.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FontDescription.cpp; sourceTree = "<group>"; };
37F818FB0D657606005E1F05 /* WebCoreURLResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebCoreURLResponse.h; sourceTree = "<group>"; };
37F818FC0D657606005E1F05 /* WebCoreURLResponse.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebCoreURLResponse.mm; sourceTree = "<group>"; };
+ 416E75BC0EDF8FD700360E1D /* ScriptCallStack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScriptCallStack.h; sourceTree = "<group>"; };
+ 416E75BD0EDF8FD700360E1D /* ScriptCallStack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScriptCallStack.cpp; sourceTree = "<group>"; };
+ 416E75C90EDF90C700360E1D /* ScriptCallFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScriptCallFrame.h; sourceTree = "<group>"; };
+ 416E75CA0EDF90C700360E1D /* ScriptCallFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScriptCallFrame.cpp; sourceTree = "<group>"; };
416F45EF0ED7B311008215B6 /* ScriptString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScriptString.h; sourceTree = "<group>"; };
41C760B00EDE03D300C1655F /* ScriptState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScriptState.h; sourceTree = "<group>"; };
4415292C0E1AE8A000C4A2D0 /* HTMLPlugInImageElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLPlugInImageElement.h; sourceTree = "<group>"; };
BCE99EC20DCA624100182683 /* JSXSLTProcessorConstructor.h */,
BCA378BA0D15F64200B793D6 /* ScheduledAction.cpp */,
BCA378BB0D15F64200B793D6 /* ScheduledAction.h */,
+ 416E75C90EDF90C700360E1D /* ScriptCallFrame.h */,
+ 416E75CA0EDF90C700360E1D /* ScriptCallFrame.cpp */,
+ 416E75BC0EDF8FD700360E1D /* ScriptCallStack.h */,
+ 416E75BD0EDF8FD700360E1D /* ScriptCallStack.cpp */,
93B70D5309EB0C7C009D8468 /* ScriptController.cpp */,
93B70D5409EB0C7C009D8468 /* ScriptController.h */,
A83E1C720E49042B00140B9C /* ScriptControllerMac.mm */,
1CEFC9B90D78DC8C007D2579 /* SchedulePair.h in Headers */,
5DFE8F570D16477C0076E937 /* ScheduledAction.h in Headers */,
BCEC01BE0C274DAC009F4EC9 /* Screen.h in Headers */,
+ 416E75BE0EDF8FD700360E1D /* ScriptCallStack.h in Headers */,
+ 416E75CB0EDF90C700360E1D /* ScriptCallFrame.h in Headers */,
93B70D7009EB0C7C009D8468 /* ScriptController.h in Headers */,
08A484780E5272C500C3FE76 /* ScriptElement.h in Headers */,
E11C9D9B0EB3681200E409DB /* ScriptExecutionContext.h in Headers */,
1CE24F970D7CAF0E007E04C2 /* SchedulePairMac.mm in Sources */,
5DFE8F560D16477B0076E937 /* ScheduledAction.cpp in Sources */,
BCEC01BD0C274DAC009F4EC9 /* Screen.cpp in Sources */,
+ 416E75BF0EDF8FD700360E1D /* ScriptCallStack.cpp in Sources */,
+ 416E75CC0EDF90C700360E1D /* ScriptCallFrame.cpp in Sources */,
93B70D6F09EB0C7C009D8468 /* ScriptController.cpp in Sources */,
A83E1C740E49042C00140B9C /* ScriptControllerMac.mm in Sources */,
08A484770E5272C500C3FE76 /* ScriptElement.cpp in Sources */,
return constructArray(exec, list);
}
-JSValue* JSConsole::debug(ExecState* exec, const ArgList& arguments)
-{
- impl()->debug(exec, arguments);
- return jsUndefined();
-}
-
-JSValue* JSConsole::error(ExecState* exec, const ArgList& arguments)
-{
- impl()->error(exec, arguments);
- return jsUndefined();
-}
-
-JSValue* JSConsole::info(ExecState* exec, const ArgList& arguments)
-{
- impl()->info(exec, arguments);
- return jsUndefined();
-}
-
-JSValue* JSConsole::log(ExecState* exec, const ArgList& arguments)
-{
- impl()->log(exec, arguments);
- return jsUndefined();
-}
-
-JSValue* JSConsole::warn(ExecState* exec, const ArgList& arguments)
-{
- impl()->warn(exec, arguments);
- return jsUndefined();
-}
-
-JSValue* JSConsole::dir(ExecState* exec, const ArgList& arguments)
-{
- impl()->dir(exec, arguments);
- return jsUndefined();
-}
-
-JSValue* JSConsole::dirxml(ExecState* exec, const ArgList& arguments)
-{
- impl()->dirxml(exec, arguments);
- return jsUndefined();
-}
-
-JSValue* JSConsole::trace(ExecState* exec, const ArgList&)
-{
- impl()->trace(exec);
- return jsUndefined();
-}
-
-JSValue* JSConsole::assertCondition(ExecState* exec, const ArgList& arguments)
-{
- ArgList messageParameters;
- arguments.getSlice(1, messageParameters);
-
- impl()->assertCondition(arguments.at(exec, 0)->toBoolean(exec), exec, messageParameters);
- return jsUndefined();
-}
-
-JSValue* JSConsole::count(ExecState* exec, const ArgList& arguments)
-{
- impl()->count(exec, arguments);
- return jsUndefined();
-}
-
-JSValue* JSConsole::timeEnd(ExecState* exec, const ArgList& arguments)
-{
- impl()->timeEnd(exec, arguments);
- return jsUndefined();
-}
-
-JSValue* JSConsole::profile(ExecState* exec, const ArgList& arguments)
-{
- impl()->profile(exec, arguments);
- return jsUndefined();
-}
-
-JSValue* JSConsole::profileEnd(ExecState* exec, const ArgList& arguments)
-{
- impl()->profileEnd(exec, arguments);
- return jsUndefined();
-}
-
-JSValue* JSConsole::group(ExecState* exec, const ArgList& arguments)
-{
- impl()->group(exec, arguments);
- return jsUndefined();
-}
-
} // namespace WebCore
#ifndef ScriptString_h
#define ScriptString_h
+#include "PlatformString.h"
#include <runtime/JSLock.h>
#include <runtime/UString.h>
class ScriptString {
public:
+ ScriptString() {}
ScriptString(const char* s) : m_str(s) {}
ScriptString(const JSC::UString& s) : m_str(s) {}
return *this;
}
+ bool operator==(const ScriptString& s) const
+ {
+ JSC::JSLock lock(false);
+ return m_str == s.m_str;
+ }
+
+ bool operator!=(const ScriptString& s) const
+ {
+ JSC::JSLock lock(false);
+ // Avoid exporting an extra symbol by re-using "==" operator.
+ return !(m_str == s.m_str);
+ }
+
private:
JSC::UString m_str;
};
bool ScriptValue::getString(String& result) const
{
- if (!m_value.get())
+ if (!m_value)
return false;
JSLock lock(false);
UString ustring;
return true;
}
+bool ScriptValue::isNull() const
+{
+ if (!m_value)
+ return false;
+ return m_value->isNull();
+}
+
+bool ScriptValue::isUndefined() const
+{
+ if (!m_value)
+ return false;
+ return m_value->isUndefined();
+}
+
} // namespace WebCore
JSC::JSValue* jsValue() const { return m_value.get(); }
bool getString(String& result) const;
+ bool isNull() const;
+ bool isUndefined() const;
private:
JSC::ProtectedPtr<JSC::JSValue> m_value;
my $hasOptionalArguments = 0;
+ if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {
+ push(@implContent, " ScriptCallStack callStack(exec, args, $numParameters);\n");
+ $implIncludes{"ScriptCallStack.h"} = 1;
+ }
+
foreach my $parameter (@{$function->parameters}) {
if (!$hasOptionalArguments && $parameter->extendedAttributes->{"Optional"}) {
push(@implContent, "\n int argsCount = args.size();\n");
my $podType = shift;
my $implClassName = shift;
+ if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {
+ $functionString .= ", " if $paramIndex;
+ ++$paramIndex;
+ $functionString .= "&callStack";
+ }
+
if (@{$function->raisesExceptions}) {
$functionString .= ", " if $paramIndex;
$functionString .= "ec";
#include "ResourceRequest.h"
#include "ResourceResponse.h"
#include "Settings.h"
+#include "ScriptCallStack.h"
#include "SharedBuffer.h"
#include "SystemTime.h"
#include "TextEncoding.h"
{
}
- ConsoleMessage(MessageSource s, MessageLevel l, ExecState* exec, const ArgList& args, unsigned li, const String& u, unsigned g)
+ ConsoleMessage(MessageSource s, MessageLevel l, ScriptCallStack* callStack, unsigned g, bool storeTrace = false)
: source(s)
, level(l)
- , wrappedArguments(args.size())
- , line(li)
- , url(u)
+ , wrappedArguments(callStack->at(0).argumentCount())
+ , frames(storeTrace ? callStack->size() : 0)
, groupLevel(g)
, repeatCount(1)
{
+ const ScriptCallFrame& lastCaller = callStack->at(0);
+ line = lastCaller.lineNumber();
+ url = lastCaller.sourceURL().string();
+
+ // FIXME: For now, just store function names as strings.
+ // As ScriptCallStack start storing line number and source URL for all
+ // frames, refactor to use that, as well.
+ if (storeTrace) {
+ unsigned stackSize = callStack->size();
+ for (unsigned i = 0; i < stackSize; ++i)
+ frames[i] = callStack->at(i).functionName();
+ }
+
JSLock lock(false);
- for (unsigned i = 0; i < args.size(); ++i)
- wrappedArguments[i] = JSInspectedObjectWrapper::wrap(exec, args.at(exec, i));
+
+ for (unsigned i = 0; i < lastCaller.argumentCount(); ++i)
+ wrappedArguments[i] = JSInspectedObjectWrapper::wrap(callStack->state(), lastCaller.argumentAt(i).jsValue());
}
bool isEqual(ExecState* exec, ConsoleMessage* msg) const
if (msg->wrappedArguments.size() != this->wrappedArguments.size() ||
(!exec && msg->wrappedArguments.size()))
return false;
-
+
for (size_t i = 0; i < msg->wrappedArguments.size(); ++i) {
ASSERT_ARG(exec, exec);
if (!JSValueIsEqual(toRef(exec), toRef(msg->wrappedArguments[i].get()), toRef(this->wrappedArguments[i].get()), 0))
return false;
}
+
+ size_t frameCount = msg->frames.size();
+ if (frameCount != this->frames.size())
+ return false;
+
+ for (size_t i = 0; i < frameCount; ++i) {
+ const ScriptString& myFrameFunctionName = this->frames[i];
+ if (myFrameFunctionName != msg->frames[i])
+ return false;
+ }
return msg->source == this->source
&& msg->level == this->level
MessageLevel level;
String message;
Vector<ProtectedPtr<JSValue> > wrappedArguments;
+ Vector<ScriptString> frames;
unsigned line;
String url;
unsigned groupLevel;
m_showAfterVisible = CurrentPanel;
}
-void InspectorController::addMessageToConsole(MessageSource source, MessageLevel level, ExecState* exec, const ArgList& arguments, unsigned lineNumber, const String& sourceURL)
+void InspectorController::addMessageToConsole(MessageSource source, MessageLevel level, ScriptCallStack* callStack)
{
if (!enabled())
return;
- addConsoleMessage(exec, new ConsoleMessage(source, level, exec, arguments, lineNumber, sourceURL, m_groupLevel));
+ addConsoleMessage(callStack->state(), new ConsoleMessage(source, level, callStack, m_groupLevel, level == TraceMessageLevel));
}
void InspectorController::addMessageToConsole(MessageSource source, MessageLevel level, const String& message, unsigned lineNumber, const String& sourceID)
callFunction(m_scriptContext, m_scriptObject, "setRecordingProfile", 1, &isProvingValue, exception);
}
-void InspectorController::startGroup(MessageSource source, ExecState* exec, const ArgList& arguments, unsigned lineNumber, const String& sourceURL)
+void InspectorController::startGroup(MessageSource source, ScriptCallStack* callStack)
{
++m_groupLevel;
- addConsoleMessage(exec, new ConsoleMessage(source, StartGroupMessageLevel, exec, arguments, lineNumber, sourceURL, m_groupLevel));
+ addConsoleMessage(callStack->state(), new ConsoleMessage(source, StartGroupMessageLevel, callStack, m_groupLevel));
}
void InspectorController::endGroup(MessageSource source, unsigned lineNumber, const String& sourceURL)
arguments[argumentCount++] = groupLevelValue;
arguments[argumentCount++] = repeatCountValue;
- if (!message->wrappedArguments.isEmpty()) {
+ if (!message->frames.isEmpty()) {
+ unsigned remainingSpaceInArguments = maximumMessageArguments - argumentCount;
+ unsigned argumentsToAdd = min(remainingSpaceInArguments, static_cast<unsigned>(message->frames.size()));
+ for (unsigned i = 0; i < argumentsToAdd; ++i)
+ arguments[argumentCount++] = JSValueMakeString(m_scriptContext, jsStringRef(message->frames[i]).get());
+ } else if (!message->wrappedArguments.isEmpty()) {
unsigned remainingSpaceInArguments = maximumMessageArguments - argumentCount;
unsigned argumentsToAdd = min(remainingSpaceInArguments, static_cast<unsigned>(message->wrappedArguments.size()));
for (unsigned i = 0; i < argumentsToAdd; ++i)
drawHighlightForBoxes(context, lineBoxQuads, absContentQuad, absPaddingQuad, absBorderQuad, absMarginQuad);
}
-void InspectorController::count(const UString& title, unsigned lineNumber, const String& sourceID)
+void InspectorController::count(const String& title, unsigned lineNumber, const String& sourceID)
{
- String identifier = String(title) + String::format("@%s:%d", sourceID.utf8().data(), lineNumber);
+ String identifier = title + String::format("@%s:%d", sourceID.utf8().data(), lineNumber);
HashMap<String, unsigned>::iterator it = m_counts.find(identifier);
int count;
if (it == m_counts.end())
m_counts.add(identifier, count);
- String message = String::format("%s: %d", title.UTF8String().c_str(), count);
+ String message = String::format("%s: %d", title.utf8().data(), count);
addMessageToConsole(JSMessageSource, LogMessageLevel, message, lineNumber, sourceID);
}
-void InspectorController::startTiming(const UString& title)
+void InspectorController::startTiming(const String& title)
{
m_times.add(title, currentTime() * 1000);
}
-bool InspectorController::stopTiming(const UString& title, double& elapsed)
+bool InspectorController::stopTiming(const String& title, double& elapsed)
{
HashMap<String, double>::iterator it = m_times.find(title);
if (it == m_times.end())
class Page;
class ResourceResponse;
class ResourceError;
+class ScriptCallStack;
class SharedBuffer;
struct ConsoleMessage;
bool windowVisible();
void setWindowVisible(bool visible = true, bool attached = false);
- void addMessageToConsole(MessageSource, MessageLevel, JSC::ExecState*, const JSC::ArgList& arguments, unsigned lineNumber, const String& sourceID);
+ void addMessageToConsole(MessageSource, MessageLevel, ScriptCallStack*);
void addMessageToConsole(MessageSource, MessageLevel, const String& message, unsigned lineNumber, const String& sourceID);
void clearConsoleMessages();
void toggleRecordButton(bool);
void drawNodeHighlight(GraphicsContext&) const;
- void count(const JSC::UString& title, unsigned lineNumber, const String& sourceID);
+ void count(const String& title, unsigned lineNumber, const String& sourceID);
- void startTiming(const JSC::UString& title);
- bool stopTiming(const JSC::UString& title, double& elapsed);
+ void startTiming(const String& title);
+ bool stopTiming(const String& title, double& elapsed);
- void startGroup(MessageSource source, JSC::ExecState* exec, const JSC::ArgList& arguments, unsigned lineNumber, const String& sourceURL);
+ void startGroup(MessageSource source, ScriptCallStack* callFrame);
void endGroup(MessageSource source, unsigned lineNumber, const String& sourceURL);
private:
span.addStyleClass("console-formatted-trace");
var stack = Array.prototype.slice.call(arguments, 6);
var funcNames = stack.map(function(f) {
- return f.name || WebInspector.UIString("(anonymous function)");
+ return f || WebInspector.UIString("(anonymous function)");
});
span.appendChild(document.createTextNode(funcNames.join("\n")));
this.formattedMessage = span;
#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 <runtime/Completion.h>
-#include <runtime/JSObject.h>
-#include <interpreter/Interpreter.h>
+
+#if USE(JSC)
#include <profiler/Profiler.h>
-#include <stdio.h>
+#endif
-using namespace JSC;
+#include "ScriptCallStack.h"
+#include <stdio.h>
namespace WebCore {
}
}
+static bool getFirstArgumentAsString(const ScriptCallFrame& callFrame, String& result, bool checkForNullOrUndefined = false)
+{
+ if (!callFrame.argumentCount())
+ return false;
+
+ const ScriptValue& value = callFrame.argumentAt(0);
+ if (checkForNullOrUndefined && (value.isNull() || value.isUndefined()))
+ return false;
+
+ return value.getString(result);
+}
+
static void printMessageSourceAndLevelPrefix(MessageSource source, MessageLevel level)
{
const char* sourceString;
printf("%s %s:", sourceString, levelString);
}
-static void printToStandardOut(MessageSource source, MessageLevel level, const String& message, const String& sourceURL, unsigned lineNumber)
+void Console::addMessage(MessageSource source, MessageLevel level, const String& message, unsigned lineNumber, const String& sourceURL)
{
+ Page* page = this->page();
+ if (!page)
+ return;
+
+ if (source == JSMessageSource || source == WMLMessageSource)
+ page->chrome()->client()->addMessageToConsole(message, lineNumber, sourceURL);
+
+ page->inspectorController()->addMessageToConsole(source, level, message, lineNumber, sourceURL);
+
if (!Console::shouldPrintExceptions())
return;
printf(" %s\n", message.utf8().data());
}
-static void printToStandardOut(MessageLevel level, ExecState* exec, const ArgList& args, const KURL& url)
-{
- if (!Console::shouldPrintExceptions())
+void Console::addMessage(MessageLevel level, ScriptCallStack* callStack, bool acceptNoArguments) {
+ Page* page = this->page();
+ if (!page)
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");
-}
+ const ScriptCallFrame& lastCaller = callStack->at(0);
-static inline void retrieveLastCaller(ExecState* exec, KURL& url, unsigned& lineNumber)
-{
- int signedLineNumber;
- intptr_t sourceID;
- UString urlString;
- JSValue* function;
+ if (!acceptNoArguments && !lastCaller.argumentCount())
+ return;
- exec->interpreter()->retrieveLastCaller(exec, signedLineNumber, sourceID, urlString, function);
+ String message;
+ if (getFirstArgumentAsString(lastCaller, message))
+ page->chrome()->client()->addMessageToConsole(message, lastCaller.lineNumber(), lastCaller.sourceURL().prettyURL());
- url = KURL(urlString);
- lineNumber = (signedLineNumber >= 0 ? signedLineNumber : 0);
-}
+ page->inspectorController()->addMessageToConsole(JSMessageSource, level, callStack);
-void Console::addMessage(MessageSource source, MessageLevel level, const String& message, unsigned lineNumber, const String& sourceURL)
-{
- Page* page = this->page();
- if (!page)
+ if (!Console::shouldPrintExceptions())
return;
- if (source == JSMessageSource || source == WMLMessageSource)
- page->chrome()->client()->addMessageToConsole(message, lineNumber, sourceURL);
-
- page->inspectorController()->addMessageToConsole(source, level, message, lineNumber, sourceURL);
+ printSourceURLAndLine(lastCaller.sourceURL().prettyURL(), 0);
+ printMessageSourceAndLevelPrefix(JSMessageSource, level);
- printToStandardOut(source, level, message, sourceURL, lineNumber);
+ for (unsigned i = 0; i < lastCaller.argumentCount(); ++i) {
+ String argAsString;
+ if (lastCaller.argumentAt(i).getString(argAsString))
+ printf(" %s", argAsString.utf8().data());
+ }
+ printf("\n");
}
-void Console::debug(ExecState* exec, const ArgList& args)
+void Console::debug(ScriptCallStack* callStack)
{
// In Firebug, console.debug has the same behavior as console.log. So we'll do the same.
- log(exec, args);
+ log(callStack);
}
-void Console::error(ExecState* exec, const ArgList& args)
+void Console::error(ScriptCallStack* callStack)
{
- 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, ErrorMessageLevel, exec, args, lineNumber, url.string());
-
- printToStandardOut(ErrorMessageLevel, exec, args, url);
+ addMessage(ErrorMessageLevel, callStack);
}
-void Console::info(ExecState* exec, const ArgList& args)
+void Console::info(ScriptCallStack* callStack)
{
- 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, LogMessageLevel, exec, args, lineNumber, url.string());
-
- printToStandardOut(LogMessageLevel, exec, args, url);
+ log(callStack);
}
-void Console::log(ExecState* exec, const ArgList& args)
+void Console::log(ScriptCallStack* callStack)
{
- 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, LogMessageLevel, exec, args, lineNumber, url.string());
-
- printToStandardOut(LogMessageLevel, exec, args, url);
+ addMessage(LogMessageLevel, callStack);
}
-void Console::dir(ExecState* exec, const ArgList& args)
+void Console::dir(ScriptCallStack* callStack)
{
- if (args.isEmpty())
- return;
-
- Page* page = this->page();
- if (!page)
- return;
-
- page->inspectorController()->addMessageToConsole(JSMessageSource, ObjectMessageLevel, exec, args, 0, String());
+ addMessage(ObjectMessageLevel, callStack);
}
-void Console::dirxml(ExecState* exec, const ArgList& args)
+void Console::dirxml(ScriptCallStack* callStack)
{
- if (args.isEmpty())
- return;
-
- Page* page = this->page();
- if (!page)
- return;
-
- page->inspectorController()->addMessageToConsole(JSMessageSource, NodeMessageLevel, exec, args, 0, String());
+ addMessage(NodeMessageLevel, callStack);
}
-void Console::trace(ExecState* exec)
+void Console::trace(ScriptCallStack* callStack)
{
- Page* page = this->page();
- if (!page)
- return;
-
- int signedLineNumber;
- intptr_t sourceID;
- UString urlString;
- JSValue* func;
+ addMessage(TraceMessageLevel, callStack, true);
- exec->interpreter()->retrieveLastCaller(exec, signedLineNumber, sourceID, urlString, func);
+ if (!shouldPrintExceptions())
+ return;
- ArgList args;
- while (!func->isNull()) {
- args.append(func);
- func = exec->interpreter()->retrieveCaller(exec, asInternalFunction(func));
+ printf("Stack Trace\n");
+ for (unsigned i = 0; i < callStack->size(); ++i) {
+ String functionName = String(callStack->at(i).functionName());
+ printf("\t%s\n", functionName.utf8().data());
}
-
- page->inspectorController()->addMessageToConsole(JSMessageSource, TraceMessageLevel, exec, args, 0, String());
}
-void Console::assertCondition(bool condition, ExecState* exec, const ArgList& args)
+void Console::assertCondition(bool condition, ScriptCallStack* callStack)
{
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);
+ addMessage(ErrorMessageLevel, callStack, true);
}
-void Console::count(ExecState* exec, const ArgList& args)
+void Console::count(ScriptCallStack* callStack)
{
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));
+ const ScriptCallFrame& lastCaller = callStack->at(0);
+ // Follow Firebug's behavior of counting with null and undefined title in
+ // the same bucket as no argument
+ String title;
+ getFirstArgumentAsString(lastCaller, title);
- page->inspectorController()->count(title, lineNumber, url.string());
+ page->inspectorController()->count(title, lastCaller.lineNumber(), lastCaller.sourceURL().string());
}
-void Console::profile(ExecState* exec, const ArgList& args)
+#if USE(JSC)
+
+void Console::profile(const JSC::UString& title, ScriptCallStack* callStack)
{
Page* page = this->page();
if (!page)
return;
+ if (title.isNull())
+ 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);
+ JSC::Profiler::profiler()->startProfiling(callStack->state(), title);
}
-void Console::profileEnd(ExecState* exec, const ArgList& args)
+void Console::profileEnd(const JSC::UString& title, ScriptCallStack* callStack)
{
Page* page = this->page();
if (!page)
return;
- if (!page->inspectorController()->profilerEnabled())
+ if (title.isNull())
return;
- UString title;
- if (args.size() >= 1)
- title = valueToStringWithUndefinedOrNullCheck(exec, args.at(exec, 0));
+ if (!page->inspectorController()->profilerEnabled())
+ return;
- RefPtr<Profile> profile = Profiler::profiler()->stopProfiling(exec, title);
+ RefPtr<JSC::Profile> profile = JSC::Profiler::profiler()->stopProfiling(callStack->state(), 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);
+ const ScriptCallFrame& lastCaller = callStack->at(0);
+ page->inspectorController()->addProfile(profile, lastCaller.lineNumber(), lastCaller.sourceURL());
}
}
-void Console::time(const UString& title)
-{
- if (title.isNull())
- return;
+#endif
+void Console::time(const String& title)
+{
Page* page = this->page();
if (!page)
return;
+
+ // Follow Firebug's behavior of requiring a title that is not null or
+ // undefined for timing functions
+ if (title.isNull())
+ return;
page->inspectorController()->startTiming(title);
}
-void Console::timeEnd(ExecState* exec, const ArgList& args)
+void Console::timeEnd(const String& title, ScriptCallStack* callStack)
{
- UString title;
- if (args.size() >= 1)
- title = valueToStringWithUndefinedOrNullCheck(exec, args.at(exec, 0));
- if (title.isNull())
- return;
-
Page* page = this->page();
if (!page)
return;
+ // Follow Firebug's behavior of requiring a title that is not null or
+ // undefined for timing functions
+ if (title.isNull())
+ return;
+
double elapsed;
if (!page->inspectorController()->stopTiming(title, elapsed))
return;
- String message = String(title) + String::format(": %.0fms", elapsed);
+ String message = title + String::format(": %.0fms", elapsed);
- KURL url;
- unsigned lineNumber;
- retrieveLastCaller(exec, url, lineNumber);
-
- page->inspectorController()->addMessageToConsole(JSMessageSource, LogMessageLevel, message, lineNumber, url.string());
+ const ScriptCallFrame& lastCaller = callStack->at(0);
+ page->inspectorController()->addMessageToConsole(JSMessageSource, LogMessageLevel, message, lastCaller.lineNumber(), lastCaller.sourceURL().string());
}
-void Console::group(ExecState* exec, const ArgList& arguments)
+void Console::group(ScriptCallStack* callStack)
{
Page* page = this->page();
if (!page)
return;
- page->inspectorController()->startGroup(JSMessageSource, exec, arguments, 0, String());
+ page->inspectorController()->startGroup(JSMessageSource, callStack);
}
void Console::groupEnd()
page->inspectorController()->endGroup(JSMessageSource, 0, String());
}
-void Console::warn(ExecState* exec, const ArgList& args)
+void Console::warn(ScriptCallStack* callStack)
{
- 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);
+ addMessage(WarningMessageLevel, callStack);
}
static bool printExceptions = false;
#define Console_h
#include "PlatformString.h"
+
+#if USE(JSC)
#include <profiler/Profile.h>
+#endif
+
#include <wtf/RefCounted.h>
#include <wtf/PassRefPtr.h>
-namespace JSC {
- class ExecState;
- class ArgList;
-}
-
namespace WebCore {
+#if USE(JSC)
typedef Vector<RefPtr<JSC::Profile> > ProfilesArray;
+#endif
class Frame;
class Page;
class String;
+ class ScriptCallStack;
// Keep in sync with inspector/front-end/Console.js
enum MessageSource {
void addMessage(MessageSource, MessageLevel, const String& message, unsigned lineNumber, const String& sourceURL);
+ void debug(ScriptCallStack*);
+ void error(ScriptCallStack*);
+ void info(ScriptCallStack*);
+ void log(ScriptCallStack*);
+ void warn(ScriptCallStack*);
+ void dir(ScriptCallStack*);
+ void dirxml(ScriptCallStack*);
+ void trace(ScriptCallStack*);
+ void assertCondition(bool condition, ScriptCallStack*);
+ void count(ScriptCallStack*);
#if USE(JSC)
- void debug(JSC::ExecState*, const JSC::ArgList&);
- void error(JSC::ExecState*, const JSC::ArgList&);
- void info(JSC::ExecState*, const JSC::ArgList&);
- void log(JSC::ExecState*, const JSC::ArgList&);
- void warn(JSC::ExecState*, const JSC::ArgList&);
- void dir(JSC::ExecState*, const JSC::ArgList&);
- void dirxml(JSC::ExecState*, const JSC::ArgList& arguments);
- void trace(JSC::ExecState*);
- void assertCondition(bool condition, JSC::ExecState*, const JSC::ArgList&);
- void count(JSC::ExecState*, const JSC::ArgList&);
- void profile(JSC::ExecState*, const JSC::ArgList&);
- void profileEnd(JSC::ExecState*, const JSC::ArgList&);
- void time(const JSC::UString& title);
- void timeEnd(JSC::ExecState*, const JSC::ArgList&);
- void group(JSC::ExecState*, const JSC::ArgList&);
+ void profile(const JSC::UString&, ScriptCallStack*);
+ void profileEnd(const JSC::UString&, ScriptCallStack*);
+#endif
+ void time(const String&);
+ void timeEnd(const String&, ScriptCallStack*);
+ void group(ScriptCallStack*);
void groupEnd();
static bool shouldPrintExceptions();
static void setShouldPrintExceptions(bool);
+#if USE(JSC)
const ProfilesArray& profiles() const { return m_profiles; }
#endif
private:
inline Page* page() const;
+ void addMessage(MessageLevel, ScriptCallStack*, bool acceptNoArguments = false);
Console(Frame*);
Frame* m_frame;
+#if USE(JSC)
ProfilesArray m_profiles;
+#endif
};
} // namespace WebCore
module window {
interface Console {
- readonly attribute [CustomGetter] Array profiles;
+
+#if !defined(V8_BINDING)
+ readonly attribute [CustomGetter] Array profiles;
+#endif
- [Custom] void debug();
- [Custom] void error();
- [Custom] void info();
- [Custom] void log();
- [Custom] void warn();
- [Custom] void dir();
- [Custom] void dirxml();
- [Custom] void trace();
- [Custom, ImplementationFunction=assertCondition] void assert(in boolean condition);
- [Custom] void count();
+ [CustomArgumentHandling] void debug();
+ [CustomArgumentHandling] void error();
+ [CustomArgumentHandling] void info();
+ [CustomArgumentHandling] void log();
+ [CustomArgumentHandling] void warn();
+ [CustomArgumentHandling] void dir();
+ [CustomArgumentHandling] void dirxml();
+ [CustomArgumentHandling] void trace();
+ [CustomArgumentHandling, ImplementationFunction=assertCondition] void assert(in boolean condition);
+ [CustomArgumentHandling] void count();
+
+#if !defined(V8_BINDING)
+ [CustomArgumentHandling] void profile(in [ConvertUndefinedOrNullToNullString] DOMString title);
+ [CustomArgumentHandling] void profileEnd(in [ConvertUndefinedOrNullToNullString] DOMString title);
+#endif
- [Custom] void profile(in DOMString title);
- [Custom] void profileEnd();
void time(in [ConvertUndefinedOrNullToNullString] DOMString title);
- [Custom] void timeEnd();
- [Custom] void group();
+ [CustomArgumentHandling] void timeEnd(in [ConvertUndefinedOrNullToNullString] DOMString title);
+ [CustomArgumentHandling] void group();
void groupEnd();
};