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

Sources/ucode/tests/custom/06_metamethods/20_delete

  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