summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/channel.c19
-rw-r--r--src/json.c21
-rw-r--r--src/testdir/test_channel.py7
-rw-r--r--src/testdir/test_channel.vim7
-rw-r--r--src/testdir/test_json.vim3
-rw-r--r--src/version.c2
6 files changed, 47 insertions, 12 deletions
diff --git a/src/channel.c b/src/channel.c
index 811d87ae1..a6458c65e 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -853,24 +853,31 @@ channel_exe_cmd(int idx, char_u *cmd, typval_T *arg2, typval_T *arg3)
{
typval_T *tv;
typval_T err_tv;
- char_u *json;
+ char_u *json = NULL;
/* Don't pollute the display with errors. */
++emsg_skip;
tv = eval_expr(arg, NULL);
- --emsg_skip;
if (is_eval)
{
- if (tv == NULL)
+ if (tv != NULL)
+ json = json_encode_nr_expr(arg3->vval.v_number, tv);
+ if (tv == NULL || (json != NULL && *json == NUL))
{
+ /* If evaluation failed or the result can't be encoded
+ * then return the string "ERROR". */
err_tv.v_type = VAR_STRING;
err_tv.vval.v_string = (char_u *)"ERROR";
tv = &err_tv;
+ json = json_encode_nr_expr(arg3->vval.v_number, tv);
+ }
+ if (json != NULL)
+ {
+ channel_send(idx, json, "eval");
+ vim_free(json);
}
- json = json_encode_nr_expr(arg3->vval.v_number, tv);
- channel_send(idx, json, "eval");
- vim_free(json);
}
+ --emsg_skip;
if (tv != &err_tv)
free_tv(tv);
}
diff --git a/src/json.c b/src/json.c
index 6688437ae..17eed4fa1 100644
--- a/src/json.c
+++ b/src/json.c
@@ -21,6 +21,8 @@ static int json_decode_item(js_read_T *reader, typval_T *res);
/*
* Encode "val" into a JSON format string.
+ * The result is in allocated memory.
+ * The result is empty when encoding fails.
*/
char_u *
json_encode(typval_T *val)
@@ -29,12 +31,16 @@ json_encode(typval_T *val)
/* Store bytes in the growarray. */
ga_init2(&ga, 1, 4000);
- json_encode_item(&ga, val, get_copyID(), TRUE);
+ if (json_encode_item(&ga, val, get_copyID(), TRUE) == FAIL)
+ {
+ vim_free(ga.ga_data);
+ return vim_strsave((char_u *)"");
+ }
return ga.ga_data;
}
/*
- * Encode ["nr", "val"] into a JSON format string.
+ * Encode ["nr", "val"] into a JSON format string in allocated memory.
* Returns NULL when out of memory.
*/
char_u *
@@ -136,8 +142,11 @@ json_encode_item(garray_T *gap, typval_T *val, int copyID, int allow_none)
case VVAL_FALSE: ga_concat(gap, (char_u *)"false"); break;
case VVAL_TRUE: ga_concat(gap, (char_u *)"true"); break;
case VVAL_NONE: if (!allow_none)
+ {
/* TODO: better error */
EMSG(_(e_invarg));
+ return FAIL;
+ }
break;
case VVAL_NULL: ga_concat(gap, (char_u *)"null"); break;
}
@@ -155,6 +164,7 @@ json_encode_item(garray_T *gap, typval_T *val, int copyID, int allow_none)
break;
case VAR_FUNC:
+ case VAR_JOB:
/* no JSON equivalent TODO: better error */
EMSG(_(e_invarg));
return FAIL;
@@ -226,14 +236,15 @@ json_encode_item(garray_T *gap, typval_T *val, int copyID, int allow_none)
}
break;
-#ifdef FEAT_FLOAT
case VAR_FLOAT:
+#ifdef FEAT_FLOAT
vim_snprintf((char *)numbuf, NUMBUFLEN, "%g", val->vval.v_float);
ga_concat(gap, numbuf);
break;
#endif
- default: EMSG2(_(e_intern2), "json_encode_item()"); break;
- return FAIL;
+ case VAR_UNKNOWN:
+ EMSG2(_(e_intern2), "json_encode_item()"); break;
+ return FAIL;
}
return OK;
}
diff --git a/src/testdir/test_channel.py b/src/testdir/test_channel.py
index d8830c519..40a2043cc 100644
--- a/src/testdir/test_channel.py
+++ b/src/testdir/test_channel.py
@@ -93,6 +93,13 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
print("sending: {}".format(cmd))
self.request.sendall(cmd.encode('utf-8'))
response = "ok"
+ elif decoded[1] == 'eval-error':
+ # Send an eval request that works but the result can't
+ # be encoded.
+ cmd = '["eval","function(\\"tr\\")", -3]'
+ print("sending: {}".format(cmd))
+ self.request.sendall(cmd.encode('utf-8'))
+ response = "ok"
elif decoded[1] == 'eval-bad':
# Send an eval request missing the third argument.
cmd = '["eval","xxx"]'
diff --git a/src/testdir/test_channel.vim b/src/testdir/test_channel.vim
index 94ad81cca..2a56c0d28 100644
--- a/src/testdir/test_channel.vim
+++ b/src/testdir/test_channel.vim
@@ -118,10 +118,15 @@ func Test_communicate()
sleep 10m
call assert_equal([-2, 'ERROR'], ch_sendexpr(handle, 'eval-result'))
+ " Send an eval request that works but can't be encoded.
+ call assert_equal('ok', ch_sendexpr(handle, 'eval-error'))
+ sleep 10m
+ call assert_equal([-3, 'ERROR'], ch_sendexpr(handle, 'eval-result'))
+
" Send a bad eval request. There will be no response.
call assert_equal('ok', ch_sendexpr(handle, 'eval-bad'))
sleep 10m
- call assert_equal([-2, 'ERROR'], ch_sendexpr(handle, 'eval-result'))
+ call assert_equal([-3, 'ERROR'], ch_sendexpr(handle, 'eval-result'))
" Send an expr request
call assert_equal('ok', ch_sendexpr(handle, 'an expr'))
diff --git a/src/testdir/test_json.vim b/src/testdir/test_json.vim
index 05c394968..52cffc825 100644
--- a/src/testdir/test_json.vim
+++ b/src/testdir/test_json.vim
@@ -75,6 +75,9 @@ func Test_encode()
call assert_fails('echo jsonencode(function("tr"))', 'E474:')
call assert_fails('echo jsonencode([function("tr")])', 'E474:')
call assert_fails('echo jsonencode({"key":v:none})', 'E474:')
+
+ silent! let res = jsonencode(function("tr"))
+ call assert_equal("", res)
endfunc
func Test_decode()
diff --git a/src/version.c b/src/version.c
index f979949b5..00b7176f5 100644
--- a/src/version.c
+++ b/src/version.c
@@ -748,6 +748,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1278,
+/**/
1277,
/**/
1276,