summaryrefslogtreecommitdiff
path: root/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'runtime')
-rw-r--r--runtime/ops/tty.rs115
1 files changed, 71 insertions, 44 deletions
diff --git a/runtime/ops/tty.rs b/runtime/ops/tty.rs
index 3146f22e2..a3dc03a6f 100644
--- a/runtime/ops/tty.rs
+++ b/runtime/ops/tty.rs
@@ -7,7 +7,34 @@ use deno_io::StdFileResource;
use std::io::Error;
#[cfg(unix)]
+use deno_core::ResourceId;
+#[cfg(unix)]
use nix::sys::termios;
+#[cfg(unix)]
+use std::cell::RefCell;
+#[cfg(unix)]
+use std::collections::HashMap;
+#[cfg(unix)]
+use std::rc::Rc;
+
+#[cfg(unix)]
+#[derive(Default, Clone)]
+struct TtyModeStore(Rc<RefCell<HashMap<ResourceId, termios::Termios>>>);
+
+#[cfg(unix)]
+impl TtyModeStore {
+ pub fn get(&self, id: ResourceId) -> Option<termios::Termios> {
+ self.0.borrow().get(&id).map(ToOwned::to_owned)
+ }
+
+ pub fn take(&self, id: ResourceId) -> Option<termios::Termios> {
+ self.0.borrow_mut().remove(&id)
+ }
+
+ pub fn set(&self, id: ResourceId, mode: termios::Termios) {
+ self.0.borrow_mut().insert(id, mode);
+ }
+}
#[cfg(windows)]
use deno_core::error::custom_error;
@@ -35,6 +62,10 @@ fn get_windows_handle(
deno_core::extension!(
deno_tty,
ops = [op_stdin_set_raw, op_isatty, op_console_size],
+ state = |state| {
+ #[cfg(unix)]
+ state.put(TtyModeStore::default());
+ },
customizer = |ext: &mut deno_core::ExtensionBuilder| {
ext.force_op_registration();
},
@@ -118,53 +149,49 @@ fn op_stdin_set_raw(
{
use std::os::unix::io::AsRawFd;
- StdFileResource::with_file_and_metadata(
- state,
- rid,
- move |std_file, meta_data| {
- let raw_fd = std_file.as_raw_fd();
-
- if is_raw {
- let mut raw = {
- let mut meta_data = meta_data.lock();
- let maybe_tty_mode = &mut meta_data.tty.mode;
- if maybe_tty_mode.is_none() {
- // Save original mode.
- let original_mode = termios::tcgetattr(raw_fd)?;
- maybe_tty_mode.replace(original_mode);
- }
- maybe_tty_mode.clone().unwrap()
- };
-
- raw.input_flags &= !(termios::InputFlags::BRKINT
- | termios::InputFlags::ICRNL
- | termios::InputFlags::INPCK
- | termios::InputFlags::ISTRIP
- | termios::InputFlags::IXON);
-
- raw.control_flags |= termios::ControlFlags::CS8;
-
- raw.local_flags &= !(termios::LocalFlags::ECHO
- | termios::LocalFlags::ICANON
- | termios::LocalFlags::IEXTEN);
- if !cbreak {
- raw.local_flags &= !(termios::LocalFlags::ISIG);
- }
- raw.control_chars[termios::SpecialCharacterIndices::VMIN as usize] =
- 1;
- raw.control_chars[termios::SpecialCharacterIndices::VTIME as usize] =
- 0;
- termios::tcsetattr(raw_fd, termios::SetArg::TCSADRAIN, &raw)?;
- } else {
- // Try restore saved mode.
- if let Some(mode) = meta_data.lock().tty.mode.take() {
- termios::tcsetattr(raw_fd, termios::SetArg::TCSADRAIN, &mode)?;
+ let tty_mode_store = state.borrow::<TtyModeStore>().clone();
+ let previous_mode = tty_mode_store.get(rid);
+
+ StdFileResource::with_file(state, rid, move |std_file| {
+ let raw_fd = std_file.as_raw_fd();
+
+ if is_raw {
+ let mut raw = match previous_mode {
+ Some(mode) => mode,
+ None => {
+ // Save original mode.
+ let original_mode = termios::tcgetattr(raw_fd)?;
+ tty_mode_store.set(rid, original_mode.clone());
+ original_mode
}
+ };
+
+ raw.input_flags &= !(termios::InputFlags::BRKINT
+ | termios::InputFlags::ICRNL
+ | termios::InputFlags::INPCK
+ | termios::InputFlags::ISTRIP
+ | termios::InputFlags::IXON);
+
+ raw.control_flags |= termios::ControlFlags::CS8;
+
+ raw.local_flags &= !(termios::LocalFlags::ECHO
+ | termios::LocalFlags::ICANON
+ | termios::LocalFlags::IEXTEN);
+ if !cbreak {
+ raw.local_flags &= !(termios::LocalFlags::ISIG);
+ }
+ raw.control_chars[termios::SpecialCharacterIndices::VMIN as usize] = 1;
+ raw.control_chars[termios::SpecialCharacterIndices::VTIME as usize] = 0;
+ termios::tcsetattr(raw_fd, termios::SetArg::TCSADRAIN, &raw)?;
+ } else {
+ // Try restore saved mode.
+ if let Some(mode) = tty_mode_store.take(rid) {
+ termios::tcsetattr(raw_fd, termios::SetArg::TCSADRAIN, &mode)?;
}
+ }
- Ok(())
- },
- )
+ Ok(())
+ })
}
}