patch 9.1.1013: Vim9: Regression caused by patch v9.1.0646

Commit: 
https://github.com/vim/vim/commit/6289f9159102e0855bedc566636b5e7ca6ced72c
Author: Yegappan Lakshmanan <yegap...@yahoo.com>
Date:   Tue Jan 14 17:13:36 2025 +0100

    patch 9.1.1013: Vim9: Regression caused by patch v9.1.0646
    
    Problem:  Vim9: Regression caused by patch v9.1.0646
    Solution: Translate the function name before invoking it in call()
              (Yegappan Lakshmanan)
    
    fixes: #16430
    closes: #16445
    
    Signed-off-by: Yegappan Lakshmanan <yegap...@yahoo.com>
    Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/src/evalfunc.c b/src/evalfunc.c
index d81480b50..ef30792ad 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -3739,7 +3739,6 @@ f_call(typval_T *argvars, typval_T *rettv)
     char_u     *func;
     partial_T   *partial = NULL;
     dict_T     *selfdict = NULL;
-    char_u     *dot;
     char_u     *tofree = NULL;
 
     if (in_vim9script()
@@ -3765,36 +3764,26 @@ f_call(typval_T *argvars, typval_T *rettv)
     if (func == NULL || *func == NUL)
        return;         // type error, empty name or null function
 
-    dot = vim_strchr(func, '.');
-    if (dot != NULL)
+    char_u     *p = func;
+    tofree = trans_function_name(&p, NULL, FALSE, TFN_INT|TFN_QUIET);
+    if (tofree == NULL)
     {
-       imported_T *import = find_imported(func, dot - func, TRUE);
-
-       if (import != NULL && SCRIPT_ID_VALID(import->imp_sid))
-       {
-           scriptitem_T *si = SCRIPT_ITEM(import->imp_sid);
-
-           if (si->sn_autoload_prefix != NULL)
-           {
-               // Turn "import.Func" into "scriptname#Func".
-               tofree = concat_str(si->sn_autoload_prefix, dot + 1);
-               if (tofree == NULL)
-                   return;
-               func = tofree;
-           }
-       }
+       emsg_funcname(e_unknown_function_str, func);
+       return;
     }
+    func = tofree;
 
     if (argvars[2].v_type != VAR_UNKNOWN)
     {
        if (check_for_dict_arg(argvars, 2) == FAIL)
-           return;
+           goto done;
 
        selfdict = argvars[2].vval.v_dict;
     }
 
     (void)func_call(func, &argvars[1], partial, selfdict, rettv);
 
+done:
     vim_free(tofree);
 }
 
diff --git a/src/option.c b/src/option.c
index 52f996975..653b87cae 100644
--- a/src/option.c
+++ b/src/option.c
@@ -8786,15 +8786,33 @@ option_set_callback_func(char_u *optval UNUSED, 
callback_T *optcb UNUSED)
        vim_free(cb.cb_name);
     free_tv(tv);
 
-    if (in_vim9script() && funcname && (vim_strchr(optval, '.') != NULL))
+    char_u  *dot = NULL;
+    if (in_vim9script() && funcname
+                               && ((dot = vim_strchr(optval, '.')) != NULL))
     {
-       // When a Vim9 imported function name is used, it is expanded by the
-       // call to get_callback() above to <SNR>_funcname.   Revert the name to
-       // back to "import.funcname".
        if (optcb->cb_free_name)
            vim_free(optcb->cb_name);
-       optcb->cb_name = vim_strsave(optval);
-       optcb->cb_free_name = TRUE;
+
+       imported_T *import = find_imported(optval, dot - optval, FALSE);
+       if (import != NULL && SCRIPT_ID_VALID(import->imp_sid)
+                               && !(import->imp_flags & IMP_FLAGS_AUTOLOAD))
+       {
+           char_u      fnamebuf[MAX_FUNC_NAME_LEN];
+
+           // Imported non-autoloaded function.  Replace the import script
+           // name (import.funcname) with the script ID (<SNR>123_funcname)
+           vim_snprintf((char *)fnamebuf, sizeof(fnamebuf), "<SNR>%d_%s",
+                                               import->imp_sid, dot + 1);
+           optcb->cb_name = vim_strsave(fnamebuf);
+           optcb->cb_free_name = TRUE;
+       }
+       else
+       {
+           // Imported autoloaded function.  Store the function name as
+           // "import.funcname".
+           optcb->cb_name = vim_strsave(optval);
+           optcb->cb_free_name = TRUE;
+       }
     }
     // when using Vim9 style "import.funcname" it needs to be expanded to
     // "import#funcname".
diff --git a/src/testdir/test_user_func.vim b/src/testdir/test_user_func.vim
index 992329bc7..99ac90662 100644
--- a/src/testdir/test_user_func.vim
+++ b/src/testdir/test_user_func.vim
@@ -427,7 +427,7 @@ func Test_script_local_func()
   " Try to call a script local function in global scope
   let lines =<< trim [CODE]
     :call assert_fails('call s:Xfunc()', 'E81:')
-    :call assert_fails('let x = call("<SID>Xfunc", [])', 'E120:')
+    :call assert_fails('let x = call("<SID>Xfunc", [])', ['E81:', 'E117:'])
     :call writefile(v:errors, 'Xresult')
     :qall
 
diff --git a/src/testdir/test_vim9_builtin.vim 
b/src/testdir/test_vim9_builtin.vim
index 6103453a2..c82608b46 100644
--- a/src/testdir/test_vim9_builtin.vim
+++ b/src/testdir/test_vim9_builtin.vim
@@ -540,7 +540,7 @@ def Test_call_imports()
     const Imported = i_imp.Imported
     const foo = i_imp.foo
 
