<!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>[260113] 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/260113">260113</a></dd>
<dt>Author</dt> <dd>drousso@apple.com</dd>
<dt>Date</dt> <dd>2020-04-14 19:35:04 -0700 (Tue, 14 Apr 2020)</dd>
</dl>

<h3>Log Message</h3>
<pre>Web Inspector: Debugger: add a Step next that steps by expression
https://bugs.webkit.org/show_bug.cgi?id=210324

Reviewed by Timothy Hatcher.

Source/JavaScriptCore:

Step next is a hybrid of Step over and Step into which continues execution to the next pause
opportunity within the current (or ancestor) call frame. It is especially useful when trying
to debug minified code, such as trying to continue to `c()` in `a() && b() && c();`, where
Step over would continue to the next statement (i.e. after the `;`) and Step in would
continue to the first line inside `a()` (and would require a Step out to get back).

* inspector/protocol/Debugger.json:
* inspector/agents/InspectorDebuggerAgent.h:
* inspector/agents/InspectorDebuggerAgent.cpp:
(Inspector::InspectorDebuggerAgent::stepNext): Added.

* debugger/Debugger.h:
* debugger/Debugger.cpp:
(JSC::Debugger::stepNextExpression): Added.
(JSC::Debugger::atExpression):
(JSC::Debugger::clearNextPauseState):

Source/WebInspectorUI:

Step next is a hybrid of Step over and Step into which continues execution to the next pause
opportunity within the current (or ancestor) call frame. It is especially useful when trying
to debug minified code, such as trying to continue to `c()` in `a() && b() && c();`, where
Step over would continue to the next statement (i.e. after the `;`) and Step in would
continue to the first line inside `a()` (and would require a Step out to get back).

* UserInterface/Controllers/DebuggerManager.js:
(WI.DebuggerManager.prototype.stepNext): Added.

* UserInterface/Base/Main.js:
(WI.contentLoaded):
(WI.debuggerStepNext): Added.
* UserInterface/Views/SourcesNavigationSidebarPanel.js:
(WI.SourcesNavigationSidebarPanel):
(WI.SourcesNavigationSidebarPanel.prototype._handleDebuggerPaused):
(WI.SourcesNavigationSidebarPanel.prototype._handleDebuggerResumed):

* Localizations/en.lproj/localizedStrings.js:
* UserInterface/Images/StepNext.svg: Added.

LayoutTests:

* inspector/debugger/stepping/stepNext.html: Added.
* inspector/debugger/stepping/stepNext-expected.txt: Added.

