Bug 147664 - Web Inspector: Add breakpoint option to ignore n times before stopping
Summary: Web Inspector: Add breakpoint option to ignore n times before stopping
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Web Inspector (show other bugs)
Version: 528+ (Nightly build)
Hardware: All All
: P2 Normal
Assignee: Matt Baker
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2015-08-04 17:05 PDT by Matt Baker
Modified: 2015-10-02 20:18 PDT (History)
8 users (show)

See Also:


Attachments
[Patch] WIP (22.87 KB, patch)
2015-08-28 14:41 PDT, Matt Baker
no flags Details | Formatted Diff | Diff
[Video] Using the "Ignore" option (5.79 MB, video/quicktime)
2015-08-28 14:43 PDT, Matt Baker
no flags Details
[Patch] Proposed Fix (30.75 KB, patch)
2015-09-29 14:56 PDT, Matt Baker
no flags Details | Formatted Diff | Diff
[Patch] Proposed Fix (34.44 KB, patch)
2015-10-02 14:39 PDT, Matt Baker
no flags Details | Formatted Diff | Diff
[Patch] Proposed Fix (24.12 KB, patch)
2015-10-02 18:35 PDT, Matt Baker
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Matt Baker 2015-08-04 17:05:58 PDT
* SUMMARY
Add breakpoint option to ignore n times before stopping. Breakpoints in Xcode have this feature.
Comment 1 Radar WebKit Bug Importer 2015-08-13 16:23:31 PDT
<rdar://problem/22278809>
Comment 2 Matt Baker 2015-08-27 14:51:04 PDT
I checked how breakpoints in Xcode behave when both a Condition and Ignore count are specified. In Xcode the Condition is not evaluated until the hit count exceeds the ignore count. For example:

BREAKPOINT
----------
Line: 2
Condition: "i & 1"
Ignore Count: 5
Log message action: "@i@"


SAMPLE CODE
-----------
  01: for (int i = 0; i < 10; ++i) {
> 02:    // Do stuff
  03: }

OUTPUT
------
5
7
9
Comment 3 Matt Baker 2015-08-28 14:41:54 PDT
Created attachment 260180 [details]
[Patch] WIP

Just need to write a test
Comment 4 Matt Baker 2015-08-28 14:43:06 PDT
Created attachment 260181 [details]
[Video] Using the "Ignore" option
Comment 5 Joseph Pecoraro 2015-08-28 16:03:05 PDT
Comment on attachment 260180 [details]
[Patch] WIP

View in context: https://bugs.webkit.org/attachment.cgi?id=260180&action=review

Needs tests.

Would it be worth updating the frontend with "# Skips Remaining" events?

> Source/JavaScriptCore/inspector/protocol/Debugger.json:52
> +                { "name": "ignoreCount", "type": "integer", "optional": 0, "description": "Number of times to ignore this breakpoint, before stopping on the breakpoint and running actions." }

