Skip to content

Commit 6feeea6

Browse files
committed
fix(ui): prevent window leaks across tabpages when rendering markdown
1 parent 33a6629 commit 6feeea6

2 files changed

Lines changed: 32 additions & 6 deletions

File tree

lua/opencode/ui/renderer/flush.lua

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -462,15 +462,24 @@ local function do_trigger_on_data_rendered()
462462
if not state.windows or not state.windows.output_buf or not state.windows.output_win then
463463
return
464464
end
465-
vim.b[state.windows.output_buf].opencode_markdown_namespace = output_window.markdown_namespace
465+
local output_buf = state.windows.output_buf
466+
local output_win = state.windows.output_win
467+
if
468+
not vim.api.nvim_buf_is_valid(output_buf)
469+
or not vim.api.nvim_win_is_valid(output_win)
470+
or vim.api.nvim_win_get_buf(output_win) ~= output_buf
471+
then
472+
return
473+
end
474+
vim.b[output_buf].opencode_markdown_namespace = output_window.markdown_namespace
466475
if cb_type == 'function' then
467-
pcall(config.ui.output.rendering.on_data_rendered, state.windows.output_buf, state.windows.output_win)
476+
pcall(config.ui.output.rendering.on_data_rendered, output_buf, output_win)
468477
elseif vim.fn.exists(':RenderMarkdown') > 0 then
469-
vim.api.nvim_buf_call(state.windows.output_buf, function()
478+
vim.api.nvim_win_call(output_win, function()
470479
vim.cmd(':RenderMarkdown buf_enable')
471480
end)
472481
elseif vim.fn.exists(':Markview') > 0 then
473-
vim.cmd(':Markview render ' .. state.windows.output_buf)
482+
vim.cmd(':Markview render ' .. output_buf)
474483
end
475484
end
476485

tests/unit/services_session_runtime_spec.lua

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -656,7 +656,7 @@ describe('opencode.services.session_runtime', function()
656656
end)
657657

658658
describe('markdown rendering metadata', function()
659-
it('stores the markdown namespace on the output buffer before rendering', function()
659+
it('renders markdown in the output window without leaking into the current tab', function()
660660
local output_window = require('opencode.ui.output_window')
661661
local buf = vim.api.nvim_create_buf(false, true)
662662
local win = vim.api.nvim_open_win(buf, false, {
@@ -667,10 +667,16 @@ describe('opencode.services.session_runtime', function()
667667
col = 0,
668668
style = 'minimal',
669669
})
670+
local output_tab = vim.api.nvim_win_get_tabpage(win)
670671

671672
state.ui.set_windows({ output_buf = buf, output_win = win })
672673
vim.api.nvim_buf_set_var(buf, 'opencode_markdown_namespace', 0)
673674

675+
vim.cmd('tabnew')
676+
local current_tab = vim.api.nvim_get_current_tabpage()
677+
local current_win = vim.api.nvim_get_current_win()
678+
local current_tab_windows = vim.api.nvim_tabpage_list_wins(current_tab)
679+
674680
local defer_stub = stub(vim, 'defer_fn').invokes(function(cb)
675681
cb()
676682
return 1
@@ -682,17 +688,28 @@ describe('opencode.services.session_runtime', function()
682688
end
683689
return original_exists(name)
684690
end
685-
local cmd_stub = stub(vim, 'cmd')
691+
local rendered_tab
692+
local rendered_win
693+
local cmd_stub = stub(vim, 'cmd').invokes(function()
694+
rendered_tab = vim.api.nvim_get_current_tabpage()
695+
rendered_win = vim.api.nvim_get_current_win()
696+
end)
686697

687698
flush.trigger_on_data_rendered()
688699

689700
assert.equals(output_window.markdown_namespace, vim.b[buf].opencode_markdown_namespace)
690701
assert.stub(cmd_stub).was_called_with(':RenderMarkdown buf_enable')
702+
assert.equals(output_tab, rendered_tab)
703+
assert.equals(win, rendered_win)
704+
assert.equals(current_tab, vim.api.nvim_get_current_tabpage())
705+
assert.equals(current_win, vim.api.nvim_get_current_win())
706+
assert.same(current_tab_windows, vim.api.nvim_tabpage_list_wins(current_tab))
691707

692708
cmd_stub:revert()
693709
defer_stub:revert()
694710
vim.fn.exists = original_exists
695711
state.ui.set_windows(nil)
712+
vim.cmd('tabclose')
696713
pcall(vim.api.nvim_win_close, win, true)
697714
pcall(vim.api.nvim_buf_delete, buf, { force = true })
698715
end)

0 commit comments

Comments
 (0)