diff options
author | zeertzjq <zeertzjq@outlook.com> | 2023-03-11 21:29:25 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-03-11 21:29:25 +0800 |
commit | 7dc9182cf0b27cbfb4e289db55dd7b02998ef5c8 (patch) | |
tree | 3eca706a2115138bbbb76ce562ba441c13bf659d | |
parent | 6d0c61d90d316473eee0729363e20bf06825b09b (diff) | |
download | rneovim-7dc9182cf0b27cbfb4e289db55dd7b02998ef5c8.tar.gz rneovim-7dc9182cf0b27cbfb4e289db55dd7b02998ef5c8.tar.bz2 rneovim-7dc9182cf0b27cbfb4e289db55dd7b02998ef5c8.zip |
vim-patch:8.2.1398: autoload script sourced twice if sourced directly (#22622)
Problem: Autoload script sourced twice if sourced directly.
Solution: Do not source an autoload script again. (issue vim/vim#6644)
https://github.com/vim/vim/commit/daa2f36573db3e1df7eb1fdbc3a09a2815644048
Cherry-pick ret_sid changes from patch 8.2.0149.
Use do_in_runtimepath() as that's what source_runtime() calls in Nvim.
Co-authored-by: Bram Moolenaar <Bram@vim.org>
-rw-r--r-- | src/nvim/api/vim.c | 2 | ||||
-rw-r--r-- | src/nvim/ex_session.c | 2 | ||||
-rw-r--r-- | src/nvim/lua/executor.c | 11 | ||||
-rw-r--r-- | src/nvim/main.c | 12 | ||||
-rw-r--r-- | src/nvim/runtime.c | 76 | ||||
-rw-r--r-- | src/nvim/syntax.c | 2 | ||||
-rw-r--r-- | test/old/testdir/sautest/autoload/sourced.vim | 3 |
7 files changed, 59 insertions, 49 deletions
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 0f27040fd3..315ccd13e6 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -579,7 +579,7 @@ ArrayOf(String) nvim__get_runtime(Array pat, Boolean all, Dict(runtime) *opts, E if (source) { for (size_t i = 0; i < res.size; i++) { String name = res.items[i].data.string; - (void)do_source(name.data, false, DOSO_NONE); + (void)do_source(name.data, false, DOSO_NONE, NULL); } } diff --git a/src/nvim/ex_session.c b/src/nvim/ex_session.c index 8e3e68d9b7..855a5f7538 100644 --- a/src/nvim/ex_session.c +++ b/src/nvim/ex_session.c @@ -909,7 +909,7 @@ void ex_loadview(exarg_T *eap) return; } - if (do_source(fname, false, DOSO_NONE) == FAIL) { + if (do_source(fname, false, DOSO_NONE, NULL) == FAIL) { semsg(_(e_notopen), fname); } xfree(fname); diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 078bc4fea9..11a02ea402 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -2061,10 +2061,15 @@ void nlua_set_sctx(sctx_T *current) break; } char *source_path = fix_fname(info->source + 1); - get_current_script_id(&source_path, current); - xfree(source_path); - current->sc_lnum = info->currentline; + int sid = find_script_by_name(source_path); + if (sid > 0) { + xfree(source_path); + } else { + new_script_item(source_path, &sid); + } + current->sc_sid = sid; current->sc_seq = -1; + current->sc_lnum = info->currentline; cleanup: xfree(info); diff --git a/src/nvim/main.c b/src/nvim/main.c index be1714b207..ea5f511fc6 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -1937,7 +1937,7 @@ static void do_system_initialization(void) dir_len += 1; } memcpy(vimrc + dir_len, path_tail, sizeof(path_tail)); - if (do_source(vimrc, false, DOSO_NONE) != FAIL) { + if (do_source(vimrc, false, DOSO_NONE, NULL) != FAIL) { xfree(vimrc); xfree(config_dirs); return; @@ -1949,7 +1949,7 @@ static void do_system_initialization(void) #ifdef SYS_VIMRC_FILE // Get system wide defaults, if the file name is defined. - (void)do_source(SYS_VIMRC_FILE, false, DOSO_NONE); + (void)do_source(SYS_VIMRC_FILE, false, DOSO_NONE, NULL); #endif } @@ -1978,7 +1978,7 @@ static bool do_user_initialization(void) // init.lua if (os_path_exists(init_lua_path) - && do_source(init_lua_path, true, DOSO_VIMRC)) { + && do_source(init_lua_path, true, DOSO_VIMRC, NULL)) { if (os_path_exists(user_vimrc)) { semsg(_("E5422: Conflicting configs: \"%s\" \"%s\""), init_lua_path, user_vimrc); @@ -1992,7 +1992,7 @@ static bool do_user_initialization(void) xfree(init_lua_path); // init.vim - if (do_source(user_vimrc, true, DOSO_VIMRC) != FAIL) { + if (do_source(user_vimrc, true, DOSO_VIMRC, NULL) != FAIL) { do_exrc = p_exrc; if (do_exrc) { do_exrc = (path_full_compare(VIMRC_FILE, user_vimrc, false, true) != kEqualFiles); @@ -2018,7 +2018,7 @@ static bool do_user_initialization(void) memmove(vimrc, dir, dir_len); vimrc[dir_len] = PATHSEP; memmove(vimrc + dir_len + 1, path_tail, sizeof(path_tail)); - if (do_source(vimrc, true, DOSO_VIMRC) != FAIL) { + if (do_source(vimrc, true, DOSO_VIMRC, NULL) != FAIL) { do_exrc = p_exrc; if (do_exrc) { do_exrc = (path_full_compare(VIMRC_FILE, vimrc, false, true) != kEqualFiles); @@ -2084,7 +2084,7 @@ static void source_startup_scripts(const mparm_T *const parmp) || strequal(parmp->use_vimrc, "NORC")) { // Do nothing. } else { - if (do_source(parmp->use_vimrc, false, DOSO_NONE) != OK) { + if (do_source(parmp->use_vimrc, false, DOSO_NONE, NULL) != OK) { semsg(_("E282: Cannot read from \"%s\""), parmp->use_vimrc); } } diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c index c316b61082..c9667d58ed 100644 --- a/src/nvim/runtime.c +++ b/src/nvim/runtime.c @@ -78,6 +78,8 @@ garray_T script_items = { 0, 0, sizeof(scriptitem_T *), 20, NULL }; /// The names of packages that once were loaded are remembered. static garray_T ga_loaded = { 0, 0, sizeof(char *), 4, NULL }; +static int last_current_SID_seq = 0; + /// Initialize the execution stack. void estack_init(void) { @@ -266,7 +268,7 @@ void set_context_in_runtime_cmd(expand_T *xp, const char *arg) static void source_callback(char *fname, void *cookie) { - (void)do_source(fname, false, DOSO_NONE); + (void)do_source(fname, false, DOSO_NONE, cookie); } /// Find the file "name" in all directories in "path" and invoke @@ -855,7 +857,7 @@ static void source_all_matches(char *pat) } for (int i = 0; i < num_files; i++) { - (void)do_source(files[i], false, DOSO_NONE); + (void)do_source(files[i], false, DOSO_NONE, NULL); } FreeWild(num_files, files); } @@ -1701,7 +1703,7 @@ static void cmd_source(char *fname, exarg_T *eap) || eap->cstack->cs_idx >= 0); // ":source" read ex commands - } else if (do_source(fname, false, DOSO_NONE) == FAIL) { + } else if (do_source(fname, false, DOSO_NONE, NULL) == FAIL) { semsg(_(e_notopen), fname); } } @@ -1954,9 +1956,12 @@ int do_source_str(const char *cmd, const char *traceback_name) /// @param fname /// @param check_other check for .vimrc and _vimrc /// @param is_vimrc DOSO_ value +/// @param ret_sid if not NULL and we loaded the script before, don't load it again /// /// @return FAIL if file could not be opened, OK otherwise -int do_source(char *fname, int check_other, int is_vimrc) +/// +/// If a scriptitem_T was found or created "*ret_sid" is set to the SID. +int do_source(char *fname, int check_other, int is_vimrc, int *ret_sid) { struct source_cookie cookie; char *p; @@ -1982,6 +1987,15 @@ int do_source(char *fname, int check_other, int is_vimrc) goto theend; } + // See if we loaded this script before. + int sid = find_script_by_name(fname_exp); + if (sid > 0 && ret_sid != NULL) { + // Already loaded and no need to load again, return here. + *ret_sid = sid; + retval = OK; + goto theend; + } + // Apply SourceCmd autocommands, they should get the file and source it. if (has_autocmd(EVENT_SOURCECMD, fname_exp, NULL) && apply_autocmds(EVENT_SOURCECMD, fname_exp, fname_exp, @@ -2080,7 +2094,24 @@ int do_source(char *fname, int check_other, int is_vimrc) save_funccal(&funccalp_entry); const sctx_T save_current_sctx = current_sctx; - si = get_current_script_id(&fname_exp, ¤t_sctx); + + current_sctx.sc_lnum = 0; + + // Always use a new sequence number. + current_sctx.sc_seq = ++last_current_SID_seq; + + if (sid > 0) { + // loading the same script again + si = SCRIPT_ITEM(sid); + } else { + // It's new, generate a new SID. + si = new_script_item(fname_exp, &sid); + fname_exp = xstrdup(si->sn_name); // used for autocmd + if (ret_sid != NULL) { + *ret_sid = sid; + } + } + current_sctx.sc_sid = sid; // Keep the sourcing name/lnum, for recursive calls. estack_push(ETYPE_SCRIPT, si->sn_name, 0); @@ -2192,7 +2223,7 @@ theend: /// Find an already loaded script "name". /// If found returns its script ID. If not found returns -1. -static int find_script_by_name(char *name) +int find_script_by_name(char *name) { assert(script_items.ga_len >= 0); for (int sid = script_items.ga_len; sid > 0; sid--) { @@ -2209,35 +2240,6 @@ static int find_script_by_name(char *name) return -1; } -/// Check if fname was sourced before to finds its SID. -/// If it's new, generate a new SID. -/// -/// @param[in,out] fnamep pointer to file path of script -/// @param[out] ret_sctx sctx of this script -scriptitem_T *get_current_script_id(char **fnamep, sctx_T *ret_sctx) -{ - static int last_current_SID_seq = 0; - - scriptitem_T *si; - int sid = find_script_by_name(*fnamep); - if (sid > 0) { - si = SCRIPT_ITEM(sid); - } else { - si = new_script_item(*fnamep, &sid); - *fnamep = xstrdup(si->sn_name); - } - - sctx_T script_sctx = { .sc_seq = ++last_current_SID_seq, - .sc_lnum = 0, - .sc_sid = sid }; - - if (ret_sctx != NULL) { - *ret_sctx = script_sctx; - } - - return si; -} - /// ":scriptnames" void ex_scriptnames(exarg_T *eap) { @@ -2704,7 +2706,9 @@ bool script_autoload(const char *const name, const size_t name_len, const bool r } // Try loading the package from $VIMRUNTIME/autoload/<name>.vim - if (source_runtime(scriptname, 0) == OK) { + // Use "ret_sid" to avoid loading the same script again. + int ret_sid; + if (do_in_runtimepath(scriptname, 0, source_callback, &ret_sid) == OK) { ret = true; } } diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index d4161b9ca2..14fef19399 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -4026,7 +4026,7 @@ static void syn_cmd_include(exarg_T *eap, int syncing) prev_toplvl_grp = curwin->w_s->b_syn_topgrp; curwin->w_s->b_syn_topgrp = sgl_id; if (source - ? do_source(eap->arg, false, DOSO_NONE) == FAIL + ? do_source(eap->arg, false, DOSO_NONE, NULL) == FAIL : source_runtime(eap->arg, DIP_ALL) == FAIL) { semsg(_(e_notopen), eap->arg); } diff --git a/test/old/testdir/sautest/autoload/sourced.vim b/test/old/testdir/sautest/autoload/sourced.vim index f69f00cb53..aac96b11ce 100644 --- a/test/old/testdir/sautest/autoload/sourced.vim +++ b/test/old/testdir/sautest/autoload/sourced.vim @@ -1,3 +1,4 @@ let g:loaded_sourced_vim += 1 -func! sourced#something() +func sourced#something() endfunc +call sourced#something() |