Ignore:
Timestamp:
Feb 17, 2012, 1:17:59 PM (13 years ago)
Author:
[email protected]
Message:

Implement Error.stack
https://bugs.webkit.org/show_bug.cgi?id=66994

Reviewed by Gavin Barraclough.

Source/JavaScriptCore:

Implement support for stack traces on exception objects. This is a rewrite
of the core portion of the last stack walking logic, but the mechanical work
of adding the information to an exception comes from the original work by
Juan Carlos Montemayor Elosua.

  • interpreter/Interpreter.cpp:

(JSC::getCallerInfo):
(JSC):
(JSC::getSourceURLFromCallFrame):
(JSC::getStackFrameCodeType):
(JSC::Interpreter::getStackTrace):
(JSC::Interpreter::throwException):
(JSC::Interpreter::privateExecute):

  • interpreter/Interpreter.h:

(JSC):
(StackFrame):
(JSC::StackFrame::toString):
(Interpreter):

  • jsc.cpp:

(GlobalObject::finishCreation):
(functionJSCStack):

  • parser/Nodes.h:

(JSC::FunctionBodyNode::setInferredName):

  • parser/Parser.h:

(JSC::::parse):

  • runtime/CommonIdentifiers.h:
  • runtime/Error.cpp:

(JSC::addErrorInfo):

  • runtime/Error.h:

(JSC):

LayoutTests:

Add testcases for producing a stack trace on exception objects.

  • fast/js/exception-properties-expected.txt:
  • fast/js/script-tests/exception-properties.js:
  • fast/js/script-tests/stack-trace.js: Added.

(printStack):
(hostThrower):
(callbacker):
(outer):
(inner):
(evaler):
(normalOuter):
(normalInner):
(scripterInner):
(scripterOuter):
(selfRecursive1):
(selfRecursive2):
(selfRecursive3):
(throwError):
(object.get getter1.o.valueOf):
(object.get getter1):
(object.get getter2):
(object.get getter3.o2.valueOf):
(object.get getter3):
(object.nonInlineable.callCount):
(object.nonInlineable):
(object.inlineable):
(yetAnotherInlinedCall):
(makeInlinableCall):
(.try.g):
(h):
(mapTest):
(mapTestDriver):
(dfgFunction):
(try.f):

  • fast/js/stack-trace-expected.txt: Added.
  • fast/js/stack-trace.html: Added.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.h

    r108036 r108112  
    3232#include "ArgList.h"
    3333#include "JSCell.h"
     34#include "JSFunction.h"
    3435#include "JSValue.h"
    3536#include "JSObject.h"
     
    4344    class CodeBlock;
    4445    class EvalExecutable;
     46    class ExecutableBase;
    4547    class FunctionExecutable;
    46     class JSFunction;
    4748    class JSGlobalObject;
    4849    class ProgramExecutable;
     
    6364    };
    6465
     66    enum StackFrameCodeType {
     67        StackFrameGlobalCode,
     68        StackFrameEvalCode,
     69        StackFrameFunctionCode,
     70        StackFrameNativeCode
     71    };
     72
     73    struct StackFrame {
     74        Strong<JSObject> callee;
     75        StackFrameCodeType codeType;
     76        Strong<ExecutableBase> executable;
     77        int line;
     78        UString sourceURL;
     79        UString toString(CallFrame* callFrame) const
     80        {
     81            bool hasSourceURLInfo = !sourceURL.isNull() && !sourceURL.isEmpty();
     82            bool hasLineInfo = line > -1;
     83            String traceLine;
     84            JSObject* stackFrameCallee = callee.get();
     85
     86            switch (codeType) {
     87            case StackFrameEvalCode:
     88                if (hasSourceURLInfo) {
     89                    traceLine = hasLineInfo ? String::format("eval code@%s:%d", sourceURL.ascii().data(), line)
     90                                            : String::format("eval code@%s", sourceURL.ascii().data());
     91                } else
     92                    traceLine = String::format("eval code");
     93                break;
     94            case StackFrameNativeCode: {
     95                if (callee) {
     96                    UString functionName = getCalculatedDisplayName(callFrame, stackFrameCallee);
     97                    traceLine = String::format("%s@[native code]", functionName.ascii().data());
     98                } else
     99                    traceLine = "[native code]";
     100                break;
     101            }
     102            case StackFrameFunctionCode: {
     103                UString functionName = getCalculatedDisplayName(callFrame, stackFrameCallee);
     104                if (hasSourceURLInfo) {
     105                    traceLine = hasLineInfo ? String::format("%s@%s:%d", functionName.ascii().data(), sourceURL.ascii().data(), line)
     106                                            : String::format("%s@%s", functionName.ascii().data(), sourceURL.ascii().data());
     107                } else
     108                    traceLine = String::format("%s\n", functionName.ascii().data());
     109                break;
     110            }
     111            case StackFrameGlobalCode:
     112                if (hasSourceURLInfo) {
     113                    traceLine = hasLineInfo ? String::format("global code@%s:%d", sourceURL.ascii().data(), line)
     114                                            : String::format("global code@%s", sourceURL.ascii().data());
     115                } else
     116                    traceLine = String::format("global code");
     117                   
     118            }
     119            return traceLine.impl();
     120        }
     121    };
     122
    65123    class TopCallFrameSetter {
    66124    public:
     
    152210        NEVER_INLINE HandlerInfo* throwException(CallFrame*&, JSValue&, unsigned bytecodeOffset);
    153211        NEVER_INLINE void debug(CallFrame*, DebugHookID, int firstLine, int lastLine);
     212        static const UString getTraceLine(CallFrame*, StackFrameCodeType, const UString&, int);
     213        JS_EXPORT_PRIVATE static void getStackTrace(JSGlobalData*, int line, Vector<StackFrame>& results);
    154214
    155215        void dumpSampleData(ExecState* exec);
Note: See TracChangeset for help on using the changeset viewer.