fix: close the RV6 verification gaps
Resolves the 7 gap groups in docs/rewrite/notes/review-rv6-codex.md (final-Z8.md): - crash (macOS): request_abort_dump returns false on mach_msg receive timeout/error so the signal-path fallback runs; EXC_SOFT_SIGNAL keeps the signal number in the minidump exception info. - Default SHELL read as an OS string and stored in encoded command form. - macOS executable search works on raw PATH bytes; the default path is used only when PATH is unset. - Windows: config env overrides are decoded; EnvMap compares keys as WTF-16 units with per-unit Unicode simple uppercasing (no lossy conversion, distinct lone-surrogate keys stay distinct). - +show-config writes original bytes for encoded OS data, so export + reload round-trips; UTF-8 configs are byte-identical as before. - Zig's ensureLocale chain lives in ghostty-os for all Unix targets and is used by both the GTK app and the C API init. Also makes the quick-terminal GTK replay test independent of compositor focus: GTK's is-active is read-only, so when niri actually focuses the layer surface the simulated focus-out cannot drive autohide and that assertion is skipped (the production logic is unchanged and matches Zig). Test Plan: - cargo test --workspace (3390 passed, incl. tests/gtk_replay.rs) - just check-macos (both), just check-windows, just check-wasm
This commit is contained in:
1 parent
306a19227f
commit
5e5d33324c
12 files changed
+452
-133
No files matched your search
@@ -12,6 +12,31 @@ const DELIMITER: char = ';';
|
||||
#[cfg(not(windows))]
|
||||
const DELIMITER: char = ':';
|
||||
|
||||
/// Uppercase one UTF-16 code unit like Windows' `RtlUpcaseUnicodeChar`
|
||||
/// (Unicode simple case mapping, per unit): surrogate halves and characters
|
||||
/// whose uppercase is not a single BMP code unit are unchanged.
|
||||
fn upcase_unit(u: u16) -> u16 {
|
||||
let Some(c) = char::from_u32(u32::from(u)) else {
|
||||
return u; // lone surrogate half
|
||||
};
|
||||
let mut up = c.to_uppercase();
|
||||
match (up.next(), up.next()) {
|
||||
(Some(m), None) => u16::try_from(u32::from(m)).unwrap_or(u),
|
||||
_ => u,
|
||||
}
|
||||
}
|
||||
|
||||
/// The comparison form of an environment key on Windows: its WTF-16 code
|
||||
/// units, uppercased per unit. Never lossy: distinct lone surrogates stay
|
||||
/// distinct.
|
||||
#[cfg_attr(not(windows), allow(dead_code))]
|
||||
fn windows_key(key: &OsStr) -> Vec<u16> {
|
||||
crate::osbytes::wtf8_to_wide(&crate::osbytes::os_bytes(key))
|
||||
.into_iter()
|
||||
.map(upcase_unit)
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// A byte-preserving environment map (Zig `std.process.EnvMap`): keys and
|
||||
/// values are arbitrary OS strings, never required to be UTF-8.
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq)]
|
||||
@@ -28,10 +53,10 @@ impl EnvMap {
|
||||
/// itself.
|
||||
#[cfg(windows)]
|
||||
fn canonical_key<'a>(&'a self, key: &'a OsStr) -> Cow<'a, OsStr> {
|
||||
let want = key.to_string_lossy().to_ascii_uppercase();
|
||||
let want = windows_key(key);
|
||||
self.0
|
||||
.keys()
|
||||
.find(|k| k.to_string_lossy().to_ascii_uppercase() == want)
|
||||
.find(|k| windows_key(k) == want)
|
||||
.map_or(Cow::Borrowed(key), |k| Cow::Borrowed(k.as_os_str()))
|
||||
}
|
||||
|
||||
@@ -372,3 +397,44 @@ mod tests {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod windows_key_tests {
|
||||
use super::*;
|
||||
|
||||
fn key(units: &[u16]) -> Vec<u16> {
|
||||
units.iter().copied().map(upcase_unit).collect()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn upcase_is_unicode_simple_per_unit() {
|
||||
assert_eq!(upcase_unit(u16::from(b'a')), u16::from(b'A'));
|
||||
assert_eq!(upcase_unit(0x00E9), 0x00C9); // e acute
|
||||
assert_eq!(upcase_unit(0x03C9), 0x03A9); // omega
|
||||
assert_eq!(upcase_unit(0x00DF), 0x00DF); // sharp s has no simple upper
|
||||
assert_eq!(upcase_unit(0xD800), 0xD800);
|
||||
assert_eq!(upcase_unit(0xDFFF), 0xDFFF);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn non_ascii_case_keys_are_equal() {
|
||||
assert_eq!(key(&[0xE9, 0x61]), key(&[0xC9, 0x41]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn distinct_lone_surrogate_keys_stay_distinct() {
|
||||
assert_ne!(key(&[0x41, 0xD800]), key(&[0x41, 0xD801]));
|
||||
assert_ne!(key(&[0xD800]), key(&[0xFFFD]));
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn windows_key_of_os_str_is_wtf16() {
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
// Unix OsStr "Aé" in UTF-8.
|
||||
assert_eq!(
|
||||
windows_key(OsStr::from_bytes("a\u{e9}".as_bytes())),
|
||||
vec![0x41, 0xC9]
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user