changeset 20017:ee823254dda5 v8.2.0564

patch 8.2.0564: Vim9: calling a def function from non-vim9 may fail Commit: https://github.com/vim/vim/commit/23e032523e377d367e06441e88c67692a8c6c3e9 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Apr 12 22:22:31 2020 +0200 patch 8.2.0564: Vim9: calling a def function from non-vim9 may fail Problem: Vim9: calling a def function from non-vim9 may fail. Solution: Convert varargs to a list.
author Bram Moolenaar <Bram@vim.org>
date Sun, 12 Apr 2020 22:30:03 +0200
parents 90d957ae667c
children 33b501a289fc
files src/testdir/test_vim9_func.vim src/version.c src/vim9execute.c
diffstat 3 files changed, 32 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- 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.
--- 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,
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -477,11 +477,12 @@ call_eval_func(char_u *name, int argcoun
     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;