<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[207228] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/207228">207228</a></dd>
<dt>Author</dt> <dd>joepeck@webkit.org</dd>
<dt>Date</dt> <dd>2016-10-12 11:47:48 -0700 (Wed, 12 Oct 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Emit DebugHooks uniformly with pause locations instead of having separate pause locations and op_debug emits
https://bugs.webkit.org/show_bug.cgi?id=162809

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

Change how BytecodeGeneration emits debug hooks to be more consistent.
Previously most nodes individually generated their own debug hook
and we asserted that it matched a breakpoint location identified
by the parser. This could get out of sync, or nodes could forget to
emit debug hooks expected by the parser.

With this change, we always check and emit a debug hook for any
node. The default behavior is for BytecodeGenerator::emitNode
to emit the debug hook when emitting the node itself. This covers
the majority of cases (statements).

There are a few exceptions where we continue to need to customize
emitting debug hooks:

    1. Nodes with emitBytecodeInConditionContext
        - non-Expression nodes customize how they emit their children
        - constants conditions may emit nothing, but we had recorded a breakpoint location so emit a debug hook
        - always emit one debug hook in case we recorded a breakpoint location, but avoid emitting multiple
          in nodes which may call up to the ExpressionNode::emitBytecodeInConditionContext base impl.
    2. Specialized Debug Hooks
        - such as hooks for Program start/end, debugger statements, etc.
    3. Debug Hooks in for..of / for..in that don't correspond to re-emitting nodes
        - such as pausing on the assignment expression inside these loops

The majority of nodes no longer have custom emits.

* bytecompiler/BytecodeGenerator.h:
(JSC::BytecodeGenerator::emitNodeInTailPosition):
(JSC::BytecodeGenerator::emitNodeInConditionContext):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitDebugHook):
(JSC::BytecodeGenerator::emitEnumeration):
By default, when emitting a node check if we should also emit an op_debug for it.
This default DebugHook is WillExecuteStatement, which is a normal pause point.

* bytecompiler/NodesCodegen.cpp:
(JSC::ConstantNode::emitBytecodeInConditionContext):
(JSC::LogicalNotNode::emitBytecodeInConditionContext):
(JSC::BinaryOpNode::emitBytecodeInConditionContext):
(JSC::LogicalOpNode::emitBytecodeInConditionContext):
The parser would have generated a pause location for these conditions
no matter what constant folding and re-writing these nodes may perform.
So, when emitting these nodes in condition context check if they need
emit their own debug hook.

(JSC::EmptyStatementNode::emitBytecode):
(JSC::ExprStatementNode::emitBytecode):
(JSC::DeclarationStatement::emitBytecode):
(JSC::IfElseNode::emitBytecode):
(JSC::DoWhileNode::emitBytecode):
(JSC::WhileNode::emitBytecode):
(JSC::ForNode::emitBytecode):
(JSC::ContinueNode::emitBytecode):
(JSC::BreakNode::emitBytecode):
(JSC::ReturnNode::emitBytecode):
(JSC::WithNode::emitBytecode):
(JSC::SwitchNode::emitBytecode):
(JSC::ThrowNode::emitBytecode):
No longer need to custom emit debug hooks. The default emitNode will handle these.

(JSC::ForInNode::emitBytecode):
Include extra debug hooks the user expects to return back to the assignment
expression in the loop header before starting the body again. The same is done
for for..of with emitEnumeration.

* parser/ASTBuilder.h:
(JSC::ASTBuilder::createExportDefaultDeclaration):
(JSC::ASTBuilder::createExportLocalDeclaration):
These are no longer needed to fake-satisfy assertions. We never wanted to
emit debug hooks for these inner statements because the export statement
will already have the debug hooks.

(JSC::ASTBuilder::createForInLoop):
(JSC::ASTBuilder::createForOfLoop):
Include the correct location where the declaration starts.

(JSC::ASTBuilder::breakpointLocation):
Simplify to a general implementation for Node.

* parser/SyntaxChecker.h:
(JSC::SyntaxChecker::createForInLoop):
(JSC::SyntaxChecker::createForOfLoop):
Ignore the new extra parameter.

* parser/Nodes.h:
(JSC::Node::needsDebugHook):
(JSC::Node::setNeedsDebugHook):
(JSC::ExpressionNode::needsDebugHook): Deleted.
(JSC::ExpressionNode::setNeedsDebugHook): Deleted.
(JSC::StatementNode::isEmptyStatement): Deleted.
(JSC::StatementNode::needsDebugHook): Deleted.
(JSC::StatementNode::setNeedsDebugHook): Deleted.
Move debug hook logic into the base Node class.

(JSC::StatementNode::isDebuggerStatement):
Provide a way to distinguish a debugger statement.

* parser/Parser.cpp:
(JSC::Parser&lt;LexerType&gt;::parseForStatement):
Provide the location before the declaration starts.

Source/WebInspectorUI:

* UserInterface/Views/SourceCodeTextEditor.js:
(WebInspector.SourceCodeTextEditor.prototype.textEditorExecutionHighlightRange):
When pausing on the variable assignment inside for..of and for..in don't just
highlight &quot;var foo&quot; but include the right hand side &quot;var foo in ...&quot; or
&quot;var foo of ...&quot;.

LayoutTests:

* inspector/debugger/stepping/stepping-control-flow-expected.txt:
* inspector/debugger/stepping/stepping-control-flow.html:
Add new tests for stepping through conditional expressions with constants,
logical operations, binary operations, and unary negations.

