mirror of
https://github.com/vim/vim.git
synced 2025-09-24 03:44:06 -04:00
patch 8.2.1236: Vim9: a few errors not caught by try/catch
Problem: Vim9: a few errors not caught by try/catch. Solution: Do not bail out if an error is inside try/catch. Fix that a not matching catch doesn't jump to :endtry.
This commit is contained in:
@@ -511,6 +511,22 @@ def Test_try_catch()
|
||||
endtry # comment
|
||||
assert_equal(['1', 'wrong', '3'], l)
|
||||
|
||||
l = []
|
||||
try
|
||||
try
|
||||
add(l, '1')
|
||||
throw 'wrong'
|
||||
add(l, '2')
|
||||
catch /right/
|
||||
add(l, v:exception)
|
||||
endtry
|
||||
catch /wrong/
|
||||
add(l, 'caught')
|
||||
finally
|
||||
add(l, 'finally')
|
||||
endtry
|
||||
assert_equal(['1', 'caught', 'finally'], l)
|
||||
|
||||
let n: number
|
||||
try
|
||||
n = l[3]
|
||||
@@ -591,15 +607,63 @@ def Test_try_catch()
|
||||
endtry
|
||||
assert_equal(277, n)
|
||||
|
||||
# TODO: make this work
|
||||
# try
|
||||
# &ts = g:astring
|
||||
# catch /E1093:/
|
||||
# n = 288
|
||||
# endtry
|
||||
# assert_equal(288, n)
|
||||
try
|
||||
&ts = g:astring
|
||||
catch /E1029:/
|
||||
n = 288
|
||||
endtry
|
||||
assert_equal(288, n)
|
||||
|
||||
try
|
||||
&backspace = 'asdf'
|
||||
catch /E474:/
|
||||
n = 299
|
||||
endtry
|
||||
assert_equal(299, n)
|
||||
|
||||
l = [1]
|
||||
try
|
||||
l[3] = 3
|
||||
catch /E684:/
|
||||
n = 300
|
||||
endtry
|
||||
assert_equal(300, n)
|
||||
|
||||
try
|
||||
d[''] = 3
|
||||
catch /E713:/
|
||||
n = 311
|
||||
endtry
|
||||
assert_equal(311, n)
|
||||
|
||||
try
|
||||
unlet g:does_not_exist
|
||||
catch /E108:/
|
||||
n = 322
|
||||
endtry
|
||||
assert_equal(322, n)
|
||||
|
||||
try
|
||||
d = {'text': 1, g:astring: 2}
|
||||
catch /E721:/
|
||||
n = 333
|
||||
endtry
|
||||
assert_equal(333, n)
|
||||
|
||||
try
|
||||
l = DeletedFunc()
|
||||
catch /E933:/
|
||||
n = 344
|
||||
endtry
|
||||
assert_equal(344, n)
|
||||
enddef
|
||||
|
||||
def DeletedFunc(): list<any>
|
||||
return ['delete me']
|
||||
enddef
|
||||
defcompile
|
||||
delfunc DeletedFunc
|
||||
|
||||
def ThrowFromDef()
|
||||
throw "getout" # comment
|
||||
enddef
|
||||
|
@@ -754,6 +754,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1236,
|
||||
/**/
|
||||
1235,
|
||||
/**/
|
||||
|
@@ -4961,6 +4961,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
||||
}
|
||||
if (need_type(stacktype, &t_list_any, -1, cctx, FALSE) == FAIL)
|
||||
goto theend;
|
||||
// TODO: check the length of a constant list here
|
||||
generate_CHECKLEN(cctx, semicolon ? var_count - 1 : var_count,
|
||||
semicolon);
|
||||
}
|
||||
@@ -6539,6 +6540,7 @@ compile_finally(char_u *arg, cctx_T *cctx)
|
||||
// Previous catch without match jumps here
|
||||
isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
|
||||
isn->isn_arg.jump.jump_where = instr->ga_len;
|
||||
scope->se_u.se_try.ts_catch_label = 0;
|
||||
}
|
||||
|
||||
// TODO: set index in ts_finally_label jumps
|
||||
@@ -6584,8 +6586,18 @@ compile_endtry(char_u *arg, cctx_T *cctx)
|
||||
compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
|
||||
|
||||
// End :catch or :finally scope: set value in ISN_TRY instruction
|
||||
if (isn->isn_arg.try.try_catch == 0)
|
||||
isn->isn_arg.try.try_catch = instr->ga_len;
|
||||
if (isn->isn_arg.try.try_finally == 0)
|
||||
isn->isn_arg.try.try_finally = instr->ga_len;
|
||||
|
||||
if (scope->se_u.se_try.ts_catch_label != 0)
|
||||
{
|
||||
// Last catch without match jumps here
|
||||
isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
|
||||
isn->isn_arg.jump.jump_where = instr->ga_len;
|
||||
}
|
||||
|
||||
compile_endblock(cctx);
|
||||
|
||||
if (generate_instr(cctx, ISN_ENDTRY) == NULL)
|
||||
|
@@ -1241,7 +1241,7 @@ call_def_function(
|
||||
if (msg != NULL)
|
||||
{
|
||||
emsg(_(msg));
|
||||
goto failed;
|
||||
goto on_error;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1272,7 +1272,8 @@ call_def_function(
|
||||
--ectx.ec_stack.ga_len;
|
||||
if (set_vim_var_tv(iptr->isn_arg.number, STACK_TV_BOT(0))
|
||||
== FAIL)
|
||||
goto failed;
|
||||
// should not happen, type is checked when compiling
|
||||
goto on_error;
|
||||
break;
|
||||
|
||||
// store g:/b:/w:/t: variable
|
||||
@@ -1335,7 +1336,7 @@ call_def_function(
|
||||
if (lidx < 0 || lidx > list->lv_len)
|
||||
{
|
||||
semsg(_(e_listidx), lidx);
|
||||
goto failed;
|
||||
goto on_error;
|
||||
}
|
||||
tv = STACK_TV_BOT(-3);
|
||||
if (lidx < list->lv_len)
|
||||
@@ -1348,7 +1349,7 @@ call_def_function(
|
||||
}
|
||||
else
|
||||
{
|
||||
// append to list
|
||||
// append to list, only fails when out of memory
|
||||
if (list_append_tv(list, tv) == FAIL)
|
||||
goto failed;
|
||||
clear_tv(tv);
|
||||
@@ -1371,18 +1372,19 @@ call_def_function(
|
||||
if (key == NULL || *key == NUL)
|
||||
{
|
||||
emsg(_(e_emptykey));
|
||||
goto failed;
|
||||
goto on_error;
|
||||
}
|
||||
tv = STACK_TV_BOT(-3);
|
||||
di = dict_find(dict, key, -1);
|
||||
if (di != NULL)
|
||||
{
|
||||
// overwrite existing value
|
||||
clear_tv(&di->di_tv);
|
||||
di->di_tv = *tv;
|
||||
}
|
||||
else
|
||||
{
|
||||
// add to dict
|
||||
// add to dict, only fails when out of memory
|
||||
if (dict_add_tv(dict, (char *)key, tv) == FAIL)
|
||||
goto failed;
|
||||
clear_tv(tv);
|
||||
@@ -1465,7 +1467,7 @@ call_def_function(
|
||||
case ISN_UNLET:
|
||||
if (do_unlet(iptr->isn_arg.unlet.ul_name,
|
||||
iptr->isn_arg.unlet.ul_forceit) == FAIL)
|
||||
goto failed;
|
||||
goto on_error;
|
||||
break;
|
||||
case ISN_UNLETENV:
|
||||
vim_unsetenv(iptr->isn_arg.unlet.ul_name);
|
||||
@@ -1489,17 +1491,31 @@ call_def_function(
|
||||
goto failed;
|
||||
for (idx = 0; idx < count; ++idx)
|
||||
{
|
||||
// check key type is VAR_STRING
|
||||
// have already checked key type is VAR_STRING
|
||||
tv = STACK_TV_BOT(2 * (idx - count));
|
||||
// check key is unique
|
||||
item = dict_find(dict, tv->vval.v_string, -1);
|
||||
if (item != NULL)
|
||||
{
|
||||
semsg(_(e_duplicate_key), tv->vval.v_string);
|
||||
dict_unref(dict);
|
||||
goto on_error;
|
||||
}
|
||||
item = dictitem_alloc(tv->vval.v_string);
|
||||
clear_tv(tv);
|
||||
if (item == NULL)
|
||||
{
|
||||
dict_unref(dict);
|
||||
goto failed;
|
||||
}
|
||||
item->di_tv = *STACK_TV_BOT(2 * (idx - count) + 1);
|
||||
item->di_tv.v_lock = 0;
|
||||
if (dict_add(dict, item) == FAIL)
|
||||
{
|
||||
dict_unref(dict);
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
if (count > 0)
|
||||
ectx.ec_stack.ga_len -= 2 * count - 1;
|
||||
@@ -1519,7 +1535,7 @@ call_def_function(
|
||||
if (call_dfunc(iptr->isn_arg.dfunc.cdf_idx,
|
||||
iptr->isn_arg.dfunc.cdf_argcount,
|
||||
&ectx) == FAIL)
|
||||
goto failed;
|
||||
goto on_error;
|
||||
break;
|
||||
|
||||
// call a builtin function
|
||||
|
Reference in New Issue
Block a user