1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-22 07:14:47 -05:00

fix(runtime/windows): ensure Deno.stdin.setRaw(false) properly disables raw mode (#17983)

This commit is contained in:
Roy Ivy III 2023-03-08 13:56:49 -06:00 committed by GitHub
parent 23e1ba7e2d
commit f2e5e01832
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -43,6 +43,26 @@ pub fn init() -> Extension {
.build()
}
// ref: <https://learn.microsoft.com/en-us/windows/console/setconsolemode>
#[cfg(windows)]
const COOKED_MODE: DWORD =
// enable line-by-line input (returns input only after CR is read)
wincon::ENABLE_LINE_INPUT
// enables real-time character echo to console display (requires ENABLE_LINE_INPUT)
| wincon::ENABLE_ECHO_INPUT
// system handles CTRL-C (with ENABLE_LINE_INPUT, also handles BS, CR, and LF) and other control keys (when using `ReadFile` or `ReadConsole`)
| wincon::ENABLE_PROCESSED_INPUT;
#[cfg(windows)]
fn mode_raw_input_on(original_mode: DWORD) -> DWORD {
original_mode & !COOKED_MODE | wincon::ENABLE_VIRTUAL_TERMINAL_INPUT
}
#[cfg(windows)]
fn mode_raw_input_off(original_mode: DWORD) -> DWORD {
original_mode & !wincon::ENABLE_VIRTUAL_TERMINAL_INPUT | COOKED_MODE
}
#[op(fast)]
fn op_stdin_set_raw(
state: &mut OpState,
@ -83,13 +103,10 @@ fn op_stdin_set_raw(
return Err(Error::last_os_error().into());
}
const RAW_MODE_MASK: DWORD = wincon::ENABLE_LINE_INPUT
| wincon::ENABLE_ECHO_INPUT
| wincon::ENABLE_PROCESSED_INPUT;
let new_mode = if is_raw {
original_mode & !RAW_MODE_MASK | wincon::ENABLE_VIRTUAL_TERMINAL_INPUT
mode_raw_input_on(original_mode)
} else {
original_mode | RAW_MODE_MASK & !wincon::ENABLE_VIRTUAL_TERMINAL_INPUT
mode_raw_input_off(original_mode)
};
// SAFETY: winapi call
@ -271,3 +288,31 @@ pub fn console_size(
}
}
}
#[cfg(all(test, windows))]
mod tests {
#[test]
fn test_winos_raw_mode_transitions() {
use crate::ops::tty::mode_raw_input_off;
use crate::ops::tty::mode_raw_input_on;
let known_off_modes =
[0xf7 /* Win10/CMD */, 0x1f7 /* Win10/WinTerm */];
let known_on_modes =
[0x2f0 /* Win10/CMD */, 0x3f0 /* Win10/WinTerm */];
// assert known transitions
assert_eq!(known_on_modes[0], mode_raw_input_on(known_off_modes[0]));
assert_eq!(known_on_modes[1], mode_raw_input_on(known_off_modes[1]));
// assert ON-OFF round-trip is neutral
assert_eq!(
known_off_modes[0],
mode_raw_input_off(mode_raw_input_on(known_off_modes[0]))
);
assert_eq!(
known_off_modes[1],
mode_raw_input_off(mode_raw_input_on(known_off_modes[1]))
);
}
}