From: Miguel Barro Date: Mon, 22 Jun 2026 19:19:24 +0000 (+0000) Subject: patch 9.2.0703: session file does not store relative Vim9 autoload imports X-Git-Tag: v9.2.0703^0 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a82ed3a6f37e0dcc821e0c3c0d5764b227e40901;p=thirdparty%2Fvim.git patch 9.2.0703: session file does not store relative Vim9 autoload imports Problem: mksession misses relative or absolute imports in the session, homonymous autoload scripts imported from different scripts cause errors (after v9.2.0579). Solution: Correctly write scripts imported via :import autoload, skip any that are no longer readable, and comment out imports whose autoload prefix or file name tail would conflict with an earlier one (Miguel Barro). fixes: #12641 closes: #20564 Signed-off-by: Miguel Barro Signed-off-by: Christian Brabandt --- diff --git a/src/session.c b/src/session.c index 090448937f..0fa03e556d 100644 --- a/src/session.c +++ b/src/session.c @@ -1333,10 +1333,42 @@ ex_mkrc(exarg_T *eap) for (sid = 1; sid <= script_items.ga_len; ++sid) { si = SCRIPT_ITEM(sid); - if (si->sn_autoload_prefix && - (fprintf(fd, "import autoload '%s'", si->sn_name) < 0 || - put_eol(fd) == FAIL)) + + // Autoload script paths may be absolute, relative to the + // current script or relative to a 'runtimepath' directory + // Ignore if missing + if ((si->sn_autoload_prefix || si->sn_import_autoload) + && file_is_readable(si->sn_name)) + { + // Check if conflicts with a previous import + int b_sid = sid - 1; + char_u *name = gettail(si->sn_name); + + for (; b_sid; --b_sid) + { + scriptitem_T *b_si = SCRIPT_ITEM(b_sid); + + // Only autoload may conflict. Ignore if missing + if ((!b_si->sn_autoload_prefix && !b_si->sn_import_autoload) + || !file_is_readable(b_si->sn_name)) + continue; + + // compare prefixes if available + if (si->sn_autoload_prefix != NULL && b_si->sn_autoload_prefix != NULL + && (STRCMP(si->sn_autoload_prefix, b_si->sn_autoload_prefix) == 0)) + break; + + // otherwise compare tails + char_u *b_name = gettail(b_si->sn_name); + if (STRCMP(name, b_name) == 0) + break; + } + + // import the auto script if there are no conflicts + if (fprintf(fd, "%simport autoload '%s'", b_sid ? "# " : "", si->sn_name) < 0 || + put_eol(fd) == FAIL) failed = TRUE; + } } #endif } diff --git a/src/testdir/test_mksession.vim b/src/testdir/test_mksession.vim index 4dec8815a4..0bccad1c66 100644 --- a/src/testdir/test_mksession.vim +++ b/src/testdir/test_mksession.vim @@ -1598,4 +1598,128 @@ func Test_mksession_localmappings() endfunc +" Test vim9 script relative auto imports (issue #12641) +func Test_mksession_vim9_relative_auto_import() + + " Dummy vim9 script + let script_sources =<< trim END + vim9script + import autoload './XAuto.vim' + nnoremap dummy-test XAuto.Test() + END + call writefile(script_sources, 'XScript.vim', 'D') + + let auto_sources =<< trim END + vim9script + const ref_txt = 'Hello from vim9 dummy relative auto script!' + export def Test() + if !has("gui_running") + exe $"echomsg '{ref_txt}'" + endif + writefile([ref_txt], 'XDummyOutput') + enddef + END + call writefile(auto_sources, 'XAuto.vim', 'D') + + " Source the script + const ref_txt = 'Hello from vim9 dummy relative auto script!' + source XScript.vim + + " Execute mapping + normal dummy-test + + if !has('gui_running') + call assert_match(ref_txt, execute('messages'), 'No vim9 auto script XAuto.Test() execution') + endif + call assert_true(filereadable('XDummyOutput'), 'Output file was not created by Vim9 auto script') + call assert_equal([ref_txt], readfile('XDummyOutput')) + call delete('XDummyOutput') + + " Create a session file + mksession! XDummySession.vim + defer delete('XDummySession.vim') + call assert_true(filereadable('XDummySession.vim'), 'Session file was not created') + + " Check the session file mappings are operational + let test_sources =<< trim END + " Load session + source XDummySession.vim + " Execute mapping + normal dummy-test + " on my way + cq + END + call writefile(test_sources, 'XTest.vim', 'D') + " spawn a new Vim instance to load the session and execute the mapping + call system(GetVimCommand('XTest.vim')) + call assert_true(filereadable('XDummyOutput'), + \ 'Expected output file was not created by Vim9 auto script mapping') + defer delete('XDummyOutput') + call assert_equal([ref_txt], readfile('XDummyOutput')) + +endfunc + +" Test vim9 script avoid homonimous auto imports +func Test_mksession_vim9_duplicate_import() + + " Auto script + let auto_sources =<< trim END + vim9script + const ref_txt = 'Hello from a duplicated vim9 script!' + export def Test() + writefile([ref_txt], 'XDummyOutput') + enddef + END + + " Dummy vim9 script + let script_sources =<< trim END + vim9script + import autoload './XAuto.vim' + nnoremap dummy-test XAuto.Test() + END + + for i in range(1, 5) + let dir = $'XDir{i}' + call mkdir(dir, 'p') + defer delete(dir, 'rf') + + let autofile = dir . '/XAuto.vim' + call writefile(auto_sources, autofile, 'D') + + let scriptfile = dir . '/XScript.vim' + call writefile(script_sources, scriptfile, 'D') + exe "source " . scriptfile + endfor + + " Create a session file + mksession! XDummySession.vim + defer delete('XDummySession.vim') + call assert_true(filereadable('XDummySession.vim'), 'Session file was not created') + + " Check there are commented imports in the session file + let commented_imports = filter(readfile('XDummySession.vim'), + \ {_, v -> v =~ '^# import autoload'}) + call assert_equal(4, len(commented_imports), + \ 'Session file does not contain the expected number of commented imports') + + " Check the session file mappings are operational + const ref_txt = 'Hello from a duplicated vim9 script!' + let test_sources =<< trim END + " Load session + source XDummySession.vim + " Execute mapping + normal dummy-test + " on my way + cq + END + call writefile(test_sources, 'XTest.vim', 'D') + " spawn a new Vim instance to load the session and execute the mapping + call system(GetVimCommand('XTest.vim')) + call assert_true(filereadable('XDummyOutput'), + \ 'Expected output file was not created by Vim9 auto script mapping') + defer delete('XDummyOutput') + call assert_equal([ref_txt], readfile('XDummyOutput')) + +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index 67a0fa6508..45b222e7ad 100644 --- a/src/version.c +++ b/src/version.c @@ -759,6 +759,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 703, /**/ 702, /**/