Skip to content

Commit 3cf3c48

Browse files
committed
Merge remote-tracking branch 'vim/master'
2 parents 9787680 + 9bfdba3 commit 3cf3c48

File tree

9 files changed

+112
-39
lines changed

9 files changed

+112
-39
lines changed

src/channel.c

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -314,8 +314,11 @@ add_channel(void)
314314
}
315315

316316
/*
317+
* Called when the refcount of a channel is zero.
317318
* Return TRUE if "channel" has a callback and the associated job wasn't
318319
* killed.
320+
* If the job was killed the channel is not expected to work anymore.
321+
* If there is no callback then nobody can get readahead.
319322
*/
320323
static int
321324
channel_still_useful(channel_T *channel)
@@ -334,12 +337,17 @@ channel_still_useful(channel_T *channel)
334337
* Close a channel and free all its resources if there is no further action
335338
* possible, there is no callback to be invoked or the associated job was
336339
* killed.
340+
* Return TRUE if the channel was freed.
337341
*/
338-
void
342+
int
339343
channel_may_free(channel_T *channel)
340344
{
341345
if (!channel_still_useful(channel))
346+
{
342347
channel_free(channel);
348+
return TRUE;
349+
}
350+
return FALSE;
343351
}
344352

345353
/*
@@ -350,6 +358,7 @@ channel_free(channel_T *channel)
350358
{
351359
channel_close(channel, TRUE);
352360
channel_clear(channel);
361+
ch_log(channel, "Freeing channel");
353362
if (channel->ch_next != NULL)
354363
channel->ch_next->ch_prev = channel->ch_prev;
355364
if (channel->ch_prev == NULL)
@@ -794,6 +803,10 @@ channel_set_pipes(channel_T *channel, sock_T in, sock_T out, sock_T err)
794803
}
795804
#endif
796805

806+
/*
807+
* Sets the job the channel is associated with.
808+
* This does not keep a refcount, when the job is freed ch_job is cleared.
809+
*/
797810
void
798811
channel_set_job(channel_T *channel, job_T *job)
799812
{
@@ -951,10 +964,15 @@ invoke_callback(channel_T *channel, char_u *callback, typval_T *argv)
951964
clear_tv(&rettv);
952965

953966
/* If an echo command was used the cursor needs to be put back where
954-
* it belongs. */
967+
* it belongs. If highlighting was changed a redraw is needed. */
968+
update_screen(0);
955969
setcursor();
956970
cursor_on();
957971
out_flush();
972+
#ifdef FEAT_GUI
973+
gui_update_cursor(TRUE, FALSE);
974+
gui_mch_flush();
975+
#endif
958976
}
959977

960978
/*
@@ -1440,7 +1458,10 @@ may_invoke_callback(channel_T *channel, int part)
14401458
if (callback == NULL && buffer == NULL)
14411459
{
14421460
while ((msg = channel_get(channel, part)) != NULL)
1461+
{
1462+
ch_logs(channel, "Dropping message '%s'", (char *)msg);
14431463
vim_free(msg);
1464+
}
14441465
return FALSE;
14451466
}
14461467

@@ -1494,7 +1515,8 @@ may_invoke_callback(channel_T *channel, int part)
14941515
{
14951516
if (item->cq_seq_nr == seq_nr)
14961517
{
1497-
ch_log(channel, "Invoking one-time callback");
1518+
ch_logs(channel, "Invoking one-time callback '%s'",
1519+
(char *)item->cq_callback);
14981520
/* Remove the item from the list first, if the callback
14991521
* invokes ch_close() the list will be cleared. */
15001522
remove_cb_node(head, item);
@@ -1507,7 +1529,7 @@ may_invoke_callback(channel_T *channel, int part)
15071529
item = item->cq_next;
15081530
}
15091531
if (!done)
1510-
ch_log(channel, "Dropping message without callback");
1532+
ch_logn(channel, "Dropping message %d without callback", seq_nr);
15111533
}
15121534
else if (callback != NULL || buffer != NULL)
15131535
{
@@ -1558,6 +1580,8 @@ may_invoke_callback(channel_T *channel, int part)
15581580
invoke_callback(channel, callback, argv);
15591581
}
15601582
}
1583+
else if (msg != NULL)
1584+
ch_logs(channel, "Dropping message '%s'", (char *)msg);
15611585
else
15621586
ch_log(channel, "Dropping message");
15631587

