Diff
Modified: trunk/LayoutTests/ChangeLog (207227 => 207228)
--- trunk/LayoutTests/ChangeLog 2016-10-12 18:43:19 UTC (rev 207227)
+++ trunk/LayoutTests/ChangeLog 2016-10-12 18:47:48 UTC (rev 207228)
@@ -1,3 +1,19 @@
+2016-10-12 Joseph Pecoraro <[email protected]>
+
+ 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.
+
2016-10-12 Carlos Alberto Lopez Perez <[email protected]>
[GTK] Tests that fail since the new URLParser has been enabled on r207162.
Modified: trunk/LayoutTests/inspector/debugger/stepping/stepping-control-flow-expected.txt (207227 => 207228)
--- 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)
@@ -7,13 +7,13 @@
STEPS: over, over, over, over, resume
PAUSED (debugger-statement)
PAUSE AT entryIfSingleStatement:16:5
- 12 }
+ 12
13
14 function entryIfSingleStatement() {
-> 15 |debugger;
- 16 if (true)
+ 16 if (truthy)
17 a();
- 18 if (false)
+ 18 if (falsey)
ACTION: step-over
PAUSE AT entryIfSingleStatement:17:9
@@ -20,9 +20,9 @@
13
14 function entryIfSingleStatement() {
15 debugger;
- -> 16 if (|true)
+ -> 16 if (|truthy)
17 a();
- 18 if (false)
+ 18 if (falsey)
19 a();
ACTION: step-over
@@ -29,9 +29,9 @@
PAUSE AT entryIfSingleStatement:18:9
14 function entryIfSingleStatement() {
15 debugger;
- 16 if (true)
+ 16 if (truthy)
-> 17 |a();
- 18 if (false)
+ 18 if (falsey)
19 a();
20 }
@@ -38,9 +38,9 @@
ACTION: step-over
PAUSE AT entryIfSingleStatement:19:9
15 debugger;
- 16 if (true)
+ 16 if (truthy)
17 a();
- -> 18 if (|false)
+ -> 18 if (|falsey)
19 a();
20 }
21
@@ -48,7 +48,7 @@
ACTION: step-over
PAUSE AT entryIfSingleStatement:21:2
17 a();
- 18 if (false)
+ 18 if (falsey)
19 a();
-> 20 }|
21
@@ -68,7 +68,7 @@
21
22 function entryIfMultiStatement() {
-> 23 |debugger;
- 24 if (true) {
+ 24 if (truthy) {
25 a();
26 a();
@@ -77,7 +77,7 @@
21
22 function entryIfMultiStatement() {
23 debugger;
- -> 24 if (|true) {
+ -> 24 if (|truthy) {
25 a();
26 a();
27 }
@@ -86,20 +86,20 @@
PAUSE AT entryIfMultiStatement:26:9
22 function entryIfMultiStatement() {
23 debugger;
- 24 if (true) {
+ 24 if (truthy) {
-> 25 |a();
26 a();
27 }
- 28 if (false) {
+ 28 if (falsey) {
ACTION: step-over
PAUSE AT entryIfMultiStatement:27:9
23 debugger;
- 24 if (true) {
+ 24 if (truthy) {
25 a();
-> 26 |a();
27 }
- 28 if (false) {
+ 28 if (falsey) {
29 a();
ACTION: step-over
@@ -107,7 +107,7 @@
25 a();
26 a();
27 }
- -> 28 if (|false) {
+ -> 28 if (|falsey) {
29 a();
30 a();
31 }
@@ -135,7 +135,7 @@
33
34 function entryIfElse() {
-> 35 |debugger;
- 36 if (true)
+ 36 if (truthy)
37 a();
38 else
@@ -144,7 +144,7 @@
33
34 function entryIfElse() {
35 debugger;
- -> 36 if (|true)
+ -> 36 if (|truthy)
37 a();
38 else
39 a();
@@ -153,11 +153,11 @@
PAUSE AT entryIfElse:38:9
34 function entryIfElse() {
35 debugger;
- 36 if (true)
+ 36 if (truthy)
-> 37 |a();
38 else
39 a();
- 40 if (false)
+ 40 if (falsey)
ACTION: step-over
PAUSE AT entryIfElse:41:9
@@ -164,7 +164,7 @@
37 a();
38 else
39 a();
- -> 40 if (|false)
+ -> 40 if (|falsey)
41 a();
42 else
43 a();
@@ -171,7 +171,7 @@
ACTION: step-over
PAUSE AT entryIfElse:44:9
- 40 if (false)
+ 40 if (falsey)
41 a();
42 else
-> 43 |a();
@@ -202,9 +202,9 @@
45
46 function entryIfElseChain() {
-> 47 |debugger;
- 48 if (false)
+ 48 if (falsey)
49 a();
- 50 else if (true)
+ 50 else if (truthy)
ACTION: step-over
PAUSE AT entryIfElseChain:49:9
@@ -211,17 +211,17 @@
45
46 function entryIfElseChain() {
47 debugger;
- -> 48 if (|false)
+ -> 48 if (|falsey)
49 a();
- 50 else if (true)
+ 50 else if (truthy)
51 a();
ACTION: step-over
PAUSE AT entryIfElseChain:51:14
47 debugger;
- 48 if (false)
+ 48 if (falsey)
49 a();
- -> 50 else if (|true)
+ -> 50 else if (|truthy)
51 a();
52 else
53 a();
@@ -228,9 +228,9 @@
ACTION: step-over
PAUSE AT entryIfElseChain:52:9
- 48 if (false)
+ 48 if (falsey)
49 a();
- 50 else if (true)
+ 50 else if (truthy)
-> 51 |a();
52 else
53 a();
@@ -241,17 +241,17 @@
52 else
53 a();
54
- -> 55 if (|false)
+ -> 55 if (|falsey)
56 a();
- 57 else if (false)
+ 57 else if (falsey)
58 a();
ACTION: step-over
PAUSE AT entryIfElseChain:58:14
54
- 55 if (false)
+ 55 if (falsey)
56 a();
- -> 57 else if (|false)
+ -> 57 else if (|falsey)
58 a();
59 else
60 a();
@@ -258,7 +258,7 @@
ACTION: step-over
PAUSE AT entryIfElseChain:61:9
- 57 else if (false)
+ 57 else if (falsey)
58 a();
59 else
-> 60 |a();
@@ -321,7 +321,7 @@
-> 67 }|
68
69 function entryTernary() {
- 70 let t = () => true;
+ 70 let t = () => truthy;
ACTION: resume
RESUMED
@@ -351,14 +351,14 @@
68
ACTION: step-in
-PAUSE AT a:8:5
- 4 <script src=""
- 5 <script>
- 6 function a() {
- -> 7 |return 1;
- 8 }
- 9
- 10 function b() {
+PAUSE AT a:11:16
+ 7 var value = 1;
+ 8 var truthy = true;
+ 9 var falsey = false;
+ -> 10 function a() { |return value; }
+ 11 function b() { return value; }
+ 12
+ 13
ACTION: step-out
PAUSE AT entryIfWithCall:66:16
@@ -371,14 +371,14 @@
68
ACTION: step-in
-PAUSE AT a:8:5
- 4 <script src=""
- 5 <script>
- 6 function a() {
- -> 7 |return 1;
- 8 }
- 9
- 10 function b() {
+PAUSE AT a:11:16
+ 7 var value = 1;
+ 8 var truthy = true;
+ 9 var falsey = false;
+ -> 10 function a() { |return value; }
+ 11 function b() { return value; }
+ 12
+ 13
ACTION: step-out
PAUSE AT entryIfWithCall:67:9
@@ -398,7 +398,7 @@
-> 67 }|
68
69 function entryTernary() {
- 70 let t = () => true;
+ 70 let t = () => truthy;
ACTION: resume
RESUMED
@@ -410,8 +410,8 @@
PAUSED (debugger-statement)
PAUSE AT entryTernary:73:5
69 function entryTernary() {
- 70 let t = () => true;
- 71 let f = () => false;
+ 70 let t = () => truthy;
+ 71 let f = () => falsey;
-> 72 |debugger;
73 let x = t() ? a() : b();
74 let y = f() ? a() : b();
@@ -419,8 +419,8 @@
ACTION: step-over
PAUSE AT entryTernary:74:5
- 70 let t = () => true;
- 71 let f = () => false;
+ 70 let t = () => truthy;
+ 71 let f = () => falsey;
72 debugger;
-> 73 |let x = t() ? a() : b();
74 let y = f() ? a() : b();
@@ -429,13 +429,13 @@
ACTION: step-over
PAUSE AT entryTernary:75:5
- 71 let f = () => false;
+ 71 let f = () => falsey;
72 debugger;
73 let x = t() ? a() : b();
-> 74 |let y = f() ? a() : b();
75 }
76
- 77 // ---------
+ 77 function entryIfConstantBranch() {
ACTION: step-over
PAUSE AT entryTernary:76:2
@@ -444,8 +444,8 @@
74 let y = f() ? a() : b();
-> 75 }|
76
- 77 // ---------
- 78
+ 77 function entryIfConstantBranch() {
+ 78 debugger;
ACTION: resume
RESUMED
@@ -457,8 +457,8 @@
PAUSED (debugger-statement)
PAUSE AT entryTernary:73:5
69 function entryTernary() {
- 70 let t = () => true;
- 71 let f = () => false;
+ 70 let t = () => truthy;
+ 71 let f = () => falsey;
-> 72 |debugger;
73 let x = t() ? a() : b();
74 let y = f() ? a() : b();
@@ -466,8 +466,8 @@
ACTION: step-over
PAUSE AT entryTernary:74:5
- 70 let t = () => true;
- 71 let f = () => false;
+ 70 let t = () => truthy;
+ 71 let f = () => falsey;
72 debugger;
-> 73 |let x = t() ? a() : b();
74 let y = f() ? a() : b();
@@ -479,15 +479,15 @@
67 }
68
69 function entryTernary() {
- -> 70 let t = () => |true;
- 71 let f = () => false;
+ -> 70 let t = () => |truthy;
+ 71 let f = () => falsey;
72 debugger;
73 let x = t() ? a() : b();
ACTION: step-out
PAUSE AT entryTernary:74:19
- 70 let t = () => true;
- 71 let f = () => false;
+ 70 let t = () => truthy;
+ 71 let f = () => falsey;
72 debugger;
-> 73 let x = t() ? |a() : b();
74 let y = f() ? a() : b();
@@ -495,31 +495,31 @@
76
ACTION: step-in
-PAUSE AT a:8:5
- 4 <script src=""
- 5 <script>
- 6 function a() {
- -> 7 |return 1;
- 8 }
- 9
- 10 function b() {
+PAUSE AT a:11:16
+ 7 var value = 1;
+ 8 var truthy = true;
+ 9 var falsey = false;
+ -> 10 function a() { |return value; }
+ 11 function b() { return value; }
+ 12
+ 13
ACTION: step-out
PAUSE AT entryTernary:75:5
- 71 let f = () => false;
+ 71 let f = () => falsey;
72 debugger;
73 let x = t() ? a() : b();
-> 74 |let y = f() ? a() : b();
75 }
76
- 77 // ---------
+ 77 function entryIfConstantBranch() {
ACTION: step-in
PAUSE AT f:72:19
68
69 function entryTernary() {
- 70 let t = () => true;
- -> 71 let f = () => |false;
+ 70 let t = () => truthy;
+ -> 71 let f = () => |falsey;
72 debugger;
73 let x = t() ? a() : b();
74 let y = f() ? a() : b();
@@ -526,21 +526,21 @@
ACTION: step-out
PAUSE AT entryTernary:75:25
- 71 let f = () => false;
+ 71 let f = () => falsey;
72 debugger;
73 let x = t() ? a() : b();
-> 74 let y = f() ? a() : |b();
75 }
76
- 77 // ---------
+ 77 function entryIfConstantBranch() {
ACTION: step-in
-PAUSE AT b:12:5
- 8 }
- 9
- 10 function b() {
- -> 11 |return 2;
- 12 }
+PAUSE AT b:12:16
+ 8 var truthy = true;
+ 9 var falsey = false;
+ 10 function a() { return value; }
+ -> 11 function b() { |return value; }
+ 12
13
14 function entryIfSingleStatement() {
@@ -551,10 +551,278 @@
74 let y = f() ? a() : b();
-> 75 }|
76
- 77 // ---------
- 78
+ 77 function entryIfConstantBranch() {
+ 78 debugger;
ACTION: resume
RESUMED
PASS: Should have used all steps.
+-- 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() {
+ -> 78 |debugger;
+ 79 if (true)
+ 80 a();
+ 81 if (false)
+
+ACTION: step-over
+PAUSE AT entryIfConstantBranch:80:9
+ 76
+ 77 function entryIfConstantBranch() {
+ 78 debugger;
+ -> 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)
+ -> 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();
+ -> 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();
+ -> 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();
+ -> 85 if (|null)
+ 86 a();
+ 87 }
+ 88
+
+ACTION: step-over
+PAUSE AT entryIfConstantBranch:88:2
+ 84 a();
+ 85 if (null)
+ 86 a();
+ -> 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() {
+ -> 90 |debugger;
+ 91 if (true && a() && a())
+ 92 b();
+ 93 }
+
+ACTION: step-over
+PAUSE AT entryIfWithLogicalOperation:92:9
+ 88
+ 89 function entryIfWithLogicalOperation() {
+ 90 debugger;
+ -> 91 if (|true && a() && 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;
+ -> 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;
+ -> 91 if (true && a() && |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;
+ -> 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 && a() && a())
+ -> 92 |b();
+ 93 }
+ 94
+ 95 function entryIfWithBinaryOperation() {
+
+ACTION: step-over
+PAUSE AT entryIfWithLogicalOperation:94:2
+ 90 debugger;
+ 91 if (true && a() && a())
+ 92 b();
+ -> 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();
+ -> 97 |debugger;
+ 98 if (i < 2)
+ 99 b();
+ 100 }
+
+ACTION: step-over
+PAUSE AT entryIfWithBinaryOperation:99:9
+ 95 function entryIfWithBinaryOperation() {
+ 96 let i = a();
+ 97 debugger;
+ -> 98 if (|i < 2)
+ 99 b();
+ 100 }
+ 101
+
+ACTION: step-in
+PAUSE AT entryIfWithBinaryOperation:100:9
+ 96 let i = a();
+ 97 debugger;
+ 98 if (i < 2)
+ -> 99 |b();
+ 100 }
+ 101
+ 102 function entryIfWithNotOperation() {
+
+ACTION: step-over
+PAUSE AT entryIfWithBinaryOperation:101:2
+ 97 debugger;
+ 98 if (i < 2)
+ 99 b();
+ -> 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() {
+ -> 103 |debugger;
+ 104 if (!false)
+ 105 a();
+ 106 if (!!true)
+
+ACTION: step-over
+PAUSE AT entryIfWithNotOperation:105:9
+ 101
+ 102 function entryIfWithNotOperation() {
+ 103 debugger;
+ -> 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)
+ -> 105 |a();
+ 106 if (!!true)
+ 107 a();
+ 108 }
+
+ACTION: step-over
+PAUSE AT entryIfWithNotOperation:107:9
+ 103 debugger;
+ 104 if (!false)
+ 105 a();
+ -> 106 if (|!!true)
+ 107 a();
+ 108 }
+ 109
+
+ACTION: step-in
+PAUSE AT entryIfWithNotOperation:108:9
+ 104 if (!false)
+ 105 a();
+ 106 if (!!true)
+ -> 107 |a();
+ 108 }
+ 109
+ 110 // ---------
+
+ACTION: step-over
+PAUSE AT entryIfWithNotOperation:109:2
+ 105 a();
+ 106 if (!!true)
+ 107 a();
+ -> 108 }|
+ 109
+ 110 // ---------
+ 111
+
+ACTION: resume
+RESUMED
+PASS: Should have used all steps.
+
Modified: trunk/LayoutTests/inspector/debugger/stepping/stepping-control-flow.html (207227 => 207228)
--- 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)
@@ -4,29 +4,29 @@
<script src=""
<script src=""
<script>
-function a() {
- return 1;
-}
+// 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; }
-function b() {
- return 2;
-}
function entryIfSingleStatement() {
debugger;
- if (true)
+ if (truthy)
a();
- if (false)
+ if (falsey)
a();
}
function entryIfMultiStatement() {
debugger;
- if (true) {
+ if (truthy) {
a();
a();
}
- if (false) {
+ if (falsey) {
a();
a();
}
@@ -34,11 +34,11 @@
function entryIfElse() {
debugger;
- if (true)
+ if (truthy)
a();
else
a();
- if (false)
+ if (falsey)
a();
else
a();
@@ -46,16 +46,16 @@
function entryIfElseChain() {
debugger;
- if (false)
+ if (falsey)
a();
- else if (true)
+ else if (truthy)
a();
else
a();
- if (false)
+ if (falsey)
a();
- else if (false)
+ else if (falsey)
a();
else
a();
@@ -68,13 +68,46 @@
}
function entryTernary() {
- let t = () => true;
- let f = () => false;
+ let t = () => truthy;
+ let f = () => falsey;
debugger;
let x = t() ? a() : b();
let y = f() ? a() : b();
}
+function entryIfConstantBranch() {
+ debugger;
+ if (true)
+ a();
+ if (false)
+ a();
+ if (0)
+ a();
+ if (null)
+ a();
+}
+
+function entryIfWithLogicalOperation() {
+ debugger;
+ if (true && a() && a())
+ b();
+}
+
+function entryIfWithBinaryOperation() {
+ let i = a();
+ debugger;
+ if (i < 2)
+ b();
+}
+
+function entryIfWithNotOperation() {
+ debugger;
+ if (!false)
+ a();
+ if (!!true)
+ a();
+}
+
// ---------
function test()
@@ -197,6 +230,62 @@
]
});
+ addSteppingTestCase({
+ name: "Debugger.stepping.ConstantBranch",
+ description: "Should pause for constant branches.",
+ _expression_: "setTimeout(entryIfConstantBranch)",
+ steps: [
+ "over",
+ "over", // (true)
+ "over", // a()
+ "over", // (false)
+ "over", // (0)
+ "over", // (null)
+ "resume",
+ ]
+ });
+
+ addSteppingTestCase({
+ name: "Debugger.stepping.IfWithLogicalOperation",
+ description: "Should always pause for a condition with logical operations.",
+ _expression_: "setTimeout(entryIfWithLogicalOperation)",
+ steps: [
+ "over",
+ "in", // into a()
+ "out", // out of a() - before a()
+ "in", // into a()
+ "out", // out of a() - before b()
+ "over", // b() - leaving entry
+ "resume",
+ ]
+ });
+
+ addSteppingTestCase({
+ name: "Debugger.stepping.IfWithBinaryOperation",
+ description: "Should always pause for a condition with logical operations.",
+ _expression_: "setTimeout(entryIfWithBinaryOperation)",
+ steps: [
+ "over",
+ "in", // i < 2 [true]
+ "over", // over b() - leaving entry
+ "resume",
+ ]
+ });
+
+ addSteppingTestCase({
+ name: "Debugger.stepping.IfWithNotOperation",
+ description: "Should always pause for a condition that is a not operation.",
+ _expression_: "setTimeout(entryIfWithNotOperation)",
+ steps: [
+ "over",
+ "in", // !false
+ "over", // a()
+ "in", // !!truth
+ "over", // a() - leaving entry
+ "resume",
+ ]
+ });
+
loadMainPageContent().then(() => {
suite.runTestCasesAndFinish();
});
Modified: trunk/LayoutTests/inspector/debugger/stepping/stepping-loops-expected.txt (207227 => 207228)
--- 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)
@@ -148,7 +148,7 @@
-- Running test case: Debugger.stepping.TraditionalForStepOver
_expression_: setTimeout(entryTraditionalFor)
-STEPS: over, over, over, over, over, over, over, over, resume
+STEPS: over, over, over, over, over, over, over, over, over, resume
PAUSED (debugger-statement)
PAUSE AT entryTraditionalFor:27:5
23 }
@@ -170,6 +170,16 @@
30
ACTION: step-over
+PAUSE AT entryTraditionalFor:28:21
+ 24
+ 25 function entryTraditionalFor() {
+ 26 debugger;
+ -> 27 for (let i = 0; |i < 2; ++i)
+ 28 a();
+ 29 }
+ 30
+
+ACTION: step-over
PAUSE AT entryTraditionalFor:29:9
25 function entryTraditionalFor() {
26 debugger;
@@ -449,7 +459,7 @@
-- Running test case: Debugger.stepping.ForIn
_expression_: setTimeout(entryForIn)
-STEPS: over, over, over, over, over, over, resume
+STEPS: over, over, over, over, over, over, over, resume
PAUSED (debugger-statement)
PAUSE AT entryForIn:41:5
37
@@ -471,6 +481,16 @@
44
ACTION: step-over
+PAUSE AT entryForIn:42:10
+ 38 function entryForIn() {
+ 39 let o = {key1: 1, key2: 2};
+ 40 debugger;
+ -> 41 for (|let property in o)
+ 42 a();
+ 43 }
+ 44
+
+ACTION: step-over
PAUSE AT entryForIn:43:9
39 let o = {key1: 1, key2: 2};
40 debugger;
@@ -481,11 +501,11 @@
45 function entryForOf() {
ACTION: step-over
-PAUSE AT entryForIn:42:26
+PAUSE AT entryForIn:42:10
38 function entryForIn() {
39 let o = {key1: 1, key2: 2};
40 debugger;
- -> 41 for (let property in |o)
+ -> 41 for (|let property in o)
42 a();
43 }
44
@@ -501,11 +521,11 @@
45 function entryForOf() {
ACTION: step-over
-PAUSE AT entryForIn:42:26
+PAUSE AT entryForIn:42:10
38 function entryForIn() {
39 let o = {key1: 1, key2: 2};
40 debugger;
- -> 41 for (let property in |o)
+ -> 41 for (|let property in o)
42 a();
43 }
44
@@ -526,7 +546,7 @@
-- Running test case: Debugger.stepping.ForIn
_expression_: setTimeout(entryForOf)
-STEPS: over, over, over, over, over, over, resume
+STEPS: over, over, over, over, over, over, over, resume
PAUSED (debugger-statement)
PAUSE AT entryForOf:48:5
44
@@ -548,6 +568,16 @@
51
ACTION: step-over
+PAUSE AT entryForOf:49:10
+ 45 function entryForOf() {
+ 46 let arr = [1, 2];
+ 47 debugger;
+ -> 48 for (|let value of arr)
+ 49 a();
+ 50 }
+ 51
+
+ACTION: step-over
PAUSE AT entryForOf:50:9
46 let arr = [1, 2];
47 debugger;
@@ -558,11 +588,11 @@
52 function entryWhileBreakContinue() {
ACTION: step-over
-PAUSE AT entryForOf:49:23
+PAUSE AT entryForOf:49:10
45 function entryForOf() {
46 let arr = [1, 2];
47 debugger;
- -> 48 for (let value of |arr)
+ -> 48 for (|let value of arr)
49 a();
50 }
51
@@ -578,11 +608,11 @@
52 function entryWhileBreakContinue() {
ACTION: step-over
-PAUSE AT entryForOf:49:23
+PAUSE AT entryForOf:49:10
45 function entryForOf() {
46 let arr = [1, 2];
47 debugger;
- -> 48 for (let value of |arr)
+ -> 48 for (|let value of arr)
49 a();
50 }
51
@@ -610,7 +640,7 @@
52 function entryWhileBreakContinue() {
53 let i = 0;
-> 54 |debugger;
- 55 while (true) {
+ 55 while (truthy) {
56 ++i;
57 if (i === 1)
@@ -619,7 +649,7 @@
52 function entryWhileBreakContinue() {
53 let i = 0;
54 debugger;
- -> 55 while (|true) {
+ -> 55 while (|truthy) {
56 ++i;
57 if (i === 1)
58 continue;
@@ -628,7 +658,7 @@
PAUSE AT entryWhileBreakContinue:57:9
53 let i = 0;
54 debugger;
- 55 while (true) {
+ 55 while (truthy) {
-> 56 |++i;
57 if (i === 1)
58 continue;
@@ -637,7 +667,7 @@
ACTION: step-over
PAUSE AT entryWhileBreakContinue:58:13
54 debugger;
- 55 while (true) {
+ 55 while (truthy) {
56 ++i;
-> 57 if (|i === 1)
58 continue;
@@ -646,7 +676,7 @@
ACTION: step-over
PAUSE AT entryWhileBreakContinue:59:13
- 55 while (true) {
+ 55 while (truthy) {
56 ++i;
57 if (i === 1)
-> 58 |continue;
@@ -659,7 +689,7 @@
52 function entryWhileBreakContinue() {
53 let i = 0;
54 debugger;
- -> 55 while (|true) {
+ -> 55 while (|truthy) {
56 ++i;
57 if (i === 1)
58 continue;
@@ -668,7 +698,7 @@
PAUSE AT entryWhileBreakContinue:57:9
53 let i = 0;
54 debugger;
- 55 while (true) {
+ 55 while (truthy) {
-> 56 |++i;
57 if (i === 1)
58 continue;
@@ -677,7 +707,7 @@
ACTION: step-over
PAUSE AT entryWhileBreakContinue:58:13
54 debugger;
- 55 while (true) {
+ 55 while (truthy) {
56 ++i;
-> 57 if (|i === 1)
58 continue;
Modified: trunk/LayoutTests/inspector/debugger/stepping/stepping-loops.html (207227 => 207228)
--- 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)
@@ -4,10 +4,10 @@
<script src=""
<script src=""
<script>
-function a() {
- return 1;
-}
+var truthy = true;
+function a() { return 1; }
+
function entryWhile() {
let i = 2;
debugger;
@@ -53,7 +53,7 @@
function entryWhileBreakContinue() {
let i = 0;
debugger;
- while (true) {
+ while (truthy) {
++i;
if (i === 1)
continue;
@@ -117,7 +117,8 @@
_expression_: "setTimeout(entryTraditionalFor)",
steps: [
"over",
- "over", // complete: let i = 0; i < 2
+ "over", // complete: let i = 0
+ "over", // complete: i < 2
"over", // complete: a()
"over", // complete: ++i
"over", // complete: i < 2 [i=1]
@@ -169,6 +170,7 @@
_expression_: "setTimeout(entryForIn)",
steps: [
"over",
+ "over", // complete: (o)
"over", // complete: let property in o [key1]
"over", // complete: a()
"over", // complete: let property in o [key2]
@@ -184,6 +186,7 @@
_expression_: "setTimeout(entryForOf)",
steps: [
"over",
+ "over", // complete (arr)
"over", // complete: let value of arr [1]
"over", // complete: a()
"over", // complete: let value of arr [2]
Modified: trunk/Source/_javascript_Core/ChangeLog (207227 => 207228)
--- trunk/Source/_javascript_Core/ChangeLog 2016-10-12 18:43:19 UTC (rev 207227)
+++ trunk/Source/_javascript_Core/ChangeLog 2016-10-12 18:47:48 UTC (rev 207228)
@@ -1,3 +1,111 @@
+2016-10-12 Joseph Pecoraro <[email protected]>
+
+ 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<LexerType>::parseForStatement):
+ Provide the location before the declaration starts.
+
2016-10-12 Mark Lam <[email protected]>
Array.prototype.slice should not modify frozen objects.
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (207227 => 207228)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2016-10-12 18:43:19 UTC (rev 207227)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2016-10-12 18:47:48 UTC (rev 207228)
@@ -3504,14 +3504,16 @@
void BytecodeGenerator::emitDebugHook(StatementNode* statement)
{
- RELEASE_ASSERT(statement->needsDebugHook());
+ // DebuggerStatementNode will output its own special debug hook.
+ if (statement->isDebuggerStatement())
+ return;
+
emitDebugHook(WillExecuteStatement, statement->position());
}
-void BytecodeGenerator::emitDebugHook(ExpressionNode* expr, DebugHookType debugHookType)
+void BytecodeGenerator::emitDebugHook(ExpressionNode* expr)
{
- RELEASE_ASSERT(expr->needsDebugHook());
- emitDebugHook(debugHookType, expr->position());
+ emitDebugHook(WillExecuteStatement, expr->position());
}
void BytecodeGenerator::emitWillLeaveCallFrameDebugHook()
@@ -4202,7 +4204,7 @@
if (forLoopNode) {
RELEASE_ASSERT(forLoopNode->isForOfNode());
prepareLexicalScopeForNextForLoopIteration(forLoopNode, forLoopSymbolTable);
- emitDebugHook(forLoopNode->expr(), WillExecuteStatement);
+ emitDebugHook(forLoopNode->lexpr());
}
{
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (207227 => 207228)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2016-10-12 18:43:19 UTC (rev 207227)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2016-10-12 18:47:48 UTC (rev 207228)
@@ -386,6 +386,8 @@
emitThrowExpressionTooDeepException();
return;
}
+ if (UNLIKELY(n->needsDebugHook()))
+ emitDebugHook(n);
n->emitBytecode(*this, dst);
}
@@ -411,6 +413,8 @@
ASSERT(!dst || dst == ignoredResult() || !dst->isTemporary() || dst->refCount());
if (UNLIKELY(!m_vm->isSafeToRecurse()))
return emitThrowExpressionTooDeepException();
+ if (UNLIKELY(n->needsDebugHook()))
+ emitDebugHook(n);
return n->emitBytecode(*this, dst);
}
@@ -430,7 +434,6 @@
emitThrowExpressionTooDeepException();
return;
}
-
n->emitBytecodeInConditionContext(*this, trueTarget, falseTarget, fallThroughMode);
}
@@ -684,7 +687,7 @@
void emitDebugHook(DebugHookType, const JSTextPosition&);
void emitDebugHook(DebugHookType, unsigned line, unsigned charOffset, unsigned lineStart);
void emitDebugHook(StatementNode*);
- void emitDebugHook(ExpressionNode*, DebugHookType);
+ void emitDebugHook(ExpressionNode*);
void emitWillLeaveCallFrameDebugHook();
bool isInFinallyBlock() { return m_finallyDepth > 0; }
Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (207227 => 207228)
--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2016-10-12 18:43:19 UTC (rev 207227)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2016-10-12 18:47:48 UTC (rev 207228)
@@ -94,6 +94,12 @@
void ConstantNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
{
TriState value = jsValue(generator).pureToBoolean();
+
+ if (UNLIKELY(needsDebugHook())) {
+ if (value != MixedTriState)
+ generator.emitDebugHook(this);
+ }
+
if (value == MixedTriState)
ExpressionNode::emitBytecodeInConditionContext(generator, trueTarget, falseTarget, fallThroughMode);
else if (value == TrueTriState && fallThroughMode == FallThroughMeansFalse)
@@ -1669,7 +1675,10 @@
void LogicalNotNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
{
- // reverse the true and false targets
+ if (UNLIKELY(needsDebugHook()))
+ generator.emitDebugHook(this);
+
+ // Reverse the true and false targets.
generator.emitNodeInConditionContext(expr(), falseTarget, trueTarget, invert(fallThroughMode));
}
@@ -1799,6 +1808,11 @@
ExpressionNode* branchExpression;
tryFoldToBranch(generator, branchCondition, branchExpression);
+ if (UNLIKELY(needsDebugHook())) {
+ if (branchCondition != MixedTriState)
+ generator.emitDebugHook(this);
+ }
+
if (branchCondition == MixedTriState)
ExpressionNode::emitBytecodeInConditionContext(generator, trueTarget, falseTarget, fallThroughMode);
else if (branchCondition == TrueTriState)
@@ -2000,6 +2014,9 @@
void LogicalOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
{
+ if (UNLIKELY(needsDebugHook()))
+ generator.emitDebugHook(this);
+
RefPtr<Label> afterExpr1 = generator.newLabel();
if (m_operator == OpLogicalAnd)
generator.emitNodeInConditionContext(m_expr1, afterExpr1.get(), falseTarget, FallThroughMeansTrue);
@@ -2376,9 +2393,9 @@
// ------------------------------ EmptyStatementNode ---------------------------
-void EmptyStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
+void EmptyStatementNode::emitBytecode(BytecodeGenerator&, RegisterID*)
{
- generator.emitDebugHook(this);
+ RELEASE_ASSERT(needsDebugHook());
}
// ------------------------------ DebuggerStatementNode ---------------------------
@@ -2393,7 +2410,6 @@
void ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
ASSERT(m_expr);
- generator.emitDebugHook(this);
generator.emitNode(dst, m_expr);
}
@@ -2402,7 +2418,6 @@
void DeclarationStatement::emitBytecode(BytecodeGenerator& generator, RegisterID*)
{
ASSERT(m_expr);
- generator.emitDebugHook(this);
generator.emitNode(m_expr);
}
@@ -2490,8 +2505,6 @@
void IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
- generator.emitDebugHook(m_condition, WillExecuteStatement);
-
RefPtr<Label> beforeThen = generator.newLabel();
RefPtr<Label> beforeElse = generator.newLabel();
RefPtr<Label> afterElse = generator.newLabel();
@@ -2536,7 +2549,6 @@
generator.emitNodeInTailPosition(dst, m_statement);
generator.emitLabel(scope->continueTarget());
- generator.emitDebugHook(m_expr, WillExecuteStatement);
generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
generator.emitLabel(scope->breakTarget());
@@ -2549,7 +2561,6 @@
LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
RefPtr<Label> topOfLoop = generator.newLabel();
- generator.emitDebugHook(m_expr, WillExecuteStatement);
generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansTrue);
generator.emitLabel(topOfLoop.get());
@@ -2559,7 +2570,6 @@
generator.emitNodeInTailPosition(dst, m_statement);
generator.emitLabel(scope->continueTarget());
- generator.emitDebugHook(m_expr, WillExecuteStatement);
generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
@@ -2577,21 +2587,12 @@
RegisterID* forLoopSymbolTable = nullptr;
generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested, &forLoopSymbolTable);
- 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);
+ if (m_expr1)
generator.emitNode(generator.ignoredResult(), m_expr1);
- }
RefPtr<Label> topOfLoop = generator.newLabel();
- if (m_expr2) {
- generator.emitDebugHook(m_expr2, WillExecuteExpression);
+ if (m_expr2)
generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), FallThroughMeansTrue);
- }
generator.emitLabel(topOfLoop.get());
generator.emitLoopHint();
@@ -2601,15 +2602,12 @@
generator.emitLabel(scope->continueTarget());
generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
- if (m_expr3) {
- generator.emitDebugHook(m_expr3, WillExecuteStatement);
+ if (m_expr3)
generator.emitNode(generator.ignoredResult(), m_expr3);
- }
- if (m_expr2) {
- generator.emitDebugHook(m_expr2, WillExecuteStatement);
+ if (m_expr2)
generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
- } else
+ else
generator.emitJump(topOfLoop.get());
generator.emitLabel(scope->breakTarget());
@@ -2738,8 +2736,6 @@
RegisterID* forLoopSymbolTable = nullptr;
generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested, &forLoopSymbolTable);
- generator.emitDebugHook(m_expr, WillExecuteStatement);
-
if (m_lexpr->isAssignResolveNode())
generator.emitNode(generator.ignoredResult(), m_lexpr);
@@ -2751,6 +2747,9 @@
RefPtr<RegisterID> local = this->tryGetBoundLocal(generator);
RefPtr<RegisterID> enumeratorIndex;
+ // Pause at the assignment _expression_ for each for..in iteration.
+ generator.emitDebugHook(m_lexpr);
+
int profilerStartOffset = m_statement->startOffset();
int profilerEndOffset = m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0);
@@ -2788,7 +2787,7 @@
generator.emitLabel(scope->continueTarget());
generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
generator.emitInc(i.get());
- generator.emitDebugHook(m_expr, WillExecuteStatement);
+ generator.emitDebugHook(m_lexpr); // Pause at the assignment _expression_ for each for..in iteration.
generator.emitJump(loopStart.get());
generator.emitLabel(scope->breakTarget());
@@ -2828,7 +2827,7 @@
generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
generator.emitInc(enumeratorIndex.get());
generator.emitEnumeratorStructurePropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
- generator.emitDebugHook(m_expr, WillExecuteStatement);
+ generator.emitDebugHook(m_lexpr); // Pause at the assignment _expression_ for each for..in iteration.
generator.emitJump(loopStart.get());
generator.emitLabel(scope->breakTarget());
@@ -2865,7 +2864,7 @@
generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
generator.emitInc(enumeratorIndex.get());
generator.emitEnumeratorGenericPropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
- generator.emitDebugHook(m_expr, WillExecuteStatement);
+ generator.emitDebugHook(m_lexpr); // Pause at the assignment _expression_ for each for..in iteration.
generator.emitJump(loopStart.get());
generator.emitLabel(scope->breakTarget());
@@ -2962,8 +2961,6 @@
void ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
{
- generator.emitDebugHook(this);
-
LabelScopePtr scope = generator.continueTarget(m_ident);
ASSERT(scope);
@@ -2991,8 +2988,6 @@
void BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
{
- generator.emitDebugHook(this);
-
LabelScopePtr scope = generator.breakTarget(m_ident);
ASSERT(scope);
@@ -3006,8 +3001,6 @@
void ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
- generator.emitDebugHook(this);
-
ASSERT(generator.codeType() == FunctionCode);
if (dst == generator.ignoredResult())
@@ -3034,8 +3027,6 @@
void WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
- generator.emitDebugHook(m_expr, WillExecuteStatement);
-
RefPtr<RegisterID> scope = generator.emitNode(m_expr);
generator.emitExpressionInfo(m_divot, m_divot - m_expressionLength, m_divot);
generator.emitPushWithScope(scope.get());
@@ -3209,8 +3200,6 @@
void SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
- generator.emitDebugHook(m_expr, WillExecuteStatement);
-
LabelScopePtr scope = generator.newLabelScope(LabelScope::Switch);
RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
@@ -3239,8 +3228,6 @@
void ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
- generator.emitDebugHook(this);
-
if (dst == generator.ignoredResult())
dst = 0;
RefPtr<RegisterID> expr = generator.emitNode(m_expr);
Modified: trunk/Source/_javascript_Core/parser/ASTBuilder.h (207227 => 207228)
--- trunk/Source/_javascript_Core/parser/ASTBuilder.h 2016-10-12 18:43:19 UTC (rev 207227)
+++ trunk/Source/_javascript_Core/parser/ASTBuilder.h 2016-10-12 18:47:48 UTC (rev 207228)
@@ -559,7 +559,7 @@
return result;
}
- StatementNode* createForInLoop(const JSTokenLocation& location, ExpressionNode* lhs, ExpressionNode* iter, StatementNode* statements, const JSTextPosition& eStart, const JSTextPosition& eDivot, const JSTextPosition& eEnd, int start, int end, VariableEnvironment& lexicalVariables)
+ StatementNode* createForInLoop(const JSTokenLocation& location, ExpressionNode* lhs, ExpressionNode* iter, StatementNode* statements, const JSTokenLocation&, const JSTextPosition& eStart, const JSTextPosition& eDivot, const JSTextPosition& eEnd, int start, int end, VariableEnvironment& lexicalVariables)
{
ForInNode* result = new (m_parserArena) ForInNode(location, lhs, iter, statements, lexicalVariables);
result->setLoc(start, end, location.startOffset, location.lineStartOffset);
@@ -567,13 +567,13 @@
return result;
}
- StatementNode* createForInLoop(const JSTokenLocation& location, DestructuringPatternNode* pattern, ExpressionNode* iter, StatementNode* statements, const JSTextPosition& eStart, const JSTextPosition& eDivot, const JSTextPosition& eEnd, int start, int end, VariableEnvironment& lexicalVariables)
+ StatementNode* createForInLoop(const JSTokenLocation& location, DestructuringPatternNode* pattern, ExpressionNode* iter, StatementNode* statements, const JSTokenLocation& declLocation, const JSTextPosition& eStart, const JSTextPosition& eDivot, const JSTextPosition& eEnd, int start, int end, VariableEnvironment& lexicalVariables)
{
- auto lexpr = new (m_parserArena) DestructuringAssignmentNode(location, pattern, 0);
- return createForInLoop(location, lexpr, iter, statements, eStart, eDivot, eEnd, start, end, lexicalVariables);
+ auto lexpr = new (m_parserArena) DestructuringAssignmentNode(declLocation, pattern, nullptr);
+ return createForInLoop(location, lexpr, iter, statements, declLocation, eStart, eDivot, eEnd, start, end, lexicalVariables);
}
- StatementNode* createForOfLoop(const JSTokenLocation& location, ExpressionNode* lhs, ExpressionNode* iter, StatementNode* statements, const JSTextPosition& eStart, const JSTextPosition& eDivot, const JSTextPosition& eEnd, int start, int end, VariableEnvironment& lexicalVariables)
+ StatementNode* createForOfLoop(const JSTokenLocation& location, ExpressionNode* lhs, ExpressionNode* iter, StatementNode* statements, const JSTokenLocation&, const JSTextPosition& eStart, const JSTextPosition& eDivot, const JSTextPosition& eEnd, int start, int end, VariableEnvironment& lexicalVariables)
{
ForOfNode* result = new (m_parserArena) ForOfNode(location, lhs, iter, statements, lexicalVariables);
result->setLoc(start, end, location.startOffset, location.lineStartOffset);
@@ -581,10 +581,10 @@
return result;
}
- StatementNode* createForOfLoop(const JSTokenLocation& location, DestructuringPatternNode* pattern, ExpressionNode* iter, StatementNode* statements, const JSTextPosition& eStart, const JSTextPosition& eDivot, const JSTextPosition& eEnd, int start, int end, VariableEnvironment& lexicalVariables)
+ StatementNode* createForOfLoop(const JSTokenLocation& location, DestructuringPatternNode* pattern, ExpressionNode* iter, StatementNode* statements, const JSTokenLocation& declLocation, const JSTextPosition& eStart, const JSTextPosition& eDivot, const JSTextPosition& eEnd, int start, int end, VariableEnvironment& lexicalVariables)
{
- auto lexpr = new (m_parserArena) DestructuringAssignmentNode(location, pattern, 0);
- return createForOfLoop(location, lexpr, iter, statements, eStart, eDivot, eEnd, start, end, lexicalVariables);
+ auto lexpr = new (m_parserArena) DestructuringAssignmentNode(declLocation, pattern, nullptr);
+ return createForOfLoop(location, lexpr, iter, statements, declLocation, eStart, eDivot, eEnd, start, end, lexicalVariables);
}
bool isBindingNode(const DestructuringPattern& pattern)
@@ -752,21 +752,11 @@
StatementNode* createExportDefaultDeclaration(const JSTokenLocation& location, StatementNode* declaration, const Identifier& localName)
{
- // 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:
- // <https://webkit.org/b/162809> Emit DebugHooks uniformly with pause locations instead of having separate pause locations and op_debug emits
- declaration->setNeedsDebugHook();
return new (m_parserArena) ExportDefaultDeclarationNode(location, declaration, localName);
}
StatementNode* createExportLocalDeclaration(const JSTokenLocation& location, StatementNode* declaration)
{
- // 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:
- // <https://webkit.org/b/162809> Emit DebugHooks uniformly with pause locations instead of having separate pause locations and op_debug emits
- declaration->setNeedsDebugHook();
return new (m_parserArena) ExportLocalDeclarationNode(location, declaration);
}
@@ -983,18 +973,12 @@
node->setStartOffset(offset);
}
- JSTextPosition breakpointLocation(StatementNode* statement)
+ JSTextPosition breakpointLocation(Node* node)
{
- statement->setNeedsDebugHook();
- return statement->position();
+ node->setNeedsDebugHook();
+ return node->position();
}
- JSTextPosition breakpointLocation(ExpressionNode* expr)
- {
- expr->setNeedsDebugHook();
- return expr->position();
- }
-
void propagateArgumentsUse() { usesArguments(); }
private:
Modified: trunk/Source/_javascript_Core/parser/Nodes.h (207227 => 207228)
--- trunk/Source/_javascript_Core/parser/Nodes.h 2016-10-12 18:43:19 UTC (rev 207227)
+++ trunk/Source/_javascript_Core/parser/Nodes.h 2016-10-12 18:47:48 UTC (rev 207228)
@@ -145,9 +145,13 @@
void setEndOffset(int offset) { m_endOffset = offset; }
void setStartOffset(int offset) { m_position.offset = offset; }
+ bool needsDebugHook() const { return m_needsDebugHook; }
+ void setNeedsDebugHook() { m_needsDebugHook = true; }
+
protected:
JSTextPosition m_position;
int m_endOffset;
+ bool m_needsDebugHook { false };
};
class ExpressionNode : public Node {
@@ -191,12 +195,8 @@
ResultType resultDescriptor() const { return m_resultType; }
- bool needsDebugHook() { return m_needsDebugHook; }
- void setNeedsDebugHook() { m_needsDebugHook = true; }
-
private:
ResultType m_resultType;
- bool m_needsDebugHook { false };
};
class StatementNode : public Node {
@@ -213,6 +213,7 @@
void setNext(StatementNode* next) { m_next = next; }
virtual bool isEmptyStatement() const { return false; }
+ virtual bool isDebuggerStatement() const { return false; }
virtual bool isFunctionNode() const { return false; }
virtual bool isReturnNode() const { return false; }
virtual bool isExprStatement() const { return false; }
@@ -224,13 +225,9 @@
virtual bool isModuleDeclarationNode() const { return false; }
virtual bool isForOfNode() const { return false; }
- bool needsDebugHook() { return m_needsDebugHook; }
- void setNeedsDebugHook() { m_needsDebugHook = true; }
-
protected:
StatementNode* m_next;
int m_lastLine;
- bool m_needsDebugHook { false };
};
class VariableEnvironmentNode : public ParserArenaDeletable {
@@ -1366,6 +1363,8 @@
class DebuggerStatementNode : public StatementNode {
public:
DebuggerStatementNode(const JSTokenLocation&);
+
+ bool isDebuggerStatement() const override { return true; }
private:
void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
@@ -1473,6 +1472,7 @@
EnumerationNode(const JSTokenLocation&, ExpressionNode*, ExpressionNode*, StatementNode*, VariableEnvironment&);
+ ExpressionNode* lexpr() const { return m_lexpr; }
ExpressionNode* expr() const { return m_expr; }
protected:
Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (207227 => 207228)
--- trunk/Source/_javascript_Core/parser/Parser.cpp 2016-10-12 18:43:19 UTC (rev 207227)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp 2016-10-12 18:47:48 UTC (rev 207228)
@@ -1186,6 +1186,7 @@
handleProductionOrFail(OPENPAREN, "(", "start", "for-loop header");
int nonLHSCount = m_parserState.nonLHSCount;
int declarations = 0;
+ JSTokenLocation declLocation(tokenLocation());
JSTextPosition declsStart;
JSTextPosition declsEnd;
TreeExpression decls = 0;
@@ -1280,12 +1281,12 @@
gatherLexicalVariablesIfNecessary();
TreeStatement result;
if (isOfEnumeration)
- result = context.createForOfLoop(location, forInTarget, expr, statement, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
+ result = context.createForOfLoop(location, forInTarget, expr, statement, declLocation, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
else {
if (isVarDeclaraton && forInInitializer)
- result = context.createForInLoop(location, decls, expr, statement, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
+ result = context.createForInLoop(location, decls, expr, statement, declLocation, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
else
- result = context.createForInLoop(location, forInTarget, expr, statement, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
+ result = context.createForInLoop(location, forInTarget, expr, statement, declLocation, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
}
popLexicalScopeIfNecessary();
return result;
@@ -1372,17 +1373,17 @@
if (pattern) {
ASSERT(!decls);
if (isOfEnumeration)
- result = context.createForOfLoop(location, pattern, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
+ result = context.createForOfLoop(location, pattern, expr, statement, declLocation, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
else
- result = context.createForInLoop(location, pattern, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
+ result = context.createForInLoop(location, pattern, expr, statement, declLocation, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
popLexicalScopeIfNecessary();
return result;
}
if (isOfEnumeration)
- result = context.createForOfLoop(location, decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
+ result = context.createForOfLoop(location, decls, expr, statement, declLocation, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
else
- result = context.createForInLoop(location, decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
+ result = context.createForInLoop(location, decls, expr, statement, declLocation, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
popLexicalScopeIfNecessary();
return result;
}
Modified: trunk/Source/_javascript_Core/parser/SyntaxChecker.h (207227 => 207228)
--- trunk/Source/_javascript_Core/parser/SyntaxChecker.h 2016-10-12 18:43:19 UTC (rev 207227)
+++ trunk/Source/_javascript_Core/parser/SyntaxChecker.h 2016-10-12 18:47:48 UTC (rev 207228)
@@ -238,8 +238,8 @@
int createIfStatement(const JSTokenLocation&, int, int, int, int) { return StatementResult; }
int createIfStatement(const JSTokenLocation&, int, int, int, int, int) { return StatementResult; }
int createForLoop(const JSTokenLocation&, int, int, int, int, int, int, VariableEnvironment&) { return StatementResult; }
- int createForInLoop(const JSTokenLocation&, int, int, int, int, int, int, int, int, VariableEnvironment&) { return StatementResult; }
- int createForOfLoop(const JSTokenLocation&, int, int, int, int, int, int, int, int, VariableEnvironment&) { return StatementResult; }
+ int createForInLoop(const JSTokenLocation&, int, int, int, const JSTokenLocation&, int, int, int, int, int, VariableEnvironment&) { return StatementResult; }
+ int createForOfLoop(const JSTokenLocation&, int, int, int, const JSTokenLocation&, int, int, int, int, int, VariableEnvironment&) { return StatementResult; }
int createEmptyStatement(const JSTokenLocation&) { return StatementResult; }
int createDeclarationStatement(const JSTokenLocation&, int, int, int) { return StatementResult; }
int createReturnStatement(const JSTokenLocation&, int, int, int) { return StatementResult; }
Modified: trunk/Source/WebInspectorUI/ChangeLog (207227 => 207228)
--- 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)
@@ -1,5 +1,18 @@
2016-10-12 Joseph Pecoraro <[email protected]>
+ 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 "var foo" but include the right hand side "var foo in ..." or
+ "var foo of ...".
+
+2016-10-12 Joseph Pecoraro <[email protected]>
+
Web Inspector: Whole program sometimes highlighted instead of just first statement
https://bugs.webkit.org/show_bug.cgi?id=163300
<rdar://problem/28723162>
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/SourceCodeTextEditor.js (207227 => 207228)
--- 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)
@@ -1236,6 +1236,7 @@
// Find a node starting at this offset.
// Avoid highlighting the entire program if this is the start of the first statement.
+ // Special case the assignment _expression_ inside of a for..of and for..in to highlight a larger range.
for (let node of nodes) {
let startOffset = node.range[0];
if (startOffset === offset && node.type !== WebInspector.ScriptSyntaxTree.NodeType.Program) {
@@ -1242,6 +1243,12 @@
callback(convertRangeOffsetsToSourceCodeOffsets(node.range));
return;
}
+ 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;
+ }
+ }
if (startOffset > offset)
break;
}