1 The `__set__` metamethod is consulted when a property is assigned which is 2 not already an own property of the object. It is invoked as a method on the 3 instance, with the key and the value as arguments. 4 5 -- Testcase -- 6 {% 7 let log = []; 8 9 let o = proto({ own: 1 }, { 10 __set__(key, val) { 11 push(log, key + "=" + val); 12 rawset(this, "backing:" + key, val); 13 } 14 }); 15 16 o.nw = 2; 17 o.own = 3; 18 19 print(rawget(o, "backing:nw"), " ", o.own, "\n"); 20 print(log, " 21 "); 22 %} 23 -- End -- 24 25 -- Expect stdout -- 26 2 3 27 [ "nw=2" ] 28 -- End -- 29 30 An assignment evaluates to the assigned value, not to whatever the invoked 31 `__set__` returns. 32 33 -- Testcase -- 34 {% 35 let o = proto({}, { 36 __set__(key, val) { 37 rawset(this, key, val * 2); 38 return "ignored"; 39 } 40 }); 41 42 print((o.x = 21) === 21, " ", o.x, "\n"); 43 %} 44 -- End -- 45 46 -- Expect stdout -- 47 true 42 48 -- End -- 49 50 Object literals store their members without dispatching `__set__`, including 51 a metamethod of the very same object. 52 53 -- Testcase -- 54 {% 55 let o = { 56 __set__(key, val) { 57 die("intercepted " + key); 58 }, 59 a: 1, 60 b: null 61 }; 62 63 print(o.a, " ", o.b === null, " ", length(keys(o)), "\n"); 64 %} 65 -- End -- 66 67 -- Expect stdout -- 68 1 true 3 69 -- End -- 70 71 A null value is stored and read back like any other value. 72 73 -- Testcase -- 74 {% 75 let o = proto({ n: null }, { __get__(key) { return "virtual"; } }); 76 77 print(o.n === null, " "); 78 79 o.a = 1; 80 o.a = null; 81 print(o.a === null, " ", rawget(o, "a") === null, " "); 82 83 rawset(o, "b", null); 84 printf("%.J\n", keys(o)); 85 %} 86 -- End -- 87 88 -- Expect stdout -- 89 true true true [ 90 "n", 91 "a", 92 "b" 93 ] 94 -- End -- 95 96 A `__set__` which is itself an object (rather than a function) delegates the 97 store to that object. 98 99 -- Testcase -- 100 {% 101 let target = {}; 102 let o = proto({}, { __set__: target }); 103 104 o.x = 42; 105 o.y = "hello"; 106 107 print(target.x, " ", target.y, "\n"); 108 print(rawget(o, "x") === null, "\n"); 109 %} 110 -- End -- 111 112 -- Expect stdout -- 113 42 hello 114 true 115 -- End -- 116 117 A delegated store re-dispatches the target's own metamethods, so a chain of 118 delegation reaches the final storage. 119 120 -- Testcase -- 121 {% 122 let store = {}; 123 let mid = proto({}, { __set__(key, val) { store[key] = val; } }); 124 let o = proto({}, { __set__: mid }); 125 126 o.n = 7; 127 128 print(store.n, " ", rawget(o, "n") === null, "\n"); 129 %} 130 -- End -- 131 132 -- Expect stdout -- 133 7 true 134 -- End -- 135 136 Arrays with their own prototype take part in `__set__` delegation for non-index 137 keys just like objects do. 138 139 -- Testcase -- 140 {% 141 let target = {}; 142 let a = proto([10, 20], { __set__: target, __get__: target }); 143 144 a[0] = 99; 145 a.name = "lan"; 146 147 print(a[0], " ", a.name, " ", target.name, "\n"); 148 %} 149 -- End -- 150 151 -- Expect stdout -- 152 99 lan lan 153 -- End --
This page was automatically generated by LXR 0.3.1. • OpenWrt