@@ -1656,6 +1680,8 @@ channel_close(channel_T *channel, int invoke_close_cb)
16561680

16571681
/* invoke the close callback; increment the refcount to avoid it
16581682
* being freed halfway */
1683+
ch_logs(channel, "Invoking close callback %s",
1684+
(char *)channel->ch_close_cb);
16591685
argv[0].v_type = VAR_CHANNEL;
16601686
argv[0].vval.v_channel = channel;
16611687
++channel->ch_refcount;
@@ -1723,6 +1749,7 @@ channel_clear_one(channel_T *channel, int part)
17231749
void
17241750
channel_clear(channel_T *channel)
17251751
{
1752+
ch_log(channel, "Clearing channel");
17261753
channel_clear_one(channel, PART_SOCK);
17271754
#ifdef CHANNEL_PIPES
17281755
channel_clear_one(channel, PART_OUT);
@@ -1740,6 +1767,7 @@ channel_free_all(void)
17401767
{
17411768
channel_T *channel;
17421769

1770+
ch_log(NULL, "channel_free_all()");
17431771
for (channel = first_channel; channel != NULL; channel = channel->ch_next)
17441772
channel_clear(channel);
17451773
}
@@ -1817,7 +1845,6 @@ channel_wait(channel_T *channel, sock_T fd, int timeout)
18171845
return OK;
18181846
#endif
18191847
}
1820-
ch_log(channel, "Nothing to read");
18211848
return FAIL;
18221849
}
18231850

