javascript - 当已经在“常规”调试器语句处停止时,如何进入 eval('debugger') 模式?
问题描述
我最近开始用语句替换我的所有debugger
语句eval('debugger')
。原因是对于普通版本,并非所有“事实上/理论上”可见变量都是“实际上”可见的。发生这种情况是因为优化(请参阅前面的 SO 问题)。
有了这个技巧,问题就像“解决了 90%”——有一些缺点。除了更长的源代码外,还有:
- 当涉及第三方库时,这是不可行的,甚至不可能在那里完成
debugger
->eval('debugger')
转换。 - 当我宁愿在调试器本身中设置断点而不是更改代码时,这是无法完成的——或者可以吗?
- 当我已经停止在“正常”
debugger
语句(在第三方代码中,或者我忘记了)时,没有办法切换到所需的模式 - 当然eval('debugger')
在控制台上输入也无济于事。如果我想要这个功能,我必须更改调试器语句,然后再次运行代码,这可能需要大量工作 - 当我在一个语句处停下来
eval('debugger')
,但随后使用调试器“跳过/进入/退出”功能时,我“失去了我的特殊身份”。
我该如何解决这个问题?有没有办法告诉 v8 通过 eval('debugger') 解释所有调试器语句?有没有一个技巧可以让你“进入另一种模式”——好像 eval('debugger') 语句会神奇地出现在你停止的调试器语句之后的下一个语句?chrome可执行文件的命令行选项有帮助吗?也许Firefox中有一种方法?
我在回答我自己最近的一个 SO 问题时了解到了这个eval('debugger')
技巧
公告
我接下来要做的是编写一个小转译器,以便在节点网络服务器中使用。转译器将在所有地方插入eval('')
语句(默认情况下,在每个函数的开头/主体处插入一次,如果在查询字符串中指定了更多或更少的语句。)然后我可以在 eval 语句所在的位置设置断点,执行“步入”然后我得到了我想要的。然后我要回答我自己的问题。
当然,除非有人会打败我。那将是最令人愉快的,因为我还有其他事情要做。
解决方案
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
并且没有其他人需要它)。如果inner
contains eval
,那么它可能需要所有外部范围变量。--编辑结束]
这是因为优化
嗯......因为优化,即在堆栈上还是在“上下文对象”中分配变量时很聪明。这与通常所说的“函数优化”完全无关,即通过优化编译器运行它们。这就是为什么%NeverOptimizeFunction
在另一个问题中讨论的 hack 没有效果——这是一个不相关的机制。
推荐阅读
- sql - 年度销售额比较的 CASE 表达式?
- java - Java 中 void lambda 的函数纯度
- google-cloud-monitoring - 图表统计视图中的 Stackdriver 相似度
- javascript - 如何根据选择的单选按钮显示和验证文本框
- java - 在 JavaFX 中逐像素生成图像,进度可见
- keras - tflearn 中的稀疏分类交叉熵损失
- php - wordpress css 尝试从子主题而不是父主题加载文件
- angular - 捕获并返回错误时,Rxjs 可观察到的抛出错误
- php - PHP POST 方法添加磨损值
- bash - 通过 apt-get 安装时,Linux 中的 virtualenvwrapper 函数在哪里获取?