summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2021-04-18 14:12:31 +0200
committerBram Moolenaar <Bram@vim.org>2021-04-18 14:12:31 +0200
commitb7c21afef14bba0208f2c40d47c050a004eb2f34 (patch)
treed7ac8993ffa95c8e45240dd873eb04e00235f074
parentd551d6c268e435e2fbba22775510fbd0a54477f6 (diff)
downloadvim-git-b7c21afef14bba0208f2c40d47c050a004eb2f34.tar.gz
patch 8.2.2781: add() silently skips when adding to null list or blobv8.2.2781
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.
-rw-r--r--src/evalvars.c6
-rw-r--r--src/list.c27
-rw-r--r--src/testdir/test_blob.vim56
-rw-r--r--src/testdir/test_vim9_builtin.vim26
-rw-r--r--src/version.c2
-rw-r--r--src/vim9execute.c4
6 files changed, 101 insertions, 20 deletions
diff --git a/src/evalvars.c b/src/evalvars.c
index ebfc42b18..9952ffcad 100644
--- a/src/evalvars.c
+++ b/src/evalvars.c
@@ -2662,6 +2662,12 @@ eval_variable(
if (tv->vval.v_list != NULL)
++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);
}
}
diff --git a/src/list.c b/src/list.c
index 56b2188ff..988b2d982 100644
--- a/src/list.c
+++ b/src/list.c
@@ -2412,22 +2412,33 @@ f_mapnew(typval_T *argvars, typval_T *rettv)
void
f_add(typval_T *argvars, typval_T *rettv)
{
- list_T *l;
- blob_T *b;
-
rettv->vval.v_number = 1; // Default: Failed
if (argvars[0].v_type == VAR_LIST)
{
- if ((l = argvars[0].vval.v_list) != NULL
- && !value_check_lock(l->lv_lock,
- (char_u *)N_("add() argument"), TRUE)
+ list_T *l = argvars[0].vval.v_list;
+
+ 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)
+ {
copy_tv(&argvars[0], rettv);
+ }
}
else if (argvars[0].v_type == VAR_BLOB)
{
- if ((b = argvars[0].vval.v_blob) != NULL
- && !value_check_lock(b->bv_lock,
+ blob_T *b = argvars[0].vval.v_blob;
+
+ 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))
{
int error = FALSE;
diff --git a/src/testdir/test_blob.vim b/src/testdir/test_blob.vim
index fa482b432..f54d7733f 100644
--- a/src/testdir/test_blob.vim
+++ b/src/testdir/test_blob.vim
@@ -316,27 +316,59 @@ func Test_blob_for_loop()
endfunc
func Test_blob_concatenate()
- let b = 0z0011
- let b += 0z2233
- call assert_equal(0z00112233, b)
+ let lines =<< trim END
+ VAR b = 0z0011
+ LET b += 0z2233
+ call assert_equal(0z00112233, b)
+
+ LET b = 0zDEAD + 0zBEEF
+ call assert_equal(0zDEADBEEF, b)
+ END
+ call CheckLegacyAndVim9Success(lines)
- call assert_fails('let b += "a"')
- call assert_fails('let b += 88')
+ let lines =<< trim END
+ VAR b = 0z0011
+ LET b += "a"
+ END
+ call CheckLegacyAndVim9Failure(lines, ['E734:', 'E1012:', 'E734:'])
- let b = 0zDEAD + 0zBEEF
- call assert_equal(0zDEADBEEF, b)
+ let lines =<< trim END
+ VAR b = 0z0011
+ LET b += 88
+ END
+ call CheckLegacyAndVim9Failure(lines, ['E734:', 'E1012:', 'E734:'])
endfunc
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
- call add(b, 0x22)
- call assert_equal(0z001122, b)
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_fails('call add(b, [9])', 'E745:')
- call assert_fails('call add("", 0x01)', 'E897:')
+ let lines =<< trim END
+ 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
func Test_blob_empty()
diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim
index 5c13d5127..bf15a4159 100644
--- a/src/testdir/test_vim9_builtin.vim
+++ b/src/testdir/test_vim9_builtin.vim
@@ -87,10 +87,23 @@ def Test_add_list()
CheckDefFailure(lines, 'E1012:', 2)
lines =<< trim END
+ add(test_null_list(), 123)
+ END
+ CheckDefExecAndScriptFailure(lines, 'E1130:', 1)
+
+ lines =<< trim END
var l: list<number> = test_null_list()
add(l, 123)
END
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
def Test_add_blob()
@@ -109,10 +122,23 @@ def Test_add_blob()
CheckDefFailure(lines, 'E1012:', 2)
lines =<< trim END
+ add(test_null_blob(), 123)
+ END
+ CheckDefExecAndScriptFailure(lines, 'E1131:', 1)
+
+ lines =<< trim END
var b: blob = test_null_blob()
add(b, 123)
END
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
def Test_append()
diff --git a/src/version.c b/src/version.c
index c3e2ea852..6216faff7 100644
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 2781,
+/**/
2780,
/**/
2779,
diff --git a/src/vim9execute.c b/src/vim9execute.c
index 4e1af4e58..60b58f98a 100644
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -1020,6 +1020,10 @@ allocate_if_null(typval_T *tv)
if (tv->vval.v_dict == NULL)
(void)rettv_dict_alloc(tv);
break;
+ case VAR_BLOB:
+ if (tv->vval.v_blob == NULL)
+ (void)rettv_blob_alloc(tv);
+ break;
default:
break;
}