# HG changeset patch # User Bram Moolenaar # Date 1589117403 -7200 # Node ID 0e1dfff4f2949a3501c4079d3732b437fffa88e5 # Parent cd52b48baba5a49a97ac017709a369bf184046ae patch 8.2.0729: Vim9: When reloading a script variables are not cleared Commit: https://github.com/vim/vim/commit/89483d40438830fb9e74a5ec6c92d2470b05e4c2 Author: Bram Moolenaar Date: Sun May 10 15:24:44 2020 +0200 patch 8.2.0729: Vim9: When reloading a script variables are not cleared Problem: Vim9: When reloading a script variables are not cleared. Solution: When sourcing a script again clear all script-local variables. diff --git a/src/dict.c b/src/dict.c --- a/src/dict.c +++ b/src/dict.c @@ -105,28 +105,37 @@ rettv_dict_set(typval_T *rettv, dict_T * void dict_free_contents(dict_T *d) { + hashtab_free_contents(&d->dv_hashtab); +} + +/* + * Clear hashtab "ht" and dict items it contains. + */ + void +hashtab_free_contents(hashtab_T *ht) +{ int todo; hashitem_T *hi; dictitem_T *di; // Lock the hashtab, we don't want it to resize while freeing items. - hash_lock(&d->dv_hashtab); - todo = (int)d->dv_hashtab.ht_used; - for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi) + hash_lock(ht); + todo = (int)ht->ht_used; + for (hi = ht->ht_array; todo > 0; ++hi) { if (!HASHITEM_EMPTY(hi)) { // Remove the item before deleting it, just in case there is // something recursive causing trouble. di = HI2DI(hi); - hash_remove(&d->dv_hashtab, hi); + hash_remove(ht, hi); dictitem_free(di); --todo; } } - // The hashtab is still locked, it has to be re-initialized anyway - hash_clear(&d->dv_hashtab); + // The hashtab is still locked, it has to be re-initialized anyway. + hash_clear(ht); } static void diff --git a/src/proto/dict.pro b/src/proto/dict.pro --- a/src/proto/dict.pro +++ b/src/proto/dict.pro @@ -5,6 +5,7 @@ dict_T *dict_alloc_lock(int lock); int rettv_dict_alloc(typval_T *rettv); void rettv_dict_set(typval_T *rettv, dict_T *d); void dict_free_contents(dict_T *d); +void hashtab_free_contents(hashtab_T *ht); void dict_unref(dict_T *d); int dict_free_nonref(int copyID); void dict_free_items(int copyID); diff --git a/src/scriptfile.c b/src/scriptfile.c --- a/src/scriptfile.c +++ b/src/scriptfile.c @@ -1295,9 +1295,6 @@ do_source( if (sid > 0) { hashtab_T *ht; - hashitem_T *hi; - dictitem_T *di; - int todo; int is_vim9 = si->sn_version == SCRIPT_VERSION_VIM9; // loading the same script again @@ -1306,14 +1303,22 @@ do_source( current_sctx.sc_sid = sid; ht = &SCRIPT_VARS(sid); - todo = (int)ht->ht_used; - for (hi = ht->ht_array; todo > 0; ++hi) - if (!HASHITEM_EMPTY(hi)) - { - --todo; - di = HI2DI(hi); - di->di_flags |= DI_FLAGS_RELOAD; - } + if (is_vim9) + hashtab_free_contents(ht); + else + { + int todo = (int)ht->ht_used; + hashitem_T *hi; + dictitem_T *di; + + for (hi = ht->ht_array; todo > 0; ++hi) + if (!HASHITEM_EMPTY(hi)) + { + --todo; + di = HI2DI(hi); + di->di_flags |= DI_FLAGS_RELOAD; + } + } // old imports are no longer valid free_imports(sid); diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -610,7 +610,6 @@ def Test_vim9_import_export() let import_star_lines =<< trim END vim9script import * from './Xexport.vim' - g:imported = exported END writefile(import_star_lines, 'Ximport.vim') assert_fails('source Ximport.vim', 'E1045:') @@ -807,6 +806,28 @@ def Test_vim9script_reload_delfunc() delete('Xreloaded.vim') enddef +def Test_vim9script_reload_delvar() + # write the script with a script-local variable + let lines =<< trim END + vim9script + let var = 'string' + END + writefile(lines, 'XreloadVar.vim') + source XreloadVar.vim + + # now write the script using the same variable locally - works + lines =<< trim END + vim9script + def Func() + let var = 'string' + enddef + END + writefile(lines, 'XreloadVar.vim') + source XreloadVar.vim + + delete('XreloadVar.vim') +enddef + def Test_import_absolute() let import_lines = [ 'vim9script', @@ -862,8 +883,7 @@ def Test_import_rtp() unlet g:imported_rtp delete('Ximport_rtp.vim') - delete('import/Xexport_rtp.vim') - delete('import', 'd') + delete('import', 'rf') enddef def Test_fixed_size_list() diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -747,6 +747,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 729, +/**/ 728, /**/ 727,