-    assert_fails('call("i_imp.foo", [])', 'E117:') # foo is not a function
+    assert_fails('call("i_imp.foo", [])', ['E46:', 'E117:']) # foo is not a 
function
     assert_fails('call("foo", [])', 'E117:') # foo is not a function
     assert_fails('call("i_xxx.foo", [])', 'E117:') # i_xxx not imported file
   END
diff --git a/src/testdir/test_vim9_disassemble.vim 
b/src/testdir/test_vim9_disassemble.vim
index 2dc925a35..b4e25c39a 100644
--- a/src/testdir/test_vim9_disassemble.vim
+++ b/src/testdir/test_vim9_disassemble.vim
@@ -3611,4 +3611,26 @@ def Test_disassemble_interface_variable_access()
   unlet g:instr
 enddef
 
+" Disassemble the code generated for accessing a script-local funcref
+def Test_disassemble_using_script_local_funcref()
+  var lines =<< trim END
+    vim9script
+    def Noop()
+    enddef
+    export var Setup = Noop
+    export def Run()
+      Setup()
+    enddef
+    g:instr = execute('disassemble Run')
+  END
+  v9.CheckScriptSuccess(lines)
+  assert_match('<SNR>\d\+_Run\_s*' ..
+    'Setup()\_s*' ..
+    '0 LOADSCRIPT Setup-0 from .*\_s*' ..
+    '1 PCALL (argc 0)\_s*' ..
+    '2 DROP\_s*' ..
+    '3 RETURN void\_s*', g:instr)
+  unlet g:instr
+enddef
+
 " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim
index 4188f82e5..38832e99d 100644
--- a/src/testdir/test_vim9_func.vim
+++ b/src/testdir/test_vim9_func.vim
@@ -4714,6 +4714,47 @@ def Test_comment_after_inner_block()
   v9.CheckScriptSuccess(lines)
 enddef
 
+" Test for calling an imported funcref which is modified in the current script
+def Test_call_modified_import_func()
+  var lines =<< trim END
+    vim9script
+
+    export var done = 0
+
+    def Noop()
+    enddef
+
+    export var Setup = Noop
+
+    export def Run()
+      done = 0
+      Setup()
+      done += 1
+    enddef
+  END
+  writefile(lines, 'XcallModifiedImportFunc.vim', 'D')
+
+  lines =<< trim END
+    vim9script
+
+    import './XcallModifiedImportFunc.vim' as imp
+
+    var setup = 0
+
+    imp.Run()
+
+    imp.Setup = () => {
+      ++setup
+    }
+
+    imp.Run()
+
+    assert_equal(1, setup)
+    assert_equal(1, imp.done)
+  END
+  v9.CheckScriptSuccess(lines)
+enddef
+
 " The following messes up syntax highlight, keep near the end.
 if has('python3')
   def Test_python3_command()
diff --git a/src/userfunc.c b/src/userfunc.c
index b4ee0a267..06be445af 100644
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -2308,49 +2308,6 @@ find_func_with_prefix(char_u *name, int sid)
     return NULL;
 }
 
-/*
- * Find a function by name, return pointer to it.
- * The name may be a local script variable, VAR_FUNC. or it may be a fully
- * qualified import name such as 'i_imp.FuncName'.
- *
- * When VAR_FUNC, the import might either direct or autoload.
- * When 'i_imp.FuncName' it is direct, autoload is rewritten as i_imp#FuncName
- * in f_call and subsequently found.
- */
-    static ufunc_T *
-find_func_imported(char_u *name, int flags)
-{
-    ufunc_T    *func = NULL;
-    char_u     *dot = name; // Find a dot, '.', in the name
-
-    // Either run into '.' or the end of the string
-    while (eval_isnamec(*dot))
-       ++dot;
-
-    if (*dot == '.')
-    {
-       imported_T *import = find_imported(name, dot - name, FALSE);
-       if (import != NULL)
-           func = find_func_with_sid(dot + 1, import->imp_sid);
-    }
-    else if (*dot == NUL) // looking at the entire string
-    {
-       hashtab_T *ht = get_script_local_ht();
-       if (ht != NULL)
-       {
-           hashitem_T *hi = hash_find(ht, name);
-           if (!HASHITEM_EMPTY(hi))
-           {
-               dictitem_T *di = HI2DI(hi);
-               if (di->di_tv.v_type == VAR_FUNC
-                       && di->di_tv.vval.v_string != NULL)
-                   func = find_func_even_dead(di->di_tv.vval.v_string, flags);
-           }
-       }
-    }
-    return func;
-}
-
 /*
  * Find a function by name, return pointer to it in ufuncs.
  * When "flags" has FFED_IS_GLOBAL don't find script-local or imported
@@ -2400,15 +2357,8 @@ find_func_even_dead(char_u *name, int flags)
     }
 
     // Find autoload function if this is an autoload script.
-    func = find_func_with_prefix(name[0] == 's' && name[1] == ':'
+    return find_func_with_prefix(name[0] == 's' && name[1] == ':'
                                       ? name + 2 : name, current_sctx.sc_sid);
-    if (func != NULL)
-       return func;
-
-    // Find a script-local "VAR_FUNC" or i_"imp.Func", so vim9script).
-    if (in_vim9script())
-       func = find_func_imported(name, flags);
-    return func;
 }
 
 /*
diff --git a/src/version.c b/src/version.c
index 9dddabc05..2cf4f4697 100644
--- a/src/version.c
+++ b/src/version.c
@@ -704,6 +704,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1013,
 /**/
     1012,
 /**/

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
To view this discussion visit 
https://groups.google.com/d/msgid/vim_dev/E1tXjns-00Bqjl-OC%40256bit.org.

Raspunde prin e-mail lui