Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Angular debugging doesn't work with nightly vscode-js-debug #1491

Closed
rajinder-yadav opened this issue Dec 22, 2022 · 9 comments
Closed

Angular debugging doesn't work with nightly vscode-js-debug #1491

rajinder-yadav opened this issue Dec 22, 2022 · 9 comments

Comments

@rajinder-yadav
Copy link

Type: Bug

I installed the nightly vscode-js-debug extenstion and I am still unable to debug an Angular app, breakpoint is never hit and shows as greyed out in vscode.

I have to use the work around of "ng serve --host=127.0.0.1", however if the project is setup to use a local proxy server, this workaround will fail.

Extension version: 2022.12.1417
VS Code version: Code - Insiders 1.75.0-insider (11238faea62d570d77afe6edfe05c8b732c44a2b, 2022-12-13T05:22:26.937Z)
OS version: Linux x64 6.0.12-1-default
Modes:
Sandboxed: Yes

System Info
Item Value
CPUs AMD Ryzen 9 5900X 12-Core Processor (24 x 3999)
GPU Status 2d_canvas: enabled
canvas_oop_rasterization: disabled_off
direct_rendering_display_compositor: disabled_off_ok
gpu_compositing: enabled
multiple_raster_threads: enabled_on
opengl: enabled_on
rasterization: enabled
raw_draw: disabled_off_ok
skia_renderer: enabled_on
video_decode: disabled_software
video_encode: disabled_software
vulkan: disabled_off
webgl: enabled
webgl2: enabled
webgpu: disabled_off
Load (avg) 1, 1, 1
Memory (System) 62.72GB (50.50GB free)
Process Argv . --crash-reporter-id 210d9130-10f4-4cf9-ad76-187d60112fd6
Screen Reader no
VM 0%
DESKTOP_SESSION /usr/share/xsessions/plasma5
XDG_CURRENT_DESKTOP KDE
XDG_SESSION_DESKTOP KDE
XDG_SESSION_TYPE x11
A/B Experiments
vsliv695:30137379
vsins829:30139715
vsliv368:30146709
vsreu685:30147344
python383:30185418
vspor879:30202332
vspor708:30202333
vspor363:30204092
vslsvsres303:30308271
pythonvspyl392:30422396
pythontb:30258533
vsc_aa:30263845
pythonptprofiler:30281269
vshan820:30294714
pythondataviewer:30285072
vscod805cf:30301675
bridge0708:30335490
bridge0723:30353136
cmake_vspar411:30581797
vsaa593cf:30376535
pythonvs932:30404738
cppdebug:30492333
vsclangdf:30492506
c4g48928:30535728
dsvsc012cf:30540253
pynewext54:30618038
pylantcb52:30590116
pyindex848:30611229
nodejswelcome1:30587009
pyind779:30611226
pythonsymbol12:30622696
fim-prod:30623723

@rajinder-yadav
Copy link
Author

rajinder-yadav commented Dec 22, 2022

Steps to reproduce:

Use the Angular CLI to create a new project and just selecte the default.

ng new demo

Open project from vscode.
Open file app.components.ts and set a breakpoint on line 9 (title = 'demo';).
Run the debugger (press F5).

@rajinder-yadav
Copy link
Author

Also see previous bug report that was closed for additional details: microsoft/vscode#167353 (comment)

Unfortunately that fix didn't work for me.

@rajinder-yadav
Copy link
Author

rajinder-yadav commented Dec 27, 2022

I found the source of my problem. In my /etc/hosts I had localhost defined twice, like:

127.0.0.1     localhost

# Somewhere else in the file
::1           localhost

Once I deleted one of the definition, the debugged started to working normally.

As a result, my recommendation is the fallback code that @connor4312 added should be removed. I can't find a way to get the fallback code block working by debugging the nightly debugger extension.

@rajinder-yadav
Copy link
Author

rajinder-yadav commented Dec 27, 2022

There are a few error in the fallback check, other than the typo of 'localhost'. This is the code I was using to debug but it fails to work. I do get a 200 response, but for some reason the response body is missing "source" and "sourcesContent".

  protected async fetchHttp(
    url: string,
    cancellationToken: CancellationToken,
    headers?: Headers,
  ): Promise<Response<string>> {
    const parsed = new URL(url);

    const isSecure = parsed.protocol !== 'http:';
    const options: OptionsOfTextResponseBody = { headers, followRedirect: true };
    if (isSecure && (await isLoopback(url))) {
      options.rejectUnauthorized = false;
    }

    this.options?.provideOptions(options, url);

    const response = await this.requestHttp(url, options, cancellationToken);

    // Try the other net family if localhost fails,
    // see https://github.com/microsoft/vscode/issues/140536#issuecomment-1011281962
    // and later https://github.com/microsoft/vscode/issues/167353
    if (response.statusCode === 503 && parsed.hostname === 'localhost') {
      let resolved: LookupAddress;
      try {
        resolved = await dns.lookup(parsed.hostname);
      } catch {
        return response;
      }

      const fallbackHostname = resolved.family === 6 ? '[::1]' : '127.0.0.1';
      const fallbackResponse = await this.requestHttp(
        `http://${fallbackHostname}:4200/runtime.js.map`,
        options,
        cancellationToken,
      );
      return fallbackResponse;
    }

    return response;
  }

