diff options
author | Bram Moolenaar <Bram@vim.org> | 2016-03-24 21:23:06 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2016-03-24 21:23:06 +0100 |
commit | 24c77a1e3a2ad510582116229462b482d69b4b8e (patch) | |
tree | 4a9dcaa87719c7690ebdabf09f7014644a27248b | |
parent | d4caf5c16a9f1c9477d426e58d8d3dc47ab5f066 (diff) | |
download | vim-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.c | 96 | ||||
-rw-r--r-- | src/testdir/test_partial.vim | 13 | ||||
-rw-r--r-- | src/version.c | 2 |
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, |