aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/misc1.c
diff options
context:
space:
mode:
authorMagnus Groß <magnus.gross@rwth-aachen.de>2021-11-17 17:55:49 +0100
committerMagnus Groß <magnus.gross@rwth-aachen.de>2021-11-18 14:23:33 +0100
commit1fb101afe4f28ada83721c4ac260de46d23504ee (patch)
treea4aa3a2f24cd51f6b53fea0b15400bce0bf06f7f /src/nvim/misc1.c
parentfdfd1eda434b70b02b4cb804546c97ef8ff09049 (diff)
downloadrneovim-1fb101afe4f28ada83721c4ac260de46d23504ee.tar.gz
rneovim-1fb101afe4f28ada83721c4ac260de46d23504ee.tar.bz2
rneovim-1fb101afe4f28ada83721c4ac260de46d23504ee.zip
vim-patch:8.2.3609: internal error when ModeChanged is triggered recursively
Problem: Internal error when ModeChanged is triggered when v:event is already in use. Solution: Save and restore v:event if needed. https://github.com/vim/vim/commit/3075a45592fe76f2febb6321632a23e352efe949 In the vim codebase there is no occurrence of get_vim_var_dict(VV_EVENT) after the above patch, so in order to hold the same invariant in the neovim codebase we needed to replace more occurrences than the related vim patch.
Diffstat (limited to 'src/nvim/misc1.c')
-rw-r--r--src/nvim/misc1.c31
1 files changed, 28 insertions, 3 deletions
diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c
index b50d8682eb..9900a68fac 100644
--- a/src/nvim/misc1.c
+++ b/src/nvim/misc1.c
@@ -1060,6 +1060,31 @@ void add_time(char_u *buf, size_t buflen, time_t tt)
}
}
+dict_T *get_v_event(save_v_event_T *sve)
+{
+ dict_T *v_event = get_vim_var_dict(VV_EVENT);
+
+ if (v_event->dv_hashtab.ht_used > 0) {
+ // recursive use of v:event, save, make empty and restore later
+ sve->sve_did_save = true;
+ sve->sve_hashtab = v_event->dv_hashtab;
+ hash_init(&v_event->dv_hashtab);
+ } else {
+ sve->sve_did_save = false;
+ }
+ return v_event;
+}
+
+void restore_v_event(dict_T *v_event, save_v_event_T *sve)
+{
+ tv_dict_free_contents(v_event);
+ if (sve->sve_did_save) {
+ v_event->dv_hashtab = sve->sve_hashtab;
+ } else {
+ hash_init(&v_event->dv_hashtab);
+ }
+}
+
/// Fires a ModeChanged autocmd.
void trigger_modechanged(void)
{
@@ -1073,7 +1098,8 @@ void trigger_modechanged(void)
return;
}
- dict_T *v_event = get_vim_var_dict(VV_EVENT);
+ save_v_event_T save_v_event;
+ dict_T *v_event = get_v_event(&save_v_event);
tv_dict_add_str(v_event, S_LEN("new_mode"), mode);
tv_dict_add_str(v_event, S_LEN("old_mode"), last_mode);
@@ -1086,6 +1112,5 @@ void trigger_modechanged(void)
last_mode = mode;
xfree(pat);
- tv_dict_free_contents(v_event);
- hash_init(&v_event->dv_hashtab);
+ restore_v_event(v_event, &save_v_event);
}