fix(window): making float with title/footer non-float leaks memory (#30551)

This commit is contained in:
zeertzjq
2024-09-28 10:21:06 +08:00
committed by GitHub
parent 0f067cd34d
commit 4f9311b759
5 changed files with 60 additions and 27 deletions

View File

@ -448,7 +448,7 @@ void nvim_win_set_config(Window window, Dict(win_config) *config, Error *err)
}
}
}
win->w_config = fconfig;
merge_win_config(&win->w_config, fconfig);
// If there's no "vertical" or "split" set, or if "split" is unchanged,
// then we can just change the size of the window.
@ -1312,12 +1312,7 @@ static bool parse_win_config(win_T *wp, Dict(win_config) *config, WinConfig *fco
return true;
fail:
if (wp == NULL || fconfig->title_chunks.items != wp->w_config.title_chunks.items) {
clear_virttext(&fconfig->title_chunks);
}
if (wp == NULL || fconfig->footer_chunks.items != wp->w_config.footer_chunks.items) {
clear_virttext(&fconfig->footer_chunks);
}
merge_win_config(fconfig, wp != NULL ? wp->w_config : WIN_CONFIG_INIT);
return false;
#undef HAS_KEY_X
}

View File

@ -798,6 +798,19 @@ int win_fdccol_count(win_T *wp)
return fdc[0] - '0';
}
/// Merges two window configs, freeing replaced fields if necessary.
void merge_win_config(WinConfig *dst, const WinConfig src)
FUNC_ATTR_NONNULL_ALL
{
if (dst->title_chunks.items != src.title_chunks.items) {
clear_virttext(&dst->title_chunks);
}
if (dst->footer_chunks.items != src.footer_chunks.items) {
clear_virttext(&dst->footer_chunks);
}
*dst = src;
}
void ui_ext_win_position(win_T *wp, bool validate)
{
wp->w_pos_changed = false;
@ -1288,7 +1301,7 @@ win_T *win_split_ins(int size, int flags, win_T *new_wp, int dir, frame_T *to_fl
new_frame(wp);
// non-floating window doesn't store float config or have a border.
wp->w_config = WIN_CONFIG_INIT;
merge_win_config(&wp->w_config, WIN_CONFIG_INIT);
CLEAR_FIELD(wp->w_border_adj);
}

View File

@ -203,13 +203,7 @@ void win_config_float(win_T *wp, WinConfig fconfig)
wp->w_config.border_hl_ids,
sizeof fconfig.border_hl_ids) != 0);
if (fconfig.title_chunks.items != wp->w_config.title_chunks.items) {
clear_virttext(&wp->w_config.title_chunks);
}
if (fconfig.footer_chunks.items != wp->w_config.footer_chunks.items) {
clear_virttext(&wp->w_config.footer_chunks);
}
wp->w_config = fconfig;
merge_win_config(&wp->w_config, fconfig);
bool has_border = wp->w_floating && wp->w_config.border;
for (int i = 0; i < 4; i++) {

View File

@ -1815,10 +1815,10 @@ describe('API/win', function()
'title/footer must be string or array',
pcall_err(api.nvim_open_win, 0, false, {
relative = 'editor',
row = 5,
col = 5,
height = 5,
width = 5,
row = 10,
col = 10,
height = 10,
width = 10,
border = 'single',
title = { { 'TITLE' } },
footer = 0,
@ -1831,10 +1831,10 @@ describe('API/win', function()
'title/footer must be string or array',
pcall_err(api.nvim_open_win, 0, false, {
relative = 'editor',
row = 5,
col = 5,
height = 5,
width = 5,
row = 10,
col = 10,
height = 10,
width = 10,
border = 'single',
title = 0,
footer = { { 'FOOTER' } },
@ -2840,10 +2840,10 @@ describe('API/win', function()
before_each(function()
win = api.nvim_open_win(0, false, {
relative = 'editor',
row = 5,
col = 5,
height = 5,
width = 5,
row = 10,
col = 10,
height = 10,
width = 10,
border = 'single',
title = { { 'OLD_TITLE' } },
footer = { { 'OLD_FOOTER' } },

View File

@ -2562,6 +2562,37 @@ describe('float window', function()
end
eq({{"🦄", ""}, {"BB", {"B0", "B1", ""}}}, api.nvim_win_get_config(win).title)
eq({{"🦄", ""}, {"BB", {"B0", "B1", ""}}}, api.nvim_win_get_config(win).footer)
-- making it a split should not leak memory
api.nvim_win_set_config(win, { vertical = true })
if multigrid then
screen:expect{grid=[[
## grid 1
[4:--------------------]{5:│}[2:-------------------]|*5
{5:[No Name] [+] }{4:[No Name] }|
[3:----------------------------------------]|
## grid 2
^ |
{0:~ }|*4
## grid 3
|
## grid 4
halloj! |
BORDAA |
{0:~ }|*3
]], win_viewport={
[2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
[4] = {win = 1001, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
halloj! {5:│}^ |
BORDAA {5:│}{0:~ }|
{0:~ }{5:│}{0:~ }|*3
{5:[No Name] [+] }{4:[No Name] }|
|
]]}
end
end)
it('terminates border on edge of viewport when window extends past viewport', function()