Closed Bug 977972 Opened 10 years ago Closed 5 years ago

Breakpoints not working inside callback functions

Categories

(DevTools :: Debugger, defect, P2)

35 Branch
x86
Windows 7
defect

Tracking

(Not tracked)

RESOLVED DUPLICATE of bug 801304

People

(Reporter: lb1.3, Unassigned)

References

(Blocks 2 open bugs)

Details

(Whiteboard: [breakpoint])

Attachments

(1 file, 1 obsolete file)

User Agent: Mozilla/5.0 (Windows NT 6.1; rv:30.0) Gecko/20100101 Firefox/30.0 (Beta/Release)
Build ID: 20140227030203

Steps to reproduce:

Tried debugging callback - for example, go to: http://jsfiddle.net/8uXZk/embedded/result/

In debugger, go to the /show/light/ source and add breakpoint to line 21, and 22:

jQuery.get('',{},function(data) {
   console.log('got '+data); 




Actual results:

When you reload the page, it breaks at the first breakpoint, click "resume", and it goes to the next one, logs output as you would expect.

If you stop at the first breakpoint, "Step over" (F10) and then click "resume", it will continue like it never got to the console.log, but it actually ran, and printed the results in the console!


Expected results:

Breakpoints should work, even if they are in a callback function.
Component: Untriaged → Developer Tools: Debugger
Status: UNCONFIRMED → NEW
Ever confirmed: true
Summary: Debugger doesn't stop at callback function → Breakpoints not working inside callback functions
Still happening in Firefox 35.
Version: 30 Branch → 35 Branch
Here's what I'm seeing in Firefox 36. Not only does it not break at the callback breakpoint, it's not even showing the breakpoint until I click the file to the left.
I can repro, setting devedition-40
Whiteboard: [devedition-40]
I think the root cause here is iframes. On jsfiddle some weird things happen:

1. the parent page is loaded
2. the iframe with the user's code is loaded
3. some user code there runs

the debugger does not seem to be able to tell the difference between the the parent content and the iframe content, possibly because they have similar URLs:

http://jsfiddle.net/8uXZk/embedded/result/

vs 

http://fiddle.jshell.net/8uXZk/show/light/

The netmonitor ( if you run it in a non-e10s window in nightly ) get this right and displays the right source for each url. The debugger does not:

http://note.io/1DTSEhT
Going to take a look at this tomorrow.
Assignee: nobody → ejpbruel
Here's a new attempt. It doesn't change your original check, it just extends the set of cases where we detect an inline source.
Attachment #8602585 - Flags: review?(jlong)
Comment on attachment 8602585 [details] [diff] [review]
Detect inline sources by checking the element that introduced them

Argh, I added this patch to the wrong bug!
Attachment #8602585 - Attachment is obsolete: true
Attachment #8602585 - Flags: review?(jlong)
I can reproduce this bug. Looking into it now.
When I set a breakpoint on line 22 and line 23, and then refresh the page, the breakpoint on line 22 hits, as expected. When I then resume, the breakpoint on line 23 hits, as expected.

However, if I then refresh the page again, wait for the breakpoint on line 22 to hit, and then step to the next line, the onStep handler is never called for the frame corresponding to line 23. That leads me to think there are two possibilities here:

1. Our computation of the location from the frame is wrong (which is doubtful imho)
2. This a bug in the debugger API

Tom, could you take a look into this bug and tell me what your thoughts are?
Flags: needinfo?(ttromey)
I built a new fx-team just now and I can't even see the /show/light source properly.
In the debugger, /show/light and /embedded/result are identical.  Searching in the
debugger for "console.log" does not find the line emitting the "got ..." to the console.

But, this line is being executed; and in the network tool, the XHR for /show/light
does show the correct source.

I'm not sure how to reproduce this enough to investigate the bug.
It seems as though some other bug has crept in to obscure the situation.
Flags: needinfo?(ttromey)
(In reply to Tom Tromey :tromey from comment #10)

> I'm not sure how to reproduce this enough to investigate the bug.
> It seems as though some other bug has crept in to obscure the situation.

The patch from bug 1158498 helps here.
(In reply to Eddy Bruel [:ejpbruel] from comment #9)

> However, if I then refresh the page again, wait for the breakpoint on line
> 22 to hit, and then step to the next line, the onStep handler is never
> called for the frame corresponding to line 23. That leads me to think there
> are two possibilities here:
> 
> 1. Our computation of the location from the frame is wrong (which is
> doubtful imho)
> 2. This a bug in the debugger API
> 
> Tom, could you take a look into this bug and tell me what your thoughts are?

Something is definitely odd here.

When I continue to hit the breakpoint on line 23, the stack does not
have the /show/light source anywhere except the innermost frame.
What this means to me is that the callback is being invoked asynchronously.

However, then I reload.  The debugger stops at the breakpoint on line 22.
Now if I step over, it moves to line line 24.  Ok so far.
But now if I continue -- the breakpoint on line 22 is not hit.
I don't understand this behavior.

But wait!  There is more not to understand!
I stopped at the first breakpoint and cleared the console.
Then I did a step-over.
At this point I see the console log, so now the callback
seems to be running synchronously -- which makes no sense to me.
Maybe the backtrace in experiment #1 was incorrect somehow?
From looking at the code, it seems that we are doing an asynchronous XHR request here, so the callback should be invoked asynchronously.

That made me remember bug 801304. Nested event loops, the mechanism we use to create the illusion that the debuggee is paused, do not properly suppress XHR events. This is just a hunch, but that means the callback could be invoked while the debugger is not ready for it, and the debuggee is supposed to be paused.

This would explain the weird discrepancy we're seeing where the callback seems to be invoked asynchronously one time, but synchronously another (after the step-over, the debuggee is supposed to be paused, but XHR events can still be triggered, causing the callback to be invoked).
Depends on: 801304
I'm going to see if I can fix bug 801304. If my hypothesis is correct, this should automagically fix this bug.
Priority: -- → P1
Whiteboard: [devedition-40] → [polish-backlog]
Whiteboard: [polish-backlog] → [polish-backlog][difficulty=hard]
Assignee: ejpbruel → nobody
I tested this again in Firefox 58, and I'm not sure to follow what the problem is:

I see the following code and set the following breakpoints:

    $(window).load(function(){
 >  jQuery.get('',{},function(data) {
 >     console.log('got '+data); 
    });
    });//]]> 

If I reload, I'm paused here:

    $(window).load(function(){
*>  jQuery.get('',{},function(data) {
 >     console.log('got '+data); 
    });
    });//]]> 

If I step over, I end up here (last line of the code block):

    $(window).load(function(){
 >  jQuery.get('',{},function(data) {
 >     console.log('got '+data); 
    });
*   });//]]> 

This is expected, right? I stepped over the get function call.
And in the console, I can see the expected output.
So from there, if I resume, I don't hit the second breakpoint because that part of the code has already been executed.

If, instead of stepping over I just resume, here is the flow. I start here:

    $(window).load(function(){
*>  jQuery.get('',{},function(data) {
 >     console.log('got '+data); 
    });
    });//]]> 

I hit resume, end up here:

    $(window).load(function(){
 >  jQuery.get('',{},function(data) {
*>     console.log('got '+data); 
    });
    });//]]> 

Expected too, right? Then I hit resume again:

    $(window).load(function(){
 >  jQuery.get('',{},function(data) {
 >     console.log('got '+data); 
    });
    });//]]> 

Now the console contains the output and the debugger isn't paused anymore.

I fail to see a problem here. Maybe someone can clarify. In the meantime, moving down to P2.
Priority: P1 → P2
Whiteboard: [polish-backlog][difficulty=hard] → [breakpoint]
Blocks: dbg-r2c
Product: Firefox → DevTools
I can reproduce this bug, and it is fixed by the patch in bug 801304.

(In reply to Patrick Brosset <:pbro> from comment #15)
> This is expected, right? I stepped over the get function call.
> And in the console, I can see the expected output.
> So from there, if I resume, I don't hit the second breakpoint because that
> part of the code has already been executed.

The second breakpoint should hit when doing this resume: this callback runs asynchronously and shouldn't be called until after the script calling jQuery.get returns.  The problem is that we do invoke that callback when pausing after the step-over and spinning the event loop.  The handler for the breakpoint in the callback should be hit, but ThreadActor._paused ignores nested attempts to pause, so the UI never pauses at that breakpoint.

The fix in bug 801304 avoids doing XHR activity when spinning the event loop while the main thread's actor is paused.  The callback doesn't run until after the thread unpauses, and its breakpoint will be hit when resuming.
Status: NEW → RESOLVED
Closed: 5 years ago
Resolution: --- → DUPLICATE
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: