]> granicus.if.org Git - vim/commitdiff
patch 9.0.1149: class members may be garbage collected v9.0.1149
authorBram Moolenaar <Bram@vim.org>
Thu, 5 Jan 2023 13:16:04 +0000 (13:16 +0000)
committerBram Moolenaar <Bram@vim.org>
Thu, 5 Jan 2023 13:16:04 +0000 (13:16 +0000)
Problem:    Class members may be garbage collected.
Solution:   Mark class members as being in use.

src/eval.c
src/structs.h
src/testdir/test_vim9_class.vim
src/version.c

index 9ca805061d9506c18d8a371166fd89ca459de1b6..c9d2151dad14be9df11b9ec95ee418885fe3bb3a 100644 (file)
@@ -5674,9 +5674,32 @@ set_ref_in_item(
        }
 
        case VAR_CLASS:
-           // TODO: Mark methods in class_obj_methods ?
-           // Mark initializer expressions?
-           break;
+           {
+               class_T *cl = tv->vval.v_class;
+               if (cl != NULL && cl->class_copyID != copyID)
+               {
+                   cl->class_copyID = copyID;
+                   for (int i = 0; !abort
+                                     && i < cl->class_class_member_count; ++i)
+                       abort = abort || set_ref_in_item(
+                                               &cl->class_members_tv[i],
+                                                copyID, ht_stack, list_stack);
+
+
+                   for (int i = 0; !abort
+                                   && i < cl->class_class_function_count; ++i)
+                       abort = abort || set_ref_in_func(NULL,
+                                        cl->class_class_functions[i], copyID);
+
+                   for (int i = 0; !abort
+                                   && i < cl->class_obj_method_count; ++i)
+                       abort = abort || set_ref_in_func(NULL,
+                                            cl->class_obj_methods[i], copyID);
+
+                   // Mark initializer expressions?
+               }
+               break;
+           }
 
        case VAR_OBJECT:
            {
index 50260aeff282e94c68a1d2bb78a9b7d057a92781..5b3f566dcb9667920bf36763aa640bb69420f3de 100644 (file)
@@ -1487,6 +1487,7 @@ struct class_S
 {
     char_u     *class_name;            // allocated
     int                class_refcount;
+    int                class_copyID;           // used by garbage collection
 
     // class members: "static varname"
     int                class_class_member_count;
index a55671bcb65e90f1d7b6b7f6427b316c7023e3d1..b98b96f58e89c497e3433ac05380ba3cb58e4845 100644 (file)
@@ -493,6 +493,23 @@ def Test_class_member()
   v9.CheckScriptFailure(lines, 'E1341: Variable already declared in the class: count')
 enddef
 
+func Test_class_garbagecollect()
+  let lines =<< trim END
+      vim9script
+
+      class Point
+        this.p = [2, 3]
+        static pl = ['a', 'b']
+        static pd = {a: 'a', b: 'b'}
+      endclass
+
+      echo Point.pl Point.pd
+      call test_garbagecollect_now()
+      echo Point.pl Point.pd
+  END
+  call v9.CheckScriptSuccess(lines)
+endfunc
+
 def Test_class_function()
   var lines =<< trim END
       vim9script
index a12cda2ee44f0319383785c0456288346a1f21f1..d90b673d85d566577a3f1188f19785655a50ef18 100644 (file)
@@ -695,6 +695,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1149,
 /**/
     1148,
 /**/