* inspector/debugger/stepping/stepping-loops-expected.txt:
* inspector/debugger/stepping/stepping-loops.html:
Update tests for changes in stepping behavior in for loops.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsinspectordebuggersteppingsteppingcontrolflowexpectedtxt">trunk/LayoutTests/inspector/debugger/stepping/stepping-control-flow-expected.txt</a></li>
<li><a href="#trunkLayoutTestsinspectordebuggersteppingsteppingcontrolflowhtml">trunk/LayoutTests/inspector/debugger/stepping/stepping-control-flow.html</a></li>
<li><a href="#trunkLayoutTestsinspectordebuggersteppingsteppingloopsexpectedtxt">trunk/LayoutTests/inspector/debugger/stepping/stepping-loops-expected.txt</a></li>
<li><a href="#trunkLayoutTestsinspectordebuggersteppingsteppingloopshtml">trunk/LayoutTests/inspector/debugger/stepping/stepping-loops.html</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp">trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorh">trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerNodesCodegencpp">trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserASTBuilderh">trunk/Source/JavaScriptCore/parser/ASTBuilder.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserNodesh">trunk/Source/JavaScriptCore/parser/Nodes.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserParsercpp">trunk/Source/JavaScriptCore/parser/Parser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserSyntaxCheckerh">trunk/Source/JavaScriptCore/parser/SyntaxChecker.h</a></li>
<li><a href="#trunkSourceWebInspectorUIChangeLog">trunk/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsSourceCodeTextEditorjs">trunk/Source/WebInspectorUI/UserInterface/Views/SourceCodeTextEditor.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (207227 => 207228)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-10-12 18:43:19 UTC (rev 207227)
+++ trunk/LayoutTests/ChangeLog        2016-10-12 18:47:48 UTC (rev 207228)
</span><span class="lines">@@ -1,3 +1,19 @@
</span><ins>+2016-10-12  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
+
+        Emit DebugHooks uniformly with pause locations instead of having separate pause locations and op_debug emits
+        https://bugs.webkit.org/show_bug.cgi?id=162809
+
+        Reviewed by Geoffrey Garen.
+
+        * inspector/debugger/stepping/stepping-control-flow-expected.txt:
+        * inspector/debugger/stepping/stepping-control-flow.html:
+        Add new tests for stepping through conditional expressions with constants,
+        logical operations, binary operations, and unary negations.
+
+        * inspector/debugger/stepping/stepping-loops-expected.txt:
+        * inspector/debugger/stepping/stepping-loops.html:
+        Update tests for changes in stepping behavior in for loops.
+
</ins><span class="cx"> 2016-10-12  Carlos Alberto Lopez Perez  &lt;clopez@igalia.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [GTK] Tests that fail since the new URLParser has been enabled on r207162.
</span></span></pre></div>
<a id="trunkLayoutTestsinspectordebuggersteppingsteppingcontrolflowexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/inspector/debugger/stepping/stepping-control-flow-expected.txt (207227 => 207228)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/debugger/stepping/stepping-control-flow-expected.txt        2016-10-12 18:43:19 UTC (rev 207227)
+++ trunk/LayoutTests/inspector/debugger/stepping/stepping-control-flow-expected.txt        2016-10-12 18:47:48 UTC (rev 207228)
</span><span class="lines">@@ -7,13 +7,13 @@
</span><span class="cx"> STEPS: over, over, over, over, resume
</span><span class="cx"> PAUSED (debugger-statement)
</span><span class="cx"> PAUSE AT entryIfSingleStatement:16:5
</span><del>-     12    }
</del><ins>+     12    
</ins><span class="cx">      13    
</span><span class="cx">      14    function entryIfSingleStatement() {
</span><span class="cx">  -&gt;  15        |debugger;
</span><del>-     16        if (true)
</del><ins>+     16        if (truthy)
</ins><span class="cx">      17            a();
</span><del>-     18        if (false)
</del><ins>+     18        if (falsey)
</ins><span class="cx"> 
</span><span class="cx"> ACTION: step-over
</span><span class="cx"> PAUSE AT entryIfSingleStatement:17:9
</span><span class="lines">@@ -20,9 +20,9 @@
</span><span class="cx">      13    
</span><span class="cx">      14    function entryIfSingleStatement() {
</span><span class="cx">      15        debugger;
</span><del>- -&gt;  16        if (|true)
</del><ins>+ -&gt;  16        if (|truthy)
</ins><span class="cx">      17            a();
</span><del>-     18        if (false)
</del><ins>+     18        if (falsey)
</ins><span class="cx">      19            a();
</span><span class="cx"> 
</span><span class="cx"> ACTION: step-over
</span><span class="lines">@@ -29,9 +29,9 @@
</span><span class="cx"> PAUSE AT entryIfSingleStatement:18:9
</span><span class="cx">      14    function entryIfSingleStatement() {
</span><span class="cx">      15        debugger;
</span><del>-     16        if (true)
</del><ins>+     16        if (truthy)
</ins><span class="cx">  -&gt;  17            |a();
</span><del>-     18        if (false)
</del><ins>+     18        if (falsey)
</ins><span class="cx">      19            a();
</span><span class="cx">      20    }
</span><span class="cx"> 
</span><span class="lines">@@ -38,9 +38,9 @@
</span><span class="cx"> ACTION: step-over
</span><span class="cx"> PAUSE AT entryIfSingleStatement:19:9
</span><span class="cx">      15        debugger;
</span><del>-     16        if (true)
</del><ins>+     16        if (truthy)
</ins><span class="cx">      17            a();
</span><del>- -&gt;  18        if (|false)
</del><ins>+ -&gt;  18        if (|falsey)
</ins><span class="cx">      19            a();
</span><span class="cx">      20    }
</span><span class="cx">      21    
</span><span class="lines">@@ -48,7 +48,7 @@
</span><span class="cx"> ACTION: step-over
</span><span class="cx"> PAUSE AT entryIfSingleStatement:21:2
</span><span class="cx">      17            a();
</span><del>-     18        if (false)
</del><ins>+     18        if (falsey)
</ins><span class="cx">      19            a();
</span><span class="cx">  -&gt;  20    }|
</span><span class="cx">      21    
</span><span class="lines">@@ -68,7 +68,7 @@
</span><span class="cx">      21    
</span><span class="cx">      22    function entryIfMultiStatement() {
</span><span class="cx">  -&gt;  23        |debugger;
</span><del>-     24        if (true) {
</del><ins>+     24        if (truthy) {
</ins><span class="cx">      25            a();
</span><span class="cx">      26            a();
</span><span class="cx"> 
</span><span class="lines">@@ -77,7 +77,7 @@
</span><span class="cx">      21    
</span><span class="cx">      22    function entryIfMultiStatement() {
</span><span class="cx">      23        debugger;
</span><del>- -&gt;  24        if (|true) {
</del><ins>+ -&gt;  24        if (|truthy) {
</ins><span class="cx">      25            a();
</span><span class="cx">      26            a();
</span><span class="cx">      27        }
</span><span class="lines">@@ -86,20 +86,20 @@
</span><span class="cx"> PAUSE AT entryIfMultiStatement:26:9
</span><span class="cx">      22    function entryIfMultiStatement() {
</span><span class="cx">      23        debugger;
</span><del>-     24        if (true) {
</del><ins>+     24        if (truthy) {
</ins><span class="cx">  -&gt;  25            |a();
</span><span class="cx">      26            a();
</span><span class="cx">      27        }
</span><del>-     28        if (false) {
</del><ins>+     28        if (falsey) {
</ins><span class="cx"> 
</span><span class="cx"> ACTION: step-over
</span><span class="cx"> PAUSE AT entryIfMultiStatement:27:9
</span><span class="cx">      23        debugger;
</span><del>-     24        if (true) {
</del><ins>+     24        if (truthy) {
</ins><span class="cx">      25            a();
</span><span class="cx">  -&gt;  26            |a();
</span><span class="cx">      27        }
</span><del>-     28        if (false) {
</del><ins>+     28        if (falsey) {
</ins><span class="cx">      29            a();
</span><span class="cx"> 
</span><span class="cx"> ACTION: step-over
</span><span class="lines">@@ -107,7 +107,7 @@
</span><span class="cx">      25            a();
</span><span class="cx">      26            a();
</span><span class="cx">      27        }
</span><del>- -&gt;  28        if (|false) {
</del><ins>+ -&gt;  28        if (|falsey) {
</ins><span class="cx">      29            a();
</span><span class="cx">      30            a();
</span><span class="cx">      31        }
</span><span class="lines">@@ -135,7 +135,7 @@
</span><span class="cx">      33    
</span><span class="cx">      34    function entryIfElse() {
</span><span class="cx">  -&gt;  35        |debugger;
</span><del>-     36        if (true)
</del><ins>+     36        if (truthy)
</ins><span class="cx">      37            a();
</span><span class="cx">      38        else
</span><span class="cx"> 
</span><span class="lines">@@ -144,7 +144,7 @@
</span><span class="cx">      33    
</span><span class="cx">      34    function entryIfElse() {
</span><span class="cx">      35        debugger;
</span><del>- -&gt;  36        if (|true)
</del><ins>+ -&gt;  36        if (|truthy)
</ins><span class="cx">      37            a();
</span><span class="cx">      38        else
</span><span class="cx">      39            a();
</span><span class="lines">@@ -153,11 +153,11 @@
</span><span class="cx"> PAUSE AT entryIfElse:38:9
</span><span class="cx">      34    function entryIfElse() {
</span><span class="cx">      35        debugger;
</span><del>-     36        if (true)
</del><ins>+     36        if (truthy)
</ins><span class="cx">  -&gt;  37            |a();
</span><span class="cx">      38        else
</span><span class="cx">      39            a();
</span><del>-     40        if (false)
</del><ins>+     40        if (falsey)
</ins><span class="cx"> 
</span><span class="cx"> ACTION: step-over
</span><span class="cx"> PAUSE AT entryIfElse:41:9
</span><span class="lines">@@ -164,7 +164,7 @@
</span><span class="cx">      37            a();
</span><span class="cx">      38        else
</span><span class="cx">      39            a();
</span><del>- -&gt;  40        if (|false)
</del><ins>+ -&gt;  40        if (|falsey)
</ins><span class="cx">      41            a();
</span><span class="cx">      42        else
</span><span class="cx">      43            a();
</span><span class="lines">@@ -171,7 +171,7 @@
</span><span class="cx"> 
</span><span class="cx"> ACTION: step-over
</span><span class="cx"> PAUSE AT entryIfElse:44:9
</span><del>-     40        if (false)
</del><ins>+     40        if (falsey)
</ins><span class="cx">      41            a();
</span><span class="cx">      42        else
</span><span class="cx">  -&gt;  43            |a();
</span><span class="lines">@@ -202,9 +202,9 @@
</span><span class="cx">      45    
</span><span class="cx">      46    function entryIfElseChain() {
</span><span class="cx">  -&gt;  47        |debugger;
</span><del>-     48        if (false)
</del><ins>+     48        if (falsey)
</ins><span class="cx">      49            a();
</span><del>-     50        else if (true)
</del><ins>+     50        else if (truthy)
</ins><span class="cx"> 
</span><span class="cx"> ACTION: step-over
</span><span class="cx"> PAUSE AT entryIfElseChain:49:9
</span><span class="lines">@@ -211,17 +211,17 @@
</span><span class="cx">      45    
</span><span class="cx">      46    function entryIfElseChain() {
</span><span class="cx">      47        debugger;
</span><del>- -&gt;  48        if (|false)
</del><ins>+ -&gt;  48        if (|falsey)
</ins><span class="cx">      49            a();
</span><del>-     50        else if (true)
</del><ins>+     50        else if (truthy)
</ins><span class="cx">      51            a();
</span><span class="cx"> 
</span><span class="cx"> ACTION: step-over
</span><span class="cx"> PAUSE AT entryIfElseChain:51:14
</span><span class="cx">      47        debugger;
</span><del>-     48        if (false)
</del><ins>+     48        if (falsey)
</ins><span class="cx">      49            a();
</span><del>- -&gt;  50        else if (|true)
</del><ins>+ -&gt;  50        else if (|truthy)
</ins><span class="cx">      51            a();
</span><span class="cx">      52        else
</span><span class="cx">      53            a();
</span><span class="lines">@@ -228,9 +228,9 @@
</span><span class="cx"> 
</span><span class="cx"> ACTION: step-over
</span><span class="cx"> PAUSE AT entryIfElseChain:52:9
</span><del>-     48        if (false)
</del><ins>+     48        if (falsey)
</ins><span class="cx">      49            a();
</span><del>-     50        else if (true)
</del><ins>+     50        else if (truthy)
</ins><span class="cx">  -&gt;  51            |a();
</span><span class="cx">      52        else
</span><span class="cx">      53            a();
</span><span class="lines">@@ -241,17 +241,17 @@
</span><span class="cx">      52        else
</span><span class="cx">      53            a();
</span><span class="cx">      54    
</span><del>- -&gt;  55        if (|false)
</del><ins>+ -&gt;  55        if (|falsey)
</ins><span class="cx">      56            a();
</span><del>-     57        else if (false)
</del><ins>+     57        else if (falsey)
</ins><span class="cx">      58            a();
</span><span class="cx"> 
</span><span class="cx"> ACTION: step-over
</span><span class="cx"> PAUSE AT entryIfElseChain:58:14
</span><span class="cx">      54    
</span><del>-     55        if (false)
</del><ins>+     55        if (falsey)
</ins><span class="cx">      56            a();
</span><del>- -&gt;  57        else if (|false)
</del><ins>+ -&gt;  57        else if (|falsey)
</ins><span class="cx">      58            a();
</span><span class="cx">      59        else
</span><span class="cx">      60            a();
</span><span class="lines">@@ -258,7 +258,7 @@
</span><span class="cx"> 
</span><span class="cx"> ACTION: step-over
</span><span class="cx"> PAUSE AT entryIfElseChain:61:9
</span><del>-     57        else if (false)
</del><ins>+     57        else if (falsey)
</ins><span class="cx">      58            a();
</span><span class="cx">      59        else
</span><span class="cx">  -&gt;  60            |a();
</span><span class="lines">@@ -321,7 +321,7 @@
</span><span class="cx">  -&gt;  67    }|
</span><span class="cx">      68    
</span><span class="cx">      69    function entryTernary() {
</span><del>-     70        let t = () =&gt; true;
</del><ins>+     70        let t = () =&gt; truthy;
</ins><span class="cx"> 
</span><span class="cx"> ACTION: resume
</span><span class="cx"> RESUMED
</span><span class="lines">@@ -351,14 +351,14 @@
</span><span class="cx">      68    
</span><span class="cx"> 
</span><span class="cx"> ACTION: step-in
</span><del>-PAUSE AT a:8:5
-      4    &lt;script src=&quot;../resources/log-pause-location.js&quot;&gt;&lt;/script&gt;
-      5    &lt;script&gt;
-      6    function a() {
- -&gt;   7        |return 1;
-      8    }
-      9    
-     10    function b() {
</del><ins>+PAUSE AT a:11:16
+      7    var value = 1;
+      8    var truthy = true;
+      9    var falsey = false;
+ -&gt;  10    function a() { |return value; }
+     11    function b() { return value; }
+     12    
+     13    
</ins><span class="cx"> 
</span><span class="cx"> ACTION: step-out
</span><span class="cx"> PAUSE AT entryIfWithCall:66:16
</span><span class="lines">@@ -371,14 +371,14 @@
</span><span class="cx">      68    
</span><span class="cx"> 
</span><span class="cx"> ACTION: step-in
</span><del>-PAUSE AT a:8:5
-      4    &lt;script src=&quot;../resources/log-pause-location.js&quot;&gt;&lt;/script&gt;
-      5    &lt;script&gt;
-      6    function a() {
- -&gt;   7        |return 1;
-      8    }
-      9    
-     10    function b() {
</del><ins>+PAUSE AT a:11:16
+      7    var value = 1;
+      8    var truthy = true;
+      9    var falsey = false;
+ -&gt;  10    function a() { |return value; }
+     11    function b() { return value; }
+     12    
+     13    
</ins><span class="cx"> 
</span><span class="cx"> ACTION: step-out
</span><span class="cx"> PAUSE AT entryIfWithCall:67:9
</span><span class="lines">@@ -398,7 +398,7 @@
</span><span class="cx">  -&gt;  67    }|
</span><span class="cx">      68    
</span><span class="cx">      69    function entryTernary() {
</span><del>-     70        let t = () =&gt; true;
</del><ins>+     70        let t = () =&gt; truthy;
</ins><span class="cx"> 
</span><span class="cx"> ACTION: resume
</span><span class="cx"> RESUMED
</span><span class="lines">@@ -410,8 +410,8 @@
</span><span class="cx"> PAUSED (debugger-statement)
</span><span class="cx"> PAUSE AT entryTernary:73:5
</span><span class="cx">      69    function entryTernary() {
</span><del>-     70        let t = () =&gt; true;
-     71        let f = () =&gt; false;
</del><ins>+     70        let t = () =&gt; truthy;
+     71        let f = () =&gt; falsey;
</ins><span class="cx">  -&gt;  72        |debugger;
</span><span class="cx">      73        let x = t() ? a() : b();
</span><span class="cx">      74        let y = f() ? a() : b();
</span><span class="lines">@@ -419,8 +419,8 @@
</span><span class="cx"> 
</span><span class="cx"> ACTION: step-over
</span><span class="cx"> PAUSE AT entryTernary:74:5
</span><del>-     70        let t = () =&gt; true;
-     71        let f = () =&gt; false;
</del><ins>+     70        let t = () =&gt; truthy;
+     71        let f = () =&gt; falsey;
</ins><span class="cx">      72        debugger;
</span><span class="cx">  -&gt;  73        |let x = t() ? a() : b();
</span><span class="cx">      74        let y = f() ? a() : b();
</span><span class="lines">@@ -429,13 +429,13 @@
</span><span class="cx"> 
</span><span class="cx"> ACTION: step-over
</span><span class="cx"> PAUSE AT entryTernary:75:5
</span><del>-     71        let f = () =&gt; false;
</del><ins>+     71        let f = () =&gt; falsey;
</ins><span class="cx">      72        debugger;
</span><span class="cx">      73        let x = t() ? a() : b();
</span><span class="cx">  -&gt;  74        |let y = f() ? a() : b();
</span><span class="cx">      75    }
</span><span class="cx">      76    
</span><del>-     77    // ---------
</del><ins>+     77    function entryIfConstantBranch() {
</ins><span class="cx"> 
</span><span class="cx"> ACTION: step-over
</span><span class="cx"> PAUSE AT entryTernary:76:2
</span><span class="lines">@@ -444,8 +444,8 @@
</span><span class="cx">      74        let y = f() ? a() : b();
</span><span class="cx">  -&gt;  75    }|
</span><span class="cx">      76    
</span><del>-     77    // ---------
-     78    
</del><ins>+     77    function entryIfConstantBranch() {
+     78        debugger;
</ins><span class="cx"> 
</span><span class="cx"> ACTION: resume
</span><span class="cx"> RESUMED
</span><span class="lines">@@ -457,8 +457,8 @@
</span><span class="cx"> PAUSED (debugger-statement)
</span><span class="cx"> PAUSE AT entryTernary:73:5
</span><span class="cx">      69    function entryTernary() {
</span><del>-     70        let t = () =&gt; true;
-     71        let f = () =&gt; false;
</del><ins>+     70        let t = () =&gt; truthy;
+     71        let f = () =&gt; falsey;
</ins><span class="cx">  -&gt;  72        |debugger;
</span><span class="cx">      73        let x = t() ? a() : b();
</span><span class="cx">      74        let y = f() ? a() : b();
</span><span class="lines">@@ -466,8 +466,8 @@
</span><span class="cx"> 
</span><span class="cx"> ACTION: step-over
</span><span class="cx"> PAUSE AT entryTernary:74:5
</span><del>-     70        let t = () =&gt; true;
-     71        let f = () =&gt; false;
</del><ins>+     70        let t = () =&gt; truthy;
+     71        let f = () =&gt; falsey;
</ins><span class="cx">      72        debugger;
</span><span class="cx">  -&gt;  73        |let x = t() ? a() : b();
</span><span class="cx">      74        let y = f() ? a() : b();
</span><span class="lines">@@ -479,15 +479,15 @@
</span><span class="cx">      67    }
</span><span class="cx">      68    
</span><span class="cx">      69    function entryTernary() {
</span><del>- -&gt;  70        let t = () =&gt; |true;
-     71        let f = () =&gt; false;
</del><ins>+ -&gt;  70        let t = () =&gt; |truthy;
+     71        let f = () =&gt; falsey;
</ins><span class="cx">      72        debugger;
</span><span class="cx">      73        let x = t() ? a() : b();
</span><span class="cx"> 
</span><span class="cx"> ACTION: step-out
</span><span class="cx"> PAUSE AT entryTernary:74:19
</span><del>-     70        let t = () =&gt; true;
-     71        let f = () =&gt; false;
</del><ins>+     70        let t = () =&gt; truthy;
+     71        let f = () =&gt; falsey;
</ins><span class="cx">      72        debugger;
</span><span class="cx">  -&gt;  73        let x = t() ? |a() : b();
</span><span class="cx">      74        let y = f() ? a() : b();
</span><span class="lines">@@ -495,31 +495,31 @@
</span><span class="cx">      76    
</span><span class="cx"> 
</span><span class="cx"> ACTION: step-in
</span><del>-PAUSE AT a:8:5
-      4    &lt;script src=&quot;../resources/log-pause-location.js&quot;&gt;&lt;/script&gt;
-      5    &lt;script&gt;
-      6    function a() {
- -&gt;   7        |return 1;
-      8    }
-      9    
-     10    function b() {
</del><ins>+PAUSE AT a:11:16
+      7    var value = 1;
+      8    var truthy = true;
+      9    var falsey = false;
+ -&gt;  10    function a() { |return value; }
+     11    function b() { return value; }
+     12    
+     13    
</ins><span class="cx"> 
</span><span class="cx"> ACTION: step-out
</span><span class="cx"> PAUSE AT entryTernary:75:5
</span><del>-     71        let f = () =&gt; false;
</del><ins>+     71        let f = () =&gt; falsey;
</ins><span class="cx">      72        debugger;
</span><span class="cx">      73        let x = t() ? a() : b();
</span><span class="cx">  -&gt;  74        |let y = f() ? a() : b();
</span><span class="cx">      75    }
</span><span class="cx">      76    
</span><del>-     77    // ---------
</del><ins>+     77    function entryIfConstantBranch() {
</ins><span class="cx"> 
</span><span class="cx"> ACTION: step-in
</span><span class="cx"> PAUSE AT f:72:19
</span><span class="cx">      68    
</span><span class="cx">      69    function entryTernary() {
</span><del>-     70        let t = () =&gt; true;
- -&gt;  71        let f = () =&gt; |false;
</del><ins>+     70        let t = () =&gt; truthy;
+ -&gt;  71        let f = () =&gt; |falsey;
</ins><span class="cx">      72        debugger;
</span><span class="cx">      73        let x = t() ? a() : b();
</span><span class="cx">      74        let y = f() ? a() : b();
</span><span class="lines">@@ -526,21 +526,21 @@
</span><span class="cx"> 
</span><span class="cx"> ACTION: step-out
</span><span class="cx"> PAUSE AT entryTernary:75:25
</span><del>-     71        let f = () =&gt; false;
</del><ins>+     71        let f = () =&gt; falsey;
</ins><span class="cx">      72        debugger;
</span><span class="cx">      73        let x = t() ? a() : b();
</span><span class="cx">  -&gt;  74        let y = f() ? a() : |b();
</span><span class="cx">      75    }
</span><span class="cx">      76    
</span><del>-     77    // ---------
</del><ins>+     77    function entryIfConstantBranch() {
</ins><span class="cx"> 
</span><span class="cx"> ACTION: step-in
</span><del>-PAUSE AT b:12:5
-      8    }
-      9    
-     10    function b() {
- -&gt;  11        |return 2;
-     12    }
</del><ins>+PAUSE AT b:12:16
+      8    var truthy = true;
+      9    var falsey = false;
+     10    function a() { return value; }
+ -&gt;  11    function b() { |return value; }
+     12    
</ins><span class="cx">      13    
</span><span class="cx">      14    function entryIfSingleStatement() {
</span><span class="cx"> 
</span><span class="lines">@@ -551,10 +551,278 @@
</span><span class="cx">      74        let y = f() ? a() : b();
</span><span class="cx">  -&gt;  75    }|
</span><span class="cx">      76    
</span><del>-     77    // ---------
-     78    
</del><ins>+     77    function entryIfConstantBranch() {
+     78        debugger;
</ins><span class="cx"> 
</span><span class="cx"> ACTION: resume
</span><span class="cx"> RESUMED
</span><span class="cx"> PASS: Should have used all steps.
</span><span class="cx"> 
</span><ins>+-- Running test case: Debugger.stepping.ConstantBranch
+EXPRESSION: setTimeout(entryIfConstantBranch)
+STEPS: over, over, over, over, over, over, resume
+PAUSED (debugger-statement)
+PAUSE AT entryIfConstantBranch:79:5
+     75    }
+     76    
+     77    function entryIfConstantBranch() {
+ -&gt;  78        |debugger;
+     79        if (true)
+     80            a();
+     81        if (false)
+
+ACTION: step-over
+PAUSE AT entryIfConstantBranch:80:9
+     76    
+     77    function entryIfConstantBranch() {
+     78        debugger;
+ -&gt;  79        if (|true)
+     80            a();
+     81        if (false)
+     82            a();
+
+ACTION: step-over
+PAUSE AT entryIfConstantBranch:81:9
+     77    function entryIfConstantBranch() {
+     78        debugger;
+     79        if (true)
+ -&gt;  80            |a();
+     81        if (false)
+     82            a();
+     83        if (0)
+
+ACTION: step-over
+PAUSE AT entryIfConstantBranch:82:9
+     78        debugger;
+     79        if (true)
+     80            a();
+ -&gt;  81        if (|false)
+     82            a();
+     83        if (0)
+     84            a();
+
+ACTION: step-over
+PAUSE AT entryIfConstantBranch:84:9
+     80            a();
+     81        if (false)
+     82            a();
+ -&gt;  83        if (|0)
+     84            a();
+     85        if (null)
+     86            a();
+
+ACTION: step-over
+PAUSE AT entryIfConstantBranch:86:9
+     82            a();
+     83        if (0)
+     84            a();
+ -&gt;  85        if (|null)
+     86            a();
+     87    }
+     88    
+
+ACTION: step-over
+PAUSE AT entryIfConstantBranch:88:2
+     84            a();
+     85        if (null)
+     86            a();
+ -&gt;  87    }|
+     88    
+     89    function entryIfWithLogicalOperation() {
+     90        debugger;
+
+ACTION: resume
+RESUMED
+PASS: Should have used all steps.
+
+-- Running test case: Debugger.stepping.IfWithLogicalOperation
+EXPRESSION: setTimeout(entryIfWithLogicalOperation)
+STEPS: over, in, out, in, out, over, resume
+PAUSED (debugger-statement)
+PAUSE AT entryIfWithLogicalOperation:91:5
+     87    }
+     88    
+     89    function entryIfWithLogicalOperation() {
+ -&gt;  90        |debugger;
+     91        if (true &amp;&amp; a() &amp;&amp; a())
+     92            b();
+     93    }
+
+ACTION: step-over
+PAUSE AT entryIfWithLogicalOperation:92:9
+     88    
+     89    function entryIfWithLogicalOperation() {
+     90        debugger;
+ -&gt;  91        if (|true &amp;&amp; a() &amp;&amp; a())
+     92            b();
+     93    }
+     94    
+
+ACTION: step-in
+PAUSE AT a:11:16
+      7    var value = 1;
+      8    var truthy = true;
+      9    var falsey = false;
+ -&gt;  10    function a() { |return value; }
+     11    function b() { return value; }
+     12    
+     13    
+
+ACTION: step-out
+PAUSE AT entryIfWithLogicalOperation:92:24
+     88    
+     89    function entryIfWithLogicalOperation() {
+     90        debugger;
+ -&gt;  91        if (true &amp;&amp; a() &amp;&amp; |a())
+     92            b();
+     93    }
+     94    
+
+ACTION: step-in
+PAUSE AT a:11:16
+      7    var value = 1;
+      8    var truthy = true;
+      9    var falsey = false;
+ -&gt;  10    function a() { |return value; }
+     11    function b() { return value; }
+     12    
+     13    
+
+ACTION: step-out
+PAUSE AT entryIfWithLogicalOperation:93:9
+     89    function entryIfWithLogicalOperation() {
+     90        debugger;
+     91        if (true &amp;&amp; a() &amp;&amp; a())
+ -&gt;  92            |b();
+     93    }
+     94    
+     95    function entryIfWithBinaryOperation() {
+
+ACTION: step-over
+PAUSE AT entryIfWithLogicalOperation:94:2
+     90        debugger;
+     91        if (true &amp;&amp; a() &amp;&amp; a())
+     92            b();
+ -&gt;  93    }|
+     94    
+     95    function entryIfWithBinaryOperation() {
+     96        let i = a();
+
+ACTION: resume
+RESUMED
+PASS: Should have used all steps.
+
+-- Running test case: Debugger.stepping.IfWithBinaryOperation
+EXPRESSION: setTimeout(entryIfWithBinaryOperation)
+STEPS: over, in, over, resume
+PAUSED (debugger-statement)
+PAUSE AT entryIfWithBinaryOperation:98:5
+     94    
+     95    function entryIfWithBinaryOperation() {
+     96        let i = a();
+ -&gt;  97        |debugger;
+     98        if (i &lt; 2)
+     99            b();
+    100    }
+
+ACTION: step-over
+PAUSE AT entryIfWithBinaryOperation:99:9
+     95    function entryIfWithBinaryOperation() {
+     96        let i = a();
+     97        debugger;
+ -&gt;  98        if (|i &lt; 2)
+     99            b();
+    100    }
+    101    
+
+ACTION: step-in
+PAUSE AT entryIfWithBinaryOperation:100:9
+     96        let i = a();
+     97        debugger;
+     98        if (i &lt; 2)
+ -&gt;  99            |b();
+    100    }
+    101    
+    102    function entryIfWithNotOperation() {
+
+ACTION: step-over
+PAUSE AT entryIfWithBinaryOperation:101:2
+     97        debugger;
+     98        if (i &lt; 2)
+     99            b();
+ -&gt; 100    }|
+    101    
+    102    function entryIfWithNotOperation() {
+    103        debugger;
+
+ACTION: resume
+RESUMED
+PASS: Should have used all steps.
+
+-- Running test case: Debugger.stepping.IfWithNotOperation
+EXPRESSION: setTimeout(entryIfWithNotOperation)
+STEPS: over, in, over, in, over, resume
+PAUSED (debugger-statement)
+PAUSE AT entryIfWithNotOperation:104:5
+    100    }
+    101    
+    102    function entryIfWithNotOperation() {
+ -&gt; 103        |debugger;
+    104        if (!false)
+    105            a();
+    106        if (!!true)
+
+ACTION: step-over
+PAUSE AT entryIfWithNotOperation:105:9
+    101    
+    102    function entryIfWithNotOperation() {
+    103        debugger;
+ -&gt; 104        if (|!false)
+    105            a();
+    106        if (!!true)
+    107            a();
+
+ACTION: step-in
+PAUSE AT entryIfWithNotOperation:106:9
+    102    function entryIfWithNotOperation() {
+    103        debugger;
+    104        if (!false)
+ -&gt; 105            |a();
+    106        if (!!true)
+    107            a();
+    108    }
+
+ACTION: step-over
+PAUSE AT entryIfWithNotOperation:107:9
+    103        debugger;
+    104        if (!false)
+    105            a();
+ -&gt; 106        if (|!!true)
+    107            a();
+    108    }
+    109    
+
+ACTION: step-in
+PAUSE AT entryIfWithNotOperation:108:9
+    104        if (!false)
+    105            a();
+    106        if (!!true)
+ -&gt; 107            |a();
+    108    }
+    109    
+    110    // ---------
+
+ACTION: step-over
+PAUSE AT entryIfWithNotOperation:109:2
+    105            a();
+    106        if (!!true)
+    107            a();
+ -&gt; 108    }|
+    109    
+    110    // ---------
+    111    
+
+ACTION: resume
+RESUMED
+PASS: Should have used all steps.
+
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectordebuggersteppingsteppingcontrolflowhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/inspector/debugger/stepping/stepping-control-flow.html (207227 => 207228)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/debugger/stepping/stepping-control-flow.html        2016-10-12 18:43:19 UTC (rev 207227)
+++ trunk/LayoutTests/inspector/debugger/stepping/stepping-control-flow.html        2016-10-12 18:47:48 UTC (rev 207228)
</span><span class="lines">@@ -4,29 +4,29 @@
</span><span class="cx"> &lt;script src=&quot;../../../http/tests/inspector/resources/inspector-test.js&quot;&gt;&lt;/script&gt;
</span><span class="cx"> &lt;script src=&quot;../resources/log-pause-location.js&quot;&gt;&lt;/script&gt;
</span><span class="cx"> &lt;script&gt;
</span><del>-function a() {
-    return 1;
-}
</del><ins>+// We may want to allow constants to eliminate branches. Use vars for existing tests and have constant specific tests.
+var value = 1;
+var truthy = true;
+var falsey = false;
+function a() { return value; }
+function b() { return value; }
</ins><span class="cx"> 
</span><del>-function b() {
-    return 2;
-}
</del><span class="cx"> 
</span><span class="cx"> function entryIfSingleStatement() {
</span><span class="cx">     debugger;
</span><del>-    if (true)
</del><ins>+    if (truthy)
</ins><span class="cx">         a();
</span><del>-    if (false)
</del><ins>+    if (falsey)
</ins><span class="cx">         a();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> function entryIfMultiStatement() {
</span><span class="cx">     debugger;
</span><del>-    if (true) {
</del><ins>+    if (truthy) {
</ins><span class="cx">         a();
</span><span class="cx">         a();
</span><span class="cx">     }
</span><del>-    if (false) {
</del><ins>+    if (falsey) {
</ins><span class="cx">         a();
</span><span class="cx">         a();
</span><span class="cx">     }
</span><span class="lines">@@ -34,11 +34,11 @@
</span><span class="cx"> 
</span><span class="cx"> function entryIfElse() {
</span><span class="cx">     debugger;
</span><del>-    if (true)
</del><ins>+    if (truthy)
</ins><span class="cx">         a();
</span><span class="cx">     else
</span><span class="cx">         a();
</span><del>-    if (false)
</del><ins>+    if (falsey)
</ins><span class="cx">         a();
</span><span class="cx">     else
</span><span class="cx">         a();
</span><span class="lines">@@ -46,16 +46,16 @@
</span><span class="cx"> 
</span><span class="cx"> function entryIfElseChain() {
</span><span class="cx">     debugger;
</span><del>-    if (false)
</del><ins>+    if (falsey)
</ins><span class="cx">         a();
</span><del>-    else if (true)
</del><ins>+    else if (truthy)
</ins><span class="cx">         a();
</span><span class="cx">     else
</span><span class="cx">         a();
</span><span class="cx"> 
</span><del>-    if (false)
</del><ins>+    if (falsey)
</ins><span class="cx">         a();
</span><del>-    else if (false)
</del><ins>+    else if (falsey)
</ins><span class="cx">         a();
</span><span class="cx">     else
</span><span class="cx">         a();
</span><span class="lines">@@ -68,13 +68,46 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> function entryTernary() {
</span><del>-    let t = () =&gt; true;
-    let f = () =&gt; false;
</del><ins>+    let t = () =&gt; truthy;
+    let f = () =&gt; falsey;
</ins><span class="cx">     debugger;
</span><span class="cx">     let x = t() ? a() : b();
</span><span class="cx">     let y = f() ? a() : b();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+function entryIfConstantBranch() {
+    debugger;
+    if (true)
+        a();
+    if (false)
+        a();
+    if (0)
+        a();
+    if (null)
+        a();
+}
+
+function entryIfWithLogicalOperation() {
+    debugger;
+    if (true &amp;&amp; a() &amp;&amp; a())
+        b();
+}
+
+function entryIfWithBinaryOperation() {
+    let i = a();
+    debugger;
+    if (i &lt; 2)
+        b();
+}
+
+function entryIfWithNotOperation() {
+    debugger;
+    if (!false)
+        a();
+    if (!!true)
+        a();
+}
+
</ins><span class="cx"> // ---------
</span><span class="cx"> 
</span><span class="cx"> function test()
</span><span class="lines">@@ -197,6 +230,62 @@
</span><span class="cx">         ]
</span><span class="cx">     });
</span><span class="cx"> 
</span><ins>+    addSteppingTestCase({
+        name: &quot;Debugger.stepping.ConstantBranch&quot;,
+        description: &quot;Should pause for constant branches.&quot;,
+        expression: &quot;setTimeout(entryIfConstantBranch)&quot;,
+        steps: [
+            &quot;over&quot;,
+                &quot;over&quot;, // (true)
+                &quot;over&quot;, // a()
+                &quot;over&quot;, // (false)
+                &quot;over&quot;, // (0)
+                &quot;over&quot;, // (null)
+            &quot;resume&quot;,
+        ]
+    });
+
+    addSteppingTestCase({
+        name: &quot;Debugger.stepping.IfWithLogicalOperation&quot;,
+        description: &quot;Should always pause for a condition with logical operations.&quot;,
+        expression: &quot;setTimeout(entryIfWithLogicalOperation)&quot;,
+        steps: [
+            &quot;over&quot;,
+                &quot;in&quot;,   // into a()
+                &quot;out&quot;,  // out of a() - before a()
+                &quot;in&quot;,   // into a()
+                &quot;out&quot;,  // out of a() - before b()
+                &quot;over&quot;, // b() - leaving entry
+            &quot;resume&quot;,
+        ]
+    });
+
+    addSteppingTestCase({
+        name: &quot;Debugger.stepping.IfWithBinaryOperation&quot;,
+        description: &quot;Should always pause for a condition with logical operations.&quot;,
+        expression: &quot;setTimeout(entryIfWithBinaryOperation)&quot;,
+        steps: [
+            &quot;over&quot;,
+                &quot;in&quot;,    // i &lt; 2 [true]
+                &quot;over&quot;,  // over b() - leaving entry
+            &quot;resume&quot;,
+        ]
+    });
+
+    addSteppingTestCase({
+        name: &quot;Debugger.stepping.IfWithNotOperation&quot;,
+        description: &quot;Should always pause for a condition that is a not operation.&quot;,
+        expression: &quot;setTimeout(entryIfWithNotOperation)&quot;,
+        steps: [
+            &quot;over&quot;,
+                &quot;in&quot;,   // !false
+                &quot;over&quot;, // a()
+                &quot;in&quot;,   // !!truth
+                &quot;over&quot;, // a() - leaving entry
+            &quot;resume&quot;,
+        ]
+    });
+
</ins><span class="cx">     loadMainPageContent().then(() =&gt; {
</span><span class="cx">         suite.runTestCasesAndFinish();
</span><span class="cx">     });
</span></span></pre></div>
<a id="trunkLayoutTestsinspectordebuggersteppingsteppingloopsexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/inspector/debugger/stepping/stepping-loops-expected.txt (207227 => 207228)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/debugger/stepping/stepping-loops-expected.txt        2016-10-12 18:43:19 UTC (rev 207227)
+++ trunk/LayoutTests/inspector/debugger/stepping/stepping-loops-expected.txt        2016-10-12 18:47:48 UTC (rev 207228)
</span><span class="lines">@@ -148,7 +148,7 @@
</span><span class="cx"> 
</span><span class="cx"> -- Running test case: Debugger.stepping.TraditionalForStepOver
</span><span class="cx"> EXPRESSION: setTimeout(entryTraditionalFor)
</span><del>-STEPS: over, over, over, over, over, over, over, over, resume
</del><ins>+STEPS: over, over, over, over, over, over, over, over, over, resume
</ins><span class="cx"> PAUSED (debugger-statement)
</span><span class="cx"> PAUSE AT entryTraditionalFor:27:5
</span><span class="cx">      23    }
</span><span class="lines">@@ -170,6 +170,16 @@
</span><span class="cx">      30    
</span><span class="cx"> 
</span><span class="cx"> ACTION: step-over
</span><ins>+PAUSE AT entryTraditionalFor:28:21
+     24    
+     25    function entryTraditionalFor() {
+     26        debugger;
+ -&gt;  27        for (let i = 0; |i &lt; 2; ++i)
+     28            a();
+     29    }
+     30    
+
+ACTION: step-over
</ins><span class="cx"> PAUSE AT entryTraditionalFor:29:9
</span><span class="cx">      25    function entryTraditionalFor() {
</span><span class="cx">      26        debugger;
</span><span class="lines">@@ -449,7 +459,7 @@
</span><span class="cx"> 
</span><span class="cx"> -- Running test case: Debugger.stepping.ForIn
</span><span class="cx"> EXPRESSION: setTimeout(entryForIn)
</span><del>-STEPS: over, over, over, over, over, over, resume
</del><ins>+STEPS: over, over, over, over, over, over, over, resume
</ins><span class="cx"> PAUSED (debugger-statement)
</span><span class="cx"> PAUSE AT entryForIn:41:5
</span><span class="cx">      37    
</span><span class="lines">@@ -471,6 +481,16 @@
</span><span class="cx">      44    
</span><span class="cx"> 
</span><span class="cx"> ACTION: step-over
</span><ins>+PAUSE AT entryForIn:42:10
+     38    function entryForIn() {
+     39        let o = {key1: 1, key2: 2};
+     40        debugger;
+ -&gt;  41        for (|let property in o)
+     42            a();
+     43    }
+     44    
+
+ACTION: step-over
</ins><span class="cx"> PAUSE AT entryForIn:43:9
</span><span class="cx">      39        let o = {key1: 1, key2: 2};
</span><span class="cx">      40        debugger;
</span><span class="lines">@@ -481,11 +501,11 @@
</span><span class="cx">      45    function entryForOf() {
</span><span class="cx"> 
</span><span class="cx"> ACTION: step-over
</span><del>-PAUSE AT entryForIn:42:26
</del><ins>+PAUSE AT entryForIn:42:10
</ins><span class="cx">      38    function entryForIn() {
</span><span class="cx">      39        let o = {key1: 1, key2: 2};
</span><span class="cx">      40        debugger;
</span><del>- -&gt;  41        for (let property in |o)
</del><ins>+ -&gt;  41        for (|let property in o)
</ins><span class="cx">      42            a();
</span><span class="cx">      43    }
</span><span class="cx">      44    
</span><span class="lines">@@ -501,11 +521,11 @@
</span><span class="cx">      45    function entryForOf() {
</span><span class="cx"> 
</span><span class="cx"> ACTION: step-over
</span><del>-PAUSE AT entryForIn:42:26
</del><ins>+PAUSE AT entryForIn:42:10
</ins><span class="cx">      38    function entryForIn() {
</span><span class="cx">      39        let o = {key1: 1, key2: 2};
</span><span class="cx">      40        debugger;
</span><del>- -&gt;  41        for (let property in |o)
</del><ins>+ -&gt;  41        for (|let property in o)
</ins><span class="cx">      42            a();
</span><span class="cx">      43    }
</span><span class="cx">      44    
</span><span class="lines">@@ -526,7 +546,7 @@
</span><span class="cx"> 
</span><span class="cx"> -- Running test case: Debugger.stepping.ForIn
</span><span class="cx"> EXPRESSION: setTimeout(entryForOf)
</span><del>-STEPS: over, over, over, over, over, over, resume
</del><ins>+STEPS: over, over, over, over, over, over, over, resume
</ins><span class="cx"> PAUSED (debugger-statement)
</span><span class="cx"> PAUSE AT entryForOf:48:5
</span><span class="cx">      44    
</span><span class="lines">@@ -548,6 +568,16 @@
</span><span class="cx">      51    
</span><span class="cx"> 
</span><span class="cx"> ACTION: step-over
</span><ins>+PAUSE AT entryForOf:49:10
+     45    function entryForOf() {
+     46        let arr = [1, 2];
+     47        debugger;
+ -&gt;  48        for (|let value of arr)
+     49            a();
+     50    }
+     51    
+
+ACTION: step-over
</ins><span class="cx"> PAUSE AT entryForOf:50:9
</span><span class="cx">      46        let arr = [1, 2];
</span><span class="cx">      47        debugger;
</span><span class="lines">@@ -558,11 +588,11 @@
</span><span class="cx">      52    function entryWhileBreakContinue() {
</span><span class="cx"> 
</span><span class="cx"> ACTION: step-over
</span><del>-PAUSE AT entryForOf:49:23
</del><ins>+PAUSE AT entryForOf:49:10
</ins><span class="cx">      45    function entryForOf() {
</span><span class="cx">      46        let arr = [1, 2];
</span><span class="cx">      47        debugger;
</span><del>- -&gt;  48        for (let value of |arr)
</del><ins>+ -&gt;  48        for (|let value of arr)
</ins><span class="cx">      49            a();
</span><span class="cx">      50    }
</span><span class="cx">      51    
</span><span class="lines">@@ -578,11 +608,11 @@
</span><span class="cx">      52    function entryWhileBreakContinue() {
</span><span class="cx"> 
</span><span class="cx"> ACTION: step-over
</span><del>-PAUSE AT entryForOf:49:23
</del><ins>+PAUSE AT entryForOf:49:10
</ins><span class="cx">      45    function entryForOf() {
</span><span class="cx">      46        let arr = [1, 2];
</span><span class="cx">      47        debugger;
</span><del>- -&gt;  48        for (let value of |arr)
</del><ins>+ -&gt;  48        for (|let value of arr)
</ins><span class="cx">      49            a();
</span><span class="cx">      50    }
</span><span class="cx">      51    
</span><span class="lines">@@ -610,7 +640,7 @@
</span><span class="cx">      52    function entryWhileBreakContinue() {
</span><span class="cx">      53        let i = 0;
</span><span class="cx">  -&gt;  54        |debugger;
</span><del>-     55        while (true) {
</del><ins>+     55        while (truthy) {
</ins><span class="cx">      56            ++i;
</span><span class="cx">      57            if (i === 1)
</span><span class="cx"> 
</span><span class="lines">@@ -619,7 +649,7 @@
</span><span class="cx">      52    function entryWhileBreakContinue() {
</span><span class="cx">      53        let i = 0;
</span><span class="cx">      54        debugger;
</span><del>- -&gt;  55        while (|true) {
</del><ins>+ -&gt;  55        while (|truthy) {
</ins><span class="cx">      56            ++i;
</span><span class="cx">      57            if (i === 1)
</span><span class="cx">      58                continue;
</span><span class="lines">@@ -628,7 +658,7 @@
</span><span class="cx"> PAUSE AT entryWhileBreakContinue:57:9
</span><span class="cx">      53        let i = 0;
</span><span class="cx">      54        debugger;
</span><del>-     55        while (true) {
</del><ins>+     55        while (truthy) {
</ins><span class="cx">  -&gt;  56            |++i;
</span><span class="cx">      57            if (i === 1)
</span><span class="cx">      58                continue;
</span><span class="lines">@@ -637,7 +667,7 @@
</span><span class="cx"> ACTION: step-over
</span><span class="cx"> PAUSE AT entryWhileBreakContinue:58:13
</span><span class="cx">      54        debugger;
</span><del>-     55        while (true) {
</del><ins>+     55        while (truthy) {
</ins><span class="cx">      56            ++i;
</span><span class="cx">  -&gt;  57            if (|i === 1)
</span><span class="cx">      58                continue;
</span><span class="lines">@@ -646,7 +676,7 @@
</span><span class="cx"> 
</span><span class="cx"> ACTION: step-over
</span><span class="cx"> PAUSE AT entryWhileBreakContinue:59:13
</span><del>-     55        while (true) {
</del><ins>+     55        while (truthy) {
</ins><span class="cx">      56            ++i;
</span><span class="cx">      57            if (i === 1)
</span><span class="cx">  -&gt;  58                |continue;
</span><span class="lines">@@ -659,7 +689,7 @@
</span><span class="cx">      52    function entryWhileBreakContinue() {
</span><span class="cx">      53        let i = 0;
</span><span class="cx">      54        debugger;
</span><del>- -&gt;  55        while (|true) {
</del><ins>+ -&gt;  55        while (|truthy) {
</ins><span class="cx">      56            ++i;
</span><span class="cx">      57            if (i === 1)
</span><span class="cx">      58                continue;
</span><span class="lines">@@ -668,7 +698,7 @@
</span><span class="cx"> PAUSE AT entryWhileBreakContinue:57:9
</span><span class="cx">      53        let i = 0;
</span><span class="cx">      54        debugger;
</span><del>-     55        while (true) {
</del><ins>+     55        while (truthy) {
</ins><span class="cx">  -&gt;  56            |++i;
</span><span class="cx">      57            if (i === 1)
</span><span class="cx">      58                continue;
</span><span class="lines">@@ -677,7 +707,7 @@
</span><span class="cx"> ACTION: step-over
</span><span class="cx"> PAUSE AT entryWhileBreakContinue:58:13
</span><span class="cx">      54        debugger;
</span><del>-     55        while (true) {
</del><ins>+     55        while (truthy) {
</ins><span class="cx">      56            ++i;
</span><span class="cx">  -&gt;  57            if (|i === 1)
</span><span class="cx">      58                continue;
</span></span></pre></div>
<a id="trunkLayoutTestsinspectordebuggersteppingsteppingloopshtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/inspector/debugger/stepping/stepping-loops.html (207227 => 207228)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/debugger/stepping/stepping-loops.html        2016-10-12 18:43:19 UTC (rev 207227)
+++ trunk/LayoutTests/inspector/debugger/stepping/stepping-loops.html        2016-10-12 18:47:48 UTC (rev 207228)
</span><span class="lines">@@ -4,10 +4,10 @@
</span><span class="cx"> &lt;script src=&quot;../../../http/tests/inspector/resources/inspector-test.js&quot;&gt;&lt;/script&gt;
</span><span class="cx"> &lt;script src=&quot;../resources/log-pause-location.js&quot;&gt;&lt;/script&gt;
</span><span class="cx"> &lt;script&gt;
</span><del>-function a() {
-    return 1;
-}
</del><ins>+var truthy = true;
+function a() { return 1; }
</ins><span class="cx"> 
</span><ins>+
</ins><span class="cx"> function entryWhile() {
</span><span class="cx">     let i = 2;
</span><span class="cx">     debugger;
</span><span class="lines">@@ -53,7 +53,7 @@
</span><span class="cx"> function entryWhileBreakContinue() {
</span><span class="cx">     let i = 0;
</span><span class="cx">     debugger;
</span><del>-    while (true) {
</del><ins>+    while (truthy) {
</ins><span class="cx">         ++i;
</span><span class="cx">         if (i === 1)
</span><span class="cx">             continue;
</span><span class="lines">@@ -117,7 +117,8 @@
</span><span class="cx">         expression: &quot;setTimeout(entryTraditionalFor)&quot;,
</span><span class="cx">         steps: [
</span><span class="cx">             &quot;over&quot;,
</span><del>-                &quot;over&quot;, // complete: let i = 0; i &lt; 2
</del><ins>+                &quot;over&quot;, // complete: let i = 0
+                &quot;over&quot;, // complete: i &lt; 2
</ins><span class="cx">                 &quot;over&quot;, // complete: a()
</span><span class="cx">                 &quot;over&quot;, // complete: ++i
</span><span class="cx">                 &quot;over&quot;, // complete: i &lt; 2 [i=1]
</span><span class="lines">@@ -169,6 +170,7 @@
</span><span class="cx">         expression: &quot;setTimeout(entryForIn)&quot;,
</span><span class="cx">         steps: [
</span><span class="cx">             &quot;over&quot;,
</span><ins>+                &quot;over&quot;, // complete: (o)
</ins><span class="cx">                 &quot;over&quot;, // complete: let property in o [key1]
</span><span class="cx">                 &quot;over&quot;, // complete: a()
</span><span class="cx">                 &quot;over&quot;, // complete: let property in o [key2]
</span><span class="lines">@@ -184,6 +186,7 @@
</span><span class="cx">         expression: &quot;setTimeout(entryForOf)&quot;,
</span><span class="cx">         steps: [
</span><span class="cx">             &quot;over&quot;,
</span><ins>+                &quot;over&quot;, // complete (arr)
</ins><span class="cx">                 &quot;over&quot;, // complete: let value of arr [1]
</span><span class="cx">                 &quot;over&quot;, // complete: a()
</span><span class="cx">                 &quot;over&quot;, // complete: let value of arr [2]
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (207227 => 207228)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-10-12 18:43:19 UTC (rev 207227)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-10-12 18:47:48 UTC (rev 207228)
</span><span class="lines">@@ -1,3 +1,111 @@
</span><ins>+2016-10-12  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
+
+        Emit DebugHooks uniformly with pause locations instead of having separate pause locations and op_debug emits
+        https://bugs.webkit.org/show_bug.cgi?id=162809
+
+        Reviewed by Geoffrey Garen.
+
+        Change how BytecodeGeneration emits debug hooks to be more consistent.
+        Previously most nodes individually generated their own debug hook
+        and we asserted that it matched a breakpoint location identified
+        by the parser. This could get out of sync, or nodes could forget to
+        emit debug hooks expected by the parser.
+        
+        With this change, we always check and emit a debug hook for any
+        node. The default behavior is for BytecodeGenerator::emitNode
+        to emit the debug hook when emitting the node itself. This covers
+        the majority of cases (statements).
+
+        There are a few exceptions where we continue to need to customize
+        emitting debug hooks:
+
+            1. Nodes with emitBytecodeInConditionContext
+                - non-Expression nodes customize how they emit their children
+                - constants conditions may emit nothing, but we had recorded a breakpoint location so emit a debug hook
+                - always emit one debug hook in case we recorded a breakpoint location, but avoid emitting multiple
+                  in nodes which may call up to the ExpressionNode::emitBytecodeInConditionContext base impl.
+            2. Specialized Debug Hooks
+                - such as hooks for Program start/end, debugger statements, etc.
+            3. Debug Hooks in for..of / for..in that don't correspond to re-emitting nodes
+                - such as pausing on the assignment expression inside these loops
+
+        The majority of nodes no longer have custom emits.
+
+        * bytecompiler/BytecodeGenerator.h:
+        (JSC::BytecodeGenerator::emitNodeInTailPosition):
+        (JSC::BytecodeGenerator::emitNodeInConditionContext):
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::emitDebugHook):
+        (JSC::BytecodeGenerator::emitEnumeration):
+        By default, when emitting a node check if we should also emit an op_debug for it.
+        This default DebugHook is WillExecuteStatement, which is a normal pause point.
+
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::ConstantNode::emitBytecodeInConditionContext):
+        (JSC::LogicalNotNode::emitBytecodeInConditionContext):
+        (JSC::BinaryOpNode::emitBytecodeInConditionContext):
+        (JSC::LogicalOpNode::emitBytecodeInConditionContext):
+        The parser would have generated a pause location for these conditions
+        no matter what constant folding and re-writing these nodes may perform.
+        So, when emitting these nodes in condition context check if they need
+        emit their own debug hook.
+
+        (JSC::EmptyStatementNode::emitBytecode):
+        (JSC::ExprStatementNode::emitBytecode):
+        (JSC::DeclarationStatement::emitBytecode):
+        (JSC::IfElseNode::emitBytecode):
+        (JSC::DoWhileNode::emitBytecode):
+        (JSC::WhileNode::emitBytecode):
+        (JSC::ForNode::emitBytecode):
+        (JSC::ContinueNode::emitBytecode):
+        (JSC::BreakNode::emitBytecode):
+        (JSC::ReturnNode::emitBytecode):
+        (JSC::WithNode::emitBytecode):
+        (JSC::SwitchNode::emitBytecode):
+        (JSC::ThrowNode::emitBytecode):
+        No longer need to custom emit debug hooks. The default emitNode will handle these.
+
+        (JSC::ForInNode::emitBytecode):
+        Include extra debug hooks the user expects to return back to the assignment
+        expression in the loop header before starting the body again. The same is done
+        for for..of with emitEnumeration.
+
+        * parser/ASTBuilder.h:
+        (JSC::ASTBuilder::createExportDefaultDeclaration):
+        (JSC::ASTBuilder::createExportLocalDeclaration):
+        These are no longer needed to fake-satisfy assertions. We never wanted to
+        emit debug hooks for these inner statements because the export statement
+        will already have the debug hooks.
+
+        (JSC::ASTBuilder::createForInLoop):
+        (JSC::ASTBuilder::createForOfLoop):
+        Include the correct location where the declaration starts.
+
+        (JSC::ASTBuilder::breakpointLocation):
+        Simplify to a general implementation for Node.
+
+        * parser/SyntaxChecker.h:
+        (JSC::SyntaxChecker::createForInLoop):
+        (JSC::SyntaxChecker::createForOfLoop):
+        Ignore the new extra parameter.
+
+        * parser/Nodes.h:
+        (JSC::Node::needsDebugHook):
+        (JSC::Node::setNeedsDebugHook):
+        (JSC::ExpressionNode::needsDebugHook): Deleted.
+        (JSC::ExpressionNode::setNeedsDebugHook): Deleted.
+        (JSC::StatementNode::isEmptyStatement): Deleted.
+        (JSC::StatementNode::needsDebugHook): Deleted.
+        (JSC::StatementNode::setNeedsDebugHook): Deleted.
+        Move debug hook logic into the base Node class.
+
+        (JSC::StatementNode::isDebuggerStatement):
+        Provide a way to distinguish a debugger statement.
+
+        * parser/Parser.cpp:
+        (JSC::Parser&lt;LexerType&gt;::parseForStatement):
+        Provide the location before the declaration starts.
+
</ins><span class="cx"> 2016-10-12  Mark Lam  &lt;mark.lam@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Array.prototype.slice should not modify frozen objects.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (207227 => 207228)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2016-10-12 18:43:19 UTC (rev 207227)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2016-10-12 18:47:48 UTC (rev 207228)
</span><span class="lines">@@ -3504,14 +3504,16 @@
</span><span class="cx"> 
</span><span class="cx"> void BytecodeGenerator::emitDebugHook(StatementNode* statement)
</span><span class="cx"> {
</span><del>-    RELEASE_ASSERT(statement-&gt;needsDebugHook());
</del><ins>+    // DebuggerStatementNode will output its own special debug hook.
+    if (statement-&gt;isDebuggerStatement())
+        return;
+
</ins><span class="cx">     emitDebugHook(WillExecuteStatement, statement-&gt;position());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void BytecodeGenerator::emitDebugHook(ExpressionNode* expr, DebugHookType debugHookType)
</del><ins>+void BytecodeGenerator::emitDebugHook(ExpressionNode* expr)
</ins><span class="cx"> {
</span><del>-    RELEASE_ASSERT(expr-&gt;needsDebugHook());
-    emitDebugHook(debugHookType, expr-&gt;position());
</del><ins>+    emitDebugHook(WillExecuteStatement, expr-&gt;position());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void BytecodeGenerator::emitWillLeaveCallFrameDebugHook()
</span><span class="lines">@@ -4202,7 +4204,7 @@
</span><span class="cx">         if (forLoopNode) {
</span><span class="cx">             RELEASE_ASSERT(forLoopNode-&gt;isForOfNode());
</span><span class="cx">             prepareLexicalScopeForNextForLoopIteration(forLoopNode, forLoopSymbolTable);
</span><del>-            emitDebugHook(forLoopNode-&gt;expr(), WillExecuteStatement);
</del><ins>+            emitDebugHook(forLoopNode-&gt;lexpr());
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h (207227 => 207228)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2016-10-12 18:43:19 UTC (rev 207227)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2016-10-12 18:47:48 UTC (rev 207228)
</span><span class="lines">@@ -386,6 +386,8 @@
</span><span class="cx">                 emitThrowExpressionTooDeepException();
</span><span class="cx">                 return;
</span><span class="cx">             }
</span><ins>+            if (UNLIKELY(n-&gt;needsDebugHook()))
+                emitDebugHook(n);
</ins><span class="cx">             n-&gt;emitBytecode(*this, dst);
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -411,6 +413,8 @@
</span><span class="cx">             ASSERT(!dst || dst == ignoredResult() || !dst-&gt;isTemporary() || dst-&gt;refCount());
</span><span class="cx">             if (UNLIKELY(!m_vm-&gt;isSafeToRecurse()))
</span><span class="cx">                 return emitThrowExpressionTooDeepException();
</span><ins>+            if (UNLIKELY(n-&gt;needsDebugHook()))
+                emitDebugHook(n);
</ins><span class="cx">             return n-&gt;emitBytecode(*this, dst);
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -430,7 +434,6 @@
</span><span class="cx">                 emitThrowExpressionTooDeepException();
</span><span class="cx">                 return;
</span><span class="cx">             }
</span><del>-
</del><span class="cx">             n-&gt;emitBytecodeInConditionContext(*this, trueTarget, falseTarget, fallThroughMode);
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -684,7 +687,7 @@
</span><span class="cx">         void emitDebugHook(DebugHookType, const JSTextPosition&amp;);
</span><span class="cx">         void emitDebugHook(DebugHookType, unsigned line, unsigned charOffset, unsigned lineStart);
</span><span class="cx">         void emitDebugHook(StatementNode*);
</span><del>-        void emitDebugHook(ExpressionNode*, DebugHookType);
</del><ins>+        void emitDebugHook(ExpressionNode*);
</ins><span class="cx">         void emitWillLeaveCallFrameDebugHook();
</span><span class="cx"> 
</span><span class="cx">         bool isInFinallyBlock() { return m_finallyDepth &gt; 0; }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerNodesCodegencpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp (207227 => 207228)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2016-10-12 18:43:19 UTC (rev 207227)
+++ trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2016-10-12 18:47:48 UTC (rev 207228)
</span><span class="lines">@@ -94,6 +94,12 @@
</span><span class="cx"> void ConstantNode::emitBytecodeInConditionContext(BytecodeGenerator&amp; generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
</span><span class="cx"> {
</span><span class="cx">     TriState value = jsValue(generator).pureToBoolean();
</span><ins>+
+    if (UNLIKELY(needsDebugHook())) {
+        if (value != MixedTriState)
+            generator.emitDebugHook(this);
+    }
+
</ins><span class="cx">     if (value == MixedTriState)
</span><span class="cx">         ExpressionNode::emitBytecodeInConditionContext(generator, trueTarget, falseTarget, fallThroughMode);
</span><span class="cx">     else if (value == TrueTriState &amp;&amp; fallThroughMode == FallThroughMeansFalse)
</span><span class="lines">@@ -1669,7 +1675,10 @@
</span><span class="cx"> 
</span><span class="cx"> void LogicalNotNode::emitBytecodeInConditionContext(BytecodeGenerator&amp; generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
</span><span class="cx"> {
</span><del>-    // reverse the true and false targets
</del><ins>+    if (UNLIKELY(needsDebugHook()))
+        generator.emitDebugHook(this);
+
+    // Reverse the true and false targets.
</ins><span class="cx">     generator.emitNodeInConditionContext(expr(), falseTarget, trueTarget, invert(fallThroughMode));
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1799,6 +1808,11 @@
</span><span class="cx">     ExpressionNode* branchExpression;
</span><span class="cx">     tryFoldToBranch(generator, branchCondition, branchExpression);
</span><span class="cx"> 
</span><ins>+    if (UNLIKELY(needsDebugHook())) {
+        if (branchCondition != MixedTriState)
+            generator.emitDebugHook(this);
+    }
+
</ins><span class="cx">     if (branchCondition == MixedTriState)
</span><span class="cx">         ExpressionNode::emitBytecodeInConditionContext(generator, trueTarget, falseTarget, fallThroughMode);
</span><span class="cx">     else if (branchCondition == TrueTriState)
</span><span class="lines">@@ -2000,6 +2014,9 @@
</span><span class="cx"> 
</span><span class="cx"> void LogicalOpNode::emitBytecodeInConditionContext(BytecodeGenerator&amp; generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
</span><span class="cx"> {
</span><ins>+    if (UNLIKELY(needsDebugHook()))
+        generator.emitDebugHook(this);
+
</ins><span class="cx">     RefPtr&lt;Label&gt; afterExpr1 = generator.newLabel();
</span><span class="cx">     if (m_operator == OpLogicalAnd)
</span><span class="cx">         generator.emitNodeInConditionContext(m_expr1, afterExpr1.get(), falseTarget, FallThroughMeansTrue);
</span><span class="lines">@@ -2376,9 +2393,9 @@
</span><span class="cx"> 
</span><span class="cx"> // ------------------------------ EmptyStatementNode ---------------------------
</span><span class="cx"> 
</span><del>-void EmptyStatementNode::emitBytecode(BytecodeGenerator&amp; generator, RegisterID*)
</del><ins>+void EmptyStatementNode::emitBytecode(BytecodeGenerator&amp;, RegisterID*)
</ins><span class="cx"> {
</span><del>-    generator.emitDebugHook(this);
</del><ins>+    RELEASE_ASSERT(needsDebugHook());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> // ------------------------------ DebuggerStatementNode ---------------------------
</span><span class="lines">@@ -2393,7 +2410,6 @@
</span><span class="cx"> void ExprStatementNode::emitBytecode(BytecodeGenerator&amp; generator, RegisterID* dst)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(m_expr);
</span><del>-    generator.emitDebugHook(this);
</del><span class="cx">     generator.emitNode(dst, m_expr);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -2402,7 +2418,6 @@
</span><span class="cx"> void DeclarationStatement::emitBytecode(BytecodeGenerator&amp; generator, RegisterID*)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(m_expr);
</span><del>-    generator.emitDebugHook(this);
</del><span class="cx">     generator.emitNode(m_expr);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -2490,8 +2505,6 @@
</span><span class="cx"> 
</span><span class="cx"> void IfElseNode::emitBytecode(BytecodeGenerator&amp; generator, RegisterID* dst)
</span><span class="cx"> {
</span><del>-    generator.emitDebugHook(m_condition, WillExecuteStatement);
-    
</del><span class="cx">     RefPtr&lt;Label&gt; beforeThen = generator.newLabel();
</span><span class="cx">     RefPtr&lt;Label&gt; beforeElse = generator.newLabel();
</span><span class="cx">     RefPtr&lt;Label&gt; afterElse = generator.newLabel();
</span><span class="lines">@@ -2536,7 +2549,6 @@
</span><span class="cx">     generator.emitNodeInTailPosition(dst, m_statement);
</span><span class="cx"> 
</span><span class="cx">     generator.emitLabel(scope-&gt;continueTarget());
</span><del>-    generator.emitDebugHook(m_expr, WillExecuteStatement);
</del><span class="cx">     generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope-&gt;breakTarget(), FallThroughMeansFalse);
</span><span class="cx"> 
</span><span class="cx">     generator.emitLabel(scope-&gt;breakTarget());
</span><span class="lines">@@ -2549,7 +2561,6 @@
</span><span class="cx">     LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
</span><span class="cx">     RefPtr&lt;Label&gt; topOfLoop = generator.newLabel();
</span><span class="cx"> 
</span><del>-    generator.emitDebugHook(m_expr, WillExecuteStatement);
</del><span class="cx">     generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope-&gt;breakTarget(), FallThroughMeansTrue);
</span><span class="cx"> 
</span><span class="cx">     generator.emitLabel(topOfLoop.get());
</span><span class="lines">@@ -2559,7 +2570,6 @@
</span><span class="cx">     generator.emitNodeInTailPosition(dst, m_statement);
</span><span class="cx"> 
</span><span class="cx">     generator.emitLabel(scope-&gt;continueTarget());
</span><del>-    generator.emitDebugHook(m_expr, WillExecuteStatement);
</del><span class="cx"> 
</span><span class="cx">     generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope-&gt;breakTarget(), FallThroughMeansFalse);
</span><span class="cx"> 
</span><span class="lines">@@ -2577,21 +2587,12 @@
</span><span class="cx">     RegisterID* forLoopSymbolTable = nullptr;
</span><span class="cx">     generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested, &amp;forLoopSymbolTable);
</span><span class="cx"> 
</span><del>-    if (m_expr1 || m_expr2) {
-        ExpressionNode* firstExpr = m_expr1 ? m_expr1 : m_expr2;
-        generator.emitDebugHook(firstExpr, WillExecuteStatement);
-    }
-
-    if (m_expr1) {
-        generator.emitDebugHook(m_expr1, WillExecuteExpression);
</del><ins>+    if (m_expr1)
</ins><span class="cx">         generator.emitNode(generator.ignoredResult(), m_expr1);
</span><del>-    }
</del><span class="cx"> 
</span><span class="cx">     RefPtr&lt;Label&gt; topOfLoop = generator.newLabel();
</span><del>-    if (m_expr2) {
-        generator.emitDebugHook(m_expr2, WillExecuteExpression);
</del><ins>+    if (m_expr2)
</ins><span class="cx">         generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope-&gt;breakTarget(), FallThroughMeansTrue);
</span><del>-    }
</del><span class="cx"> 
</span><span class="cx">     generator.emitLabel(topOfLoop.get());
</span><span class="cx">     generator.emitLoopHint();
</span><span class="lines">@@ -2601,15 +2602,12 @@
</span><span class="cx"> 
</span><span class="cx">     generator.emitLabel(scope-&gt;continueTarget());
</span><span class="cx">     generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
</span><del>-    if (m_expr3) {
-        generator.emitDebugHook(m_expr3, WillExecuteStatement);
</del><ins>+    if (m_expr3)
</ins><span class="cx">         generator.emitNode(generator.ignoredResult(), m_expr3);
</span><del>-    }
</del><span class="cx"> 
</span><del>-    if (m_expr2) {
-        generator.emitDebugHook(m_expr2, WillExecuteStatement);
</del><ins>+    if (m_expr2)
</ins><span class="cx">         generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope-&gt;breakTarget(), FallThroughMeansFalse);
</span><del>-    } else
</del><ins>+    else
</ins><span class="cx">         generator.emitJump(topOfLoop.get());
</span><span class="cx"> 
</span><span class="cx">     generator.emitLabel(scope-&gt;breakTarget());
</span><span class="lines">@@ -2738,8 +2736,6 @@
</span><span class="cx">     RegisterID* forLoopSymbolTable = nullptr;
</span><span class="cx">     generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested, &amp;forLoopSymbolTable);
</span><span class="cx"> 
</span><del>-    generator.emitDebugHook(m_expr, WillExecuteStatement);
-
</del><span class="cx">     if (m_lexpr-&gt;isAssignResolveNode())
</span><span class="cx">         generator.emitNode(generator.ignoredResult(), m_lexpr);
</span><span class="cx"> 
</span><span class="lines">@@ -2751,6 +2747,9 @@
</span><span class="cx">     RefPtr&lt;RegisterID&gt; local = this-&gt;tryGetBoundLocal(generator);
</span><span class="cx">     RefPtr&lt;RegisterID&gt; enumeratorIndex;
</span><span class="cx"> 
</span><ins>+    // Pause at the assignment expression for each for..in iteration.
+    generator.emitDebugHook(m_lexpr);
+
</ins><span class="cx">     int profilerStartOffset = m_statement-&gt;startOffset();
</span><span class="cx">     int profilerEndOffset = m_statement-&gt;endOffset() + (m_statement-&gt;isBlock() ? 1 : 0);
</span><span class="cx"> 
</span><span class="lines">@@ -2788,7 +2787,7 @@
</span><span class="cx">         generator.emitLabel(scope-&gt;continueTarget());
</span><span class="cx">         generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
</span><span class="cx">         generator.emitInc(i.get());
</span><del>-        generator.emitDebugHook(m_expr, WillExecuteStatement);
</del><ins>+        generator.emitDebugHook(m_lexpr); // Pause at the assignment expression for each for..in iteration.
</ins><span class="cx">         generator.emitJump(loopStart.get());
</span><span class="cx"> 
</span><span class="cx">         generator.emitLabel(scope-&gt;breakTarget());
</span><span class="lines">@@ -2828,7 +2827,7 @@
</span><span class="cx">         generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
</span><span class="cx">         generator.emitInc(enumeratorIndex.get());
</span><span class="cx">         generator.emitEnumeratorStructurePropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
</span><del>-        generator.emitDebugHook(m_expr, WillExecuteStatement);
</del><ins>+        generator.emitDebugHook(m_lexpr); // Pause at the assignment expression for each for..in iteration.
</ins><span class="cx">         generator.emitJump(loopStart.get());
</span><span class="cx">         
</span><span class="cx">         generator.emitLabel(scope-&gt;breakTarget());
</span><span class="lines">@@ -2865,7 +2864,7 @@
</span><span class="cx">         generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
</span><span class="cx">         generator.emitInc(enumeratorIndex.get());
</span><span class="cx">         generator.emitEnumeratorGenericPropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
</span><del>-        generator.emitDebugHook(m_expr, WillExecuteStatement);
</del><ins>+        generator.emitDebugHook(m_lexpr); // Pause at the assignment expression for each for..in iteration.
</ins><span class="cx">         generator.emitJump(loopStart.get());
</span><span class="cx"> 
</span><span class="cx">         generator.emitLabel(scope-&gt;breakTarget());
</span><span class="lines">@@ -2962,8 +2961,6 @@
</span><span class="cx"> 
</span><span class="cx"> void ContinueNode::emitBytecode(BytecodeGenerator&amp; generator, RegisterID*)
</span><span class="cx"> {
</span><del>-    generator.emitDebugHook(this);
-    
</del><span class="cx">     LabelScopePtr scope = generator.continueTarget(m_ident);
</span><span class="cx">     ASSERT(scope);
</span><span class="cx"> 
</span><span class="lines">@@ -2991,8 +2988,6 @@
</span><span class="cx"> 
</span><span class="cx"> void BreakNode::emitBytecode(BytecodeGenerator&amp; generator, RegisterID*)
</span><span class="cx"> {
</span><del>-    generator.emitDebugHook(this);
-    
</del><span class="cx">     LabelScopePtr scope = generator.breakTarget(m_ident);
</span><span class="cx">     ASSERT(scope);
</span><span class="cx"> 
</span><span class="lines">@@ -3006,8 +3001,6 @@
</span><span class="cx"> 
</span><span class="cx"> void ReturnNode::emitBytecode(BytecodeGenerator&amp; generator, RegisterID* dst)
</span><span class="cx"> {
</span><del>-    generator.emitDebugHook(this);
-
</del><span class="cx">     ASSERT(generator.codeType() == FunctionCode);
</span><span class="cx"> 
</span><span class="cx">     if (dst == generator.ignoredResult())
</span><span class="lines">@@ -3034,8 +3027,6 @@
</span><span class="cx"> 
</span><span class="cx"> void WithNode::emitBytecode(BytecodeGenerator&amp; generator, RegisterID* dst)
</span><span class="cx"> {
</span><del>-    generator.emitDebugHook(m_expr, WillExecuteStatement);
-
</del><span class="cx">     RefPtr&lt;RegisterID&gt; scope = generator.emitNode(m_expr);
</span><span class="cx">     generator.emitExpressionInfo(m_divot, m_divot - m_expressionLength, m_divot);
</span><span class="cx">     generator.emitPushWithScope(scope.get());
</span><span class="lines">@@ -3209,8 +3200,6 @@
</span><span class="cx"> 
</span><span class="cx"> void SwitchNode::emitBytecode(BytecodeGenerator&amp; generator, RegisterID* dst)
</span><span class="cx"> {
</span><del>-    generator.emitDebugHook(m_expr, WillExecuteStatement);
-    
</del><span class="cx">     LabelScopePtr scope = generator.newLabelScope(LabelScope::Switch);
</span><span class="cx"> 
</span><span class="cx">     RefPtr&lt;RegisterID&gt; r0 = generator.emitNode(m_expr);
</span><span class="lines">@@ -3239,8 +3228,6 @@
</span><span class="cx"> 
</span><span class="cx"> void ThrowNode::emitBytecode(BytecodeGenerator&amp; generator, RegisterID* dst)
</span><span class="cx"> {
</span><del>-    generator.emitDebugHook(this);
-
</del><span class="cx">     if (dst == generator.ignoredResult())
</span><span class="cx">         dst = 0;
</span><span class="cx">     RefPtr&lt;RegisterID&gt; expr = generator.emitNode(m_expr);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserASTBuilderh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/ASTBuilder.h (207227 => 207228)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/ASTBuilder.h        2016-10-12 18:43:19 UTC (rev 207227)
+++ trunk/Source/JavaScriptCore/parser/ASTBuilder.h        2016-10-12 18:47:48 UTC (rev 207228)
</span><span class="lines">@@ -559,7 +559,7 @@
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    StatementNode* createForInLoop(const JSTokenLocation&amp; location, ExpressionNode* lhs, ExpressionNode* iter, StatementNode* statements, const JSTextPosition&amp; eStart, const JSTextPosition&amp; eDivot, const JSTextPosition&amp; eEnd, int start, int end, VariableEnvironment&amp; lexicalVariables)
</del><ins>+    StatementNode* createForInLoop(const JSTokenLocation&amp; location, ExpressionNode* lhs, ExpressionNode* iter, StatementNode* statements, const JSTokenLocation&amp;, const JSTextPosition&amp; eStart, const JSTextPosition&amp; eDivot, const JSTextPosition&amp; eEnd, int start, int end, VariableEnvironment&amp; lexicalVariables)
</ins><span class="cx">     {
</span><span class="cx">         ForInNode* result = new (m_parserArena) ForInNode(location, lhs, iter, statements, lexicalVariables);
</span><span class="cx">         result-&gt;setLoc(start, end, location.startOffset, location.lineStartOffset);
</span><span class="lines">@@ -567,13 +567,13 @@
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    StatementNode* createForInLoop(const JSTokenLocation&amp; location, DestructuringPatternNode* pattern, ExpressionNode* iter, StatementNode* statements, const JSTextPosition&amp; eStart, const JSTextPosition&amp; eDivot, const JSTextPosition&amp; eEnd, int start, int end, VariableEnvironment&amp; lexicalVariables)
</del><ins>+    StatementNode* createForInLoop(const JSTokenLocation&amp; location, DestructuringPatternNode* pattern, ExpressionNode* iter, StatementNode* statements, const JSTokenLocation&amp; declLocation, const JSTextPosition&amp; eStart, const JSTextPosition&amp; eDivot, const JSTextPosition&amp; eEnd, int start, int end, VariableEnvironment&amp; lexicalVariables)
</ins><span class="cx">     {
</span><del>-        auto lexpr = new (m_parserArena) DestructuringAssignmentNode(location, pattern, 0);
-        return createForInLoop(location, lexpr, iter, statements, eStart, eDivot, eEnd, start, end, lexicalVariables);
</del><ins>+        auto lexpr = new (m_parserArena) DestructuringAssignmentNode(declLocation, pattern, nullptr);
+        return createForInLoop(location, lexpr, iter, statements, declLocation, eStart, eDivot, eEnd, start, end, lexicalVariables);
</ins><span class="cx">     }
</span><span class="cx">     
</span><del>-    StatementNode* createForOfLoop(const JSTokenLocation&amp; location, ExpressionNode* lhs, ExpressionNode* iter, StatementNode* statements, const JSTextPosition&amp; eStart, const JSTextPosition&amp; eDivot, const JSTextPosition&amp; eEnd, int start, int end, VariableEnvironment&amp; lexicalVariables)
</del><ins>+    StatementNode* createForOfLoop(const JSTokenLocation&amp; location, ExpressionNode* lhs, ExpressionNode* iter, StatementNode* statements, const JSTokenLocation&amp;, const JSTextPosition&amp; eStart, const JSTextPosition&amp; eDivot, const JSTextPosition&amp; eEnd, int start, int end, VariableEnvironment&amp; lexicalVariables)
</ins><span class="cx">     {
</span><span class="cx">         ForOfNode* result = new (m_parserArena) ForOfNode(location, lhs, iter, statements, lexicalVariables);
</span><span class="cx">         result-&gt;setLoc(start, end, location.startOffset, location.lineStartOffset);
</span><span class="lines">@@ -581,10 +581,10 @@
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    StatementNode* createForOfLoop(const JSTokenLocation&amp; location, DestructuringPatternNode* pattern, ExpressionNode* iter, StatementNode* statements, const JSTextPosition&amp; eStart, const JSTextPosition&amp; eDivot, const JSTextPosition&amp; eEnd, int start, int end, VariableEnvironment&amp; lexicalVariables)
</del><ins>+    StatementNode* createForOfLoop(const JSTokenLocation&amp; location, DestructuringPatternNode* pattern, ExpressionNode* iter, StatementNode* statements, const JSTokenLocation&amp; declLocation, const JSTextPosition&amp; eStart, const JSTextPosition&amp; eDivot, const JSTextPosition&amp; eEnd, int start, int end, VariableEnvironment&amp; lexicalVariables)
</ins><span class="cx">     {
</span><del>-        auto lexpr = new (m_parserArena) DestructuringAssignmentNode(location, pattern, 0);
-        return createForOfLoop(location, lexpr, iter, statements, eStart, eDivot, eEnd, start, end, lexicalVariables);
</del><ins>+        auto lexpr = new (m_parserArena) DestructuringAssignmentNode(declLocation, pattern, nullptr);
+        return createForOfLoop(location, lexpr, iter, statements, declLocation, eStart, eDivot, eEnd, start, end, lexicalVariables);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     bool isBindingNode(const DestructuringPattern&amp; pattern)
</span><span class="lines">@@ -752,21 +752,11 @@
</span><span class="cx"> 
</span><span class="cx">     StatementNode* createExportDefaultDeclaration(const JSTokenLocation&amp; location, StatementNode* declaration, const Identifier&amp; localName)
</span><span class="cx">     {
</span><del>-        // We need to mark the inner statement as needing a debug hook (so that when the statement is generated we don't
-        // assert when generating an op_debug for it) without recording a breakpoint location because the export statement
-        // itself will get the breakpoint location. This will be eliminated by:
-        // &lt;https://webkit.org/b/162809&gt; Emit DebugHooks uniformly with pause locations instead of having separate pause locations and op_debug emits
-        declaration-&gt;setNeedsDebugHook();
</del><span class="cx">         return new (m_parserArena) ExportDefaultDeclarationNode(location, declaration, localName);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     StatementNode* createExportLocalDeclaration(const JSTokenLocation&amp; location, StatementNode* declaration)
</span><span class="cx">     {
</span><del>-        // We need to mark the inner statement as needing a debug hook (so that when the statement is generated we don't
-        // assert when generating an op_debug for it) without recording a breakpoint location because the export statement
-        // itself will get the breakpoint location. This will be eliminated by:
-        // &lt;https://webkit.org/b/162809&gt; Emit DebugHooks uniformly with pause locations instead of having separate pause locations and op_debug emits
-        declaration-&gt;setNeedsDebugHook();
</del><span class="cx">         return new (m_parserArena) ExportLocalDeclarationNode(location, declaration);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -983,18 +973,12 @@
</span><span class="cx">         node-&gt;setStartOffset(offset);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    JSTextPosition breakpointLocation(StatementNode* statement)
</del><ins>+    JSTextPosition breakpointLocation(Node* node)
</ins><span class="cx">     {
</span><del>-        statement-&gt;setNeedsDebugHook();
-        return statement-&gt;position();
</del><ins>+        node-&gt;setNeedsDebugHook();
+        return node-&gt;position();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    JSTextPosition breakpointLocation(ExpressionNode* expr)
-    {
-        expr-&gt;setNeedsDebugHook();
-        return expr-&gt;position();
-    }
-
</del><span class="cx">     void propagateArgumentsUse() { usesArguments(); }
</span><span class="cx">     
</span><span class="cx"> private:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserNodesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Nodes.h (207227 => 207228)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Nodes.h        2016-10-12 18:43:19 UTC (rev 207227)
+++ trunk/Source/JavaScriptCore/parser/Nodes.h        2016-10-12 18:47:48 UTC (rev 207228)
</span><span class="lines">@@ -145,9 +145,13 @@
</span><span class="cx">         void setEndOffset(int offset) { m_endOffset = offset; }
</span><span class="cx">         void setStartOffset(int offset) { m_position.offset = offset; }
</span><span class="cx"> 
</span><ins>+        bool needsDebugHook() const { return m_needsDebugHook; }
+        void setNeedsDebugHook() { m_needsDebugHook = true; }
+
</ins><span class="cx">     protected:
</span><span class="cx">         JSTextPosition m_position;
</span><span class="cx">         int m_endOffset;
</span><ins>+        bool m_needsDebugHook { false };
</ins><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     class ExpressionNode : public Node {
</span><span class="lines">@@ -191,12 +195,8 @@
</span><span class="cx"> 
</span><span class="cx">         ResultType resultDescriptor() const { return m_resultType; }
</span><span class="cx"> 
</span><del>-        bool needsDebugHook() { return m_needsDebugHook; }
-        void setNeedsDebugHook() { m_needsDebugHook = true; }
-
</del><span class="cx">     private:
</span><span class="cx">         ResultType m_resultType;
</span><del>-        bool m_needsDebugHook { false };
</del><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     class StatementNode : public Node {
</span><span class="lines">@@ -213,6 +213,7 @@
</span><span class="cx">         void setNext(StatementNode* next) { m_next = next; }
</span><span class="cx"> 
</span><span class="cx">         virtual bool isEmptyStatement() const { return false; }
</span><ins>+        virtual bool isDebuggerStatement() const { return false; }
</ins><span class="cx">         virtual bool isFunctionNode() const { return false; }
</span><span class="cx">         virtual bool isReturnNode() const { return false; }
</span><span class="cx">         virtual bool isExprStatement() const { return false; }
</span><span class="lines">@@ -224,13 +225,9 @@
</span><span class="cx">         virtual bool isModuleDeclarationNode() const { return false; }
</span><span class="cx">         virtual bool isForOfNode() const { return false; }
</span><span class="cx"> 
</span><del>-        bool needsDebugHook() { return m_needsDebugHook; }
-        void setNeedsDebugHook() { m_needsDebugHook = true; }
-
</del><span class="cx">     protected:
</span><span class="cx">         StatementNode* m_next;
</span><span class="cx">         int m_lastLine;
</span><del>-        bool m_needsDebugHook { false };
</del><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     class VariableEnvironmentNode : public ParserArenaDeletable {
</span><span class="lines">@@ -1366,6 +1363,8 @@
</span><span class="cx">     class DebuggerStatementNode : public StatementNode {
</span><span class="cx">     public:
</span><span class="cx">         DebuggerStatementNode(const JSTokenLocation&amp;);
</span><ins>+
+        bool isDebuggerStatement() const override { return true; }
</ins><span class="cx">         
</span><span class="cx">     private:
</span><span class="cx">         void emitBytecode(BytecodeGenerator&amp;, RegisterID* = 0) override;
</span><span class="lines">@@ -1473,6 +1472,7 @@
</span><span class="cx"> 
</span><span class="cx">         EnumerationNode(const JSTokenLocation&amp;, ExpressionNode*, ExpressionNode*, StatementNode*, VariableEnvironment&amp;);
</span><span class="cx"> 
</span><ins>+        ExpressionNode* lexpr() const { return m_lexpr; }
</ins><span class="cx">         ExpressionNode* expr() const { return m_expr; }
</span><span class="cx"> 
</span><span class="cx">     protected:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Parser.cpp (207227 => 207228)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Parser.cpp        2016-10-12 18:43:19 UTC (rev 207227)
+++ trunk/Source/JavaScriptCore/parser/Parser.cpp        2016-10-12 18:47:48 UTC (rev 207228)
</span><span class="lines">@@ -1186,6 +1186,7 @@
</span><span class="cx">     handleProductionOrFail(OPENPAREN, &quot;(&quot;, &quot;start&quot;, &quot;for-loop header&quot;);
</span><span class="cx">     int nonLHSCount = m_parserState.nonLHSCount;
</span><span class="cx">     int declarations = 0;
</span><ins>+    JSTokenLocation declLocation(tokenLocation());
</ins><span class="cx">     JSTextPosition declsStart;
</span><span class="cx">     JSTextPosition declsEnd;
</span><span class="cx">     TreeExpression decls = 0;
</span><span class="lines">@@ -1280,12 +1281,12 @@
</span><span class="cx">         gatherLexicalVariablesIfNecessary();
</span><span class="cx">         TreeStatement result;
</span><span class="cx">         if (isOfEnumeration)
</span><del>-            result = context.createForOfLoop(location, forInTarget, expr, statement, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
</del><ins>+            result = context.createForOfLoop(location, forInTarget, expr, statement, declLocation, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
</ins><span class="cx">         else {
</span><span class="cx">             if (isVarDeclaraton &amp;&amp; forInInitializer)
</span><del>-                result = context.createForInLoop(location, decls, expr, statement, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
</del><ins>+                result = context.createForInLoop(location, decls, expr, statement, declLocation, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
</ins><span class="cx">             else
</span><del>-                result = context.createForInLoop(location, forInTarget, expr, statement, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
</del><ins>+                result = context.createForInLoop(location, forInTarget, expr, statement, declLocation, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
</ins><span class="cx">         }
</span><span class="cx">         popLexicalScopeIfNecessary();
</span><span class="cx">         return result;
</span><span class="lines">@@ -1372,17 +1373,17 @@
</span><span class="cx">     if (pattern) {
</span><span class="cx">         ASSERT(!decls);
</span><span class="cx">         if (isOfEnumeration)
</span><del>-            result = context.createForOfLoop(location, pattern, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
</del><ins>+            result = context.createForOfLoop(location, pattern, expr, statement, declLocation, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
</ins><span class="cx">         else 
</span><del>-            result = context.createForInLoop(location, pattern, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
</del><ins>+            result = context.createForInLoop(location, pattern, expr, statement, declLocation, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
</ins><span class="cx"> 
</span><span class="cx">         popLexicalScopeIfNecessary();
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="cx">     if (isOfEnumeration)
</span><del>-        result = context.createForOfLoop(location, decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
</del><ins>+        result = context.createForOfLoop(location, decls, expr, statement, declLocation, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
</ins><span class="cx">     else
</span><del>-        result = context.createForInLoop(location, decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
</del><ins>+        result = context.createForInLoop(location, decls, expr, statement, declLocation, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
</ins><span class="cx">     popLexicalScopeIfNecessary();
</span><span class="cx">     return result;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserSyntaxCheckerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/SyntaxChecker.h (207227 => 207228)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/SyntaxChecker.h        2016-10-12 18:43:19 UTC (rev 207227)
+++ trunk/Source/JavaScriptCore/parser/SyntaxChecker.h        2016-10-12 18:47:48 UTC (rev 207228)
</span><span class="lines">@@ -238,8 +238,8 @@
</span><span class="cx">     int createIfStatement(const JSTokenLocation&amp;, int, int, int, int) { return StatementResult; }
</span><span class="cx">     int createIfStatement(const JSTokenLocation&amp;, int, int, int, int, int) { return StatementResult; }
</span><span class="cx">     int createForLoop(const JSTokenLocation&amp;, int, int, int, int, int, int, VariableEnvironment&amp;) { return StatementResult; }
</span><del>-    int createForInLoop(const JSTokenLocation&amp;, int, int, int, int, int, int, int, int, VariableEnvironment&amp;) { return StatementResult; }
-    int createForOfLoop(const JSTokenLocation&amp;, int, int, int, int, int, int, int, int, VariableEnvironment&amp;) { return StatementResult; }
</del><ins>+    int createForInLoop(const JSTokenLocation&amp;, int, int, int, const JSTokenLocation&amp;, int, int, int, int, int, VariableEnvironment&amp;) { return StatementResult; }
+    int createForOfLoop(const JSTokenLocation&amp;, int, int, int, const JSTokenLocation&amp;, int, int, int, int, int, VariableEnvironment&amp;) { return StatementResult; }
</ins><span class="cx">     int createEmptyStatement(const JSTokenLocation&amp;) { return StatementResult; }
</span><span class="cx">     int createDeclarationStatement(const JSTokenLocation&amp;, int, int, int) { return StatementResult; }
</span><span class="cx">     int createReturnStatement(const JSTokenLocation&amp;, int, int, int) { return StatementResult; }
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/ChangeLog (207227 => 207228)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/ChangeLog        2016-10-12 18:43:19 UTC (rev 207227)
+++ trunk/Source/WebInspectorUI/ChangeLog        2016-10-12 18:47:48 UTC (rev 207228)
</span><span class="lines">@@ -1,5 +1,18 @@
</span><span class="cx"> 2016-10-12  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        Emit DebugHooks uniformly with pause locations instead of having separate pause locations and op_debug emits
+        https://bugs.webkit.org/show_bug.cgi?id=162809
+
+        Reviewed by Geoffrey Garen.
+
+        * UserInterface/Views/SourceCodeTextEditor.js:
+        (WebInspector.SourceCodeTextEditor.prototype.textEditorExecutionHighlightRange):
+        When pausing on the variable assignment inside for..of and for..in don't just
+        highlight &quot;var foo&quot; but include the right hand side &quot;var foo in ...&quot; or
+        &quot;var foo of ...&quot;.
+
+2016-10-12  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
+
</ins><span class="cx">         Web Inspector: Whole program sometimes highlighted instead of just first statement
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=163300
</span><span class="cx">         &lt;rdar://problem/28723162&gt;
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsSourceCodeTextEditorjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/SourceCodeTextEditor.js (207227 => 207228)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/SourceCodeTextEditor.js        2016-10-12 18:43:19 UTC (rev 207227)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/SourceCodeTextEditor.js        2016-10-12 18:47:48 UTC (rev 207228)
</span><span class="lines">@@ -1236,6 +1236,7 @@
</span><span class="cx"> 
</span><span class="cx">             // Find a node starting at this offset.
</span><span class="cx">             // Avoid highlighting the entire program if this is the start of the first statement.
</span><ins>+            // Special case the assignment expression inside of a for..of and for..in to highlight a larger range.
</ins><span class="cx">             for (let node of nodes) {
</span><span class="cx">                 let startOffset = node.range[0];
</span><span class="cx">                 if (startOffset === offset &amp;&amp; node.type !== WebInspector.ScriptSyntaxTree.NodeType.Program) {
</span><span class="lines">@@ -1242,6 +1243,12 @@
</span><span class="cx">                     callback(convertRangeOffsetsToSourceCodeOffsets(node.range));
</span><span class="cx">                     return;
</span><span class="cx">                 }
</span><ins>+                if (node.type === WebInspector.ScriptSyntaxTree.NodeType.ForInStatement || node.type === WebInspector.ScriptSyntaxTree.NodeType.ForOfStatement) {
+                    if (node.left.range[0] === offset) {
+                        callback(convertRangeOffsetsToSourceCodeOffsets([node.left.range[0], node.right.range[1]]));
+                        return;
+                    }
+                }
</ins><span class="cx">                 if (startOffset &gt; offset)
</span><span class="cx">                     break;
</span><span class="cx">             }
</span></span></pre>
</div>
</div>

</body>
</html>