教程:使用 Debugger
设置断点¶
此页面展示了如何使用 Firefox 的 Scratchpad 自己尝试 Debugger
API。我们使用 Debugger
在函数中设置断点,然后在每次断点命中时计算表达式。
本教程已针对 Firefox 58 Beta 和 Nightly 版本进行了测试。它不适用于 Firefox 57。
由于
Debugger
API 仅对特权 JavaScript 代码可用,因此您需要使用浏览器内容工具箱来试用它。为此,请打开 Firefox 开发者工具,单击工具箱右上角的选项齿轮,并确保选中“启用浏览器 chrome 和附加组件调试工具箱”和“启用远程调试”。这些位于选项面板的右下角;您可能需要滚动才能看到它们。选中后,您可以关闭开发者工具。将以下文本保存到 HTML 文件中
<div onclick="report('the best div');">Click me!</div> <div onclick="report('another great div');">Or me!</div> <script> function report(what) { console.log('clicked: ' + what); } </script>
在浏览器中访问 HTML 文件,并通过打开 Firefox 菜单、选择“浏览器工具”,然后选择“浏览器内容工具箱”来打开浏览器内容工具箱。如果“浏览器工具”菜单中未显示该项目,请确保您已选中两个框以启用浏览器内容工具箱,如步骤 1 中所述。
我们的示例代码足够长,因此运行它的最佳方法是使用 Scratchpad 面板,该面板默认情况下未启用。要启用它,请单击浏览器内容工具箱右上角的选项齿轮,并确保选中左侧“默认开发者工具”部分中的“Scratchpad”框。Scratchpad 面板应显示在工具箱顶部,与控制台、调试器和内存面板并排。
单击 Scratchpad 面板并输入以下代码
const { addDebuggerToGlobal } = ChromeUtils.importESModule( "resource://gre/modules/jsdebugger.sys.mjs" ); // This simply defines 'Debugger' in this Scratchpad; // it doesn't actually start debugging anything. addDebuggerToGlobal(globalThis); // Create a 'Debugger' instance. var dbg = new Debugger; // Make the tab's top window a debuggee, and get a // Debugger.Object referring to the window. var windowDO = dbg.addDebuggee(tabs[0].content); // Get a Debugger.Object referring to the window's `report` // function. var reportDO = windowDO.getOwnPropertyDescriptor('report').value; // Set a breakpoint at the entry point of `report`. reportDO.script.setBreakpoint(0, { hit: function (frame) { console.log('hit breakpoint in ' + frame.callee.name); console.log('what = ' + frame.eval('what').return); } }); console.log('Finished setting breakpoint!');
在 Scratchpad 中,确保没有选中任何文本,然后按“运行”按钮。
现在,单击网页中显示的“点击我!”文本。这将运行
div
元素的onclick
处理程序。当控制权到达report
函数的开头时,Debugger
调用断点处理程序的hit
方法,并传递一个Debugger.Frame
实例。hit
方法将断点命中记录到浏览器内容工具箱的控制台。然后它在给定的堆栈帧中计算表达式what
,并记录其结果。工具箱的控制台现在如下所示您也可以单击显示“或者我!”的文本,以查看从不同处理程序调用的
report
。如果
Debugger
无法找到report
函数,或者控制台输出未显示,请在控制台中计算表达式tabs[0].content.document.location
以确保tabs[0]
确实引用了您访问的 HTML 文件。如果您有多个选项卡访问file:
URL,则它们都共享一个内容进程,因此您可能需要使用数组的不同元素作为调试对象。再次在 Scratchpad 中按“运行”。现在,单击“点击我!”会导致断点命中被记录两次——每个
Debugger
实例一次。多个
Debugger
实例可以观察同一个调试对象。在 Scratchpad 中重新运行代码会创建一个新的Debugger
实例,将同一个网页添加为其调试对象,然后设置一个新的断点。当您单击div
元素时,两个Debugger
的断点都会命中,并且两个处理程序都会运行。这表明任意数量的基于
Debugger
的工具可以同时观察单个网页。实际上,您可以使用浏览器内容工具箱的调试器面板在report
中设置自己的断点,它将与前两个一起触发。但是请记住,当多个调试器共享一个调试对象时,其处理程序运行的顺序未指定。如果多个工具试图影响调试对象的行为,则它们的组合行为可能是不可预测的。关闭网页和浏览器内容工具箱。
由于 Scratchpad 的全局对象和调试对象窗口现在都消失了,因此
Debugger
实例将被垃圾回收,因为它们不再对 Firefox 的行为产生任何可见影响。Debugger
API 尝试尽可能透明地与垃圾回收交互;例如,如果Debugger.Object
实例及其引用都不可访问,则它们都将被回收,即使属于该阴影的Debugger
实例继续存在。