* inspector/debugger/stepping/stepInto.html:
* inspector/debugger/stepping/stepInto-expected.txt:
* inspector/debugger/stepping/stepOut.html:
* inspector/debugger/stepping/stepOut-expected.txt:
* inspector/debugger/stepping/stepOver.html:
* inspector/debugger/stepping/stepOver-expected.txt:
Renamed functions for clarity and added additional test cases from other commands.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsinspectordebuggersteppingstepIntoexpectedtxt">trunk/LayoutTests/inspector/debugger/stepping/stepInto-expected.txt</a></li>
<li><a href="#trunkLayoutTestsinspectordebuggersteppingstepIntohtml">trunk/LayoutTests/inspector/debugger/stepping/stepInto.html</a></li>
<li><a href="#trunkLayoutTestsinspectordebuggersteppingstepOutexpectedtxt">trunk/LayoutTests/inspector/debugger/stepping/stepOut-expected.txt</a></li>
<li><a href="#trunkLayoutTestsinspectordebuggersteppingstepOuthtml">trunk/LayoutTests/inspector/debugger/stepping/stepOut.html</a></li>
<li><a href="#trunkLayoutTestsinspectordebuggersteppingstepOverexpectedtxt">trunk/LayoutTests/inspector/debugger/stepping/stepOver-expected.txt</a></li>
<li><a href="#trunkLayoutTestsinspectordebuggersteppingstepOverhtml">trunk/LayoutTests/inspector/debugger/stepping/stepOver.html</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoredebuggerDebuggercpp">trunk/Source/JavaScriptCore/debugger/Debugger.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredebuggerDebuggerh">trunk/Source/JavaScriptCore/debugger/Debugger.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectoragentsInspectorDebuggerAgentcpp">trunk/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectoragentsInspectorDebuggerAgenth">trunk/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectorprotocolDebuggerjson">trunk/Source/JavaScriptCore/inspector/protocol/Debugger.json</a></li>
<li><a href="#trunkSourceWebInspectorUIChangeLog">trunk/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#trunkSourceWebInspectorUILocalizationsenlprojlocalizedStringsjs">trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceBaseMainjs">trunk/Source/WebInspectorUI/UserInterface/Base/Main.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceControllersDebuggerManagerjs">trunk/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsSourcesNavigationSidebarPaneljs">trunk/Source/WebInspectorUI/UserInterface/Views/SourcesNavigationSidebarPanel.js</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsinspectordebuggersteppingstepNextexpectedtxt">trunk/LayoutTests/inspector/debugger/stepping/stepNext-expected.txt</a></li>
<li><a href="#trunkLayoutTestsinspectordebuggersteppingstepNexthtml">trunk/LayoutTests/inspector/debugger/stepping/stepNext.html</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceImagesStepNextsvg">trunk/Source/WebInspectorUI/UserInterface/Images/StepNext.svg</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (260112 => 260113)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog      2020-04-15 01:24:30 UTC (rev 260112)
+++ trunk/LayoutTests/ChangeLog 2020-04-15 02:35:04 UTC (rev 260113)
</span><span class="lines">@@ -1,3 +1,21 @@
</span><ins>+2020-04-14  Devin Rousso  <drousso@apple.com>
+
+        Web Inspector: Debugger: add a Step next that steps by expression
+        https://bugs.webkit.org/show_bug.cgi?id=210324
+
+        Reviewed by Timothy Hatcher.
+
+        * inspector/debugger/stepping/stepNext.html: Added.
+        * inspector/debugger/stepping/stepNext-expected.txt: Added.
+
+        * inspector/debugger/stepping/stepInto.html:
+        * inspector/debugger/stepping/stepInto-expected.txt:
+        * inspector/debugger/stepping/stepOut.html:
+        * inspector/debugger/stepping/stepOut-expected.txt:
+        * inspector/debugger/stepping/stepOver.html:
+        * inspector/debugger/stepping/stepOver-expected.txt:
+        Renamed functions for clarity and added additional test cases from other commands.
+
</ins><span class="cx"> 2020-04-14  Diego Pino Garcia  <dpino@igalia.com>
</span><span class="cx"> 
</span><span class="cx">         [GTK] Gardening, update expectations after r260062
</span></span></pre></div>
<a id="trunkLayoutTestsinspectordebuggersteppingstepIntoexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/inspector/debugger/stepping/stepInto-expected.txt (260112 => 260113)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/debugger/stepping/stepInto-expected.txt      2020-04-15 01:24:30 UTC (rev 260112)
+++ trunk/LayoutTests/inspector/debugger/stepping/stepInto-expected.txt 2020-04-15 02:35:04 UTC (rev 260113)
</span><span class="lines">@@ -1,4 +1,3 @@
</span><del>-ALERT: log 1
</del><span class="cx"> Checking pause locations when stepping with "stepInto".
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -5,18 +4,18 @@
</span><span class="cx"> == Running test suite: Debugger.stepInto
</span><span class="cx"> -- Running test case: Debugger.stepInto.statements
</span><span class="cx"> PAUSED (debugger-statement)
</span><del>-PAUSE AT entry1:12:5
-      8    }
</del><ins>+PAUSE AT testStatements:12:5
+      8    function c() { return "c"; }
</ins><span class="cx">       9    
</span><del>-     10    function entry1() {
</del><ins>+     10    function testStatements() {
</ins><span class="cx">  ->  11        |debugger;
</span><span class="cx">      12        let x = 1;
</span><span class="cx">      13        let y = 2;
</span><span class="cx">      14    }
</span><span class="cx"> 
</span><del>-PAUSE AT entry1:13:5
</del><ins>+PAUSE AT testStatements:13:5
</ins><span class="cx">       9    
</span><del>-     10    function entry1() {
</del><ins>+     10    function testStatements() {
</ins><span class="cx">      11        debugger;
</span><span class="cx">  ->  12        |let x = 1;
</span><span class="cx">      13        let y = 2;
</span><span class="lines">@@ -23,22 +22,22 @@
</span><span class="cx">      14    }
</span><span class="cx">      15    
</span><span class="cx"> 
</span><del>-PAUSE AT entry1:14:5
-     10    function entry1() {
</del><ins>+PAUSE AT testStatements:14:5
+     10    function testStatements() {
</ins><span class="cx">      11        debugger;
</span><span class="cx">      12        let x = 1;
</span><span class="cx">  ->  13        |let y = 2;
</span><span class="cx">      14    }
</span><span class="cx">      15    
</span><del>-     16    function entry2() {
</del><ins>+     16    function testFunctions() {
</ins><span class="cx"> 
</span><del>-PAUSE AT entry1:15:2
</del><ins>+PAUSE AT testStatements:15:2
</ins><span class="cx">      11        debugger;
</span><span class="cx">      12        let x = 1;
</span><span class="cx">      13        let y = 2;
</span><span class="cx">  ->  14    }|
</span><span class="cx">      15    
</span><del>-     16    function entry2() {
</del><ins>+     16    function testFunctions() {
</ins><span class="cx">      17        debugger;
</span><span class="cx"> 
</span><span class="cx"> RESUMED
</span><span class="lines">@@ -45,67 +44,67 @@
</span><span class="cx"> 
</span><span class="cx"> -- Running test case: Debugger.stepInto.function
</span><span class="cx"> PAUSED (debugger-statement)
</span><del>-PAUSE AT entry2:18:5
</del><ins>+PAUSE AT testFunctions:18:5
</ins><span class="cx">      14    }
</span><span class="cx">      15    
</span><del>-     16    function entry2() {
</del><ins>+     16    function testFunctions() {
</ins><span class="cx">  ->  17        |debugger;
</span><span class="cx">      18        let before = 1;
</span><del>-     19        testAlert("log 1");
</del><ins>+     19        a();
</ins><span class="cx">      20        let after = 2;
</span><span class="cx"> 
</span><del>-PAUSE AT entry2:19:5
</del><ins>+PAUSE AT testFunctions:19:5
</ins><span class="cx">      15    
</span><del>-     16    function entry2() {
</del><ins>+     16    function testFunctions() {
</ins><span class="cx">      17        debugger;
</span><span class="cx">  ->  18        |let before = 1;
</span><del>-     19        testAlert("log 1");
</del><ins>+     19        a();
</ins><span class="cx">      20        let after = 2;
</span><span class="cx">      21    }
</span><span class="cx"> 
</span><del>-PAUSE AT entry2:20:5
-     16    function entry2() {
</del><ins>+PAUSE AT testFunctions:20:5
+     16    function testFunctions() {
</ins><span class="cx">      17        debugger;
</span><span class="cx">      18        let before = 1;
</span><del>- ->  19        |testAlert("log 1");
</del><ins>+ ->  19        |a();
</ins><span class="cx">      20        let after = 2;
</span><span class="cx">      21    }
</span><span class="cx">      22    
</span><span class="cx"> 
</span><del>-PAUSE AT testAlert:8:5
</del><ins>+PAUSE AT a:7:16
+      3    <script src="../../../http/tests/inspector/resources/inspector-test.js"></script>
</ins><span class="cx">       4    <script src="../resources/log-pause-location.js"></script>
</span><span class="cx">       5    <script>
</span><del>-      6    function testAlert(str) {
- ->   7        |alert(str);
-      8    }
</del><ins>+ ->   6    function a() { |return "a"; }
+      7    function b() { return "b"; }
+      8    function c() { return "c"; }
</ins><span class="cx">       9    
</span><del>-     10    function entry1() {
</del><span class="cx"> 
</span><del>-PAUSE AT testAlert:9:2
</del><ins>+PAUSE AT a:7:29
+      3    <script src="../../../http/tests/inspector/resources/inspector-test.js"></script>
+      4    <script src="../resources/log-pause-location.js"></script>
</ins><span class="cx">       5    <script>
</span><del>-      6    function testAlert(str) {
-      7        alert(str);
- ->   8    }|
</del><ins>+ ->   6    function a() { return "a"; }|
+      7    function b() { return "b"; }
+      8    function c() { return "c"; }
</ins><span class="cx">       9    
</span><del>-     10    function entry1() {
-     11        debugger;
</del><span class="cx"> 
</span><del>-PAUSE AT entry2:21:5
</del><ins>+PAUSE AT testFunctions:21:5
</ins><span class="cx">      17        debugger;
</span><span class="cx">      18        let before = 1;
</span><del>-     19        testAlert("log 1");
</del><ins>+     19        a();
</ins><span class="cx">  ->  20        |let after = 2;
</span><span class="cx">      21    }
</span><span class="cx">      22    
</span><del>-     23    function entry3() {
</del><ins>+     23    function testEval() {
</ins><span class="cx"> 
</span><del>-PAUSE AT entry2:22:2
</del><ins>+PAUSE AT testFunctions:22:2
</ins><span class="cx">      18        let before = 1;
</span><del>-     19        testAlert("log 1");
</del><ins>+     19        a();
</ins><span class="cx">      20        let after = 2;
</span><span class="cx">  ->  21    }|
</span><span class="cx">      22    
</span><del>-     23    function entry3() {
</del><ins>+     23    function testEval() {
</ins><span class="cx">      24        debugger;
</span><span class="cx"> 
</span><span class="cx"> RESUMED
</span><span class="lines">@@ -112,18 +111,18 @@
</span><span class="cx"> 
</span><span class="cx"> -- Running test case: Debugger.stepInto.eval
</span><span class="cx"> PAUSED (debugger-statement)
</span><del>-PAUSE AT entry3:25:5
</del><ins>+PAUSE AT testEval:25:5
</ins><span class="cx">      21    }
</span><span class="cx">      22    
</span><del>-     23    function entry3() {
</del><ins>+     23    function testEval() {
</ins><span class="cx">  ->  24        |debugger;
</span><span class="cx">      25        let before = 1;
</span><span class="cx">      26        eval("1 + 1");
</span><span class="cx">      27        let after = 2;
</span><span class="cx"> 
</span><del>-PAUSE AT entry3:26:5
</del><ins>+PAUSE AT testEval:26:5
</ins><span class="cx">      22    
</span><del>-     23    function entry3() {
</del><ins>+     23    function testEval() {
</ins><span class="cx">      24        debugger;
</span><span class="cx">  ->  25        |let before = 1;
</span><span class="cx">      26        eval("1 + 1");
</span><span class="lines">@@ -130,8 +129,8 @@
</span><span class="cx">      27        let after = 2;
</span><span class="cx">      28    }
</span><span class="cx"> 
</span><del>-PAUSE AT entry3:27:5
-     23    function entry3() {
</del><ins>+PAUSE AT testEval:27:5
+     23    function testEval() {
</ins><span class="cx">      24        debugger;
</span><span class="cx">      25        let before = 1;
</span><span class="cx">  ->  26        |eval("1 + 1");
</span><span class="lines">@@ -145,7 +144,7 @@
</span><span class="cx"> PAUSE AT Eval Code:1:6
</span><span class="cx"> --- Source Unavailable ---
</span><span class="cx"> 
</span><del>-PAUSE AT entry3:28:5
</del><ins>+PAUSE AT testEval:28:5
</ins><span class="cx">      24        debugger;
</span><span class="cx">      25        let before = 1;
</span><span class="cx">      26        eval("1 + 1");
</span><span class="lines">@@ -152,15 +151,15 @@
</span><span class="cx">  ->  27        |let after = 2;
</span><span class="cx">      28    }
</span><span class="cx">      29    
</span><del>-     30    function entry4() {
</del><ins>+     30    function testInnerFunction() {
</ins><span class="cx"> 
</span><del>-PAUSE AT entry3:29:2
</del><ins>+PAUSE AT testEval:29:2
</ins><span class="cx">      25        let before = 1;
</span><span class="cx">      26        eval("1 + 1");
</span><span class="cx">      27        let after = 2;
</span><span class="cx">  ->  28    }|
</span><span class="cx">      29    
</span><del>-     30    function entry4() {
</del><ins>+     30    function testInnerFunction() {
</ins><span class="cx">      31        (function() {
</span><span class="cx"> 
</span><span class="cx"> RESUMED
</span><span class="lines">@@ -169,7 +168,7 @@
</span><span class="cx"> PAUSED (debugger-statement)
</span><span class="cx"> PAUSE AT <anonymous>:33:9
</span><span class="cx">      29    
</span><del>-     30    function entry4() {
</del><ins>+     30    function testInnerFunction() {
</ins><span class="cx">      31        (function() {
</span><span class="cx">  ->  32            |debugger;
</span><span class="cx">      33            let inner = 1;
</span><span class="lines">@@ -177,7 +176,7 @@
</span><span class="cx">      35        let outer = 2;
</span><span class="cx"> 
</span><span class="cx"> PAUSE AT <anonymous>:34:9
</span><del>-     30    function entry4() {
</del><ins>+     30    function testInnerFunction() {
</ins><span class="cx">      31        (function() {
</span><span class="cx">      32            debugger;
</span><span class="cx">  ->  33            |let inner = 1;
</span><span class="lines">@@ -194,7 +193,7 @@
</span><span class="cx">      36    }
</span><span class="cx">      37    
</span><span class="cx"> 
</span><del>-PAUSE AT entry4:36:5
</del><ins>+PAUSE AT testInnerFunction:36:5
</ins><span class="cx">      32            debugger;
</span><span class="cx">      33            let inner = 1;
</span><span class="cx">      34        })();
</span><span class="lines">@@ -201,16 +200,339 @@
</span><span class="cx">  ->  35        |let outer = 2;
</span><span class="cx">      36    }
</span><span class="cx">      37    
</span><del>-     38    // ---------
</del><ins>+     38    function testCommas() {
</ins><span class="cx"> 
</span><del>-PAUSE AT entry4:37:2
</del><ins>+PAUSE AT testInnerFunction:37:2
</ins><span class="cx">      33            let inner = 1;
</span><span class="cx">      34        })();
</span><span class="cx">      35        let outer = 2;
</span><span class="cx">  ->  36    }|
</span><span class="cx">      37    
</span><del>-     38    // ---------
-     39    
</del><ins>+     38    function testCommas() {
+     39        debugger;
</ins><span class="cx"> 
</span><span class="cx"> RESUMED
</span><span class="cx"> 
</span><ins>+-- Running test case: Debugger.stepInto.commas
+PAUSED (debugger-statement)
+PAUSE AT testCommas:40:5
+     36    }
+     37    
+     38    function testCommas() {
+ ->  39        |debugger;
+     40        let x = 1,
+     41            y = 2,
+     42            z = 3;
+
+PAUSE AT testCommas:41:5
+     37    
+     38    function testCommas() {
+     39        debugger;
+ ->  40        |let x = 1,
+     41            y = 2,
+     42            z = 3;
+     43        a(), b(), c();
+
+PAUSE AT testCommas:42:9
+     38    function testCommas() {
+     39        debugger;
+     40        let x = 1,
+ ->  41            |y = 2,
+     42            z = 3;
+     43        a(), b(), c();
+     44        true && (a(), b(), c());
+
+PAUSE AT testCommas:43:9
+     39        debugger;
+     40        let x = 1,
+     41            y = 2,
+ ->  42            |z = 3;
+     43        a(), b(), c();
+     44        true && (a(), b(), c());
+     45    }
+
+PAUSE AT testCommas:44:5
+     40        let x = 1,
+     41            y = 2,
+     42            z = 3;
+ ->  43        |a(), b(), c();
+     44        true && (a(), b(), c());
+     45    }
+     46    
+
+PAUSE AT a:7:16
+      3    <script src="../../../http/tests/inspector/resources/inspector-test.js"></script>
+      4    <script src="../resources/log-pause-location.js"></script>
+      5    <script>
+ ->   6    function a() { |return "a"; }
+      7    function b() { return "b"; }
+      8    function c() { return "c"; }
+      9    
+
+PAUSE AT a:7:29
+      3    <script src="../../../http/tests/inspector/resources/inspector-test.js"></script>
+      4    <script src="../resources/log-pause-location.js"></script>
+      5    <script>
+ ->   6    function a() { return "a"; }|
+      7    function b() { return "b"; }
+      8    function c() { return "c"; }
+      9    
+
+PAUSE AT testCommas:44:10
+     40        let x = 1,
+     41            y = 2,
+     42            z = 3;
+ ->  43        a(), |b(), c();
+     44        true && (a(), b(), c());
+     45    }
+     46    
+
+PAUSE AT b:8:16
+      4    <script src="../resources/log-pause-location.js"></script>
+      5    <script>
+      6    function a() { return "a"; }
+ ->   7    function b() { |return "b"; }
+      8    function c() { return "c"; }
+      9    
+     10    function testStatements() {
+
+PAUSE AT b:8:29
+      4    <script src="../resources/log-pause-location.js"></script>
+      5    <script>
+      6    function a() { return "a"; }
+ ->   7    function b() { return "b"; }|
+      8    function c() { return "c"; }
+      9    
+     10    function testStatements() {
+
+PAUSE AT testCommas:44:15
+     40        let x = 1,
+     41            y = 2,
+     42            z = 3;
+ ->  43        a(), b(), |c();
+     44        true && (a(), b(), c());
+     45    }
+     46    
+
+PAUSE AT c:9:16
+      5    <script>
+      6    function a() { return "a"; }
+      7    function b() { return "b"; }
+ ->   8    function c() { |return "c"; }
+      9    
+     10    function testStatements() {
+     11        debugger;
+
+PAUSE AT c:9:29
+      5    <script>
+      6    function a() { return "a"; }
+      7    function b() { return "b"; }
+ ->   8    function c() { return "c"; }|
+      9    
+     10    function testStatements() {
+     11        debugger;
+
+PAUSE AT testCommas:45:5
+     41            y = 2,
+     42            z = 3;
+     43        a(), b(), c();
+ ->  44        |true && (a(), b(), c());
+     45    }
+     46    
+     47    function testChainedExpressions() {
+
+PAUSE AT testCommas:45:14
+     41            y = 2,
+     42            z = 3;
+     43        a(), b(), c();
+ ->  44        true && (|a(), b(), c());
+     45    }
+     46    
+     47    function testChainedExpressions() {
+
+PAUSE AT a:7:16
+      3    <script src="../../../http/tests/inspector/resources/inspector-test.js"></script>
+      4    <script src="../resources/log-pause-location.js"></script>
+      5    <script>
+ ->   6    function a() { |return "a"; }
+      7    function b() { return "b"; }
+      8    function c() { return "c"; }
+      9    
+
+PAUSE AT a:7:29
+      3    <script src="../../../http/tests/inspector/resources/inspector-test.js"></script>
+      4    <script src="../resources/log-pause-location.js"></script>
+      5    <script>
+ ->   6    function a() { return "a"; }|
+      7    function b() { return "b"; }
+      8    function c() { return "c"; }
+      9    
+
+PAUSE AT testCommas:45:19
+     41            y = 2,
+     42            z = 3;
+     43        a(), b(), c();
+ ->  44        true && (a(), |b(), c());
+     45    }
+     46    
+     47    function testChainedExpressions() {
+
+PAUSE AT b:8:16
+      4    <script src="../resources/log-pause-location.js"></script>
+      5    <script>
+      6    function a() { return "a"; }
+ ->   7    function b() { |return "b"; }
+      8    function c() { return "c"; }
+      9    
+     10    function testStatements() {
+
+PAUSE AT b:8:29
+      4    <script src="../resources/log-pause-location.js"></script>
+      5    <script>
+      6    function a() { return "a"; }
+ ->   7    function b() { return "b"; }|
+      8    function c() { return "c"; }
+      9    
+     10    function testStatements() {
+
+PAUSE AT testCommas:45:24
+     41            y = 2,
+     42            z = 3;
+     43        a(), b(), c();
+ ->  44        true && (a(), b(), |c());
+     45    }
+     46    
+     47    function testChainedExpressions() {
+
+PAUSE AT c:9:16
+      5    <script>
+      6    function a() { return "a"; }
+      7    function b() { return "b"; }
+ ->   8    function c() { |return "c"; }
+      9    
+     10    function testStatements() {
+     11        debugger;
+
+PAUSE AT c:9:29
+      5    <script>
+      6    function a() { return "a"; }
+      7    function b() { return "b"; }
+ ->   8    function c() { return "c"; }|
+      9    
+     10    function testStatements() {
+     11        debugger;
+
+PAUSE AT testCommas:46:2
+     42            z = 3;
+     43        a(), b(), c();
+     44        true && (a(), b(), c());
+ ->  45    }|
+     46    
+     47    function testChainedExpressions() {
+     48        debugger;
+
+RESUMED
+
+-- Running test case: Debugger.stepInto.chainedExpressions
+PAUSED (debugger-statement)
+PAUSE AT testChainedExpressions:49:5
+     45    }
+     46    
+     47    function testChainedExpressions() {
+ ->  48        |debugger;
+     49        a() && b() && c();
+     50    }
+     51    
+
+PAUSE AT testChainedExpressions:50:5
+     46    
+     47    function testChainedExpressions() {
+     48        debugger;
+ ->  49        |a() && b() && c();
+     50    }
+     51    
+     52    // ---------
+
+PAUSE AT a:7:16
+      3    <script src="../../../http/tests/inspector/resources/inspector-test.js"></script>
+      4    <script src="../resources/log-pause-location.js"></script>
+      5    <script>
+ ->   6    function a() { |return "a"; }
+      7    function b() { return "b"; }
+      8    function c() { return "c"; }
+      9    
+
+PAUSE AT a:7:29
+      3    <script src="../../../http/tests/inspector/resources/inspector-test.js"></script>
+      4    <script src="../resources/log-pause-location.js"></script>
+      5    <script>
+ ->   6    function a() { return "a"; }|
+      7    function b() { return "b"; }
+      8    function c() { return "c"; }
+      9    
+
+PAUSE AT testChainedExpressions:50:12
+     46    
+     47    function testChainedExpressions() {
+     48        debugger;
+ ->  49        a() && |b() && c();
+     50    }
+     51    
+     52    // ---------
+
+PAUSE AT b:8:16
+      4    <script src="../resources/log-pause-location.js"></script>
+      5    <script>
+      6    function a() { return "a"; }
+ ->   7    function b() { |return "b"; }
+      8    function c() { return "c"; }
+      9    
+     10    function testStatements() {
+
+PAUSE AT b:8:29
+      4    <script src="../resources/log-pause-location.js"></script>
+      5    <script>
+      6    function a() { return "a"; }
+ ->   7    function b() { return "b"; }|
+      8    function c() { return "c"; }
+      9    
+     10    function testStatements() {
+
+PAUSE AT testChainedExpressions:50:19
+     46    
+     47    function testChainedExpressions() {
+     48        debugger;
+ ->  49        a() && b() && |c();
+     50    }
+     51    
+     52    // ---------
+
+PAUSE AT c:9:16
+      5    <script>
+      6    function a() { return "a"; }
+      7    function b() { return "b"; }
+ ->   8    function c() { |return "c"; }
+      9    
+     10    function testStatements() {
+     11        debugger;
+
+PAUSE AT c:9:29
+      5    <script>
+      6    function a() { return "a"; }
+      7    function b() { return "b"; }
+ ->   8    function c() { return "c"; }|
+      9    
+     10    function testStatements() {
+     11        debugger;
+
+PAUSE AT testChainedExpressions:51:2
+     47    function testChainedExpressions() {
+     48        debugger;
+     49        a() && b() && c();
+ ->  50    }|
+     51    
+     52    // ---------
+     53    
+
+RESUMED
+
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectordebuggersteppingstepIntohtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/inspector/debugger/stepping/stepInto.html (260112 => 260113)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/debugger/stepping/stepInto.html      2020-04-15 01:24:30 UTC (rev 260112)
+++ trunk/LayoutTests/inspector/debugger/stepping/stepInto.html 2020-04-15 02:35:04 UTC (rev 260113)
</span><span class="lines">@@ -4,24 +4,24 @@
</span><span class="cx"> <script src="../../../http/tests/inspector/resources/inspector-test.js"></script>
</span><span class="cx"> <script src="../resources/log-pause-location.js"></script>
</span><span class="cx"> <script>
</span><del>-function testAlert(str) {
-    alert(str);
-}
</del><ins>+function a() { return "a"; }
+function b() { return "b"; }
+function c() { return "c"; }
</ins><span class="cx"> 
</span><del>-function entry1() {
</del><ins>+function testStatements() {
</ins><span class="cx">     debugger;
</span><span class="cx">     let x = 1;
</span><span class="cx">     let y = 2;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-function entry2() {
</del><ins>+function testFunctions() {
</ins><span class="cx">     debugger;
</span><span class="cx">     let before = 1;
</span><del>-    testAlert("log 1");
</del><ins>+    a();
</ins><span class="cx">     let after = 2;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-function entry3() {
</del><ins>+function testEval() {
</ins><span class="cx">     debugger;
</span><span class="cx">     let before = 1;
</span><span class="cx">     eval("1 + 1");
</span><span class="lines">@@ -28,7 +28,7 @@
</span><span class="cx">     let after = 2;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-function entry4() {
</del><ins>+function testInnerFunction() {
</ins><span class="cx">     (function() {
</span><span class="cx">         debugger;
</span><span class="cx">         let inner = 1;
</span><span class="lines">@@ -36,6 +36,20 @@
</span><span class="cx">     let outer = 2;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+function testCommas() {
+    debugger;
+    let x = 1,
+        y = 2,
+        z = 3;
+    a(), b(), c();
+    true && (a(), b(), c());
+}
+
+function testChainedExpressions() {
+    debugger;
+    a() && b() && c();
+}
+
</ins><span class="cx"> // ---------
</span><span class="cx"> 
</span><span class="cx"> function test()
</span><span class="lines">@@ -69,27 +83,39 @@
</span><span class="cx">     addTestCase({
</span><span class="cx">         name: "Debugger.stepInto.statements",
</span><span class="cx">         description: "step-into should step over statements.",
</span><del>-        expression: "setTimeout(entry1)",
</del><ins>+        expression: "setTimeout(testStatements)",
</ins><span class="cx">     });
</span><span class="cx"> 
</span><span class="cx">     addTestCase({
</span><span class="cx">         name: "Debugger.stepInto.function",
</span><span class="cx">         description: "step-into should step into function calls.",
</span><del>-        expression: "setTimeout(entry2)",
</del><ins>+        expression: "setTimeout(testFunctions)",
</ins><span class="cx">     });
</span><span class="cx"> 
</span><span class="cx">     addTestCase({
</span><span class="cx">         name: "Debugger.stepInto.eval",
</span><span class="cx">         description: "step-into should step into an eval program.",
</span><del>-        expression: "setTimeout(entry3)",
</del><ins>+        expression: "setTimeout(testEval)",
</ins><span class="cx">     });
</span><span class="cx"> 
</span><span class="cx">     addTestCase({
</span><span class="cx">         name: "Debugger.stepInto.innerFunction",
</span><span class="cx">         description: "step-into should step out of a function to its caller.",
</span><del>-        expression: "setTimeout(entry4)",
</del><ins>+        expression: "setTimeout(testInnerFunction)",
</ins><span class="cx">     });
</span><span class="cx"> 
</span><ins>+    addTestCase({
+        name: "Debugger.stepInto.commas",
+        description: "step-into should step into each sub-expression within comma expressions.",
+        expression: "setTimeout(testCommas)",
+    });
+
+    addTestCase({
+        name: "Debugger.stepInto.chainedExpressions",
+        description: "step-into should step into each sub-expression within chained expressions.",
+        expression: "setTimeout(testChainedExpressions)",
+    });
+
</ins><span class="cx">     loadMainPageContent().then(() => {
</span><span class="cx">         suite.runTestCasesAndFinish();
</span><span class="cx">     });
</span></span></pre></div>
<a id="trunkLayoutTestsinspectordebuggersteppingstepNextexpectedtxtfromrev260112trunkLayoutTestsinspectordebuggersteppingstepOverexpectedtxt"></a>
<div class="copfile"><h4>Copied: trunk/LayoutTests/inspector/debugger/stepping/stepNext-expected.txt (from rev 260112, trunk/LayoutTests/inspector/debugger/stepping/stepOver-expected.txt) (0 => 260113)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/debugger/stepping/stepNext-expected.txt                              (rev 0)
+++ trunk/LayoutTests/inspector/debugger/stepping/stepNext-expected.txt 2020-04-15 02:35:04 UTC (rev 260113)
</span><span class="lines">@@ -0,0 +1,352 @@
</span><ins>+Checking pause locations when stepping with "stepNext".
+
+
+== Running test suite: Debugger.stepNext
+-- Running test case: Debugger.stepNext.statements
+PAUSED (debugger-statement)
+PAUSE AT testStatements:12:5
+      8    function c() { return "c"; }
+      9    
+     10    function testStatements() {
+ ->  11        |debugger;
+     12        let x = 1;
+     13        let y = 2;
+     14    }
+
+PAUSE AT testStatements:13:5
+      9    
+     10    function testStatements() {
+     11        debugger;
+ ->  12        |let x = 1;
+     13        let y = 2;
+     14    }
+     15    
+
+PAUSE AT testStatements:14:5
+     10    function testStatements() {
+     11        debugger;
+     12        let x = 1;
+ ->  13        |let y = 2;
+     14    }
+     15    
+     16    function testFunctions() {
+
+PAUSE AT testStatements:15:2
+     11        debugger;
+     12        let x = 1;
+     13        let y = 2;
+ ->  14    }|
+     15    
+     16    function testFunctions() {
+     17        debugger;
+
+RESUMED
+
+-- Running test case: Debugger.stepNext.function
+PAUSED (debugger-statement)
+PAUSE AT testFunctions:18:5
+     14    }
+     15    
+     16    function testFunctions() {
+ ->  17        |debugger;
+     18        let before = 1;
+     19        a();
+     20        let after = 2;
+
+PAUSE AT testFunctions:19:5
+     15    
+     16    function testFunctions() {
+     17        debugger;
+ ->  18        |let before = 1;
+     19        a();
+     20        let after = 2;
+     21    }
+
+PAUSE AT testFunctions:20:5
+     16    function testFunctions() {
+     17        debugger;
+     18        let before = 1;
+ ->  19        |a();
+     20        let after = 2;
+     21    }
+     22    
+
+PAUSE AT testFunctions:21:5
+     17        debugger;
+     18        let before = 1;
+     19        a();
+ ->  20        |let after = 2;
+     21    }
+     22    
+     23    function testEval() {
+
+PAUSE AT testFunctions:22:2
+     18        let before = 1;
+     19        a();
+     20        let after = 2;
+ ->  21    }|
+     22    
+     23    function testEval() {
+     24        debugger;
+
+RESUMED
+
+-- Running test case: Debugger.stepNext.eval
+PAUSED (debugger-statement)
+PAUSE AT testEval:25:5
+     21    }
+     22    
+     23    function testEval() {
+ ->  24        |debugger;
+     25        let before = 1;
+     26        eval("1 + 1");
+     27        let after = 2;
+
+PAUSE AT testEval:26:5
+     22    
+     23    function testEval() {
+     24        debugger;
+ ->  25        |let before = 1;
+     26        eval("1 + 1");
+     27        let after = 2;
+     28    }
+
+PAUSE AT testEval:27:5
+     23    function testEval() {
+     24        debugger;
+     25        let before = 1;
+ ->  26        |eval("1 + 1");
+     27        let after = 2;
+     28    }
+     29    
+
+PAUSE AT testEval:28:5
+     24        debugger;
+     25        let before = 1;
+     26        eval("1 + 1");
+ ->  27        |let after = 2;
+     28    }
+     29    
+     30    function testInnerFunction() {
+
+PAUSE AT testEval:29:2
+     25        let before = 1;
+     26        eval("1 + 1");
+     27        let after = 2;
+ ->  28    }|
+     29    
+     30    function testInnerFunction() {
+     31        (function() {
+
+RESUMED
+
+-- Running test case: Debugger.stepNext.innerFunction
+PAUSED (debugger-statement)
+PAUSE AT <anonymous>:33:9
+     29    
+     30    function testInnerFunction() {
+     31        (function() {
+ ->  32            |debugger;
+     33            let inner = 1;
+     34        })();
+     35        let outer = 2;
+
+PAUSE AT <anonymous>:34:9
+     30    function testInnerFunction() {
+     31        (function() {
+     32            debugger;
+ ->  33            |let inner = 1;
+     34        })();
+     35        let outer = 2;
+     36    }
+
+PAUSE AT <anonymous>:35:6
+     31        (function() {
+     32            debugger;
+     33            let inner = 1;
+ ->  34        }|)();
+     35        let outer = 2;
+     36    }
+     37    
+
+PAUSE AT testInnerFunction:36:5
+     32            debugger;
+     33            let inner = 1;
+     34        })();
+ ->  35        |let outer = 2;
+     36    }
+     37    
+     38    function testCommas() {
+
+PAUSE AT testInnerFunction:37:2
+     33            let inner = 1;
+     34        })();
+     35        let outer = 2;
+ ->  36    }|
+     37    
+     38    function testCommas() {
+     39        debugger;
+
+RESUMED
+
+-- Running test case: Debugger.stepNext.commas
+PAUSED (debugger-statement)
+PAUSE AT testCommas:40:5
+     36    }
+     37    
+     38    function testCommas() {
+ ->  39        |debugger;
+     40        let x = 1,
+     41            y = 2,
+     42            z = 3;
+
+PAUSE AT testCommas:41:5
+     37    
+     38    function testCommas() {
+     39        debugger;
+ ->  40        |let x = 1,
+     41            y = 2,
+     42            z = 3;
+     43        a(), b(), c();
+
+PAUSE AT testCommas:42:9
+     38    function testCommas() {
+     39        debugger;
+     40        let x = 1,
+ ->  41            |y = 2,
+     42            z = 3;
+     43        a(), b(), c();
+     44        true && (a(), b(), c());
+
+PAUSE AT testCommas:43:9
+     39        debugger;
+     40        let x = 1,
+     41            y = 2,
+ ->  42            |z = 3;
+     43        a(), b(), c();
+     44        true && (a(), b(), c());
+     45    }
+
+PAUSE AT testCommas:44:5
+     40        let x = 1,
+     41            y = 2,
+     42            z = 3;
+ ->  43        |a(), b(), c();
+     44        true && (a(), b(), c());
+     45    }
+     46    
+
+PAUSE AT testCommas:44:10
+     40        let x = 1,
+     41            y = 2,
+     42            z = 3;
+ ->  43        a(), |b(), c();
+     44        true && (a(), b(), c());
+     45    }
+     46    
+
+PAUSE AT testCommas:44:15
+     40        let x = 1,
+     41            y = 2,
+     42            z = 3;
+ ->  43        a(), b(), |c();
+     44        true && (a(), b(), c());
+     45    }
+     46    
+
+PAUSE AT testCommas:45:5
+     41            y = 2,
+     42            z = 3;
+     43        a(), b(), c();
+ ->  44        |true && (a(), b(), c());
+     45    }
+     46    
+     47    function testChainedExpressions() {
+
+PAUSE AT testCommas:45:14
+     41            y = 2,
+     42            z = 3;
+     43        a(), b(), c();
+ ->  44        true && (|a(), b(), c());
+     45    }
+     46    
+     47    function testChainedExpressions() {
+
+PAUSE AT testCommas:45:19
+     41            y = 2,
+     42            z = 3;
+     43        a(), b(), c();
+ ->  44        true && (a(), |b(), c());
+     45    }
+     46    
+     47    function testChainedExpressions() {
+
+PAUSE AT testCommas:45:24
+     41            y = 2,
+     42            z = 3;
+     43        a(), b(), c();
+ ->  44        true && (a(), b(), |c());
+     45    }
+     46    
+     47    function testChainedExpressions() {
+
+PAUSE AT testCommas:46:2
+     42            z = 3;
+     43        a(), b(), c();
+     44        true && (a(), b(), c());
+ ->  45    }|
+     46    
+     47    function testChainedExpressions() {
+     48        debugger;
+
+RESUMED
+
+-- Running test case: Debugger.stepNext.chainedExpressions
+PAUSED (debugger-statement)
+PAUSE AT testChainedExpressions:49:5
+     45    }
+     46    
+     47    function testChainedExpressions() {
+ ->  48        |debugger;
+     49        a() && b() && c();
+     50    }
+     51    
+
+PAUSE AT testChainedExpressions:50:5
+     46    
+     47    function testChainedExpressions() {
+     48        debugger;
+ ->  49        |a() && b() && c();
+     50    }
+     51    
+     52    // ---------
+
+PAUSE AT testChainedExpressions:50:12
+     46    
+     47    function testChainedExpressions() {
+     48        debugger;
+ ->  49        a() && |b() && c();
+     50    }
+     51    
+     52    // ---------
+
+PAUSE AT testChainedExpressions:50:19
+     46    
+     47    function testChainedExpressions() {
+     48        debugger;
+ ->  49        a() && b() && |c();
+     50    }
+     51    
+     52    // ---------
+
+PAUSE AT testChainedExpressions:51:2
+     47    function testChainedExpressions() {
+     48        debugger;
+     49        a() && b() && c();
+ ->  50    }|
+     51    
+     52    // ---------
+     53    
+
+RESUMED
+
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectordebuggersteppingstepNexthtmlfromrev260112trunkLayoutTestsinspectordebuggersteppingstepOverhtml"></a>
<div class="copfile"><h4>Copied: trunk/LayoutTests/inspector/debugger/stepping/stepNext.html (from rev 260112, trunk/LayoutTests/inspector/debugger/stepping/stepOver.html) (0 => 260113)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/debugger/stepping/stepNext.html                              (rev 0)
+++ trunk/LayoutTests/inspector/debugger/stepping/stepNext.html 2020-04-15 02:35:04 UTC (rev 260113)
</span><span class="lines">@@ -0,0 +1,128 @@
</span><ins>+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../../http/tests/inspector/resources/inspector-test.js"></script>
+<script src="../resources/log-pause-location.js"></script>
+<script>
+function a() { return "a"; }
+function b() { return "b"; }
+function c() { return "c"; }
+
+function testStatements() {
+    debugger;
+    let x = 1;
+    let y = 2;
+}
+
+function testFunctions() {
+    debugger;
+    let before = 1;
+    a();
+    let after = 2;
+}
+
+function testEval() {
+    debugger;
+    let before = 1;
+    eval("1 + 1");
+    let after = 2;
+}
+
+function testInnerFunction() {
+    (function() {
+        debugger;
+        let inner = 1;
+    })();
+    let outer = 2;
+}
+
+function testCommas() {
+    debugger;
+    let x = 1,
+        y = 2,
+        z = 3;
+    a(), b(), c();
+    true && (a(), b(), c());
+}
+
+function testChainedExpressions() {
+    debugger;
+    a() && b() && c();
+}
+
+// ---------
+
+function test()
+{
+    let suite = InspectorTest.createAsyncSuite("Debugger.stepNext");
+
+    // Always step-next when call frames change.
+    WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.CallFramesDidChange, (event) => {
+        if (!WI.debuggerManager.activeCallFrame)
+            return;
+        logPauseLocation();
+        WI.debuggerManager.stepNext();
+    });
+
+    function addTestCase({name, description, expression}) {
+        suite.addTestCase({
+            name, description,
+            test(resolve, reject) {
+                InspectorTest.evaluateInPage(expression);
+                WI.debuggerManager.singleFireEventListener(WI.DebuggerManager.Event.Paused, (event) => {
+                    InspectorTest.log(`PAUSED (${WI.debuggerManager.dataForTarget(WI.debuggerManager.activeCallFrame.target).pauseReason})`);
+                });
+                WI.debuggerManager.singleFireEventListener(WI.DebuggerManager.Event.Resumed, (event) => {
+                    InspectorTest.log("RESUMED");
+                    resolve();
+                });
+            }
+        });
+    }
+
+    addTestCase({
+        name: "Debugger.stepNext.statements",
+        description: "step-next should step over statements.",
+        expression: "setTimeout(testStatements)",
+    });
+
+    addTestCase({
+        name: "Debugger.stepNext.function",
+        description: "step-next should step over function calls.",
+        expression: "setTimeout(testFunctions)",
+    });
+
+    addTestCase({
+        name: "Debugger.stepNext.eval",
+        description: "step-next should step over an eval program.",
+        expression: "setTimeout(testEval)",
+    });
+
+    addTestCase({
+        name: "Debugger.stepNext.innerFunction",
+        description: "step-next should step out of a function to its caller.",
+        expression: "setTimeout(testInnerFunction)",
+    });
+
+    addTestCase({
+        name: "Debugger.stepNext.commas",
+        description: "step-next should step to each sub-expression within comma expressions.",
+        expression: "setTimeout(testCommas)",
+    });
+
+    addTestCase({
+        name: "Debugger.stepNext.chainedExpressions",
+        description: "step-next should step to each sub-expression within chained expressions.",
+        expression: "setTimeout(testChainedExpressions)",
+    });
+
+    loadMainPageContent().then(() => {
+        suite.runTestCasesAndFinish();
+    });
+}
+</script>
+</head>
+<body onload="runTest()">
+<p>Checking pause locations when stepping with "stepNext".</p>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectordebuggersteppingstepOutexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/inspector/debugger/stepping/stepOut-expected.txt (260112 => 260113)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/debugger/stepping/stepOut-expected.txt       2020-04-15 01:24:30 UTC (rev 260112)
+++ trunk/LayoutTests/inspector/debugger/stepping/stepOut-expected.txt  2020-04-15 02:35:04 UTC (rev 260113)
</span><span class="lines">@@ -4,14 +4,14 @@
</span><span class="cx"> == Running test suite: Debugger.stepOut
</span><span class="cx"> -- Running test case: Debugger.stepOut.function
</span><span class="cx"> PAUSED (debugger-statement)
</span><del>-PAUSE AT entry1:8:5
-      4    <script src="../resources/log-pause-location.js"></script>
-      5    <script>
-      6    function entry1() {
- ->   7        |debugger;
-      8        let x = 1;
-      9        let y = 2;
-     10    }
</del><ins>+PAUSE AT testFunctions:12:5
+      8    function c() { return "c"; }
+      9    
+     10    function testFunctions() {
+ ->  11        |debugger;
+     12        let x = 1;
+     13        let y = 2;
+     14    }
</ins><span class="cx"> 
</span><span class="cx"> RESUMED
</span><span class="cx"> 
</span><span class="lines">@@ -24,54 +24,80 @@
</span><span class="cx"> 
</span><span class="cx"> -- Running test case: Debugger.stepOut.innerFunction
</span><span class="cx"> PAUSED (debugger-statement)
</span><del>-PAUSE AT beta:24:9
-     20            beta();
-     21        }
-     22        function beta() {
- ->  23            |debugger;
-     24        }
-     25        alpha();
-     26    }
</del><ins>+PAUSE AT beta:28:9
+     24            beta();
+     25        }
+     26        function beta() {
+ ->  27            |debugger;
+     28        }
+     29        alpha();
+     30    }
</ins><span class="cx"> 
</span><del>-PAUSE AT alpha:22:6
-     18    function entry3() {
-     19        function alpha() {
-     20            beta();
- ->  21        }|
-     22        function beta() {
-     23            debugger;
-     24        }
</del><ins>+PAUSE AT alpha:26:6
+     22    function testInnerFunction() {
+     23        function alpha() {
+     24            beta();
+ ->  25        }|
+     26        function beta() {
+     27            debugger;
+     28        }
</ins><span class="cx"> 
</span><del>-PAUSE AT entry3:27:2
-     23            debugger;
-     24        }
-     25        alpha();
- ->  26    }|
-     27    
-     28    function entry4() {
-     29        (function() {
</del><ins>+PAUSE AT testInnerFunction:31:2
+     27            debugger;
+     28        }
+     29        alpha();
+ ->  30    }|
+     31    
+     32    function testAnonymousFunction() {
+     33        (function() {
</ins><span class="cx"> 
</span><span class="cx"> RESUMED
</span><span class="cx"> 
</span><span class="cx"> -- Running test case: Debugger.stepOut.anonymousFunction
</span><span class="cx"> PAUSED (debugger-statement)
</span><del>-PAUSE AT <anonymous>:31:9
-     27    
-     28    function entry4() {
-     29        (function() {
- ->  30            |debugger;
-     31            let inner = 1;
-     32        })();
-     33        let outer = 2;
</del><ins>+PAUSE AT <anonymous>:35:9
+     31    
+     32    function testAnonymousFunction() {
+     33        (function() {
+ ->  34            |debugger;
+     35            let inner = 1;
+     36        })();
+     37        let outer = 2;
</ins><span class="cx"> 
</span><del>-PAUSE AT entry4:34:5
-     30            debugger;
-     31            let inner = 1;
-     32        })();
- ->  33        |let outer = 2;
-     34    }
-     35    
-     36    // ---------
</del><ins>+PAUSE AT testAnonymousFunction:38:5
+     34            debugger;
+     35            let inner = 1;
+     36        })();
+ ->  37        |let outer = 2;
+     38    }
+     39    
+     40    function testCommas() {
</ins><span class="cx"> 
</span><span class="cx"> RESUMED
</span><span class="cx"> 
</span><ins>+-- Running test case: Debugger.stepOut.commas
+PAUSED (debugger-statement)
+PAUSE AT testCommas:42:5
+     38    }
+     39    
+     40    function testCommas() {
+ ->  41        |debugger;
+     42        let x = 1,
+     43            y = 2,
+     44            z = 3;
+
+RESUMED
+
+-- Running test case: Debugger.stepOut.chainedExpressions
+PAUSED (debugger-statement)
+PAUSE AT testChainedExpressions:51:5
+     47    }
+     48    
+     49    function testChainedExpressions() {
+ ->  50        |debugger;
+     51        a() && b() && c();
+     52    }
+     53    
+
+RESUMED
+
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectordebuggersteppingstepOuthtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/inspector/debugger/stepping/stepOut.html (260112 => 260113)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/debugger/stepping/stepOut.html       2020-04-15 01:24:30 UTC (rev 260112)
+++ trunk/LayoutTests/inspector/debugger/stepping/stepOut.html  2020-04-15 02:35:04 UTC (rev 260113)
</span><span class="lines">@@ -4,19 +4,23 @@
</span><span class="cx"> <script src="../../../http/tests/inspector/resources/inspector-test.js"></script>
</span><span class="cx"> <script src="../resources/log-pause-location.js"></script>
</span><span class="cx"> <script>
</span><del>-function entry1() {
</del><ins>+function a() { return "a"; }
+function b() { return "b"; }
+function c() { return "c"; }
+
+function testFunctions() {
</ins><span class="cx">     debugger;
</span><span class="cx">     let x = 1;
</span><span class="cx">     let y = 2;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-function entry2() {
</del><ins>+function testEval() {
</ins><span class="cx">     let before = 1;
</span><span class="cx">     eval("debugger");
</span><span class="cx">     let after = 2;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-function entry3() {
</del><ins>+function testInnerFunction() {
</ins><span class="cx">     function alpha() {
</span><span class="cx">         beta();
</span><span class="cx">     }
</span><span class="lines">@@ -26,7 +30,7 @@
</span><span class="cx">     alpha();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-function entry4() {
</del><ins>+function testAnonymousFunction() {
</ins><span class="cx">     (function() {
</span><span class="cx">         debugger;
</span><span class="cx">         let inner = 1;
</span><span class="lines">@@ -34,6 +38,20 @@
</span><span class="cx">     let outer = 2;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+function testCommas() {
+    debugger;
+    let x = 1,
+        y = 2,
+        z = 3;
+    a(), b(), c();
+    true && (a(), b(), c());
+}
+
+function testChainedExpressions() {
+    debugger;
+    a() && b() && c();
+}
+
</ins><span class="cx"> // ---------
</span><span class="cx"> 
</span><span class="cx"> function test()
</span><span class="lines">@@ -67,27 +85,39 @@
</span><span class="cx">     addTestCase({
</span><span class="cx">         name: "Debugger.stepOut.function",
</span><span class="cx">         description: "step-out should leave a function.",
</span><del>-        expression: "setTimeout(entry1)",
</del><ins>+        expression: "setTimeout(testFunctions)",
</ins><span class="cx">     });
</span><span class="cx"> 
</span><span class="cx">     addTestCase({
</span><span class="cx">         name: "Debugger.stepOut.eval",
</span><span class="cx">         description: "step-out should step leave an eval program.",
</span><del>-        expression: "setTimeout(entry2)",
</del><ins>+        expression: "setTimeout(testEval)",
</ins><span class="cx">     });
</span><span class="cx"> 
</span><span class="cx">     addTestCase({
</span><span class="cx">         name: "Debugger.stepOut.innerFunction",
</span><span class="cx">         description: "step-out should leave a function and end up after its callsite.",
</span><del>-        expression: "setTimeout(entry3)",
</del><ins>+        expression: "setTimeout(testInnerFunction)",
</ins><span class="cx">     });
</span><span class="cx"> 
</span><span class="cx">     addTestCase({
</span><span class="cx">         name: "Debugger.stepOut.anonymousFunction",
</span><span class="cx">         description: "step-out should leave an anonymous function and end up after its callsite.",
</span><del>-        expression: "setTimeout(entry4)",
</del><ins>+        expression: "setTimeout(testAnonymousFunction)",
</ins><span class="cx">     });
</span><span class="cx"> 
</span><ins>+    addTestCase({
+        name: "Debugger.stepOut.commas",
+        description: "step-out should not enter any comma separated function calls.",
+        expression: "setTimeout(testCommas)",
+    });
+
+    addTestCase({
+        name: "Debugger.stepOut.chainedExpressions",
+        description: "step-out should not enter any function calls in a chained expression.",
+        expression: "setTimeout(testChainedExpressions)",
+    });
+
</ins><span class="cx">     loadMainPageContent().then(() => {
</span><span class="cx">         suite.runTestCasesAndFinish();
</span><span class="cx">     });
</span></span></pre></div>
<a id="trunkLayoutTestsinspectordebuggersteppingstepOverexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/inspector/debugger/stepping/stepOver-expected.txt (260112 => 260113)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/debugger/stepping/stepOver-expected.txt      2020-04-15 01:24:30 UTC (rev 260112)
+++ trunk/LayoutTests/inspector/debugger/stepping/stepOver-expected.txt 2020-04-15 02:35:04 UTC (rev 260113)
</span><span class="lines">@@ -5,7 +5,7 @@
</span><span class="cx"> -- Running test case: Debugger.stepOver.statements
</span><span class="cx"> PAUSED (debugger-statement)
</span><span class="cx"> PAUSE AT testStatements:12:5
</span><del>-      8    }
</del><ins>+      8    function c() { return "c"; }
</ins><span class="cx">       9    
</span><span class="cx">      10    function testStatements() {
</span><span class="cx">  ->  11        |debugger;
</span><span class="lines">@@ -127,7 +127,7 @@
</span><span class="cx">  ->  27        |let after = 2;
</span><span class="cx">      28    }
</span><span class="cx">      29    
</span><del>-     30    function testLocalFunction() {
</del><ins>+     30    function testInnerFunction() {
</ins><span class="cx"> 
</span><span class="cx"> PAUSE AT testEval:29:2
</span><span class="cx">      25        let before = 1;
</span><span class="lines">@@ -135,7 +135,7 @@
</span><span class="cx">      27        let after = 2;
</span><span class="cx">  ->  28    }|
</span><span class="cx">      29    
</span><del>-     30    function testLocalFunction() {
</del><ins>+     30    function testInnerFunction() {
</ins><span class="cx">      31        (function() {
</span><span class="cx"> 
</span><span class="cx"> RESUMED
</span><span class="lines">@@ -144,7 +144,7 @@
</span><span class="cx"> PAUSED (debugger-statement)
</span><span class="cx"> PAUSE AT <anonymous>:33:9
</span><span class="cx">      29    
</span><del>-     30    function testLocalFunction() {
</del><ins>+     30    function testInnerFunction() {
</ins><span class="cx">      31        (function() {
</span><span class="cx">  ->  32            |debugger;
</span><span class="cx">      33            let inner = 1;
</span><span class="lines">@@ -152,7 +152,7 @@
</span><span class="cx">      35        let outer = 2;
</span><span class="cx"> 
</span><span class="cx"> PAUSE AT <anonymous>:34:9
</span><del>-     30    function testLocalFunction() {
</del><ins>+     30    function testInnerFunction() {
</ins><span class="cx">      31        (function() {
</span><span class="cx">      32            debugger;
</span><span class="cx">  ->  33            |let inner = 1;
</span><span class="lines">@@ -169,7 +169,7 @@
</span><span class="cx">      36    }
</span><span class="cx">      37    
</span><span class="cx"> 
</span><del>-PAUSE AT testLocalFunction:36:5
</del><ins>+PAUSE AT testInnerFunction:36:5
</ins><span class="cx">      32            debugger;
</span><span class="cx">      33            let inner = 1;
</span><span class="cx">      34        })();
</span><span class="lines">@@ -178,7 +178,7 @@
</span><span class="cx">      37    
</span><span class="cx">      38    function testCommas() {
</span><span class="cx"> 
</span><del>-PAUSE AT testLocalFunction:37:2
</del><ins>+PAUSE AT testInnerFunction:37:2
</ins><span class="cx">      33            let inner = 1;
</span><span class="cx">      34        })();
</span><span class="cx">      35        let outer = 2;
</span><span class="lines">@@ -261,7 +261,7 @@
</span><span class="cx">  ->  44        |true && (a(), b(), c());
</span><span class="cx">      45    }
</span><span class="cx">      46    
</span><del>-     47    function a() { }
</del><ins>+     47    function testChainedExpressions() {
</ins><span class="cx"> 
</span><span class="cx"> PAUSE AT testCommas:45:14
</span><span class="cx">      41            y = 2,
</span><span class="lines">@@ -270,7 +270,7 @@
</span><span class="cx">  ->  44        true && (|a(), b(), c());
</span><span class="cx">      45    }
</span><span class="cx">      46    
</span><del>-     47    function a() { }
</del><ins>+     47    function testChainedExpressions() {
</ins><span class="cx"> 
</span><span class="cx"> PAUSE AT testCommas:45:19
</span><span class="cx">      41            y = 2,
</span><span class="lines">@@ -279,7 +279,7 @@
</span><span class="cx">  ->  44        true && (a(), |b(), c());
</span><span class="cx">      45    }
</span><span class="cx">      46    
</span><del>-     47    function a() { }
</del><ins>+     47    function testChainedExpressions() {
</ins><span class="cx"> 
</span><span class="cx"> PAUSE AT testCommas:45:24
</span><span class="cx">      41            y = 2,
</span><span class="lines">@@ -288,7 +288,7 @@
</span><span class="cx">  ->  44        true && (a(), b(), |c());
</span><span class="cx">      45    }
</span><span class="cx">      46    
</span><del>-     47    function a() { }
</del><ins>+     47    function testChainedExpressions() {
</ins><span class="cx"> 
</span><span class="cx"> PAUSE AT testCommas:46:2
</span><span class="cx">      42            z = 3;
</span><span class="lines">@@ -296,8 +296,39 @@
</span><span class="cx">      44        true && (a(), b(), c());
</span><span class="cx">  ->  45    }|
</span><span class="cx">      46    
</span><del>-     47    function a() { }
-     48    function b() { }
</del><ins>+     47    function testChainedExpressions() {
+     48        debugger;
</ins><span class="cx"> 
</span><span class="cx"> RESUMED
</span><span class="cx"> 
</span><ins>+-- Running test case: Debugger.stepOver.chainedExpressions
+PAUSED (debugger-statement)
+PAUSE AT testChainedExpressions:49:5
+     45    }
+     46    
+     47    function testChainedExpressions() {
+ ->  48        |debugger;
+     49        a() && b() && c();
+     50    }
+     51    
+
+PAUSE AT testChainedExpressions:50:5
+     46    
+     47    function testChainedExpressions() {
+     48        debugger;
+ ->  49        |a() && b() && c();
+     50    }
+     51    
+     52    // ---------
+
+PAUSE AT testChainedExpressions:51:2
+     47    function testChainedExpressions() {
+     48        debugger;
+     49        a() && b() && c();
+ ->  50    }|
+     51    
+     52    // ---------
+     53    
+
+RESUMED
+
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectordebuggersteppingstepOverhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/inspector/debugger/stepping/stepOver.html (260112 => 260113)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/debugger/stepping/stepOver.html      2020-04-15 01:24:30 UTC (rev 260112)
+++ trunk/LayoutTests/inspector/debugger/stepping/stepOver.html 2020-04-15 02:35:04 UTC (rev 260113)
</span><span class="lines">@@ -4,9 +4,9 @@
</span><span class="cx"> <script src="../../../http/tests/inspector/resources/inspector-test.js"></script>
</span><span class="cx"> <script src="../resources/log-pause-location.js"></script>
</span><span class="cx"> <script>
</span><del>-function testAlert(str) {
-    alert(str);
-}
</del><ins>+function a() { return "a"; }
+function b() { return "b"; }
+function c() { return "c"; }
</ins><span class="cx"> 
</span><span class="cx"> function testStatements() {
</span><span class="cx">     debugger;
</span><span class="lines">@@ -28,7 +28,7 @@
</span><span class="cx">     let after = 2;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-function testLocalFunction() {
</del><ins>+function testInnerFunction() {
</ins><span class="cx">     (function() {
</span><span class="cx">         debugger;
</span><span class="cx">         let inner = 1;
</span><span class="lines">@@ -45,9 +45,10 @@
</span><span class="cx">     true && (a(), b(), c());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-function a() { }
-function b() { }
-function c() { }
</del><ins>+function testChainedExpressions() {
+    debugger;
+    a() && b() && c();
+}
</ins><span class="cx"> 
</span><span class="cx"> // ---------
</span><span class="cx"> 
</span><span class="lines">@@ -100,7 +101,7 @@
</span><span class="cx">     addTestCase({
</span><span class="cx">         name: "Debugger.stepOver.innerFunction",
</span><span class="cx">         description: "step-over should step out of a function to its caller.",
</span><del>-        expression: "setTimeout(testLocalFunction)",
</del><ins>+        expression: "setTimeout(testInnerFunction)",
</ins><span class="cx">     });
</span><span class="cx"> 
</span><span class="cx">     addTestCase({
</span><span class="lines">@@ -109,6 +110,12 @@
</span><span class="cx">         expression: "setTimeout(testCommas)",
</span><span class="cx">     });
</span><span class="cx"> 
</span><ins>+    addTestCase({
+        name: "Debugger.stepOver.chainedExpressions",
+        description: "step-over should step over chained expressions as a single statement.",
+        expression: "setTimeout(testChainedExpressions)",
+    });
+
</ins><span class="cx">     loadMainPageContent().then(() => {
</span><span class="cx">         suite.runTestCasesAndFinish();
</span><span class="cx">     });
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (260112 => 260113)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog    2020-04-15 01:24:30 UTC (rev 260112)
+++ trunk/Source/JavaScriptCore/ChangeLog       2020-04-15 02:35:04 UTC (rev 260113)
</span><span class="lines">@@ -1,3 +1,27 @@
</span><ins>+2020-04-14  Devin Rousso  <drousso@apple.com>
+
+        Web Inspector: Debugger: add a Step next that steps by expression
+        https://bugs.webkit.org/show_bug.cgi?id=210324
+
+        Reviewed by Timothy Hatcher.
+
+        Step next is a hybrid of Step over and Step into which continues execution to the next pause
+        opportunity within the current (or ancestor) call frame. It is especially useful when trying
+        to debug minified code, such as trying to continue to `c()` in `a() && b() && c();`, where
+        Step over would continue to the next statement (i.e. after the `;`) and Step in would
+        continue to the first line inside `a()` (and would require a Step out to get back).
+
+        * inspector/protocol/Debugger.json:
+        * inspector/agents/InspectorDebuggerAgent.h:
+        * inspector/agents/InspectorDebuggerAgent.cpp:
+        (Inspector::InspectorDebuggerAgent::stepNext): Added.
+
+        * debugger/Debugger.h:
+        * debugger/Debugger.cpp:
+        (JSC::Debugger::stepNextExpression): Added.
+        (JSC::Debugger::atExpression):
+        (JSC::Debugger::clearNextPauseState):
+
</ins><span class="cx"> 2020-04-13  Alexey Shvayka  <shvaikalesh@gmail.com>
</span><span class="cx"> 
</span><span class="cx">         REGRESSION (r259587): bterlson/eshost throws during init in strict mode
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredebuggerDebuggercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/debugger/Debugger.cpp (260112 => 260113)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/debugger/Debugger.cpp        2020-04-15 01:24:30 UTC (rev 260112)
+++ trunk/Source/JavaScriptCore/debugger/Debugger.cpp   2020-04-15 02:35:04 UTC (rev 260113)
</span><span class="lines">@@ -609,6 +609,17 @@
</span><span class="cx">     notifyDoneProcessingDebuggerEvents();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void Debugger::stepNextExpression()
+{
+    if (!m_isPaused)
+        return;
+
+    m_pauseOnCallFrame = m_currentCallFrame;
+    m_pauseOnStepNext = true;
+    setSteppingMode(SteppingModeEnabled);
+    notifyDoneProcessingDebuggerEvents();
+}
+
</ins><span class="cx"> void Debugger::stepIntoStatement()
</span><span class="cx"> {
</span><span class="cx">     if (!m_isPaused)
</span><span class="lines">@@ -803,8 +814,8 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // Only pause at the next expression with step-in and step-out, not step-over.
-    bool shouldAttemptPause = m_pauseAtNextOpportunity || m_pauseOnStepOut;
</del><ins>+    // Only pause at the next expression with step-in, step-next, and step-out.
+    bool shouldAttemptPause = m_pauseAtNextOpportunity || m_pauseOnStepNext || m_pauseOnStepOut;
</ins><span class="cx"> 
</span><span class="cx">     PauseReasonDeclaration reason(*this, PausedAtExpression);
</span><span class="cx">     updateCallFrame(lexicalGlobalObjectForCallFrame(m_vm, callFrame), callFrame, shouldAttemptPause ? AttemptPause : NoPause);
</span><span class="lines">@@ -910,6 +921,7 @@
</span><span class="cx"> {
</span><span class="cx">     m_pauseOnCallFrame = nullptr;
</span><span class="cx">     m_pauseAtNextOpportunity = false;
</span><ins>+    m_pauseOnStepNext = false;
</ins><span class="cx">     m_pauseOnStepOut = false;
</span><span class="cx">     m_afterBlackboxedScript = false;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredebuggerDebuggerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/debugger/Debugger.h (260112 => 260113)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/debugger/Debugger.h  2020-04-15 01:24:30 UTC (rev 260112)
+++ trunk/Source/JavaScriptCore/debugger/Debugger.h     2020-04-15 02:35:04 UTC (rev 260113)
</span><span class="lines">@@ -108,6 +108,7 @@
</span><span class="cx">     void setPauseOnNextStatement(bool);
</span><span class="cx">     void breakProgram();
</span><span class="cx">     void continueProgram();
</span><ins>+    void stepNextExpression();
</ins><span class="cx">     void stepIntoStatement();
</span><span class="cx">     void stepOverStatement();
</span><span class="cx">     void stepOutOfFunction();
</span><span class="lines">@@ -230,6 +231,7 @@
</span><span class="cx">     PauseOnExceptionsState m_pauseOnExceptionsState;
</span><span class="cx">     bool m_pauseOnDebuggerStatements : 1;
</span><span class="cx">     bool m_pauseAtNextOpportunity : 1;
</span><ins>+    bool m_pauseOnStepNext : 1;
</ins><span class="cx">     bool m_pauseOnStepOut : 1;
</span><span class="cx">     bool m_pastFirstExpressionInStatement : 1;
</span><span class="cx">     bool m_isPaused : 1;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectoragentsInspectorDebuggerAgentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.cpp (260112 => 260113)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.cpp  2020-04-15 01:24:30 UTC (rev 260112)
+++ trunk/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.cpp     2020-04-15 02:35:04 UTC (rev 260113)
</span><span class="lines">@@ -767,6 +767,15 @@
</span><span class="cx">     m_conditionToDispatchResumed = ShouldDispatchResumed::WhenContinued;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void InspectorDebuggerAgent::stepNext(ErrorString& errorString)
+{
+    if (!assertPaused(errorString))
+        return;
+
+    willStepAndMayBecomeIdle();
+    m_scriptDebugServer.stepNextExpression();
+}
+
</ins><span class="cx"> void InspectorDebuggerAgent::stepOver(ErrorString& errorString)
</span><span class="cx"> {
</span><span class="cx">     if (!assertPaused(errorString))
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectoragentsInspectorDebuggerAgenth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.h (260112 => 260113)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.h    2020-04-15 01:24:30 UTC (rev 260112)
+++ trunk/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.h       2020-04-15 02:35:04 UTC (rev 260113)
</span><span class="lines">@@ -72,6 +72,7 @@
</span><span class="cx">     void removeBreakpoint(ErrorString&, const String& breakpointIdentifier) final;
</span><span class="cx">     void continueUntilNextRunLoop(ErrorString&) final;
</span><span class="cx">     void continueToLocation(ErrorString&, const JSON::Object& location) final;
</span><ins>+    void stepNext(ErrorString&) final;
</ins><span class="cx">     void stepOver(ErrorString&) final;
</span><span class="cx">     void stepInto(ErrorString&) final;
</span><span class="cx">     void stepOut(ErrorString&) final;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorprotocolDebuggerjson"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/protocol/Debugger.json (260112 => 260113)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/protocol/Debugger.json     2020-04-15 01:24:30 UTC (rev 260112)
+++ trunk/Source/JavaScriptCore/inspector/protocol/Debugger.json        2020-04-15 02:35:04 UTC (rev 260113)
</span><span class="lines">@@ -196,6 +196,10 @@
</span><span class="cx">             ]
</span><span class="cx">         },
</span><span class="cx">         {
</span><ins>+            "name": "stepNext",
+            "description": "Steps over the expression. This will trigger either a Debugger.paused or Debugger.resumed event."
+        },
+        {
</ins><span class="cx">             "name": "stepOver",
</span><span class="cx">             "description": "Steps over the statement. This will trigger either a Debugger.paused or Debugger.resumed event."
</span><span class="cx">         },
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/ChangeLog (260112 => 260113)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/ChangeLog    2020-04-15 01:24:30 UTC (rev 260112)
+++ trunk/Source/WebInspectorUI/ChangeLog       2020-04-15 02:35:04 UTC (rev 260113)
</span><span class="lines">@@ -1,3 +1,30 @@
</span><ins>+2020-04-14  Devin Rousso  <drousso@apple.com>
+
+        Web Inspector: Debugger: add a Step next that steps by expression
+        https://bugs.webkit.org/show_bug.cgi?id=210324
+
+        Reviewed by Timothy Hatcher.
+
+        Step next is a hybrid of Step over and Step into which continues execution to the next pause
+        opportunity within the current (or ancestor) call frame. It is especially useful when trying
+        to debug minified code, such as trying to continue to `c()` in `a() && b() && c();`, where
+        Step over would continue to the next statement (i.e. after the `;`) and Step in would
+        continue to the first line inside `a()` (and would require a Step out to get back).
+
+        * UserInterface/Controllers/DebuggerManager.js:
+        (WI.DebuggerManager.prototype.stepNext): Added.
+
+        * UserInterface/Base/Main.js:
+        (WI.contentLoaded):
+        (WI.debuggerStepNext): Added.
+        * UserInterface/Views/SourcesNavigationSidebarPanel.js:
+        (WI.SourcesNavigationSidebarPanel):
+        (WI.SourcesNavigationSidebarPanel.prototype._handleDebuggerPaused):
+        (WI.SourcesNavigationSidebarPanel.prototype._handleDebuggerResumed):
+
+        * Localizations/en.lproj/localizedStrings.js:
+        * UserInterface/Images/StepNext.svg: Added.
+
</ins><span class="cx"> 2020-04-14  Nikita Vasilyev  <nvasilyev@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Web Inspector: Don't show tooltips for tabs
</span></span></pre></div>
<a id="trunkSourceWebInspectorUILocalizationsenlprojlocalizedStringsjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js (260112 => 260113)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js   2020-04-15 01:24:30 UTC (rev 260112)
+++ trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js      2020-04-15 02:35:04 UTC (rev 260113)
</span><span class="lines">@@ -1179,6 +1179,7 @@
</span><span class="cx"> localizedStrings["Statistics"] = "Statistics";
</span><span class="cx"> localizedStrings["Status"] = "Status";
</span><span class="cx"> localizedStrings["Step"] = "Step";
</span><ins>+localizedStrings["Step (%s or %s)"] = "Step (%s or %s)";
</ins><span class="cx"> localizedStrings["Step into (%s or %s)"] = "Step into (%s or %s)";
</span><span class="cx"> localizedStrings["Step out (%s or %s)"] = "Step out (%s or %s)";
</span><span class="cx"> localizedStrings["Step over (%s or %s)"] = "Step over (%s or %s)";
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceBaseMainjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Base/Main.js (260112 => 260113)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Base/Main.js   2020-04-15 01:24:30 UTC (rev 260112)
+++ trunk/Source/WebInspectorUI/UserInterface/Base/Main.js      2020-04-15 02:35:04 UTC (rev 260113)
</span><span class="lines">@@ -362,6 +362,12 @@
</span><span class="cx">     WI.stepIntoAlternateKeyboardShortcut = new WI.KeyboardShortcut(WI.KeyboardShortcut.Modifier.CommandOrControl, WI.KeyboardShortcut.Key.Semicolon, WI.debuggerStepInto);
</span><span class="cx">     WI.stepOutAlternateKeyboardShortcut = new WI.KeyboardShortcut(WI.KeyboardShortcut.Modifier.Shift | WI.KeyboardShortcut.Modifier.CommandOrControl, WI.KeyboardShortcut.Key.Semicolon, WI.debuggerStepOut);
</span><span class="cx"> 
</span><ins>+    // COMPATIBILITY (iOS 13.4): Debugger.stepNext did not exist yet.
+    if (InspectorBackend.hasCommand("Debugger.stepNext")) {
+        WI.stepNextKeyboardShortcut = new WI.KeyboardShortcut(null, WI.KeyboardShortcut.Key.F9, WI.debuggerStepNext);
+        WI.stepNextAlternateKeyboardShortcut = new WI.KeyboardShortcut(WI.KeyboardShortcut.Modifier.Shift | WI.KeyboardShortcut.Modifier.CommandOrControl, WI.KeyboardShortcut.Key.SingleQuote, WI.debuggerStepNext);
+    }
+
</ins><span class="cx">     WI.settingsKeyboardShortcut = new WI.KeyboardShortcut(WI.KeyboardShortcut.Modifier.CommandOrControl, WI.KeyboardShortcut.Key.Comma, WI._handleSettingsKeyboardShortcut);
</span><span class="cx"> 
</span><span class="cx">     WI._togglePreviousDockConfigurationKeyboardShortcut = new WI.KeyboardShortcut(WI.KeyboardShortcut.Modifier.CommandOrControl | WI.KeyboardShortcut.Modifier.Shift, "D", WI._togglePreviousDockConfiguration);
</span><span class="lines">@@ -1525,6 +1531,11 @@
</span><span class="cx">         WI.debuggerManager.pause();
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+WI.debuggerStepNext = function(event)
+{
+    WI.debuggerManager.stepNext();
+};
+
</ins><span class="cx"> WI.debuggerStepOver = function(event)
</span><span class="cx"> {
</span><span class="cx">     WI.debuggerManager.stepOver();
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceControllersDebuggerManagerjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js (260112 => 260113)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js 2020-04-15 01:24:30 UTC (rev 260112)
+++ trunk/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js    2020-04-15 02:35:04 UTC (rev 260113)
</span><span class="lines">@@ -568,6 +568,27 @@
</span><span class="cx">         return Promise.all([managerResult, ...promises]);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    stepNext()
+    {
+        if (!this.paused)
+            return Promise.reject(new Error("Cannot step next because debugger is not paused."));
+
+        let listener = new WI.EventListener(this, true);
+
+        let managerResult = new Promise(function(resolve, reject) {
+            listener.connect(WI.debuggerManager, WI.DebuggerManager.Event.ActiveCallFrameDidChange, resolve);
+        });
+
+        let protocolResult = this._activeCallFrame.target.DebuggerAgent.stepNext()
+            .catch(function(error) {
+                listener.disconnect();
+                console.error("DebuggerManager.stepNext failed: ", error);
+                throw error;
+            });
+
+        return Promise.all([managerResult, protocolResult]);
+    }
+
</ins><span class="cx">     stepOver()
</span><span class="cx">     {
</span><span class="cx">         if (!this.paused)
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceImagesStepNextsvg"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Images/StepNext.svg (0 => 260113)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Images/StepNext.svg                            (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Images/StepNext.svg       2020-04-15 02:35:04 UTC (rev 260113)
</span><span class="lines">@@ -0,0 +1,7 @@
</span><ins>+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright © 2020 Apple Inc. All rights reserved. -->
+<svg xmlns="http://www.w3.org/2000/svg" id="root" version="1.1" viewBox="0 0 15 15">
+    <rect fill="none" stroke="currentColor" x="3.5" y="10.5" width="8" height="2"/>
+    <path fill="none" stroke="currentColor" d="M 2 5 L 13 5"/>
+    <path fill="none" stroke="currentColor" d="M 10 2 L 13 5 L 10 8"/>
+</svg>
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsSourcesNavigationSidebarPaneljs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/SourcesNavigationSidebarPanel.js (260112 => 260113)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/SourcesNavigationSidebarPanel.js 2020-04-15 01:24:30 UTC (rev 260112)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/SourcesNavigationSidebarPanel.js    2020-04-15 02:35:04 UTC (rev 260113)
</span><span class="lines">@@ -106,6 +106,17 @@
</span><span class="cx">         this._debuggerStepOutButtonItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, WI.debuggerStepOut, this);
</span><span class="cx">         this._debuggerStepOutButtonItem.enabled = false;
</span><span class="cx"> 
</span><ins>+        // COMPATIBILITY (iOS 13.4): Debugger.stepNext did not exist yet.
+        if (InspectorBackend.hasCommand("Debugger.stepNext")) {
+            this._debuggerStepNextButtonItem = createButtonNavigationitem({
+                identifier: "debugger-step-next",
+                toolTipOrLabel: WI.UIString("Step (%s or %s)").format(WI.stepNextKeyboardShortcut.displayName, WI.stepNextAlternateKeyboardShortcut.displayName),
+                image: "Images/StepNext.svg",
+            });
+            this._debuggerStepNextButtonItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, WI.debuggerStepNext, this);
+            this._debuggerStepNextButtonItem.enabled = false;
+        }
+
</ins><span class="cx">         this._timelineRecordingWarningElement = null;
</span><span class="cx">         this._auditTestWarningElement = null;
</span><span class="cx">         this._breakpointsDisabledWarningElement = null;
</span><span class="lines">@@ -2345,6 +2356,8 @@
</span><span class="cx">         this._debuggerStepOverButtonItem.enabled = true;
</span><span class="cx">         this._debuggerStepIntoButtonItem.enabled = true;
</span><span class="cx">         this._debuggerStepOutButtonItem.enabled = true;
</span><ins>+        if (this._debuggerStepNextButtonItem)
+            this._debuggerStepNextButtonItem.enabled = true;
</ins><span class="cx"> 
</span><span class="cx">         this.element.classList.add("paused");
</span><span class="cx">     }
</span><span class="lines">@@ -2360,6 +2373,8 @@
</span><span class="cx">         this._debuggerStepOverButtonItem.enabled = false;
</span><span class="cx">         this._debuggerStepIntoButtonItem.enabled = false;
</span><span class="cx">         this._debuggerStepOutButtonItem.enabled = false;
</span><ins>+        if (this._debuggerStepNextButtonItem)
+            this._debuggerStepNextButtonItem.enabled = false;
</ins><span class="cx"> 
</span><span class="cx">         this.element.classList.remove("paused");
</span><span class="cx">     }
</span></span></pre>
</div>
</div>

</body>
</html>