gpui: Introduce stacker to address stack overflows with deep layout trees (#35813)
Co-authored-by: Anthony Eid <hello@anthonyeid.me> Co-authored-by: Lukas Wirth <lukas@zed.dev> Co-authored-by: Ben Kunkle <ben@zed.dev> Release Notes: - N/A Co-authored-by: Anthony Eid <hello@anthonyeid.me> Co-authored-by: Lukas Wirth <lukas@zed.dev> Co-authored-by: Ben Kunkle <ben@zed.dev>
This commit is contained in:
parent
1fbb318714
commit
ed14ab8c02
5 changed files with 56 additions and 5 deletions
|
@ -119,6 +119,7 @@ serde_json.workspace = true
|
|||
slotmap = "1.0.6"
|
||||
smallvec.workspace = true
|
||||
smol.workspace = true
|
||||
stacksafe.workspace = true
|
||||
strum.workspace = true
|
||||
sum_tree.workspace = true
|
||||
taffy = "=0.9.0"
|
||||
|
|
|
@ -27,6 +27,7 @@ use crate::{
|
|||
use collections::HashMap;
|
||||
use refineable::Refineable;
|
||||
use smallvec::SmallVec;
|
||||
use stacksafe::{StackSafe, stacksafe};
|
||||
use std::{
|
||||
any::{Any, TypeId},
|
||||
cell::RefCell,
|
||||
|
@ -1195,7 +1196,7 @@ pub fn div() -> Div {
|
|||
/// A [`Div`] element, the all-in-one element for building complex UIs in GPUI
|
||||
pub struct Div {
|
||||
interactivity: Interactivity,
|
||||
children: SmallVec<[AnyElement; 2]>,
|
||||
children: SmallVec<[StackSafe<AnyElement>; 2]>,
|
||||
prepaint_listener: Option<Box<dyn Fn(Vec<Bounds<Pixels>>, &mut Window, &mut App) + 'static>>,
|
||||
image_cache: Option<Box<dyn ImageCacheProvider>>,
|
||||
}
|
||||
|
@ -1256,7 +1257,8 @@ impl InteractiveElement for Div {
|
|||
|
||||
impl ParentElement for Div {
|
||||
fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
|
||||
self.children.extend(elements)
|
||||
self.children
|
||||
.extend(elements.into_iter().map(StackSafe::new))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1272,6 +1274,7 @@ impl Element for Div {
|
|||
self.interactivity.source_location()
|
||||
}
|
||||
|
||||
#[stacksafe]
|
||||
fn request_layout(
|
||||
&mut self,
|
||||
global_id: Option<&GlobalElementId>,
|
||||
|
@ -1307,6 +1310,7 @@ impl Element for Div {
|
|||
(layout_id, DivFrameState { child_layout_ids })
|
||||
}
|
||||
|
||||
#[stacksafe]
|
||||
fn prepaint(
|
||||
&mut self,
|
||||
global_id: Option<&GlobalElementId>,
|
||||
|
@ -1376,6 +1380,7 @@ impl Element for Div {
|
|||
)
|
||||
}
|
||||
|
||||
#[stacksafe]
|
||||
fn paint(
|
||||
&mut self,
|
||||
global_id: Option<&GlobalElementId>,
|
||||
|
|
|
@ -3,6 +3,7 @@ use crate::{
|
|||
};
|
||||
use collections::{FxHashMap, FxHashSet};
|
||||
use smallvec::SmallVec;
|
||||
use stacksafe::{StackSafe, stacksafe};
|
||||
use std::{fmt::Debug, ops::Range};
|
||||
use taffy::{
|
||||
TaffyTree, TraversePartialTree as _,
|
||||
|
@ -11,8 +12,15 @@ use taffy::{
|
|||
tree::NodeId,
|
||||
};
|
||||
|
||||
type NodeMeasureFn = Box<
|
||||
dyn FnMut(Size<Option<Pixels>>, Size<AvailableSpace>, &mut Window, &mut App) -> Size<Pixels>,
|
||||
type NodeMeasureFn = StackSafe<
|
||||
Box<
|
||||
dyn FnMut(
|
||||
Size<Option<Pixels>>,
|
||||
Size<AvailableSpace>,
|
||||
&mut Window,
|
||||
&mut App,
|
||||
) -> Size<Pixels>,
|
||||
>,
|
||||
>;
|
||||
|
||||
struct NodeContext {
|
||||
|
@ -88,7 +96,7 @@ impl TaffyLayoutEngine {
|
|||
.new_leaf_with_context(
|
||||
taffy_style,
|
||||
NodeContext {
|
||||
measure: Box::new(measure),
|
||||
measure: StackSafe::new(Box::new(measure)),
|
||||
},
|
||||
)
|
||||
.expect(EXPECT_MESSAGE)
|
||||
|
@ -143,6 +151,7 @@ impl TaffyLayoutEngine {
|
|||
Ok(edges)
|
||||
}
|
||||
|
||||
#[stacksafe]
|
||||
pub fn compute_layout(
|
||||
&mut self,
|
||||
id: LayoutId,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue