aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/eval/encode.c2
-rw-r--r--src/nvim/eval/typval.c16
-rw-r--r--test/functional/eval/interrupt_spec.lua61
3 files changed, 71 insertions, 8 deletions
diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c
index 9f16b78976..39897aa9ab 100644
--- a/src/nvim/eval/encode.c
+++ b/src/nvim/eval/encode.c
@@ -209,7 +209,7 @@ bool encode_vim_list_to_buf(const list_T *const list, size_t *const ret_len,
return false;
}
len++;
- if (TV_LIST_ITEM_TV(li)->vval.v_string != 0) {
+ if (TV_LIST_ITEM_TV(li)->vval.v_string != NULL) {
len += STRLEN(TV_LIST_ITEM_TV(li)->vval.v_string);
}
});
diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c
index 0c9c4a0347..5040695b09 100644
--- a/src/nvim/eval/typval.c
+++ b/src/nvim/eval/typval.c
@@ -406,9 +406,7 @@ void tv_list_append_list(list_T *const list, list_T *const itemlist)
TV_LIST_ITEM_TV(li)->v_lock = VAR_UNLOCKED;
TV_LIST_ITEM_TV(li)->vval.v_list = itemlist;
tv_list_append(list, li);
- if (itemlist != NULL) {
- tv_list_ref(itemlist);
- }
+ tv_list_ref(itemlist);
}
/// Append a dictionary to a list
@@ -510,6 +508,9 @@ list_T *tv_list_copy(const vimconv_T *const conv, list_T *const orig,
orig->lv_copylist = copy;
}
TV_LIST_ITER(orig, item, {
+ if (got_int) {
+ break;
+ }
listitem_T *const ni = tv_list_item_alloc();
if (deep) {
if (var_item_copy(conv, TV_LIST_ITEM_TV(item), TV_LIST_ITEM_TV(ni),
@@ -605,6 +606,9 @@ static int list_join_inner(garray_T *const gap, list_T *const l,
// Stringify each item in the list.
TV_LIST_ITER(l, item, {
+ if (got_int) {
+ break;
+ }
char *s;
size_t len;
s = encode_tv2echo(TV_LIST_ITEM_TV(item), &len);
@@ -697,7 +701,7 @@ bool tv_list_equal(list_T *const l1, list_T *const l2, const bool ic,
listitem_T *item2 = tv_list_first(l2);
for (; item1 != NULL && item2 != NULL
; (item1 = TV_LIST_ITEM_NEXT(l1, item1),
- item2 = TV_LIST_ITEM_NEXT(n2, item2))) {
+ item2 = TV_LIST_ITEM_NEXT(l2, item2))) {
if (!tv_equal(TV_LIST_ITEM_TV(item1), TV_LIST_ITEM_TV(item2), ic,
recursive)) {
return false;
@@ -2108,9 +2112,7 @@ void tv_copy(typval_T *const from, typval_T *const to)
break;
}
case VAR_LIST: {
- if (from->vval.v_list != NULL) {
- tv_list_ref(to->vval.v_list);
- }
+ tv_list_ref(to->vval.v_list);
break;
}
case VAR_DICT: {
diff --git a/test/functional/eval/interrupt_spec.lua b/test/functional/eval/interrupt_spec.lua
new file mode 100644
index 0000000000..7f4ca95317
--- /dev/null
+++ b/test/functional/eval/interrupt_spec.lua
@@ -0,0 +1,61 @@
+local helpers = require('test.functional.helpers')(after_each)
+
+local command = helpers.command
+local meths = helpers.meths
+local clear = helpers.clear
+local sleep = helpers.sleep
+local wait = helpers.wait
+local feed = helpers.feed
+local eq = helpers.eq
+
+local dur
+local min_dur = 8
+local len = 131072
+
+describe('List support code', function()
+ if not pending('does not actually allows interrupting with just got_int', function() end) then return end
+ -- The following tests are confirmed to work with os_breakcheck() just before
+ -- `if (got_int) {break;}` in tv_list_copy and list_join_inner() and not to
+ -- work without.
+ setup(function()
+ clear()
+ dur = 0
+ while true do
+ command(([[
+ let rt = reltime()
+ let bl = range(%u)
+ let dur = reltimestr(reltime(rt))
+ ]]):format(len))
+ dur = tonumber(meths.get_var('dur'))
+ if dur >= min_dur then
+ -- print(('Using len %u, dur %g'):format(len, dur))
+ break
+ else
+ len = len * 2
+ end
+ end
+ end)
+ it('allows interrupting copy', function()
+ feed(':let t_rt = reltime()<CR>:let t_bl = copy(bl)<CR>')
+ sleep(min_dur / 16 * 1000)
+ feed('<C-c>')
+ wait()
+ command('let t_dur = reltimestr(reltime(t_rt))')
+ local t_dur = tonumber(meths.get_var('t_dur'))
+ if t_dur >= dur / 8 then
+ eq(nil, ('Took too long to cancel: %g >= %g'):format(t_dur, dur / 8))
+ end
+ end)
+ it('allows interrupting join', function()
+ feed(':let t_rt = reltime()<CR>:let t_j = join(bl)<CR>')
+ sleep(min_dur / 16 * 1000)
+ feed('<C-c>')
+ wait()
+ command('let t_dur = reltimestr(reltime(t_rt))')
+ local t_dur = tonumber(meths.get_var('t_dur'))
+ print(('t_dur: %g'):format(t_dur))
+ if t_dur >= dur / 8 then
+ eq(nil, ('Took too long to cancel: %g >= %g'):format(t_dur, dur / 8))
+ end
+ end)
+end)