# HG changeset patch # User Bram Moolenaar # Date 1597239004 -7200 # Node ID 9ef7ae8ab51c8de2f4b11b52c86ce3da56ee96dd # Parent 6b6f91a7959dfc29c1016a787104b1d785cfa09f patch 8.2.1426: Vim9: cannot call autoload function in :def function Commit: https://github.com/vim/vim/commit/a177344dc0c337e5b272c1c59d13964a8318bcfa Author: Bram Moolenaar Date: Wed Aug 12 15:21:22 2020 +0200 patch 8.2.1426: Vim9: cannot call autoload function in :def function Problem: Vim9: cannot call autoload function in :def function. Solution: Load the autoload script. (closes https://github.com/vim/vim/issues/6690) diff --git a/src/scriptfile.c b/src/scriptfile.c --- a/src/scriptfile.c +++ b/src/scriptfile.c @@ -1991,7 +1991,7 @@ autoload_name(char_u *name) if (scriptname == NULL) return NULL; STRCPY(scriptname, "autoload/"); - STRCAT(scriptname, name); + STRCAT(scriptname, name[0] == 'g' && name[1] == ':' ? name + 2: name); for (p = scriptname + 9; (p = vim_strchr(p, AUTOLOAD_CHAR)) != NULL; q = p, ++p) *p = '/'; diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -1752,6 +1752,21 @@ def Test_expr7_call() "vim9script", "let x = substitute ('x', 'x', 'x', 'x')" ], 'E121:') + + let auto_lines =<< trim END + def g:some#func(): string + return 'found' + enddef + END + mkdir('Xruntime/autoload', 'p') + writefile(auto_lines, 'Xruntime/autoload/some.vim') + let save_rtp = &rtp + &rtp = getcwd() .. '/Xruntime,' .. &rtp + assert_equal('found', g:some#func()) + assert_equal('found', some#func()) + + &rtp = save_rtp + delete('Xruntime', 'rf') enddef diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -755,6 +755,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1426, +/**/ 1425, /**/ 1424, diff --git a/src/vim9compile.c b/src/vim9compile.c --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -2214,6 +2214,7 @@ compile_call( int error = FCERR_NONE; ufunc_T *ufunc; int res = FAIL; + int is_autoload; // we can evaluate "has('name')" at compile time if (varlen == 3 && STRNCMP(*arg, "has", 3) == 0) @@ -2258,7 +2259,8 @@ compile_call( if (compile_arguments(arg, cctx, &argcount) == FAIL) goto theend; - if (ASCII_ISLOWER(*name) && name[1] != ':') + is_autoload = vim_strchr(name, '#') != NULL; + if (ASCII_ISLOWER(*name) && name[1] != ':' && !is_autoload) { int idx; @@ -2281,8 +2283,9 @@ compile_call( // If the name is a variable, load it and use PCALL. // Not for g:Func(), we don't know if it is a variable or not. + // Not for eome#Func(), it will be loaded later. p = namebuf; - if (STRNCMP(namebuf, "g:", 2) != 0 + if (STRNCMP(namebuf, "g:", 2) != 0 && !is_autoload && compile_load(&p, namebuf + varlen, cctx, FALSE) == OK) { garray_T *stack = &cctx->ctx_type_stack; @@ -2295,7 +2298,7 @@ compile_call( // A global function may be defined only later. Need to figure out at // runtime. Also handles a FuncRef at runtime. - if (STRNCMP(namebuf, "g:", 2) == 0) + if (STRNCMP(namebuf, "g:", 2) == 0 || is_autoload) res = generate_UCALL(cctx, name, argcount); else semsg(_(e_unknownfunc), namebuf); diff --git a/src/vim9execute.c b/src/vim9execute.c --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -546,6 +546,15 @@ call_ufunc(ufunc_T *ufunc, int argcount, } /* + * Return TRUE if an error was given or CTRL-C was pressed. + */ + static int +vim9_aborting(int prev_called_emsg) +{ + return called_emsg > prev_called_emsg || got_int || did_throw; +} + +/* * Execute a function by "name". * This can be a builtin function or a user function. * "iptr" can be used to replace the instruction with a more efficient one. @@ -568,6 +577,18 @@ call_by_name(char_u *name, int argcount, } ufunc = find_func(name, FALSE, NULL); + + if (ufunc == NULL) + { + int called_emsg_before = called_emsg; + + if (script_autoload(name, TRUE)) + // loaded a package, search for the function again + ufunc = find_func(name, FALSE, NULL); + if (vim9_aborting(called_emsg_before)) + return FAIL; // bail out if loading the script caused an error + } + if (ufunc != NULL) return call_ufunc(ufunc, argcount, ectx, iptr);