我希望自定义在Google Chrome开发人员工具的“脚本”标签中显示在strack跟踪面板中的项目。具体来说,我想过滤掉堆栈跟踪中的项目,并为堆栈跟踪中的某些项目添加更多描述性名称,而不必重命名我的对象和函数。
我在http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi找到了V8的Stack Trace API,但是覆盖Error.prepareStackTrace似乎没有任何效果。
答案 0 :(得分:7)
该页面上的描述肯定有点难以理解,以下是它的完成方式:
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));
}
这将显示:
trace from catch():
[object Object].someObj.someMethod
[object Window].bar
[object Window].foo
[object Window].
最后一帧是全局范围(无函数名称)。
基本上,您对prepareStackTrace()的覆盖会导致error.stack成为您从prepareStackTrace()返回的任何内容。诀窍在于prepareStackTrace()的第二个参数是一个CallSite对象数组 - 支持getThis(),getFunctionName()等的对象。
上面的代码覆盖prepareStackTrace(),以便它返回CallSite对象的数组(上面的“stack”参数),这意味着当你尝试..catch一个错误时,Error.stack将包含CallSite数组对象而不是String形式的通常堆栈跟踪。另一种方法是在替换的prepareStackTrace()函数中处理CallSite对象,并将替代堆栈跟踪作为String返回。
请注意,CallSite对象非常挑剔。尝试做frame.toString(),或者只是尝试警告(框架)(隐含地涉及toString())并且它崩溃并且Chrome的开发人员工具没有显示错误。
答案 1 :(得分:1)
以下是为我提供诀窍的代码:
<head>
<script>
Error.prepareStackTrace = function()
{
return "MyStackObject";
}
try {
throw new Error();
} catch (e) {
console.log(e.stack);
}
</script>
</head>
答案 2 :(得分: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); }