]> granicus.if.org Git - vim/commitdiff
patch 8.2.4225: Vim9: depth argument of :lockvar not parsed in :def function v8.2.4225
authorBram Moolenaar <Bram@vim.org>
Wed, 26 Jan 2022 21:01:15 +0000 (21:01 +0000)
committerBram Moolenaar <Bram@vim.org>
Wed, 26 Jan 2022 21:01:15 +0000 (21:01 +0000)
Problem:    Vim9: depth argument of :lockvar not parsed in :def function.
Solution:   Parse the optional depth argument. (closes #9629)
            Fix that locking doesn't work for a non-materialize list.

src/errors.h
src/evalfunc.c
src/evalvars.c
src/structs.h
src/testdir/test_vim9_cmd.vim
src/testdir/test_vim9_disassemble.vim
src/version.c
src/vim9cmds.c
src/vim9execute.c

index d89c27c22bdc1141f1577e2ad7e87ac0c552d172..dd1b9fcc85be9f016805e178009f7004f5808c27 100644 (file)
@@ -2859,10 +2859,10 @@ EXTERN char e_assert_fails_fifth_argument[]
        INIT(= N_("E1116: \"assert_fails()\" fifth argument must be a string"));
 EXTERN char e_cannot_use_bang_with_nested_def[]
        INIT(= N_("E1117: Cannot use ! with nested :def"));
-EXTERN char e_cannot_change_list[]
-       INIT(= N_("E1118: Cannot change list"));
-EXTERN char e_cannot_change_list_item[]
-       INIT(= N_("E1119: Cannot change list item"));
+EXTERN char e_cannot_change_locked_list[]
+       INIT(= N_("E1118: Cannot change locked list"));
+EXTERN char e_cannot_change_locked_list_item[]
+       INIT(= N_("E1119: Cannot change locked list item"));
 EXTERN char e_cannot_change_dict[]
        INIT(= N_("E1120: Cannot change dict"));
 EXTERN char e_cannot_change_dict_item[]
index 4376318d0d31d63d457ddc2c0bc652ebce4acfb1..169f972c24304a59aac768f5fe1bd26f70cbf730 100644 (file)
@@ -7922,7 +7922,7 @@ range_list_materialize(list_T *list)
 {
     varnumber_T start = list->lv_u.nonmat.lv_start;
     varnumber_T end = list->lv_u.nonmat.lv_end;
-    int            stride = list->lv_u.nonmat.lv_stride;
+    int                stride = list->lv_u.nonmat.lv_stride;
     varnumber_T i;
 
     list->lv_first = NULL;
@@ -7930,8 +7930,13 @@ range_list_materialize(list_T *list)
     list->lv_len = 0;
     list->lv_u.mat.lv_idx_item = NULL;
     for (i = start; stride > 0 ? i <= end : i >= end; i += stride)
+    {
        if (list_append_number(list, (varnumber_T)i) == FAIL)
            break;
+       if (list->lv_lock & VAR_ITEMS_LOCKED)
+           list->lv_u.mat.lv_last->li_tv.v_lock = VAR_LOCKED;
+    }
+    list->lv_lock &= ~VAR_ITEMS_LOCKED;
 }
 
 /*
index 496666e1eac5e3561c840dff16dcd9dda637af1c..c53cc87fbc37e37d03a3519f8c42bdfd7417d82c 100644 (file)
@@ -2060,10 +2060,18 @@ item_lock(typval_T *tv, int deep, int lock, int check_refcount)
                    l->lv_lock |= VAR_LOCKED;
                else
                    l->lv_lock &= ~VAR_LOCKED;
-               if ((deep < 0 || deep > 1) && l->lv_first != &range_list_item)
-                   // recursive: lock/unlock the items the List contains
-                   FOR_ALL_LIST_ITEMS(l, li)
-                       item_lock(&li->li_tv, deep - 1, lock, check_refcount);
+               if (deep < 0 || deep > 1)
+               {
+                   if (l->lv_first == &range_list_item)
+                       l->lv_lock |= VAR_ITEMS_LOCKED;
+                   else
+                   {
+                       // recursive: lock/unlock the items the List contains
+                       CHECK_LIST_MATERIALIZE(l);
+                       FOR_ALL_LIST_ITEMS(l, li) item_lock(&li->li_tv,
+                                              deep - 1, lock, check_refcount);
+                   }
+               }
            }
            break;
        case VAR_DICT:
index e2f1de93a6f548d371ecf7e295144ee0f73b9550..a35361ecb6ee7402ec675f01e8afbe83d7b837a0 100644 (file)
@@ -1464,8 +1464,9 @@ typedef struct
                        // allowed to mask existing functions
 
 // Values for "v_lock".
-#define VAR_LOCKED     1       // locked with lock(), can use unlock()
-#define VAR_FIXED      2       // locked forever
+#define VAR_LOCKED         1   // locked with lock(), can use unlock()
+#define VAR_FIXED          2   // locked forever
+#define VAR_ITEMS_LOCKED    4  // items of non-materialized list locked
 
 /*
  * Structure to hold an item of a list: an internal variable without a name.
@@ -1497,7 +1498,8 @@ struct listwatch_S
  */
 struct listvar_S
 {
-    listitem_T *lv_first;      // first item, NULL if none
+    listitem_T *lv_first;      // first item, NULL if none, &range_list_item
+                               // for a non-materialized list
     listwatch_T        *lv_watch;      // first watcher, NULL if none
     union {
        struct {        // used for non-materialized range list:
index 6347a282a6795c0939895e7857dfcd2a054bbd37..7b2edfd1b1e18d7f196c1c626faa16db0a86436b 100644 (file)
@@ -1396,6 +1396,35 @@ def Test_lockvar()
     lockvar whatever
   endif
 
+  g:lockme = [1, 2, 3]
+  lockvar 1 g:lockme
+  g:lockme[1] = 77
+  assert_equal([1, 77, 3], g:lockme)
+
+  lockvar 2 g:lockme
+  var caught = false
+  try
+    g:lockme[1] = 99
+  catch /E1119:/
+    caught = true
+  endtry
+  assert_true(caught)
+  assert_equal([1, 77, 3], g:lockme)
+  unlet g:lockme
+
+  # also for non-materialized list
+  g:therange = range(3)
+  lockvar 2 g:therange
+  caught = false
+  try
+    g:therange[1] = 99
+  catch /E1119:/
+    caught = true
+  endtry
+  assert_true(caught)
+  assert_equal([0, 1, 2], g:therange)
+  unlet g:therange
+
   var d = {a: 1, b: 2}
   d.a = 3
   d.b = 4
index 8731052aa31d05482d3d0129994496f862aafbea..d3330908e5fce671cf0e3fb5db76bc4225480b2d 100644 (file)
@@ -625,7 +625,7 @@ def Test_disassemble_locl_local()
         '\d STORE $0\_s*' ..
         'lockvar d.a\_s*' ..
         '\d LOAD $0\_s*' ..
-        '\d LOCKUNLOCK lockvar d.a\_s*',
+        '\d LOCKUNLOCK lockvar d.a\_s*',
         res)
 enddef
 
index 9869aa0d810d6d274ea3755d569ecadebd44f959..7fbafc6044862327b67bec6ec097a1a8b37de65c 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    4225,
 /**/
     4224,
 /**/
index 27322df1c245b256de3bad94d0ac3bb41011f347..1af2a157ec4e75043c144fadb74cea581d5ea4b2 100644 (file)
@@ -178,7 +178,7 @@ compile_lock_unlock(
     lval_T  *lvp,
     char_u  *name_end,
     exarg_T *eap,
-    int            deep UNUSED,
+    int            deep,
     void    *coookie)
 {
     cctx_T     *cctx = coookie;
@@ -223,8 +223,9 @@ compile_lock_unlock(
        ret = FAIL;
     else
     {
-       vim_snprintf((char *)buf, len, "%s %s",
+       vim_snprintf((char *)buf, len, "%s %d %s",
                eap->cmdidx == CMD_lockvar ? "lockvar" : "unlockvar",
+               deep,
                p);
        ret = generate_EXEC_copy(cctx, isn, buf);
 
@@ -241,7 +242,23 @@ compile_lock_unlock(
     char_u *
 compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx)
 {
-    ex_unletlock(eap, arg, 0, GLV_NO_AUTOLOAD | GLV_COMPILING,
+    int            deep = 0;
+    char_u  *p = arg;
+
+    if (eap->cmdidx != CMD_unlet)
+    {
+       if (eap->forceit)
+           deep = -1;
+       else if (vim_isdigit(*p))
+       {
+           deep = getdigits(&p);
+           p = skipwhite(p);
+       }
+       else
+           deep = 2;
+    }
+
+    ex_unletlock(eap, p, deep, GLV_NO_AUTOLOAD | GLV_COMPILING,
            eap->cmdidx == CMD_unlet ? compile_unlet : compile_lock_unlock,
            cctx);
     return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd;
index 1232b35bb52f8ce310aa2201eb20fc20c98ffbeb..a45d7c5538972cf722745974d70ed5f5074cd8ac 100644 (file)
@@ -1754,7 +1754,8 @@ execute_storeindex(isn_T *iptr, ectx_T *ectx)
        {
            listitem_T *li = list_find(list, lidx);
 
-           if (error_if_locked(li->li_tv.v_lock, e_cannot_change_list_item))
+           if (error_if_locked(li->li_tv.v_lock,
+                                            e_cannot_change_locked_list_item))
                return FAIL;
            // overwrite existing list item
            clear_tv(&li->li_tv);
@@ -1762,7 +1763,7 @@ execute_storeindex(isn_T *iptr, ectx_T *ectx)
        }
        else
        {
-           if (error_if_locked(list->lv_lock, e_cannot_change_list))
+           if (error_if_locked(list->lv_lock, e_cannot_change_locked_list))
                return FAIL;
            // append to list, only fails when out of memory
            if (list_append_tv(list, tv) == FAIL)