summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAsher Gomez <ashersaupingomez@gmail.com>2024-01-24 10:01:56 +1100
committerGitHub <noreply@github.com>2024-01-24 00:01:56 +0100
commit4eedac3604dad9f366d28868077eb02eddc22661 (patch)
treedda70cd31e731aad73e986002ef30acb84692dc4
parent60688c563e6d02813b021ad91132fe1eb3f103b6 (diff)
feat: `Deno.{stdin,stdout,stderr}.isTerminal()`, deprecate `Deno.isatty()` (#22011)
This change: 1. Implements `Deno.stdin.isTerminal()`, `Deno.stdout.isTerminal()` and `Deno.stderr.isTerminal()`. 2. Deprecates `Deno.isatty()` for removal in Deno v2, in favour of the above instance methods. 3. Replaces use of `Deno.isatty()` with the above instance methods. Related #21995 --------- Co-authored-by: Bartek IwaƄczuk <biwanczuk@gmail.com> Co-authored-by: Divy Srivastava <dj.srivastava23@gmail.com>
-rw-r--r--cli/tests/unit/tty_test.ts2
-rw-r--r--cli/tests/unit_node/process_test.ts8
-rw-r--r--cli/tests/unit_node/tty_test.ts10
-rw-r--r--cli/tsc/dts/lib.deno.ns.d.ts37
-rw-r--r--ext/io/12_io.js13
-rw-r--r--ext/node/polyfills/_process/streams.mjs15
-rw-r--r--ext/node/polyfills/assertion_error.ts4
-rw-r--r--ext/node/polyfills/tty.js12
-rw-r--r--runtime/js/40_tty.js13
-rw-r--r--runtime/js/41_prompt.js7
-rw-r--r--runtime/ops/tty.rs4
11 files changed, 92 insertions, 33 deletions
diff --git a/cli/tests/unit/tty_test.ts b/cli/tests/unit/tty_test.ts
index f6dc33b6a..8ca9a5d5b 100644
--- a/cli/tests/unit/tty_test.ts
+++ b/cli/tests/unit/tty_test.ts
@@ -4,7 +4,7 @@ import { assert } from "./test_util.ts";
// Note tests for Deno.stdin.setRaw is in integration tests.
Deno.test(function consoleSize() {
- if (!Deno.isatty(Deno.stdout.rid)) {
+ if (!Deno.stdout.isTerminal()) {
return;
}
const result = Deno.consoleSize();
diff --git a/cli/tests/unit_node/process_test.ts b/cli/tests/unit_node/process_test.ts
index 4cea31ed6..23bf73864 100644
--- a/cli/tests/unit_node/process_test.ts
+++ b/cli/tests/unit_node/process_test.ts
@@ -356,14 +356,14 @@ Deno.test({
name: "process.stdin",
fn() {
assertEquals(process.stdin.fd, Deno.stdin.rid);
- assertEquals(process.stdin.isTTY, Deno.isatty(Deno.stdin.rid));
+ assertEquals(process.stdin.isTTY, Deno.stdin.isTerminal());
},
});
Deno.test({
name: "process.stdin readable with a TTY",
// TODO(PolarETech): Run this test even in non tty environment
- ignore: !Deno.isatty(Deno.stdin.rid),
+ ignore: !Deno.stdin.isTerminal(),
// stdin resource is present before the test starts.
sanitizeResources: false,
async fn() {
@@ -535,7 +535,7 @@ Deno.test({
name: "process.stdout",
fn() {
assertEquals(process.stdout.fd, Deno.stdout.rid);
- const isTTY = Deno.isatty(Deno.stdout.rid);
+ const isTTY = Deno.stdout.isTerminal();
assertEquals(process.stdout.isTTY, isTTY);
const consoleSize = isTTY ? Deno.consoleSize() : undefined;
assertEquals(process.stdout.columns, consoleSize?.columns);
@@ -563,7 +563,7 @@ Deno.test({
name: "process.stderr",
fn() {
assertEquals(process.stderr.fd, Deno.stderr.rid);
- const isTTY = Deno.isatty(Deno.stderr.rid);
+ const isTTY = Deno.stderr.isTerminal();
assertEquals(process.stderr.isTTY, isTTY);
const consoleSize = isTTY ? Deno.consoleSize() : undefined;
assertEquals(process.stderr.columns, consoleSize?.columns);
diff --git a/cli/tests/unit_node/tty_test.ts b/cli/tests/unit_node/tty_test.ts
index c393da5b3..8e2f66f9e 100644
--- a/cli/tests/unit_node/tty_test.ts
+++ b/cli/tests/unit_node/tty_test.ts
@@ -6,9 +6,9 @@ import { isatty } from "node:tty";
import process from "node:process";
Deno.test("[node/tty isatty] returns true when fd is a tty, false otherwise", () => {
- assert(Deno.isatty(Deno.stdin.rid) === isatty(Deno.stdin.rid));
- assert(Deno.isatty(Deno.stdout.rid) === isatty(Deno.stdout.rid));
- assert(Deno.isatty(Deno.stderr.rid) === isatty(Deno.stderr.rid));
+ assert(Deno.stdin.isTerminal() === isatty(Deno.stdin.rid));
+ assert(Deno.stdout.isTerminal() === isatty(Deno.stdout.rid));
+ assert(Deno.stderr.isTerminal() === isatty(Deno.stderr.rid));
const file = Deno.openSync("README.md");
assert(!isatty(file.rid));
@@ -32,6 +32,6 @@ Deno.test("[node/tty isatty] returns false for irrelevant values", () => {
});
Deno.test("[node/tty WriteStream.isTTY] returns true when fd is a tty", () => {
- assert(Deno.isatty(Deno.stdin.rid) === process.stdin.isTTY);
- assert(Deno.isatty(Deno.stdout.rid) === process.stdout.isTTY);
+ assert(Deno.stdin.isTerminal() === process.stdin.isTTY);
+ assert(Deno.stdout.isTerminal() === process.stdout.isTTY);
});
diff --git a/cli/tsc/dts/lib.deno.ns.d.ts b/cli/tsc/dts/lib.deno.ns.d.ts
index 483c5c3d0..bc3248d02 100644
--- a/cli/tsc/dts/lib.deno.ns.d.ts
+++ b/cli/tsc/dts/lib.deno.ns.d.ts
@@ -2612,6 +2612,17 @@ declare namespace Deno {
* @category I/O
*/
setRaw(mode: boolean, options?: SetRawOptions): void;
+ /**
+ * Checks if `stdin` is a TTY (terminal).
+ *
+ * ```ts
+ * // This example is system and context specific
+ * Deno.stdin.isTerminal(); // true
+ * ```
+ *
+ * @category I/O
+ */
+ isTerminal(): boolean;
};
/** A reference to `stdout` which can be used to write directly to `stdout`.
* It implements the Deno specific {@linkcode Writer}, {@linkcode WriterSync},
@@ -2629,6 +2640,17 @@ declare namespace Deno {
readonly rid: number;
/** A writable stream interface to `stdout`. */
readonly writable: WritableStream<Uint8Array>;
+ /**
+ * Checks if `stdout` is a TTY (terminal).
+ *
+ * ```ts
+ * // This example is system and context specific
+ * Deno.stdout.isTerminal(); // true
+ * ```
+ *
+ * @category I/O
+ */
+ isTerminal(): boolean;
};
/** A reference to `stderr` which can be used to write directly to `stderr`.
* It implements the Deno specific {@linkcode Writer}, {@linkcode WriterSync},
@@ -2646,6 +2668,17 @@ declare namespace Deno {
readonly rid: number;
/** A writable stream interface to `stderr`. */
readonly writable: WritableStream<Uint8Array>;
+ /**
+ * Checks if `stderr` is a TTY (terminal).
+ *
+ * ```ts
+ * // This example is system and context specific
+ * Deno.stderr.isTerminal(); // true
+ * ```
+ *
+ * @category I/O
+ */
+ isTerminal(): boolean;
};
/**
@@ -2728,6 +2761,10 @@ declare namespace Deno {
* Deno.close(ttyRid);
* ```
*
+ * @deprecated Use `Deno.stdin.isTerminal()`, `Deno.stdout.isTerminal()` or
+ * `Deno.stderr.isTerminal()` instead.
+ * {@linkcode Deno.isatty} will be removed in v2.0.0.
+ *
* @category I/O
*/
export function isatty(rid: number): boolean;
diff --git a/ext/io/12_io.js b/ext/io/12_io.js
index d9b91a947..9f4a3766b 100644
--- a/ext/io/12_io.js
+++ b/ext/io/12_io.js
@@ -7,6 +7,7 @@
import { core, primordials } from "ext:core/mod.js";
const {
op_stdin_set_raw,
+ op_is_terminal,
} = core.ensureFastOps(true);
const {
Uint8Array,
@@ -197,6 +198,10 @@ class Stdin {
const cbreak = !!(options.cbreak ?? false);
op_stdin_set_raw(mode, cbreak);
}
+
+ isTerminal() {
+ return op_is_terminal(this.rid);
+ }
}
class Stdout {
@@ -227,6 +232,10 @@ class Stdout {
}
return this.#writable;
}
+
+ isTerminal() {
+ return op_is_terminal(this.rid);
+ }
}
class Stderr {
@@ -257,6 +266,10 @@ class Stderr {
}
return this.#writable;
}
+
+ isTerminal() {
+ return op_is_terminal(this.rid);
+ }
}
const stdin = new Stdin();
diff --git a/ext/node/polyfills/_process/streams.mjs b/ext/node/polyfills/_process/streams.mjs
index 14d58fcab..166d099c8 100644
--- a/ext/node/polyfills/_process/streams.mjs
+++ b/ext/node/polyfills/_process/streams.mjs
@@ -46,30 +46,27 @@ export function createWritableStdioStream(writer, name) {
enumerable: true,
configurable: true,
get: () =>
- Deno.isatty?.(writer?.rid) ? Deno.consoleSize?.().columns : undefined,
+ writer?.isTerminal() ? Deno.consoleSize?.().columns : undefined,
},
rows: {
enumerable: true,
configurable: true,
- get: () =>
- Deno.isatty?.(writer?.rid) ? Deno.consoleSize?.().rows : undefined,
+ get: () => writer?.isTerminal() ? Deno.consoleSize?.().rows : undefined,
},
isTTY: {
enumerable: true,
configurable: true,
- get: () => Deno.isatty?.(writer?.rid),
+ get: () => writer?.isTerminal(),
},
getWindowSize: {
enumerable: true,
configurable: true,
value: () =>
- Deno.isatty?.(writer?.rid)
- ? Object.values(Deno.consoleSize?.())
- : undefined,
+ writer?.isTerminal() ? Object.values(Deno.consoleSize?.()) : undefined,
},
});
- if (Deno.isatty?.(writer?.rid)) {
+ if (writer?.isTerminal()) {
// These belong on tty.WriteStream(), but the TTY streams currently have
// following problems:
// 1. Using them here introduces a circular dependency.
@@ -180,7 +177,7 @@ export const initStdin = () => {
enumerable: true,
configurable: true,
get() {
- return Deno.isatty?.(io.stdin.rid);
+ return io.stdin.isTerminal();
},
});
stdin._isRawMode = false;
diff --git a/ext/node/polyfills/assertion_error.ts b/ext/node/polyfills/assertion_error.ts
index bec1f6ba5..ff1168dc3 100644
--- a/ext/node/polyfills/assertion_error.ts
+++ b/ext/node/polyfills/assertion_error.ts
@@ -163,7 +163,7 @@ export function createErrDiff(
// If the stderr is a tty and the input length is lower than the current
// columns per line, add a mismatch indicator below the output. If it is
// not a tty, use a default value of 80 characters.
- const maxLength = Deno.isatty(io.stderr.rid) ? getConsoleWidth() : 80;
+ const maxLength = io.stderr.isTerminal() ? getConsoleWidth() : 80;
if (inputLength < maxLength) {
while (actualRaw[i] === expectedRaw[i]) {
i++;
@@ -406,7 +406,7 @@ export class AssertionError extends Error {
if (message != null) {
super(String(message));
} else {
- if (Deno.isatty(io.stderr.rid)) {
+ if (io.stderr.isTerminal()) {
// Reset on each call to make sure we handle dynamically set environment
// variables correct.
if (Deno.noColor) {
diff --git a/ext/node/polyfills/tty.js b/ext/node/polyfills/tty.js
index 86fd34d7c..eae1db2d9 100644
--- a/ext/node/polyfills/tty.js
+++ b/ext/node/polyfills/tty.js
@@ -1,9 +1,12 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
-import { primordials } from "ext:core/mod.js";
+import { core, primordials } from "ext:core/mod.js";
const {
Error,
} = primordials;
+const {
+ op_is_terminal,
+} = core.ensureFastOps(true);
import { ERR_INVALID_FD } from "ext:deno_node/internal/errors.ts";
import { LibuvStreamWrap } from "ext:deno_node/internal_binding/stream_wrap.ts";
@@ -17,7 +20,12 @@ function isatty(fd) {
return false;
}
try {
- return Deno.isatty(fd);
+ /**
+ * TODO: Treat `fd` as real file descriptors. Currently, `rid` 0, 1, 2
+ * correspond to `fd` 0, 1, 2 (stdin, stdout, stderr). This may change in
+ * the future.
+ */
+ return op_is_terminal(fd);
} catch (_) {
return false;
}
diff --git a/runtime/js/40_tty.js b/runtime/js/40_tty.js
index e94fc0374..97e35e0c3 100644
--- a/runtime/js/40_tty.js
+++ b/runtime/js/40_tty.js
@@ -1,9 +1,9 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
-import { core, primordials } from "ext:core/mod.js";
+import { core, internals, primordials } from "ext:core/mod.js";
const {
op_console_size,
- op_isatty,
-} = core.ensureFastOps();
+ op_is_terminal,
+} = core.ensureFastOps(true);
const {
Uint32Array,
} = primordials;
@@ -16,7 +16,12 @@ function consoleSize() {
}
function isatty(rid) {
- return op_isatty(rid);
+ internals.warnOnDeprecatedApi(
+ "Deno.isatty()",
+ new Error().stack,
+ "Use `stdStream.isTerminal()` instead.",
+ );
+ return op_is_terminal(rid);
}
export { consoleSize, isatty };
diff --git a/runtime/js/41_prompt.js b/runtime/js/41_prompt.js
index fce1ac9ac..d0e065538 100644
--- a/runtime/js/41_prompt.js
+++ b/runtime/js/41_prompt.js
@@ -9,14 +9,13 @@ const {
Uint8Array,
} = primordials;
-import { isatty } from "ext:runtime/40_tty.js";
import { stdin } from "ext:deno_io/12_io.js";
const LF = StringPrototypeCharCodeAt("\n", 0);
const CR = StringPrototypeCharCodeAt("\r", 0);
function alert(message = "Alert") {
- if (!isatty(stdin.rid)) {
+ if (!stdin.isTerminal()) {
return;
}
@@ -26,7 +25,7 @@ function alert(message = "Alert") {
}
function confirm(message = "Confirm") {
- if (!isatty(stdin.rid)) {
+ if (!stdin.isTerminal()) {
return false;
}
@@ -40,7 +39,7 @@ function confirm(message = "Confirm") {
function prompt(message = "Prompt", defaultValue) {
defaultValue ??= "";
- if (!isatty(stdin.rid)) {
+ if (!stdin.isTerminal()) {
return null;
}
diff --git a/runtime/ops/tty.rs b/runtime/ops/tty.rs
index 6cc129883..40aa28494 100644
--- a/runtime/ops/tty.rs
+++ b/runtime/ops/tty.rs
@@ -52,7 +52,7 @@ deno_core::extension!(
deno_tty,
ops = [
op_stdin_set_raw,
- op_isatty,
+ op_is_terminal,
op_console_size,
op_read_line_prompt
],
@@ -210,7 +210,7 @@ fn op_stdin_set_raw(
}
#[op2(fast)]
-fn op_isatty(state: &mut OpState, rid: u32) -> Result<bool, AnyError> {
+fn op_is_terminal(state: &mut OpState, rid: u32) -> Result<bool, AnyError> {
let handle = state.resource_table.get_handle(rid)?;
Ok(handle.is_terminal())
}