forked from aniani/vim
patch 8.2.2781: add() silently skips when adding to null list or blob
Problem: Add() silently skips when adding to null list or blob. Solution: Give an error in Vim9 script. Allocate blob when it is NULL like with list and dict.
This commit is contained in:
@@ -2662,6 +2662,12 @@ eval_variable(
|
|||||||
if (tv->vval.v_list != NULL)
|
if (tv->vval.v_list != NULL)
|
||||||
++tv->vval.v_list->lv_refcount;
|
++tv->vval.v_list->lv_refcount;
|
||||||
}
|
}
|
||||||
|
else if (tv->v_type == VAR_BLOB && tv->vval.v_blob == NULL)
|
||||||
|
{
|
||||||
|
tv->vval.v_blob = blob_alloc();
|
||||||
|
if (tv->vval.v_blob != NULL)
|
||||||
|
++tv->vval.v_blob->bv_refcount;
|
||||||
|
}
|
||||||
copy_tv(tv, rettv);
|
copy_tv(tv, rettv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
27
src/list.c
27
src/list.c
@@ -2412,22 +2412,33 @@ f_mapnew(typval_T *argvars, typval_T *rettv)
|
|||||||
void
|
void
|
||||||
f_add(typval_T *argvars, typval_T *rettv)
|
f_add(typval_T *argvars, typval_T *rettv)
|
||||||
{
|
{
|
||||||
list_T *l;
|
|
||||||
blob_T *b;
|
|
||||||
|
|
||||||
rettv->vval.v_number = 1; // Default: Failed
|
rettv->vval.v_number = 1; // Default: Failed
|
||||||
if (argvars[0].v_type == VAR_LIST)
|
if (argvars[0].v_type == VAR_LIST)
|
||||||
{
|
{
|
||||||
if ((l = argvars[0].vval.v_list) != NULL
|
list_T *l = argvars[0].vval.v_list;
|
||||||
&& !value_check_lock(l->lv_lock,
|
|
||||||
(char_u *)N_("add() argument"), TRUE)
|
if (l == NULL)
|
||||||
|
{
|
||||||
|
if (in_vim9script())
|
||||||
|
emsg(_(e_cannot_add_to_null_list));
|
||||||
|
}
|
||||||
|
else if (!value_check_lock(l->lv_lock,
|
||||||
|
(char_u *)N_("add() argument"), TRUE)
|
||||||
&& list_append_tv(l, &argvars[1]) == OK)
|
&& list_append_tv(l, &argvars[1]) == OK)
|
||||||
|
{
|
||||||
copy_tv(&argvars[0], rettv);
|
copy_tv(&argvars[0], rettv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (argvars[0].v_type == VAR_BLOB)
|
else if (argvars[0].v_type == VAR_BLOB)
|
||||||
{
|
{
|
||||||
if ((b = argvars[0].vval.v_blob) != NULL
|
blob_T *b = argvars[0].vval.v_blob;
|
||||||
&& !value_check_lock(b->bv_lock,
|
|
||||||
|
if (b == NULL)
|
||||||
|
{
|
||||||
|
if (in_vim9script())
|
||||||
|
emsg(_(e_cannot_add_to_null_blob));
|
||||||
|
}
|
||||||
|
else if (!value_check_lock(b->bv_lock,
|
||||||
(char_u *)N_("add() argument"), TRUE))
|
(char_u *)N_("add() argument"), TRUE))
|
||||||
{
|
{
|
||||||
int error = FALSE;
|
int error = FALSE;
|
||||||
|
@@ -316,27 +316,59 @@ func Test_blob_for_loop()
|
|||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_blob_concatenate()
|
func Test_blob_concatenate()
|
||||||
let b = 0z0011
|
let lines =<< trim END
|
||||||
let b += 0z2233
|
VAR b = 0z0011
|
||||||
call assert_equal(0z00112233, b)
|
LET b += 0z2233
|
||||||
|
call assert_equal(0z00112233, b)
|
||||||
|
|
||||||
call assert_fails('let b += "a"')
|
LET b = 0zDEAD + 0zBEEF
|
||||||
call assert_fails('let b += 88')
|
call assert_equal(0zDEADBEEF, b)
|
||||||
|
END
|
||||||
|
call CheckLegacyAndVim9Success(lines)
|
||||||
|
|
||||||
let b = 0zDEAD + 0zBEEF
|
let lines =<< trim END
|
||||||
call assert_equal(0zDEADBEEF, b)
|
VAR b = 0z0011
|
||||||
|
LET b += "a"
|
||||||
|
END
|
||||||
|
call CheckLegacyAndVim9Failure(lines, ['E734:', 'E1012:', 'E734:'])
|
||||||
|
|
||||||
|
let lines =<< trim END
|
||||||
|
VAR b = 0z0011
|
||||||
|
LET b += 88
|
||||||
|
END
|
||||||
|
call CheckLegacyAndVim9Failure(lines, ['E734:', 'E1012:', 'E734:'])
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_blob_add()
|
func Test_blob_add()
|
||||||
|
let lines =<< trim END
|
||||||
|
VAR b = 0z0011
|
||||||
|
call add(b, 0x22)
|
||||||
|
call assert_equal(0z001122, b)
|
||||||
|
END
|
||||||
|
call CheckLegacyAndVim9Success(lines)
|
||||||
|
|
||||||
|
" Only works in legacy script
|
||||||
let b = 0z0011
|
let b = 0z0011
|
||||||
call add(b, 0x22)
|
|
||||||
call assert_equal(0z001122, b)
|
|
||||||
call add(b, '51')
|
call add(b, '51')
|
||||||
call assert_equal(0z00112233, b)
|
call assert_equal(0z001133, b)
|
||||||
call assert_equal(1, add(test_null_blob(), 0x22))
|
call assert_equal(1, add(test_null_blob(), 0x22))
|
||||||
|
|
||||||
call assert_fails('call add(b, [9])', 'E745:')
|
let lines =<< trim END
|
||||||
call assert_fails('call add("", 0x01)', 'E897:')
|
VAR b = 0z0011
|
||||||
|
call add(b, [9])
|
||||||
|
END
|
||||||
|
call CheckLegacyAndVim9Failure(lines, ['E745:', 'E1012:', 'E745:'])
|
||||||
|
|
||||||
|
let lines =<< trim END
|
||||||
|
VAR b = 0z0011
|
||||||
|
call add("", 0x01)
|
||||||
|
END
|
||||||
|
call CheckLegacyAndVim9Failure(lines, 'E897:')
|
||||||
|
|
||||||
|
let lines =<< trim END
|
||||||
|
add(test_null_blob(), 0x22)
|
||||||
|
END
|
||||||
|
call CheckDefExecAndScriptFailure(lines, 'E1131:')
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_blob_empty()
|
func Test_blob_empty()
|
||||||
|
@@ -86,11 +86,24 @@ def Test_add_list()
|
|||||||
END
|
END
|
||||||
CheckDefFailure(lines, 'E1012:', 2)
|
CheckDefFailure(lines, 'E1012:', 2)
|
||||||
|
|
||||||
|
lines =<< trim END
|
||||||
|
add(test_null_list(), 123)
|
||||||
|
END
|
||||||
|
CheckDefExecAndScriptFailure(lines, 'E1130:', 1)
|
||||||
|
|
||||||
lines =<< trim END
|
lines =<< trim END
|
||||||
var l: list<number> = test_null_list()
|
var l: list<number> = test_null_list()
|
||||||
add(l, 123)
|
add(l, 123)
|
||||||
END
|
END
|
||||||
CheckDefExecFailure(lines, 'E1130:', 2)
|
CheckDefExecFailure(lines, 'E1130:', 2)
|
||||||
|
|
||||||
|
# Getting variable with NULL list allocates a new list at script level
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
var l: list<number> = test_null_list()
|
||||||
|
add(l, 123)
|
||||||
|
END
|
||||||
|
CheckScriptSuccess(lines)
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_add_blob()
|
def Test_add_blob()
|
||||||
@@ -108,11 +121,24 @@ def Test_add_blob()
|
|||||||
END
|
END
|
||||||
CheckDefFailure(lines, 'E1012:', 2)
|
CheckDefFailure(lines, 'E1012:', 2)
|
||||||
|
|
||||||
|
lines =<< trim END
|
||||||
|
add(test_null_blob(), 123)
|
||||||
|
END
|
||||||
|
CheckDefExecAndScriptFailure(lines, 'E1131:', 1)
|
||||||
|
|
||||||
lines =<< trim END
|
lines =<< trim END
|
||||||
var b: blob = test_null_blob()
|
var b: blob = test_null_blob()
|
||||||
add(b, 123)
|
add(b, 123)
|
||||||
END
|
END
|
||||||
CheckDefExecFailure(lines, 'E1131:', 2)
|
CheckDefExecFailure(lines, 'E1131:', 2)
|
||||||
|
|
||||||
|
# Getting variable with NULL blob allocates a new blob at script level
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
var b: blob = test_null_blob()
|
||||||
|
add(b, 123)
|
||||||
|
END
|
||||||
|
CheckScriptSuccess(lines)
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_append()
|
def Test_append()
|
||||||
|
@@ -750,6 +750,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
2781,
|
||||||
/**/
|
/**/
|
||||||
2780,
|
2780,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -1020,6 +1020,10 @@ allocate_if_null(typval_T *tv)
|
|||||||
if (tv->vval.v_dict == NULL)
|
if (tv->vval.v_dict == NULL)
|
||||||
(void)rettv_dict_alloc(tv);
|
(void)rettv_dict_alloc(tv);
|
||||||
break;
|
break;
|
||||||
|
case VAR_BLOB:
|
||||||
|
if (tv->vval.v_blob == NULL)
|
||||||
|
(void)rettv_blob_alloc(tv);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user