diff options
author | Marvin Hagemeister <marvin@deno.com> | 2024-07-19 12:39:05 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-07-19 12:39:05 +0200 |
commit | ee2e6933403811d398540e0e8275b2d216546dd8 (patch) | |
tree | 4ed2944dfbc516ea127c4bee50cc771ac12f902d | |
parent | 76b8ecbb6d8c07d29c34fb0b301cc3bf3351e3aa (diff) |
fix(node): support `tty.hasColors()` and `tty.getColorDepth()` (#24619)
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 https://github.com/denoland/deno_terminal/pull/3
Fixes https://github.com/denoland/deno/issues/24616
-rw-r--r-- | Cargo.lock | 22 | ||||
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | cli/worker.rs | 2 | ||||
-rw-r--r-- | ext/node/polyfills/tty.js | 27 | ||||
-rw-r--r-- | runtime/ops/bootstrap.rs | 13 | ||||
-rw-r--r-- | runtime/worker_bootstrap.rs | 2 | ||||
-rw-r--r-- | tests/unit_node/tty_test.ts | 9 |
7 files changed, 70 insertions, 7 deletions
diff --git a/Cargo.lock b/Cargo.lock index 615abf0f0..57449dbc7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -729,7 +729,7 @@ dependencies = [ "deno_core", "deno_fetch", "deno_lockfile", - "deno_terminal", + "deno_terminal 0.2.0", "deno_tls", "fastwebsockets", "file_test_runner", @@ -1134,7 +1134,7 @@ dependencies = [ "deno_runtime", "deno_semver", "deno_task_shell", - "deno_terminal", + "deno_terminal 0.2.0", "dissimilar", "dotenvy", "dprint-plugin-json", @@ -1216,7 +1216,7 @@ dependencies = [ "anyhow", "base64 0.21.7", "deno_media_type", - "deno_terminal", + "deno_terminal 0.1.1", "dprint-swc-ext", "once_cell", "percent-encoding", @@ -1836,7 +1836,7 @@ name = "deno_permissions" version = "0.21.0" dependencies = [ "deno_core", - "deno_terminal", + "deno_terminal 0.2.0", "fqdn", "libc", "log", @@ -1868,7 +1868,7 @@ dependencies = [ "deno_net", "deno_node", "deno_permissions", - "deno_terminal", + "deno_terminal 0.2.0", "deno_tls", "deno_url", "deno_web", @@ -1949,6 +1949,16 @@ dependencies = [ ] [[package]] +name = "deno_terminal" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daef12499e89ee99e51ad6000a91f600d3937fb028ad4918af76810c5bc9e0d5" +dependencies = [ + "once_cell", + "termcolor", +] + +[[package]] name = "deno_tls" version = "0.148.0" dependencies = [ @@ -2734,7 +2744,7 @@ checksum = "05b23dcc1b671771c6f59fdace6da685735c925f859733e8fd07fba6cae6462a" dependencies = [ "anyhow", "crossbeam-channel", - "deno_terminal", + "deno_terminal 0.1.1", "parking_lot 0.12.3", "regex", "thiserror", diff --git a/Cargo.toml b/Cargo.toml index 492ddc47f..b1e1a20cc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" } diff --git a/cli/worker.rs b/cli/worker.rs index 9125f28be..36435d634 100644 --- a/cli/worker.rs +++ b/cli/worker.rs @@ -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(), @@ -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, diff --git a/ext/node/polyfills/tty.js b/ext/node/polyfills/tty.js index 3a84a1f94..2e8ecc8e1 100644 --- a/ext/node/polyfills/tty.js +++ b/ext/node/polyfills/tty.js @@ -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, @@ -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 }; diff --git a/runtime/ops/bootstrap.rs b/runtime/ops/bootstrap.rs index c5c193ef3..997bebd76 100644 --- a/runtime/ops/bootstrap.rs +++ b/runtime/ops/bootstrap.rs @@ -2,6 +2,7 @@ use deno_core::op2; use deno_core::OpState; +use deno_terminal::colors::ColorLevel; use serde::Serialize; use crate::BootstrapOptions; @@ -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, @@ -127,6 +129,17 @@ pub fn op_bootstrap_no_color(state: &mut OpState) -> bool { } #[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>(); options.is_stdout_tty diff --git a/runtime/worker_bootstrap.rs b/runtime/worker_bootstrap.rs index 0838da2d1..b13c3c428 100644 --- a/runtime/worker_bootstrap.rs +++ b/runtime/worker_bootstrap.rs @@ -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 @@ -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(), diff --git a/tests/unit_node/tty_test.ts b/tests/unit_node/tty_test.ts index 39ab4fe17..cde05b9ff 100644 --- a/tests/unit_node/tty_test.ts +++ b/tests/unit_node/tty_test.ts @@ -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", () => { @@ -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())); +}); |