Mercurial > vim
changeset 23295:d9ae7dd3a0f2 v8.2.2193
patch 8.2.2193: Vim9: can change constant in :def function
Commit: https://github.com/vim/vim/commit/3bdc90b7dfab314768a8f56454ea62929524f05c
Author: Bram Moolenaar <Bram@vim.org>
Date: Tue Dec 22 20:35:40 2020 +0100
patch 8.2.2193: Vim9: can change constant in :def function
Problem: Vim9: can change constant in :def function.
Solution: Check if a variable is locked. (issue https://github.com/vim/vim/issues/7526)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Tue, 22 Dec 2020 20:45:04 +0100 |
parents | 38b22245d35c |
children | c9123e2447bc |
files | src/evalvars.c src/proto/evalvars.pro src/testdir/test_vim9_func.vim src/version.c src/vim9execute.c |
diffstat | 5 files changed, 39 insertions(+), 10 deletions(-) [+] |
line wrap: on
line diff
--- a/src/evalvars.c +++ b/src/evalvars.c @@ -3125,13 +3125,7 @@ set_var_const( goto failed; } - // Check in this order for backwards compatibility: - // - Whether the variable is read-only - // - Whether the variable value is locked - // - Whether the variable is locked - if (var_check_ro(di->di_flags, name, FALSE) - || value_check_lock(di->di_tv.v_lock, name, FALSE) - || var_check_lock(di->di_flags, name, FALSE)) + if (var_check_permission(di, name) == FAIL) goto failed; } else @@ -3243,6 +3237,22 @@ failed: } /* + * Check in this order for backwards compatibility: + * - Whether the variable is read-only + * - Whether the variable value is locked + * - Whether the variable is locked + */ + int +var_check_permission(dictitem_T *di, char_u *name) +{ + if (var_check_ro(di->di_flags, name, FALSE) + || value_check_lock(di->di_tv.v_lock, name, FALSE) + || var_check_lock(di->di_flags, name, FALSE)) + return FAIL; + return OK; +} + +/* * Return TRUE if di_flags "flags" indicates variable "name" is read-only. * Also give an error message. */
--- a/src/proto/evalvars.pro +++ b/src/proto/evalvars.pro @@ -70,6 +70,7 @@ void vars_clear_ext(hashtab_T *ht, int f void delete_var(hashtab_T *ht, hashitem_T *hi); void set_var(char_u *name, typval_T *tv, int copy); void set_var_const(char_u *name, type_T *type, typval_T *tv_arg, int copy, int flags); +int var_check_permission(dictitem_T *di, char_u *name); int var_check_ro(int flags, char_u *name, int use_gettext); int var_check_lock(int flags, char_u *name, int use_gettext); int var_check_fixed(int flags, char_u *name, int use_gettext);
--- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -1022,6 +1022,17 @@ def Test_vim9script_call_fail_const() writefile(lines, 'Xcall_const.vim') assert_fails('source Xcall_const.vim', 'E46:', '', 1, 'MyFunc') delete('Xcall_const.vim') + + lines =<< trim END + const g:Aconst = 77 + def Change() + # comment + g:Aconst = 99 + enddef + call Change() + unlet g:Aconst + END + CheckScriptFailure(lines, 'E741: Value is locked: Aconst', 2) enddef " Test that inside :function a Python function can be defined, :def is not
--- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2193, +/**/ 2192, /**/ 2191,
--- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -1693,8 +1693,10 @@ call_def_function( case ISN_STOREW: case ISN_STORET: { - dictitem_T *di; - hashtab_T *ht; + dictitem_T *di; + hashtab_T *ht; + char_u *name = iptr->isn_arg.string + 2; + switch (iptr->isn_type) { case ISN_STOREG: @@ -1714,11 +1716,14 @@ call_def_function( } --ectx.ec_stack.ga_len; - di = find_var_in_ht(ht, 0, iptr->isn_arg.string + 2, TRUE); + di = find_var_in_ht(ht, 0, name, TRUE); if (di == NULL) store_var(iptr->isn_arg.string, STACK_TV_BOT(0)); else { + SOURCING_LNUM = iptr->isn_lnum; + if (var_check_permission(di, name) == FAIL) + goto on_error; clear_tv(&di->di_tv); di->di_tv = *STACK_TV_BOT(0); }