changeset 27086:1e2a6c6c7e42 v8.2.4072

patch 8.2.4072: Vim9: compiling function fails when autoload is not loaded Commit: https://github.com/vim/vim/commit/d041f4208b0a2149e9d41f6443aa1c14c076a411 Author: Bram Moolenaar <Bram@vim.org> Date: Wed Jan 12 19:54:00 2022 +0000 patch 8.2.4072: Vim9: compiling function fails when autoload is not loaded Problem: Vim9: compiling function fails when autoload script is not loaded yet. Solution: Depend on runtime loading.
author Bram Moolenaar <Bram@vim.org>
date Wed, 12 Jan 2022 21:00:05 +0100
parents 40b273e28f26
children e8f812ec5879
files src/testdir/test_vim9_import.vim src/version.c src/vim9execute.c src/vim9expr.c src/vim9instr.c src/vim9script.c
diffstat 6 files changed, 83 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/testdir/test_vim9_import.vim
+++ b/src/testdir/test_vim9_import.vim
@@ -1218,6 +1218,42 @@ def Test_vim9script_autoload_call()
   &rtp = save_rtp
 enddef
 
+def Test_import_autoload_postponed()
+  mkdir('Xdir/autoload', 'p')
+  var save_rtp = &rtp
+  exe 'set rtp^=' .. getcwd() .. '/Xdir'
+
+  var lines =<< trim END
+      vim9script autoload
+
+      g:loaded_postponed = 'true'
+      export var variable = 'bla'
+      export def Function(): string
+        return 'bla'
+      enddef
+  END
+  writefile(lines, 'Xdir/autoload/postponed.vim')
+
+  lines =<< trim END
+      vim9script
+
+      import autoload 'postponed.vim'
+      def Tryit()
+        echo postponed.variable
+        echo postponed.Function()
+      enddef
+      defcompile
+  END
+  CheckScriptSuccess(lines)
+  assert_false(exists('g:loaded_postponed'))
+  CheckScriptSuccess(lines + ['Tryit()'])
+  assert_equal('true', g:loaded_postponed)
+
+  unlet g:loaded_postponed
+  delete('Xdir', 'rf')
+  &rtp = save_rtp
+enddef
+
 def Test_autoload_mapping()
   mkdir('Xdir/autoload', 'p')
   var save_rtp = &rtp
--- 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 */
 /**/
+    4072,
+/**/
     4071,
 /**/
     4070,
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -2227,6 +2227,16 @@ exec_instructions(ectx_T *ectx)
 		    }
 		    di = find_var_in_ht(ht, 0, iptr->isn_arg.string, TRUE);
 
+		    if (di == NULL && ht == get_globvar_ht())
+		    {
+			// may need to load autoload script
+			if (script_autoload(iptr->isn_arg.string, FALSE))
+			    di = find_var_in_ht(ht, 0,
+						   iptr->isn_arg.string, TRUE);
+			if (did_emsg)
+			    goto on_error;
+		    }
+
 		    if (di == NULL)
 		    {
 			SOURCING_LNUM = iptr->isn_lnum;
--- a/src/vim9expr.c
+++ b/src/vim9expr.c
@@ -274,6 +274,8 @@ compile_load_scriptvar(
 	int	cc;
 	ufunc_T	*ufunc;
 	type_T	*type;
+	int	done = FALSE;
+	int	res = OK;
 
 	// TODO: if this is an autoload import do something else.
 	// Need to lookup the member.
@@ -296,11 +298,31 @@ compile_load_scriptvar(
 	cc = *p;
 	*p = NUL;
 
-	idx = find_exported(import->imp_sid, exp_name, &ufunc, &type,
+	si = SCRIPT_ITEM(import->imp_sid);
+	if (si->sn_autoload_prefix != NULL
+					&& si->sn_state == SN_STATE_NOT_LOADED)
+	{
+	    char_u  *auto_name = concat_str(si->sn_autoload_prefix, exp_name);
+
+	    // autoload script must be loaded later, access by the autoload
+	    // name.
+	    if (cc == '(')
+		res = generate_PUSHFUNC(cctx, auto_name, &t_func_any);
+	    else
+		res = generate_LOAD(cctx, ISN_LOADG, 0, auto_name, &t_any);
+	    vim_free(auto_name);
+	    done = TRUE;
+	}
+	else
+	{
+	    idx = find_exported(import->imp_sid, exp_name, &ufunc, &type,
 								   cctx, TRUE);
+	}
 	*p = cc;
 	p = skipwhite(p);
 	*end = p;
+	if (done)
+	    return res;
 
 	if (idx < 0)
 	{
--- a/src/vim9instr.c
+++ b/src/vim9instr.c
@@ -714,7 +714,6 @@ generate_PUSHBLOB(cctx_T *cctx, blob_T *
 
 /*
  * Generate an ISN_PUSHFUNC instruction with name "name".
- * Consumes "name".
  */
     int
 generate_PUSHFUNC(cctx_T *cctx, char_u *name, type_T *type)
@@ -727,7 +726,8 @@ generate_PUSHFUNC(cctx_T *cctx, char_u *
 	return FAIL;
     if (name == NULL)
 	funcname = NULL;
-    else if (*name == K_SPECIAL)  // script-local
+    else if (*name == K_SPECIAL				    // script-local
+	    || vim_strchr(name, AUTOLOAD_CHAR) != NULL)	    // autoload
 	funcname = vim_strsave(name);
     else
     {
--- a/src/vim9script.c
+++ b/src/vim9script.c
@@ -488,7 +488,16 @@ handle_import(
 	// we need a scriptitem without loading the script
 	sid = find_script_in_rtp(from_name);
 	vim_free(from_name);
-	res = SCRIPT_ID_VALID(sid) ? OK : FAIL;
+	if (SCRIPT_ID_VALID(sid))
+	{
+	    scriptitem_T    *si = SCRIPT_ITEM(sid);
+
+	    if (si->sn_autoload_prefix == NULL)
+		si->sn_autoload_prefix = get_autoload_prefix(si);
+	    res = OK;
+	}
+	else
+	    res = FAIL;
     }
     else
     {