Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support pausing the debugger on script load #24687

Closed
roblourens opened this issue Nov 28, 2018 · 23 comments
Closed

Support pausing the debugger on script load #24687

roblourens opened this issue Nov 28, 2018 · 23 comments
Labels
feature request Issues that request new features to be added to Node.js. inspector Issues and PRs related to the V8 inspector protocol stale

Comments

@roblourens
Copy link

There is a Node debugging scenario that doesn't work very well in vscode (or chrome devtools), but does in debugging Chrome, and I want to start a discussion about how we can improve this.

Typically when debugging a Node project with sourcemaps, the scripts are transpiled to disk, vscode's launch config points at these files with the "outFiles" parameter, then vscode preloads the sourcemaps so it can set breakpoints in the correct locations before the scripts are actually loaded.

But there is a scenario where scripts are transpiled on demand, so vscode can't preload their sourcemaps, and can't set breakpoints at the right spots in those scripts until some time after they are loaded. This means that the breakpoints may not be hit, due to the race between running the code and setting the breakpoint at the same time. The best way for vscode to deal with this would be to have node pause execution each time a script is loaded, giving it a chance to load its sourcemaps and set the breakpoint before running the code in the script.

The Chrome devtools protocol for Chrome actually gives us a way to pause execution each time a script is loaded, via https://chromedevtools.github.io/devtools-protocol/1-3/DOMDebugger#method-setEventListenerBreakpoint. But this is in the DOMDebugger domain which doesn't exist in Node.

So what do you think it would take to get an api like this for node as well? Can nodejs implement a subset of the DOMDebugger domain, does a new domain need to be defined? Or maybe someone has an idea for another solution entirely.

@mike-kaufman
Copy link

/cc @ofrobots, @eugeneo - I think you two have context here on the CrDP protocol integration into Node?

@alexkozy
Copy link
Member

alexkozy commented Nov 28, 2018

I believe that this method should be called setInstrumentationBreakpoint and should be part of Debugger domain, so it should be implemented in V8 and can be backported to Node 10.
It could be even smarter and be something like scriptWithSourceMapParsed to reduce performance overhead.

@hashseed hashseed added the diag-agenda Issues and PRs to discuss during the meetings of the diagnostics working group. label Nov 28, 2018
@hashseed
Copy link
Member

Seems like we should just expose the after-compile event to the devtools protocol?

@alexkozy
Copy link
Member

After compile events are exposed as Debugger.scriptParsed and Debugger.scriptFailedToParse events. In this use case it is important to not just send event but to pause JavaScript execution as well to give DevTools or VSCode frontends chance to fetch source map and set breakpoints based on this source map.

@alexkozy
Copy link
Member

DOMDebugger.setEventListenerBreakpoint for pause at first line should actually be moved all together to Debugger.setInstrumentationBreakpoint. It will help with crbug.com/724793 as well.

@hashseed
Copy link
Member

So I guess could expose an option that can be enabled which causes the Debugger.scriptParsed event to behave like a debugger pause that needs manual resume?

@hashseed
Copy link
Member

Do you envision this breakpoint to break at parsing/compiling, or upon execution?

@alexkozy
Copy link
Member

I prefer to emit regular Debugger.paused event, implementation wise it should be easier, with reason - instrumentationBreakpoint and instrumentationType inside data object, it should be less 'surprising' for different protocol clients and better aligned with existing DOMDebugger behavior.
If this breakpoint is set we schedule pause on next function call using v8::debug::SetBreakOnNextFunctionCall. Ideally we should get another callback from V8 when top level function is finished to clear requested break if no javascript was executed but I am not sure that this case is possible.
I believe that this breakpoint should trigger break at first script line.

@roblourens
Copy link
Author

roblourens commented Nov 28, 2018

Fixing http://crbug.com/724793 would be very helpful too!

I think the break should happen immediately before execution. It should happen after Debugger.scriptParsed, because we need the sourcemapURL that comes with that event. And in some cases we would need the script id to set breakpoints.

