mirror of
https://github.com/vim/vim.git
synced 2025-09-25 03:54:15 -04:00
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.
This commit is contained in:
@@ -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[]
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -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:
|
||||
|
@@ -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:
|
||||
|
@@ -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
|
||||
|
@@ -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 2 d.a\_s*',
|
||||
res)
|
||||
enddef
|
||||
|
||||
|
@@ -750,6 +750,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
4225,
|
||||
/**/
|
||||
4224,
|
||||
/**/
|
||||
|
@@ -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;
|
||||
|
@@ -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)
|
||||
|
Reference in New Issue
Block a user