Skip to content

Commit 70c43d8

Browse files
committed
patch 8.2.4225: Vim9: depth argument of :lockvar not parsed in :def function
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.
1 parent 1080c48 commit 70c43d8

File tree

9 files changed

+82
-18
lines changed

9 files changed

+82
-18
lines changed

src/errors.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2859,10 +2859,10 @@ EXTERN char e_assert_fails_fifth_argument[]
28592859
INIT(= N_("E1116: \"assert_fails()\" fifth argument must be a string"));
28602860
EXTERN char e_cannot_use_bang_with_nested_def[]
28612861
INIT(= N_("E1117: Cannot use ! with nested :def"));
2862-
EXTERN char e_cannot_change_list[]
2863-
INIT(= N_("E1118: Cannot change list"));
2864-
EXTERN char e_cannot_change_list_item[]
2865-
INIT(= N_("E1119: Cannot change list item"));
2862+
EXTERN char e_cannot_change_locked_list[]
2863+
INIT(= N_("E1118: Cannot change locked list"));
2864+
EXTERN char e_cannot_change_locked_list_item[]
2865+
INIT(= N_("E1119: Cannot change locked list item"));
28662866
EXTERN char e_cannot_change_dict[]
28672867
INIT(= N_("E1120: Cannot change dict"));
28682868
EXTERN char e_cannot_change_dict_item[]

src/evalfunc.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7922,16 +7922,21 @@ range_list_materialize(list_T *list)
79227922
{
79237923
varnumber_T start = list->lv_u.nonmat.lv_start;
79247924
varnumber_T end = list->lv_u.nonmat.lv_end;
7925-
int stride = list->lv_u.nonmat.lv_stride;
7925+
int stride = list->lv_u.nonmat.lv_stride;
79267926
varnumber_T i;
79277927

79287928
list->lv_first = NULL;
79297929
list->lv_u.mat.lv_last = NULL;
79307930
list->lv_len = 0;
79317931
list->lv_u.mat.lv_idx_item = NULL;
79327932
for (i = start; stride > 0 ? i <= end : i >= end; i += stride)
7933+
{
79337934
if (list_append_number(list, (varnumber_T)i) == FAIL)
79347935
break;
7936+
if (list->lv_lock & VAR_ITEMS_LOCKED)
7937+
list->lv_u.mat.lv_last->li_tv.v_lock = VAR_LOCKED;
7938+
}
7939+
list->lv_lock &= ~VAR_ITEMS_LOCKED;
79357940
}
79367941

