diff src/eval.c @ 25054:64bef59f11ef v8.2.3064

patch 8.2.3064: Vim9: in script cannot set item in uninitialized list Commit: https://github.com/vim/vim/commit/e65081d1b591f16dc6e380a830d87565c5eb7b03 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Jun 27 15:04:05 2021 +0200 patch 8.2.3064: Vim9: in script cannot set item in uninitialized list Problem: Vim9: in script cannot set item in uninitialized list. Solution: When a list is NULL allocate an empty one. (closes https://github.com/vim/vim/issues/8461)
author Bram Moolenaar <Bram@vim.org>
date Sun, 27 Jun 2021 15:15:03 +0200
parents 3b8d3b383fd6
children 8f2262c72178
line wrap: on
line diff
--- a/src/eval.c
+++ b/src/eval.c
@@ -932,15 +932,22 @@ get_lval(
 		semsg(_(e_dot_can_only_be_used_on_dictionary_str), name);
 	    return NULL;
 	}
-	if (!(lp->ll_tv->v_type == VAR_LIST && lp->ll_tv->vval.v_list != NULL)
-		&& !(lp->ll_tv->v_type == VAR_DICT)
-		&& !(lp->ll_tv->v_type == VAR_BLOB
-					   && lp->ll_tv->vval.v_blob != NULL))
+	if (lp->ll_tv->v_type != VAR_LIST
+		&& lp->ll_tv->v_type != VAR_DICT
+		&& lp->ll_tv->v_type != VAR_BLOB)
 	{
 	    if (!quiet)
 		emsg(_("E689: Can only index a List, Dictionary or Blob"));
 	    return NULL;
 	}
+
+	// a NULL list/blob works like an empty list/blob, allocate one now.
+	if (lp->ll_tv->v_type == VAR_LIST && lp->ll_tv->vval.v_list == NULL)
+	    rettv_list_alloc(lp->ll_tv);
+	else if (lp->ll_tv->v_type == VAR_BLOB
+					     && lp->ll_tv->vval.v_blob == NULL)
+	    rettv_blob_alloc(lp->ll_tv);
+
 	if (lp->ll_range)
 	{
 	    if (!quiet)
@@ -1201,10 +1208,20 @@ get_lval(
 	    lp->ll_li = list_find_index(lp->ll_list, &lp->ll_n1);
 	    if (lp->ll_li == NULL)
 	    {
-		clear_tv(&var2);
-		if (!quiet)
-		    semsg(_(e_listidx), lp->ll_n1);
-		return NULL;
+		// Vim9: Allow for adding an item at the end.
+		if (in_vim9script() && lp->ll_n1 == lp->ll_list->lv_len
+						  && lp->ll_list->lv_lock == 0)
+		{
+		    list_append_number(lp->ll_list, 0);
+		    lp->ll_li = list_find_index(lp->ll_list, &lp->ll_n1);
+		}
+		if (lp->ll_li == NULL)
+		{
+		    clear_tv(&var2);
+		    if (!quiet)
+			semsg(_(e_listidx), lp->ll_n1);
+		    return NULL;
+		}
 	    }
 
 	    if (lp->ll_valtype != NULL)