berry icon indicating copy to clipboard operation
berry copied to clipboard

[Bug]: Patched tsserver crashes when using client watch

Open clemyan opened this issue 1 year ago • 1 comments

Self-service

  • [ ] I'd be willing to implement a fix

Describe the bug

When using the client watch feature with the patched tsserver (introduced in TypeScript 5.3, commit, PR), the server crashes.

Looks like VS Code 1.89 (released 15 hours ago as of this writing) is A/B testing whether to use client watch in its TypeScript language service.

Investigation

In tsserver, client watch is enabled by the option canUseWatchEvents, which causes ProjectService to create different watch factories: https://github.com/microsoft/TypeScript/blob/v5.5-beta/src/server/editorServices.ts#L1229

Then the patched tsserver (synchronously) calls watchPnpFile https://github.com/yarnpkg/TypeScript/blob/merceyz/pnp-5.5-beta/src/server/editorServices.ts#L1238

When using client watch, that call ends up calling IOSession#event https://github.com/microsoft/TypeScript/blob/v5.5-beta/src/tsserver/nodeServer.ts#L611-L612

which fails the first assert and crashes because the IOSession's constructor is still at the super call, before setting this.constructed to true.


To reproduce/investigate, make sure your VS Code is at version 1.89, enable client watch with "typescript.tsserver.experimental.useVsCodeWatcher": true, and enable logging with "typescript.tsserver.log": "verbose". By unplugging the typescript package we can insert log calls. Restart the TS server or extension host to trigger the error code path. The log file path can be found in the "Output" tab. (Note: there are 2 logs files, we want the semantic server log)

By printing the stacktrace and this.constructed at the start of IOSession#event we can verify the assert fails (line numbers may be slightly shifted due to added logs)

    at IpcIOSession.event ([PROJECT_ROOT]\.yarn\unplugged\typescript-patch-5205e392bf\node_modules\typescript\lib\tsserver.js:502:25)
    at IpcIOSession.defaultEventHandler ([PROJECT_ROOT]\.yarn\unplugged\typescript-patch-5205e392bf\node_modules\typescript\lib\typescript.js:189562:14)
    at _ProjectService.eventHandler ([PROJECT_ROOT]\.yarn\unplugged\typescript-patch-5205e392bf\node_modules\typescript\lib\typescript.js:189465:83)
    at getOrCreateFileWatcher ([PROJECT_ROOT]\.yarn\unplugged\typescript-patch-5205e392bf\node_modules\typescript\lib\typescript.js:184920:15)
    at Object.watchFile2 [as watchFile] ([PROJECT_ROOT]\.yarn\unplugged\typescript-patch-5205e392bf\node_modules\typescript\lib\typescript.js:184888:12)
    at watchFile ([PROJECT_ROOT]\.yarn\unplugged\typescript-patch-5205e392bf\node_modules\typescript\lib\typescript.js:123187:67)
    at Object.watchFile ([PROJECT_ROOT]\.yarn\unplugged\typescript-patch-5205e392bf\node_modules\typescript\lib\typescript.js:123256:92)
    at createFileWatcherWithLogging ([PROJECT_ROOT]\.yarn\unplugged\typescript-patch-5205e392bf\node_modules\typescript\lib\typescript.js:123229:44)
    at Object.watchFile ([PROJECT_ROOT]\.yarn\unplugged\typescript-patch-5205e392bf\node_modules\typescript\lib\typescript.js:123206:283)
    at _ProjectService.watchPnpFile ([PROJECT_ROOT]\.yarn\unplugged\typescript-patch-5205e392bf\node_modules\typescript\lib\typescript.js:188039:30)
    at new _ProjectService ([PROJECT_ROOT]\.yarn\unplugged\typescript-patch-5205e392bf\node_modules\typescript\lib\typescript.js:185100:28)
    at new _Session ([PROJECT_ROOT]\.yarn\unplugged\typescript-patch-5205e392bf\node_modules\typescript\lib\typescript.js:189494:27)
    at new IOSession ([PROJECT_ROOT]\.yarn\unplugged\typescript-patch-5205e392bf\node_modules\typescript\lib\tsserver.js:476:7)
    at new IpcIOSession ([PROJECT_ROOT]\.yarn\unplugged\typescript-patch-5205e392bf\node_modules\typescript\lib\tsserver.js:539:3)
    at startNodeSession ([PROJECT_ROOT]\.yarn\unplugged\typescript-patch-5205e392bf\node_modules\typescript\lib\tsserver.js:576:34)
    at start ([PROJECT_ROOT]\.yarn\unplugged\typescript-patch-5205e392bf\node_modules\typescript\lib\tsserver.js:636:3)
    at Object.<anonymous> ([PROJECT_ROOT]\.yarn\unplugged\typescript-patch-5205e392bf\node_modules\typescript\lib\tsserver.js:653:1)
    ---- snip ----

Indeed, we can verify that the server can run normally without crashing by either:

  • Disabling client watch in VS Code with "typescript.tsserver.experimental.useVsCodeWatcher": false
  • Delaying the said watchPnpFile call to the next tick via process.nextTick

To reproduce

  1. Install VS Code 1.89
  2. Open a TypeScript 5.5 project (if necessary, use a fresh --user-data-dir and/or disable extensions)
  3. Use TypeScript SDK
  4. Set config "typescript.tsserver.experimental.useVsCodeWatcher": true
  5. Open any TypeScript file and restart the extension host
  6. VS Code warns that "The JS/TS language service crashed."

Environment

System:
    OS: Windows 10 10.0.19045
    CPU: (16) x64 Intel(R) Core(TM) i7-10700 CPU @ 2.90GHz      
  Binaries:
    Node: 20.8.1 - ~\AppData\Local\Temp\xfs-b99c0456\node.CMD   
    Yarn: 4.1.1-dev - ~\AppData\Local\Temp\xfs-b99c0456\yarn.CMD
    npm: 10.1.0 - C:\Program Files\nodejs\npm.CMD

Additional context

image

clemyan avatar May 03 '24 09:05 clemyan

To summarize the relevant information from the VSCode issue:

  • This will hit all VSCode + TypeScript >= 5.4.4 + PnP users at the end of May
  • Mitigation strategies:
    • Downgrade TypeScript to a version < 5.4.4
    • Add "typescript.tsserver.experimental.useVsCodeWatcher": false to .vscode/settings.json (should work at least until July)

(I created an MCVE for the VSCode issue, in case it is useful for debugging)

BurningEnlightenment avatar May 06 '24 19:05 BurningEnlightenment