diff --git a/Cargo.lock b/Cargo.lock index b9b048468cbc4f52b86b1cd0f1b0a9d3d0f4d9e0..dfd8a74acba5056e468a72d8cd105c0f2cfd156a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6212,7 +6212,6 @@ dependencies = [ name = "feature_flags" version = "0.1.0" dependencies = [ - "futures 0.3.31", "gpui", ] diff --git a/crates/crashes/src/crashes.rs b/crates/crashes/src/crashes.rs index 60af963ee5520addedcfe9abdf41941e77922867..9f18088b0ec2e709ff420b8e107e61dd7424e643 100644 --- a/crates/crashes/src/crashes.rs +++ b/crates/crashes/src/crashes.rs @@ -350,8 +350,34 @@ impl minidumper::ServerHandler for CrashServer { } } +/// Rust's string-slicing panics embed the user's string content in the message, +/// e.g. "byte index 4 is out of bounds of `a`". Strip that suffix so we +/// don't upload arbitrary user text in crash reports. +fn strip_user_string_from_panic(message: &str) -> String { + const STRING_PANIC_PREFIXES: &[&str] = &[ + // Older rustc (pre-1.95): + "byte index ", + "begin <= end (", + // Newer rustc (1.95+): + // https://github.com/rust-lang/rust/pull/145024 + "start byte index ", + "end byte index ", + "begin > end (", + ]; + + if (message.ends_with('`') || message.ends_with("`[...]")) + && STRING_PANIC_PREFIXES + .iter() + .any(|prefix| message.starts_with(prefix)) + && let Some(open) = message.find('`') + { + return format!("{} ``", &message[..open]); + } + message.to_owned() +} + pub fn panic_hook(info: &PanicHookInfo) { - let message = info.payload_as_str().unwrap_or("Box").to_owned(); + let message = strip_user_string_from_panic(info.payload_as_str().unwrap_or("Box")); let span = info .location() diff --git a/crates/feature_flags/Cargo.toml b/crates/feature_flags/Cargo.toml index a25ca1629a539a87a7356f0419ef074e9546bc52..960834211ff18980675b236cd0cc2893d563d668 100644 --- a/crates/feature_flags/Cargo.toml +++ b/crates/feature_flags/Cargo.toml @@ -12,5 +12,4 @@ workspace = true path = "src/feature_flags.rs" [dependencies] -futures.workspace = true gpui.workspace = true diff --git a/crates/feature_flags/src/feature_flags.rs b/crates/feature_flags/src/feature_flags.rs index 1d1929ed4cf89abfc5304fa111dfc7ee523d5dd8..5b8af1180aae812ed1475810acc1920a8ec708f1 100644 --- a/crates/feature_flags/src/feature_flags.rs +++ b/crates/feature_flags/src/feature_flags.rs @@ -3,12 +3,8 @@ mod flags; use std::cell::RefCell; use std::rc::Rc; use std::sync::LazyLock; -use std::time::Duration; -use std::{future::Future, pin::Pin, task::Poll}; -use futures::channel::oneshot; -use futures::{FutureExt, select_biased}; -use gpui::{App, Context, Global, Subscription, Task, Window}; +use gpui::{App, Context, Global, Subscription, Window}; pub use flags::*; @@ -122,11 +118,6 @@ pub struct OnFlagsReady { } pub trait FeatureFlagAppExt { - fn wait_for_flag(&mut self) -> WaitForFlag; - - /// Waits for the specified feature flag to resolve, up to the given timeout. - fn wait_for_flag_or_timeout(&mut self, timeout: Duration) -> Task; - fn update_flags(&mut self, staff: bool, flags: Vec); fn set_staff(&mut self, staff: bool); fn has_flag(&self) -> bool; @@ -192,54 +183,4 @@ impl FeatureFlagAppExt for App { callback(feature_flags.has_flag::(), cx); }) } - - fn wait_for_flag(&mut self) -> WaitForFlag { - let (tx, rx) = oneshot::channel::(); - let mut tx = Some(tx); - let subscription: Option; - - match self.try_global::() { - Some(feature_flags) => { - subscription = None; - tx.take().unwrap().send(feature_flags.has_flag::()).ok(); - } - None => { - subscription = Some(self.observe_global::(move |cx| { - let feature_flags = cx.global::(); - if let Some(tx) = tx.take() { - tx.send(feature_flags.has_flag::()).ok(); - } - })); - } - } - - WaitForFlag(rx, subscription) - } - - fn wait_for_flag_or_timeout(&mut self, timeout: Duration) -> Task { - let wait_for_flag = self.wait_for_flag::(); - - self.spawn(async move |cx| { - let mut wait_for_flag = wait_for_flag.fuse(); - let mut timeout = FutureExt::fuse(cx.background_executor().timer(timeout)); - - select_biased! { - is_enabled = wait_for_flag => is_enabled, - _ = timeout => false, - } - }) - } -} - -pub struct WaitForFlag(oneshot::Receiver, Option); - -impl Future for WaitForFlag { - type Output = bool; - - fn poll(mut self: Pin<&mut Self>, cx: &mut core::task::Context<'_>) -> Poll { - self.0.poll_unpin(cx).map(|result| { - self.1.take(); - result.unwrap_or(false) - }) - } } diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 079a78225c248e341121f1980a368b37f85eea84..6eee25e6faddae5fdaae7ac2704a10a979b30ce7 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -163,21 +163,24 @@ pub fn init(cx: &mut App) { cx.on_action(quit); cx.on_action(|_: &RestoreBanner, cx| title_bar::restore_banner(cx)); - let flag = cx.wait_for_flag::(); - cx.spawn(async |cx| { - if cx.update(|cx| ReleaseChannel::global(cx) == ReleaseChannel::Dev) || flag.await { - cx.update(|cx| { - cx.on_action(|_: &TestPanic, _| panic!("Ran the TestPanic action")) - .on_action(|_: &TestCrash, _| { - unsafe extern "C" { - fn puts(s: *const i8); - } - unsafe { - puts(0xabad1d3a as *const i8); - } - }); - }); - }; + + cx.observe_flag::({ + let mut added = false; + move |enabled, cx| { + if added || !enabled { + return; + } + added = true; + cx.on_action(|_: &TestPanic, _| panic!("Ran the TestPanic action")) + .on_action(|_: &TestCrash, _| { + unsafe extern "C" { + fn puts(s: *const i8); + } + unsafe { + puts(0xabad1d3a as *const i8); + } + }); + } }) .detach(); cx.on_action(|_: &OpenLog, cx| {