diff --git a/Cargo.lock b/Cargo.lock index b29c151..b7ba63d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1403,7 +1403,7 @@ dependencies = [ [[package]] name = "collections" version = "0.1.0" -source = "git+https://github.com/Kuddev/zed?rev=7c662384cd77c1d1e1566206920e3a420ea6767b#7c662384cd77c1d1e1566206920e3a420ea6767b" +source = "git+https://github.com/Kuddev/zed?rev=fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4#fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4" dependencies = [ "gpui_util", "indexmap", @@ -2013,7 +2013,7 @@ dependencies = [ [[package]] name = "derive_refineable" version = "0.1.0" -source = "git+https://github.com/Kuddev/zed?rev=7c662384cd77c1d1e1566206920e3a420ea6767b#7c662384cd77c1d1e1566206920e3a420ea6767b" +source = "git+https://github.com/Kuddev/zed?rev=fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4#fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4" dependencies = [ "proc-macro2", "quote", @@ -3105,7 +3105,7 @@ dependencies = [ [[package]] name = "gpui" version = "0.2.2" -source = "git+https://github.com/Kuddev/zed?rev=7c662384cd77c1d1e1566206920e3a420ea6767b#7c662384cd77c1d1e1566206920e3a420ea6767b" +source = "git+https://github.com/Kuddev/zed?rev=fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4#fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4" dependencies = [ "accesskit", "anyhow", @@ -3191,7 +3191,7 @@ dependencies = [ [[package]] name = "gpui-component" version = "0.5.2" -source = "git+https://github.com/Kuddev/gpui-component?rev=f46ecbb06de5907af9700f3f6e2b5b0845459188#f46ecbb06de5907af9700f3f6e2b5b0845459188" +source = "git+https://github.com/Kuddev/gpui-component?rev=fc5f5cf63dd80686dafacd2a6e37345bbd1dc7ba#fc5f5cf63dd80686dafacd2a6e37345bbd1dc7ba" dependencies = [ "aho-corasick", "anyhow", @@ -3274,7 +3274,7 @@ dependencies = [ [[package]] name = "gpui-component-assets" version = "0.5.1" -source = "git+https://github.com/Kuddev/gpui-component?rev=f46ecbb06de5907af9700f3f6e2b5b0845459188#f46ecbb06de5907af9700f3f6e2b5b0845459188" +source = "git+https://github.com/Kuddev/gpui-component?rev=fc5f5cf63dd80686dafacd2a6e37345bbd1dc7ba#fc5f5cf63dd80686dafacd2a6e37345bbd1dc7ba" dependencies = [ "anyhow", "gpui", @@ -3288,7 +3288,7 @@ dependencies = [ [[package]] name = "gpui-component-macros" version = "0.5.1" -source = "git+https://github.com/Kuddev/gpui-component?rev=f46ecbb06de5907af9700f3f6e2b5b0845459188#f46ecbb06de5907af9700f3f6e2b5b0845459188" +source = "git+https://github.com/Kuddev/gpui-component?rev=fc5f5cf63dd80686dafacd2a6e37345bbd1dc7ba#fc5f5cf63dd80686dafacd2a6e37345bbd1dc7ba" dependencies = [ "proc-macro2", "quote", @@ -3298,7 +3298,7 @@ dependencies = [ [[package]] name = "gpui_linux" version = "0.1.0" -source = "git+https://github.com/Kuddev/zed?rev=7c662384cd77c1d1e1566206920e3a420ea6767b#7c662384cd77c1d1e1566206920e3a420ea6767b" +source = "git+https://github.com/Kuddev/zed?rev=fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4#fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4" dependencies = [ "accesskit", "accesskit_unix", @@ -3350,7 +3350,7 @@ dependencies = [ [[package]] name = "gpui_macos" version = "0.1.0" -source = "git+https://github.com/Kuddev/zed?rev=7c662384cd77c1d1e1566206920e3a420ea6767b#7c662384cd77c1d1e1566206920e3a420ea6767b" +source = "git+https://github.com/Kuddev/zed?rev=fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4#fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4" dependencies = [ "accesskit", "accesskit_macos", @@ -3399,7 +3399,7 @@ dependencies = [ [[package]] name = "gpui_macros" version = "0.1.0" -source = "git+https://github.com/Kuddev/zed?rev=7c662384cd77c1d1e1566206920e3a420ea6767b#7c662384cd77c1d1e1566206920e3a420ea6767b" +source = "git+https://github.com/Kuddev/zed?rev=fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4#fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -3410,7 +3410,7 @@ dependencies = [ [[package]] name = "gpui_platform" version = "0.1.0" -source = "git+https://github.com/Kuddev/zed?rev=7c662384cd77c1d1e1566206920e3a420ea6767b#7c662384cd77c1d1e1566206920e3a420ea6767b" +source = "git+https://github.com/Kuddev/zed?rev=fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4#fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4" dependencies = [ "console_error_panic_hook", "gpui", @@ -3423,7 +3423,7 @@ dependencies = [ [[package]] name = "gpui_shared_string" version = "0.1.0" -source = "git+https://github.com/Kuddev/zed?rev=7c662384cd77c1d1e1566206920e3a420ea6767b#7c662384cd77c1d1e1566206920e3a420ea6767b" +source = "git+https://github.com/Kuddev/zed?rev=fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4#fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4" dependencies = [ "schemars", "serde", @@ -3433,7 +3433,7 @@ dependencies = [ [[package]] name = "gpui_util" version = "0.1.0" -source = "git+https://github.com/Kuddev/zed?rev=7c662384cd77c1d1e1566206920e3a420ea6767b#7c662384cd77c1d1e1566206920e3a420ea6767b" +source = "git+https://github.com/Kuddev/zed?rev=fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4#fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4" dependencies = [ "anyhow", "log", @@ -3443,7 +3443,7 @@ dependencies = [ [[package]] name = "gpui_web" version = "0.1.0" -source = "git+https://github.com/Kuddev/zed?rev=7c662384cd77c1d1e1566206920e3a420ea6767b#7c662384cd77c1d1e1566206920e3a420ea6767b" +source = "git+https://github.com/Kuddev/zed?rev=fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4#fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4" dependencies = [ "anyhow", "console_error_panic_hook", @@ -3466,7 +3466,7 @@ dependencies = [ [[package]] name = "gpui_wgpu" version = "0.1.0" -source = "git+https://github.com/Kuddev/zed?rev=7c662384cd77c1d1e1566206920e3a420ea6767b#7c662384cd77c1d1e1566206920e3a420ea6767b" +source = "git+https://github.com/Kuddev/zed?rev=fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4#fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4" dependencies = [ "anyhow", "bytemuck", @@ -3496,7 +3496,7 @@ dependencies = [ [[package]] name = "gpui_windows" version = "0.1.0" -source = "git+https://github.com/Kuddev/zed?rev=7c662384cd77c1d1e1566206920e3a420ea6767b#7c662384cd77c1d1e1566206920e3a420ea6767b" +source = "git+https://github.com/Kuddev/zed?rev=fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4#fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4" dependencies = [ "accesskit", "accesskit_windows", @@ -3792,7 +3792,7 @@ dependencies = [ [[package]] name = "http_client" version = "0.1.0" -source = "git+https://github.com/Kuddev/zed?rev=7c662384cd77c1d1e1566206920e3a420ea6767b#7c662384cd77c1d1e1566206920e3a420ea6767b" +source = "git+https://github.com/Kuddev/zed?rev=fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4#fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4" dependencies = [ "anyhow", "async-compression", @@ -4754,7 +4754,7 @@ checksum = "7ebb8d8732c6a6df3d8f032a82911cfc747e00efb95cc46e8d0acd5b5b88570c" [[package]] name = "media" version = "0.1.0" -source = "git+https://github.com/Kuddev/zed?rev=7c662384cd77c1d1e1566206920e3a420ea6767b#7c662384cd77c1d1e1566206920e3a420ea6767b" +source = "git+https://github.com/Kuddev/zed?rev=fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4#fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4" dependencies = [ "anyhow", "bindgen", @@ -6175,7 +6175,7 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "perf" version = "0.1.0" -source = "git+https://github.com/Kuddev/zed?rev=7c662384cd77c1d1e1566206920e3a420ea6767b#7c662384cd77c1d1e1566206920e3a420ea6767b" +source = "git+https://github.com/Kuddev/zed?rev=fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4#fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4" dependencies = [ "collections", "serde", @@ -7074,7 +7074,7 @@ dependencies = [ [[package]] name = "refineable" version = "0.1.0" -source = "git+https://github.com/Kuddev/zed?rev=7c662384cd77c1d1e1566206920e3a420ea6767b#7c662384cd77c1d1e1566206920e3a420ea6767b" +source = "git+https://github.com/Kuddev/zed?rev=fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4#fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4" dependencies = [ "derive_refineable", ] @@ -7669,7 +7669,7 @@ dependencies = [ [[package]] name = "scheduler" version = "0.1.0" -source = "git+https://github.com/Kuddev/zed?rev=7c662384cd77c1d1e1566206920e3a420ea6767b#7c662384cd77c1d1e1566206920e3a420ea6767b" +source = "git+https://github.com/Kuddev/zed?rev=fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4#fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4" dependencies = [ "async-task", "backtrace", @@ -8512,7 +8512,7 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "sum_tree" version = "0.1.0" -source = "git+https://github.com/Kuddev/zed?rev=7c662384cd77c1d1e1566206920e3a420ea6767b#7c662384cd77c1d1e1566206920e3a420ea6767b" +source = "git+https://github.com/Kuddev/zed?rev=fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4#fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4" dependencies = [ "heapless", "log", @@ -9838,7 +9838,7 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "util_macros" version = "0.1.0" -source = "git+https://github.com/Kuddev/zed?rev=7c662384cd77c1d1e1566206920e3a420ea6767b#7c662384cd77c1d1e1566206920e3a420ea6767b" +source = "git+https://github.com/Kuddev/zed?rev=fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4#fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4" dependencies = [ "perf", "quote", @@ -11702,7 +11702,7 @@ dependencies = [ [[package]] name = "zlog" version = "0.1.0" -source = "git+https://github.com/Kuddev/zed?rev=7c662384cd77c1d1e1566206920e3a420ea6767b#7c662384cd77c1d1e1566206920e3a420ea6767b" +source = "git+https://github.com/Kuddev/zed?rev=fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4#fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4" dependencies = [ "anyhow", "chrono", @@ -11719,7 +11719,7 @@ checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" [[package]] name = "ztracing" version = "0.1.0" -source = "git+https://github.com/Kuddev/zed?rev=7c662384cd77c1d1e1566206920e3a420ea6767b#7c662384cd77c1d1e1566206920e3a420ea6767b" +source = "git+https://github.com/Kuddev/zed?rev=fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4#fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4" dependencies = [ "tracing", "tracing-subscriber", @@ -11730,7 +11730,7 @@ dependencies = [ [[package]] name = "ztracing_macro" version = "0.1.0" -source = "git+https://github.com/Kuddev/zed?rev=7c662384cd77c1d1e1566206920e3a420ea6767b#7c662384cd77c1d1e1566206920e3a420ea6767b" +source = "git+https://github.com/Kuddev/zed?rev=fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4#fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4" [[package]] name = "zune-core" diff --git a/Cargo.toml b/Cargo.toml index 51a904a..85cbe90 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -70,7 +70,7 @@ toml_edit = "0.24.0" # GPUI v1.16.1 把平台启动入口拆到独立 crate。它必须与 `gpui` 使用完全相同 # 的 Git URL 和 rev,否则 Cargo 会把同名类型解析成两套互不兼容的 crate。 # Without font-kit, the macOS platform uses NoopTextSystem and renders no text. -gpui_platform = { git = "https://github.com/Kuddev/zed", rev = "7c662384cd77c1d1e1566206920e3a420ea6767b", version = "=0.1.0", features = ["font-kit"] } +gpui_platform = { git = "https://github.com/Kuddev/zed", rev = "fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4", version = "=0.1.0", features = ["font-kit"] } # TODO: Drop this pin and return to the crates.io release once the fix ships there. [patch.crates-io] @@ -182,10 +182,13 @@ winit = { path = "third_party/winit-0.30.13" } # tests/root_test_window.rs 验证以依赖方式编译的 Root 可使用虚拟窗口; # 上游提供等价的下游 headless 测试支持后撤销本补丁。 # -# 当前精确引用包含补丁 1-3、6 及字体内存修补;Input 补丁 4-5 仍保持独立。 -gpui = { git = "https://github.com/Kuddev/zed", rev = "7c662384cd77c1d1e1566206920e3a420ea6767b", version = "=0.2.2" } +# 当前精确引用包含补丁 1-3、6、字体内存修补及 Windows 彩色 emoji 枚举修复。 +# DirectWrite 必须先 MoveNext 再 GetCurrentRun,否则回退为黑色字形(issue #317)。 +# 修复来源:WilliamWang1721/zed codex/issue-317-color-emoji;维护分支吸收后改回其固定点。 +# Input 补丁 4-5 仍保持独立。 +gpui = { git = "https://github.com/Kuddev/zed", rev = "fc05d637cc7029d75de051fd7f52c1a0fb8fa6b4", version = "=0.2.2" } # Native inputs share rendered text's device-pixel line height and expose a # post-paint point lookup. Window selection ends on release even when a child # consumes MouseUp or the platform reports the next move without a held button. -gpui-component = { git = "https://github.com/Kuddev/gpui-component", rev = "f46ecbb06de5907af9700f3f6e2b5b0845459188", version = "=0.5.2" } -gpui-component-assets = { git = "https://github.com/Kuddev/gpui-component", rev = "f46ecbb06de5907af9700f3f6e2b5b0845459188", version = "=0.5.1" } +gpui-component = { git = "https://github.com/Kuddev/gpui-component", rev = "fc5f5cf63dd80686dafacd2a6e37345bbd1dc7ba", version = "=0.5.2" } +gpui-component-assets = { git = "https://github.com/Kuddev/gpui-component", rev = "fc5f5cf63dd80686dafacd2a6e37345bbd1dc7ba", version = "=0.5.1" } diff --git a/nebula_gpui/ARCHITECTURE.md b/nebula_gpui/ARCHITECTURE.md index a65d472..b730d68 100644 --- a/nebula_gpui/ARCHITECTURE.md +++ b/nebula_gpui/ARCHITECTURE.md @@ -68,8 +68,11 @@ application boundary. ## Dependency Policy -The v1.16.1 migration baseline is pinned by both package version and immutable -Git revision: +The v1.16.1 migration baseline was pinned by both package version and immutable +Git revision. The revisions below record that historical migration, not the +active dependency pins. Current revisions and patch rationale are maintained +in the root [`Cargo.toml`](../Cargo.toml), with resolution in +[`Cargo.lock`](../Cargo.lock): ```toml gpui = "=0.2.2" diff --git a/nebula_hook/tests/lifetime.rs b/nebula_hook/tests/lifetime.rs index 925f9ae..a4725c8 100644 --- a/nebula_hook/tests/lifetime.rs +++ b/nebula_hook/tests/lifetime.rs @@ -90,9 +90,11 @@ fn legacy_notify_still_invokes_the_users_chained_program() { ); } +/// A server-side named pipe in the exact state the live transport can leave +/// behind during shutdown: created, never accepted and never drained. The +/// default harness runs tests in one process, so every name must be unique. #[cfg(windows)] -#[test] -fn a_receiver_that_never_reads_cannot_pin_the_helper() { +mod stalled_receiver { use std::ffi::c_void; #[link(name = "kernel32")] @@ -110,28 +112,50 @@ fn a_receiver_that_never_reads_cannot_pin_the_helper() { fn CloseHandle(handle: *mut c_void) -> i32; fn GetNamedPipeClientProcessId(handle: *mut c_void, pid: *mut u32) -> i32; } - struct Pipe(*mut c_void); - impl Drop for Pipe { + + pub struct Receiver(*mut c_void); + + impl Receiver { + /// mode 1 = PIPE_ACCESS_INBOUND, one instance: mirrors the live + /// transport's one-client-at-a-time shape. + pub fn create(discriminator: &str) -> (Self, String) { + let name = format!(r"\\.\pipe\pebrel-hook-lifetime-test-{discriminator}"); + let wide: Vec = name.encode_utf16().chain(Some(0)).collect(); + let handle = unsafe { + CreateNamedPipeW(wide.as_ptr(), 1, 0, 1, 4096, 4096, 0, std::ptr::null()) + }; + assert_ne!(handle as isize, -1, "{}", std::io::Error::last_os_error()); + (Self(handle), name) + } + + /// Kernel answer to "did this process connect?" — the same identity + /// probe the live transport issues for every accepted client. + pub fn connected_client(&self) -> Option { + let mut pid = 0; + let ok = unsafe { GetNamedPipeClientProcessId(self.0, &mut pid) }; + (ok != 0 && pid != 0).then_some(pid) + } + } + + impl Drop for Receiver { fn drop(&mut self) { unsafe { CloseHandle(self.0); } } } - let name = format!(r"\\.\pipe\pebrel-hook-lifetime-test-{}", std::process::id()); - let wide: Vec = name.encode_utf16().chain(Some(0)).collect(); - // The server owns an inbound byte pipe and deliberately never drains it. - let handle = - unsafe { CreateNamedPipeW(wide.as_ptr(), 1, 0, 1, 4096, 4096, 0, std::ptr::null()) }; - assert_ne!(handle as isize, -1, "{}", std::io::Error::last_os_error()); - let _pipe = Pipe(handle); +} + +#[cfg(windows)] +#[test] +fn a_receiver_that_never_reads_cannot_pin_the_helper() { + let (receiver, name) = stalled_receiver::Receiver::create("codex-argv"); let payload = "x".repeat(16 * 1024); let invocation = Invocation::spawn(&["codex", &payload], Some(&name)); let deadline = Instant::now() + Duration::from_secs(6); loop { - let mut pid = 0; - if unsafe { GetNamedPipeClientProcessId(handle, &mut pid) } != 0 { - assert_eq!(pid, invocation.0.as_ref().unwrap().id()); + if receiver.connected_client().is_some_and(|pid| pid == invocation.0.as_ref().unwrap().id()) + { break; } assert!(Instant::now() < deadline, "helper never connected to the blocked receiver"); @@ -140,3 +164,44 @@ fn a_receiver_that_never_reads_cannot_pin_the_helper() { let output = invocation.finish(); assert!(output.stdout.is_empty() && output.stderr.is_empty()); } + +/// Issue #259: Pi's extension launches `pebrel-hook pi ` as a +/// detached Windows process and never reaps it, so a prompt burst can +/// outlive its host. The padded context field exceeds the receiver's buffer, +/// pinning the first connect mid-write — the stalled-write condition the +/// forwarding deadline exists for. +#[cfg(windows)] +#[test] +fn concurrent_pi_prompt_notifications_exit_against_a_wedged_receiver() { + let (receiver, name) = stalled_receiver::Receiver::create("pi-burst"); + let prompt = |session: u32| { + format!( + r#"{{"kind":"prompt","session_id":"s-{session}","bridge_instance":"5c1e","bridge_sequence":"{session}","event_id":"5c1e:{session}","cwd":"C:\\Users\\dev\\project","context":"{}"}}"#, + "x".repeat(16 * 1024), + ) + }; + let pending: Vec<_> = + (1..=5).map(|session| Invocation::spawn(&["pi", &prompt(session)], Some(&name))).collect(); + // The wedged receiver pins whichever helper connects first mid-write, so + // that connection stays observable until the deadline retires the helper. + let deadline = Instant::now() + Duration::from_secs(6); + loop { + if receiver.connected_client().is_some() { + break; + } + assert!(Instant::now() < deadline, "no pi prompt helper connected to the wedged receiver"); + std::thread::sleep(Duration::from_millis(10)); + } + for invocation in pending { + let output = invocation.finish(); + assert!(output.stdout.is_empty() && output.stderr.is_empty()); + } +} + +#[test] +fn pi_prompt_notification_exits_cleanly_without_a_host() { + let invocation = + Invocation::spawn(&["pi", r#"{"kind":"prompt","session_id":"s1","cwd":"/tmp"}"#], None); + let output = invocation.finish(); + assert!(output.stdout.is_empty() && output.stderr.is_empty()); +}