Patch 9.0.1468
Problem:    Recursively calling :defer function if it does :qa in a compiled
            function.
Solution:   Clear the defer entry before calling the function. (closes #12271)
Files:      src/vim9execute.c, src/testdir/test_user_func.vim


*** ../vim-9.0.1467/src/vim9execute.c   2023-04-01 22:05:35.155519002 +0100
--- src/vim9execute.c   2023-04-18 20:57:03.520916445 +0100
***************
*** 1063,1068 ****
--- 1063,1072 ----
        int         obj_off = functv->v_type == VAR_PARTIAL ? 1 : 0;
        int         argcount = l->lv_len - 1 - obj_off;
  
+       if (functv->vval.v_string == NULL)
+           // already being called, can happen if function does ":qa"
+           continue;
+ 
        if (obj_off == 1)
            arg_li = arg_li->li_next;  // second list item is the object
        for (i = 0; i < argcount; ++i)
***************
*** 1082,1090 ****
            if (funcexe.fe_object != NULL)
                ++funcexe.fe_object->obj_refcount;
        }
!       (void)call_func(functv->vval.v_string, -1,
!                                         &rettv, argcount, argvars, &funcexe);
        clear_tv(&rettv);
      }
  }
  
--- 1086,1099 ----
            if (funcexe.fe_object != NULL)
                ++funcexe.fe_object->obj_refcount;
        }
! 
!       char_u *name = functv->vval.v_string;
!       functv->vval.v_string = NULL;
! 
!       (void)call_func(name, -1, &rettv, argcount, argvars, &funcexe);
! 
        clear_tv(&rettv);
+       vim_free(name);
      }
  }
  
*** ../vim-9.0.1467/src/testdir/test_user_func.vim      2023-04-17 
19:23:41.946037074 +0100
--- src/testdir/test_user_func.vim      2023-04-18 21:04:10.898990907 +0100
***************
*** 651,680 ****
    call assert_false(filereadable('XDeleteTwo'))
  endfunc
  
! func Test_defer_quitall()
    let lines =<< trim END
-       vim9script
        func DeferLevelTwo()
!         call writefile(['text'], 'XQuitallTwo', 'D')
!         call writefile(['quit'], 'XQuitallThree', 'a')
          qa!
        endfunc
  
        def DeferLevelOne()
!         call writefile(['text'], 'XQuitallOne', 'D')
!         call DeferLevelTwo()
        enddef
  
        DeferLevelOne()
    END
!   call writefile(lines, 'XdeferQuitall', 'D')
!   let res = system(GetVimCommand() .. ' -X -S XdeferQuitall')
    call assert_equal(0, v:shell_error)
!   call assert_false(filereadable('XQuitallOne'))
!   call assert_false(filereadable('XQuitallTwo'))
!   call assert_equal(['quit'], readfile('XQuitallThree'))
  
!   call delete('XQuitallThree')
  endfunc
  
  func Test_defer_quitall_in_expr_func()
--- 651,705 ----
    call assert_false(filereadable('XDeleteTwo'))
  endfunc
  
! func Test_defer_quitall_func()
    let lines =<< trim END
        func DeferLevelTwo()
!         call writefile(['text'], 'XQuitallFuncTwo', 'D')
!         call writefile(['quit'], 'XQuitallFuncThree', 'a')
          qa!
        endfunc
  
+       func DeferLevelOne()
+         call writefile(['text'], 'XQuitalFunclOne', 'D')
+         defer DeferLevelTwo()
+       endfunc
+ 
+       call DeferLevelOne()
+   END
+   call writefile(lines, 'XdeferQuitallFunc', 'D')
+   call system(GetVimCommand() .. ' -X -S XdeferQuitallFunc')
+   call assert_equal(0, v:shell_error)
+   call assert_false(filereadable('XQuitallFuncOne'))
+   call assert_false(filereadable('XQuitallFuncTwo'))
+   call assert_equal(['quit'], readfile('XQuitallFuncThree'))
+ 
+   call delete('XQuitallFuncThree')
+ endfunc
+ 
+ func Test_defer_quitall_def()
+   let lines =<< trim END
+       vim9script
+       def DeferLevelTwo()
+         call writefile(['text'], 'XQuitallDefTwo', 'D')
+         call writefile(['quit'], 'XQuitallDefThree', 'a')
+         qa!
+       enddef
+ 
        def DeferLevelOne()
!         call writefile(['text'], 'XQuitallDefOne', 'D')
!         defer DeferLevelTwo()
        enddef
  
        DeferLevelOne()
    END
!   call writefile(lines, 'XdeferQuitallDef', 'D')
!   call system(GetVimCommand() .. ' -X -S XdeferQuitallDef')
    call assert_equal(0, v:shell_error)
!   call assert_false(filereadable('XQuitallDefOne'))
!   call assert_false(filereadable('XQuitallDefTwo'))
!   call assert_equal(['quit'], readfile('XQuitallDefThree'))
  
!   call delete('XQuitallDefThree')
  endfunc
  
  func Test_defer_quitall_in_expr_func()
***************
*** 693,699 ****
        call Test_defer_in_funcref()
    END
    call writefile(lines, 'XdeferQuitallExpr', 'D')
!   let res = system(GetVimCommand() .. ' -X -S XdeferQuitallExpr')
    call assert_equal(0, v:shell_error)
    call assert_false(filereadable('Xentry0'))
    call assert_false(filereadable('Xentry1'))
--- 718,724 ----
        call Test_defer_in_funcref()
    END
    call writefile(lines, 'XdeferQuitallExpr', 'D')
!   call system(GetVimCommand() .. ' -X -S XdeferQuitallExpr')
    call assert_equal(0, v:shell_error)
    call assert_false(filereadable('Xentry0'))
    call assert_false(filereadable('Xentry1'))
*** ../vim-9.0.1467/src/version.c       2023-04-18 20:53:17.734242016 +0100
--- src/version.c       2023-04-18 20:59:06.578559373 +0100
***************
*** 697,698 ****
--- 697,700 ----
  {   /* Add new patch number below this line */
+ /**/
+     1468,
  /**/

-- 
There are only two hard things in programming: Cache invalidation,
naming things and off-by-one errors.

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
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 [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20230418200541.EC0081C0633%40moolenaar.net.

Raspunde prin e-mail lui