patch 9.0.1431: getscriptinfo() loops even when specific SID is given

Problem:    getscriptinfo() loops even when specific SID is given.
Solution:   Only loop when needed.  Give a clearer error message.
            (closes #12207)
diff --git a/src/scriptfile.c b/src/scriptfile.c
index acc1deb..dd4a352 100644
--- a/src/scriptfile.c
+++ b/src/scriptfile.c
@@ -1299,7 +1299,7 @@
  * ":source" and associated commands.
  */
 
-#ifdef FEAT_EVAL
+#if defined(FEAT_EVAL) || defined(PROTO)
 /*
  * Return the address holding the next breakpoint line for a source cookie.
  */
@@ -2096,7 +2096,6 @@
     void
 f_getscriptinfo(typval_T *argvars, typval_T *rettv)
 {
-    int		i;
     list_T	*l;
     char_u	*pat = NULL;
     regmatch_T	regmatch;
@@ -2116,8 +2115,22 @@
 
     if (argvars[0].v_type == VAR_DICT)
     {
-	sid = dict_get_number_def(argvars[0].vval.v_dict, "sid", -1);
-	if (sid == -1)
+	dictitem_T *sid_di = dict_find(argvars[0].vval.v_dict,
+							   (char_u *)"sid", 3);
+	if (sid_di != NULL)
+	{
+	    int error = FALSE;
+	    sid = tv_get_number_chk(&sid_di->di_tv, &error);
+	    if (error)
+		return;
+	    if (sid <= 0)
+	    {
+		semsg(e_invalid_value_for_argument_str_str, "sid",
+						tv_get_string(&sid_di->di_tv));
+		return;
+	    }
+	}
+	else
 	{
 	    pat = dict_get_string(argvars[0].vval.v_dict, "name", TRUE);
 	    if (pat != NULL)
@@ -2127,7 +2140,8 @@
 	}
     }
 
-    for (i = 1; i <= script_items.ga_len; ++i)
+    for (varnumber_T i = sid > 0 ? sid : 1;
+		       (i == sid || sid <= 0) && i <= script_items.ga_len; ++i)
     {
 	scriptitem_T	*si = SCRIPT_ITEM(i);
 	dict_T		*d;
@@ -2138,9 +2152,6 @@
 	if (filterpat && !vim_regexec(&regmatch, si->sn_name, (colnr_T)0))
 	    continue;
 
-	if (sid != -1 && sid != i)
-	    continue;
-
 	if ((d = dict_alloc()) == NULL
 		|| list_append_dict(l, d) == FAIL
 		|| dict_add_string(d, "name", si->sn_name) == FAIL
@@ -2151,10 +2162,9 @@
 				si->sn_state == SN_STATE_NOT_LOADED) == FAIL)
 	    return;
 
-	// When a filter pattern is specified to return information about only
-	// specific script(s), also add the script-local variables and
-	// functions.
-	if (sid != -1)
+	// When a script ID is specified, return information about only the
+	// specified script, and add the script-local variables and functions.
+	if (sid > 0)
 	{
 	    dict_T	*var_dict;
 
diff --git a/src/testdir/test_scriptnames.vim b/src/testdir/test_scriptnames.vim
index 3f81349..a5b38ea 100644
--- a/src/testdir/test_scriptnames.vim
+++ b/src/testdir/test_scriptnames.vim
@@ -91,6 +91,16 @@
   call assert_fails("echo getscriptinfo('foobar')", 'E1206:')
 
   call assert_fails("echo getscriptinfo({'sid': []})", 'E745:')
+  call assert_fails("echo getscriptinfo({'sid': {}})", 'E728:')
+  call assert_fails("echo getscriptinfo({'sid': 0})", 'E475:')
+  call assert_fails("echo getscriptinfo({'sid': -1})", 'E475:')
+  call assert_fails("echo getscriptinfo({'sid': -999})", 'E475:')
+
+  echo getscriptinfo({'sid': '1'})
+  call assert_fails("vim9cmd echo getscriptinfo({'sid': '1'})", 'E1030:')
+
+  let max_sid = max(map(getscriptinfo(), { k, v -> v.sid }))
+  call assert_equal([], getscriptinfo({'sid': max_sid + 1}))
 endfunc
 
 " vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index ee7b363..614bffc 100644
--- a/src/version.c
+++ b/src/version.c
@@ -696,6 +696,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1431,
+/**/
     1430,
 /**/
     1429,