forked from aniani/vim
patch 8.2.2441: Vim9: extend() does not give an error for a type mismatch
Problem: Vim9: extend() does not give an error for a type mismatch. Solution: Check the type of the second argument. (closes #7760)
This commit is contained in:
34
src/list.c
34
src/list.c
@@ -2493,6 +2493,16 @@ f_count(typval_T *argvars, typval_T *rettv)
|
||||
static void
|
||||
extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new)
|
||||
{
|
||||
type_T *type = NULL;
|
||||
garray_T type_list;
|
||||
|
||||
if (!is_new && in_vim9script())
|
||||
{
|
||||
// Check that map() does not change the type of the dict.
|
||||
ga_init2(&type_list, sizeof(type_T *), 10);
|
||||
type = typval2type(argvars, &type_list);
|
||||
}
|
||||
|
||||
if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST)
|
||||
{
|
||||
list_T *l1, *l2;
|
||||
@@ -2504,7 +2514,7 @@ extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new)
|
||||
if (l1 == NULL)
|
||||
{
|
||||
emsg(_(e_cannot_extend_null_list));
|
||||
return;
|
||||
goto theend;
|
||||
}
|
||||
l2 = argvars[1].vval.v_list;
|
||||
if ((is_new || !value_check_lock(l1->lv_lock, arg_errmsg, TRUE))
|
||||
@@ -2514,14 +2524,14 @@ extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new)
|
||||
{
|
||||
l1 = list_copy(l1, FALSE, get_copyID());
|
||||
if (l1 == NULL)
|
||||
return;
|
||||
goto theend;
|
||||
}
|
||||
|
||||
if (argvars[2].v_type != VAR_UNKNOWN)
|
||||
{
|
||||
before = (long)tv_get_number_chk(&argvars[2], &error);
|
||||
if (error)
|
||||
return; // type error; errmsg already given
|
||||
goto theend; // type error; errmsg already given
|
||||
|
||||
if (before == l1->lv_len)
|
||||
item = NULL;
|
||||
@@ -2531,12 +2541,14 @@ extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new)
|
||||
if (item == NULL)
|
||||
{
|
||||
semsg(_(e_listidx), before);
|
||||
return;
|
||||
goto theend;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
item = NULL;
|
||||
if (type != NULL && check_typval_type(type, &argvars[1], 2) == FAIL)
|
||||
goto theend;
|
||||
list_extend(l1, l2, item);
|
||||
|
||||
if (is_new)
|
||||
@@ -2559,7 +2571,7 @@ extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new)
|
||||
if (d1 == NULL)
|
||||
{
|
||||
emsg(_(e_cannot_extend_null_dict));
|
||||
return;
|
||||
goto theend;
|
||||
}
|
||||
d2 = argvars[1].vval.v_dict;
|
||||
if ((is_new || !value_check_lock(d1->dv_lock, arg_errmsg, TRUE))
|
||||
@@ -2569,7 +2581,7 @@ extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new)
|
||||
{
|
||||
d1 = dict_copy(d1, FALSE, get_copyID());
|
||||
if (d1 == NULL)
|
||||
return;
|
||||
goto theend;
|
||||
}
|
||||
|
||||
// Check the third argument.
|
||||
@@ -2579,19 +2591,21 @@ extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new)
|
||||
|
||||
action = tv_get_string_chk(&argvars[2]);
|
||||
if (action == NULL)
|
||||
return; // type error; errmsg already given
|
||||
goto theend; // type error; errmsg already given
|
||||
for (i = 0; i < 3; ++i)
|
||||
if (STRCMP(action, av[i]) == 0)
|
||||
break;
|
||||
if (i == 3)
|
||||
{
|
||||
semsg(_(e_invarg2), action);
|
||||
return;
|
||||
goto theend;
|
||||
}
|
||||
}
|
||||
else
|
||||
action = (char_u *)"force";
|
||||
|
||||
if (type != NULL && check_typval_type(type, &argvars[1], 2) == FAIL)
|
||||
goto theend;
|
||||
dict_extend(d1, d2, action);
|
||||
|
||||
if (is_new)
|
||||
@@ -2606,6 +2620,10 @@ extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new)
|
||||
}
|
||||
else
|
||||
semsg(_(e_listdictarg), is_new ? "extendnew()" : "extend()");
|
||||
|
||||
theend:
|
||||
if (type != NULL)
|
||||
clear_type_list(&type_list);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user