summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2023-01-05 13:16:04 +0000
committerBram Moolenaar <Bram@vim.org>2023-01-05 13:16:04 +0000
commitcf760d50dceb46bd583321c210b88b92360eb959 (patch)
tree83c8681eebf2582148de2c4e98fc022a4a5b7f0f
parent2468add0b88849997e6349e7a0b997be133c022d (diff)
patch 9.0.1149: class members may be garbage collectedv9.0.1149
Problem: Class members may be garbage collected. Solution: Mark class members as being in use.
-rw-r--r--src/eval.c29
-rw-r--r--src/structs.h1
-rw-r--r--src/testdir/test_vim9_class.vim17
-rw-r--r--src/version.c2
4 files changed, 46 insertions, 3 deletions
diff --git a/src/eval.c b/src/eval.c
index 9ca805061d..c9d2151dad 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -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:
{
diff --git a/src/structs.h b/src/structs.h
index 50260aeff2..5b3f566dcb 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -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;
diff --git a/src/testdir/test_vim9_class.vim b/src/testdir/test_vim9_class.vim
index a55671bcb6..b98b96f58e 100644
--- a/src/testdir/test_vim9_class.vim
+++ b/src/testdir/test_vim9_class.vim
@@ -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
diff --git a/src/version.c b/src/version.c
index a12cda2ee4..d90b673d85 100644
--- a/src/version.c
+++ b/src/version.c
@@ -696,6 +696,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1149,
+/**/
1148,
/**/
1147,