changeset 24812:8fdf839af1f4 v8.2.2944

patch 8.2.2944: Vim9: no error when using job or channel as a string Commit: https://github.com/vim/vim/commit/1328bde9d406aa1292e92673fa8a026889424e79 Author: Bram Moolenaar <Bram@vim.org> Date: Sat Jun 5 20:51:38 2021 +0200 patch 8.2.2944: Vim9: no error when using job or channel as a string Problem: Vim9: no error when using job or channel as a string. Solution: Be more strict about conversion to string. (closes https://github.com/vim/vim/issues/8312)
author Bram Moolenaar <Bram@vim.org>
date Sat, 05 Jun 2021 21:00:03 +0200
parents e89d42919a21
children fd32e504070c
files src/channel.c src/eval.c src/job.c src/proto/channel.pro src/proto/job.pro src/testdir/test_vim9_builtin.vim src/typval.c src/version.c src/vim9execute.c
diffstat 9 files changed, 76 insertions(+), 34 deletions(-) [+]
line wrap: on
line diff
--- a/src/channel.c
+++ b/src/channel.c
@@ -5015,4 +5015,22 @@ f_ch_status(typval_T *argvars, typval_T 
     rettv->vval.v_string = vim_strsave((char_u *)channel_status(channel, part));
 }
 
+/*
+ * Get a string with information about the channel in "varp" in "buf".
+ * "buf" must be at least NUMBUFLEN long.
+ */
+    char_u *
+channel_to_string_buf(typval_T *varp, char_u *buf)
+{
+    channel_T *channel = varp->vval.v_channel;
+    char      *status = channel_status(channel, -1);
+
+    if (channel == NULL)
+	vim_snprintf((char *)buf, NUMBUFLEN, "channel %s", status);
+    else
+	vim_snprintf((char *)buf, NUMBUFLEN,
+				      "channel %d %s", channel->ch_id, status);
+    return buf;
+}
+
 #endif // FEAT_JOB_CHANNEL
