首页 > 解决方案 > 当已经在“常规”调试器语句处停止时,如何进入 eval('debugger') 模式?

问题描述

我最近开始用语句替换我的所有debugger语句eval('debugger')。原因是对于普通版本,并非所有“事实上/理论上”可见变量都是“实际上”可见的。发生这种情况是因为优化(请参阅前面的 SO 问题)。

有了这个技巧,问题就像“解决了 90%”——有一些缺点。除了更长的源代码外,还有:

我该如何解决这个问题?有没有办法告诉 v8 通过 eval('debugger') 解释所有调试器语句?有没有一个技巧可以让你“进入另一种模式”——好像 eval('debugger') 语句会神奇地出现在你停止的调试器语句之后的下一个语句?chrome可执行文件的命令行选项有帮助吗?也许Firefox中有一种方法?

我在回答我自己最近的一个 SO 问题时了解到了这个eval('debugger')技巧

公告

我接下来要做的是编写一个小转译器,以便在节点网络服务器中使用。转译器将在所有地方插入eval('')语句(默认情况下,在每个函数的开头/主体处插入一次,如果在查询字符串中指定了更多或更少的语句。)然后我可以在 eval 语句所在的位置设置断点,执行“步入”然后我得到了我想要的。然后我要回答我自己的问题。

当然,除非有人会打败我。那将是最令人愉快的,因为我还有其他事情要做。

标签: javascriptgoogle-chromefirefoxgoogle-chrome-devtoolsv8

解决方案


V8 开发人员在这里。

有没有办法告诉 v8 通过 eval('debugger') 解释所有调试器语句?

目前没有办法将debugger语句或断点视为eval("debugger"),但添加一个这样做的标志可能是可行的。您可以在crbug.com/v8/new上提交“功能请求”错误,并请求一个标志,强制上下文分配所有变量以进行调试。

(旁注 1:这是在eval这里有影响的部分。只要你在函数中的某个位置,eval('debugger')你可以写eval(""); debugger;or代替。)debugger; other_code(); eval("");eval

(旁注 2:这里的紧张之处在于,一方面,当程序在调试时的行为与未调试时的行为相同时,它是 Good™——否则可能会出现仅显示的问题调试时,或生产模式下不可调试的故障。另一方面,有时为了使调试成为可能,某些偏差是明确需要的。我不确定这个落在哪一边。上下文分配所有变量会降低性能并增加内存消耗,因此如果/当这种模式可用时,您可能必须(或想要)在开发工作期间来回切换;这尤其意味着这不能简单地成为默认模式当 DevTools 打开时。)

有没有一个技巧可以让你“进入另一种模式”——好像 eval('debugger') 语句会神奇地出现在你停止的调试器语句之后的下一个语句?

不,也不可能。这不是“模式”或“特殊状态”,而是在第一次解析/编译外部函数(包含您想在内部函数中看到的变量的那个)时必须做出的决定。一旦那个时间过去了,改变任何东西都为时已晚(非上下文分配的变量刚刚消失),唯一的选择是重新加载。

[针对评论进行编辑:澄清我所说的“不是模式,而是决定”的意思:从范围链的角度来看,情况与以下基本相同:

var inner;
function outer() {
  var foo = "foo";
  var bar = "bar";
  inner = function() {
    console.log(bar);
    debugger;
  }
  // "inner();" here is moved below
}
outer();
inner();

inner()被调用的那一刻,foo要么仍然存在bar(如果它是上下文分配的,因为在 V8 的编译时outer确定inner需要它),要么已经消失(如果 V8 确定它是本地的outer并且没有其他人需要它)。如果innercontains eval,那么它可能需要所有外部范围变量。--编辑结束]

这是因为优化

嗯......因为优化,即在堆栈上还是在“上下文对象”中分配变量时很聪明这与通常所说的“函数优化”完全无关,即通过优化编译器运行它们。这就是为什么%NeverOptimizeFunction在另一个问题中讨论的 hack 没有效果——这是一个不相关的机制。


推荐阅读