summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2021-06-05 20:51:38 +0200
committerBram Moolenaar <Bram@vim.org>2021-06-05 20:51:38 +0200
commit1328bde9d406aa1292e92673fa8a026889424e79 (patch)
treea0415264993e4c6bc6ecf5d982aa20032b5d5af4
parentc6d71532dda0b3a244907bb5d1826f9340f7571d (diff)
patch 8.2.2944: Vim9: no error when using job or channel as a stringv8.2.2944
Problem: Vim9: no error when using job or channel as a string. Solution: Be more strict about conversion to string. (closes #8312)
-rw-r--r--src/channel.c18
-rw-r--r--src/eval.c3
-rw-r--r--src/job.c30
-rw-r--r--src/proto/channel.pro1
-rw-r--r--src/proto/job.pro1
-rw-r--r--src/testdir/test_vim9_builtin.vim12
-rw-r--r--src/typval.c40
-rw-r--r--src/version.c2
-rw-r--r--src/vim9execute.c3
9 files changed, 76 insertions, 34 deletions
diff --git a/src/channel.c b/src/channel.c
index fa329bdba3..2a93e2578c 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -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
diff --git a/src/eval.c b/src/eval.c
index 77578f3650..1fb1f5e70b 100644
--- 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);
diff --git a/src/job.c b/src/job.c
index aeb2af7b53..189c06eb6e 100644
--- 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
diff --git a/src/proto/channel.pro b/src/proto/channel.pro
index bbe5288a38..32e68d8942 100644
--- a/src/proto/channel.pro
+++ b/src/proto/channel.pro
@@ -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 : */
diff --git a/src/proto/job.pro b/src/proto/job.pro
index bf97577e12..3927e7f48e 100644
--- a/src/proto/job.pro
+++ b/src/proto/job.pro
@@ -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 : */
diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim
index 9cae4a34e1..b98c840ce0 100644
--- 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")
diff --git a/src/typval.c b/src/typval.c
index 3d1bd7f53f..f08d1aa421 100644
--- 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 *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:
diff --git a/src/version.c b/src/version.c
index 87bc2a09ed..b729c99f5e 100644
--- 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,
diff --git a/src/vim9execute.c b/src/vim9execute.c
index 455a205070..a13b0ab986 100644
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -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