Skip to content

Debugger breakpoints using incorrect URL for a remote debugging session and therefore failing to pause the process #103

Closed
@treffynnon

Description

@treffynnon

Symptoms

This is related to the closed ticket #99, which describes the symptoms of this very problem.

You set a breakpoint, but the process isn't paused when that breakpoint is encountered and carries merrily on.

Environment

This is a remote debugging session between a Windows client (running Chrome devtools) and a remote Linux server (running node with --inspect=0.0.0.0).

What's wrong

By watching the websocket communication with Wireshark it is apparent that the Chrome Dev tools are using an incorrect filepath/URL when calling Debugger.setBreakpointByUrl.

What I am seeing

Request

{
  "id": 17,
  "method": "Debugger.setBreakpointByUrl",
  "params": {
    "lineNumber": 67,
    "url": "EFS\\DEV-efsbastion\\username\\application\\projects\\service\\module\\index.js",
    "columnNumber": 18,
    "condition": ""
  }
}

Response

{
  "id": 17,
  "result": {
    "breakpointId": "EFS\\DEV-efsbastion\\username\\application\\projects\\service\\module\\index.js:67:18",
    "locations": []
  }
}

Note the empty locations array. I am no node debugger expert, but it feels like this locations array should be checked to ensure it is not empty after setting a new breakpoint marker before then showing the marker as active in the UI.

What I should be seeing

Request

{
  "id": 17,
  "method": "Debugger.setBreakpointByUrl",
  "params": {
    "lineNumber": 67,
    "url": "/EFS/DEV-efsbastion/username/application/projects/service/module/index.js",
    "columnNumber": 18,
    "condition": ""
  }
}

Response

{
  "id": 17,
  "result": {
    "breakpointId": "/EFS/DEV-efsbastion/username/application/projects/service/module/index.js:67:18",
    "locations": [{
      "scriptId":"104",
      "lineNumber":67,
      "columnNumber":18
    }]
  }
}

Note the Linux path separators instead of Windows and the initial root slash on the path.

But isn't this a node bug?

No, it is not from what I can tell because of the following two discoveries.

PHPStorm

PHPStorm/WebStorm debugger continues to work just fine using it's URL regexes

Request

{
  "id": 17,
  "method": "Debugger.setBreakpointByUrl",
  "params": {
    "lineNumber": 67,
    "urlRegex": "[/\\\\][iI][nN][dD][eE][xX]\\.[jJ][sS]([;?#!].*)?$"
  }
}

Response

{
  "id": 17,
  "result": {
    "breakpointId": "/[/\\\\][iI][nN][dD][eE][xX]\\.[jJ][sS]([;?#!].*)?$/:67:18",
    "locations": [{
      "scriptId":"104",
      "lineNumber":67,
      "columnNumber":18
    }]
  }
}

Manually recreating the request successfully

If I manually set the breakpoint myself I see a success response back over the websocket. For example consider the following code run from the Chrome console:

let id, key, socket

id = 1000
key = '<debugger-key-goes-here>'

const connect = userSuppliedKey => {
	socket = new WebSocket(`ws://<ip-address-goes-here>:9229/${userSuppliedKey || key}`)
	socket.addEventListener('message', e => {
		const d = JSON.parse(e.data)
		if (d) {
			if (d.method === 'Debugger.scriptParsed') return console.log('scriptParsed', JSON.stringify({ scriptId: d.params.scriptId, url: d.params.url }))
			if (d.method === 'Debugger.breakpointResolved') return console.log('breakpointResolved', JSON.stringify(Object.assign({ breakpointId: d.params.breakpointId }, d.params.location)))
		}
		console.info(`${e.data}`)
	})
}
const send = (method, x) => socket.send(JSON.stringify({ id: ++id, method: `Debugger.${method}`, params: x }))
const _getPossibleBps = (start, end) => send('getPossibleBreakpoints', { start, end })
const getPossibleBps = (scriptId, start, end) => _getPossibleBps({ scriptId, lineNumber: start }, { scriptId, lineNumber: end })
const setBp = (lineNumber, url) => send('setBreakpointByUrl', { lineNumber, url, })
const removeBp = (lineNumber, url, columnNumber) => send('removeBreakpoint', { breakpointId: `${url}:${lineNumber}:${columnNumber || 0}` })
const enable = () => send('enable')

Which gives us this when run in the Chrome console

connect('<debugger-key-goes-here>')
// '<debugger-key-goes-here>'

enable()
// ...
// scriptParsed {"scriptId":"104","url":"/EFS/DEV-efsbastion/username/application/projects/service/module/index.js"}
// ...

getPossibleBps('104', 9, 15)
// {"id":1016,"result":{"locations":[{"scriptId":"104","lineNumber":9,"columnNumber":15},{"scriptId":"104","lineNumber":11,"columnNumber":15},{"scriptId":"104","lineNumber":12,"columnNumber":16},{"scriptId":"104","lineNumber":14,"columnNumber":4},{"scriptId":"104","lineNumber":15,"columnNumber":0},{"scriptId":"104","lineNumber":17,"columnNumber":4},{"scriptId":"104","lineNumber":18,"columnNumber":14}]}}

setBp(11, '/EFS/DEV-efsbastion/username/application/projects/service/module/index.js')
// {"id":1024,"result":{"breakpointId":"/EFS/DEV-efsbastion/username/application/projects/service/module/index.js:11:0","locations":[{"scriptId":"104","lineNumber":11,"columnNumber":15}]}}

removeBp(11, '/EFS/DEV-efsbastion/username/application/projects/service/module/index.js')
// {"id":1019,"result":{}}

Possible introduction of the issue

https://chromium.googlesource.com/chromium/src/+/2140ffeadf3e081e2e0821fc8e1ee040373b205d%5E%21/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js

in combination with https://chromium.googlesource.com/chromium/src/+blame/master/third_party/blink/renderer/devtools/front_end/common/ParsedURL.js#103

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions