1
0
forked from aniani/vim

patch 9.0.2059: outstanding exceptions may be skipped

Problem:  outstanding exceptions may be skipped
Solution: When restoring exception state, process remaining outstanding
          exceptions

closes: #13386

Signed-off-by: Christian Brabandt <cb@256bit.org>
Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
This commit is contained in:
Yegappan Lakshmanan
2023-10-21 11:59:42 +02:00
committed by Christian Brabandt
parent a36acb7ac4
commit 0ab500dede
9 changed files with 173 additions and 18 deletions

View File

@@ -757,6 +757,7 @@ 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;
}
/*
@@ -765,11 +766,14 @@ exception_state_save(exception_state_T *estate)
void
exception_state_restore(exception_state_T *estate)
{
if (current_exception == NULL)
current_exception = estate->estate_current_exception;
did_throw |= estate->estate_did_throw;
need_rethrow |= estate->estate_need_rethrow;
trylevel |= estate->estate_trylevel;
// Handle any outstanding exceptions before restoring the state
if (did_throw)
handle_did_throw();
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;
}
/*
@@ -782,6 +786,7 @@ exception_state_clear(void)
did_throw = FALSE;
need_rethrow = FALSE;
trylevel = 0;
did_emsg = 0;
}
/*

View File

@@ -1099,6 +1099,7 @@ struct exception_state_S
int estate_did_throw;
int estate_need_rethrow;
int estate_trylevel;
int estate_did_emsg;
};
#ifdef FEAT_SYN_HL

View File

@@ -904,7 +904,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

View File

@@ -8347,10 +8347,10 @@ def Test_class_variable_as_operands()
public static TruthyFn: func
static list: list<any> = []
static four: number = 4
static hello: string = 'hello'
static str: string = 'hello'
static def Hello(): string
return hello
static def Str(): string
return str
enddef
static def Four(): number
@@ -8374,8 +8374,17 @@ def Test_class_variable_as_operands()
assert_equal(16, 1 << Tests.four)
assert_equal(8, Tests.four + four)
assert_equal(8, four + Tests.four)
assert_equal('hellohello', Tests.hello .. hello)
assert_equal('hellohello', hello .. Tests.hello)
assert_equal('hellohello', Tests.str .. str)
assert_equal('hellohello', str .. Tests.str)
# Using class variable for list indexing
var l = range(10)
assert_equal(4, l[Tests.four])
assert_equal([4, 5, 6], l[Tests.four : Tests.four + 2])
# Using class variable for Dict key
var d = {hello: 'abc'}
assert_equal('abc', d[Tests.str])
enddef
endclass
@@ -8390,8 +8399,17 @@ def Test_class_variable_as_operands()
assert_equal(16, 1 << Tests.four)
assert_equal(8, Tests.four + Tests.Four())
assert_equal(8, Tests.Four() + Tests.four)
assert_equal('hellohello', Tests.hello .. Tests.Hello())
assert_equal('hellohello', Tests.Hello() .. Tests.hello)
assert_equal('hellohello', Tests.str .. Tests.Str())
assert_equal('hellohello', Tests.Str() .. Tests.str)
# Using class variable for list indexing
var l = range(10)
assert_equal(4, l[Tests.four])
assert_equal([4, 5, 6], l[Tests.four : Tests.four + 2])
# Using class variable for Dict key
var d = {hello: 'abc'}
assert_equal('abc', d[Tests.str])
enddef
Tests.TruthyFn = Tests.Truthy
@@ -8409,8 +8427,17 @@ def Test_class_variable_as_operands()
assert_equal(16, 1 << Tests.four)
assert_equal(8, Tests.four + Tests.Four())
assert_equal(8, Tests.Four() + Tests.four)
assert_equal('hellohello', Tests.hello .. Tests.Hello())
assert_equal('hellohello', Tests.Hello() .. Tests.hello)
assert_equal('hellohello', Tests.str .. Tests.Str())
assert_equal('hellohello', Tests.Str() .. Tests.str)
# Using class variable for list indexing
var l = range(10)
assert_equal(4, l[Tests.four])
assert_equal([4, 5, 6], l[Tests.four : Tests.four + 2])
# Using class variable for Dict key
var d = {hello: 'abc'}
assert_equal('abc', d[Tests.str])
END
v9.CheckSourceSuccess(lines)
enddef

View File

@@ -4725,6 +4725,64 @@ def Test_defer_after_exception()
v9.CheckScriptSuccess(lines)
enddef
" 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.
def Test_multidefer_with_exception()
var lines =<< trim END
vim9script
var callTrace: list<number> = []
def Except()
callTrace += [1]
throw 'InnerException'
callTrace += [2]
enddef
def FirstDefer()
callTrace += [3]
callTrace += [4]
enddef
def SecondDeferWithExcept()
callTrace += [5]
Except()
callTrace += [6]
enddef
def ThirdDefer()
callTrace += [7]
callTrace += [8]
enddef
def Foo()
callTrace += [9]
defer FirstDefer()
defer SecondDeferWithExcept()
defer ThirdDefer()
callTrace += [10]
enddef
v:errmsg = ''
try
callTrace += [11]
Foo()
callTrace += [12]
catch /TestException/
callTrace += [13]
catch
callTrace += [14]
finally
callTrace += [15]
endtry
callTrace += [16]
assert_equal('E605: Exception not caught: InnerException', v:errmsg)
assert_equal([11, 9, 10, 7, 8, 5, 1, 3, 4, 12, 15, 16], callTrace)
END
v9.CheckScriptSuccess(lines)
enddef
" Keep this last, it messes up highlighting.
def Test_substitute_cmd()
new

View File

@@ -704,6 +704,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
2059,
/**/
2058,
/**/

View File

@@ -2340,8 +2340,7 @@ class_object_index(
}
if (did_emsg == did_emsg_save)
member_not_found_msg(cl, is_object ? VAR_OBJECT : VAR_CLASS, name,
len);
member_not_found_msg(cl, rettv->v_type, name, len);
}
return FAIL;