]> granicus.if.org Git - vim/commitdiff
patch 8.2.2944: Vim9: no error when using job or channel as a string v8.2.2944
authorBram Moolenaar <Bram@vim.org>
Sat, 5 Jun 2021 18:51:38 +0000 (20:51 +0200)
committerBram Moolenaar <Bram@vim.org>
Sat, 5 Jun 2021 18:51:38 +0000 (20:51 +0200)
Problem:    Vim9: no error when using job or channel as a string.
Solution:   Be more strict about conversion to string. (closes #8312)

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

index fa329bdba3ae26da0424761c9f5a5f1f89e08275..2a93e2578cae67f70c6fbdc8d156fcc184a52830 100644 (file)
@@ -5015,4 +5015,22 @@ f_ch_status(typval_T *argvars, typval_T *rettv)
     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
index 77578f3650525ed7f9f5e29f81ed7b0889c9fc8a..1fb1f5e70bc0226d65128b924c828a3bc237e499 100644 (file)
@@ -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);
index aeb2af7b532673baaa96baface5ee3eb5e765918..189c06eb6e0da2109e2f94e653ad1148c24462e0 100644 (file)
--- a/src/job.c
+++ b/src/job.c
@@ -1927,4 +1927,34 @@ f_job_stop(typval_T *argvars, typval_T *rettv)
        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
index bbe5288a386894462ce17d8e3835aae64e578a9f..32e68d894287cf1fdb228ede9677d318e4f2919e 100644 (file)
@@ -58,4 +58,5 @@ void f_ch_evalraw(typval_T *argvars, typval_T *rettv);
 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 : */
index bf97577e121991a4c0c11159f9db4b7171e2351a..3927e7f48eb0ff975d362fccdc5e7eaf8ae91fb0 100644 (file)
@@ -34,4 +34,5 @@ void f_job_setoptions(typval_T *argvars, typval_T *rettv);
 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 : */
index 9cae4a34e187beee9664311631a88af336b78d2f..b98c840ce04c9fb36b4c41dffce2f53f7103fe03 100644 (file)
@@ -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")
index 3d1bd7f53f773a257cebfb6ff4bce5de2ea745b1..f08d1aa42151d791faaac099a903f87c549bc57d 100644 (file)
@@ -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 *varp, char_u *buf, int strict)
            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:
index 87bc2a09ed87ca9e566c818001af9f22f3478e8b..b729c99f5e64a0686429c9dcb10bc91c27fad720 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2944,
 /**/
     2943,
 /**/
index 455a20507016cd606e7d2c34db828f8d585aa0ff..a13b0ab9869a7a4a29b82d9e5b7b123f41259c99 100644 (file)
@@ -4831,10 +4831,11 @@ list_instructions(char *pfx, isn_T *instr, int instr_count, ufunc_T *ufunc)
                {
                    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