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.