0
0
mirror of https://github.com/vim/vim.git synced 2025-09-25 03:54:15 -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:
Bram Moolenaar
2020-07-18 15:17:02 +02:00
parent 2764d06ab7
commit e859312e74
4 changed files with 113 additions and 19 deletions

View File

@@ -511,6 +511,22 @@ def Test_try_catch()
endtry # comment endtry # comment
assert_equal(['1', 'wrong', '3'], l) 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 let n: number
try try
n = l[3] n = l[3]
@@ -591,15 +607,63 @@ def Test_try_catch()
endtry endtry
assert_equal(277, n) assert_equal(277, n)
# TODO: make this work try
# try &ts = g:astring
# &ts = g:astring catch /E1029:/
# catch /E1093:/ n = 288
# n = 288 endtry
# endtry assert_equal(288, n)
# 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 enddef
def DeletedFunc(): list<any>
return ['delete me']
enddef
defcompile
delfunc DeletedFunc
def ThrowFromDef() def ThrowFromDef()
throw "getout" # comment throw "getout" # comment
enddef enddef

View File

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

View File

@@ -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) if (need_type(stacktype, &t_list_any, -1, cctx, FALSE) == FAIL)
goto theend; goto theend;
// TODO: check the length of a constant list here
generate_CHECKLEN(cctx, semicolon ? var_count - 1 : var_count, generate_CHECKLEN(cctx, semicolon ? var_count - 1 : var_count,
semicolon); semicolon);
} }
@@ -6539,6 +6540,7 @@ compile_finally(char_u *arg, cctx_T *cctx)
// Previous catch without match jumps here // Previous catch without match jumps here
isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label; isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
isn->isn_arg.jump.jump_where = instr->ga_len; 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 // 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); 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 // 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) if (isn->isn_arg.try.try_finally == 0)
isn->isn_arg.try.try_finally = instr->ga_len; 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); compile_endblock(cctx);
if (generate_instr(cctx, ISN_ENDTRY) == NULL) if (generate_instr(cctx, ISN_ENDTRY) == NULL)

View File

@@ -1241,7 +1241,7 @@ call_def_function(
if (msg != NULL) if (msg != NULL)
{ {
emsg(_(msg)); emsg(_(msg));
goto failed; goto on_error;
} }
} }
break; break;
@@ -1272,7 +1272,8 @@ call_def_function(
--ectx.ec_stack.ga_len; --ectx.ec_stack.ga_len;
if (set_vim_var_tv(iptr->isn_arg.number, STACK_TV_BOT(0)) if (set_vim_var_tv(iptr->isn_arg.number, STACK_TV_BOT(0))
== FAIL) == FAIL)
goto failed; // should not happen, type is checked when compiling
goto on_error;
break; break;
// store g:/b:/w:/t: variable // store g:/b:/w:/t: variable
@@ -1335,7 +1336,7 @@ call_def_function(
if (lidx < 0 || lidx > list->lv_len) if (lidx < 0 || lidx > list->lv_len)
{ {
semsg(_(e_listidx), lidx); semsg(_(e_listidx), lidx);
goto failed; goto on_error;
} }
tv = STACK_TV_BOT(-3); tv = STACK_TV_BOT(-3);
if (lidx < list->lv_len) if (lidx < list->lv_len)
@@ -1348,7 +1349,7 @@ call_def_function(
} }
else else
{ {
// append to list // append to list, only fails when out of memory
if (list_append_tv(list, tv) == FAIL) if (list_append_tv(list, tv) == FAIL)
goto failed; goto failed;
clear_tv(tv); clear_tv(tv);
@@ -1371,18 +1372,19 @@ call_def_function(
if (key == NULL || *key == NUL) if (key == NULL || *key == NUL)
{ {
emsg(_(e_emptykey)); emsg(_(e_emptykey));
goto failed; goto on_error;
} }
tv = STACK_TV_BOT(-3); tv = STACK_TV_BOT(-3);
di = dict_find(dict, key, -1); di = dict_find(dict, key, -1);
if (di != NULL) if (di != NULL)
{ {
// overwrite existing value
clear_tv(&di->di_tv); clear_tv(&di->di_tv);
di->di_tv = *tv; di->di_tv = *tv;
} }
else else
{ {
// add to dict // add to dict, only fails when out of memory
if (dict_add_tv(dict, (char *)key, tv) == FAIL) if (dict_add_tv(dict, (char *)key, tv) == FAIL)
goto failed; goto failed;
clear_tv(tv); clear_tv(tv);
@@ -1465,7 +1467,7 @@ call_def_function(
case ISN_UNLET: case ISN_UNLET:
if (do_unlet(iptr->isn_arg.unlet.ul_name, if (do_unlet(iptr->isn_arg.unlet.ul_name,
iptr->isn_arg.unlet.ul_forceit) == FAIL) iptr->isn_arg.unlet.ul_forceit) == FAIL)
goto failed; goto on_error;
break; break;
case ISN_UNLETENV: case ISN_UNLETENV:
vim_unsetenv(iptr->isn_arg.unlet.ul_name); vim_unsetenv(iptr->isn_arg.unlet.ul_name);
@@ -1489,17 +1491,31 @@ call_def_function(
goto failed; goto failed;
for (idx = 0; idx < count; ++idx) 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)); 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); item = dictitem_alloc(tv->vval.v_string);
clear_tv(tv); clear_tv(tv);
if (item == NULL) if (item == NULL)
{
dict_unref(dict);
goto failed; goto failed;
}
item->di_tv = *STACK_TV_BOT(2 * (idx - count) + 1); item->di_tv = *STACK_TV_BOT(2 * (idx - count) + 1);
item->di_tv.v_lock = 0; item->di_tv.v_lock = 0;
if (dict_add(dict, item) == FAIL) if (dict_add(dict, item) == FAIL)
{
dict_unref(dict);
goto failed; goto failed;
} }
}
if (count > 0) if (count > 0)
ectx.ec_stack.ga_len -= 2 * count - 1; ectx.ec_stack.ga_len -= 2 * count - 1;
@@ -1519,7 +1535,7 @@ call_def_function(
if (call_dfunc(iptr->isn_arg.dfunc.cdf_idx, if (call_dfunc(iptr->isn_arg.dfunc.cdf_idx,
iptr->isn_arg.dfunc.cdf_argcount, iptr->isn_arg.dfunc.cdf_argcount,
&ectx) == FAIL) &ectx) == FAIL)
goto failed; goto on_error;
break; break;
// call a builtin function // call a builtin function