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

Sources/ucode/tests/custom/03_stdlib/40_proto

  1 The `proto()` function retrievs or sets the prototype of the given object
  2 or resource value.
  3 
  4 Throws an exception if given value does not support setting prototypes.
  5 
  6 When invoked with one argument, returns the prototype of the given value
  7 (if any).
  8 
  9 When invoked with two arguments, returns the given value.
 10 
 11 -- Testcase --
 12 {%
 13         let fs = require("fs");
 14 
 15         // create a "class instance" by attaching a function dictionary to
 16         // a plain object.
 17         let obj = proto({}, {
 18                 greeting: function(name) {
 19                         printf("Hello, %s!\n", name);
 20                 }
 21         });
 22 
 23         // accessing a property on `obj` will look up the prototype chain
 24         // if the object itself does not have it
 25         obj.greeting("World");
 26 
 27         printf("%.J\n", [
 28                 // retrieve prototype of `fs.file` resource
 29                 proto(fs.stdout),
 30 
 31                 // retrieve prototype of `obj`
 32                 proto(obj)
 33         ]);
 34 %}
 35 -- End --
 36 
 37 -- Expect stdout --
 38 Hello, World!
 39 [
 40         {
 41                 "ioctl": "function ioctl(...) { [native code] }",
 42                 "lock": "function lock(...) { [native code] }",
 43                 "truncate": "function truncate(...) { [native code] }",
 44                 "isatty": "function isatty(...) { [native code] }",
 45                 "error": "function error(...) { [native code] }",
 46                 "fileno": "function fileno(...) { [native code] }",
 47                 "flush": "function flush(...) { [native code] }",
 48                 "close": "function close(...) { [native code] }",
 49                 "tell": "function tell(...) { [native code] }",
 50                 "seek": "function seek(...) { [native code] }",
 51                 "write": "function write(...) { [native code] }",
 52                 "read": "function read(...) { [native code] }"
 53         },
 54         {
 55                 "greeting": "function(name) { ... }"
 56         }
 57 ]
 58 -- End --
 59 
 60 
 61 
 62 Passing an invalid value throws an exception.
 63 
 64 -- Testcase --
 65 {%
 66         proto("inval", {});
 67 %}
 68 -- End --
 69 
 70 -- Expect stderr --
 71 Type error: Passed value is neither a prototype, resource or object
 72 In line 2, byte 19:
 73 
 74  `    proto("inval", {});`
 75       ~~~~~~~~~~~~~~~~~^~
 76 
 77 
 78 -- End --
 79 
 80 -- Testcase --
 81 {%
 82         proto({}, "inval");
 83 %}
 84 -- End --
 85 
 86 -- Expect stderr --
 87 Type error: Passed value is neither a prototype, resource or object
 88 In line 2, byte 19:
 89 
 90  `    proto({}, "inval");`
 91       ~~~~~~~~~~~~~~~~~^~
 92 
 93 
 94 -- End --
 95 
 96 
 97 Setting the prototype of a value to itself is rejected, as it would
 98 create a circular prototype chain causing endless loops in lookups.
 99 
100 -- Testcase --
101 {%
102         let a = {};
103         proto(a, a);
104 %}
105 -- End --
106 
107 -- Expect stderr --
108 Type error: Cannot set circular prototype
109 In line 3, byte 12:
110 
111  `    proto(a, a);`
112       ~~~~~~~~~~^~
113 
114 
115 -- End --
116 
117 
118 Setting the prototype of a value to a value in its own prototype chain
119 is rejected as well.
120 
121 -- Testcase --
122 {%
123         let a = {};
124         let b = {};
125 
126         proto(a, b);
127         proto(b, a);
128 %}
129 -- End --
130 
131 -- Expect stderr --
132 Type error: Cannot set circular prototype
133 In line 6, byte 12:
134 
135  `    proto(b, a);`
136       ~~~~~~~~~~^~
137 
138 
139 -- End --
140 
141 
142 Longer circular chains are rejected as well.
143 
144 -- Testcase --
145 {%
146         let a = {};
147         let b = {};
148         let c = {};
149 
150         proto(a, b);
151         proto(b, c);
152         proto(c, a);
153 %}
154 -- End --
155 
156 -- Expect stderr --
157 Type error: Cannot set circular prototype
158 In line 8, byte 12:
159 
160  `    proto(c, a);`
161       ~~~~~~~~~~^~
162 
163 
164 -- End --
165 
166 
167 Reassigning a prototype to a value that is not in its chain remains
168 allowed, including pointing at a former ancestor.
169 
170 -- Testcase --
171 {%
172         let a = {};
173         let b = { x: 1 };
174         let c = { y: 2 };
175 
176         proto(a, b);
177         proto(b, c);
178 
179         // a -> b -> c, pointing a at c does not create a cycle
180         proto(a, c);
181 
182         // b is no longer in a's chain, so a.x is null but a.y resolves
183         printf("%.J\n", [ a.x, a.y ]);
184 %}
185 -- End --
186 
187 -- Expect stdout --
188 [
189         null,
190         2
191 ]
192 -- End --
193 
194 
195 Setting a prototype takes exactly one reference on it, which the value
196 releases when it is freed or given another prototype.
197 
198 -- Testcase --
199 {%
200         let getinfo = require("debug").getinfo;
201         let p = { x: 1 };
202         let base = getinfo(p).refcount;
203         let refs = () => getinfo(p).refcount - base;
204         let counts = {};
205 
206         for (let i = 0; i < 100; i++)
207                 proto({}, p);
208 
209         counts.discarded = refs();
210 
211         let held = [];
212 
213         for (let i = 0; i < 10; i++)
214                 push(held, proto({}, p));
215 
216         counts.held = refs();
217 
218         held = null;
219         counts.released = refs();
220 
221         let a = proto({}, p);
222 
223         proto(a, { y: 2 });
224         counts.reassigned = refs();
225 
226         let c = proto({}, p);
227         let before = getinfo(c).refcount;
228 
229         try {
230                 proto(p, c);
231         }
232         catch (e) {
233                 counts.rejected = getinfo(c).refcount - before;
234         }
235 
236         printf("%.J\n", counts);
237 %}
238 -- End --
239 
240 -- Expect stdout --
241 {
242         "discarded": 0,
243         "held": 10,
244         "released": 0,
245         "reassigned": 0,
246         "rejected": 0
247 }
248 -- End --
249 
250 
251 Setting the prototype of a resource with an own prototype releases the
252 previous one.
253 
254 -- Testcase --
255 {%
256         let ffi;
257 
258         try {
259                 ffi = require("ffi");
260         }
261         catch (e) {
262                 exit(77);
263         }
264 
265         let getinfo = require("debug").getinfo;
266         let p = { x: 1 };
267         let q = { y: 2 };
268         let base = getinfo(p).refcount;
269         let counts = {};
270 
271         proto(ffi.C, p);
272         counts.held = getinfo(p).refcount - base;
273 
274         proto(ffi.C, q);
275         counts.released = getinfo(p).refcount - base;
276         counts.current = (proto(ffi.C) == q);
277 
278         printf("%.J\n", counts);
279 %}
280 -- End --
281 
282 -- Expect stdout --
283 {
284         "held": 1,
285         "released": 0,
286         "current": true
287 }
288 -- End --

This page was automatically generated by LXR 0.3.1.  •  OpenWrt