changeset 26626:4d18b3a5254a v8.2.3842

patch 8.2.3842: Vim9: can change locked list and list items Commit: https://github.com/vim/vim/commit/422085f1c87cb6bea879158b8b05c4a5cf7ab48b Author: Bram Moolenaar <Bram@vim.org> Date: Fri Dec 17 20:36:15 2021 +0000 patch 8.2.3842: Vim9: can change locked list and list items Problem: Vim9: can change locked list and list items. Solution: Check that a list and list item isn't locked.
author Bram Moolenaar <Bram@vim.org>
date Fri, 17 Dec 2021 21:45:03 +0100
parents 05e524ae9236
children a56abea18a57
files src/testdir/test_listdict.vim src/version.c src/vim9execute.c
diffstat 3 files changed, 32 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/src/testdir/test_listdict.vim
+++ b/src/testdir/test_listdict.vim
@@ -719,6 +719,7 @@ func Test_list_locked_var_unlet()
       call assert_equal(expected[depth][u][1], ps)
     endfor
   endfor
+
   " Deleting a list range should fail if the range is locked
   let l = [1, 2, 3, 4]
   lockvar l[1:2]
@@ -848,6 +849,17 @@ func Test_let_lock_list()
   call assert_fails('let l[1:2] = [0, 1]', 'E741:')
   call assert_equal([1, 2, 3, 4], l)
   unlet l
+
+  let lines =<< trim END
+      def TryUnletListItem(l: list<any>)
+        unlet l[0]
+      enddef
+      let l = [1, 2, 3, 4]
+      lockvar! l
+      call TryUnletListItem(l)
+  END
+  call CheckScriptFailure(lines, 'E741:')
+  unlet g:l
 endfunc
 
 " Locking part of the list
--- a/src/version.c
+++ b/src/version.c
@@ -750,6 +750,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    3842,
+/**/
     3841,
 /**/
     3840,
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -2898,18 +2898,26 @@ exec_instructions(ectx_T *ectx)
 			{
 			    list_T	*l = tv_dest->vval.v_list;
 			    long	n = (long)tv_idx->vval.v_number;
-			    listitem_T	*li = NULL;
-
-			    li = list_find(l, n);
-			    if (li == NULL)
+
+			    if (l != NULL && value_check_lock(
+						      l->lv_lock, NULL, FALSE))
+				status = FAIL;
+			    else
 			    {
-				SOURCING_LNUM = iptr->isn_lnum;
-				semsg(_(e_listidx), n);
-				status = FAIL;
+				listitem_T	*li = list_find(l, n);
+
+				if (li == NULL)
+				{
+				    SOURCING_LNUM = iptr->isn_lnum;
+				    semsg(_(e_listidx), n);
+				    status = FAIL;
+				}
+				else if (value_check_lock(li->li_tv.v_lock,
+								  NULL, FALSE))
+				    status = FAIL;
+				else
+				    listitem_remove(l, li);
 			    }
-			    else
-				// TODO: check for list or item locked
-				listitem_remove(l, li);
 			}
 		    }
 		    else