This is an automated email from the git hooks/post-receive script.
git pushed a commit to branch edje-vector-intergration
in repository efl.
View the commit online.
commit 4452af9a5add3b56e70327d00ef2a2c2bd64c2dd
Author: [email protected] <[email protected]>
AuthorDate: Sat May 2 19:29:18 2026 -0600
edje_cc: simplify vector-tree wrapper ownership with EINA_LIST_FREE
The vector-tree serializer in data_write_vectors_trees() was
shallow-copying each tree struct into the flat directory array, then
nullifying src->root and leaving the wrapper allocations for
_edje_cc_vg_cleanup() to reclaim later. This split the ownership story
across two files and made the data flow harder to follow.
Introduce _edje_cc_vg_all_trees_steal() to make ownership transfer
explicit at the API boundary: serialize takes ownership, consumes all
trees in one pass with EINA_LIST_FREE, and frees each wrapper immediately
after copying. Cleanup correctly handles the post-steal NULL list by
falling back to a destructive walk only on early-abort paths (VEC001
duplicate-name, VEC003 parent-cycle, VEC004 missing-root, VEC014
transform-form conflict) where serialize never ran.
No behavioural change for valid input. On abort paths, cleanup still
reclaims live trees correctly. The refactoring makes the contract
explicit: _get() borrows; _steal() transfers.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
---
src/bin/edje/edje_cc.h | 1 +
src/bin/edje/edje_cc_handlers.c | 45 ++++++++++++++++++++++-------------------
src/bin/edje/edje_cc_out.c | 18 +++++++++--------
3 files changed, 35 insertions(+), 29 deletions(-)
diff --git a/src/bin/edje/edje_cc.h b/src/bin/edje/edje_cc.h
index 18541c9479..d074c8b9ed 100644
--- a/src/bin/edje/edje_cc.h
+++ b/src/bin/edje/edje_cc.h
@@ -325,6 +325,7 @@ void convert_color_code(char *str, int *r, int *g, int *b, int *a);
/* Vector-tree parser accessors */
Eina_List *_edje_cc_vg_all_trees_get(void);
+Eina_List *_edje_cc_vg_all_trees_steal(void);
Eina_Hash *_edje_cc_vg_desc_to_tree_get(void);
void _edje_cc_vg_cleanup(void);
diff --git a/src/bin/edje/edje_cc_handlers.c b/src/bin/edje/edje_cc_handlers.c
index 18329778de..57e3d57738 100644
--- a/src/bin/edje/edje_cc_handlers.c
+++ b/src/bin/edje/edje_cc_handlers.c
@@ -258,6 +258,17 @@ _edje_cc_vg_all_trees_get(void)
return all_vg_trees;
}
+/* Transfer ownership of the trees list to the caller; `all_vg_trees` is
+ * cleared so cleanup will not walk freed memory. Used by the serializer
+ * once it has consumed the trees into the flat directory array. */
+Eina_List *
+_edje_cc_vg_all_trees_steal(void)
+{
+ Eina_List *l = all_vg_trees;
+ all_vg_trees = NULL;
+ return l;
+}
+
Eina_Hash *
_edje_cc_vg_desc_to_tree_get(void)
{
@@ -267,27 +278,19 @@ _edje_cc_vg_desc_to_tree_get(void)
void
_edje_cc_vg_cleanup(void)
{
- /* Trees themselves: data_write_vectors_trees() has shallow-copied each
- Edje_Vg_Tree struct into the flat array and nullified src->root. We
- still own the list-wrapper heap allocations (the Edje_Vg_Tree* pointers
- in all_vg_trees themselves); free them here. _edje_vg_tree_free_fields
- is a no-op when root==NULL so it is safe to call. */
- if (all_vg_trees)
- {
- Eina_List *l;
- Edje_Vg_Tree *t;
- EINA_LIST_FOREACH(all_vg_trees, l, t)
- {
- /* root was nullified by shallow-copy in the normal path.
- On early abort (e.g. VEC001 duplicate-name error), the
- shallow-copy never ran and root is still live — so always
- call _edje_vg_tree_free_fields before freeing the wrapper. */
- _edje_vg_tree_free_fields(t, EINA_TRUE);
- free(t);
- }
- eina_list_free(all_vg_trees);
- all_vg_trees = NULL;
- }
+ /* On the normal serialize path, data_write_vectors_trees() has stolen
+ the trees list and freed each wrapper, leaving all_vg_trees == NULL.
+ This block only fires on early-abort paths (e.g. VEC001 duplicate-name
+ error) where the trees still hold live root subtrees that must be
+ reclaimed. */
+ {
+ Edje_Vg_Tree *t;
+ EINA_LIST_FREE(all_vg_trees, t)
+ {
+ _edje_vg_tree_free_fields(t, EINA_TRUE);
+ free(t);
+ }
+ }
/* Release parser-side scaffolding. The toplevel hash stores borrowed
pointers (the trees are now in all_vg_trees / vd->trees[]); no
data-free callback was set. Same for the node stack. */
diff --git a/src/bin/edje/edje_cc_out.c b/src/bin/edje/edje_cc_out.c
index 87cd4d0d05..cf9fe40d00 100644
--- a/src/bin/edje/edje_cc_out.c
+++ b/src/bin/edje/edje_cc_out.c
@@ -1536,11 +1536,14 @@ _vg_finalize_class_names(Edje_Vg_Directory *vd, Eina_Hash *seen)
static void
data_write_vectors_trees(Eet_File *ef, int *tree_num)
{
- Eina_List *trees = _edje_cc_vg_all_trees_get();
+ /* Take ownership: Step B will free both the wrapper allocations and
+ * the list nodes via EINA_LIST_FREE. After steal(), _edje_cc_vg_cleanup
+ * sees a NULL list and skips the (now-redundant) wrapper-free walk. */
+ Eina_List *trees = _edje_cc_vg_all_trees_steal();
if (!trees) return;
unsigned int n = eina_list_count(trees);
- if (n == 0) return;
+ if (n == 0) { eina_list_free(trees); return; }
/* --- Allocate the directory and its flat tree array. --- */
Edje_Vg_Directory *vd = calloc(1, sizeof(Edje_Vg_Directory));
@@ -1572,17 +1575,16 @@ data_write_vectors_trees(Eet_File *ef, int *tree_num)
}
}
- /* --- Step B: shallow-copy each tree struct into the flat array.
- Ownership of the root node subtree transfers to vd->trees[i].root.
- Nullify src->root so that _edje_cc_vg_cleanup() doesn't double-free. */
+ /* --- Step B: shallow-copy each tree struct into the flat array,
+ then free the wrapper allocation and its list node in one pass.
+ Ownership of the root node subtree transfers to vd->trees[i].root. */
{
- Eina_List *l;
Edje_Vg_Tree *src;
unsigned int i = 0;
- EINA_LIST_FOREACH(trees, l, src)
+ EINA_LIST_FREE(trees, src)
{
vd->trees[i] = *src;
- src->root = NULL;
+ free(src);
i++;
}
}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.