buf = NULL;
if ((flags & BLN_CURBUF) && curbuf_reusable())
{
+ bufref_T bufref;
+
buf = curbuf;
+ set_bufref(&bufref, buf);
trigger_undo_ftplugin(buf, curwin);
// It's like this buffer is deleted. Watch out for autocommands that
// change curbuf! If that happens, allocate a new buffer anyway.
buf_freeall(buf, BFA_WIPE | BFA_DEL);
- if (buf != curbuf) // autocommands deleted the buffer!
- return NULL;
#ifdef FEAT_EVAL
if (aborting()) // autocmds may abort script processing
{
return NULL;
}
#endif
+ if (!bufref_valid(&bufref))
+ buf = NULL; // buf was deleted; allocate a new buffer
}
if (buf != curbuf || curbuf == NULL)
{
%bw!
endfunc
+func Test_reuse_curbuf_leak()
+ new bar
+ let s:bar_buf = bufnr()
+ augroup testing
+ autocmd!
+ autocmd BufDelete * ++once let s:triggered = 1 | execute s:bar_buf 'buffer'
+ augroup END
+ enew
+ let empty_buf = bufnr()
+
+ " Old curbuf should be reused, firing BufDelete. As BufDelete changes curbuf,
+ " reusing the buffer would fail and leak the ffname.
+ edit foo
+ call assert_equal(1, s:triggered)
+ " Wasn't reused because the buffer changed, but buffer "foo" is still created.
+ call assert_equal(1, bufexists(empty_buf))
+ call assert_notequal(empty_buf, bufnr())
+ call assert_equal('foo', bufname())
+ call assert_equal('bar', bufname(s:bar_buf))
+
+ unlet! s:bar_buf s:triggered
+ call CleanUpTestAuGroup()
+ %bw!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab