/*
* Close popup "wp" and invoke any close callback for it.
+ * Careful: callback function might have freed the popup window already
*/
static void
popup_close_and_callback(win_T *wp, typval_T *arg)
{
- int id = wp->w_id;
+ int id;
+
+ if (!win_valid(wp))
+ return;
+
+ id = wp->w_id;
#ifdef FEAT_TERMINAL
if (wp == curwin && curbuf->b_term != NULL)
call assert_fails('call win_execute(winid, "wincmd t")', 'E994:')
call assert_fails('call win_execute(winid, "wincmd b")', 'E994:')
call popup_clear()
+ bw filename
endfunc
func Test_popup_with_wrap()
call StopVimInTerminal(buf)
endfunc
+func Test_popupwin_callback_closes_popupwin()
+ " Test that the command line is properly cleared for overlong
+ " popup windows and using popup_hide()
+ CheckRunVimInTerminal
+
+ let lines =<< trim END
+ vim9script
+
+ def Filter(winid: number, keyCode: string): bool
+ popup_close(winid)
+ colorscheme missing
+ return true
+ enddef
+
+ def Popup(): number
+ return popup_create('', {
+ border: [2, 2, 2, 2],
+ close: 'button',
+ filter: Filter,
+ })
+ enddef
+ nnoremap gs <scriptcmd>Popup()<cr>
+ END
+ call writefile(lines, 'XtestPopup1_win', 'D')
+ let buf = RunVimInTerminal('-S XtestPopup1_win', #{rows: 10})
+ let i = 0
+ while i <= 10
+ call term_sendkeys(buf, "gs")
+ call term_wait(buf)
+ " this was causing a use-after-free
+ call term_sendkeys(buf, "q")
+ " clear the hit-enter prompt
+ call term_sendkeys(buf, "\<cr>")
+ call term_wait(buf)
+ let i += 1
+ endwhile
+ call term_sendkeys(buf, ":echo 'Done'\<cr>")
+ call WaitForAssert({-> assert_match('Done', term_getline(buf, 10))})
+
+ " clean up
+ call StopVimInTerminal(buf)
+endfunc
+
" vim: shiftwidth=2 sts=2