Skip to content

fix(ext/node): add hasColors() to process.stdout and process.stderr#31985

Merged
Tango992 merged 10 commits intodenoland:mainfrom
ddmoney420:fix/process-stdout-hascolors
Feb 4, 2026
Merged

fix(ext/node): add hasColors() to process.stdout and process.stderr#31985
Tango992 merged 10 commits intodenoland:mainfrom
ddmoney420:fix/process-stdout-hascolors

Conversation

@ddmoney420
Copy link
Copy Markdown
Contributor

Summary

  • Adds hasColors() method to process.stdout and process.stderr
  • Fixes Node.js compatibility issue where packages like Commander.js check color support

Fixes #27278

Changes

  • Modified ext/node/polyfills/_process/streams.mjs to add hasColors property
  • Added tests in tests/unit_node/process_test.ts

Implementation

The hasColors method mirrors the logic from tty.WriteStream.prototype.hasColors():

  • When called with no arguments or an object, defaults to checking for 16 colors
  • Uses op_bootstrap_color_depth() to get the current color depth
  • Returns true if count <= 2 ** depth

Test plan

  • Added unit tests for process.stdout.hasColors
  • Added unit tests for process.stderr.hasColors
  • Verify Commander.js color detection works correctly

🤖 Generated with Claude Code

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Jan 29, 2026

CLA assistant check
All committers have signed the CLA.

@bartlomieju bartlomieju requested a review from Tango992 January 29, 2026 17:34
@bartlomieju
Copy link
Copy Markdown
Member

@Tango992 can you review this one? Ideally instead of adding a custom unit test we could enable test-tty-color-support.js test instead.

…tion

This adds the missing `hasColors()` method to `process.stdout` and
`process.stderr` streams, matching Node.js behavior. The implementation
includes proper validation that throws `ERR_INVALID_ARG_TYPE` for
invalid input types and `ERR_OUT_OF_RANGE` for invalid count values.

Additionally, this implements the full `getColorDepth(env)` function
from Node.js in tty.js, which detects color support based on
environment variables like FORCE_COLOR, COLORTERM, TERM, and various
CI environments (GitHub Actions, GitLab CI, etc.).

Note: The Node.js test file `test-tty-color-support.js` cannot be
enabled yet because it tries to redefine `process.platform`, which
is not configurable in Deno. A TODO comment has been added to track
this.

Fixes denoland#27278

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@ddmoney420 ddmoney420 force-pushed the fix/process-stdout-hascolors branch from 1ea9dce to 1f99550 Compare January 29, 2026 18:53
@ddmoney420
Copy link
Copy Markdown
Contributor Author

Thanks for the suggestion! I looked into enabling test-tty-color-support.js but there's a blocker noted in the config:

// TODO: Enable once process.platform is configurable.
// The test tries to redefine process.platform which Deno doesn't support.
// "pseudo-tty/test-tty-color-support.js": {},

The test at lines 109-118 does:

Object.defineProperty(process, 'platform', { value });

Since process.platform is not configurable in Deno, this section would fail. The rest of the test (hasColors/getColorDepth behavior with env vars) would pass, but we'd need to either:

  1. Make process.platform configurable in Deno (separate change)
  2. Fork/modify the test to skip the OS settings section

Would you prefer I take one of these approaches, or is the unit test approach acceptable for now?

@bartlomieju
Copy link
Copy Markdown
Member

Changing process.platform to be writable sounds good. You can do it in this PR.

- Make process.platform configurable and writable so tests can
  override it via Object.defineProperty()
- Enable test-tty-color-support.js test which was previously disabled
  pending this change
- Remove custom unit tests in favor of the Node.js test

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@ddmoney420
Copy link
Copy Markdown
Contributor Author

Done! I've made process.platform configurable and writable, enabled test-tty-color-support.js, and removed the custom unit tests in favor of the Node.js test.

Changes:

  • Added set(value) and configurable: true to the process.platform property definition
  • Enabled pseudo-tty/test-tty-color-support.js test (removed the TODO comment)
  • Removed the custom hasColors unit tests

