0
0
mirror of https://github.com/vim/vim.git synced 2025-10-03 05:14:07 -04:00

patch 8.2.2223: Vim9: Reloading marks a :def function as deleted

Problem:    Vim9: Reloading marks a :def function as deleted.
Solution:   Clear the function contents but keep the index.
This commit is contained in:
Bram Moolenaar
2020-12-26 17:43:08 +01:00
parent 2b32700dab
commit cdc40c43f1
5 changed files with 18 additions and 38 deletions

View File

@@ -219,23 +219,6 @@ some point when loaded again. E.g. when a buffer local option is set: >
def g:SomeFunc() def g:SomeFunc()
.... ....
There is one gotcha: If a compiled function is replaced and it is called from
another compiled function that is not replaced, it will try to call the
function from before it was replaced, which no longer exists. This doesn't
work: >
vimscript noclear
def ReplaceMe()
echo 'function redefined every time'
enddef
if exists('s:loaded') | finish | endif
var s:loaded = true
def NotReplaced()
ReplaceMe() # Error if ReplaceMe() was redefined
enddef
Variable declarations with :var, :final and :const ~ Variable declarations with :var, :final and :const ~
*vim9-declaration* *:var* *vim9-declaration* *:var*

View File

@@ -1174,10 +1174,7 @@ def Test_vim9script_reload_noclear()
var s:notReloaded = 'yes' var s:notReloaded = 'yes'
s:reloaded = 'first' s:reloaded = 'first'
def g:Values(): list<string> def g:Values(): list<string>
return [s:reloaded, s:notReloaded, Once()] return [s:reloaded, s:notReloaded, Again(), Once()]
enddef
def g:CallAgain(): string
return Again()
enddef enddef
def Once(): string def Once(): string
@@ -1188,20 +1185,16 @@ def Test_vim9script_reload_noclear()
g:loadCount = 0 g:loadCount = 0
source XReloaded source XReloaded
assert_equal(1, g:loadCount) assert_equal(1, g:loadCount)
assert_equal(['first', 'yes', 'once'], g:Values()) assert_equal(['first', 'yes', 'again', 'once'], g:Values())
assert_equal('again', g:CallAgain())
source XReloaded source XReloaded
assert_equal(2, g:loadCount) assert_equal(2, g:loadCount)
assert_equal(['init', 'yes', 'once'], g:Values()) assert_equal(['init', 'yes', 'again', 'once'], g:Values())
assert_fails('call g:CallAgain()', 'E933:')
source XReloaded source XReloaded
assert_equal(3, g:loadCount) assert_equal(3, g:loadCount)
assert_equal(['init', 'yes', 'once'], g:Values()) assert_equal(['init', 'yes', 'again', 'once'], g:Values())
assert_fails('call g:CallAgain()', 'E933:')
delete('Xreloaded') delete('Xreloaded')
delfunc g:Values delfunc g:Values
delfunc g:CallAgain
unlet g:loadCount unlet g:loadCount
enddef enddef

View File

@@ -3628,7 +3628,7 @@ define_function(exarg_T *eap, char_u *name_arg)
fp->uf_profiling = FALSE; fp->uf_profiling = FALSE;
fp->uf_prof_initialized = FALSE; fp->uf_prof_initialized = FALSE;
#endif #endif
unlink_def_function(fp); fp->uf_def_status = UF_NOT_COMPILED;
} }
} }
} }
@@ -3694,8 +3694,6 @@ define_function(exarg_T *eap, char_u *name_arg)
fp = alloc_clear(offsetof(ufunc_T, uf_name) + STRLEN(name) + 1); fp = alloc_clear(offsetof(ufunc_T, uf_name) + STRLEN(name) + 1);
if (fp == NULL) if (fp == NULL)
goto erret; goto erret;
fp->uf_def_status = eap->cmdidx == CMD_def ? UF_TO_BE_COMPILED
: UF_NOT_COMPILED;
if (fudi.fd_dict != NULL) if (fudi.fd_dict != NULL)
{ {

View File

@@ -750,6 +750,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
2223,
/**/ /**/
2222, 2222,
/**/ /**/

View File

@@ -145,7 +145,7 @@ struct cctx_S {
int ctx_has_cmdmod; // ISN_CMDMOD was generated int ctx_has_cmdmod; // ISN_CMDMOD was generated
}; };
static void delete_def_function_contents(dfunc_T *dfunc); static void delete_def_function_contents(dfunc_T *dfunc, int mark_deleted);
/* /*
* Lookup variable "name" in the local scope and return it in "lvar". * Lookup variable "name" in the local scope and return it in "lvar".
@@ -7498,12 +7498,12 @@ compile_def_function(ufunc_T *ufunc, int check_return_type, cctx_T *outer_cctx)
int new_def_function = FALSE; int new_def_function = FALSE;
// When using a function that was compiled before: Free old instructions. // When using a function that was compiled before: Free old instructions.
// Otherwise add a new entry in "def_functions". // The index is reused. Otherwise add a new entry in "def_functions".
if (ufunc->uf_dfunc_idx > 0) if (ufunc->uf_dfunc_idx > 0)
{ {
dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
+ ufunc->uf_dfunc_idx; + ufunc->uf_dfunc_idx;
delete_def_function_contents(dfunc); delete_def_function_contents(dfunc, FALSE);
} }
else else
{ {
@@ -8344,7 +8344,7 @@ delete_instr(isn_T *isn)
* Free all instructions for "dfunc" except df_name. * Free all instructions for "dfunc" except df_name.
*/ */
static void static void
delete_def_function_contents(dfunc_T *dfunc) delete_def_function_contents(dfunc_T *dfunc, int mark_deleted)
{ {
int idx; int idx;
@@ -8355,9 +8355,13 @@ delete_def_function_contents(dfunc_T *dfunc)
for (idx = 0; idx < dfunc->df_instr_count; ++idx) for (idx = 0; idx < dfunc->df_instr_count; ++idx)
delete_instr(dfunc->df_instr + idx); delete_instr(dfunc->df_instr + idx);
VIM_CLEAR(dfunc->df_instr); VIM_CLEAR(dfunc->df_instr);
dfunc->df_instr = NULL;
} }
if (mark_deleted)
dfunc->df_deleted = TRUE; dfunc->df_deleted = TRUE;
if (dfunc->df_ufunc != NULL)
dfunc->df_ufunc->uf_def_status = UF_NOT_COMPILED;
} }
/* /*
@@ -8374,7 +8378,7 @@ unlink_def_function(ufunc_T *ufunc)
+ ufunc->uf_dfunc_idx; + ufunc->uf_dfunc_idx;
if (--dfunc->df_refcount <= 0) if (--dfunc->df_refcount <= 0)
delete_def_function_contents(dfunc); delete_def_function_contents(dfunc, TRUE);
ufunc->uf_def_status = UF_NOT_COMPILED; ufunc->uf_def_status = UF_NOT_COMPILED;
ufunc->uf_dfunc_idx = 0; ufunc->uf_dfunc_idx = 0;
if (dfunc->df_ufunc == ufunc) if (dfunc->df_ufunc == ufunc)
@@ -8410,7 +8414,7 @@ free_def_functions(void)
{ {
dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + idx; dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + idx;
delete_def_function_contents(dfunc); delete_def_function_contents(dfunc, TRUE);
vim_free(dfunc->df_name); vim_free(dfunc->df_name);
} }