@@ -1989,11 +2016,11 @@ channel_read_block(channel_T *channel, int part, int timeout)
19892016
*/
19902017
int
19912018
channel_read_json_block(
1992-
channel_T *channel,
1993-
int part,
1994-
int timeout,
1995-
int id,
1996-
typval_T **rettv)
2019+
channel_T *channel,
2020+
int part,
2021+
int timeout,
2022+
int id,
2023+
typval_T **rettv)
19972024
{
19982025
int more;
19992026
sock_T fd;

src/eval.c

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7741,16 +7741,13 @@ get_dict_tv(char_u **arg, typval_T *rettv, int evaluate)
77417741
/*
77427742
* Decrement the reference count on "channel" and maybe free it when it goes
77437743
* down to zero. Don't free it if there is a pending action.
7744-
* Returns TRUE when the channel was freed.
7744+
* Returns TRUE when the channel is no longer referenced.
77457745
*/
77467746
int
77477747
channel_unref(channel_T *channel)
77487748
{
77497749
if (channel != NULL && --channel->ch_refcount <= 0)
7750-
{
7751-
channel_may_free(channel);
7752-
return TRUE;
7753-
}
7750+
return channel_may_free(channel);
77547751
return FALSE;
77557752
}
77567753
#endif
@@ -7762,6 +7759,7 @@ static job_T *first_job = NULL;
77627759
job_free(job_T *job)
77637760
{
77647761
# ifdef FEAT_CHANNEL
7762+
ch_log(job->jv_channel, "Freeing job");
77657763
if (job->jv_channel != NULL)
77667764
{
77677765
/* The link from the channel to the job doesn't count as a reference,
@@ -7796,7 +7794,19 @@ job_unref(job_T *job)
77967794
* "stoponexit" flag or an exit callback. */
77977795
if (job->jv_status != JOB_STARTED
77987796
|| (job->jv_stoponexit == NULL && job->jv_exit_cb == NULL))
7797+
{
77997798
job_free(job);
7799+
}
7800+
# ifdef FEAT_CHANNEL
7801+
else if (job->jv_channel != NULL)
7802+
{
7803+
/* Do remove the link to the channel, otherwise it hangs
7804+
* around until Vim exits. See job_free() for refcount. */
7805+
job->jv_channel->ch_job = NULL;
7806+
channel_unref(job->jv_channel);
7807+
job->jv_channel = NULL;
7808+
}
7809+
# endif
78007810
}
78017811
}
78027812

@@ -10467,7 +10477,10 @@ common_channel_read(typval_T *argvars, typval_T *rettv, int raw)
1046710477
id = opt.jo_id;
1046810478
channel_read_json_block(channel, part, timeout, id, &listtv);
1046910479
if (listtv != NULL)
10480+
{
1047010481
*rettv = *listtv;
10482+
vim_free(listtv);
10483+
}
1047110484
else
1047210485
{
1047310486
rettv->v_type = VAR_SPECIAL;
@@ -15311,6 +15324,9 @@ f_job_stop(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
1531115324
return;
1531215325
}
1531315326
}
15327+
# ifdef FEAT_CHANNEL
15328+
ch_logs(job->jv_channel, "Stopping job with '%s'", (char *)arg);
15329+
# endif
1531415330
if (mch_stop_job(job, arg) == FAIL)
1531515331
rettv->vval.v_number = 0;
1531615332
else

src/json.c

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ write_string(garray_T *gap, char_u *str)
8686

8787
if (!enc_utf8)
8888
{
89+
/* Convert the text from 'encoding' to utf-8, the JSON string is
90+
* always utf-8. */
8991
conv.vc_type = CONV_NONE;
9092
convert_setup(&conv, p_enc, (char_u*)"utf-8");
9193
if (conv.vc_type != CONV_NONE)
@@ -534,33 +536,23 @@ json_decode_string(js_read_T *reader, typval_T *res)
534536
int c;
535537
long nr;
536538
char_u buf[NUMBUFLEN];
537-
#if defined(FEAT_MBYTE) && defined(USE_ICONV)
538-
vimconv_T conv;
539-
char_u *converted = NULL;
540-
#endif
541539

542540
if (res != NULL)
543541
ga_init2(&ga, 1, 200);
544542

545543
p = reader->js_buf + reader->js_used + 1; /* skip over " */
546-
#if defined(FEAT_MBYTE) && defined(USE_ICONV)
547-
if (!enc_utf8)
548-
{
549-
conv.vc_type = CONV_NONE;
550-
convert_setup(&conv, (char_u*)"utf-8", p_enc);
551-
if (conv.vc_type != CONV_NONE)
552-
converted = p = string_convert(&conv, p, NULL);
553-
convert_setup(&conv, NULL, NULL);
554-
}
555-
#endif
556544
while (*p != '"')
557545
{
546+
/* The JSON is always expected to be utf-8, thus use utf functions
547+
* here. The string is converted below if needed. */
558548
if (*p == NUL || p[1] == NUL
559549
#ifdef FEAT_MBYTE
560550
|| utf_ptr2len(p) < utf_byte2len(*p)
561551
#endif
562552
)
563553
{
554+
/* Not enough bytes to make a character or end of the string. Get
555+
* more if possible. */
564556
if (reader->js_fill == NULL)
565557
break;
566558
len = (int)(reader->js_end - p);
@@ -652,9 +644,6 @@ json_decode_string(js_read_T *reader, typval_T *res)
652644
if (ga_grow(&ga, len) == FAIL)
653645
{
654646
ga_clear(&ga);
655-
#if defined(FEAT_MBYTE) && defined(USE_ICONV)
656-
vim_free(converted);
657-
#endif
658647
return FAIL;
659648
}
660649
mch_memmove((char *)ga.ga_data + ga.ga_len, p, (size_t)len);
@@ -663,18 +652,34 @@ json_decode_string(js_read_T *reader, typval_T *res)
663652
p += len;
664653
}
665654
}
666-
#if defined(FEAT_MBYTE) && defined(USE_ICONV)
667-
vim_free(converted);
668-
#endif
669655

670656
reader->js_used = (int)(p - reader->js_buf);
671657
if (*p == '"')
672658
{
673659
++reader->js_used;
674660
if (res != NULL)
675661
{
662+
ga_append(&ga, NUL);
676663
res->v_type = VAR_STRING;
677-
res->vval.v_string = ga.ga_data;
664+
#if defined(FEAT_MBYTE) && defined(USE_ICONV)
665+
if (!enc_utf8)
666+
{
667+
vimconv_T conv;
668+
669+
/* Convert the utf-8 string to 'encoding'. */
670+
conv.vc_type = CONV_NONE;
671+
convert_setup(&conv, (char_u*)"utf-8", p_enc);
672+
if (conv.vc_type != CONV_NONE)
673+
{
674+
res->vval.v_string =
675+
string_convert(&conv, ga.ga_data, NULL);
676+
vim_free(ga.ga_data);
677+
}
678+
convert_setup(&conv, NULL, NULL);
679+
}
680+
else
681+
#endif
682+
res->vval.v_string = ga.ga_data;
678683
}
679684
return OK;
680685
}

src/proto/channel.pro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ int ch_log_active(void);
44
void ch_log(channel_T *ch, char *msg);
55
void ch_logs(channel_T *ch, char *msg, char *name);
66
channel_T *add_channel(void);
7-
void channel_may_free(channel_T *channel);
7+
int channel_may_free(channel_T *channel);
88
void channel_free(channel_T *channel);
99
void channel_gui_register(channel_T *channel);
1010
void channel_gui_register_all(void);

src/testdir/Make_all.mak

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ NEW_TESTS = test_arglist.res \
176176
test_channel.res \
177177
test_hardcopy.res \
178178
test_increment.res \
179+
test_json.res \
179180
test_langmap.res \
180181
test_perl.res \
181182
test_quickfix.res \

src/testdir/Make_amiga.mak

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ clean:
3434

3535
.in.out:
3636
copy $*.ok test.ok
37-
$(VIMPROG) -u amiga.vim -U NONE --noplugin -s dotest.in $*.in
37+
$(VIMPROG) -u amiga.vim -U NONE --noplugin --not-a-term -s dotest.in $*.in
3838
diff test.out $*.ok
3939
rename test.out $*.out
4040
-delete X#? ALL QUIET

src/testdir/test_alot.vim

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ source test_cursor_func.vim
66
source test_delete.vim
77
source test_expand.vim
88
source test_glob2regpat.vim
9-
source test_json.vim
109
source test_lispwords.vim
1110
source test_menu.vim
1211
source test_reltime.vim

src/testdir/test_json.vim

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
" Test for JSON functions.
2+
3+
" JSON requires using utf-8. Conversion breaks the asserts, therefore set
4+
" 'encoding' to utf-8.
5+
if !has('multi_byte')
6+
finish
7+
endif
8+
set encoding=utf-8
29
scriptencoding utf-8
310

411
let s:json1 = '"str\"in\\g"'

src/version.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,24 @@ static char *(features[]) =
758758

759759
static int included_patches[] =
760760
{ /* Add new patch number below this line */
761+
/**/
762+
1453,
763+
/**/
764+
1452,
765+
/**/
766+
1451,
767+
/**/
768+
1450,
769+
/**/
770+
1449,
771+
/**/
772+
1448,
773+
/**/
774+
1447,
775+
/**/
776+
1446,
777+
/**/
778+
1445,
761779
/**/
762780
1444,
763781
/**/

0 commit comments

Comments
 (0)