有没有办法在堆栈跟踪中更改函数的路径?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了有没有办法在堆栈跟踪中更改函数的路径?相关的知识,希望对你有一定的参考价值。

假设我们有一个函数,它生成一个错误抛出函数:

function p(){
    function q(){
        throw new Error();
    }
    q();
}
p();

堆栈跟踪看起来像这样:

Error: x
    at path:3:8
    at q (path:5:4)
    at p (path:7:1)

然后p函数看起来像这样:

如何更改p以获得如下堆栈跟踪?

Error: x
    at something-else:12:12
    at q (something-else:34:34)
    at p (path:7:1)

我不控制文件,因为通过客户端代码我们现在使用bundle,所以将q放入一个单独的文件不是一个解决方案。据我所知,我的要求是不可能的,但也许有人比我更了解js。 :d

如果你想知道这里的目标是什么,我想教一下路径在帧字符串中的堆栈解析器。

答案

我找到了多种方法:

1.) data URI

我开始使用数据URI方法,这种方法并没有广泛支持,但仍然不止于此:

function report(e){
    console.log(e.stack);
}

window.onload = function (){
    var s = document.createElement("script");
    s.setAttribute("src", "data:text/html,try {throw new Error;}catch(e){report(e);}");
    var body = document.getElementsByTagName("body")[0];
    body.appendChild(s);
}

它适用于除IE之外的最新主要桌面浏览器,它不允许脚本标记的数据URI。它记录以下堆栈:

Error
    at data:text/html,try {throw new Error;}catch(e){report(e);}:1:12

2.) IFrames

在那之后我想到了它并且我认为如果这适用于数据URI,那么它也可能适用于iframe,所以我提出了这个:

function report(e){
    console.log(e.stack);
}

window.onload = function (){
    var i = document.createElement("iframe");
    i.setAttribute("style", "display:none");
    var body = document.getElementsByTagName("body")[0];
    body.appendChild(i);

    var idoc = i.contentDocument || i.contentWindow.document;
    var ibody = idoc.getElementsByTagName("body")[0];
    var s = document.createElement("script");
    s.innerHTML="try {throw new Error;}catch(e){parent.report(e);}";
    ibody.appendChild(s);
}

它记录以下堆栈:

FF:

@about:blank:1:12
window.onload@file:///C:/Users/inf3rno/Downloads/x.html:18:2

Chrome和Opera:

Error
    at <anonymous>:1:12

IE11

Error
   at Global code (Unknown script code:1:6)
   at window.onload (file:///C:/Users/inf3rno/Downloads/x.html:17:2)

我们可以通过添加函数调用添加另一个框架:

s.innerHTML="function a(){
try {
throw new Error;
}catch(e){
parent.report(e);
}
};
 a();";

在IE中记录以下内容:

Error
   at a (Unknown script code:3:1)
   at Global code (Unknown script code:8:2)
   at window.onload (file:///C:/Users/inf3rno/Downloads/x.html:19:2)

所以我们可以将at a (Unknown script code:3:1)与父窗口中调用的类似函数进行比较:at a (file:///C:/Users/inf3rno/Downloads/x.html:13:1),它相对容易找到路径。

3.) Eval

使用eval是一种有趣的方法。它在IE中提供类似at a (eval code:3:1)的东西,而在其他浏览器和节点中它提供了一个复杂的嵌套位置:at a (eval at window.onload (x.html:21), <anonymous>:3:7)at a (eval at <anonymous> (repl:1:1), <anonymous>:1:20)。我认为这是最好的方法,因为它不需要DOM,即使在严格模式下也可以在每个js环境中使用。

以上是关于有没有办法在堆栈跟踪中更改函数的路径?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法在黑莓中以字符串的形式获取异常的堆栈跟踪?

有没有办法在不抛出异常的情况下转储堆栈跟踪?

在 Firebase 中禁用自动活动跟踪

跟踪应用程序堆栈更改事件 wp8.1

LinuxBPF学习笔记 - 堆栈跟踪[3]

LinuxBPF学习笔记 - 堆栈跟踪[3]