mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
eval,functests: Reference all additional_* items created by ShaDa
This commit is contained in:
parent
0d15b35d49
commit
804e074096
138
src/nvim/eval.c
138
src/nvim/eval.c
@ -5541,6 +5541,7 @@ static int list_join(garray_T *const gap, list_T *const l,
|
||||
bool garbage_collect(void)
|
||||
{
|
||||
bool abort = false;
|
||||
#define ABORTING(func) abort = abort || func
|
||||
|
||||
// Only do this once.
|
||||
want_garbage_collect = false;
|
||||
@ -5559,45 +5560,104 @@ bool garbage_collect(void)
|
||||
// referenced through previous_funccal. This must be first, because if
|
||||
// the item is referenced elsewhere the funccal must not be freed.
|
||||
for (funccall_T *fc = previous_funccal; fc != NULL; fc = fc->caller) {
|
||||
abort = abort || set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID + 1, NULL);
|
||||
abort = abort || set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID + 1, NULL);
|
||||
ABORTING(set_ref_in_ht)(&fc->l_vars.dv_hashtab, copyID + 1, NULL);
|
||||
ABORTING(set_ref_in_ht)(&fc->l_avars.dv_hashtab, copyID + 1, NULL);
|
||||
}
|
||||
|
||||
// script-local variables
|
||||
for (int i = 1; i <= ga_scripts.ga_len; ++i) {
|
||||
abort = abort || set_ref_in_ht(&SCRIPT_VARS(i), copyID, NULL);
|
||||
ABORTING(set_ref_in_ht)(&SCRIPT_VARS(i), copyID, NULL);
|
||||
}
|
||||
|
||||
// buffer-local variables
|
||||
FOR_ALL_BUFFERS(buf) {
|
||||
abort = abort || set_ref_in_item(&buf->b_bufvar.di_tv, copyID, NULL, NULL);
|
||||
// buffer-local variables
|
||||
ABORTING(set_ref_in_item)(&buf->b_bufvar.di_tv, copyID, NULL, NULL);
|
||||
// buffer marks (ShaDa additional data)
|
||||
ABORTING(set_ref_in_fmark)(buf->b_last_cursor, copyID);
|
||||
ABORTING(set_ref_in_fmark)(buf->b_last_insert, copyID);
|
||||
ABORTING(set_ref_in_fmark)(buf->b_last_change, copyID);
|
||||
for (size_t i = 0; i < NMARKS; i++) {
|
||||
ABORTING(set_ref_in_fmark)(buf->b_namedm[i], copyID);
|
||||
}
|
||||
// buffer change list (ShaDa additional data)
|
||||
for (int i = 0; i < buf->b_changelistlen; i++) {
|
||||
ABORTING(set_ref_in_fmark)(buf->b_changelist[i], copyID);
|
||||
}
|
||||
// buffer ShaDa additional data
|
||||
ABORTING(set_ref_dict)(buf->additional_data, copyID);
|
||||
}
|
||||
|
||||
// window-local variables
|
||||
FOR_ALL_TAB_WINDOWS(tp, wp) {
|
||||
abort = abort || set_ref_in_item(&wp->w_winvar.di_tv, copyID, NULL, NULL);
|
||||
// window-local variables
|
||||
ABORTING(set_ref_in_item)(&wp->w_winvar.di_tv, copyID, NULL, NULL);
|
||||
// window jump list (ShaDa additional data)
|
||||
for (int i = 0; i < wp->w_jumplistlen; i++) {
|
||||
ABORTING(set_ref_in_fmark)(wp->w_jumplist[i].fmark, copyID);
|
||||
}
|
||||
}
|
||||
if (aucmd_win != NULL) {
|
||||
abort = abort ||
|
||||
set_ref_in_item(&aucmd_win->w_winvar.di_tv, copyID, NULL, NULL);
|
||||
ABORTING(set_ref_in_item)(&aucmd_win->w_winvar.di_tv, copyID, NULL, NULL);
|
||||
}
|
||||
|
||||
// registers (ShaDa additional data)
|
||||
{
|
||||
const void *reg_iter = NULL;
|
||||
do {
|
||||
yankreg_T reg;
|
||||
char name;
|
||||
reg_iter = op_register_iter(reg_iter, &name, ®);
|
||||
if (reg.y_array != NULL) {
|
||||
ABORTING(set_ref_dict)(reg.additional_data, copyID);
|
||||
}
|
||||
} while (reg_iter != NULL);
|
||||
}
|
||||
|
||||
// tabpage-local variables
|
||||
FOR_ALL_TABS(tp) {
|
||||
abort = abort || set_ref_in_item(&tp->tp_winvar.di_tv, copyID, NULL, NULL);
|
||||
ABORTING(set_ref_in_item)(&tp->tp_winvar.di_tv, copyID, NULL, NULL);
|
||||
}
|
||||
|
||||
// global variables
|
||||
abort = abort || set_ref_in_ht(&globvarht, copyID, NULL);
|
||||
ABORTING(set_ref_in_ht)(&globvarht, copyID, NULL);
|
||||
|
||||
// function-local variables
|
||||
for (funccall_T *fc = current_funccal; fc != NULL; fc = fc->caller) {
|
||||
abort = abort || set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID, NULL);
|
||||
abort = abort || set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID, NULL);
|
||||
ABORTING(set_ref_in_ht)(&fc->l_vars.dv_hashtab, copyID, NULL);
|
||||
ABORTING(set_ref_in_ht)(&fc->l_avars.dv_hashtab, copyID, NULL);
|
||||
}
|
||||
|
||||
// v: vars
|
||||
abort = abort || set_ref_in_ht(&vimvarht, copyID, NULL);
|
||||
ABORTING(set_ref_in_ht)(&vimvarht, copyID, NULL);
|
||||
|
||||
// history items (ShaDa additional elements)
|
||||
if (p_hi) {
|
||||
for (uint8_t i = 0; i < HIST_COUNT; i++) {
|
||||
const void *iter = NULL;
|
||||
do {
|
||||
histentry_T hist;
|
||||
iter = hist_iter(iter, i, false, &hist);
|
||||
if (hist.hisstr != NULL) {
|
||||
ABORTING(set_ref_list)(hist.additional_elements, copyID);
|
||||
}
|
||||
} while (iter != NULL);
|
||||
}
|
||||
}
|
||||
|
||||
// previously used search/substitute patterns (ShaDa additional data)
|
||||
{
|
||||
SearchPattern pat;
|
||||
get_search_pattern(&pat);
|
||||
ABORTING(set_ref_dict)(pat.additional_data, copyID);
|
||||
get_substitute_pattern(&pat);
|
||||
ABORTING(set_ref_dict)(pat.additional_data, copyID);
|
||||
}
|
||||
|
||||
// previously used replacement string
|
||||
{
|
||||
SubReplacementString sub;
|
||||
sub_get_replacement(&sub);
|
||||
ABORTING(set_ref_list)(sub.additional_elements, copyID);
|
||||
}
|
||||
|
||||
bool did_free = false;
|
||||
if (!abort) {
|
||||
@ -5626,6 +5686,7 @@ bool garbage_collect(void)
|
||||
verb_msg((char_u *)_(
|
||||
"Not enough memory to set references, garbage collection aborted!"));
|
||||
}
|
||||
#undef ABORTING
|
||||
return did_free;
|
||||
}
|
||||
|
||||
@ -5685,6 +5746,7 @@ static int free_unref_items(int copyID)
|
||||
///
|
||||
/// @returns true if setting references failed somehow.
|
||||
bool set_ref_in_ht(hashtab_T *ht, int copyID, list_stack_T **list_stack)
|
||||
FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
bool abort = false;
|
||||
ht_stack_T *ht_stack = NULL;
|
||||
@ -5727,6 +5789,7 @@ bool set_ref_in_ht(hashtab_T *ht, int copyID, list_stack_T **list_stack)
|
||||
///
|
||||
/// @returns true if setting references failed somehow.
|
||||
bool set_ref_in_list(list_T *l, int copyID, ht_stack_T **ht_stack)
|
||||
FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
bool abort = false;
|
||||
list_stack_T *list_stack = NULL;
|
||||
@ -5767,6 +5830,7 @@ bool set_ref_in_list(list_T *l, int copyID, ht_stack_T **ht_stack)
|
||||
/// @returns true if setting references failed somehow.
|
||||
bool set_ref_in_item(typval_T *tv, int copyID, ht_stack_T **ht_stack,
|
||||
list_stack_T **list_stack)
|
||||
FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
bool abort = false;
|
||||
|
||||
@ -5816,6 +5880,52 @@ bool set_ref_in_item(typval_T *tv, int copyID, ht_stack_T **ht_stack,
|
||||
return abort;
|
||||
}
|
||||
|
||||
/// Mark all lists and dicts referenced in given mark
|
||||
///
|
||||
/// @returns true if setting references failed somehow.
|
||||
static inline bool set_ref_in_fmark(fmark_T fm, int copyID)
|
||||
FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
if (fm.additional_data != NULL
|
||||
&& fm.additional_data->dv_copyID != copyID) {
|
||||
fm.additional_data->dv_copyID = copyID;
|
||||
return set_ref_in_ht(&fm.additional_data->dv_hashtab, copyID, NULL);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Mark all lists and dicts referenced in given list and the list itself
|
||||
///
|
||||
/// @returns true if setting references failed somehow.
|
||||
static inline bool set_ref_list(list_T *list, int copyID)
|
||||
FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
if (list != NULL) {
|
||||
typval_T tv = (typval_T) {
|
||||
.v_type = VAR_LIST,
|
||||
.vval = { .v_list = list }
|
||||
};
|
||||
return set_ref_in_item(&tv, copyID, NULL, NULL);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Mark all lists and dicts referenced in given dict and the dict itself
|
||||
///
|
||||
/// @returns true if setting references failed somehow.
|
||||
static inline bool set_ref_dict(dict_T *dict, int copyID)
|
||||
FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
if (dict != NULL) {
|
||||
typval_T tv = (typval_T) {
|
||||
.v_type = VAR_DICT,
|
||||
.vval = { .v_dict = dict }
|
||||
};
|
||||
return set_ref_in_item(&tv, copyID, NULL, NULL);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate an empty header for a dictionary.
|
||||
*/
|
||||
|
@ -5330,7 +5330,7 @@ static inline bool reg_empty(const yankreg_T *const reg)
|
||||
/// @return Pointer that needs to be passed to next `op_register_iter` call or
|
||||
/// NULL if iteration is over.
|
||||
const void *op_register_iter(const void *const iter, char *const name,
|
||||
yankreg_T *const reg)
|
||||
yankreg_T *const reg)
|
||||
FUNC_ATTR_PURE FUNC_ATTR_NONNULL_ARG(2, 3) FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
const yankreg_T *iter_reg = (iter == NULL
|
||||
|
@ -45,6 +45,11 @@ describe('ShaDa forward compatibility support code', function()
|
||||
end
|
||||
end
|
||||
eq(true, found)
|
||||
nvim_eval('garbagecollect(1)')
|
||||
nvim_eval('garbagecollect(1)')
|
||||
nvim_command('rshada! ' .. shada_fname)
|
||||
nvim_eval('garbagecollect(1)')
|
||||
nvim_eval('garbagecollect(1)')
|
||||
end)
|
||||
|
||||
it('works with s/search pattern item with BOOL unknown (sX) key value', function()
|
||||
@ -72,6 +77,11 @@ describe('ShaDa forward compatibility support code', function()
|
||||
end
|
||||
end
|
||||
eq(true, found)
|
||||
nvim_eval('garbagecollect(1)')
|
||||
nvim_eval('garbagecollect(1)')
|
||||
nvim_command('rshada!' .. shada_fname)
|
||||
nvim_eval('garbagecollect(1)')
|
||||
nvim_eval('garbagecollect(1)')
|
||||
end)
|
||||
|
||||
it('works with replacement item with BOOL additional value in list', function()
|
||||
@ -100,6 +110,11 @@ describe('ShaDa forward compatibility support code', function()
|
||||
end
|
||||
end
|
||||
eq(true, found)
|
||||
nvim_eval('garbagecollect(1)')
|
||||
nvim_eval('garbagecollect(1)')
|
||||
nvim_command('rshada!' .. shada_fname)
|
||||
nvim_eval('garbagecollect(1)')
|
||||
nvim_eval('garbagecollect(1)')
|
||||
end)
|
||||
|
||||
for _, v in ipairs({{name='global mark', mpack='\007\001\018\131\162mX\195\161f\196\006/a/b/c\161nA'},
|
||||
@ -138,6 +153,11 @@ describe('ShaDa forward compatibility support code', function()
|
||||
end
|
||||
end
|
||||
eq(false, found)
|
||||
nvim_eval('garbagecollect(1)')
|
||||
nvim_eval('garbagecollect(1)')
|
||||
nvim_command('rshada!' .. shada_fname)
|
||||
nvim_eval('garbagecollect(1)')
|
||||
nvim_eval('garbagecollect(1)')
|
||||
end)
|
||||
|
||||
if v.name == 'global mark' or v.name == 'local mark' then
|
||||
@ -175,6 +195,11 @@ describe('ShaDa forward compatibility support code', function()
|
||||
end
|
||||
end
|
||||
eq(0, found)
|
||||
nvim_eval('garbagecollect(1)')
|
||||
nvim_eval('garbagecollect(1)')
|
||||
nvim_command('rshada!' .. shada_fname)
|
||||
nvim_eval('garbagecollect(1)')
|
||||
nvim_eval('garbagecollect(1)')
|
||||
end)
|
||||
end
|
||||
end
|
||||
@ -202,6 +227,11 @@ describe('ShaDa forward compatibility support code', function()
|
||||
end
|
||||
end
|
||||
eq(false, found)
|
||||
nvim_eval('garbagecollect(1)')
|
||||
nvim_eval('garbagecollect(1)')
|
||||
nvim_command('rshada!' .. shada_fname)
|
||||
nvim_eval('garbagecollect(1)')
|
||||
nvim_eval('garbagecollect(1)')
|
||||
end)
|
||||
|
||||
it('works with register item with <C-a> name', function()
|
||||
@ -233,6 +263,11 @@ describe('ShaDa forward compatibility support code', function()
|
||||
end
|
||||
end
|
||||
eq(0, found)
|
||||
nvim_eval('garbagecollect(1)')
|
||||
nvim_eval('garbagecollect(1)')
|
||||
nvim_command('rshada!' .. shada_fname)
|
||||
nvim_eval('garbagecollect(1)')
|
||||
nvim_eval('garbagecollect(1)')
|
||||
end)
|
||||
|
||||
it('works with register item with type 10', function()
|
||||
@ -265,6 +300,11 @@ describe('ShaDa forward compatibility support code', function()
|
||||
end
|
||||
end
|
||||
eq(0, found)
|
||||
nvim_eval('garbagecollect(1)')
|
||||
nvim_eval('garbagecollect(1)')
|
||||
nvim_command('rshada!' .. shada_fname)
|
||||
nvim_eval('garbagecollect(1)')
|
||||
nvim_eval('garbagecollect(1)')
|
||||
end)
|
||||
|
||||
it('works with buffer list item with BOOL unknown (bX) key', function()
|
||||
@ -295,6 +335,11 @@ describe('ShaDa forward compatibility support code', function()
|
||||
end
|
||||
eq(false, found)
|
||||
nvim_command('bwipeout!')
|
||||
nvim_eval('garbagecollect(1)')
|
||||
nvim_eval('garbagecollect(1)')
|
||||
nvim_command('rshada!' .. shada_fname)
|
||||
nvim_eval('garbagecollect(1)')
|
||||
nvim_eval('garbagecollect(1)')
|
||||
end)
|
||||
|
||||
it('works with history item with BOOL additional value in list', function()
|
||||
@ -324,6 +369,11 @@ describe('ShaDa forward compatibility support code', function()
|
||||
end
|
||||
end
|
||||
eq(true, found)
|
||||
nvim_eval('garbagecollect(1)')
|
||||
nvim_eval('garbagecollect(1)')
|
||||
nvim_command('rshada!' .. shada_fname)
|
||||
nvim_eval('garbagecollect(1)')
|
||||
nvim_eval('garbagecollect(1)')
|
||||
end)
|
||||
|
||||
it('works with history item with type 10', function()
|
||||
@ -356,6 +406,11 @@ describe('ShaDa forward compatibility support code', function()
|
||||
end
|
||||
end
|
||||
eq(0, found)
|
||||
nvim_eval('garbagecollect(1)')
|
||||
nvim_eval('garbagecollect(1)')
|
||||
nvim_command('rshada!' .. shada_fname)
|
||||
nvim_eval('garbagecollect(1)')
|
||||
nvim_eval('garbagecollect(1)')
|
||||
end)
|
||||
|
||||
it('works with item with 100 type', function()
|
||||
@ -388,5 +443,10 @@ describe('ShaDa forward compatibility support code', function()
|
||||
end
|
||||
end
|
||||
eq(0, found)
|
||||
nvim_eval('garbagecollect(1)')
|
||||
nvim_eval('garbagecollect(1)')
|
||||
nvim_command('rshada!' .. shada_fname)
|
||||
nvim_eval('garbagecollect(1)')
|
||||
nvim_eval('garbagecollect(1)')
|
||||
end)
|
||||
end)
|
||||
|
Loading…
Reference in New Issue
Block a user