Node uses the V8 Inspector Protocol. It is described in .json
here which is fairly difficult to read. I wasn't able to find other documentation which means this will be trial and error.
It can be inspected a bit better with http://jsonparseronline.com. Copy the content of RAW V8 Inspector Protocl JSON and paste it to the page. You will then be able to click through the protocol.
- Run
yarn start-node
, which will startstub.js
with node. - Run
yarn start
which will run the UI.
- Copy the
ws
url from the terminal you ranyarn start-node
in. - Paste the url into the first input in the UI and hit enter.
According to the V8 Inspector Protocol, messages sent to it, contain an id
for identification, a method
with the method / command you're trying to execute and optional params
which is an object containing a key value mapping of the params needed for the desired method.
{
"id": 42,
"method": "SomeObject.someMethod",
"params": {
"firstParam": 1,
"secondParam": "2"
}
}
Information on what params are needed for what method / operation, can be found in the API (JSON) spec.
- Enter a message in the custom message field.
- Press shift + enter for a new line.
- Press enter to submit.
This field, pretty prints JSON as soon as it's valid.
The text above the url input, represents the WebSocket state. It can be one of the following states.
Value | Meaning |
---|---|
ENTER URL | You haven't entered a url yet. |
OPEN | The WebSocket was successfully opened. |
CLOSED | The WebSocket was successfully closed. |
ERROR | There was an error with the WebSocket connection. |
- Run
npm run start-node2
instead ofnpm run start-node
. - Send
Debugger.enable
.
{
"id": 1,
"method": "Debugger.enable"
}
- Open Chrome Devtools and press on the Node icon on the top left. (What happends after this???)
- You'll see that the debugger continued to the location we want it to. It is now at the beginning of
stub.js
. (What happens before this???) - The newest message you see should be
Debugger.paused
which is an event, fired because the debugger was paused. There is a lot of information in there. - In the Chrome Dev Tools you should see that the debugger is paused on the first line. Try sending another message
Debugger.stepOver
.
{
"id": 1,
"method": "Debugger.stepOver"
}
- Try asking for possible breakpoint locations.
{
"id": 1,
"method": "Debugger.getPossibleBreakpoints",
"params": {
"start": {
"scriptId": "53",
"lineNumber": 0,
"columnNumber": 0
},
"end": {
"scriptId": "53",
"lineNumber": 3,
"columnNumber": 0
}
}
}
- Evaluate some expressions.
{
"id": 1,
"method": "Debugger.evaluateOnCallFrame",
"params": {
"callFrameId": "{\"ordinal\":0,\"injectedScriptId\":1}",
"expression": "1 + 1"
}
}
{
"id": 1,
"method": "Debugger.evaluateOnCallFrame",
"params": {
"callFrameId": "{\"ordinal\":0,\"injectedScriptId\":1}",
"expression": "['a', 'b', 'c'].map(e => e.toUpperCase()).join('')"
}
}
- Set another breakpoint and resume script.
{
"id": 1,
"method": "Debugger.setBreakpoint",
"params": {
"location": {
"scriptId": "53",
"lineNumber": 4,
"columnNumber": 0
}
}
}
{
"id": 1,
"method": "Debugger.resume"
}
You will see, that the Chrome Dev Tools stop at the 3rd line. The script was continued and a breakpoint was set.
- Resume again and exit.
{
"id": 1,
"method": "Debugger.resume"
}
To implement a debugger that speaks to the V8 Inspector API, it is necessary to create helper methods like createMessage(message: String, params: Object)
or in Java String createMessage(String message, Map<String, Object> params)
. This will make it easy to send messages as typing them by hand is not fun.
To implement a debugger the following V8 Inspector API methods should be relevant.
Debugger.enable
Debugger.disable
Debugger.stepOver
Debugger.stepInto
Debugger.stepOut
Debugger.evaluateOnCallFrame
Debugger.getPossibleBreakpoints
Debugger.getStackTrace
Debugger.pause
Debugger.resume
Debugger.removeBreakpoint
Debugger.restartFrame
Debugger.removeBreakpoint
Debugger.setBreakpoint
Debugger.setBreakpointsActive
Debugger.setVariableValue