如何覆盖/扩展Chrome';什么是JavaScript?

如何覆盖/扩展Chrome';什么是JavaScript?,javascript,google-chrome,google-chrome-devtools,chromium,developer-tools,Javascript,Google Chrome,Google Chrome Devtools,Chromium,Developer Tools,为了简化调试,我将在Chrome中捕获所有控制台日志,以便提交反馈条目的用户也将所有日志提交到我们的服务器。当有人在生产中遇到问题时,我可以首先让他们重新工作,这样我就可以坐下来更彻底地查看所有日志,以确定用户在生产中遇到的任何问题的根本原因 我用于捕获日志的技术涉及重写console.log,以便在同时调用遗留函数时将第一个参数中输入的所有文本存储在一个数组中,以便我仍然可以在控制台中看到日志 问题在于偶尔会出现未捕获的异常。上传的日志中不包含这些内容,因此并不总是清楚问题的原因。因此,我尝试

为了简化调试,我将在Chrome中捕获所有控制台日志,以便提交反馈条目的用户也将所有日志提交到我们的服务器。当有人在生产中遇到问题时,我可以首先让他们重新工作,这样我就可以坐下来更彻底地查看所有日志,以确定用户在生产中遇到的任何问题的根本原因

我用于捕获日志的技术涉及重写console.log,以便在同时调用遗留函数时将第一个参数中输入的所有文本存储在一个数组中,以便我仍然可以在控制台中看到日志

问题在于偶尔会出现未捕获的异常。上传的日志中不包含这些内容,因此并不总是清楚问题的原因。因此,我尝试重写ReferenceError,方法是编写一个JavaScript函数,将函数作为参数,然后返回一个新函数来处理它,比如将数据存储在变量中,然后调用遗留函数作为最后一步:

function overrideException(legacyFn) {  

    /** arguments for original fn **/
    return function() {

        var args = [];

        args[0] = arguments[0];

        // pass in as arguments to original function and store result to 
          // prove we overrode the ReferenceError
        output = ">> " + legacyFn.apply(this, args).stack;

        return legacyFn.apply(this, arguments);
    }           

}
为了测试OverrideeException函数,我在控制台上运行了以下代码:

ReferenceError = overrideException(ReferenceError);
之后,我通过手动抛出ReferenceError来测试返回的函数new ReferenceError:

throw new ReferenceError("YES!! IT WORKS! HAHAHA!");
控制台上的结果输出为:

参考错误:是!!它起作用了!哈哈哈

从OverrideeException函数检查全局变量
输出
,表明它确实运行了:

output
  ">> ReferenceError: YES!! IT WORKS! HAHAHA!
  at ReferenceError (<anonymous>)
  at new <anonymous> (<anonymous>:18:35)
  at <anonymous>:2:7
  at Object.InjectedScript._evaluateOn (<anonymous>:562:39)
  at Object.InjectedScript._evaluateAndWrap (<anonymous>:521:52)
  at Object.InjectedScript.evaluate (<anonymous>:440:21)"
其结果是:

ReferenceError:未定义ttt

但是,与我们显式抛出错误的情况不同,在这种情况下,函数不会启动,只剩下遗留功能。变量
输出的内容与第一次测试中的内容相同

所以问题似乎是这样的:我们如何覆盖JavaScript引擎用来抛出错误的ReferenceError功能,使其与抛出ReferenceError时使用的功能相同?


请记住,目前我的问题仅限于Chrome;我正在构建一个Chrome套装应用程序。

出于同样的原因,我做了很多研究:我想记录错误并报告它们

无法“重写”本机类型(无论是
ReferenceError
String
、还是
Array

Chrome在运行任何Javascript之前都会绑定这些内容,因此重新定义
window.ReferenceError
没有任何效果

您可以使用类似于
ReferenceError.prototype.extension=function(){return 0;}
的内容扩展
ReferenceError
,甚至可以覆盖
toString
(为了一致性,请在页面上尝试,而不是在开发工具上)

那帮不了你多少忙

但不要担心……

(1) 使用
window.onerror
获取未捕获错误的文件名、1索引行号和0索引位置,以及错误本身

var errorData = [];
onerror = function(message, file, line, position, error) {
    errorData.push({message:message, file:file, line:line, position:position, error:error});
};
有关示例,请参见。由于OP是特定于Chrome的,因此它仅在Chrome中测试过

(2) 由于(1)的改进,这不再是必要的,但为了完整起见,我将第二种技术留在这里,因为
onerror
是。您有时还会看到以下内容:

var errors = [];
function protectedFunction(f) {
    return function() {
        try {
            f.apply(this, arguments);
        } catch(e) {
            errors.push(e);
            throw e;
        }
    };
}
setTimeout = protectedFunction(setTimeout);
setInterval = protectedFunction(setInterval);
etc...

仅供参考,所有这些都非常类似于Google Closure编译器库中所做的工作,它是在Gmail开发过程中创建的,目的就是要做到这一点。特别有趣的是
goog.debug.ErrorHandler
goog.debug.ErrorReporter

猜测您不想将代码包装在
try/catch
中,然后处理错误对象,然后重新抛出到那里?@CrazyTrain-我可以这样做,而且我可能会这样做。然而,这是乏味的,也有可能错过一些东西。我喜欢虚拟证明和包罗万象的解决方案,因为它们通常也是“我太忙了证明”:)我的计划当然是使用更多的try/catch,但这似乎是一个非常好的解决方案,所以我开始深入研究。我指的是一个完整的
try/catch
,它包装了所有代码。既然目标似乎不是就地处理错误,而是以某种方式重新格式化错误,那么将所有代码包装在一个
try/catch
中似乎与当前替换构造函数的方法没有什么不同。你只需要确定你会抛出你得到的任何错误。@CrazyTrain-我确实想过,但是整个应用程序会停止工作。。。六羟甲基三聚氰胺六甲醚。。。或者它会。。。出于好奇,我可能不得不尝试您的建议,但我真的很想看看如何覆盖这些本机错误对象。:)@CrazyTrain——这是一个创造性的建议,但问题是try/catch中的代码只运行一次,当页面最初加载并加载所有其他函数和事件处理程序时。一旦运行,它就不再运行了,所以每个函数和事件处理程序仍然需要自己独立的try/catch块。希望这有帮助!先生,你真是个天才!我尝试了一下,实际上我的代码中有一个我不知道的真正未捕获的异常,它被记录到了我的日志框架中!我需要更多地使用它,因为我注意到它在某些回调中不起作用。我希望您的setTimeout/setInterval方法能适用于这些情况+1谢谢。(1) 应适用于所有未捕获的异常(无论是来自脚本求值、事件侦听器等)。如果你发现它不起作用,请告诉我。明天我将不得不继续处理它,我可能刚刚犯了一个错误,但我记得其他一些事件处理程序抛出了chrome.app.window.create中生成的错误,而不是window.onerror处理它们。我正在Chrome打包的应用程序
create
方法回调函数中尝试此操作。
Chrome.app.window.create
似乎是
var errors = [];
function protectedFunction(f) {
    return function() {
        try {
            f.apply(this, arguments);
        } catch(e) {
            errors.push(e);
            throw e;
        }
    };
}
setTimeout = protectedFunction(setTimeout);
setInterval = protectedFunction(setInterval);
etc...