mirror of
https://github.com/neovim/neovim.git
synced 2024-09-17 20:58:20 -04:00
vim-patch:9.0.2059: outstanding exceptions may be skipped (#25736)
Problem: outstanding exceptions may be skipped
Solution: When restoring exception state, process remaining outstanding
exceptions
closes: vim/vim#13386
0ab500dede
Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
This commit is contained in:
parent
c049ce56cd
commit
9971bea6f1
@ -410,7 +410,8 @@ Any return value of the deferred function is discarded. The function cannot
|
||||
be followed by anything, such as "->func" or ".member". Currently `:defer
|
||||
GetArg()->TheFunc()` does not work, it may work in a later version.
|
||||
|
||||
Errors are reported but do not cause aborting execution of deferred functions.
|
||||
Errors are reported but do not cause aborting execution of deferred functions
|
||||
or altering execution outside of deferred functions.
|
||||
|
||||
No range is accepted. The function can be a partial with extra arguments, but
|
||||
not with a dictionary. *E1300*
|
||||
|
@ -668,17 +668,21 @@ void exception_state_save(exception_state_T *estate)
|
||||
estate->estate_did_throw = did_throw;
|
||||
estate->estate_need_rethrow = need_rethrow;
|
||||
estate->estate_trylevel = trylevel;
|
||||
estate->estate_did_emsg = did_emsg;
|
||||
}
|
||||
|
||||
/// Restore the current exception state from "estate"
|
||||
void exception_state_restore(exception_state_T *estate)
|
||||
{
|
||||
if (current_exception == NULL) {
|
||||
current_exception = estate->estate_current_exception;
|
||||
// Handle any outstanding exceptions before restoring the state
|
||||
if (did_throw) {
|
||||
handle_did_throw();
|
||||
}
|
||||
did_throw |= estate->estate_did_throw;
|
||||
need_rethrow |= estate->estate_need_rethrow;
|
||||
trylevel |= estate->estate_trylevel;
|
||||
current_exception = estate->estate_current_exception;
|
||||
did_throw = estate->estate_did_throw;
|
||||
need_rethrow = estate->estate_need_rethrow;
|
||||
trylevel = estate->estate_trylevel;
|
||||
did_emsg = estate->estate_did_emsg;
|
||||
}
|
||||
|
||||
/// Clear the current exception state
|
||||
@ -688,6 +692,7 @@ void exception_state_clear(void)
|
||||
did_throw = false;
|
||||
need_rethrow = false;
|
||||
trylevel = 0;
|
||||
did_emsg = 0;
|
||||
}
|
||||
|
||||
// Flags specifying the message displayed by report_pending.
|
||||
|
@ -126,6 +126,7 @@ struct exception_state_S {
|
||||
bool estate_did_throw;
|
||||
bool estate_need_rethrow;
|
||||
int estate_trylevel;
|
||||
int estate_did_emsg;
|
||||
};
|
||||
|
||||
#endif // NVIM_EX_EVAL_DEFS_H
|
||||
|
@ -827,7 +827,68 @@ func Test_defer_after_exception()
|
||||
|
||||
delfunc Defer
|
||||
delfunc Foo
|
||||
delfunc Bar
|
||||
unlet g:callTrace
|
||||
endfunc
|
||||
|
||||
" Test for multiple deferred function which throw exceptions.
|
||||
" Exceptions thrown by deferred functions should result in error messages but
|
||||
" not propagated into the calling functions.
|
||||
func Test_multidefer_with_exception()
|
||||
let g:callTrace = []
|
||||
func Except()
|
||||
let g:callTrace += [1]
|
||||
throw 'InnerException'
|
||||
let g:callTrace += [2]
|
||||
endfunc
|
||||
|
||||
func FirstDefer()
|
||||
let g:callTrace += [3]
|
||||
let g:callTrace += [4]
|
||||
endfunc
|
||||
|
||||
func SecondDeferWithExcept()
|
||||
let g:callTrace += [5]
|
||||
call Except()
|
||||
let g:callTrace += [6]
|
||||
endfunc
|
||||
|
||||
func ThirdDefer()
|
||||
let g:callTrace += [7]
|
||||
let g:callTrace += [8]
|
||||
endfunc
|
||||
|
||||
func Foo()
|
||||
let g:callTrace += [9]
|
||||
defer FirstDefer()
|
||||
defer SecondDeferWithExcept()
|
||||
defer ThirdDefer()
|
||||
let g:callTrace += [10]
|
||||
endfunc
|
||||
|
||||
let v:errmsg = ''
|
||||
try
|
||||
let g:callTrace += [11]
|
||||
call Foo()
|
||||
let g:callTrace += [12]
|
||||
catch /TestException/
|
||||
let g:callTrace += [13]
|
||||
catch
|
||||
let g:callTrace += [14]
|
||||
finally
|
||||
let g:callTrace += [15]
|
||||
endtry
|
||||
let g:callTrace += [16]
|
||||
|
||||
call assert_equal('E605: Exception not caught: InnerException', v:errmsg)
|
||||
call assert_equal([11, 9, 10, 7, 8, 5, 1, 3, 4, 12, 15, 16], g:callTrace)
|
||||
|
||||
unlet g:callTrace
|
||||
delfunc Except
|
||||
delfunc FirstDefer
|
||||
delfunc SecondDeferWithExcept
|
||||
delfunc ThirdDefer
|
||||
delfunc Foo
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
Loading…
Reference in New Issue
Block a user