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 3// found in the LICENSE file. 4 5// Flags: --harmony-proxies --harmony-reflect 6 7var target = { target: 1 }; 8target.__proto__ = {}; 9var handler = { handler: 1 }; 10var proxy = new Proxy(target, handler); 11 12assertSame(Object.getPrototypeOf(proxy), target.__proto__ ); 13 14 15assertThrows(function() { Object.setPrototypeOf(proxy, undefined) }, TypeError); 16assertThrows(function() { Object.setPrototypeOf(proxy, 1) }, TypeError); 17 18var prototype = [1]; 19assertSame(proxy, Object.setPrototypeOf(proxy, prototype)); 20assertSame(prototype, Object.getPrototypeOf(proxy)); 21assertSame(prototype, Object.getPrototypeOf(target)); 22 23var pair = Proxy.revocable(target, handler); 24assertSame(pair.proxy, Object.setPrototypeOf(pair.proxy, prototype)); 25assertSame(prototype, Object.getPrototypeOf(pair.proxy)); 26pair.revoke(); 27assertThrows('Object.setPrototypeOf(pair.proxy, prototype)', TypeError); 28 29handler.setPrototypeOf = function(target, proto) { 30 return false; 31}; 32assertThrows(function() { Object.setPrototypeOf(proxy, {a:1}) }, TypeError); 33 34handler.setPrototypeOf = function(target, proto) { 35 return undefined; 36}; 37assertThrows(function() { Object.setPrototypeOf(proxy, {a:2}) }, TypeError); 38 39handler.setPrototypeOf = function(proto) {}; 40assertThrows(function() { Object.setPrototypeOf(proxy, {a:3}) }, TypeError); 41 42handler.setPrototypeOf = function(target, proto) { 43 throw Error(); 44}; 45assertThrows(function() { Object.setPrototypeOf(proxy, {a:4}) }, Error); 46 47var seen_prototype; 48var seen_target; 49handler.setPrototypeOf = function(target, proto) { 50 seen_target = target; 51 seen_prototype = proto; 52 return true; 53} 54assertSame(Object.setPrototypeOf(proxy, {a:5}), proxy); 55assertSame(target, seen_target); 56assertEquals({a:5}, seen_prototype); 57 58(function setPrototypeProxyTarget() { 59 var target = { target: 1 }; 60 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__ ); 66 67 var prototype = [2,3]; 68 assertSame(proxy2, Object.setPrototypeOf(proxy2, prototype)); 69 assertSame(prototype, Object.getPrototypeOf(proxy2)); 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})(); 123