diff options
author | Bram Moolenaar <Bram@vim.org> | 2020-04-12 22:22:31 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2020-04-12 22:22:31 +0200 |
commit | 23e032523e377d367e06441e88c67692a8c6c3e9 (patch) | |
tree | 04db10f3d16be0dfae4a784937c28fc159fd2c56 /src | |
parent | 5e774c7579a4a00d3f44fdcfcb56861bd73372e4 (diff) | |
download | vim-git-23e032523e377d367e06441e88c67692a8c6c3e9.tar.gz |
patch 8.2.0564: Vim9: calling a def function from non-vim9 may failv8.2.0564
Problem: Vim9: calling a def function from non-vim9 may fail.
Solution: Convert varargs to a list.
Diffstat (limited to 'src')
-rw-r--r-- | src/testdir/test_vim9_func.vim | 7 | ||||
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/vim9execute.c | 24 |
3 files changed, 32 insertions, 1 deletions
diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index 38d7c5a5a..c98acc906 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -576,6 +576,13 @@ def Test_multiline() assert_equal('text777one-two', MultiLine('text', 777, 'one', 'two')) enddef +func Test_multiline_not_vim9() + call assert_equal('text1234', MultiLine('text')) + call assert_equal('text777', MultiLine('text', 777)) + call assert_equal('text777one', MultiLine('text', 777, 'one')) + call assert_equal('text777one-two', MultiLine('text', 777, 'one', 'two')) +endfunc + " When using CheckScriptFailure() for the below test, E1010 is generated instead " of E1056. diff --git a/src/version.c b/src/version.c index d43c9d578..7b40fa4cb 100644 --- a/src/version.c +++ b/src/version.c @@ -739,6 +739,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 564, +/**/ 563, /**/ 562, diff --git a/src/vim9execute.c b/src/vim9execute.c index f8fb061f8..4ac760e66 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -477,11 +477,12 @@ call_eval_func(char_u *name, int argcount, ectx_T *ectx, isn_T *iptr) int call_def_function( ufunc_T *ufunc, - int argc, // nr of arguments + int argc_arg, // nr of arguments typval_T *argv, // arguments typval_T *rettv) // return value { ectx_T ectx; // execution context + int argc = argc_arg; int initial_frame_ptr; typval_T *tv; int idx; @@ -512,13 +513,34 @@ call_def_function( copy_tv(&argv[idx], STACK_TV_BOT(0)); ++ectx.ec_stack.ga_len; } + + // Turn varargs into a list. Empty list if no args. + if (ufunc->uf_va_name != NULL) + { + int vararg_count = argc - ufunc->uf_args.ga_len; + + if (vararg_count < 0) + vararg_count = 0; + else + argc -= vararg_count; + if (exe_newlist(vararg_count, &ectx) == FAIL) + goto failed; + if (defcount > 0) + // Move varargs list to below missing default arguments. + *STACK_TV_BOT(defcount- 1) = *STACK_TV_BOT(-1); + --ectx.ec_stack.ga_len; + } + // Make space for omitted arguments, will store default value below. + // Any varargs list goes after them. if (defcount > 0) for (idx = 0; idx < defcount; ++idx) { STACK_TV_BOT(0)->v_type = VAR_UNKNOWN; ++ectx.ec_stack.ga_len; } + if (ufunc->uf_va_name != NULL) + ++ectx.ec_stack.ga_len; // Frame pointer points to just after arguments. ectx.ec_frame = ectx.ec_stack.ga_len; |