The correct response look like this:

{
    "version": 3,
    "file": "runtime.js",
    "mappings": ";;;;UAAA;UACA;;UAEA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;;UAEA;UACA;;UAEA;UACA;UACA;;UAEA;UACA;;;;;WCzBA;WACA;WACA;WACA;WACA,+BAA+B,wCAAwC;WACvE;WACA;WACA;WACA;WACA,iBAAiB,qBAAqB;WACtC;WACA;WACA,kBAAkB,qBAAqB;WACvC;WACA;WACA,KAAK;WACL;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;;;;;WC3BA;WACA;WACA;WACA;WACA;WACA,iCAAiC,WAAW;WAC5C;WACA;;;;;WCPA;WACA;WACA;WACA;WACA,yCAAyC,wCAAwC;WACjF;WACA;WACA;;;;;WCPA;;;;;WCAA;;;;;WCAA;WACA;WACA;WACA,uDAAuD,iBAAiB;WACxE;WACA,gDAAgD,aAAa;WAC7D;;;;;WCNA;;WAEA;WACA;WACA;WACA;WACA;WACA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA,MAAM,qBAAqB;WAC3B;WACA;WACA;WACA;WACA;WACA;WACA;WACA;;WAEA;WACA;WACA",
    "sources": [
        "webpack/bootstrap",
        "webpack/runtime/chunk loaded",
        "webpack/runtime/compat get default export",
        "webpack/runtime/define property getters",
        "webpack/runtime/getFullHash",
        "webpack/runtime/hasOwnProperty shorthand",
        "webpack/runtime/make namespace object",
        "webpack/runtime/jsonp chunk loading",
        "webpack/before-startup",
        "webpack/startup",
        "webpack/after-startup"
    ],
    "sourcesContent": [
        "// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n",
        "var deferred = [];\n__webpack_require__.O = (result, chunkIds, fn, priority) => {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar [chunkIds, fn, priority] = deferred[i];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};",
        "// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};",
        "// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};",
        "__webpack_require__.h = () => (\"00b107654779f55a\")",
        "__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))",
        "// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};",
        "// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t\"runtime\": 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = (parentChunkLoadingFunction, data) => {\n\tvar [chunkIds, moreModules, runtime] = data;\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some((id) => (installedChunks[id] !== 0))) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = self[\"webpackChunkdemo\"] = self[\"webpackChunkdemo\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));",
        "",
        "",
        ""
    ],
    "names": [],
    "sourceRoot": "webpack:///",
    "x_google_ignoreList": [
        0,
        1,
        2,
        3,
        4,
        5,
        6,
        7,
        8,
        9,
        10
    ]
}

However the working fallback code get the following response body. I don't think it's worth debugging because the fallback is not need anymore imho.

{
  "version": 3,
  "file": "runtime.js",
  "mappings": ";;;;UAAA;UACA;;UAEA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;;UAEA;UACA;;UAEA;UACA;UACA;;UAEA;UACA;;;;;WCzBA;WACA;WACA;WACA;WACA,+BAA+B,wCAAwC;WACvE;WACA;WACA;WACA;WACA,iBAAiB,qBAAqB;WACtC;WACA;WACA,kBAAkB,qBAAqB;WACvC;WACA;WACA,KAAK;WACL;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;;;;;WC3BA;WACA;WACA;WACA;WACA;WACA,iCAAiC,WAAW;WAC5C;WACA;;;;;WCPA;WACA;WACA;WACA;WACA,yCAAyC,wCAAwC;WACjF;WACA;WACA;;;;;WCPA;;;;;WCAA;;;;;WC…Id]) {\\n\\t\\t\\tinstalledChunks[chunkId][0]();\\n\\t\\t}\\n\\t\\tinstalledChunks[chunkId] = 0;\\n\\t}\\n\\treturn __webpack_require__.O(result);\\n}\\n\\nvar chunkLoadingGlobal = self[\\"webpackChunkdemo\\"] = self[\\"webpackChunkdemo\\"] || [];\\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));",
  "",
  "",
  ""
],
"names": [],
"sourceRoot": "webpack:///",
"x_google_ignoreList": [
  0,
  1,
  2,
  3,
  4,
  5,
  6,
  7,
  8,
  9,
  10
]
}

