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.

Reply via email to