diff options
author | Bram Moolenaar <Bram@vim.org> | 2020-07-18 15:17:02 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2020-07-18 15:17:02 +0200 |
commit | e859312e748297bde67a053fd3c486fc2c14b532 (patch) | |
tree | 54c9085cc2d7e8fce75f916b3a163fbf8ff68cc3 | |
parent | 2764d06ab7140c95b6317e344d853e4a32c76e9a (diff) | |
download | vim-git-e859312e748297bde67a053fd3c486fc2c14b532.tar.gz |
patch 8.2.1236: Vim9: a few errors not caught by try/catchv8.2.1236
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.
-rw-r--r-- | src/testdir/test_vim9_script.vim | 78 | ||||
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/vim9compile.c | 12 | ||||
-rw-r--r-- | src/vim9execute.c | 40 |
4 files changed, 113 insertions, 19 deletions
diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 035ea0b84..a646de978 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -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,14 +607,62 @@ 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 diff --git a/src/version.c b/src/version.c index a65bf1a9a..d8353cc4a 100644 --- a/src/version.c +++ b/src/version.c @@ -755,6 +755,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1236, +/**/ 1235, /**/ 1234, diff --git a/src/vim9compile.c b/src/vim9compile.c index 8c2de343a..634706b50 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -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) diff --git a/src/vim9execute.c b/src/vim9execute.c index 88979afa4..ce1278167 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -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); @@ -1481,24 +1483,38 @@ call_def_function( // create a dict from items on the stack case ISN_NEWDICT: { - int count = iptr->isn_arg.number; - dict_T *dict = dict_alloc(); - dictitem_T *item; + int count = iptr->isn_arg.number; + dict_T *dict = dict_alloc(); + dictitem_T *item; if (dict == NULL) 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) @@ -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 |