changeset 25078:eac6e5a94e9d v8.2.3076

patch 8.2.3076: Vim9: using try in catch block causes a hang Commit: https://github.com/vim/vim/commit/3f987b59173926420998ca92eb71688ee3e4a3e3 Author: Bram Moolenaar <Bram@vim.org> Date: Wed Jun 30 12:02:24 2021 +0200 patch 8.2.3076: Vim9: using try in catch block causes a hang Problem: Vim9: using try in catch block causes a hang. Solution: Save and restore the ec_in_catch flag. (closes https://github.com/vim/vim/issues/8478)
author Bram Moolenaar <Bram@vim.org>
date Wed, 30 Jun 2021 12:15:04 +0200
parents 3438b2048ba7
children 0516203ae9c5
files src/testdir/test_vim9_script.vim src/version.c src/vim9execute.c
diffstat 3 files changed, 32 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/src/testdir/test_vim9_script.vim
+++ b/src/testdir/test_vim9_script.vim
@@ -605,6 +605,32 @@ def Test_try_catch_throw()
   unlet g:caught
 enddef
 
+def Test_try_in_catch()
+  var lines =<< trim END
+      vim9script
+      var seq = []
+      def DoIt()
+        try
+          seq->add('throw 1')
+          eval [][0]
+          seq->add('notreached')
+        catch
+          seq->add('catch')
+          try
+            seq->add('throw 2')
+            eval [][0]
+            seq->add('notreached')
+          catch /nothing/
+            seq->add('notreached')
+          endtry
+          seq->add('done')
+        endtry
+      enddef
+      DoIt()
+      assert_equal(['throw 1', 'catch', 'throw 2', 'done'], seq)
+  END
+enddef
+
 " :while at the very start of a function that :continue jumps to
 def TryContinueFunc()
  while g:Count < 2
--- a/src/version.c
+++ b/src/version.c
@@ -756,6 +756,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    3076,
+/**/
     3075,
 /**/
     3074,
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -26,6 +26,7 @@
 typedef struct {
     int	    tcd_frame_idx;	// ec_frame_idx at ISN_TRY
     int	    tcd_stack_len;	// size of ectx.ec_stack at ISN_TRY
+    int	    tcd_save_in_catch;	// saved ec_in_catch
     int	    tcd_catch_idx;	// instruction of the first :catch or :finally
     int	    tcd_finally_idx;	// instruction of the :finally block or zero
     int	    tcd_endtry_idx;	// instruction of the :endtry
@@ -3166,6 +3167,8 @@ exec_instructions(ectx_T *ectx)
 		    CLEAR_POINTER(trycmd);
 		    trycmd->tcd_frame_idx = ectx->ec_frame_idx;
 		    trycmd->tcd_stack_len = ectx->ec_stack.ga_len;
+		    trycmd->tcd_save_in_catch = ectx->ec_in_catch;
+		    ectx->ec_in_catch = FALSE;
 		    trycmd->tcd_catch_idx =
 					  iptr->isn_arg.try.try_ref->try_catch;
 		    trycmd->tcd_finally_idx =
@@ -3263,9 +3266,9 @@ exec_instructions(ectx_T *ectx)
 
 			--trystack->ga_len;
 			--trylevel;
-			ectx->ec_in_catch = FALSE;
 			trycmd = ((trycmd_T *)trystack->ga_data)
 							    + trystack->ga_len;
+			ectx->ec_in_catch = trycmd->tcd_save_in_catch;
 			if (trycmd->tcd_caught && current_exception != NULL)
 			{
 			    // discard the exception