summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2016-03-24 21:23:06 +0100
committerBram Moolenaar <Bram@vim.org>2016-03-24 21:23:06 +0100
commit24c77a1e3a2ad510582116229462b482d69b4b8e (patch)
tree4a9dcaa87719c7690ebdabf09f7014644a27248b
parentd4caf5c16a9f1c9477d426e58d8d3dc47ab5f066 (diff)
downloadvim-24c77a1e3a2ad510582116229462b482d69b4b8e.zip
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)
-rw-r--r--src/eval.c96
-rw-r--r--src/testdir/test_partial.vim13
-rw-r--r--src/version.c2
3 files changed, 62 insertions, 49 deletions
diff --git a/src/eval.c b/src/eval.c
index 55d61e79b..453756217 100644
--- 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 *rettv)
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);
diff --git a/src/testdir/test_partial.vim b/src/testdir/test_partial.vim
index f67bb41dd..75cc49251 100644
--- 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
diff --git a/src/version.c b/src/version.c
index 4cd93d284..b90a0d0a9 100644
--- 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,