+1 for

I prefer to emit regular Debugger.paused event, implementation wise it should be easier, with reason - instrumentationBreakpoint and instrumentationType inside data object, it should be less 'surprising' for different protocol clients and better aligned with existing DOMDebugger behavior.

@hashseed
Copy link
Member

Iirc SetBreakOnNextFunctionCall would pause before we even enter the top-level function. Sgtm.

@alexkozy
Copy link
Member

We can actually provide sourceMappingURL and sourceURL inside data param of Debugger.paused to make it easier.

@hashseed
Copy link
Member

Now that I think about this, triggering the pause at the after-compile event is probably more straightforward to implement. Otherwise we would have to schedule a pause and remember until that pause for what reason we paused (and what script URL to pass).

@alexkozy
Copy link
Member

We already have infrastructure for this use case - V8DebuggerAgentImpl::schedulePauseOnNextStatement method. So we need to call this method from V8DebuggeragentImpl::didParseSource, we just need to add another flag to this method to distinguish call to this method from V8 and from V8DebuggerAgentImpl::enable method.

@alexkozy
Copy link
Member

I uploaded patch for V8: CL. It looks good to me but definitely requires accurate review 😄

@roblourens
Copy link
Author

That was fast! This looks great, scriptWithSourceMapParsed is a good idea and will help a ton with perf.

One question - what happens when this is enabled and there is a breakpoint on the first line of the script? Ideally, the debugger can

  • Hit the instrumentation breakpoint
  • Continue
  • Hit the user breakpoint on (1,1)

This API in Chrome used to work that way. Then at some point the behavior changed such that if we continue from the instrumentation bp, it will skip the user bp at 1,1, so we now have to check manually whether the user set a bp there.

@mike-kaufman
Copy link

Any update here? Seems like the v8 CL is still open with some pending comments?

@mhdawson
Copy link
Member

Kevin was going to follow up since person who opened left Google.

@alexkozy
Copy link
Member

alexkozy commented Apr 18, 2019

I addressed comments and I hope to get review and land my CL soon. It was very busy December and later I forgot about this thread - sorry!

@alexkozy
Copy link
Member

My commit was finally landed. Test might be good starting point to see how to use this new API.
I am wondering should we backport it to Node 12, don't we?

@mhdawson
Copy link
Member

Just waiting on a backport to Node.js 12.x and then we can close

@mhdawson mhdawson removed the diag-agenda Issues and PRs to discuss during the meetings of the diagnostics working group. label May 15, 2019
@alexkozy
Copy link
Member

Could someone approve backport #27720 please? :)

alexkozy pushed a commit to alexkozy/node that referenced this issue Aug 2, 2019
Original commit message:

inspector: added Debugger.setInstrumentationBreakpoint method

There are two possible type:
- scriptParsed - breakpoint for any script,
- scriptWithSourceMapParsed - breakpoint for script with
  sourceMappingURL.

When one of the breakpoints is set then for each matched script
we add breakpoint on call to top level function of that script.

Node: nodejs#24687
@jasnell jasnell added feature request Issues that request new features to be added to Node.js. inspector Issues and PRs related to the V8 inspector protocol labels Jun 26, 2020
@github-actions
Copy link
Contributor

github-actions bot commented Mar 8, 2022

There has been no activity on this feature request for 5 months and it is unlikely to be implemented. It will be closed 6 months after the last non-automated comment.

For more information on how the project manages feature requests, please consult the feature request management document.

@github-actions
Copy link
Contributor

github-actions bot commented Apr 8, 2022

There has been no activity on this feature request and it is being closed. If you feel closing this issue is not the right thing to do, please leave a comment.

For more information on how the project manages feature requests, please consult the feature request management document.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request Issues that request new features to be added to Node.js. inspector Issues and PRs related to the V8 inspector protocol stale
Projects
None yet
Development

No branches or pull requests

6 participants