1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-21 15:04:11 -05:00

fix(runtime): output to stderr with colors if a tty and stdout is piped (#23813)

This also fixes a bug where Deno would output to stderr with colours
when piped and stdout was not piped.
This commit is contained in:
David Sherret 2024-05-14 17:32:09 -04:00 committed by GitHub
parent 1e2b0a2219
commit e39b94f3aa
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 61 additions and 33 deletions

View file

@ -601,7 +601,8 @@ impl CliMainWorkerFactory {
locale: deno_core::v8::icu::get_language_tag(),
location: shared.options.location.clone(),
no_color: !colors::use_color(),
is_tty: deno_terminal::is_stdout_tty(),
is_stdout_tty: deno_terminal::is_stdout_tty(),
is_stderr_tty: deno_terminal::is_stderr_tty(),
unstable: shared.options.unstable,
unstable_features,
user_agent: version::get_user_agent().to_string(),
@ -811,7 +812,8 @@ fn create_web_worker_callback(
locale: deno_core::v8::icu::get_language_tag(),
location: Some(args.main_module.clone()),
no_color: !colors::use_color(),
is_tty: deno_terminal::is_stdout_tty(),
is_stdout_tty: deno_terminal::is_stdout_tty(),
is_stderr_tty: deno_terminal::is_stderr_tty(),
unstable: shared.options.unstable,
unstable_features,
user_agent: version::get_user_agent().to_string(),

View file

@ -156,14 +156,20 @@ const {
Uint8Array,
} = primordials;
let noColor = () => false;
let noColorStdout = () => false;
let noColorStderr = () => false;
function setNoColorFn(fn) {
noColor = fn;
function setNoColorFns(stdoutFn, stderrFn) {
noColorStdout = stdoutFn;
noColorStderr = stderrFn;
}
function getNoColor() {
return noColor();
function getStdoutNoColor() {
return noColorStdout();
}
function getStderrNoColor() {
return noColorStderr();
}
function assert(cond, msg = "Assertion failed.") {
@ -2927,6 +2933,7 @@ function cssToAnsi(css, prevCss = null) {
function inspectArgs(args, inspectOptions = {}) {
const ctx = {
...getDefaultInspectOptions(),
colors: inspectOptions.colors ?? !noColorStdout(),
...inspectOptions,
};
if (inspectOptions.iterableLimit !== undefined) {
@ -2939,7 +2946,7 @@ function inspectArgs(args, inspectOptions = {}) {
if (ctx.maxArrayLength === null) ctx.maxArrayLength = Infinity;
if (ctx.maxStringLength === null) ctx.maxStringLength = Infinity;
const noColor = getNoColor();
const noColor = !ctx.colors;
const first = args[0];
let a = 0;
let string = "";
@ -3053,12 +3060,12 @@ const countMap = new SafeMap();
const timerMap = new SafeMap();
const isConsoleInstance = Symbol("isConsoleInstance");
function getConsoleInspectOptions() {
const color = !getNoColor();
/** @param noColor {boolean} */
function getConsoleInspectOptions(noColor) {
return {
...getDefaultInspectOptions(),
colors: color,
stylize: color ? createStylizeWithColor(styles, colors) : stylizeNoColor,
colors: !noColor,
stylize: noColor ? stylizeNoColor : createStylizeWithColor(styles, colors),
};
}
@ -3090,7 +3097,7 @@ class Console {
log = (...args) => {
this.#printFunc(
inspectArgs(args, {
...getConsoleInspectOptions(),
...getConsoleInspectOptions(noColorStdout()),
indentLevel: this.indentLevel,
}) + "\n",
1,
@ -3100,7 +3107,7 @@ class Console {
debug = (...args) => {
this.#printFunc(
inspectArgs(args, {
...getConsoleInspectOptions(),
...getConsoleInspectOptions(noColorStdout()),
indentLevel: this.indentLevel,
}) + "\n",
0,
@ -3110,7 +3117,7 @@ class Console {
info = (...args) => {
this.#printFunc(
inspectArgs(args, {
...getConsoleInspectOptions(),
...getConsoleInspectOptions(noColorStdout()),
indentLevel: this.indentLevel,
}) + "\n",
1,
@ -3119,8 +3126,10 @@ class Console {
dir = (obj = undefined, options = {}) => {
this.#printFunc(
inspectArgs([obj], { ...getConsoleInspectOptions(), ...options }) +
"\n",
inspectArgs([obj], {
...getConsoleInspectOptions(noColorStdout()),
...options,
}) + "\n",
1,
);
};
@ -3130,7 +3139,7 @@ class Console {
warn = (...args) => {
this.#printFunc(
inspectArgs(args, {
...getConsoleInspectOptions(),
...getConsoleInspectOptions(noColorStderr()),
indentLevel: this.indentLevel,
}) + "\n",
2,
@ -3140,7 +3149,7 @@ class Console {
error = (...args) => {
this.#printFunc(
inspectArgs(args, {
...getConsoleInspectOptions(),
...getConsoleInspectOptions(noColorStderr()),
indentLevel: this.indentLevel,
}) + "\n",
3,
@ -3353,7 +3362,10 @@ class Console {
trace = (...args) => {
const message = inspectArgs(
args,
{ ...getConsoleInspectOptions(), indentLevel: 0 },
{
...getConsoleInspectOptions(noColorStderr()),
indentLevel: 0,
},
);
const err = {
name: "Trace",
@ -3473,10 +3485,11 @@ export {
formatNumber,
formatValue,
getDefaultInspectOptions,
getNoColor,
getStderrNoColor,
getStdoutNoColor,
inspect,
inspectArgs,
quoteString,
setNoColorFn,
setNoColorFns,
styles,
};

View file

@ -8,7 +8,8 @@ import { core, internals, primordials } from "ext:core/mod.js";
const ops = core.ops;
import {
op_bootstrap_args,
op_bootstrap_is_tty,
op_bootstrap_is_stderr_tty,
op_bootstrap_is_stdout_tty,
op_bootstrap_no_color,
op_bootstrap_pid,
op_main_module,
@ -62,10 +63,10 @@ import * as timers from "ext:deno_web/02_timers.js";
import {
customInspect,
getDefaultInspectOptions,
getNoColor,
getStderrNoColor,
inspectArgs,
quoteString,
setNoColorFn,
setNoColorFns,
} from "ext:deno_console/01_console.js";
import * as performance from "ext:deno_web/15_performance.js";
import * as url from "ext:deno_url/00_url.js";
@ -379,7 +380,10 @@ function importScripts(...urls) {
const opArgs = memoizeLazy(() => op_bootstrap_args());
const opPid = memoizeLazy(() => op_bootstrap_pid());
setNoColorFn(() => op_bootstrap_no_color() || !op_bootstrap_is_tty());
setNoColorFns(
() => op_bootstrap_no_color() || !op_bootstrap_is_stdout_tty(),
() => op_bootstrap_no_color() || !op_bootstrap_is_stderr_tty(),
);
function formatException(error) {
if (
@ -390,11 +394,11 @@ function formatException(error) {
} else if (typeof error == "string") {
return `Uncaught ${
inspectArgs([quoteString(error, getDefaultInspectOptions())], {
colors: !getNoColor(),
colors: !getStderrNoColor(),
})
}`;
} else {
return `Uncaught ${inspectArgs([error], { colors: !getNoColor() })}`;
return `Uncaught ${inspectArgs([error], { colors: !getStderrNoColor() })}`;
}
}

View file

@ -16,7 +16,8 @@ deno_core::extension!(
op_bootstrap_language,
op_bootstrap_log_level,
op_bootstrap_no_color,
op_bootstrap_is_tty,
op_bootstrap_is_stdout_tty,
op_bootstrap_is_stderr_tty,
op_bootstrap_unstable_args,
op_snapshot_options,
],
@ -117,7 +118,13 @@ pub fn op_bootstrap_no_color(state: &mut OpState) -> bool {
}
#[op2(fast)]
pub fn op_bootstrap_is_tty(state: &mut OpState) -> bool {
pub fn op_bootstrap_is_stdout_tty(state: &mut OpState) -> bool {
let options = state.borrow::<BootstrapOptions>();
options.is_tty
options.is_stdout_tty
}
#[op2(fast)]
pub fn op_bootstrap_is_stderr_tty(state: &mut OpState) -> bool {
let options = state.borrow::<BootstrapOptions>();
options.is_stderr_tty
}

View file

@ -76,7 +76,8 @@ pub struct BootstrapOptions {
pub location: Option<ModuleSpecifier>,
/// Sets `Deno.noColor` in JS runtime.
pub no_color: bool,
pub is_tty: bool,
pub is_stdout_tty: bool,
pub is_stderr_tty: bool,
// --unstable flag, deprecated
pub unstable: bool,
// --unstable-* flags
@ -109,7 +110,8 @@ impl Default for BootstrapOptions {
user_agent,
cpu_count,
no_color: !colors::use_color(),
is_tty: deno_terminal::is_stdout_tty(),
is_stdout_tty: deno_terminal::is_stdout_tty(),
is_stderr_tty: deno_terminal::is_stderr_tty(),
enable_op_summary_metrics: Default::default(),
enable_testing_features: Default::default(),
log_level: Default::default(),