isolated-vm icon indicating copy to clipboard operation
isolated-vm copied to clipboard

Debug on VSCode?

Open joetex opened this issue 1 year ago • 6 comments

I finally got my script running inside isolated-vm, but I can't seem to get the Chrome DevTools to work properly. I can see the code, but that is about it. I can't breakpoint or get source maps to work.

I get this warning for sourcemaps:

DevTools failed to load source map: Could not load content for file:///server.bundle.dev.js.map: Unknown error

There is no way to configure the location, its always looking at file:///<filename>.map it doesn't even have the same path as I defined in my code, since the file sits in another folder.

Instead, how can we use VSCode to attach to the debugging used for let channel = isolate.createInspectorSession(); ? I read that VSCode supports the DevTools debugging protocol, but it doesn't look like the JavaScript Debugger used by VSCode supports it after all?

Error: Could not connect to debug target at http://localhost:10000: Could not find any debuggable target

This is the error I see when I attempt to connect to the websocket. I recently switched from vm2 as they have officially abandoned their project. On vm2, I was able to get inline-source-maps, breakpoints, and watch inside VSCode from the same terminal I ran the vm. So I'm hoping to replicate the scenario with isolated-vm. Thanks.

joetex avatar Jul 15 '23 01:07 joetex

Debugging in Chrome DevTools.

I did a bit more fiddling and was able to get sourcemaps and breakpoints working on a chrome tab with devtools.

  1. The correct URL to open in a Chrome tab is: devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=127.0.0.1:10000 (change host/port to what your websocket server uses)
  2. In the inspector-example.js both channel.dispatchProtocolMessage and ws.send should be using message.toString(). The pull request only had it on the dispatch.
  3. In webpack, use devtool: "inline-source-map". If you need a sourcemap file by itself i.e., devtool: "source-map", you'll need to add plugin plugins: [new webpack.SourceMapDevToolPlugin()] to webpack config for it to find the file properly, not sure why.
  4. If you are on windows, you need to convert the filepath seperator \\ to unix seperator /. Chrome Dev Tools doesn't seem to like the backward slashes for filepaths.
  5. ScriptOrigin.filename that you pass to compileScript should have the full path, i.e. file:///E:/GitHub/acos-games/memorize-up/builds/server/server.bundle.dev.js. Note that I'm using unix seperator.

I am still struggling to get the stack trace from my vm script. I was only able to get the full stack trace once. 99.99% of the time I only get the stack message, and the trace only shows like the example below.

Example of my bad stack trace:

ReferenceError: test is not defined
    at (<isolated-vm boundary>)

The ultimate scenario would still be to get it working on VSCode, but this will have to suffice until then.

joetex avatar Jul 15 '23 05:07 joetex

Finally, I got VSCode Debugging working too!

VSCode's default NodeJS debugging uses a different connection schema http://, so just had to use websocketAddress to attach to the ws:// schema.

  1. Edit launch.json to include this:
        {
            "name": "Debug ACOS Game",
            "type": "node",
            "request": "attach",
            "websocketAddress": "ws://127.0.0.1:10000",
            "restart": true,
        },
  1. In webpack use devtool: "inline-source-map"
  2. Windows users, need to still convert filepath seperator from \\ to /
  3. Run the Debug ACOS Game configuration to attach.

If you want to launch your main program that runs the VM and attach in one step, you can do this:

        {
            "command": "cd memorize-up && npm start",
            "name": "Launch Memorize-Up",
            "request": "launch",
            "type": "node-terminal",
            "serverReadyAction": {
                "action": "startDebugging",
                "name": "Debug ACOS Game",
                "pattern": "Watching files"
            }
        },

Just edit pattern to match any terminal output you want, for my example, it looks for "Watching files" in one of the log lines.

Still no luck with the stack trace though 😢

joetex avatar Jul 15 '23 16:07 joetex

There is definitely something weird happening with stack traces.

Setting filename: "file:///fullpath" is the right way, but full stack trace will not appear until you cause interference with breakpoints or some internal mechanism.

I don't think it's because I'm running the isolate from a worker thread, but it's becoming a bit unreliable to get the stack trace.

Also, breakpointing is unreliable, as it requires some fiddling to get working. Like I have to trigger at start of script with a debugger;, but even then I have to set/unset the breakpoint several times to trigger a reliable breakpoint.

I tried following the c++ code, but it's a bit over my head as the filename disappears into the void somewhere.

Any help on these points would be appreciated. Thanks.

Edit: At the moment, I can only recommend isolated-vm for production workloads, where security takes priority over debugging. I have since changed to using the vm that is built into nodejs for local development of games, as debugging is within the same context as the main node script, making it more reliable.

joetex avatar Jul 16 '23 16:07 joetex

May I ask if you are using isolated-vm to find an elegant debugging solution? The vm2 used before can be directly inserted into the debugger in the code, but it has not been able to be used in isolated-vm, and the usage examples will continue to have problems

Mankvis avatar Jul 18 '23 09:07 Mankvis

May I ask if you are using isolated-vm to find an elegant debugging solution? The vm2 used before can be directly inserted into the debugger in the code, but it has not been able to be used in isolated-vm, and the usage examples will continue to have problems

@Mankvis No, I wanted to use isolated-vm for both production and local development. Games for my platform are coded on local environment in VSCode, and I was hoping I could use one solution for both. vm2 is oficially deprecated, so NPM and GitHub will cry about its vulnerabilities til the end of time. Node-vm, while very insecure, is fine for local development and I get full stack traces + instant debugging with breakpoints using sourcemaps.

joetex avatar Jul 18 '23 13:07 joetex

Hey ya, a lil bit on the vscode and the debugging protocol context here.

For us we have to implement some simple http endpoint in order to achieve the similar experience as node.js debugging.

Mainly,

GET /json/list

which returns

[
                {
                    description: '...  instance',
                    devtoolsFrontendUrl: `devtools://devtools/bundled/js_app.html?experiments=true&v8only=true&ws=localhost:${this.port}/${this.uuid}`,
                    devtoolsFrontendUrlCompat: `evtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=localhost:${this.port}/${this.uuid}`,
                    faviconUrl: 'https://nodejs.org/static/images/favicons/favicon.ico',
                    id: this.uuid,
                    title: this.filename,
                    type: 'javascript',
                    url: this.filename.includes('file://${filename}') ,
                    webSocketDebuggerUrl: `ws://localhost:${this.port}/${this.uuid}`,
                },
            ]

GET /json/version

{
                Browser: `node.js/${process.version}`,
                'Protocol-Version': '1.1',
            }

GET /json -> list request


About stack traces, make sure when you call the eval/run/createScript/createModule api, the filename and line offset are passed correctly.

kiddkai avatar Jul 21 '23 00:07 kiddkai