OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Flags: --harmony-proxies | 5 // Flags: --harmony-proxies --harmony-reflect |
6 | 6 |
7 var target = { target: 1 }; | 7 var target = { target: 1 }; |
8 target.__proto__ = {}; | 8 target.__proto__ = {}; |
9 var handler = { handler: 1 }; | 9 var handler = { handler: 1 }; |
10 var proxy = new Proxy(target, handler); | 10 var proxy = new Proxy(target, handler); |
11 | 11 |
12 assertSame(Object.getPrototypeOf(proxy), target.__proto__ ); | 12 assertSame(Object.getPrototypeOf(proxy), target.__proto__ ); |
13 | 13 |
| 14 |
14 assertThrows(function() { Object.setPrototypeOf(proxy, undefined) }, TypeError); | 15 assertThrows(function() { Object.setPrototypeOf(proxy, undefined) }, TypeError); |
15 assertThrows(function() { Object.setPrototypeOf(proxy, 1) }, TypeError); | 16 assertThrows(function() { Object.setPrototypeOf(proxy, 1) }, TypeError); |
16 | 17 |
17 var prototype = [1]; | 18 var prototype = [1]; |
18 assertSame(proxy, Object.setPrototypeOf(proxy, prototype)); | 19 assertSame(proxy, Object.setPrototypeOf(proxy, prototype)); |
19 assertSame(prototype, Object.getPrototypeOf(proxy)); | 20 assertSame(prototype, Object.getPrototypeOf(proxy)); |
20 assertSame(prototype, Object.getPrototypeOf(target)); | 21 assertSame(prototype, Object.getPrototypeOf(target)); |
21 | 22 |
| 23 var pair = Proxy.revocable(target, handler); |
| 24 assertSame(pair.proxy, Object.setPrototypeOf(pair.proxy, prototype)); |
| 25 assertSame(prototype, Object.getPrototypeOf(pair.proxy)); |
| 26 pair.revoke(); |
| 27 assertThrows('Object.setPrototypeOf(pair.proxy, prototype)', TypeError); |
| 28 |
22 handler.setPrototypeOf = function(target, proto) { | 29 handler.setPrototypeOf = function(target, proto) { |
23 return false; | 30 return false; |
24 }; | 31 }; |
25 assertThrows(function() { Object.setPrototypeOf(proxy, {a:1}) }, TypeError); | 32 assertThrows(function() { Object.setPrototypeOf(proxy, {a:1}) }, TypeError); |
26 | 33 |
27 handler.setPrototypeOf = function(target, proto) { | 34 handler.setPrototypeOf = function(target, proto) { |
28 return undefined; | 35 return undefined; |
29 }; | 36 }; |
30 assertThrows(function() { Object.setPrototypeOf(proxy, {a:2}) }, TypeError); | 37 assertThrows(function() { Object.setPrototypeOf(proxy, {a:2}) }, TypeError); |
31 | 38 |
32 handler.setPrototypeOf = function(proto) {}; | 39 handler.setPrototypeOf = function(proto) {}; |
33 assertThrows(function() { Object.setPrototypeOf(proxy, {a:3}) }, TypeError); | 40 assertThrows(function() { Object.setPrototypeOf(proxy, {a:3}) }, TypeError); |
34 | 41 |
35 handler.setPrototypeOf = function(target, proto) { | 42 handler.setPrototypeOf = function(target, proto) { |
36 throw Error(); | 43 throw Error(); |
37 }; | 44 }; |
38 assertThrows(function() { Object.setPrototypeOf(proxy, {a:4}) }, Error); | 45 assertThrows(function() { Object.setPrototypeOf(proxy, {a:4}) }, Error); |
39 | 46 |
40 var seen_prototype; | 47 var seen_prototype; |
41 var seen_target; | 48 var seen_target; |
42 handler.setPrototypeOf = function(target, proto) { | 49 handler.setPrototypeOf = function(target, proto) { |
43 seen_target = target; | 50 seen_target = target; |
44 seen_prototype = proto; | 51 seen_prototype = proto; |
45 return true; | 52 return true; |
46 } | 53 } |
47 assertSame(Object.setPrototypeOf(proxy, {a:5}), proxy); | 54 assertSame(Object.setPrototypeOf(proxy, {a:5}), proxy); |
48 assertSame(target, seen_target); | 55 assertSame(target, seen_target); |
49 assertEquals({a:5}, seen_prototype); | 56 assertEquals({a:5}, seen_prototype); |
50 | 57 |
51 // Target is a Proxy: | 58 (function setPrototypeProxyTarget() { |
52 var target2 = new Proxy(target, {}); | 59 var target = { target: 1 }; |
53 var proxy2 = new Proxy(target2, {}); | 60 target.__proto__ = {}; |
54 assertSame(Object.getPrototypeOf(proxy2), target.__proto__ ); | 61 var handler = {}; |
| 62 var handler2 = {}; |
| 63 var target2 = new Proxy(target, handler2); |
| 64 var proxy2 = new Proxy(target2, handler); |
| 65 assertSame(Object.getPrototypeOf(proxy2), target.__proto__ ); |
55 | 66 |
56 prototype = [2,3]; | 67 var prototype = [2,3]; |
57 assertSame(proxy2, Object.setPrototypeOf(proxy2, prototype)); | 68 assertSame(proxy2, Object.setPrototypeOf(proxy2, prototype)); |
58 assertSame(prototype, Object.getPrototypeOf(proxy2)); | 69 assertSame(prototype, Object.getPrototypeOf(proxy2)); |
59 assertSame(prototype, Object.getPrototypeOf(target)); | 70 assertSame(prototype, Object.getPrototypeOf(target)); |
| 71 })(); |
| 72 |
| 73 (function testProxyTrapInconsistent() { |
| 74 var target = { target: 1 }; |
| 75 target.__proto__ = {}; |
| 76 var handler = {}; |
| 77 var handler2 = { |
| 78 }; |
| 79 |
| 80 var target2 = new Proxy(target, handler); |
| 81 var proxy2 = new Proxy(target2, handler2); |
| 82 |
| 83 // If the final target is extensible we can set any prototype. |
| 84 var prototype = [1]; |
| 85 Reflect.setPrototypeOf(proxy2, prototype); |
| 86 assertSame(prototype, Reflect.getPrototypeOf(target)); |
| 87 |
| 88 handler2.setPrototypeOf = function(target, value) { |
| 89 Reflect.setPrototypeOf(target, value); |
| 90 return true; |
| 91 }; |
| 92 prototype = [2]; |
| 93 Reflect.setPrototypeOf(proxy2, prototype); |
| 94 assertSame(prototype, Reflect.getPrototypeOf(target)); |
| 95 |
| 96 // Prevent getting the target's prototype used to check the invariant. |
| 97 var gotPrototype = false; |
| 98 handler.getPrototypeOf = function() { |
| 99 gotPrototype = true; |
| 100 throw TypeError() |
| 101 }; |
| 102 // If the target is extensible we do not check the invariant. |
| 103 prototype = [3]; |
| 104 Reflect.setPrototypeOf(proxy2, prototype); |
| 105 assertFalse(gotPrototype); |
| 106 assertSame(prototype, Reflect.getPrototypeOf(target)); |
| 107 |
| 108 // Changing the prototype of a non-extensible target will trigger the |
| 109 // invariant-check and throw in the above handler. |
| 110 Reflect.preventExtensions(target); |
| 111 assertThrows(() => {Reflect.setPrototypeOf(proxy2, [4])}, TypeError); |
| 112 assertTrue(gotPrototype); |
| 113 assertEquals([3], Reflect.getPrototypeOf(target)); |
| 114 |
| 115 // Setting the prototype of a non-extensible target is fine if the prototype |
| 116 // doesn't change. |
| 117 delete handler.getPrototypeOf; |
| 118 Reflect.setPrototypeOf(proxy2, prototype); |
| 119 // Changing the prototype will throw. |
| 120 prototype = [5]; |
| 121 assertThrows(() => {Reflect.setPrototypeOf(proxy2, prototype)}, TypeError); |
| 122 })(); |
OLD | NEW |