mirror of
https://github.com/neovim/neovim.git
synced 2025-10-17 07:16:09 +00:00
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)
daa2f36573
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>
This commit is contained in:
@@ -579,7 +579,7 @@ ArrayOf(String) nvim__get_runtime(Array pat, Boolean all, Dict(runtime) *opts, E
|
|||||||
if (source) {
|
if (source) {
|
||||||
for (size_t i = 0; i < res.size; i++) {
|
for (size_t i = 0; i < res.size; i++) {
|
||||||
String name = res.items[i].data.string;
|
String name = res.items[i].data.string;
|
||||||
(void)do_source(name.data, false, DOSO_NONE);
|
(void)do_source(name.data, false, DOSO_NONE, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -909,7 +909,7 @@ void ex_loadview(exarg_T *eap)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (do_source(fname, false, DOSO_NONE) == FAIL) {
|
if (do_source(fname, false, DOSO_NONE, NULL) == FAIL) {
|
||||||
semsg(_(e_notopen), fname);
|
semsg(_(e_notopen), fname);
|
||||||
}
|
}
|
||||||
xfree(fname);
|
xfree(fname);
|
||||||
|
@@ -2061,10 +2061,15 @@ void nlua_set_sctx(sctx_T *current)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
char *source_path = fix_fname(info->source + 1);
|
char *source_path = fix_fname(info->source + 1);
|
||||||
get_current_script_id(&source_path, current);
|
int sid = find_script_by_name(source_path);
|
||||||
xfree(source_path);
|
if (sid > 0) {
|
||||||
current->sc_lnum = info->currentline;
|
xfree(source_path);
|
||||||
|
} else {
|
||||||
|
new_script_item(source_path, &sid);
|
||||||
|
}
|
||||||
|
current->sc_sid = sid;
|
||||||
current->sc_seq = -1;
|
current->sc_seq = -1;
|
||||||
|
current->sc_lnum = info->currentline;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
xfree(info);
|
xfree(info);
|
||||||
|
@@ -1937,7 +1937,7 @@ static void do_system_initialization(void)
|
|||||||
dir_len += 1;
|
dir_len += 1;
|
||||||
}
|
}
|
||||||
memcpy(vimrc + dir_len, path_tail, sizeof(path_tail));
|
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(vimrc);
|
||||||
xfree(config_dirs);
|
xfree(config_dirs);
|
||||||
return;
|
return;
|
||||||
@@ -1949,7 +1949,7 @@ static void do_system_initialization(void)
|
|||||||
|
|
||||||
#ifdef SYS_VIMRC_FILE
|
#ifdef SYS_VIMRC_FILE
|
||||||
// Get system wide defaults, if the file name is defined.
|
// 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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1978,7 +1978,7 @@ static bool do_user_initialization(void)
|
|||||||
|
|
||||||
// init.lua
|
// init.lua
|
||||||
if (os_path_exists(init_lua_path)
|
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)) {
|
if (os_path_exists(user_vimrc)) {
|
||||||
semsg(_("E5422: Conflicting configs: \"%s\" \"%s\""), init_lua_path,
|
semsg(_("E5422: Conflicting configs: \"%s\" \"%s\""), init_lua_path,
|
||||||
user_vimrc);
|
user_vimrc);
|
||||||
@@ -1992,7 +1992,7 @@ static bool do_user_initialization(void)
|
|||||||
xfree(init_lua_path);
|
xfree(init_lua_path);
|
||||||
|
|
||||||
// init.vim
|
// 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;
|
do_exrc = p_exrc;
|
||||||
if (do_exrc) {
|
if (do_exrc) {
|
||||||
do_exrc = (path_full_compare(VIMRC_FILE, user_vimrc, false, true) != kEqualFiles);
|
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);
|
memmove(vimrc, dir, dir_len);
|
||||||
vimrc[dir_len] = PATHSEP;
|
vimrc[dir_len] = PATHSEP;
|
||||||
memmove(vimrc + dir_len + 1, path_tail, sizeof(path_tail));
|
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;
|
do_exrc = p_exrc;
|
||||||
if (do_exrc) {
|
if (do_exrc) {
|
||||||
do_exrc = (path_full_compare(VIMRC_FILE, vimrc, false, true) != kEqualFiles);
|
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")) {
|
|| strequal(parmp->use_vimrc, "NORC")) {
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
} else {
|
} 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);
|
semsg(_("E282: Cannot read from \"%s\""), parmp->use_vimrc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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.
|
/// The names of packages that once were loaded are remembered.
|
||||||
static garray_T ga_loaded = { 0, 0, sizeof(char *), 4, NULL };
|
static garray_T ga_loaded = { 0, 0, sizeof(char *), 4, NULL };
|
||||||
|
|
||||||
|
static int last_current_SID_seq = 0;
|
||||||
|
|
||||||
/// Initialize the execution stack.
|
/// Initialize the execution stack.
|
||||||
void estack_init(void)
|
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)
|
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
|
/// 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++) {
|
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);
|
FreeWild(num_files, files);
|
||||||
}
|
}
|
||||||
@@ -1701,7 +1703,7 @@ static void cmd_source(char *fname, exarg_T *eap)
|
|||||||
|| eap->cstack->cs_idx >= 0);
|
|| eap->cstack->cs_idx >= 0);
|
||||||
|
|
||||||
// ":source" read ex commands
|
// ":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);
|
semsg(_(e_notopen), fname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1954,9 +1956,12 @@ int do_source_str(const char *cmd, const char *traceback_name)
|
|||||||
/// @param fname
|
/// @param fname
|
||||||
/// @param check_other check for .vimrc and _vimrc
|
/// @param check_other check for .vimrc and _vimrc
|
||||||
/// @param is_vimrc DOSO_ value
|
/// @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
|
/// @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;
|
struct source_cookie cookie;
|
||||||
char *p;
|
char *p;
|
||||||
@@ -1982,6 +1987,15 @@ int do_source(char *fname, int check_other, int is_vimrc)
|
|||||||
goto theend;
|
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.
|
// Apply SourceCmd autocommands, they should get the file and source it.
|
||||||
if (has_autocmd(EVENT_SOURCECMD, fname_exp, NULL)
|
if (has_autocmd(EVENT_SOURCECMD, fname_exp, NULL)
|
||||||
&& apply_autocmds(EVENT_SOURCECMD, fname_exp, fname_exp,
|
&& 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);
|
save_funccal(&funccalp_entry);
|
||||||
|
|
||||||
const sctx_T save_current_sctx = current_sctx;
|
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.
|
// Keep the sourcing name/lnum, for recursive calls.
|
||||||
estack_push(ETYPE_SCRIPT, si->sn_name, 0);
|
estack_push(ETYPE_SCRIPT, si->sn_name, 0);
|
||||||
@@ -2192,7 +2223,7 @@ theend:
|
|||||||
|
|
||||||
/// Find an already loaded script "name".
|
/// Find an already loaded script "name".
|
||||||
/// If found returns its script ID. If not found returns -1.
|
/// 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);
|
assert(script_items.ga_len >= 0);
|
||||||
for (int sid = script_items.ga_len; sid > 0; sid--) {
|
for (int sid = script_items.ga_len; sid > 0; sid--) {
|
||||||
@@ -2209,35 +2240,6 @@ static int find_script_by_name(char *name)
|
|||||||
return -1;
|
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"
|
/// ":scriptnames"
|
||||||
void ex_scriptnames(exarg_T *eap)
|
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
|
// 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;
|
ret = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4026,7 +4026,7 @@ static void syn_cmd_include(exarg_T *eap, int syncing)
|
|||||||
prev_toplvl_grp = curwin->w_s->b_syn_topgrp;
|
prev_toplvl_grp = curwin->w_s->b_syn_topgrp;
|
||||||
curwin->w_s->b_syn_topgrp = sgl_id;
|
curwin->w_s->b_syn_topgrp = sgl_id;
|
||||||
if (source
|
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) {
|
: source_runtime(eap->arg, DIP_ALL) == FAIL) {
|
||||||
semsg(_(e_notopen), eap->arg);
|
semsg(_(e_notopen), eap->arg);
|
||||||
}
|
}
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
let g:loaded_sourced_vim += 1
|
let g:loaded_sourced_vim += 1
|
||||||
func! sourced#something()
|
func sourced#something()
|
||||||
endfunc
|
endfunc
|
||||||
|
call sourced#something()
|
||||||
|
Reference in New Issue
Block a user