1 The `__delete__` metamethod is consulted when a property is deleted which is 2 not an own property of the object. It is invoked as a method on the instance, 3 with the key as single argument. A truthy return value means "deleted". 4 5 -- Testcase -- 6 {% 7 let log = []; 8 9 let o = proto({ own: 1 }, { 10 __delete__(key) { 11 push(log, key); 12 return key == "virtual"; 13 } 14 }); 15 16 print(delete o.virtual, " ", delete o.other, " ", delete o.own, " ", o.own === null, "\n"); 17 print(log, " 18 "); 19 %} 20 -- End -- 21 22 -- Expect stdout -- 23 true false true true 24 [ "virtual", "other" ] 25 -- End -- 26 27 Deleting an own property does not consult the metamethod. 28 29 -- Testcase -- 30 {% 31 let o = proto({ own: 1 }, { 32 __delete__(key) { 33 die("intercepted " + key); 34 } 35 }); 36 37 print(delete o.own, "\n"); 38 %} 39 -- End -- 40 41 -- Expect stdout -- 42 true 43 -- End -- 44 45 A `__delete__` which is itself an object (rather than a function) delegates the 46 delete to that object. 47 48 -- Testcase -- 49 {% 50 let target = { a: 1, b: 2 }; 51 let o = proto({}, { __delete__: target }); 52 53 print(delete o.a, " ", delete o.c, "\n"); 54 print(target.a === null, " ", target.b, "\n"); 55 %} 56 -- End -- 57 58 -- Expect stdout -- 59 true false 60 true 2 61 -- End -- 62 63 A delegated delete re-dispatches the target's own metamethods. 64 65 -- Testcase -- 66 {% 67 let store = { x: 1 }; 68 let log = []; 69 let mid = proto({}, { 70 __delete__(key) { 71 push(log, key); 72 return delete store[key]; 73 } 74 }); 75 let o = proto({}, { __delete__: mid }); 76 77 print(delete o.x, " ", delete o.missing, "\n"); 78 print(store.x === null, " ", log, "\n"); 79 %} 80 -- End -- 81 82 -- Expect stdout -- 83 true false 84 true [ "x", "missing" ] 85 -- End -- 86 87 Arrays take part in `__delete__` for non-index keys, just like they do for 88 `__get__` and `__set__`: since an array has no own-key storage to remove the 89 key from, the metamethod is the only way to handle such a key. 90 91 -- Testcase -- 92 {% 93 let store = { x: 1, y: 2 }; 94 let log = []; 95 96 let a = proto([1, 2], { 97 __set__(key, val) { store[key] = val; }, 98 __get__(key) { return store[key]; }, 99 __delete__(key) { 100 push(log, key); 101 return delete store[key]; 102 } 103 }); 104 105 a.x = 3; 106 107 print(a.x, " ", delete a.x, " ", delete a.ghost, " ", delete a.z, "\n"); 108 print(store, " ", log, "\n"); 109 %} 110 -- End -- 111 112 -- Expect stdout -- 113 3 true false false 114 { "y": 2 } [ "x", "ghost", "z" ] 115 -- End -- 116 117 A `__delete__` which is an object delegates the delete of an array key to that 118 object as well. 119 120 -- Testcase -- 121 {% 122 let target = { k: 1 }; 123 let a = proto([], { __delete__: target }); 124 125 print(delete a.k, " ", delete a.j, " ", target.k === null, "\n"); 126 %} 127 -- End -- 128 129 -- Expect stdout -- 130 true false true 131 -- End -- 132 133 Array elements are positional and not deletable, so a key which is an array 134 index - in range or not - is refused without consulting the metamethod, just 135 like on the read and write paths. Only keys which are no indices reach the 136 metamethod. 137 138 -- Testcase -- 139 {% 140 let a = proto([1, 2], { 141 __delete__(key) { 142 print("intercepted ", key, "\n"); 143 return true; 144 } 145 }); 146 147 let refused = []; 148 149 for (let k in [0, "1", -1, -9]) { 150 try { 151 delete a[k]; 152 push(refused, "accepted " + k); 153 } 154 catch (e) { 155 push(refused, "refused " + k); 156 } 157 } 158 159 print(refused, "\n"); 160 print(delete a[1.5], " ", delete a.name, " ", length(a), "\n"); 161 %} 162 -- End -- 163 164 -- Expect stdout -- 165 [ "refused 0", "refused 1", "refused -1", "refused -9" ] 166 intercepted 1.5 167 intercepted name 168 true true 2 169 -- End -- 170 171 Without a `__delete__` in effect there is nothing which could remove the key, 172 so the delete is refused with a reference error, as it is for any other value 173 kind which cannot carry a metamethod. 174 175 -- Testcase -- 176 {% 177 let a = [1, 2]; 178 179 try { delete a.x; } catch (e) { print(e, "\n"); } 180 try { delete a[0]; } catch (e) { print(e, "\n"); } 181 try { delete a.name; } catch (e) { print(e, "\n"); } 182 %} 183 -- End -- 184 185 -- Expect stdout -- 186 left-hand side expression is not an object 187 left-hand side expression is not an object 188 left-hand side expression is not an object 189 -- End --
This page was automatically generated by LXR 0.3.1. • OpenWrt