diff --git a/cli/js/deno.ts b/cli/js/deno.ts index 248e9cdc903d56..ebd1c8382689aa 100644 --- a/cli/js/deno.ts +++ b/cli/js/deno.ts @@ -85,7 +85,7 @@ export { ShutdownMode, shutdown } from "./net.ts"; -export { dir, env, exit, isTTY, execPath, hostname, loadavg } from "./os.ts"; +export { dir, env, exit, execPath, hostname, loadavg } from "./os.ts"; export { permissions, PermissionName, @@ -114,7 +114,7 @@ export { statSync, lstatSync, stat, lstat } from "./stat.ts"; export { symlinkSync, symlink } from "./symlink.ts"; export { connectTLS, listenTLS } from "./tls.ts"; export { truncateSync, truncate } from "./truncate.ts"; -export { isatty, setRaw } from "./tty.ts"; +export { isatty, isTTY, setRaw } from "./tty.ts"; export { utimeSync, utime } from "./utime.ts"; export { version } from "./version.ts"; export { writeFileSync, writeFile, WriteFileOptions } from "./write_file.ts"; diff --git a/cli/js/dispatch.ts b/cli/js/dispatch.ts index fc52dc2f656347..ae67afc80ba901 100644 --- a/cli/js/dispatch.ts +++ b/cli/js/dispatch.ts @@ -7,7 +7,6 @@ import { AsyncHandler } from "./plugins.ts"; export let OP_READ: number; export let OP_WRITE: number; export let OP_EXIT: number; -export let OP_IS_TTY: number; export let OP_ENV: number; export let OP_EXEC_PATH: number; export let OP_UTIME: number; diff --git a/cli/js/lib.deno.ns.d.ts b/cli/js/lib.deno.ns.d.ts index df30080931f514..489ad3a80b6183 100644 --- a/cli/js/lib.deno.ns.d.ts +++ b/cli/js/lib.deno.ns.d.ts @@ -30,16 +30,6 @@ declare namespace Deno { export function runTests(opts?: RunTestsOptions): Promise; - /** Check if running in terminal. - * - * console.log(Deno.isTTY().stdout); - */ - export function isTTY(): { - stdin: boolean; - stdout: boolean; - stderr: boolean; - }; - /** Get the loadavg. Requires the `--allow-env` flag. * * console.log(Deno.loadavg()); @@ -564,6 +554,16 @@ declare namespace Deno { */ export function setRaw(rid: number, mode: boolean): void; + /** Check if running in terminal. + * + * console.log(Deno.isTTY().stdout); + */ + export function isTTY(): { + stdin: boolean; + stdout: boolean; + stderr: boolean; + }; + // @url js/buffer.d.ts /** A Buffer is a variable-sized buffer of bytes with read() and write() diff --git a/cli/js/os.ts b/cli/js/os.ts index d3c0d1b7243945..4a48ae15eafb68 100644 --- a/cli/js/os.ts +++ b/cli/js/os.ts @@ -4,13 +4,6 @@ import { sendSync } from "./dispatch_json.ts"; import { Err } from "./errors.ts"; import * as util from "./util.ts"; -/** Check if running in terminal. - * - * console.log(Deno.isTTY().stdout); - */ -export function isTTY(): { stdin: boolean; stdout: boolean; stderr: boolean } { - return sendSync(dispatch.OP_IS_TTY); -} /** Get the loadavg. * Requires the `--allow-env` flag. * diff --git a/cli/js/os_test.ts b/cli/js/os_test.ts index 325cbdaa6d5e48..8175d3184e4383 100644 --- a/cli/js/os_test.ts +++ b/cli/js/os_test.ts @@ -115,10 +115,6 @@ test(function osPid(): void { assert(Deno.pid > 0); }); -test(function osIsTTYSmoke(): void { - console.log(Deno.isTTY()); -}); - testPerm({ env: true }, function getDir(): void { type supportOS = "mac" | "win" | "linux"; diff --git a/cli/js/tty.ts b/cli/js/tty.ts index 8cddcd7e001d83..b4d3e07e582ec4 100644 --- a/cli/js/tty.ts +++ b/cli/js/tty.ts @@ -13,3 +13,15 @@ export function setRaw(rid: number, mode: boolean): void { mode }); } + +/** Check if running in terminal. + * + * console.log(Deno.isTTY().stdout); + */ +export function isTTY(): { stdin: boolean; stdout: boolean; stderr: boolean } { + return { + stdin: isatty(0), + stdout: isatty(1), + stderr: isatty(2) + }; +} diff --git a/cli/js/tty_test.ts b/cli/js/tty_test.ts new file mode 100644 index 00000000000000..c91d5173025f01 --- /dev/null +++ b/cli/js/tty_test.ts @@ -0,0 +1,27 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. +import { test, testPerm, assert } from "./test_util.ts"; + +// setRaw test is in integration tests. + +// Smoke test to ensure no error. +test(function isTTYSmoke(): void { + console.log(Deno.isTTY()); +}); + +testPerm({ read: true }, function isatty(): void { + // CI not under TTY, so cannot test stdin/stdout/stderr. + const f = Deno.openSync("cli/tests/hello.txt"); + assert(!Deno.isatty(f.rid)); +}); + +test(function isattyError(): void { + let caught = false; + try { + // Absurdly large rid. + Deno.isatty(0x7fffffff); + } catch (e) { + caught = true; + assert(e instanceof Deno.Err.BadResource); + } + assert(caught); +}); diff --git a/cli/js/unit_tests.ts b/cli/js/unit_tests.ts index ec4505c219bfce..d2237477707001 100644 --- a/cli/js/unit_tests.ts +++ b/cli/js/unit_tests.ts @@ -53,6 +53,7 @@ import "./text_encoding_test.ts"; import "./timers_test.ts"; import "./tls_test.ts"; import "./truncate_test.ts"; +import "./tty_test.ts"; import "./url_test.ts"; import "./url_search_params_test.ts"; import "./utime_test.ts"; diff --git a/cli/ops/files.rs b/cli/ops/files.rs index cc06ea69b1a364..ba4aca27f6433a 100644 --- a/cli/ops/files.rs +++ b/cli/ops/files.rs @@ -1,8 +1,6 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. use super::dispatch_json::{Deserialize, JsonOp, Value}; use super::io::{FileMetadata, StreamResource}; -use crate::deno_error::DenoError; -use crate::deno_error::ErrorKind; use crate::fs as deno_fs; use crate::op_error::OpError; use crate::ops::json_op; diff --git a/cli/ops/os.rs b/cli/ops/os.rs index 10c5e247e07047..7d7cc8a9b6db80 100644 --- a/cli/ops/os.rs +++ b/cli/ops/os.rs @@ -3,7 +3,6 @@ use super::dispatch_json::{Deserialize, JsonOp, Value}; use crate::op_error::OpError; use crate::ops::json_op; use crate::state::State; -use atty; use deno_core::*; use std::collections::HashMap; use std::env; @@ -13,7 +12,6 @@ use url::Url; pub fn init(i: &mut Isolate, s: &State) { i.register_op("exit", s.core_op(json_op(s.stateful_op(op_exit)))); - i.register_op("is_tty", s.core_op(json_op(s.stateful_op(op_is_tty)))); i.register_op("env", s.core_op(json_op(s.stateful_op(op_env)))); i.register_op("exec_path", s.core_op(json_op(s.stateful_op(op_exec_path)))); i.register_op("set_env", s.core_op(json_op(s.stateful_op(op_set_env)))); @@ -151,18 +149,6 @@ fn op_exit( std::process::exit(args.code) } -fn op_is_tty( - _s: &State, - _args: Value, - _zero_copy: Option, -) -> Result { - Ok(JsonOp::Sync(json!({ - "stdin": atty::is(atty::Stream::Stdin), - "stdout": atty::is(atty::Stream::Stdout), - "stderr": atty::is(atty::Stream::Stderr), - }))) -} - fn op_loadavg( state: &State, _args: Value, diff --git a/cli/ops/tty.rs b/cli/ops/tty.rs index f38becaf6f1b4c..ce54caeca14716 100644 --- a/cli/ops/tty.rs +++ b/cli/ops/tty.rs @@ -1,7 +1,6 @@ use super::dispatch_json::JsonOp; use super::io::StreamResource; -use crate::deno_error::bad_resource; -use crate::deno_error::other_error; +use crate::op_error::OpError; use crate::ops::json_op; use crate::state::State; use atty; @@ -22,15 +21,15 @@ const RAW_MODE_MASK: DWORD = wincon::ENABLE_LINE_INPUT #[cfg(windows)] fn get_windows_handle( f: &std::fs::File, -) -> Result { +) -> Result { use std::os::windows::io::AsRawHandle; use winapi::um::handleapi; let handle = f.as_raw_handle(); if handle == handleapi::INVALID_HANDLE_VALUE { - return Err(ErrBox::from(std::io::Error::last_os_error())); + return Err(OpError::from(std::io::Error::last_os_error())); } else if handle.is_null() { - return Err(ErrBox::from(other_error("null handle".to_owned()))); + return Err(OpError::other("null handle".to_owned())); } Ok(handle) } @@ -45,7 +44,7 @@ macro_rules! wincheck { ($funcall:expr) => {{ let rc = unsafe { $funcall }; if rc == 0 { - Err(ErrBox::from(std::io::Error::last_os_error()))?; + Err(OpError::from(std::io::Error::last_os_error()))?; } rc }}; @@ -61,7 +60,7 @@ pub fn op_set_raw( state_: &State, args: Value, _zero_copy: Option, -) -> Result { +) -> Result { let args: SetRawArgs = serde_json::from_value(args)?; let rid = args.rid; let is_raw = args.mode; @@ -79,7 +78,7 @@ pub fn op_set_raw( let state = state_.borrow_mut(); let resource = state.resource_table.get::(rid); if resource.is_none() { - return Err(bad_resource()); + return Err(OpError::bad_resource()); } // For now, only stdin. @@ -91,14 +90,14 @@ pub fn op_set_raw( std_file.as_raw_handle() } _ => { - return Err(other_error("Not supported".to_owned())); + return Err(OpError::OpError::other("Not supported".to_owned())); } }; if handle == handleapi::INVALID_HANDLE_VALUE { - return Err(ErrBox::from(std::io::Error::last_os_error())); + return Err(OpError::from(std::io::Error::last_os_error())); } else if handle.is_null() { - return Err(ErrBox::from(other_error("null handle".to_owned()))); + return Err(OpError::other("null handle".to_owned())); } let mut original_mode: DWORD = 0; wincheck!(consoleapi::GetConsoleMode(handle, &mut original_mode)); @@ -118,7 +117,7 @@ pub fn op_set_raw( let mut state = state_.borrow_mut(); let resource = state.resource_table.get_mut::(rid); if resource.is_none() { - return Err(bad_resource()); + return Err(OpError::bad_resource()); } if is_raw { @@ -132,7 +131,7 @@ pub fn op_set_raw( (std_file.as_raw_fd(), &mut metadata.tty.mode) } _ => { - return Err(other_error("Not supported".to_owned())); + return Err(OpError::other("Not supported".to_owned())); } }; @@ -174,7 +173,7 @@ pub fn op_set_raw( (std_file.as_raw_fd(), &mut metadata.tty.mode) } _ => { - return Err(other_error("Not supported".to_owned())); + return Err(OpError::other("Not supported".to_owned())); } }; @@ -196,13 +195,13 @@ pub fn op_isatty( state_: &State, args: Value, _zero_copy: Option, -) -> Result { +) -> Result { let args: IsattyArgs = serde_json::from_value(args)?; let rid = args.rid; let state = state_.borrow_mut(); if !state.resource_table.has(rid) { - return Err(bad_resource()); + return Err(OpError::bad_resource()); } let resource = state.resource_table.get::(rid);