summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2016-08-26 17:58:53 +0200
committerBram Moolenaar <Bram@vim.org>2016-08-26 17:58:53 +0200
commitf1f0792e55e72cdc7c833b30f565a9b02f18bb1e (patch)
tree0c63bd3971cde94874394587ca3bede776f87abf /src
parent9f28953f0c1e3d9fffd49af76503f54eaa279acb (diff)
downloadvim-f1f0792e55e72cdc7c833b30f565a9b02f18bb1e.zip
patch 7.4.2258
Problem: Two JSON messages are sent without a separator. Solution: Separate messages with a NL. (closes #1001)
Diffstat (limited to 'src')
-rw-r--r--src/channel.c6
-rw-r--r--src/json.c35
-rw-r--r--src/testdir/test_channel.py6
-rw-r--r--src/testdir/test_channel.vim11
-rw-r--r--src/version.c2
-rw-r--r--src/vim.h1
6 files changed, 45 insertions, 16 deletions
diff --git a/src/channel.c b/src/channel.c
index 443524885..748857423 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -2165,7 +2165,7 @@ channel_exe_cmd(channel_T *channel, int part, typval_T *argv)
int id = argv[id_idx].vval.v_number;
if (tv != NULL)
- json = json_encode_nr_expr(id, tv, options);
+ json = json_encode_nr_expr(id, tv, options | JSON_NL);
if (tv == NULL || (json != NULL && *json == NUL))
{
/* If evaluation failed or the result can't be encoded
@@ -2175,7 +2175,7 @@ channel_exe_cmd(channel_T *channel, int part, typval_T *argv)
err_tv.v_type = VAR_STRING;
err_tv.vval.v_string = (char_u *)"ERROR";
tv = &err_tv;
- json = json_encode_nr_expr(id, tv, options);
+ json = json_encode_nr_expr(id, tv, options | JSON_NL);
}
if (json != NULL)
{
@@ -3500,7 +3500,7 @@ ch_expr_common(typval_T *argvars, typval_T *rettv, int eval)
id = ++channel->ch_last_msg_id;
text = json_encode_nr_expr(id, &argvars[1],
- ch_mode == MODE_JS ? JSON_JS : 0);
+ (ch_mode == MODE_JS ? JSON_JS : 0) | JSON_NL);
if (text == NULL)
return;
diff --git a/src/json.c b/src/json.c
index 89c2fd254..bdfeb83e2 100644
--- a/src/json.c
+++ b/src/json.c
@@ -23,9 +23,26 @@ static int json_decode_item(js_read_T *reader, typval_T *res, int options);
/*
* Encode "val" into a JSON format string.
+ * The result is added to "gap"
+ * Returns FAIL on failure and makes gap->ga_data empty.
+ */
+ static int
+json_encode_gap(garray_T *gap, typval_T *val, int options)
+{
+ if (json_encode_item(gap, val, get_copyID(), options) == FAIL)
+ {
+ ga_clear(gap);
+ gap->ga_data = vim_strsave((char_u *)"");
+ return FAIL;
+ }
+ return OK;
+}
+
+/*
+ * Encode "val" into a JSON format string.
* The result is in allocated memory.
* The result is empty when encoding fails.
- * "options" can be JSON_JS or zero;
+ * "options" can contain JSON_JS, JSON_NO_NONE and JSON_NL.
*/
char_u *
json_encode(typval_T *val, int options)
@@ -34,17 +51,13 @@ json_encode(typval_T *val, int options)
/* Store bytes in the growarray. */
ga_init2(&ga, 1, 4000);
- if (json_encode_item(&ga, val, get_copyID(), options) == FAIL)
- {
- vim_free(ga.ga_data);
- return vim_strsave((char_u *)"");
- }
+ json_encode_gap(&ga, val, options);
return ga.ga_data;
}
/*
* Encode ["nr", "val"] into a JSON format string in allocated memory.
- * "options" can be JSON_JS or zero;
+ * "options" can contain JSON_JS, JSON_NO_NONE and JSON_NL.
* Returns NULL when out of memory.
*/
char_u *
@@ -52,7 +65,7 @@ json_encode_nr_expr(int nr, typval_T *val, int options)
{
typval_T listtv;
typval_T nrtv;
- char_u *text;
+ garray_T ga;
nrtv.v_type = VAR_NUMBER;
nrtv.vval.v_number = nr;
@@ -65,9 +78,11 @@ json_encode_nr_expr(int nr, typval_T *val, int options)
return NULL;
}
- text = json_encode(&listtv, options);
+ ga_init2(&ga, 1, 4000);
+ if (json_encode_gap(&ga, &listtv, options) == OK && (options & JSON_NL))
+ ga_append(&ga, '\n');
list_unref(listtv.vval.v_list);
- return text;
+ return ga.ga_data;
}
static void
diff --git a/src/testdir/test_channel.py b/src/testdir/test_channel.py
index b5a912c07..07a22418a 100644
--- a/src/testdir/test_channel.py
+++ b/src/testdir/test_channel.py
@@ -38,15 +38,15 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
print("received: {0}".format(received))
# We may receive two messages at once. Take the part up to the
- # matching "]" (recognized by finding "][").
+ # newline, which should be after the matching "]".
todo = received
while todo != '':
- splitidx = todo.find('][')
+ splitidx = todo.find('\n')
if splitidx < 0:
used = todo
todo = ''
else:
- used = todo[:splitidx + 1]
+ used = todo[:splitidx]
todo = todo[splitidx + 1:]
if used != received:
print("using: {0}".format(used))
diff --git a/src/testdir/test_channel.vim b/src/testdir/test_channel.vim
index fff9ebd6c..964024474 100644
--- a/src/testdir/test_channel.vim
+++ b/src/testdir/test_channel.vim
@@ -55,6 +55,17 @@ func Ch_communicate(port)
call WaitFor('exists("g:split")')
call assert_equal(123, g:split)
+ " string with ][ should work
+ call assert_equal('this][that', ch_evalexpr(handle, 'echo this][that'))
+
+ " sending three messages quickly then reading should work
+ for i in range(3)
+ call ch_sendexpr(handle, 'echo hello ' . i)
+ endfor
+ call assert_equal('hello 0', ch_read(handle)[1])
+ call assert_equal('hello 1', ch_read(handle)[1])
+ call assert_equal('hello 2', ch_read(handle)[1])
+
" Request that triggers sending two ex commands. These will usually be
" handled before getting the response, but it's not guaranteed, thus wait a
" tiny bit for the commands to get executed.
diff --git a/src/version.c b/src/version.c
index 9feaa0280..83bf09bc3 100644
--- a/src/version.c
+++ b/src/version.c
@@ -764,6 +764,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 2258,
+/**/
2257,
/**/
2256,
diff --git a/src/vim.h b/src/vim.h
index 8d49dcd18..41c4bac70 100644
--- a/src/vim.h
+++ b/src/vim.h
@@ -2440,6 +2440,7 @@ typedef enum
/* Options for json_encode() and json_decode. */
#define JSON_JS 1 /* use JS instead of JSON */
#define JSON_NO_NONE 2 /* v:none item not allowed */
+#define JSON_NL 4 /* append a NL */
/* Used for flags of do_in_path() */
#define DIP_ALL 0x01 /* all matches, not just the first one */