]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.0.1240: cannot access a private object member in a lambda v9.0.1240
authorBram Moolenaar <Bram@vim.org>
Tue, 24 Jan 2023 15:07:04 +0000 (15:07 +0000)
committerBram Moolenaar <Bram@vim.org>
Tue, 24 Jan 2023 15:07:04 +0000 (15:07 +0000)
Problem:    Cannot access a private object member in a lambda defined inside
            the class.
Solution:   Go up the context stack to find the class. (closes #11866)

src/proto/vim9class.pro
src/testdir/test_vim9_class.vim
src/version.c
src/vim9class.c
src/vim9expr.c

index 74d33c00c9760ae565fea1e03f032a5706f6f659..13a643dd5cc57a4a10ddcbe3188c82f70088b1c3 100644 (file)
@@ -7,6 +7,7 @@ void ex_type(exarg_T *eap);
 int class_object_index(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int verbose);
 ufunc_T *find_class_func(char_u **arg);
 int class_member_index(char_u *name, size_t len, class_T **cl_ret, cctx_T *cctx);
+int inside_class(cctx_T *cctx_arg, class_T *cl);
 void copy_object(typval_T *from, typval_T *to);
 void object_unref(object_T *obj);
 void copy_class(typval_T *from, typval_T *to);
index a3fdbdb9c33cdfa6b54f001127494f060ec743e0..389213680b8c2ca4c4da33c615303c381c6d8288 100644 (file)
@@ -645,6 +645,24 @@ def Test_class_member()
   END
   v9.CheckScriptSuccess(lines)
 
+  # access private member in lambda
+  lines =<< trim END
+      vim9script
+
+      class Foo
+        this._x: number = 0
+
+        def Add(n: number): number
+          const F = (): number => this._x + n
+          return F()
+        enddef
+      endclass
+
+      var foo = Foo.new()
+      assert_equal(5, foo.Add(5))
+  END
+  v9.CheckScriptSuccess(lines)
+
   # check shadowing
   lines =<< trim END
       vim9script
index f21a1887aed96d49b89ac560495c7ac8d0442971..4a3355c0b14bbbd30e69c48c384a2abeb2505f83 100644 (file)
@@ -695,6 +695,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1240,
 /**/
     1239,
 /**/
index 0262e025d56fca347c07aeb3f99f5ae1280f2b05..484500576ec6dd875753c1d5ac6a9f6e1fbb305c 100644 (file)
@@ -1387,6 +1387,19 @@ class_member_index(char_u *name, size_t len, class_T **cl_ret, cctx_T *cctx)
     return -1;
 }
 
+/*
+ * Return TRUE if current context "cctx_arg" is inside class "cl".
+ * Return FALSE if not.
+ */
+    int
+inside_class(cctx_T *cctx_arg, class_T *cl)
+{
+    for (cctx_T *cctx = cctx_arg; cctx != NULL; cctx = cctx->ctx_outer)
+       if (cctx->ctx_ufunc != NULL && cctx->ctx_ufunc->uf_class == cl)
+           return TRUE;
+    return FALSE;
+}
+
 /*
  * Make a copy of an object.
  */
index 95c6d7db0c04469308502ef3c45f303d99d5128a..1034f64b070deab058bd2d5ff59673c4787316b3 100644 (file)
@@ -357,7 +357,7 @@ compile_class_object_index(cctx_T *cctx, char_u **arg, type_T *type)
            ocmember_T *m = &cl->class_obj_members[i];
            if (STRNCMP(name, m->ocm_name, len) == 0 && m->ocm_name[len] == NUL)
            {
-               if (*name == '_' && cctx->ctx_ufunc->uf_class != cl)
+               if (*name == '_' && !inside_class(cctx, cl))
                {
                    semsg(_(e_cannot_access_private_member_str), m->ocm_name);
                    return FAIL;