microsoft / microsoft/vscode-js-debug
Breakpoints in anonymous functions are sometimes disabled in a transpiled language using source maps
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 2k
- Forks
- 373
- Avg merge
- 1d 9m
- Merged PRs (30d)
- 6
Description
This is a bit of an esoteric use-case, but I would still very much like to solve it,
since it hampers development in my language: SmallJS ( https://github.com/Small-JS/SmallJS ).
This issue is perhaps for someone with a deeper knowledge of SourceMaps in VSCode.
SmallJS is a Smalltalk (ST) dialect that transpiles to JavaScript (JS).
Using SourceMaps I can succesfully debug the ST source code that is executing in JS.
For every ST function call (message send), a positioned SourceNode is generated
with line and column number, so VSCode can halt on set breakpoints and inspect variables.
In most cases this works great.
ST also has the concept of anonymous functions, called blocks, with square brackets [ ],
that are transpiled directly to their JS equivalents.
Now the problem:
In some case, on starting debugging, VSCode disables (unbinds) breakpoints set within these blocks.
and the code will execute without the debugger being activated.
Below is an ST code fragment wth 2 log statements, each within an anonymous function, with a breakpoint set.
- In the 1st example "log: 'h1'" the breakpoint is kept after starting and it works correctly.
- In the 2nd example "log: 'h2'" the breakpoint is removed (greyed out, unbound) after starting and does not work.
And I'm quite certain the SourceNodes for the SourceMap are generated correctly, the same as for the 1st,
And the console also logs 'h2', so the function is called. - Below the ST code is the transpiled JS code, where breakpoints work correctly on both examples
when set directly in JS on the log statements.
So the question is how to get the breakpoint in case 2 to work correctly.
(BTW a very common use-case in Smalltalk).
Any help is greatly appreciated.
Cheers,
Richard
--
Screenshot:
ST code:
myTest
"Setting a breakpoint within this block on the log statement works:"
| block |
block := [
self log: 'h1' ].
block value. "Executes the anonymous function"
"... but setting a breakpoint this log statement does *not* work."
true ifTrue: [
self log: 'h2' ].
!
Tanspiled JS code: (breakpoints work normally)
$myTest()
{
let block = stNil;
block = stBlock$class.$fromJs$( ( ) => {
return this.$log$( stString$class.$fromJs$( 'h1' ) );
} );
block.$value();
stTrue.$ifTrue$( stBlock$class.$fromJs$( ( ) => {
return this.$log$( stString$class.$fromJs$( 'h2' ) );
} ) );
return this;
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the breakpoint behavior with the SmallJS ST fragment and the transpiled JavaScript shown in the issue. Inspect how the debugger binds source-mapped breakpoints inside the two anonymous functions, comparing the working block value case with the failing ifTrue case. Done means the second source-level breakpoint remains bound and pauses execution.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, typescript, vscode
- Domain
- devtools
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 32/100