changeset 26046:f773ef3c641d v8.2.3557

patch 8.2.3557: Vim9: cannot call imported funcref at script level Commit: https://github.com/vim/vim/commit/5fe07d2e08f05c6f3905fecdf07f4cfad4d6ed17 Author: Bram Moolenaar <Bram@vim.org> Date: Fri Oct 22 22:17:53 2021 +0100 patch 8.2.3557: Vim9: cannot call imported funcref at script level Problem: Vim9: cannot call imported funcref at script level. Solution: Check for an imported function. (closes https://github.com/vim/vim/issues/9007)
author Bram Moolenaar <Bram@vim.org>
date Fri, 22 Oct 2021 23:30:04 +0200
parents f67fadf790b9
children dd99f8800b80
files src/testdir/test_vim9_script.vim src/userfunc.c src/version.c
diffstat 3 files changed, 77 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/src/testdir/test_vim9_script.vim
+++ b/src/testdir/test_vim9_script.vim
@@ -1477,6 +1477,33 @@ def Test_vim9_import_export()
   delete('Xvim9_script')
 enddef
 
+def Test_import_funcref()
+  var lines =<< trim END
+      vim9script
+      export def F(): number
+        return 42
+      enddef
+      export const G = F
+  END
+  writefile(lines, 'Xlib.vim')
+
+  lines =<< trim END
+      vim9script
+      import {G} from './Xlib.vim'
+      const Foo = G()
+      assert_equal(42, Foo)
+
+      def DoTest()
+        const Goo = G()
+        assert_equal(42, Foo)
+      enddef
+      DoTest()
+  END
+  CheckScriptSuccess(lines)
+
+  delete('Xlib.vim')
+enddef
+
 def Test_import_star_fails()
   writefile([], 'Xfoo.vim')
   var lines =<< trim END
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -1548,9 +1548,11 @@ deref_func_name(
 	int	    no_autoload)
 {
     dictitem_T	*v;
+    typval_T	*tv = NULL;
     int		cc;
     char_u	*s = NULL;
     hashtab_T	*ht;
+    int		did_type = FALSE;
 
     if (partialp != NULL)
 	*partialp = NULL;
@@ -1562,20 +1564,59 @@ deref_func_name(
     name[*lenp] = cc;
     if (v != NULL)
     {
-	if (v->di_tv.v_type == VAR_FUNC)
+	tv = &v->di_tv;
+    }
+    else if (in_vim9script() || STRNCMP(name, "s:", 2) == 0)
+    {
+	imported_T  *import;
+	char_u	    *p = name;
+	int	    len = *lenp;
+
+	if (STRNCMP(name, "s:", 2) == 0)
+	{
+	    p = name + 2;
+	    len -= 2;
+	}
+	import = find_imported(p, len, NULL);
+
+	// imported variable from another script
+	if (import != NULL)
 	{
-	    if (v->di_tv.vval.v_string == NULL)
+	    if (import->imp_funcname != NULL)
+	    {
+		s = import->imp_funcname;
+		*lenp = (int)STRLEN(s);
+		return s;
+	    }
+	    // TODO: what if (import->imp_flags & IMP_FLAGS_STAR)
+	    {
+		scriptitem_T    *si = SCRIPT_ITEM(import->imp_sid);
+		svar_T		*sv = ((svar_T *)si->sn_var_vals.ga_data)
+						    + import->imp_var_vals_idx;
+		tv = sv->sv_tv;
+		if (type != NULL)
+		    *type = sv->sv_type;
+		did_type = TRUE;
+	    }
+	}
+    }
+
+    if (tv != NULL)
+    {
+	if (tv->v_type == VAR_FUNC)
+	{
+	    if (tv->vval.v_string == NULL)
 	    {
 		*lenp = 0;
 		return (char_u *)"";	// just in case
 	    }
-	    s = v->di_tv.vval.v_string;
+	    s = tv->vval.v_string;
 	    *lenp = (int)STRLEN(s);
 	}
 
-	if (v->di_tv.v_type == VAR_PARTIAL)
+	if (tv->v_type == VAR_PARTIAL)
 	{
-	    partial_T *pt = v->di_tv.vval.v_partial;
+	    partial_T *pt = tv->vval.v_partial;
 
 	    if (pt == NULL)
 	    {
@@ -1590,9 +1631,9 @@ deref_func_name(
 
 	if (s != NULL)
 	{
-	    if (type != NULL && ht == get_script_local_ht())
+	    if (!did_type && type != NULL && ht == get_script_local_ht())
 	    {
-		svar_T  *sv = find_typval_in_script(&v->di_tv);
+		svar_T  *sv = find_typval_in_script(tv);
 
 		if (sv != NULL)
 		    *type = sv->sv_type;
--- a/src/version.c
+++ b/src/version.c
@@ -758,6 +758,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    3557,
+/**/
     3556,
 /**/
     3555,