changeset 27841:5ce69c07a106 v8.2.4446

patch 8.2.4446: Vim9: cannot refer to a global function like a local one Commit: https://github.com/vim/vim/commit/fe73255c92b6cb54851f82fa32458340b736298d Author: Bram Moolenaar <Bram@vim.org> Date: Tue Feb 22 19:39:13 2022 +0000 patch 8.2.4446: Vim9: cannot refer to a global function like a local one Problem: Vim9: cannot refer to a global function like a local one. Solution: When g:name is not a variable but a function, use a function reference. (closes #9826)
author Bram Moolenaar <Bram@vim.org>
date Tue, 22 Feb 2022 20:45:04 +0100
parents a93a7405f2e2
children 4b3c59be80c7
files src/testdir/test_vim9_builtin.vim src/version.c src/vim9execute.c
diffstat 3 files changed, 39 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/src/testdir/test_vim9_builtin.vim
+++ b/src/testdir/test_vim9_builtin.vim
@@ -427,6 +427,21 @@ def Test_call_call()
   call('reverse', [l])
   l->assert_equal([1, 2, 3])
 
+  var lines =<< trim END
+      vim9script
+      def Outer()
+        def g:Inner()
+          g:done = 'Inner'
+        enddef
+        call(g:Inner, [])
+      enddef
+      Outer()
+      assert_equal('Inner', g:done)
+      unlet g:done
+  END
+  v9.CheckScriptSuccess(lines)
+  delfunc g:Inner
+
   v9.CheckDefExecAndScriptFailure(['call(123, [2])'], 'E1256: String or function required for argument 1')
   v9.CheckDefExecAndScriptFailure(['call(true, [2])'], 'E1256: String or function required for argument 1')
   v9.CheckDefAndScriptFailure(['call("reverse", 2)'], ['E1013: Argument 2: type mismatch, expected list<any> but got number', 'E1211: List required for argument 2'])
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    4446,
+/**/
     4445,
 /**/
     4444,
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -2333,16 +2333,33 @@ load_namespace_var(ectx_T *ectx, isntype
 
     if (di == NULL)
     {
+	if (isn_type == ISN_LOADG)
+	{
+	    ufunc_T *ufunc = find_func(iptr->isn_arg.string, TRUE);
+
+	    // g:Something could be a function
+	    if (ufunc != NULL)
+	    {
+		typval_T    *tv = STACK_TV_BOT(0);
+
+		++ectx->ec_stack.ga_len;
+		tv->v_type = VAR_FUNC;
+		tv->vval.v_string = alloc(STRLEN(iptr->isn_arg.string) + 3);
+		if (tv->vval.v_string == NULL)
+		    return FAIL;
+		STRCPY(tv->vval.v_string, "g:");
+		STRCPY(tv->vval.v_string + 2, iptr->isn_arg.string);
+		return OK;
+	    }
+	}
 	SOURCING_LNUM = iptr->isn_lnum;
-	if (vim_strchr(iptr->isn_arg.string,
-					AUTOLOAD_CHAR) != NULL)
+	if (vim_strchr(iptr->isn_arg.string, AUTOLOAD_CHAR) != NULL)
 	    // no check if the item exists in the script but
 	    // isn't exported, it is too complicated
-	    semsg(_(e_item_not_found_in_script_str),
-					 iptr->isn_arg.string);
+	    semsg(_(e_item_not_found_in_script_str), iptr->isn_arg.string);
 	else
 	    semsg(_(e_undefined_variable_char_str),
-			     namespace, iptr->isn_arg.string);
+					      namespace, iptr->isn_arg.string);
 	return FAIL;
     }
     else