Nit: `"optional": 0` should instead be `"optional": true`
Comment 6 Joseph Pecoraro 2015-08-28 16:58:10 PDT
(In reply to comment #5)
> Comment on attachment 260180 [details]
> [Patch] WIP
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=260180&action=review
> 
> Needs tests.
> 
> Would it be worth updating the frontend with "# Skips Remaining" events?
> 
> > Source/JavaScriptCore/inspector/protocol/Debugger.json:52
> > +                { "name": "ignoreCount", "type": "integer", "optional": 0, "description": "Number of times to ignore this breakpoint, before stopping on the breakpoint and running actions." }
> 
> Nit: `"optional": 0` should instead be `"optional": true`

In fact, I think that the generator should throw an exception here, since it type checks this.
Comment 7 BJ Burg 2015-09-01 09:42:55 PDT
Comment on attachment 260180 [details]
[Patch] WIP

View in context: https://bugs.webkit.org/attachment.cgi?id=260180&action=review

This looks good, just needs tests. Ask if you need help. Setting r- to remove it from the review queue.

> Source/JavaScriptCore/debugger/Breakpoint.h:44
> +        , hitCount(0)

Please use brace initializers in the declaration.

> Source/JavaScriptCore/inspector/ScriptBreakpoint.h:89
> +    int ignoreCount;

Here too. Even if all constructors initialize the value (right now), it's a good habit to take up.

BTW, this should also be unsigned to match Breakpoint's field.

>>> Source/JavaScriptCore/inspector/protocol/Debugger.json:52
>>> +                { "name": "ignoreCount", "type": "integer", "optional": 0, "description": "Number of times to ignore this breakpoint, before stopping on the breakpoint and running actions." }
>> 
>> Nit: `"optional": 0` should instead be `"optional": true`
> 
> In fact, I think that the generator should throw an exception here, since it type checks this.

Filed: https://bugs.webkit.org/show_bug.cgi?id=148679

> Source/WebInspectorUI/UserInterface/Models/Breakpoint.js:395
> +            const match = /^[0-9]*$/.exec(event.target.value);

const [match,] = ...
ignoreCount = match ? parseInt(match, 10) : 0

> Source/WebInspectorUI/UserInterface/Models/Breakpoint.js:450
> +            // COMPATIBILITY (iOS 9): Legacy backends don't support breakpoint ignore count. Since support

This is fine for now, but I filed a bug about how we can do it better: https://bugs.webkit.org/show_bug.cgi?id=148680
Comment 8 Matt Baker 2015-09-11 09:19:53 PDT
Comment on attachment 260180 [details]
[Patch] WIP

View in context: https://bugs.webkit.org/attachment.cgi?id=260180&action=review

>> Source/JavaScriptCore/inspector/ScriptBreakpoint.h:89
>> +    int ignoreCount;
> 
> Here too. Even if all constructors initialize the value (right now), it's a good habit to take up.
> 
> BTW, this should also be unsigned to match Breakpoint's field.

I agree, however there is a bit of a ripple effect here. InspectorDebuggerAgent APIs deal with ints, likely requiring casts. InspectorObjectBase also lacks function templates for setInteger (for which a FIXME exists). We should do this work under a separate issue.

>> Source/WebInspectorUI/UserInterface/Models/Breakpoint.js:395
>> +            const match = /^[0-9]*$/.exec(event.target.value);
> 
> const [match,] = ...
> ignoreCount = match ? parseInt(match, 10) : 0

I do like this style, but is there a particular reason to prefer this?

>> Source/WebInspectorUI/UserInterface/Models/Breakpoint.js:450
>> +            // COMPATIBILITY (iOS 9): Legacy backends don't support breakpoint ignore count. Since support
> 
> This is fine for now, but I filed a bug about how we can do it better: https://bugs.webkit.org/show_bug.cgi?id=148680

I'll add a // FIXME referring to the bug.
Comment 9 Devin Rousso 2015-09-13 23:04:31 PDT
Comment on attachment 260180 [details]
[Patch] WIP

View in context: https://bugs.webkit.org/attachment.cgi?id=260180&action=review

>>> Source/WebInspectorUI/UserInterface/Models/Breakpoint.js:395
>>> +            const match = /^[0-9]*$/.exec(event.target.value);
>> 
>> const [match,] = ...
>> ignoreCount = match ? parseInt(match, 10) : 0
> 
> I do like this style, but is there a particular reason to prefer this?

NIT: I almost feel like just calling "parseInt(event.target.value)" on the value would be simpler.  Then you could check for "isNaN(ignoreCount)" and "ignoreCount < 0" and set ignoreCount to 0 if either is true.

> Source/WebInspectorUI/UserInterface/Models/Breakpoint.js:461
> +                this._ignoreCountInput.max = 1000000;

NIT: Is there any particular reason that you are specifying a maximum here?
Comment 10 Matt Baker 2015-09-29 14:56:48 PDT
Created attachment 262111 [details]
[Patch] Proposed Fix
Comment 11 Matt Baker 2015-09-29 15:04:17 PDT
(In reply to comment #9)
> Comment on attachment 260180 [details]
> [Patch] WIP
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=260180&action=review
> 
> >>> Source/WebInspectorUI/UserInterface/Models/Breakpoint.js:395
> >>> +            const match = /^[0-9]*$/.exec(event.target.value);
> >> 
> >> const [match,] = ...
> >> ignoreCount = match ? parseInt(match, 10) : 0
> > 
> > I do like this style, but is there a particular reason to prefer this?
> 
> NIT: I almost feel like just calling "parseInt(event.target.value)" on the
> value would be simpler.  Then you could check for "isNaN(ignoreCount)" and
> "ignoreCount < 0" and set ignoreCount to 0 if either is true.

It's simpler. I'll change it.

> > Source/WebInspectorUI/UserInterface/Models/Breakpoint.js:461
> > +                this._ignoreCountInput.max = 1000000;
> 
> NIT: Is there any particular reason that you are specifying a maximum here?

It was arbitrary. We don't range check other numeric values before shipping over the protocol, so I removed it.
Comment 12 Joseph Pecoraro 2015-09-29 16:53:27 PDT
Comment on attachment 262111 [details]
[Patch] Proposed Fix

View in context: https://bugs.webkit.org/attachment.cgi?id=262111&action=review

Nice!

What should the behavior be across reloads. Is the breakpoint still "alive" or does its ignore/hit count reset to 0?

> Source/JavaScriptCore/debugger/Breakpoint.h:70
> +    unsigned hitCount {0};

Style: We've been converging on style with spaces, like "unsigned foo { 0 };".

> Source/JavaScriptCore/debugger/Debugger.cpp:424
> +    if (breakpoint->ignoreCount >= ++breakpoint->hitCount)
> +        return false;

Style: As elegant as this is, I think we tend to break up the increment and comparison into multiple lines for maximum clarity.

> Source/JavaScriptCore/inspector/ScriptBreakpoint.h:89
> +    int ignoreCount {0};

Style: Same style here.

> Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.cpp:308
> +        options->getInteger(ASCIILiteral("ignoreCount"), ignoreCount);

We should verify that ignoreCount >= 0, and 0 if missing.

> Source/WebInspectorUI/UserInterface/Models/Breakpoint.js:156
> +        this._ignoreCount = ignoreCount;

Nit: console.assert(ignoreCount >= 0)
Comment 13 Matt Baker 2015-09-29 17:00:51 PDT
(In reply to comment #12)
> Comment on attachment 262111 [details]
> [Patch] Proposed Fix
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=262111&action=review
> 
> Nice!
> 
> What should the behavior be across reloads. Is the breakpoint still "alive"
> or does its ignore/hit count reset to 0?

I hadn't considered this! The hit count should definitely reset to zero on reload. I'll make sure this is the case in the patch for landing.
Comment 14 Matt Baker 2015-10-01 13:32:52 PDT
Comment on attachment 262111 [details]
[Patch] Proposed Fix

View in context: https://bugs.webkit.org/attachment.cgi?id=262111&action=review

>> Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.cpp:308
>> +        options->getInteger(ASCIILiteral("ignoreCount"), ignoreCount);
> 
> We should verify that ignoreCount >= 0, and 0 if missing.

InspectorObjectBase::getInteger doesn't modify the output variable if the name is missing, so the value will be zero by default. I'll change ignoreCount to unsigned.
Comment 15 Joseph Pecoraro 2015-10-01 14:22:31 PDT
(In reply to comment #14)
> Comment on attachment 262111 [details]
> [Patch] Proposed Fix
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=262111&action=review
> 
> >> Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.cpp:308
> >> +        options->getInteger(ASCIILiteral("ignoreCount"), ignoreCount);
> > 
> > We should verify that ignoreCount >= 0, and 0 if missing.
> 
> InspectorObjectBase::getInteger doesn't modify the output variable if the
> name is missing, so the value will be zero by default. I'll change
> ignoreCount to unsigned.

This value may come in through the protocol. An endpoint can send any integer value.
Comment 16 Matt Baker 2015-10-02 14:39:56 PDT
Created attachment 262351 [details]
[Patch] Proposed Fix

Added a second test, addressed style issues
Comment 17 Joseph Pecoraro 2015-10-02 15:05:48 PDT
Comment on attachment 262351 [details]
[Patch] Proposed Fix

View in context: https://bugs.webkit.org/attachment.cgi?id=262351&action=review

r=me

> Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.cpp:355
> +    int ignoreCount = 0;

Seems this one should be unsigned as well.

> LayoutTests/inspector/debugger/breakpoint-ignore-after-reload-expected.txt:4
> +inside breakpointBasic
> +Was inside breakpoint after page reload.

This worries me that the test might be flakey. I think there is a preexisting issue that reloadPage can cause the test to have flakey output. If you run this test 100 times `run-webkit-tests --iterations=100 inspector/debugger/breakpoint-ignore-after-reload.html` is it flakey? We might need to mark it as such if it is.
Comment 18 Matt Baker 2015-10-02 18:23:16 PDT
(In reply to comment #17)
> Comment on attachment 262351 [details]
> [Patch] Proposed Fix
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=262351&action=review
> 
> r=me
> 
> > Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.cpp:355
> > +    int ignoreCount = 0;
> 
> Seems this one should be unsigned as well.
> 
> > LayoutTests/inspector/debugger/breakpoint-ignore-after-reload-expected.txt:4
> > +inside breakpointBasic
> > +Was inside breakpoint after page reload.
> 
> This worries me that the test might be flakey. I think there is a
> preexisting issue that reloadPage can cause the test to have flakey output.
> If you run this test 100 times `run-webkit-tests --iterations=100
> inspector/debugger/breakpoint-ignore-after-reload.html` is it flakey? We
> might need to mark it as such if it is.

It ran 1000 times without problems. Is the reloadPage flakiness related to the frontend test harness resending results?
Comment 19 Matt Baker 2015-10-02 18:35:25 PDT
Created attachment 262373 [details]
[Patch] Proposed Fix
Comment 20 WebKit Commit Bot 2015-10-02 20:18:47 PDT
Comment on attachment 262373 [details]
[Patch] Proposed Fix

Clearing flags on attachment: 262373

Committed r190542: <http://trac.webkit.org/changeset/190542>
Comment 21 WebKit Commit Bot 2015-10-02 20:18:52 PDT
All reviewed patches have been landed.  Closing bug.