changeset 8710:af3cb5c068fd v7.4.1644

commit https://github.com/vim/vim/commit/24c77a1e3a2ad510582116229462b482d69b4b8e Author: Bram Moolenaar <Bram@vim.org> Date: Thu Mar 24 21:23:06 2016 +0100 patch 7.4.1644 Problem: Using string() on a partial that exists in the dictionary it binds results in an error. (Nikolai Pavlov) Solution: Make string() not fail on a recursively nested structure. (Ken Takta)
author Christian Brabandt <cb@256bit.org>
date Thu, 24 Mar 2016 21:30:06 +0100
parents 0e13fb6f07f4
children 0579053e5409
files src/eval.c src/testdir/test_partial.vim src/version.c
diffstat 3 files changed, 62 insertions(+), 49 deletions(-) [+]
line wrap: on
line diff
--- a/src/eval.c
+++ b/src/eval.c
@@ -7851,10 +7851,50 @@ echo_string(
 	    break;
 
 	case VAR_PARTIAL:
-	    *tofree = NULL;
-	    /* TODO: arguments */
-	    r = tv->vval.v_partial == NULL ? NULL : tv->vval.v_partial->pt_name;
-	    break;
+	    {
+		partial_T   *pt = tv->vval.v_partial;
+		char_u	    *fname = string_quote(pt == NULL ? NULL
+							: pt->pt_name, FALSE);
+		garray_T    ga;
+		int	    i;
+		char_u	    *tf;
+
+		ga_init2(&ga, 1, 100);
+		ga_concat(&ga, (char_u *)"function(");
+		if (fname != NULL)
+		{
+		    ga_concat(&ga, fname);
+		    vim_free(fname);
+		}
+		if (pt != NULL && pt->pt_argc > 0)
+		{
+		    ga_concat(&ga, (char_u *)", [");
+		    for (i = 0; i < pt->pt_argc; ++i)
+		    {
+			if (i > 0)
+			    ga_concat(&ga, (char_u *)", ");
+			ga_concat(&ga,
+			     tv2string(&pt->pt_argv[i], &tf, numbuf, copyID));
+			vim_free(tf);
+		    }
+		    ga_concat(&ga, (char_u *)"]");
+		}
+		if (pt != NULL && pt->pt_dict != NULL)
+		{
+		    typval_T dtv;
+
+		    ga_concat(&ga, (char_u *)", ");
+		    dtv.v_type = VAR_DICT;
+		    dtv.vval.v_dict = pt->pt_dict;
+		    ga_concat(&ga, tv2string(&dtv, &tf, numbuf, copyID));
+		    vim_free(tf);
+		}
+		ga_concat(&ga, (char_u *)")");
+
+		*tofree = ga.ga_data;
+		r = *tofree;
+		break;
+	    }
 
 	case VAR_LIST:
 	    if (tv->vval.v_list == NULL)
@@ -7941,50 +7981,6 @@ tv2string(
 	case VAR_FUNC:
 	    *tofree = string_quote(tv->vval.v_string, TRUE);
 	    return *tofree;
-	case VAR_PARTIAL:
-	    {
-		partial_T   *pt = tv->vval.v_partial;
-		char_u	    *fname = string_quote(pt == NULL ? NULL
-							: pt->pt_name, FALSE);
-		garray_T    ga;
-		int	    i;
-		char_u	    *tf;
-
-		ga_init2(&ga, 1, 100);
-		ga_concat(&ga, (char_u *)"function(");
-		if (fname != NULL)
-		{
-		    ga_concat(&ga, fname);
-		    vim_free(fname);
-		}
-		if (pt != NULL && pt->pt_argc > 0)
-		{
-		    ga_concat(&ga, (char_u *)", [");
-		    for (i = 0; i < pt->pt_argc; ++i)
-		    {
-			if (i > 0)
-			    ga_concat(&ga, (char_u *)", ");
-			ga_concat(&ga,
-			     tv2string(&pt->pt_argv[i], &tf, numbuf, copyID));
-			vim_free(tf);
-		    }
-		    ga_concat(&ga, (char_u *)"]");
-		}
-		if (pt != NULL && pt->pt_dict != NULL)
-		{
-		    typval_T dtv;
-
-		    ga_concat(&ga, (char_u *)", ");
-		    dtv.v_type = VAR_DICT;
-		    dtv.vval.v_dict = pt->pt_dict;
-		    ga_concat(&ga, tv2string(&dtv, &tf, numbuf, copyID));
-		    vim_free(tf);
-		}
-		ga_concat(&ga, (char_u *)")");
-
-		*tofree = ga.ga_data;
-		return *tofree;
-	    }
 	case VAR_STRING:
 	    *tofree = string_quote(tv->vval.v_string, FALSE);
 	    return *tofree;
@@ -7997,6 +7993,7 @@ tv2string(
 	case VAR_NUMBER:
 	case VAR_LIST:
 	case VAR_DICT:
+	case VAR_PARTIAL:
 	case VAR_SPECIAL:
 	case VAR_JOB:
 	case VAR_CHANNEL:
@@ -19258,7 +19255,8 @@ f_string(typval_T *argvars, typval_T *re
     char_u	numbuf[NUMBUFLEN];
 
     rettv->v_type = VAR_STRING;
-    rettv->vval.v_string = tv2string(&argvars[0], &tofree, numbuf, 0);
+    rettv->vval.v_string = tv2string(&argvars[0], &tofree, numbuf,
+								get_copyID());
     /* Make a copy if we have a value but it's not in allocated memory. */
     if (rettv->vval.v_string != NULL && tofree == NULL)
 	rettv->vval.v_string = vim_strsave(rettv->vval.v_string);
--- a/src/testdir/test_partial.vim
+++ b/src/testdir/test_partial.vim
@@ -180,3 +180,16 @@ func Test_func_unref()
   unlet obj
   call assert_false(exists('*{' . funcnumber . '}'))
 endfunc
+
+func Test_tostring()
+  let d = {}
+  let d.d = d
+  function d.test3()
+    echo 42
+  endfunction
+  try
+    call string(d.test3)
+  catch
+    call assert_true(v:false, v:exception)
+  endtry
+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 */
 /**/
+    1644,
+/**/
     1643,
 /**/
     1642,