Skip to content

Commit

Permalink
fix(node): support tty.hasColors() and tty.getColorDepth() (#24619)
Browse files Browse the repository at this point in the history
This PR adds support for
[`tty.WriteStream.prototype.hasColors()`](https://nodejs.org/api/tty.html#writestreamhascolorscount-env)
and
[`tty.WriteStream.prototype.getColorDepth()`](https://nodejs.org/api/tty.html#writestreamgetcolordepthenv).

I couldn't find any usage on GitHub which passes parameters to it.
Therefore I've skipped adding support for the `env` parameter to keep
our snapshot size small.

Based on denoland/deno_terminal#3

Fixes #24616
  • Loading branch information
marvinhagemeister committed Jul 19, 2024
1 parent 76b8ecb commit ee2e693
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 7 deletions.
22 changes: 16 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 51,7 @@ deno_lockfile = "0.20.0"
deno_media_type = { version = "0.1.4", features = ["module_specifier"] }
deno_permissions = { version = "0.21.0", path = "./runtime/permissions" }
deno_runtime = { version = "0.169.0", path = "./runtime" }
deno_terminal = "0.1.1"
deno_terminal = "0.2.0"
napi_sym = { version = "0.91.0", path = "./cli/napi/sym" }
test_util = { package = "test_server", path = "./tests/util/server" }

Expand Down
2 changes: 2 additions & 0 deletions cli/worker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 571,7 @@ impl CliMainWorkerFactory {
no_color: !colors::use_color(),
is_stdout_tty: deno_terminal::is_stdout_tty(),
is_stderr_tty: deno_terminal::is_stderr_tty(),
color_level: colors::get_color_level(),
unstable: shared.options.unstable,
unstable_features,
user_agent: version::get_user_agent().to_string(),
Expand Down Expand Up @@ -773,6 774,7 @@ fn create_web_worker_callback(
locale: deno_core::v8::icu::get_language_tag(),
location: Some(args.main_module.clone()),
no_color: !colors::use_color(),
color_level: colors::get_color_level(),
is_stdout_tty: deno_terminal::is_stdout_tty(),
is_stderr_tty: deno_terminal::is_stderr_tty(),
unstable: shared.options.unstable,
Expand Down
27 changes: 27 additions & 0 deletions ext/node/polyfills/tty.js
Original file line number Diff line number Diff line change
@@ -1,5 1,6 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.

import { op_bootstrap_color_depth } from "ext:core/ops";
import { core, primordials } from "ext:core/mod.js";
const {
Error,
Expand Down Expand Up @@ -105,6 106,32 @@ export class WriteStream extends Socket {
this.rows = rows;
this.isTTY = true;
}

/**
* @param {number | Record<string, string>} [count]
* @param {Record<string, string>} [env]
* @returns {boolean}
*/
hasColors(count, env) {
if (env === undefined && typeof count === "object") {
env = count;
count = 16;
}

const depth = this.getColorDepth(env);
return count <= 2 ** depth;
}

/**
* @param {Record<string, string} [env]
* @returns {1 | 4 | 8 | 24}
*/
getColorDepth(_env) {
// TODO(@marvinhagemeister): Ignore env parameter.
// Haven't seen it used anywhere, seems more done
// to make testing easier in Node
return op_bootstrap_color_depth();
}
}

export { isatty };
Expand Down
13 changes: 13 additions & 0 deletions runtime/ops/bootstrap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 2,7 @@

use deno_core::op2;
use deno_core::OpState;
use deno_terminal::colors::ColorLevel;
use serde::Serialize;

use crate::BootstrapOptions;
Expand All @@ -16,6 17,7 @@ deno_core::extension!(
op_bootstrap_language,
op_bootstrap_log_level,
op_bootstrap_no_color,
op_bootstrap_color_depth,
op_bootstrap_is_stdout_tty,
op_bootstrap_is_stderr_tty,
op_bootstrap_unstable_args,
Expand Down Expand Up @@ -126,6 128,17 @@ pub fn op_bootstrap_no_color(state: &mut OpState) -> bool {
options.no_color
}

#[op2(fast)]
pub fn op_bootstrap_color_depth(state: &mut OpState) -> i32 {
let options = state.borrow::<BootstrapOptions>();
match options.color_level {
ColorLevel::None => 1,
ColorLevel::Ansi => 4,
ColorLevel::Ansi256 => 8,
ColorLevel::TrueColor => 24,
}
}

#[op2(fast)]
pub fn op_bootstrap_is_stdout_tty(state: &mut OpState) -> bool {
let options = state.borrow::<BootstrapOptions>();
Expand Down
2 changes: 2 additions & 0 deletions runtime/worker_bootstrap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 77,7 @@ pub struct BootstrapOptions {
pub no_color: bool,
pub is_stdout_tty: bool,
pub is_stderr_tty: bool,
pub color_level: deno_terminal::colors::ColorLevel,
// --unstable flag, deprecated
pub unstable: bool,
// --unstable-* flags
Expand Down Expand Up @@ -111,6 112,7 @@ impl Default for BootstrapOptions {
no_color: !colors::use_color(),
is_stdout_tty: deno_terminal::is_stdout_tty(),
is_stderr_tty: deno_terminal::is_stderr_tty(),
color_level: colors::get_color_level(),
enable_op_summary_metrics: Default::default(),
enable_testing_features: Default::default(),
log_level: Default::default(),
Expand Down
9 changes: 9 additions & 0 deletions tests/unit_node/tty_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 3,7 @@

import { assert } from "@std/assert/mod.ts";
import { isatty } from "node:tty";
import tty from "node:tty";
import process from "node:process";

Deno.test("[node/tty isatty] returns true when fd is a tty, false otherwise", () => {
Expand Down Expand Up @@ -34,3 35,11 @@ Deno.test("[node/tty WriteStream.isTTY] returns true when fd is a tty", () => {
assert(Deno.stdin.isTerminal() === process.stdin.isTTY);
assert(Deno.stdout.isTerminal() === process.stdout.isTTY);
});

Deno.test("[node/tty WriteStream.hasColors] returns true when colors are supported", () => {
assert(tty.WriteStream.prototype.hasColors() === !Deno.noColor);
});

Deno.test("[node/tty WriteStream.getColorDepth] returns current terminal color depth", () => {
assert([1, 4, 8, 24].includes(tty.WriteStream.prototype.getColorDepth()));
});

0 comments on commit ee2e693

Please sign in to comment.