• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/ucode/tests/custom/06_metamethods/00_get

  1 The `__get__` metamethod is consulted when a property lookup yields nothing
  2 in the instance itself nor in its prototype chain. It is invoked as a method
  3 on the instance, with the key as single argument.
  4 
  5 -- Testcase --
  6 {%
  7         let o = proto({}, {
  8                 __get__(key) {
  9                         return key == "bar" ? "virtual:bar" : null;
 10                 }
 11         });
 12 
 13         print(o.bar, "\n");
 14         print(o.foo === null, "\n");
 15 %}
 16 -- End --
 17 
 18 -- Expect stdout --
 19 virtual:bar
 20 true
 21 -- End --
 22 
 23 Properties found by the normal lookup shadow the metamethod, both own ones
 24 and ones inherited from the prototype chain.
 25 
 26 -- Testcase --
 27 {%
 28         let hits = [];
 29 
 30         let o = proto({ own: 1 }, {
 31                 inherited: 2,
 32                 __get__(key) {
 33                         push(hits, key);
 34                         return "virtual";
 35                 }
 36         });
 37 
 38         print(o.own, " ", o.inherited, " ", o.missing, "\n");
 39         printf("%.J\n", hits);
 40 %}
 41 -- End --
 42 
 43 -- Expect stdout --
 44 1 2 virtual
 45 [
 46         "missing"
 47 ]
 48 -- End --
 49 
 50 Metamethods are resolved by walking the whole prototype chain, so a
 51 grandparent prototype provides them as well. An own property with a dunder
 52 name is plain data, not a metamethod: it does not shadow the prototype's
 53 metamethod and is readable like any other property.
 54 
 55 -- Testcase --
 56 {%
 57         let grand = { __get__(key) { return "grand:" + key; } };
 58         let parent = proto({}, grand);
 59         let child = proto({}, parent);
 60 
 61         print(child.x, "\n");
 62 
 63         let o = proto({}, { __get__(key) { return "parent"; } });
 64         o.__get__ = function(key) { return "own"; };
 65 
 66         print(o.x, "\n");
 67         print(type(o.__get__), "\n");
 68 %}
 69 -- End --
 70 
 71 -- Expect stdout --
 72 grand:x
 73 parent
 74 function
 75 -- End --
 76 
 77 A `__get__` which is itself an object (rather than a function) delegates the
 78 lookup to that object. This is how a common set of virtual properties can be
 79 shared without copying.
 80 
 81 -- Testcase --
 82 {%
 83         let base = { greeting: "hi", shared: "base", n: 1 };
 84         let o = proto({ shared: "own" }, { __get__: base });
 85 
 86         print(o.greeting, " ", o.shared, " ", o.n + 1, " ", o.nope === null, "\n");
 87 %}
 88 -- End --
 89 
 90 -- Expect stdout --
 91 hi own 2 true
 92 -- End --
 93 
 94 A `__get__` function may return any value; that value becomes the result of
 95 the property read, including objects and arrays.
 96 
 97 -- Testcase --
 98 {%
 99         let base = { greeting: "hi", shared: "base", n: 1 };
100         let o = proto({}, { __get__(key) { return base; } });
101 
102         print(o.anything.greeting, " ", o.anything.shared, "\n");
103 %}
104 -- End --
105 
106 -- Expect stdout --
107 hi base
108 -- End --
109 
110 A metamethod is only honored when it is an actual function. Optional
111 chaining goes through the same lookup, so `?.` yields virtual properties
112 too.
113 
114 -- Testcase --
115 {%
116         let o = proto({}, { __get__: "not callable" });
117         let p = proto({}, { __get__(key) { return "virtual:" + key; } });
118 
119         print(o.x === null, "\n");
120         print(p?.y, "\n");
121 %}
122 -- End --
123 
124 -- Expect stdout --
125 true
126 virtual:y
127 -- End --
128 
129 Arrays with their own prototype participate in `__get__` delegation for
130 non-index keys.
131 
132 -- Testcase --
133 {%
134         let base = { label: "lan", mode: "up" };
135         let a = proto([1, 2, 3], { __get__: base });
136 
137         print(a[0], " ", a.label, " ", a.mode, " ", a.nope === null, "\n");
138 %}
139 -- End --
140 
141 -- Expect stdout --
142 1 lan up true
143 -- End --

This page was automatically generated by LXR 0.3.1.  •  OpenWrt