patch 7.4.2258
Problem:    Two JSON messages are sent without a separator.
Solution:   Separate messages with a NL. (closes #1001)
diff --git a/src/channel.c b/src/channel.c
index 4435248..7488574 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -2165,7 +2165,7 @@
 		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 @@
 		    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 @@
 
     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 89c2fd2..bdfeb83 100644
--- a/src/json.c
+++ b/src/json.c
@@ -23,9 +23,26 @@
 
 /*
  * 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 @@
 
     /* 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 @@
 {
     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 @@
 	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 b5a912c..07a2241 100644
--- a/src/testdir/test_channel.py
+++ b/src/testdir/test_channel.py
@@ -38,15 +38,15 @@
             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 fff9ebd..9640244 100644
--- a/src/testdir/test_channel.vim
+++ b/src/testdir/test_channel.vim
@@ -55,6 +55,17 @@
   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 9feaa02..83bf09b 100644
--- a/src/version.c
+++ b/src/version.c
@@ -764,6 +764,8 @@
 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 8d49dcd..41c4bac 100644
--- a/src/vim.h
+++ b/src/vim.h
@@ -2440,6 +2440,7 @@
 /* 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 */