changeset 8698:13b0ed12a78a v7.4.1638

commit https://github.com/vim/vim/commit/e4eb6ff089e79e659acf33c17dd0fda7177de526 Author: Bram Moolenaar <Bram@vim.org> Date: Tue Mar 22 21:00:09 2016 +0100 patch 7.4.1638 Problem: When binding a function to a dict the reference count is wrong. Solution: Decrement dict reference count, only reference the function when actually making a copy. (Ken Takata)
author Christian Brabandt <cb@256bit.org>
date Tue, 22 Mar 2016 21:15:11 +0100
parents e3a81776a94c
children 5a9b6ac760cc
files src/eval.c src/testdir/test_partial.vim src/version.c
diffstat 3 files changed, 19 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/src/eval.c
+++ b/src/eval.c
@@ -12019,6 +12019,7 @@ partial_free(partial_T *pt)
     for (i = 0; i < pt->pt_argc; ++i)
 	clear_tv(&pt->pt_argv[i]);
     vim_free(pt->pt_argv);
+    dict_unref(pt->pt_dict);
     func_unref(pt->pt_name);
     vim_free(pt->pt_name);
     vim_free(pt);
@@ -21797,7 +21798,8 @@ handle_subscript(
 		selfdict = NULL;
 		if (rettv->v_type == VAR_FUNC)
 		{
-		    /* just a function: use selfdict */
+		    /* Just a function: Take over the function name and use
+		     * selfdict. */
 		    pt->pt_name = rettv->vval.v_string;
 		}
 		else
@@ -21805,8 +21807,11 @@ handle_subscript(
 		    partial_T	*ret_pt = rettv->vval.v_partial;
 		    int		i;
 
-		    /* partial: use selfdict and copy args */
+		    /* Partial: copy the function name, use selfdict and copy
+		     * args.  Can't take over name or args, the partial might
+		     * be referenced elsewhere. */
 		    pt->pt_name = vim_strsave(ret_pt->pt_name);
+		    func_ref(pt->pt_name);
 		    if (ret_pt->pt_argc > 0)
 		    {
 			pt->pt_argv = (typval_T *)alloc(
@@ -21823,7 +21828,6 @@ handle_subscript(
 		    }
 		    partial_unref(ret_pt);
 		}
-		func_ref(pt->pt_name);
 		rettv->v_type = VAR_PARTIAL;
 		rettv->vval.v_partial = pt;
 	    }
--- a/src/testdir/test_partial.vim
+++ b/src/testdir/test_partial.vim
@@ -170,3 +170,13 @@ func Test_partial_string()
   let F = function('MyFunc', ['foo'], d)
   call assert_equal("function('MyFunc', ['foo'], {'one': 1})", string(F))
 endfunc
+
+func Test_func_unref()
+  let obj = {}
+  function! obj.func() abort
+  endfunction
+  let funcnumber = matchstr(string(obj.func), '^function(''\zs.\{-}\ze''')
+  call assert_true(exists('*{' . funcnumber . '}'))
+  unlet obj
+  call assert_false(exists('*{' . funcnumber . '}'))
+endfunc
--- a/src/version.c
+++ b/src/version.c
@@ -749,6 +749,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1638,
+/**/
     1637,
 /**/
     1636,