【问题标题】:Is there a way to change the path of a function in the stack trace?有没有办法改变堆栈跟踪中函数的路径?
【发布时间】:2018-03-01 04:08:25
【问题描述】:

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

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)

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

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

【问题讨论】:

  • 除了使用定义自己的堆栈跟踪的自定义类扩展 Error 之外,我真的想不出客户端的其他任何东西。
  • @PatrickRoberts 我在考虑数据 URI,但我现在无法测试它,它们在旧浏览器中不起作用。

标签: javascript error-handling runtime-error stack-trace


【解决方案1】:

我找到了多种方法:

1.) 数据 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.) IFrame

后来我想了想,如果这适用于数据 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(){\ntry {\nthrow new Error;\n}catch(e){\nparent.report(e);\n}\n};\n 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 是一种有趣的方法。它在 IE 中提供类似于 at a (eval code:3:1) 的内容,而在其他浏览器和节点中,它提供了一个复杂的嵌套位置:at a (eval at window.onload (x.html:21), &lt;anonymous&gt;:3:7)at a (eval at &lt;anonymous&gt; (repl:1:1), &lt;anonymous&gt;:1:20)。我认为这是最好的方法,因为它不需要 DOM,即使在严格模式下也可以在每个 js 环境中使用。

【讨论】:

    猜你喜欢
    • 2012-07-07
    • 2021-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-28
    • 2012-06-18
    • 1970-01-01
    相关资源
    最近更新 更多