--- a/src/eval.c
+++ b/src/eval.c
@@ -5060,7 +5060,8 @@ echo_string_core(
 	case VAR_JOB:
 	case VAR_CHANNEL:
 	    *tofree = NULL;
-	    r = tv_get_string_buf(tv, numbuf);
+	    r = tv->v_type == VAR_JOB ? job_to_string_buf(tv, numbuf)
+					   : channel_to_string_buf(tv, numbuf);
 	    if (composite_val)
 	    {
 		*tofree = string_quote(r, FALSE);
--- a/src/job.c
+++ b/src/job.c
@@ -1927,4 +1927,34 @@ f_job_stop(typval_T *argvars, typval_T *
 	rettv->vval.v_number = job_stop(job, argvars, NULL);
 }
 
+/*
+ * Get a string with information about the job in "varp" in "buf".
+ * "buf" must be at least NUMBUFLEN long.
+ */
+    char_u *
+job_to_string_buf(typval_T *varp, char_u *buf)
+{
+    job_T *job = varp->vval.v_job;
+    char  *status;
+
+    if (job == NULL)
+	return (char_u *)"no process";
+    status = job->jv_status == JOB_FAILED ? "fail"
+		    : job->jv_status >= JOB_ENDED ? "dead"
+		    : "run";
+# ifdef UNIX
+    vim_snprintf((char *)buf, NUMBUFLEN,
+		"process %ld %s", (long)job->jv_pid, status);
+# elif defined(MSWIN)
+    vim_snprintf((char *)buf, NUMBUFLEN,
+		"process %ld %s",
+		(long)job->jv_proc_info.dwProcessId,
+		status);
+# else
+    // fall-back
+    vim_snprintf((char *)buf, NUMBUFLEN, "process ? %s", status);
+# endif
+    return buf;
+}
+
 #endif // FEAT_JOB_CHANNEL
--- a/src/proto/channel.pro
+++ b/src/proto/channel.pro
@@ -58,4 +58,5 @@ void f_ch_evalraw(typval_T *argvars, typ
 void f_ch_sendraw(typval_T *argvars, typval_T *rettv);
 void f_ch_setoptions(typval_T *argvars, typval_T *rettv);
 void f_ch_status(typval_T *argvars, typval_T *rettv);
+char_u *channel_to_string_buf(typval_T *varp, char_u *buf);
 /* vim: set ft=c : */
--- a/src/proto/job.pro
+++ b/src/proto/job.pro
@@ -34,4 +34,5 @@ void f_job_setoptions(typval_T *argvars,
 void f_job_start(typval_T *argvars, typval_T *rettv);
 void f_job_status(typval_T *argvars, typval_T *rettv);
 void f_job_stop(typval_T *argvars, typval_T *rettv);
+char_u *job_to_string_buf(typval_T *varp, char_u *buf);
 /* vim: set ft=c : */
--- a/src/testdir/test_vim9_builtin.vim
+++ b/src/testdir/test_vim9_builtin.vim
@@ -1104,7 +1104,7 @@ def Test_set_get_bufline()
       assert_equal([], getbufline(b, 2, 1))
 
       if has('job')
-        setbufline(b, 2, [function('eval'), {key: 123}, test_null_job()])
+        setbufline(b, 2, [function('eval'), {key: 123}, string(test_null_job())])
         assert_equal(["function('eval')",
                         "{'key': 123}",
                         "no process"],
@@ -1250,6 +1250,16 @@ def Test_submatch()
   actual->assert_equal(expected)
 enddef
 
+def Test_substitute()
+  var res = substitute('A1234', '\d', 'X', '')
+  assert_equal('AX234', res)
+
+  if has('job')
+    assert_fails('"text"->substitute(".*", () => job_start(":"), "")', 'E908: using an invalid value as a String: job')
+    assert_fails('"text"->substitute(".*", () => job_start(":")->job_getchannel(), "")', 'E908: using an invalid value as a String: channel')
+  endif
+enddef
+
 def Test_synID()
   new
   setline(1, "text")
--- a/src/typval.c
+++ b/src/typval.c
@@ -414,7 +414,7 @@ tv_get_string_strict(typval_T *varp)
     char_u *
 tv_get_string_buf(typval_T *varp, char_u *buf)
 {
-    char_u	*res =  tv_get_string_buf_chk(varp, buf);
+    char_u	*res = tv_get_string_buf_chk(varp, buf);
 
     return res != NULL ? res : (char_u *)"";
 }
@@ -478,44 +478,22 @@ tv_get_string_buf_chk_strict(typval_T *v
 	    break;
 	case VAR_JOB:
 #ifdef FEAT_JOB_CHANNEL
+	    if (in_vim9script())
 	    {
-		job_T *job = varp->vval.v_job;
-		char  *status;
-
-		if (job == NULL)
-		    return (char_u *)"no process";
-		status = job->jv_status == JOB_FAILED ? "fail"
-				: job->jv_status >= JOB_ENDED ? "dead"
-				: "run";
-# ifdef UNIX
-		vim_snprintf((char *)buf, NUMBUFLEN,
-			    "process %ld %s", (long)job->jv_pid, status);
-# elif defined(MSWIN)
-		vim_snprintf((char *)buf, NUMBUFLEN,
-			    "process %ld %s",
-			    (long)job->jv_proc_info.dwProcessId,
-			    status);
-# else
-		// fall-back
-		vim_snprintf((char *)buf, NUMBUFLEN, "process ? %s", status);
-# endif
-		return buf;
+		semsg(_(e_using_invalid_value_as_string_str), "job");
+		break;
 	    }
+	    return job_to_string_buf(varp, buf);
 #endif
 	    break;
 	case VAR_CHANNEL:
 #ifdef FEAT_JOB_CHANNEL
+	    if (in_vim9script())
 	    {
-		channel_T *channel = varp->vval.v_channel;
-		char      *status = channel_status(channel, -1);
-
-		if (channel == NULL)
-		    vim_snprintf((char *)buf, NUMBUFLEN, "channel %s", status);
-		else
-		    vim_snprintf((char *)buf, NUMBUFLEN,
-				     "channel %d %s", channel->ch_id, status);
-		return buf;
+		semsg(_(e_using_invalid_value_as_string_str), "channel");
+		break;
 	    }
+	    return channel_to_string_buf(varp, buf);
 #endif
 	    break;
 	case VAR_UNKNOWN:
--- 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 */
 /**/
+    2944,
+/**/
     2943,
 /**/
     2942,
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -4831,10 +4831,11 @@ list_instructions(char *pfx, isn_T *inst
 		{
 		    typval_T	tv;
 		    char_u	*name;
+		    char_u	buf[NUMBUFLEN];
 
 		    tv.v_type = VAR_JOB;
 		    tv.vval.v_job = iptr->isn_arg.job;
-		    name = tv_get_string(&tv);
+		    name = job_to_string_buf(&tv, buf);
 		    smsg("%s%4d PUSHJOB \"%s\"", pfx, current, name);
 		}
 #endif