Skip to content
This repository has been archived by the owner on Oct 2, 2021. It is now read-only.

add support to eval code #221

Closed
wants to merge 6 commits into from
Closed

Conversation

Alphapage
Copy link

No description provided.

@Alphapage
Copy link
Author

Related to #220
Removes global hack.
I needed to put export in a neutral file (ie index.ts) instead of regular file !

@auchenberg
Copy link
Contributor

auchenberg commented Jul 24, 2017

Thanks for the contribution! So to understand this PR correctly, it adds a temporally cache of inline sources from the stack frames?

Please incorporate the feedback from #220 (comment)

There's currently a pending question on 0 vs 1-indexing for eval

@Alphapage
Copy link
Author

Before my PR, you could see a 'VM...' file displayed with the transpiled source generated at runtime for eval code.
Now, the file is identified, sourcemapped dynamically and you see a 'origin.js' file displayed instead of 'VM...'.

It seems to work as expected from my quick tests, but the remaining problem is to find a way to display the dynamically generated code in the UI when we want to inspect the transpiled code for example.

@roblourens
Copy link
Member

I'd like to leave this open until I have a little time to dig into what chrome devtools actually does in this case. I have all the same info they do. I suspect you're right about adding an arbitrary line offset to these scripts, but I'd like to understand it a little better before I merge it.

@Alphapage
Copy link
Author

No problem. I use vscode node-debug2 with my customized vscode-chrome-debug-core for nodejs and chrome devtools for web development.
I hope you will find a better way than registering url in evalSources: chrome devtools engine should have the info somewhere, but maybe doesn't share.

@microsoft microsoft deleted a comment from msftclas Sep 26, 2017
@Alphapage
Copy link
Author

Finally,
I found what is disturbing me. The debugger removes the breakpoints when they are unreachable by chrome debugger. I think the right behaviour would be to keep original breakpoints, but turn them as unreachable breakpoints.
So, I try to add those lines :

let id:number=response.breakpoints[response.breakpoints.length-1].id+1
                for (const bp of args.originalBPs)
                    if (!response.breakpoints.some(responseBP=>{return bp.line==responseBP.line}))
                        response.breakpoints.push({...bp,column:0,verified:false,id:id++,message:'Unreachable breakpoint'})

after https://github.com/Microsoft/vscode-chrome-debug-core/blob/master/src/transformers/baseSourceMapTransformer.ts#L178 without success.
The breakpoints are always removed.

For info this._requestSeqToSetBreakpointsArgs.delete(requestSeq); should be outside of the forEach loop block. ;-)

I close the PR, but I hope you will continue the discussion and share your opinion about this subject.

@Alphapage Alphapage closed this Nov 8, 2017
@roblourens
Copy link
Member

I don't understand. What do you mean by "unreachable"? Are you describing the same issue as before, or a new one?

Any breakpoint that can be bound by Chrome should still be returned, and grayed out in the UI, with some useful message.

@Alphapage
Copy link
Author

Finally, I found a way (or a hack !) to solve the problem of this boring eval shift.
As I was telling, during eval , chrome surrounds the code with

(function(...args) { 
// the source code
}`

So, now there is a shift between the generated code and chrome parsed code. vscode-chrome-debug-core maps the generated code, then send the resulting breakpoints to chrome debugger. But we need to shift the first lines to tell chrome debugger to stop at the right position.
I didn't find any info about this shift problem and how to deal with the chrome debugger api, so I think the only way is to detect when the code is an eval one.
I changed the resolvePendingBPs in chromeDebugAdapter.ts to :

 const resolvePendingBPs = (source    )        => {
            if (this._pendingBreakpointsByUrl.has(source)) {
               
                (script as any).lineShift =0
        if (!(script as any).eval)
        (script as any).eval = !utils.existsSync(script.url)
    if ((script as any).eval) {
        this.source({ sourceReference: this.getSourceReferenceForScriptId(script.scriptId) }).then((sourceResponseBody)=>{
        if (sourceResponseBody) {
            const shiftRegExp = /\((\s|.)*?function(\s|.)*?\((\s|.)*?\)(\s|.)*?{(\s|.)*?\n/;
            const str=sourceResponseBody.content
            const match= new RegExp(shiftRegExp).exec(str)
            if (match && match.index === 0) {
                const lineShift = match[0].split('\n').length - 1;
                (script as any).lineShift = lineShift

            }
        }

        const pendingBPsArgs=(this._pendingBreakpointsByUrl.get(source) as any)
        pendingBPsArgs.args.lineShift=(script as any).lineShift
        this.resolvePendingBreakpoint(pendingBPsArgs)
        .then(() => this._pendingBreakpointsByUrl.delete(source));
    })
    }

            }
        };
  • It first checks if the script is an eval one (very ugly, I only check if the script.url exists locally)
  • loads the parsed source from chrome debugger
  • finds if the first lines matches (function(){ and calculates the shift
  • adds the line shift to pendingBPsArgs to get the info back in baseSourceMapTransformer.ts :setBreakpoints.

I added the shift to bp.line after resolving breakpoints using source-map, so the breakpoints are correctly set in chrome debugger now.
I changed at the end of the method (ugly :-)) to get line shift back in setBreakpointsResponse args :

this._requestSeqToSetBreakpointsArgs.set(requestSeq, {
            originalBPs,
            authoredPath: args.authoredPath,
            generatedPath: args.source.path
            , lineShift: (args as any).lineShift
        });

In setBreakpointsResponse, I remove the line shift to let source-map find the breakpoint lines back to authored one.

response.breakpoints.forEach((bp, i) => {
                   bp.line-=(args as any).lineShift

I combine all with #252 column number mapping addition and I'm getting the breakpoints back with the exact same position (for both line and column).

I think it could only work with nodejs for now, so maybe you will have better ideas to deal with this line shift problem:

  • better way to detect eval source
  • chrome debugger api to get the line shift
  • solve the UI problem (even if I get back all original breakpoints, the first one is never reached: only the second one and I don't understand why)

Thank you for your opinion and your help.

@Alphapage Alphapage reopened this Nov 12, 2017
@msftclas
Copy link

msftclas commented Nov 12, 2017

CLA assistant check
Thank you for your submission, we really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.

❌ Alphapage sign now
You have signed the CLA already but the status is still pending? Let us recheck it.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants