Skip to content

Commit

Permalink
refactor(runtime): use new fd methods from resource table (denoland#2…
Browse files Browse the repository at this point in the history
…0010)

Prereq for fast streams work. No longer need `#[cfg]` around
`backing_fd`.
  • Loading branch information
mmastrac committed Aug 1, 2023
1 parent ab2627a commit 45572e3
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 152 deletions.
8 changes: 2 additions & 6 deletions cli/standalone/virtual_fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use deno_core::error::AnyError;
use deno_core::parking_lot::Mutex;
use deno_core::BufMutView;
use deno_core::BufView;
use deno_core::ResourceHandleFd;
use deno_runtime::deno_fs::FsDirEntry;
use deno_runtime::deno_io;
use deno_runtime::deno_io::fs::FsError;
Expand Down Expand Up @@ -697,12 +698,7 @@ impl deno_io::fs::File for FileBackedVfsFile {
fn as_stdio(self: Rc<Self>) -> FsResult<std::process::Stdio> {
Err(FsError::NotSupported)
}
#[cfg(unix)]
fn backing_fd(self: Rc<Self>) -> Option<std::os::unix::prelude::RawFd> {
None
}
#[cfg(windows)]
fn backing_fd(self: Rc<Self>) -> Option<std::os::windows::io::RawHandle> {
fn backing_fd(self: Rc<Self>) -> Option<ResourceHandleFd> {
None
}
fn try_clone_inner(self: Rc<Self>) -> FsResult<Rc<dyn deno_io::fs::File>> {
Expand Down
16 changes: 4 additions & 12 deletions ext/io/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use deno_core::error::AnyError;
use deno_core::BufMutView;
use deno_core::BufView;
use deno_core::OpState;
use deno_core::ResourceHandleFd;
use deno_core::ResourceId;
use tokio::task::JoinError;

Expand Down Expand Up @@ -236,10 +237,7 @@ pub trait File {

// lower level functionality
fn as_stdio(self: Rc<Self>) -> FsResult<std::process::Stdio>;
#[cfg(unix)]
fn backing_fd(self: Rc<Self>) -> Option<std::os::unix::prelude::RawFd>;
#[cfg(windows)]
fn backing_fd(self: Rc<Self>) -> Option<std::os::windows::io::RawHandle>;
fn backing_fd(self: Rc<Self>) -> Option<ResourceHandleFd>;
fn try_clone_inner(self: Rc<Self>) -> FsResult<Rc<dyn File>>;
}

Expand All @@ -253,7 +251,7 @@ impl FileResource {
Self { name, file }
}

pub fn with_resource<F, R>(
fn with_resource<F, R>(
state: &OpState,
rid: ResourceId,
f: F,
Expand Down Expand Up @@ -359,13 +357,7 @@ impl deno_core::Resource for FileResource {
self.file.clone().write_sync(data).map_err(|err| err.into())
}

#[cfg(unix)]
fn backing_fd(self: Rc<Self>) -> Option<std::os::unix::prelude::RawFd> {
self.file.clone().backing_fd()
}

#[cfg(windows)]
fn backing_fd(self: Rc<Self>) -> Option<std::os::windows::io::RawHandle> {
fn backing_fd(self: Rc<Self>) -> Option<ResourceHandleFd> {
self.file.clone().backing_fd()
}
}
19 changes: 9 additions & 10 deletions ext/io/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ use deno_core::Op;
use deno_core::OpState;
use deno_core::RcRef;
use deno_core::Resource;
use deno_core::ResourceHandle;
use deno_core::ResourceHandleFd;
use deno_core::TaskQueue;
use fs::FileResource;
use fs::FsError;
Expand Down Expand Up @@ -308,6 +310,7 @@ pub struct StdFileResourceInner {
// Used to keep async actions in order and only allow one
// to occur at a time
cell_async_task_queue: TaskQueue,
handle: ResourceHandleFd,
}

impl StdFileResourceInner {
Expand All @@ -316,8 +319,11 @@ impl StdFileResourceInner {
}

fn new(kind: StdFileResourceKind, fs_file: StdFile) -> Self {
// We know this will be an fd
let handle = ResourceHandle::from_fd_like(&fs_file).as_fd_like().unwrap();
StdFileResourceInner {
kind,
handle,
cell: RefCell::new(Some(fs_file)),
cell_async_task_queue: Default::default(),
}
Expand Down Expand Up @@ -705,6 +711,7 @@ impl crate::fs::File for StdFileResourceInner {
kind: self.kind,
cell: RefCell::new(Some(inner.try_clone()?)),
cell_async_task_queue: Default::default(),
handle: self.handle,
})),
None => Err(FsError::FileBusy),
}
Expand All @@ -720,16 +727,8 @@ impl crate::fs::File for StdFileResourceInner {
}
}

#[cfg(unix)]
fn backing_fd(self: Rc<Self>) -> Option<std::os::unix::prelude::RawFd> {
use std::os::unix::io::AsRawFd;
self.with_sync(|file| Ok(file.as_raw_fd())).ok()
}

#[cfg(windows)]
fn backing_fd(self: Rc<Self>) -> Option<std::os::windows::io::RawHandle> {
use std::os::windows::prelude::AsRawHandle;
self.with_sync(|file| Ok(file.as_raw_handle())).ok()
fn backing_fd(self: Rc<Self>) -> Option<ResourceHandleFd> {
Some(self.handle)
}
}

Expand Down
204 changes: 80 additions & 124 deletions runtime/ops/tty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,9 @@
use std::io::Error;
use std::rc::Rc;

use deno_core::error::resource_unavailable;
use deno_core::error::AnyError;
use deno_core::op;
use deno_core::OpState;
use deno_core::Resource;
use deno_io::fs::FileResource;

#[cfg(unix)]
use deno_core::ResourceId;
Expand Down Expand Up @@ -45,35 +42,6 @@ use winapi::shared::minwindef::DWORD;
#[cfg(windows)]
use winapi::um::wincon;

#[cfg(windows)]
fn get_fd_from_resource(
resource: Rc<FileResource>,
) -> Result<std::os::windows::io::RawHandle, AnyError> {
use winapi::um::handleapi;

#[allow(deprecated)]
let Some(handle) = resource.backing_fd() else {
return Err(resource_unavailable());
};
if handle == handleapi::INVALID_HANDLE_VALUE {
return Err(Error::last_os_error().into());
} else if handle.is_null() {
return Err(custom_error("ReferenceError", "null handle"));
}
Ok(handle)
}

#[cfg(not(windows))]
fn get_fd_from_resource(
resource: Rc<FileResource>,
) -> Result<std::os::unix::prelude::RawFd, AnyError> {
#[allow(deprecated)]
match resource.backing_fd() {
Some(fd) => Ok(fd),
None => Err(resource_unavailable()),
}
}

deno_core::extension!(
deno_tty,
ops = [op_stdin_set_raw, op_isatty, op_console_size],
Expand Down Expand Up @@ -110,6 +78,7 @@ fn op_stdin_set_raw(
cbreak: bool,
) -> Result<(), AnyError> {
let rid = 0; // stdin is always rid=0
let handle_or_fd = state.resource_table.get_fd(rid)?;

// From https://github.com/kkawakam/rustyline/blob/master/src/tty/windows.rs
// and https://github.com/kkawakam/rustyline/blob/master/src/tty/unix.rs
Expand All @@ -121,79 +90,76 @@ fn op_stdin_set_raw(
use winapi::shared::minwindef::FALSE;
use winapi::um::consoleapi;

let handle = handle_or_fd;

if cbreak {
return Err(deno_core::error::not_supported());
}

FileResource::with_resource(state, rid, move |resource| {
let handle = get_fd_from_resource(resource)?;
let mut original_mode: DWORD = 0;
// SAFETY: winapi call
if unsafe { consoleapi::GetConsoleMode(handle, &mut original_mode) }
== FALSE
{
return Err(Error::last_os_error().into());
}
let mut original_mode: DWORD = 0;
// SAFETY: winapi call
if unsafe { consoleapi::GetConsoleMode(handle, &mut original_mode) }
== FALSE
{
return Err(Error::last_os_error().into());
}

let new_mode = if is_raw {
mode_raw_input_on(original_mode)
} else {
mode_raw_input_off(original_mode)
};
let new_mode = if is_raw {
mode_raw_input_on(original_mode)
} else {
mode_raw_input_off(original_mode)
};

// SAFETY: winapi call
if unsafe { consoleapi::SetConsoleMode(handle, new_mode) } == FALSE {
return Err(Error::last_os_error().into());
}
// SAFETY: winapi call
if unsafe { consoleapi::SetConsoleMode(handle, new_mode) } == FALSE {
return Err(Error::last_os_error().into());
}

Ok(())
})
Ok(())
}
#[cfg(unix)]
{
let tty_mode_store = state.borrow::<TtyModeStore>().clone();
let previous_mode = tty_mode_store.get(rid);

FileResource::with_resource(state, rid, move |resource| {
let raw_fd = get_fd_from_resource(resource)?;

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)?;
let raw_fd = handle_or_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(())
}
}

Expand All @@ -203,34 +169,26 @@ fn op_isatty(
rid: u32,
out: &mut [u8],
) -> Result<(), AnyError> {
FileResource::with_resource(state, rid, move |resource| {
let raw_fd = get_fd_from_resource(resource)?;
#[cfg(windows)]
{
use winapi::shared::minwindef::FALSE;
use winapi::um::consoleapi;

let handle = raw_fd;
let mut test_mode: DWORD = 0;
// If I cannot get mode out of console, it is not a console.
// TODO(bartlomieju):
#[allow(clippy::undocumented_unsafe_blocks)]
{
out[0] = unsafe {
consoleapi::GetConsoleMode(handle, &mut test_mode) != FALSE
} as u8;
}
}
#[cfg(unix)]
{
// TODO(bartlomieju):
#[allow(clippy::undocumented_unsafe_blocks)]
{
out[0] = unsafe { libc::isatty(raw_fd as libc::c_int) == 1 } as u8;
}
}
Ok(())
})
let raw_fd = state.resource_table.get_fd(rid)?;
#[cfg(windows)]
{
use winapi::shared::minwindef::FALSE;
use winapi::um::consoleapi;

let handle = raw_fd;
let mut test_mode: DWORD = 0;
// If I cannot get mode out of console, it is not a console.
out[0] =
// SAFETY: Windows API
unsafe { consoleapi::GetConsoleMode(handle, &mut test_mode) != FALSE }
as u8;
}
#[cfg(unix)]
{
// SAFETY: Posix API
out[0] = unsafe { libc::isatty(raw_fd as libc::c_int) == 1 } as u8;
}
Ok(())
}

#[op(fast)]
Expand All @@ -243,13 +201,11 @@ fn op_console_size(
result: &mut [u32],
rid: u32,
) -> Result<(), AnyError> {
FileResource::with_resource(state, rid, move |resource| {
let fd = get_fd_from_resource(resource)?;
let size = console_size_from_fd(fd)?;
result[0] = size.cols;
result[1] = size.rows;
Ok(())
})
let fd = state.resource_table.get_fd(rid)?;
let size = console_size_from_fd(fd)?;
result[0] = size.cols;
result[1] = size.rows;
Ok(())
}

let mut last_result = Ok(());
Expand Down

0 comments on commit 45572e3

Please sign in to comment.