@connor4312
Copy link
Member

I have the same hosts config, I believe that's default on macOS. Unfortunately this is network specific, and I haven't been able to readily reproduce such issues on networks I have access to. The fallback code was added to resolve previous issues and I do not think it should be removed, just fixed.

I'm quite surprised you get the 2nd response. It looks like a response chunk went missing, which could be sensible if we implemented our own request streaming, but we use got which is quite widely used and has reported no such issues. Is that missing chunk reproducible? Does it always occur in the same place?

@rajinder-yadav
Copy link
Author

rajinder-yadav commented Dec 28, 2022

Oh ok so you also have both localhost entries, I thought it was some mistake with my /etc/hosts files. I will put it back and continue to "debug" this way.

With respect to the body response, it is always reproducable. What is odd is, if I make the same request using Postman it returns the full correct response body. I don't know what is filtering out "sourcesContent" and "sources".

I need to think about this code and how to test/debug.

@rajinder-yadav
Copy link
Author

@connor4312 I am looking at the "response.body" variable inside of the BasicResourceProvider::requestHttp(...) call.

I see everything is there, but it is getting returned as a string, with some chunks and that is being assigned as if it's an object. Maybe you know what needs to be done to correct it, so everything gets return as a object. I think this will get the fallback code working.

return { ok: true, url, body: response.body, statusCode: response.statusCode };

Response body.

"{"version":3,"file":"runtime.js","mappings":";;;;UAAA;UACA;;UAEA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;;UAEA;UACA;;UAEA;UACA;UACA;;UAEA;UACA;;;;;WCzBA;WACA;WACA;WACA;WACA,+BAA+B,wCAAwC;WACvE;WACA;WACA;WACA;WACA,iBAAiB,qBAAqB;WACtC;WACA;WACA,kBAAkB,qBAAqB;WACvC;WACA;WACA,KAAK;WACL;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;;;;;WC3BA;WACA;WACA;WACA;WACA;WACA,iCAAiC,WAAW;WAC5C;WACA;;;;;WCPA;WACA;WACA;WACA;WACA,yCAAyC,wCAAwC;WACjF;WACA;WACA;;;;;WCPA;;;;;WCAA;;;;;WCAA;WACA;WACA;WACA,uDAAuD,iBAAiB;WACxE;WACA,gDAAgD,aAAa;WAC7D;;;;;WCNA;;WAEA;WACA;WACA;WACA;WACA;WACA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA,MAAM,qBAAqB;WAC3B;WACA;WACA;WACA;WACA;WACA;WACA;WACA;;WAEA;WACA;WACA","sources":["webpack/bootstrap","webpack/runtime/chunk loaded","webpack/runtime/compat get default export","webpack/runtime/define property getters","webpack/runtime/getFullHash","webpack/runtime/hasOwnProperty shorthand","webpack/runtime/make namespace object","webpack/runtime/jsonp chunk loading","webpack/before-startup","webpack/startup","webpack/after-startup"],"sourcesContent":["// The module cache\nvar webpack_module_cache = {};\n\n// The require function\nfunction webpack_require(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = webpack_module_cache[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = webpack_module_cache[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, webpack_require);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (webpack_modules)\n__webpack_require__.m = webpack_modules;\n\n","var deferred = [];\n__webpack_require__.O = (result, chunkIds, fn, priority) => {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar [chunkIds, fn, priority] = deferred[i];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(webpack_require.O).every((key) => (webpack_require.Okey))) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(webpack_require.o(definition, key) && !webpack_require.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","webpack_require.h = () => (\"00b107654779f55a\")","webpack_require.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define esModule on exports\n__webpack_require.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, 'esModule', { value: true });\n};","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t\"runtime\": 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require.O.j = (chunkId) => (installedChunks[chunkId] === 0);\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = (parentChunkLoadingFunction, data) => {\n\tvar [chunkIds, moreModules, runtime] = data;\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some((id) => (installedChunks[id] !== 0))) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(webpack_require.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(webpack_require);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(webpack_require.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId]0;\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn webpack_require.O(result);\n}\n\nvar chunkLoadingGlobal = self[\"webpackChunkdemo\"] = self[\"webpackChunkdemo\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","","",""],"names":[],"sourceRoot":"webpack:///","x_google_ignoreList":[0,1,2,3,4,5,6,7,8,9,10]}"

@elliotstoner
Copy link

Any update on this? I've tried a handful of the suggestions in this thread and microsoft/vscode#167353 without any luck.

@connor4312
Copy link
Member

Duplicates microsoft/vscode#167353 (and was fixed in the April release)

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

No branches or pull requests

3 participants