aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2024-09-28 10:21:06 +0800
committerGitHub <noreply@github.com>2024-09-28 10:21:06 +0800
commit4f9311b759fff0371433fb5b5355fccb001d54e7 (patch)
tree616920f079d5be9b7ac0c2e07fda93eb8913654c
parent0f067cd34d09b38f9aaf2e1732d825e89b573077 (diff)
downloadrneovim-4f9311b759fff0371433fb5b5355fccb001d54e7.tar.gz
rneovim-4f9311b759fff0371433fb5b5355fccb001d54e7.tar.bz2
rneovim-4f9311b759fff0371433fb5b5355fccb001d54e7.zip
fix(window): making float with title/footer non-float leaks memory (#30551)
-rw-r--r--src/nvim/api/win_config.c9
-rw-r--r--src/nvim/window.c15
-rw-r--r--src/nvim/winfloat.c8
-rw-r--r--test/functional/api/window_spec.lua24
-rw-r--r--test/functional/ui/float_spec.lua31
5 files changed, 60 insertions, 27 deletions
diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c
index b006f86a76..f63fdc5381 100644
--- a/src/nvim/api/win_config.c
+++ b/src/nvim/api/win_config.c
@@ -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
}
diff --git a/src/nvim/window.c b/src/nvim/window.c
index f7d5ee92cd..d3280a3478 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -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);
}
diff --git a/src/nvim/winfloat.c b/src/nvim/winfloat.c
index 0a90f638f3..f7e9128599 100644
--- a/src/nvim/winfloat.c
+++ b/src/nvim/winfloat.c
@@ -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++) {
diff --git a/test/functional/api/window_spec.lua b/test/functional/api/window_spec.lua
index 135b24fa5f..5ce93f9e04 100644
--- a/test/functional/api/window_spec.lua
+++ b/test/functional/api/window_spec.lua
@@ -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' } },
diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua
index 52b46d0ecb..b2ed5f5a5f 100644
--- a/test/functional/ui/float_spec.lua
+++ b/test/functional/ui/float_spec.lua
@@ -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()