# HG changeset patch # User Christian Brabandt # Date 1712252710 -7200 # Node ID d4fb6ea26ae4d33502a7c27f95099918e56aae76 # Parent 1faaf5fdbb06dc643c42db4ff0bae6c6ac5d4867 patch 9.1.0261: Vim9: protected class and funcrefs accessible outside the class Commit: https://github.com/vim/vim/commit/3e33650b3a9939f6b942c1d1eccdb261ea17a647 Author: Yegappan Lakshmanan Date: Thu Apr 4 19:35:59 2024 +0200 patch 9.1.0261: Vim9: protected class and funcrefs accessible outside the class Problem: Vim9: protected class and funcrefs accessible outside the class (Aliaksei Budavei) Solution: Check if class and object funcrefs are protected (Yegappan) closes: #14407 Signed-off-by: Yegappan Lakshmanan Signed-off-by: Christian Brabandt diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim --- a/src/testdir/test_functions.vim +++ b/src/testdir/test_functions.vim @@ -3794,6 +3794,43 @@ func Test_funcref_to_string() call assert_equal("function('g:Test_funcref_to_string')", string(Fn)) endfunc +" A funcref cannot start with an underscore (except when used as a protected +" class or object variable) +func Test_funcref_with_underscore() + " at script level + let lines =<< trim END + vim9script + var _Fn = () => 10 + END + call v9.CheckSourceFailure(lines, 'E704: Funcref variable name must start with a capital: _Fn') + + " inside a function + let lines =<< trim END + vim9script + def Func() + var _Fn = () => 10 + enddef + defcompile + END + call v9.CheckSourceFailure(lines, 'E704: Funcref variable name must start with a capital: _Fn', 1) + + " as a function argument + let lines =<< trim END + vim9script + def Func(_Fn: func) + enddef + defcompile + END + call v9.CheckSourceFailure(lines, 'E704: Funcref variable name must start with a capital: _Fn', 2) + + " as a lambda argument + let lines =<< trim END + vim9script + var Fn = (_Farg: func) => 10 + END + call v9.CheckSourceFailure(lines, 'E704: Funcref variable name must start with a capital: _Farg', 2) +endfunc + " Test for isabsolutepath() func Test_isabsolutepath() call assert_false(isabsolutepath('')) diff --git a/src/testdir/test_vim9_class.vim b/src/testdir/test_vim9_class.vim --- a/src/testdir/test_vim9_class.vim +++ b/src/testdir/test_vim9_class.vim @@ -10530,4 +10530,27 @@ def Test_use_base_class_variable_from_ba v9.CheckScriptSuccess(lines) enddef +" Test for accessing protected funcref object and class variables +def Test_protected_funcref() + # protected funcref object variable + var lines =<< trim END + vim9script + class Test1 + const _Id: func(any): any = (v) => v + endclass + var n = Test1.new()._Id(1) + END + v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_Id" in class "Test1"', 5) + + # protected funcref class variable + lines =<< trim END + vim9script + class Test2 + static const _Id: func(any): any = (v) => v + endclass + var n = Test2._Id(2) + END + v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_Id" in class "Test2"', 5) +enddef + " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker diff --git a/src/userfunc.c b/src/userfunc.c --- a/src/userfunc.c +++ b/src/userfunc.c @@ -570,10 +570,16 @@ parse_argument_types( fp->uf_arg_types[i] = type; if (i < fp->uf_args.ga_len && (type->tt_type == VAR_FUNC - || type->tt_type == VAR_PARTIAL) - && var_wrong_func_name( - ((char_u **)fp->uf_args.ga_data)[i], TRUE)) - return FAIL; + || type->tt_type == VAR_PARTIAL)) + { + char_u *name = ((char_u **)fp->uf_args.ga_data)[i]; + if (obj_members != NULL && *name == '_') + // protected object method + name++; + + if (var_wrong_func_name(name, TRUE)) + return FAIL; + } } } } diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -705,6 +705,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 261, +/**/ 260, /**/ 259, diff --git a/src/vim9class.c b/src/vim9class.c --- a/src/vim9class.c +++ b/src/vim9class.c @@ -2835,6 +2835,14 @@ call_oc_method( return FAIL; } + if (*name == '_') + { + // Protected object or class funcref variable + semsg(_(e_cannot_access_protected_variable_str), ocm->ocm_name, + cl->class_name); + return FAIL; + } + if (rettv->v_type == VAR_OBJECT) { // funcref object variable