fix(oxlint,oxfmt): Redirect JS stdout to stderr for LSP#20321
Conversation
How to use the Graphite Merge QueueAdd either label to this PR to merge it via the merge queue:
You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has enabled the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. This stack of pull requests is managed by Graphite. Learn more about stacking. |
import(jsConfig) for LSP
There was a problem hiding this comment.
Pull request overview
Adds coverage and implementation to prevent JavaScript/TypeScript config files from corrupting LSP communication by printing to stdout during config evaluation.
Changes:
- Add LSP test fixtures and snapshots for config files that write to stdout (oxlint + oxfmt).
- Wrap dynamic
import()of config modules with temporary stdout suppression in both config loaders.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| apps/oxlint/test/lsp/lint/lint.test.ts | Adds a new LSP lint fixture case for stdout-polluting TS config. |
| apps/oxlint/test/lsp/lint/fixtures/config-ts-stdout-pollution/test.js | Fixture source to trigger a diagnostic under the loaded config. |
| apps/oxlint/test/lsp/lint/fixtures/config-ts-stdout-pollution/oxlint.config.ts | Fixture config that intentionally logs to stdout. |
| apps/oxlint/test/lsp/lint/snapshots/lint.test.ts.snap | Snapshot for the new lint fixture. |
| apps/oxlint/src-js/js_config.ts | Implements stdout suppression during config import(). |
| apps/oxfmt/test/lsp/format/format.test.ts | Adds a new LSP format fixture case for stdout-polluting config. |
| apps/oxfmt/test/lsp/format/fixtures/config-js-stdout-pollution/test.ts | Fixture input for formatting under the loaded config. |
| apps/oxfmt/test/lsp/format/fixtures/config-js-stdout-pollution/oxfmt.config.ts | Fixture config that intentionally logs to stdout. |
| apps/oxfmt/test/lsp/format/snapshots/format.test.ts.snap | Snapshot for the new format fixture. |
| apps/oxfmt/src-js/cli/js_config.ts | Implements stdout suppression during config import(). |
You can also share your feedback on Copilot code review. Take the survey.
3b41b1f to
ed8cf42
Compare
ed8cf42 to
e1db09d
Compare
camc314
left a comment
There was a problem hiding this comment.
should we not block stdout writing for the entirity of the LS process?
else a console.log, during formatting for example will break the LSP
Sysix
left a comment
There was a problem hiding this comment.
Thank you! This is not my code-ownership, but I found maybe one little improvement :)
This would probably the best, but I do not think this will break atm. The config loading happens at the start, after that there can be multiple formatting requests. And here we are only looking at the source text as Could maybe help to avoid third party outputs like: #18472 |
|
Thanks to both of you. I'll take a look at it early next week. 👍🏻 |
There was a problem hiding this comment.
I happened to meet the same problem while I forgot to check the issue and the PR, so I made a fix in my personal branch again. Silly me 😂.
Different from just disabling stdout, my approach is to redirect all stdout to stderr globally, this is actually a more common practice, make users can still able to find messages printed if they run it in terminal or VSCode's output console. And typescript language server did a similar thing as well.
// https://github.com/typescript-language-server/typescript-language-server
if (this.level >= level || options?.overrideLevel) {
// All messages logged to stderr as stdout is reserved for LSP communication.
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
console.error(`[${LogLevel.toString(level)}]`, ...this.toStrings(...args));In this case, we can also solve the problem of Oxlint JS Plugin without worrying, because keeping the message visible to the user on stderr won't break any feature.
I don't know whether it is helpful to solve this issue, and I am willing to submit this branch as another PR if needed. Thanks.
|
Actually, that's very helpful! I was thinking about that at first, but I wasn't sure if it was the right approach. I'll finish this PR in that direction. Thank you~ 🙌🏻 |
e1db09d to
c25c60b
Compare
import(jsConfig) for LSP|
UPDATED: When using |
c25c60b to
2ec8349
Compare
Merge activity
|
Fixes #20320 (It's fine to release this as scheduled one)
2ec8349 to
23fec48
Compare
Fixes #20320 (It's fine to release this as scheduled one)
23fec48 to
89ce30b
Compare
|
Thank you! |

Fixes #20320
(It's fine to release this as scheduled one)