patch 9.1.0556: :bwipe doesn't remove file from jumplist of other tabpages

Commit: 
https://github.com/vim/vim/commit/2e7d89b39883b0cfd3e615b02bd55186e00fb7ce
Author: zeertzjq <zeert...@outlook.com>
Date:   Wed Jul 10 19:36:36 2024 +0200

    patch 9.1.0556: :bwipe doesn't remove file from jumplist of other tabpages
    
    Problem:  :bwipe doesn't remove file from jumplist and tagstack of other
              tabpages. Time complexity of mark_forget_file() is O(n^2) when
              removing all entries (after v9.1.0554)
    Solution: Use FOR_ALL_TAB_WINDOWS().  Start the loops over the arrays
              from the end instead of the start (zeertzjq)
    
    closes: #15199
    
    Signed-off-by: zeertzjq <zeert...@outlook.com>
    Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/src/buffer.c b/src/buffer.c
index 28967342d..82957f986 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -750,13 +750,14 @@ aucmd_abort:
      */
     if (wipe_buf)
     {
-       win_T   *wp;
+       tabpage_T       *tp;
+       win_T           *wp;
 
        // Do not wipe out the buffer if it is used in a window.
        if (buf->b_nwindows > 0)
            return FALSE;
 
-       FOR_ALL_WINDOWS(wp)
+       FOR_ALL_TAB_WINDOWS(tp, wp)
            mark_forget_file(wp, buf->b_fnum);
 
        if (action == DOBUF_WIPE_REUSE)
diff --git a/src/mark.c b/src/mark.c
index 85f7b68e2..9f6a9ccf5 100644
--- a/src/mark.c
+++ b/src/mark.c
@@ -138,28 +138,26 @@ mark_forget_file(win_T *wp, int fnum)
 {
     int                i;
 
-    for (i = 0; i < wp->w_jumplistlen; ++i)
+    for (i = wp->w_jumplistlen - 1; i >= 0; --i)
        if (wp->w_jumplist[i].fmark.fnum == fnum)
        {
            vim_free(wp->w_jumplist[i].fname);
-           mch_memmove(&wp->w_jumplist[i], &wp->w_jumplist[i + 1],
-                   (wp->w_jumplistlen - i - 1) * sizeof(xfmark_T));
            if (wp->w_jumplistidx > i)
                --wp->w_jumplistidx;
            --wp->w_jumplistlen;
-           --i;
+           mch_memmove(&wp->w_jumplist[i], &wp->w_jumplist[i + 1],
+                       (wp->w_jumplistlen - i) * sizeof(wp->w_jumplist[i]));
        }
 
-    for (i = 0; i < wp->w_tagstacklen; i++)
+    for (i = wp->w_tagstacklen - 1; i >= 0; --i)
        if (wp->w_tagstack[i].fmark.fnum == fnum)
        {
            tagstack_clear_entry(&wp->w_tagstack[i]);
-           mch_memmove(&wp->w_tagstack[i], &wp->w_tagstack[i + 1],
-                   (wp->w_tagstacklen - i - 1) * sizeof(taggy_T));
            if (wp->w_tagstackidx > i)
                --wp->w_tagstackidx;
            --wp->w_tagstacklen;
-           --i;
+           mch_memmove(&wp->w_tagstack[i], &wp->w_tagstack[i + 1],
+                       (wp->w_tagstacklen - i) * sizeof(wp->w_tagstack[i]));
        }
 }
 
diff --git a/src/testdir/test_jumplist.vim b/src/testdir/test_jumplist.vim
index 0f43a8c6e..4b9fcee78 100644
--- a/src/testdir/test_jumplist.vim
+++ b/src/testdir/test_jumplist.vim
@@ -59,7 +59,7 @@ func Test_getjumplist()
   call assert_equal(4, l[1])
 endfunc
 
-func Test_jumplist_invalid()
+func Test_jumplist_wipe_buf()
   new
   clearjumps
   " Put some random text and fill the jump list.
@@ -72,6 +72,50 @@ func Test_jumplist_invalid()
   call assert_equal([[], 0], getjumplist())
   let jumps = execute(':jumps')
   call assert_equal('>', jumps[-1:])
+
+  " Put some random text and fill the jump list.
+  call setline(1, ['foo', 'bar', 'baz'])
+  setl bufhidden=hide
+
+  " References to wiped buffer are deleted with multiple tabpages.
+  let [w1, t1] = [win_getid(), tabpagenr()]
+  clearjumps
+  normal G
+  normal gg
+  enew
+
+  split XXJumpListBuffer
+  let [w2, t2] = [win_getid(), tabpagenr()]
+  clearjumps
+  normal G
+  normal gg
+  enew
+
+  tabnew XXJumpListBuffer
+  let [w3, t3] = [win_getid(), tabpagenr()]
+  clearjumps
+  normal G
+  normal gg
+  enew
+
+  split XXJumpListBuffer
+  let [w4, t4] = [win_getid(), tabpagenr()]
+  clearjumps
+  normal G
+  normal gg
+  enew
+
+  for [w, t] in [[w1, t1], [w2, t2], [w3, t3], [w4, t4]]
+    call assert_equal(2, len(getjumplist(w, t)[0]))
+  endfor
+
+  bwipe! XXJumpListBuffer
+
+  for [w, t] in [[w1, t1], [w2, t2], [w3, t3], [w4, t4]]
+    call assert_equal(0, len(getjumplist(w, t)[0]))
+  endfor
+
+  %bwipe!
 endfunc
 
 " Test for '' mark in an empty buffer
diff --git a/src/testdir/test_tagjump.vim b/src/testdir/test_tagjump.vim
index 71237855c..c2419375a 100644
--- a/src/testdir/test_tagjump.vim
+++ b/src/testdir/test_tagjump.vim
@@ -975,8 +975,46 @@ func Test_tag_stack()
   call assert_equal(0, t.length)
   call assert_equal(1, t.curidx)
 
+  " References to wiped buffer are deleted with multiple tabpages.
+  let w1 = win_getid()
+  call settagstack(1, {'items' : []})
+  for i in range(10, 20) | edit Xtest | exe "tag var" .. i | endfor
+  enew
+
+  new
+  let w2 = win_getid()
+  call settagstack(1, {'items' : []})
+  for i in range(10, 20) | edit Xtest | exe "tag var" .. i | endfor
+  enew
+
+  tabnew
+  let w3 = win_getid()
+  call settagstack(1, {'items' : []})
+  for i in range(10, 20) | edit Xtest | exe "tag var" .. i | endfor
+  enew
+
+  new
+  let w4 = win_getid()
+  call settagstack(1, {'items' : []})
+  for i in range(10, 20) | edit Xtest | exe "tag var" .. i | endfor
+  enew
+
+  for w in [w1, w2, w3, w4]
+    let t = gettagstack(w)
+    call assert_equal(11, t.length)
+    call assert_equal(12, t.curidx)
+  endfor
+
+  bwipe! Xtest
+
+  for w in [w1, w2, w3, w4]
+    let t = gettagstack(w)
+    call assert_equal(0, t.length)
+    call assert_equal(1, t.curidx)
+  endfor
+
+  %bwipe!
   set tags&
-  %bwipe
 endfunc
 
 " Test for browsing multiple matching tags
diff --git a/src/version.c b/src/version.c
index 96691df61..8a392cac6 100644
--- a/src/version.c
+++ b/src/version.c
@@ -704,6 +704,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    556,
 /**/
     555,
 /**/

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/E1sRbqI-00Faq1-SL%40256bit.org.

Raspunde prin e-mail lui