79377942
/*

src/evalvars.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2060,10 +2060,18 @@ item_lock(typval_T *tv, int deep, int lock, int check_refcount)
20602060
l->lv_lock |= VAR_LOCKED;
20612061
else
20622062
l->lv_lock &= ~VAR_LOCKED;
2063-
if ((deep < 0 || deep > 1) && l->lv_first != &range_list_item)
2064-
// recursive: lock/unlock the items the List contains
2065-
FOR_ALL_LIST_ITEMS(l, li)
2066-
item_lock(&li->li_tv, deep - 1, lock, check_refcount);
2063+
if (deep < 0 || deep > 1)
2064+
{
2065+
if (l->lv_first == &range_list_item)
2066+
l->lv_lock |= VAR_ITEMS_LOCKED;
2067+
else
2068+
{
2069+
// recursive: lock/unlock the items the List contains
2070+
CHECK_LIST_MATERIALIZE(l);
2071+
FOR_ALL_LIST_ITEMS(l, li) item_lock(&li->li_tv,
2072+
deep - 1, lock, check_refcount);
2073+
}
2074+
}
20672075
}
20682076
break;
20692077
case VAR_DICT:

src/structs.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1464,8 +1464,9 @@ typedef struct
14641464
// allowed to mask existing functions
14651465

14661466
// Values for "v_lock".
1467-
#define VAR_LOCKED 1 // locked with lock(), can use unlock()
1468-
#define VAR_FIXED 2 // locked forever
1467+
#define VAR_LOCKED 1 // locked with lock(), can use unlock()
1468+
#define VAR_FIXED 2 // locked forever
1469+
#define VAR_ITEMS_LOCKED 4 // items of non-materialized list locked
14691470

14701471
/*
14711472
* Structure to hold an item of a list: an internal variable without a name.
@@ -1497,7 +1498,8 @@ struct listwatch_S
14971498
*/
14981499
struct listvar_S
14991500
{
1500-
listitem_T *lv_first; // first item, NULL if none
1501+
listitem_T *lv_first; // first item, NULL if none, &range_list_item
1502+
// for a non-materialized list
15011503
listwatch_T *lv_watch; // first watcher, NULL if none
15021504
union {
15031505
struct { // used for non-materialized range list:

src/testdir/test_vim9_cmd.vim

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1396,6 +1396,35 @@ def Test_lockvar()
13961396
lockvar whatever
13971397
endif
13981398

1399+
g:lockme = [1, 2, 3]
1400+
lockvar 1 g:lockme
1401+
g:lockme[1] = 77
1402+
assert_equal([1, 77, 3], g:lockme)
1403+
1404+
lockvar 2 g:lockme
1405+
var caught = false
1406+
try
1407+
g:lockme[1] = 99
1408+
catch /E1119:/
1409+
caught = true
1410+
endtry
1411+
assert_true(caught)
1412+
assert_equal([1, 77, 3], g:lockme)
1413+
unlet g:lockme
1414+
1415+
# also for non-materialized list
1416+
g:therange = range(3)
1417+
lockvar 2 g:therange
1418+
caught = false
1419+
try
1420+
g:therange[1] = 99
1421+
catch /E1119:/
1422+
caught = true
1423+
endtry
1424+
assert_true(caught)
1425+
assert_equal([0, 1, 2], g:therange)
1426+
unlet g:therange
1427+
13991428
var d = {a: 1, b: 2}
14001429
d.a = 3
14011430
d.b = 4

src/testdir/test_vim9_disassemble.vim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -625,7 +625,7 @@ def Test_disassemble_locl_local()
625625
'\d STORE $0\_s*' ..
626626
'lockvar d.a\_s*' ..
627627
'\d LOAD $0\_s*' ..
628-
'\d LOCKUNLOCK lockvar d.a\_s*',
628+
'\d LOCKUNLOCK lockvar 2 d.a\_s*',
629629
res)
630630
enddef
631631

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,8 @@ static char *(features[]) =
750750

751751
static int included_patches[] =
752752
{ /* Add new patch number below this line */
753+
/**/
754+
4225,
753755
/**/
754756
4224,
755757
/**/

src/vim9cmds.c

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ compile_lock_unlock(
178178
lval_T *lvp,
179179
char_u *name_end,
180180
exarg_T *eap,
181-
int deep UNUSED,
181+
int deep,
182182
void *coookie)
183183
{
184184
cctx_T *cctx = coookie;
@@ -223,8 +223,9 @@ compile_lock_unlock(
223223
ret = FAIL;
224224
else
225225
{
226-
vim_snprintf((char *)buf, len, "%s %s",
226+
vim_snprintf((char *)buf, len, "%s %d %s",
227227
eap->cmdidx == CMD_lockvar ? "lockvar" : "unlockvar",
228+
deep,
228229
p);
229230
ret = generate_EXEC_copy(cctx, isn, buf);
230231

@@ -241,7 +242,23 @@ compile_lock_unlock(
241242
char_u *
242243
compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx)
243244
{
244-
ex_unletlock(eap, arg, 0, GLV_NO_AUTOLOAD | GLV_COMPILING,
245+
int deep = 0;
246+
char_u *p = arg;
247+
248+
if (eap->cmdidx != CMD_unlet)
249+
{
250+
if (eap->forceit)
251+
deep = -1;
252+
else if (vim_isdigit(*p))
253+
{
254+
deep = getdigits(&p);
255+
p = skipwhite(p);
256+
}
257+
else
258+
deep = 2;
259+
}
260+
261+
ex_unletlock(eap, p, deep, GLV_NO_AUTOLOAD | GLV_COMPILING,
245262
eap->cmdidx == CMD_unlet ? compile_unlet : compile_lock_unlock,
246263
cctx);
247264
return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd;

src/vim9execute.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1754,15 +1754,16 @@ execute_storeindex(isn_T *iptr, ectx_T *ectx)
17541754
{
17551755
listitem_T *li = list_find(list, lidx);
17561756

1757-
if (error_if_locked(li->li_tv.v_lock, e_cannot_change_list_item))
1757+
if (error_if_locked(li->li_tv.v_lock,
1758+
e_cannot_change_locked_list_item))
17581759
return FAIL;
17591760
// overwrite existing list item
17601761
clear_tv(&li->li_tv);
17611762
li->li_tv = *tv;
17621763
}
17631764
else
17641765
{
1765-
if (error_if_locked(list->lv_lock, e_cannot_change_list))
1766+
if (error_if_locked(list->lv_lock, e_cannot_change_locked_list))
17661767
return FAIL;
17671768
// append to list, only fails when out of memory
17681769
if (list_append_tv(list, tv) == FAIL)

0 commit comments

Comments
 (0)