To: vim_dev@googlegroups.com Subject: Patch 7.4.1166 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 7.4.1166 Problem: Can't encode a Funcref into JSON. jsonencode() doesn't handle the same list or dict twice properly. (Nikolay Pavlov) Solution: Give an error. Reset copyID when the list or dict is finished. Files: src/json.c, src/proto/json.pro, src/testdir/test_json.vim *** ../vim-7.4.1165/src/json.c 2016-01-24 15:05:27.451868346 +0100 --- src/json.c 2016-01-24 16:40:14.781218699 +0100 *************** *** 16,21 **** --- 16,22 ---- #include "vim.h" #if defined(FEAT_EVAL) || defined(PROTO) + static int json_encode_item(garray_T *gap, typval_T *val, int copyID); static void json_decode_item(js_read_T *reader, typval_T *res); /* *************** *** 83,89 **** } } ! void json_encode_item(garray_T *gap, typval_T *val, int copyID) { char_u numbuf[NUMBUFLEN]; --- 84,94 ---- } } ! /* ! * Encode "val" into "gap". ! * Return FAIL or OK. ! */ ! static int json_encode_item(garray_T *gap, typval_T *val, int copyID) { char_u numbuf[NUMBUFLEN]; *************** *** 94,100 **** switch (val->v_type) { case VAR_SPECIAL: ! switch(val->vval.v_number) { case VVAL_FALSE: ga_concat(gap, (char_u *)"false"); break; case VVAL_TRUE: ga_concat(gap, (char_u *)"true"); break; --- 99,105 ---- switch (val->v_type) { case VAR_SPECIAL: ! switch (val->vval.v_number) { case VVAL_FALSE: ga_concat(gap, (char_u *)"false"); break; case VVAL_TRUE: ga_concat(gap, (char_u *)"true"); break; *************** *** 115,122 **** break; case VAR_FUNC: ! /* no JSON equivalent, skip */ ! break; case VAR_LIST: l = val->vval.v_list; --- 120,128 ---- break; case VAR_FUNC: ! /* no JSON equivalent */ ! EMSG(_(e_invarg)); ! return FAIL; case VAR_LIST: l = val->vval.v_list; *************** *** 134,145 **** ga_append(gap, '['); for (li = l->lv_first; li != NULL && !got_int; ) { ! json_encode_item(gap, &li->li_tv, copyID); li = li->li_next; if (li != NULL) ga_append(gap, ','); } ga_append(gap, ']'); } } break; --- 140,153 ---- ga_append(gap, '['); for (li = l->lv_first; li != NULL && !got_int; ) { ! if (json_encode_item(gap, &li->li_tv, copyID) == FAIL) ! return FAIL; li = li->li_next; if (li != NULL) ga_append(gap, ','); } ga_append(gap, ']'); + l->lv_copyID = 0; } } break; *************** *** 172,181 **** ga_append(gap, ','); write_string(gap, hi->hi_key); ga_append(gap, ':'); ! json_encode_item(gap, &dict_lookup(hi)->di_tv, ! copyID); } ga_append(gap, '}'); } } break; --- 180,191 ---- ga_append(gap, ','); write_string(gap, hi->hi_key); ga_append(gap, ':'); ! if (json_encode_item(gap, &dict_lookup(hi)->di_tv, ! copyID) == FAIL) ! return FAIL; } ga_append(gap, '}'); + d->dv_copyID = 0; } } break; *************** *** 187,193 **** --- 197,205 ---- break; #endif default: EMSG2(_(e_intern2), "json_encode_item()"); break; + return FAIL; } + return OK; } /* *** ../vim-7.4.1165/src/proto/json.pro 2016-01-23 19:45:48.626931291 +0100 --- src/proto/json.pro 2016-01-24 16:19:52.205896695 +0100 *************** *** 1,5 **** /* json.c */ char_u *json_encode(typval_T *val); - void json_encode_item(garray_T *gap, typval_T *val, int copyID); void json_decode(js_read_T *reader, typval_T *res); /* vim: set ft=c : */ --- 1,4 ---- *** ../vim-7.4.1165/src/testdir/test_json.vim 2016-01-24 15:05:27.455868305 +0100 --- src/testdir/test_json.vim 2016-01-24 16:39:44.389533642 +0100 *************** *** 27,32 **** --- 27,35 ---- let l2 = ['a', s:varl2, 'c'] let s:varl2[1] = l2 let s:varl2x = [1, ["a", [], "c"], 3] + let s:jsonl3 = '[[1,2],[1,2]]' + let l3 = [1, 2] + let s:varl3 = [l3, l3] let s:jsond1 = '{"a":1,"b":"bee","c":[1,2]}' let s:vard1 = {"a": 1, "b": "bee","c": [1,2]} *************** *** 36,41 **** --- 39,47 ---- let d2 = {"a": "aa", "b": s:vard2, "c": "cc"} let s:vard2["2"] = d2 let s:vard2x = {"1": 1, "2": {"a": "aa", "b": {}, "c": "cc"}, "3": 3} + let d3 = {"a": 1, "b": 2} + let s:vard3 = {"x": d3, "y": d3} + let s:jsond3 = '{"x":{"a":1,"b":2},"y":{"a":1,"b":2}}' let s:jsonvals = '[true,false,,null]' let s:varvals = [v:true, v:false, v:none, v:null] *************** *** 58,68 **** --- 64,79 ---- call assert_equal(s:jsonl1, jsonencode(s:varl1)) call assert_equal(s:jsonl2, jsonencode(s:varl2)) + call assert_equal(s:jsonl3, jsonencode(s:varl3)) call assert_equal(s:jsond1, jsonencode(s:vard1)) call assert_equal(s:jsond2, jsonencode(s:vard2)) + call assert_equal(s:jsond3, jsonencode(s:vard3)) call assert_equal(s:jsonvals, jsonencode(s:varvals)) + + call assert_fails('echo jsonencode(function("tr"))', 'E474:') + call assert_fails('echo jsonencode([function("tr")])', 'E474:') endfunc func Test_decode() *************** *** 84,92 **** --- 95,105 ---- call assert_equal(s:varl1, jsondecode(s:jsonl1)) call assert_equal(s:varl2x, jsondecode(s:jsonl2)) call assert_equal(s:varl2x, jsondecode(s:jsonl2s)) + call assert_equal(s:varl3, jsondecode(s:jsonl3)) call assert_equal(s:vard1, jsondecode(s:jsond1)) call assert_equal(s:vard2x, jsondecode(s:jsond2)) + call assert_equal(s:vard3, jsondecode(s:jsond3)) call assert_equal(s:varvals, jsondecode(s:jsonvals)) *** ../vim-7.4.1165/src/version.c 2016-01-24 15:35:55.529110654 +0100 --- src/version.c 2016-01-24 16:47:36.668640618 +0100 *************** *** 743,744 **** --- 743,746 ---- { /* Add new patch number below this line */ + /**/ + 1166, /**/ -- hundred-and-one symptoms of being an internet addict: 32. You don't know what sex three of your closest friends are, because they have neutral nicknames and you never bothered to ask. normal GA /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///