3

我正在寻找自定义显示在 Google Chrome 开发人员工具的“脚本”选项卡中的 strack 跟踪面板中的项目。具体来说,我想过滤掉堆栈跟踪中的项目,并为堆栈跟踪中的某些项目添加更具描述性的名称,而不必重命名我的对象和函数。

我在http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi找到了 V8 的 Stack Trace API,但覆盖 Error.prepareStackTrace 似乎没有任何效果。

4

3 回答 3

7

The description on that page is definitely a little hard to follow, here's how it's done:

Error.prepareStackTrace = function(error, stack) {
    return stack;
};

var someObj = {
    someMethod : function () { 
        crash();
    }
}
function bar(barArg) { someObj.someMethod(); };
function foo(fooArg) { bar("barArgString"); };

function getTrace(e) {
    var stack = e.stack;
    var trace = "";

    for (var i = 0; i < stack.length; i++) {
        var frame = stack[i],
            func = frame.getFunction();

        trace += "\r" + frame.getThis() + "." + frame.getFunctionName();
    }
    return trace;
}

try {
    foo("fooArgString");
} catch (e) {
    alert("trace from catch(): " + getTrace(e));
}

This will show:

trace from catch(): 
[object Object].someObj.someMethod
[object Window].bar
[object Window].foo
[object Window].

The last frame is global scope (no function name).

Essentially your override of prepareStackTrace() causes error.stack to become whatever you return from prepareStackTrace(). The trick is that the second argument to prepareStackTrace() is an Array of CallSite objects - the objects that support getThis(), getFunctionName() etc.

The code above overrides prepareStackTrace() so that it returns the Array of CallSite objects ("stack" parameter above), so this means when you try..catch an Error, Error.stack is going to contain the Array of CallSite objects instead of the usual stack trace in String form. Another approach would be to process the CallSite objects inside of your replacement prepareStackTrace() function and return your alternative stack trace as a String.

Note the CallSite objects are really finicky. Try to do frame.toString(), or just try to alert(frame) (implicitly this involves toString()) and it crashes and Chrome's developer tools show no error.

于 2012-06-08T02:35:35.847 回答
1

这是对我有用的代码:

<head>
<script>
Error.prepareStackTrace = function()
{
        return "MyStackObject";
}
try {
  throw new Error();
} catch (e) {
  console.log(e.stack);
}
</script>
</head>
于 2012-01-28T14:23:29.037 回答
0

文档已移至此处: https ://github.com/v8/v8/wiki/Stack-Trace-API

只需将其放在 javascript 代码的开头,它就会格式化一个很好的堆栈跟踪:

Error.prepareStackTrace = function(error, stack) {
    var trace = '';
    var max_width = 0;
    for (var i = 0; i < stack.length; i++){
        var frame = stack[i];

        var typeLength = 0;
        typeLength = (frame.getTypeName() !== null && frame.getTypeName() !== '[object global]') ? frame.getTypeName().length : 0;
        typeLength = typeLength.length > 50 ? 50 : typeLength;

        functionlength = frame.getFunctionName() !== null ? frame.getFunctionName().length : '<anonymous>'.length;
        functionlength = functionlength > 50 ? 50 : functionlength;

        if (typeLength + functionlength > max_width)
            max_width = typeLength + functionlength;
    }

    for (var i = 0; i < stack.length; i++) {
        var frame = stack[i];

        var filepath = frame.getFileName();

        var typeName = '';  
        if (frame.getTypeName() !== null && frame.getTypeName() !== '[object global]')
            typeName = frame.getTypeName().substring(0, 50) + '.';

        var functionName = '<anonymous>';
        if (frame.getFunctionName() !== null)
            functionName = frame.getFunctionName().substring(0, 50);

        var space = '';
        var width = max_width - (typeName.length + functionName.length) + 2;
        space = Array(width).join(' ');
        var line = '  at ' + typeName + functionName + space + filepath + 
            ' (' + frame.getLineNumber() + 
            ':' + frame.getColumnNumber() + ')\n';

        trace += line;
    }
    return trace;
};

这是测试代码的示例:

function A() { B(); }
function B() { C(); }
function C() { throw new Error('asd'); }
try {
    A();
} catch (e) { print(e + '\n' + e.stack); }
于 2016-10-04T13:47:38.710 回答