Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1953)

Side by Side Diff: test/mjsunit/harmony/proxies-example-membrane.js

Issue 8392038: A more holistic test case for proxies. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 // Flags: --harmony
29
30
31 // A simple no-op handler. Adapted from:
32 // http://wiki.ecmascript.org/doku.php?id=harmony:proxies#examplea_no-op_forward ing_proxy
Michael Starzinger 2011/10/28 12:08:34 I am not sure about the policy for long URLs in co
33
34 function createHandler(obj) {
35 return {
36 getOwnPropertyDescriptor: function(name) {
37 var desc = Object.getOwnPropertyDescriptor(obj, name);
38 if (desc !== undefined) desc.configurable = true;
39 return desc;
40 },
41 getPropertyDescriptor: function(name) {
42 var desc = Object.getOwnPropertyDescriptor(obj, name);
43 //var desc = Object.getPropertyDescriptor(obj, name); // not in ES5
44 if (desc !== undefined) desc.configurable = true;
45 return desc;
46 },
47 getOwnPropertyNames: function() {
48 return Object.getOwnPropertyNames(obj);
49 },
50 getPropertyNames: function() {
51 return Object.getOwnPropertyNames(obj);
52 //return Object.getPropertyNames(obj); // not in ES5
53 },
54 defineProperty: function(name, desc) {
55 Object.defineProperty(obj, name, desc);
56 },
57 delete: function(name) {
58 return delete obj[name];
59 },
60 fix: function() {
61 if (Object.isFrozen(obj)) {
62 var result = {};
63 Object.getOwnPropertyNames(obj).forEach(function(name) {
64 result[name] = Object.getOwnPropertyDescriptor(obj, name);
65 });
66 return result;
67 }
68 // As long as obj is not frozen, the proxy won't allow itself to be fixed
69 return undefined; // will cause a TypeError to be thrown
70 },
71 has: function(name) { return name in obj; },
72 hasOwn: function(name) { return ({}).hasOwnProperty.call(obj, name); },
73 get: function(receiver, name) { return obj[name]; },
74 set: function(receiver, name, val) {
75 obj[name] = val; // bad behavior when set fails in non-strict mode
76 return true;
77 },
78 enumerate: function() {
79 var result = [];
80 for (var name in obj) { result.push(name); };
81 return result;
82 },
83 keys: function() { return Object.keys(obj); }
84 };
85 }
86
87
88
89 // Auxiliary definitions enabling tracking of object identity in output.
90
91 var objectMap = new WeakMap;
92 var objectCounter = 0;
93
94 function registerObject(x, s) {
95 if (x === Object(x) && !objectMap.has(x))
96 objectMap.set(x, ++objectCounter + (s == undefined ? "" : ":" + s));
97 }
98
99 registerObject(this, "global");
100 registerObject(Object.prototype, "Object.prototype");
101
102 function str(x) {
103 if (x === Object(x)) return "[" + typeof x + " " + objectMap.get(x) + "]";
104 if (typeof x == "string") return "\"" + x + "\"";
105 return "" + x;
106 }
107
108
109
110 // A simple membrane. Adapted from:
111 // http://wiki.ecmascript.org/doku.php?id=harmony:proxies#a_simple_membrane
112
113 function createSimpleMembrane(target) {
114 var enabled = true;
115
116 function wrap(obj) {
117 registerObject(obj);
118 print("wrap enter", str(obj));
119 try {
120 var x = wrap2(obj);
121 registerObject(x, "wrapped");
122 print("wrap exit", str(obj), "as", str(x));
123 return x;
124 } catch(e) {
125 print("wrap exception", str(e));
126 throw e;
127 }
128 }
129
130 function wrap2(obj) {
131 if (obj !== Object(obj)) {
132 return obj;
133 }
134
135 function wrapCall(fun, that, args) {
136 registerObject(that);
137 print("wrapCall enter", fun, str(that));
138 try {
139 var x = wrapCall2(fun, that, args);
140 print("wrapCall exit", fun, str(that), "returning", str(x));
141 return x;
142 } catch(e) {
143 print("wrapCall exception", fun, str(that), str(e));
144 throw e;
145 }
146 }
147
148 function wrapCall2(fun, that, args) {
149 if (!enabled) { throw new Error("disabled"); }
150 try {
151 return wrap(fun.apply(that, Array.prototype.map.call(args, wrap)));
152 } catch (e) {
153 throw wrap(e);
154 }
155 }
156
157 var baseHandler = createHandler(obj);
158 var handler = Proxy.create(Object.freeze({
159 get: function(receiver, name) {
160 return function() {
161 var arg = (name === "get" || name == "set") ? arguments[1] : "";
162 print("handler enter", name, arg);
163 var x = wrapCall(baseHandler[name], baseHandler, arguments);
164 print("handler exit", name, arg, "returning", str(x));
165 return x;
166 }
167 }
168 }));
169 registerObject(baseHandler, "basehandler");
170 registerObject(handler, "handler");
171
172 if (typeof obj === "function") {
173 function callTrap() {
174 print("call trap enter", str(obj), str(this));
175 var x = wrapCall(obj, wrap(this), arguments);
176 print("call trap exit", str(obj), str(this), "returning", str(x));
177 return x;
178 }
179 function constructTrap() {
180 if (!enabled) { throw new Error("disabled"); }
181 try {
182 function forward(args) { return obj.apply(this, args) }
183 return wrap(new forward(Array.prototype.map.call(arguments, wrap)));
184 } catch (e) {
185 throw wrap(e);
186 }
187 }
188 return Proxy.createFunction(handler, callTrap, constructTrap);
189 } else {
190 var prototype = wrap(Object.getPrototypeOf(obj));
191 return Proxy.create(handler, prototype);
192 }
193 }
194
195 var gate = Object.freeze({
196 enable: function() { enabled = true; },
197 disable: function() { enabled = false; }
198 });
199
200 return Object.freeze({
201 wrapper: wrap(target),
202 gate: gate
203 });
204 }
205
206
207 var o = {
208 a: 6,
209 b: {bb: 8},
210 f: function(x) { return x },
211 g: function(x) { return x.a },
212 h: function(x) { this.q = x }
213 };
214 o[2] = {c: 7};
215 var m = createSimpleMembrane(o);
216 var w = m.wrapper;
217 print("w =", str(w));
218
219 var f = w.f;
220 var x = f(66);
221 var x = f({a: 1});
222 var x = w.f({a: 1});
223 var a = x.a;
224 assertEquals(6, w.a);
225 assertEquals(8, w.b.bb);
226 assertEquals(7, w[2]["c"]);
227 assertEquals(undefined, w.c);
228 assertEquals(1, w.f(1));
229 assertEquals(1, w.f({a: 1}).a);
230 assertEquals(2, w.g({a: 2}));
231 assertEquals(3, (w.r = {a: 3}).a);
232 assertEquals(3, w.r.a);
233 assertEquals(3, o.r.a);
234 w.h(3);
235 assertEquals(3, w.q);
236 assertEquals(3, o.q);
237 assertEquals(4, (new w.h(4)).q);
238
239 var wb = w.b;
240 var wr = w.r;
241 var wf = w.f;
242 var wf3 = w.f(3);
243 var wfx = w.f({a: 6});
244 var wgx = w.g({a: {aa: 7}});
245 var wh4 = new w.h(4);
246 m.gate.disable();
247 assertEquals(3, wf3);
248 assertThrows(function() { w.a }, Error);
249 assertThrows(function() { w.r }, Error);
250 assertThrows(function() { w.r = {a: 4} }, Error);
251 assertThrows(function() { o.r.a }, Error);
252 assertEquals("object", typeof o.r);
253 assertEquals(5, (o.r = {a: 5}).a);
254 assertEquals(5, o.r.a);
255 assertThrows(function() { w[1] }, Error);
256 assertThrows(function() { w.c }, Error);
257 assertThrows(function() { wb.bb }, Error);
258 assertThrows(function() { wr.a }, Error);
259 assertThrows(function() { wf(4) }, Error);
260 assertThrows(function() { wfx.a }, Error);
261 assertThrows(function() { wgx.aa }, Error);
262 assertThrows(function() { wh4.q }, Error);
263
264 m.gate.enable();
265 assertEquals(6, w.a);
266 assertEquals(5, w.r.a);
267 assertEquals(5, o.r.a);
268 assertEquals(7, w.r = 7);
269 assertEquals(7, w.r);
270 assertEquals(7, o.r);
271 assertEquals(8, w.b.bb);
272 assertEquals(7, w[2]["c"]);
273 assertEquals(undefined, w.c);
274 assertEquals(8, wb.bb);
275 assertEquals(3, wr.a);
276 assertEquals(4, wf(4));
277 assertEquals(3, wf3);
278 assertEquals(6, wfx.a);
279 assertEquals(7, wgx.aa);
280 assertEquals(4, wh4.q);
281
282
283 // An identity-preserving membrane. Adapted from:
284 // http://wiki.ecmascript.org/doku.php?id=harmony:proxies#an_identity-preserving _membrane
Michael Starzinger 2011/10/28 12:08:34 Likewise.
285
286 function createMembrane(wetTarget) {
287 var wet2dry = WeakMap();
288 var dry2wet = WeakMap();
289
290 function asDry(obj) {
291 registerObject(obj)
292 print("asDry enter", str(obj))
293 try {
294 var x = asDry2(obj);
295 registerObject(x, "dry");
296 print("asDry exit", str(obj), "as", str(x));
297 return x;
298 } catch(e) {
299 print("asDry exception", str(e));
300 throw e;
301 }
302 }
303 function asDry2(wet) {
304 if (wet !== Object(wet)) {
305 // primitives provide only irrevocable knowledge, so don't
306 // bother wrapping it.
307 return wet;
308 }
309 var dryResult = wet2dry.get(wet);
310 if (dryResult) { return dryResult; }
311
312 var wetHandler = createHandler(wet);
313 var dryRevokeHandler = Proxy.create(Object.freeze({
314 get: function(receiver, name) {
315 return function() {
316 var arg = (name === "get" || name == "set") ? arguments[1] : "";
317 print("dry handler enter", name, arg);
318 var optWetHandler = dry2wet.get(dryRevokeHandler);
319 try {
320 var x = asDry(optWetHandler[name].apply(
321 optWetHandler, Array.prototype.map.call(arguments, asWet)));
322 print("dry handler exit", name, arg, "returning", str(x));
323 return x;
324 } catch (eWet) {
325 var x = asDry(eWet);
326 print("dry handler exception", name, arg, "throwing", str(x));
327 throw x;
328 }
329 };
330 }
331 }));
332 dry2wet.set(dryRevokeHandler, wetHandler);
333
334 if (typeof wet === "function") {
335 function callTrap() {
336 print("dry call trap enter", str(this));
337 var x = asDry(wet.apply(
338 asWet(this), Array.prototype.map.call(arguments, asWet)));
339 print("dry call trap exit", str(this), "returning", str(x));
340 return x;
341 }
342 function constructTrap() {
343 function forward(args) { return wet.apply(this, args) }
344 return asDry(new forward(Array.prototype.map.call(arguments, asWet)));
345 }
346 dryResult =
347 Proxy.createFunction(dryRevokeHandler, callTrap, constructTrap);
348 } else {
349 dryResult =
350 Proxy.create(dryRevokeHandler, asDry(Object.getPrototypeOf(wet)));
351 }
352 wet2dry.set(wet, dryResult);
353 dry2wet.set(dryResult, wet);
354 return dryResult;
355 }
356
357 function asWet(obj) {
358 registerObject(obj)
359 print("asWet enter", str(obj))
360 try {
361 var x = asWet2(obj)
362 registerObject(x, "wet")
363 print("asWet exit", str(obj), "as", str(x))
364 return x
365 } catch(e) {
366 print("asWet exception", str(e))
367 throw e
368 }
369 }
370 function asWet2(dry) {
371 if (dry !== Object(dry)) {
372 // primitives provide only irrevocable knowledge, so don't
373 // bother wrapping it.
374 return dry;
375 }
376 var wetResult = dry2wet.get(dry);
377 if (wetResult) { return wetResult; }
378
379 var dryHandler = createHandler(dry);
380 var wetRevokeHandler = Proxy.create(Object.freeze({
381 get: function(receiver, name) {
382 return function() {
383 var arg = (name === "get" || name == "set") ? arguments[1] : "";
384 print("wet handler enter", name, arg);
385 var optDryHandler = wet2dry.get(wetRevokeHandler);
386 try {
387 var x = asWet(optDryHandler[name].apply(
388 optDryHandler, Array.prototype.map.call(arguments, asDry)));
389 print("wet handler exit", name, arg, "returning", str(x));
390 return x;
391 } catch (eDry) {
392 var x = asWet(eDry);
393 print("wet handler exception", name, arg, "throwing", str(x));
394 throw x;
395 }
396 };
397 }
398 }));
399 wet2dry.set(wetRevokeHandler, dryHandler);
400
401 if (typeof dry === "function") {
402 function callTrap() {
403 print("wet call trap enter", str(this));
404 var x = asWet(dry.apply(
405 asDry(this), Array.prototype.map.call(arguments, asDry)));
406 print("wet call trap exit", str(this), "returning", str(x));
407 return x;
408 }
409 function constructTrap() {
410 function forward(args) { return dry.apply(this, args) }
411 return asWet(new forward(Array.prototype.map.call(arguments, asDry)));
412 }
413 wetResult =
414 Proxy.createFunction(wetRevokeHandler, callTrap, constructTrap);
415 } else {
416 wetResult =
417 Proxy.create(wetRevokeHandler, asWet(Object.getPrototypeOf(dry)));
418 }
419 dry2wet.set(dry, wetResult);
420 wet2dry.set(wetResult, dry);
421 return wetResult;
422 }
423
424 var gate = Object.freeze({
425 revoke: function() {
426 dry2wet = wet2dry = Object.freeze({
427 get: function(key) { throw new Error("revoked"); },
428 set: function(key, val) { throw new Error("revoked"); }
429 });
430 }
431 });
432
433 return Object.freeze({ wrapper: asDry(wetTarget), gate: gate });
434 }
435
436
437 var receiver
438 var argument
439 var o = {
440 a: 6,
441 b: {bb: 8},
442 f: function(x) { receiver = this; argument = x; return x },
443 g: function(x) { receiver = this; argument = x; return x.a },
444 h: function(x) { receiver = this; argument = x; this.q = x },
445 s: function(x) { receiver = this; argument = x; this.x = {y: x}; return this }
446 }
447 o[2] = {c: 7}
448 var m = createMembrane(o)
449 var w = m.wrapper
450 print("dry w =", str(w))
451
452 var f = w.f
453 var x = f(66)
454 var x = f({a: 1})
455 var x = w.f({a: 1})
456 var a = x.a
457 assertEquals(6, w.a)
458 assertEquals(8, w.b.bb)
459 assertEquals(7, w[2]["c"])
460 assertEquals(undefined, w.c)
461 assertEquals(1, w.f(1))
462 assertSame(o, receiver)
463 assertEquals(1, w.f({a: 1}).a)
464 assertSame(o, receiver)
465 assertEquals(2, w.g({a: 2}))
466 assertSame(o, receiver)
467 assertEquals(w, w.f(w))
468 assertSame(o, receiver)
469 assertSame(o, argument)
470 assertEquals(o, w.f(o))
471 assertSame(o, receiver)
472 assertSame(o, argument)
473 assertEquals(3, (w.r = {a: 3}).a)
474 assertEquals(3, w.r.a)
475 assertEquals(3, o.r.a)
476 w.h(3)
477 assertEquals(3, w.q)
478 assertEquals(3, o.q)
479 assertEquals(4, (new w.h(4)).q)
480 assertEquals(5, w.s(5).x.y)
481 assertSame(o, receiver)
482
483 var wb = w.b
484 var wr = w.r
485 var wf = w.f
486 var wf3 = w.f(3)
487 var wfx = w.f({a: 6})
488 var wgx = w.g({a: {aa: 7}})
489 var wh4 = new w.h(4)
490 var ws5 = w.s(5)
491 var ws5x = ws5.x
492 m.gate.revoke()
493 assertEquals(3, wf3)
494 assertThrows(function() { w.a }, Error)
495 assertThrows(function() { w.r }, Error)
496 assertThrows(function() { w.r = {a: 4} }, Error)
497 assertThrows(function() { o.r.a }, Error)
498 assertEquals("object", typeof o.r)
499 assertEquals(5, (o.r = {a: 5}).a)
500 assertEquals(5, o.r.a)
501 assertThrows(function() { w[1] }, Error)
502 assertThrows(function() { w.c }, Error)
503 assertThrows(function() { wb.bb }, Error)
504 assertEquals(3, wr.a)
505 assertThrows(function() { wf(4) }, Error)
506 assertEquals(6, wfx.a)
507 assertEquals(7, wgx.aa)
508 assertThrows(function() { wh4.q }, Error)
509 assertThrows(function() { ws5.x }, Error)
510 assertThrows(function() { ws5x.y }, Error)
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698