mirror of
https://github.com/denoland/deno.git
synced 2024-12-22 15:24:46 -05:00
fix: permission prompt stuffing on Windows (#11969)
This commit is contained in:
parent
bb7ee4f445
commit
5e2c5d0afa
1 changed files with 89 additions and 9 deletions
|
@ -16,8 +16,6 @@ use log::debug;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
#[cfg(not(test))]
|
|
||||||
use std::io;
|
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use std::sync::atomic::AtomicBool;
|
use std::sync::atomic::AtomicBool;
|
||||||
|
@ -1203,13 +1201,95 @@ fn permission_prompt(message: &str) -> bool {
|
||||||
|
|
||||||
#[cfg(not(unix))]
|
#[cfg(not(unix))]
|
||||||
fn clear_stdin() {
|
fn clear_stdin() {
|
||||||
|
use winapi::shared::minwindef::TRUE;
|
||||||
|
use winapi::shared::minwindef::UINT;
|
||||||
|
use winapi::shared::minwindef::WORD;
|
||||||
|
use winapi::shared::ntdef::WCHAR;
|
||||||
|
use winapi::um::processenv::GetStdHandle;
|
||||||
|
use winapi::um::winbase::STD_INPUT_HANDLE;
|
||||||
|
use winapi::um::wincon::FlushConsoleInputBuffer;
|
||||||
|
use winapi::um::wincon::PeekConsoleInputW;
|
||||||
|
use winapi::um::wincon::WriteConsoleInputW;
|
||||||
|
use winapi::um::wincontypes::INPUT_RECORD;
|
||||||
|
use winapi::um::wincontypes::KEY_EVENT;
|
||||||
|
use winapi::um::winnt::HANDLE;
|
||||||
|
use winapi::um::winuser::MapVirtualKeyW;
|
||||||
|
use winapi::um::winuser::MAPVK_VK_TO_VSC;
|
||||||
|
use winapi::um::winuser::VK_RETURN;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let stdin = winapi::um::processenv::GetStdHandle(
|
let stdin = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
winapi::um::winbase::STD_INPUT_HANDLE,
|
// emulate an enter key press to clear any line buffered console characters
|
||||||
);
|
emulate_enter_key_press(stdin);
|
||||||
let flags =
|
// read the buffered line or enter key press
|
||||||
winapi::um::winbase::PURGE_TXCLEAR | winapi::um::winbase::PURGE_RXCLEAR;
|
read_stdin_line();
|
||||||
winapi::um::commapi::PurgeComm(stdin, flags);
|
// check if our emulated key press was executed
|
||||||
|
if is_input_buffer_empty(stdin) {
|
||||||
|
// if so, move the cursor up to prevent a blank line
|
||||||
|
move_cursor_up();
|
||||||
|
} else {
|
||||||
|
// the emulated key press is still pending, so a buffered line was read
|
||||||
|
// and we can flush the emulated key press
|
||||||
|
flush_input_buffer(stdin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn flush_input_buffer(stdin: HANDLE) {
|
||||||
|
let success = FlushConsoleInputBuffer(stdin);
|
||||||
|
if success != TRUE {
|
||||||
|
panic!(
|
||||||
|
"Error flushing console input buffer: {}",
|
||||||
|
std::io::Error::last_os_error().to_string()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn emulate_enter_key_press(stdin: HANDLE) {
|
||||||
|
// https://github.com/libuv/libuv/blob/a39009a5a9252a566ca0704d02df8dabc4ce328f/src/win/tty.c#L1121-L1131
|
||||||
|
let mut input_record: INPUT_RECORD = std::mem::zeroed();
|
||||||
|
input_record.EventType = KEY_EVENT;
|
||||||
|
input_record.Event.KeyEvent_mut().bKeyDown = TRUE;
|
||||||
|
input_record.Event.KeyEvent_mut().wRepeatCount = 1;
|
||||||
|
input_record.Event.KeyEvent_mut().wVirtualKeyCode = VK_RETURN as WORD;
|
||||||
|
input_record.Event.KeyEvent_mut().wVirtualScanCode =
|
||||||
|
MapVirtualKeyW(VK_RETURN as UINT, MAPVK_VK_TO_VSC) as WORD;
|
||||||
|
*input_record.Event.KeyEvent_mut().uChar.UnicodeChar_mut() =
|
||||||
|
'\r' as WCHAR;
|
||||||
|
|
||||||
|
let mut record_written = 0;
|
||||||
|
let success =
|
||||||
|
WriteConsoleInputW(stdin, &input_record, 1, &mut record_written);
|
||||||
|
if success != TRUE {
|
||||||
|
panic!(
|
||||||
|
"Error emulating enter key press: {}",
|
||||||
|
std::io::Error::last_os_error().to_string()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn is_input_buffer_empty(stdin: HANDLE) -> bool {
|
||||||
|
let mut buffer = Vec::with_capacity(1);
|
||||||
|
let mut events_read = 0;
|
||||||
|
let success =
|
||||||
|
PeekConsoleInputW(stdin, buffer.as_mut_ptr(), 1, &mut events_read);
|
||||||
|
if success != TRUE {
|
||||||
|
panic!(
|
||||||
|
"Error peeking console input buffer: {}",
|
||||||
|
std::io::Error::last_os_error().to_string()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
events_read == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn move_cursor_up() {
|
||||||
|
use std::io::Write;
|
||||||
|
write!(std::io::stderr(), "\x1B[1A").expect("expected to move cursor up");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_stdin_line() {
|
||||||
|
let mut input = String::new();
|
||||||
|
let stdin = std::io::stdin();
|
||||||
|
stdin.read_line(&mut input).expect("expected to read line");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1226,7 +1306,7 @@ fn permission_prompt(message: &str) -> bool {
|
||||||
eprint!("{}", colors::bold(&msg));
|
eprint!("{}", colors::bold(&msg));
|
||||||
loop {
|
loop {
|
||||||
let mut input = String::new();
|
let mut input = String::new();
|
||||||
let stdin = io::stdin();
|
let stdin = std::io::stdin();
|
||||||
let result = stdin.read_line(&mut input);
|
let result = stdin.read_line(&mut input);
|
||||||
if result.is_err() {
|
if result.is_err() {
|
||||||
return false;
|
return false;
|
||||||
|
|
Loading…
Reference in a new issue