Skip to content

Recursive style deletion on Element removal#11

Merged
ian-hon merged 12 commits intomainfrom
ian/element-deletion
Apr 27, 2026
Merged

Recursive style deletion on Element removal#11
ian-hon merged 12 commits intomainfrom
ian/element-deletion

Conversation

@ian-hon
Copy link
Copy Markdown
Contributor

@ian-hon ian-hon commented Apr 15, 2026

Closes #9
Closes #8

@nixonyh nixonyh self-requested a review April 16, 2026 02:14
Copy link
Copy Markdown
Member

@nixonyh nixonyh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some fly by review.

Comment thread crates/fynix/src/style.rs
Comment thread crates/fynix/src/style.rs Outdated
Comment thread crates/fynix/src/style.rs
let Some(parent) = self.styles.get_mut(&parent_id) else {
return;
};

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, I think we could add a

debug_assert!(parent.children.iter().any(|c| c.is_none()));

Just to make sure we're not overriding any existing child ids.

@ian-hon ian-hon force-pushed the ian/element-deletion branch from a0e0c73 to 8e94995 Compare April 22, 2026 11:23
Comment thread crates/fynix/src/element.rs Outdated
Comment thread crates/fynix/src/element.rs Outdated
Comment thread crates/fynix/src/element.rs Outdated
Comment thread crates/fynix/src/element.rs Outdated
Copy link
Copy Markdown
Member

@nixonyh nixonyh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looks good! Thanks for writing the tests 😺 . I have added some comments that can be addressed in a separate PR.

Comment thread crates/fynix/src/ctx.rs
None
};

// restore to old value
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I like comments to begin with capital and ends with fullstop xd (same goes to others too)

Comment thread crates/fynix/src/ctx.rs
/// Creates element `E`, applies the current style chain to it,
/// stores it, and returns its [`ElementId`].
///
/// Elements created with `add` dont own any styles, so their
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: typo

Suggested change
/// Elements created with `add` dont own any styles, so their
/// Elements created with `add` don't own any styles, so their

Comment on lines +186 to +205
if let Some(meta) = metas.remove(id)
&& let Some(type_meta) =
type_metas.get_slot(meta.slot)
{
(type_meta.for_each_child_mut_fn)(
elements,
id,
&mut |child_id, elements| {
remove_recursive(
child_id,
metas,
type_metas,
elements,
id_generator,
);
},
);

elements.dyn_remove_by_slot(meta.slot, id);
id_generator.recycle(*id);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just noting that we might need some debug safe guard to make sure meta points to an actual element. Though, error like these shudn't happen anyway..

Comment thread crates/fynix/src/style.rs
/// Removes a committed style node and recycles its [`StyleId`].
///
/// Returns `true` if the node was present and removed.
pub fn delete(&mut self, id: &StyleId) -> bool {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will need to remove this or make this private, it will disrupt the tree deletion flow.

Comment thread crates/fynix/src/style.rs
}

/// Recursively deletes a style and its children
pub fn delete_tree(&mut self, id: &StyleId) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pub fn delete_tree(&mut self, id: &StyleId) {
pub fn remove(&mut self, id: &StyleId) {

Probably rename this to remove and embed a fn remove_recursive similar to Elements.

Comment thread crates/fynix/src/style.rs
Comment on lines +173 to +176
for c in children {
let Some(c) = c else {
continue;
};
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
for c in children {
let Some(c) = c else {
continue;
};
for c in children.iter().filter_map(|c| c.as_ref()) {

Comment thread crates/fynix/src/style.rs
Comment on lines +247 to +250
/// Treat the style's children as a (sort-of) binary tree.
/// `children[0]` is one depth deeper (inner scope).
/// `children[1]` is same depth, subsequent style node.
children: [Option<StyleId>; 2],
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this data structure was my suggestion, but after reading more, maybe this would be a better fit as they are both different thing after all.

Suggested change
/// Treat the style's children as a (sort-of) binary tree.
/// `children[0]` is one depth deeper (inner scope).
/// `children[1]` is same depth, subsequent style node.
children: [Option<StyleId>; 2],
adjacent_child: Option<StyleId>,
nested_child: Option<StyleId>,

Comment thread crates/fynix/src/ctx.rs
Comment on lines +70 to +106
let pre_commit_id = self.parent_style_id;

let mut element = self.create_element::<E>(true);

let pre_fn_id = self.parent_style_id;

// styleId from create_element
// else, current uncomited style if is None
let first_inner_style_id = self
.parent_style_id
.filter(|id| Some(*id) != pre_commit_id)
.unwrap_or_else(|| self.fynix.styles.current_id());

f(&mut element, self);

// Restore parent style id from before the closure.
self.parent_style_id = parent_style_id;
// If self.parent_style_id has changed, that means a
// style has been committed inside the closure.
// It's ID would be that of `first_inner_style_id`,
// so our primary style is set to that.
let primary_style = if self.parent_style_id != pre_commit_id {
Some(first_inner_style_id)
} else {
None
};

// restore to old value
self.parent_style_id = pre_fn_id;

self.fynix.elements.add(element)
let id = self.fynix.elements.add(element);

if let Some(style_id) = primary_style
&& let Some(meta) = self.fynix.elements.metas.get_mut(&id)
{
meta.primary_style = Some(style_id);
}

id
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: I still think we can do a better job here instead of relying on parent_style_id. Cuz it feels a little fragile (IMO) (?)

@ian-hon ian-hon merged commit 2db1510 into main Apr 27, 2026
7 checks passed
@ian-hon ian-hon deleted the ian/element-deletion branch April 27, 2026 09:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Style cleanup Garbage collection

2 participants