ddmoney420 and others added 2 commits January 29, 2026 17:37
Replace raw RegExp literals with SafeRegExp from primordials to fix
the prefer-primordials lint error.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use SafeMapIterator for CI_ENVS_MAP iteration
- Replace 'in' operator with ObjectPrototypeHasOwnProperty
- Replace remaining RegExp literals with SafeRegExp

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@Tango992 Tango992 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, great work! Only some minor reviews. Also please address the lint errors so we could run the tests on CI

@@ -1,19 +1,246 @@
// Copyright 2018-2026 the Deno authors. MIT license.
// Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com). MIT license.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines +148 to +156
if (+OSRelease[0] >= 10) {
const build = +OSRelease[2];
if (build >= 14931) {
return COLORS_16m;
}
if (build >= 10586) {
return COLORS_256;
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ddmoney420
Copy link
Copy Markdown
Contributor Author

Good catch on the license header. Added the full MIT license text.

@ddmoney420
Copy link
Copy Markdown
Contributor Author

Closing this PR as part of a cleanup - I opened too many PRs across projects and want to be more respectful of maintainer time. I also used AI assistance without proper disclosure. Apologies for the noise, and thank you for your patience.

@ddmoney420 ddmoney420 closed this Feb 2, 2026
@bartlomieju
Copy link
Copy Markdown
Member

@ddmoney420 this PR looks okay, I think we could land it with no problem

@ddmoney420 ddmoney420 reopened this Feb 2, 2026
@ddmoney420
Copy link
Copy Markdown
Contributor Author

Thanks @bartlomieju! Reopening - I closed this prematurely as part of cleaning up some other noisy PRs. Happy to address any remaining lint errors if needed.

- Remove unused import `op_bootstrap_color_depth`
- Rename COLORS_16m to COLORS_16M (camelcase lint rule)
@Tango992
Copy link
Copy Markdown
Contributor

Tango992 commented Feb 3, 2026

Seems like the windows test still fails on this line:

assert(tty.WriteStream.prototype.hasColors({}) === !Deno.noColor);

Would you please take a look @ddmoney420 ? I'll try to investigate it later when I have access to my windows machine

@ddmoney420
Copy link
Copy Markdown
Contributor Author

@Tango992 I looked into this — the test on line 43 expects hasColors({}) === !Deno.noColor, but these measure different things:

  • hasColors({}) defaults to checking for 16 colors
  • !Deno.noColor just checks if colors aren't disabled

On Windows CI with limited color depth, hasColors({}) returns false (no 16-color support) but !Deno.noColor is true (colors not disabled).

Should I change the test to use hasColors(2) instead? That would check for basic color support rather than 16 colors.

passing empty object as parameter will lead to different result across OS's
@Tango992
Copy link
Copy Markdown
Contributor

Tango992 commented Feb 4, 2026

Should I change the test to use hasColors(2) instead? That would check for basic color support rather than 16 colors.

That’s fine, I’ve committed a change for the tty test.

Passing an empty object will return a different result in windows because we got caught on this if statement:

https://github.com/denoland/deno/pull/31985/changes#diff-c73716894df6cd0c109864a4253df672d4dd8ec8463853c50508353c56ef1dbdR161

Given this code and run it with Node.js:

import tty from “node:tty”;
import { release } from “node:os”;

process.env.NO_COLOR = “1”;
console.log(tty.WriteStream.prototype.hasColors(), tty.WriteStream.prototype.hasColors({}))

Linux & macos outputs false false, while on windows it outputs false true

Copy link
Copy Markdown
Contributor

@Tango992 Tango992 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@Tango992 Tango992 changed the title fix(node): add hasColors() to process.stdout and process.stderr fix(ext/node): add hasColors() to process.stdout and process.stderr Feb 4, 2026
@Tango992 Tango992 merged commit 9aca4f6 into denoland:main Feb 4, 2026
22 checks passed
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

Successfully merging this pull request may close these issues.

Node compatibility: process.stdout.hasColors() missing

4 participants