1014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Copyright 2015 the V8 project authors. All rights reserved. 2014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// found in the LICENSE file. 4014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Flags: --harmony-proxies --harmony-reflect 6014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 7014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar target = { target: 1 }; 8014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochtarget.__proto__ = {}; 9014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar handler = { handler: 1 }; 10014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar proxy = new Proxy(target, handler); 11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochassertSame(Object.getPrototypeOf(proxy), target.__proto__ ); 13014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 14014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 15014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochassertThrows(function() { Object.setPrototypeOf(proxy, undefined) }, TypeError); 16014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochassertThrows(function() { Object.setPrototypeOf(proxy, 1) }, TypeError); 17014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 18014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar prototype = [1]; 19014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochassertSame(proxy, Object.setPrototypeOf(proxy, prototype)); 20014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochassertSame(prototype, Object.getPrototypeOf(proxy)); 21014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochassertSame(prototype, Object.getPrototypeOf(target)); 22014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar pair = Proxy.revocable(target, handler); 24014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochassertSame(pair.proxy, Object.setPrototypeOf(pair.proxy, prototype)); 25014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochassertSame(prototype, Object.getPrototypeOf(pair.proxy)); 26014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochpair.revoke(); 27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochassertThrows('Object.setPrototypeOf(pair.proxy, prototype)', TypeError); 28014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 29014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochhandler.setPrototypeOf = function(target, proto) { 30014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return false; 31014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}; 32014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochassertThrows(function() { Object.setPrototypeOf(proxy, {a:1}) }, TypeError); 33014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 34014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochhandler.setPrototypeOf = function(target, proto) { 35014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return undefined; 36014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}; 37014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochassertThrows(function() { Object.setPrototypeOf(proxy, {a:2}) }, TypeError); 38014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 39014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochhandler.setPrototypeOf = function(proto) {}; 40014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochassertThrows(function() { Object.setPrototypeOf(proxy, {a:3}) }, TypeError); 41014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 42014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochhandler.setPrototypeOf = function(target, proto) { 43014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw Error(); 44014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}; 45014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochassertThrows(function() { Object.setPrototypeOf(proxy, {a:4}) }, Error); 46014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 47014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar seen_prototype; 48014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar seen_target; 49014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochhandler.setPrototypeOf = function(target, proto) { 50014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch seen_target = target; 51014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch seen_prototype = proto; 52014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return true; 53014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 54014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochassertSame(Object.setPrototypeOf(proxy, {a:5}), proxy); 55014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochassertSame(target, seen_target); 56014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochassertEquals({a:5}, seen_prototype); 57014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 58014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch(function setPrototypeProxyTarget() { 59014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var target = { target: 1 }; 60014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch target.__proto__ = {}; 61014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var handler = {}; 62014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var handler2 = {}; 63014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var target2 = new Proxy(target, handler2); 64014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var proxy2 = new Proxy(target2, handler); 65014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch assertSame(Object.getPrototypeOf(proxy2), target.__proto__ ); 66014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 67014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var prototype = [2,3]; 68014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch assertSame(proxy2, Object.setPrototypeOf(proxy2, prototype)); 69014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch assertSame(prototype, Object.getPrototypeOf(proxy2)); 70014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch assertSame(prototype, Object.getPrototypeOf(target)); 71014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch})(); 72014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 73014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch(function testProxyTrapInconsistent() { 74014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var target = { target: 1 }; 75014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch target.__proto__ = {}; 76014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var handler = {}; 77014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var handler2 = { 78014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch }; 79014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 80014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var target2 = new Proxy(target, handler); 81014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var proxy2 = new Proxy(target2, handler2); 82014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 83014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If the final target is extensible we can set any prototype. 84014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var prototype = [1]; 85014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Reflect.setPrototypeOf(proxy2, prototype); 86014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch assertSame(prototype, Reflect.getPrototypeOf(target)); 87014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 88014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch handler2.setPrototypeOf = function(target, value) { 89014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Reflect.setPrototypeOf(target, value); 90014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return true; 91014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch }; 92014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch prototype = [2]; 93014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Reflect.setPrototypeOf(proxy2, prototype); 94014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch assertSame(prototype, Reflect.getPrototypeOf(target)); 95014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 96014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Prevent getting the target's prototype used to check the invariant. 97014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch var gotPrototype = false; 98014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch handler.getPrototypeOf = function() { 99014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch gotPrototype = true; 100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch throw TypeError() 101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch }; 102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If the target is extensible we do not check the invariant. 103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch prototype = [3]; 104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Reflect.setPrototypeOf(proxy2, prototype); 105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch assertFalse(gotPrototype); 106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch assertSame(prototype, Reflect.getPrototypeOf(target)); 107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Changing the prototype of a non-extensible target will trigger the 109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // invariant-check and throw in the above handler. 110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Reflect.preventExtensions(target); 111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch assertThrows(() => {Reflect.setPrototypeOf(proxy2, [4])}, TypeError); 112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch assertTrue(gotPrototype); 113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch assertEquals([3], Reflect.getPrototypeOf(target)); 114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Setting the prototype of a non-extensible target is fine if the prototype 116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // doesn't change. 117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch delete handler.getPrototypeOf; 118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Reflect.setPrototypeOf(proxy2, prototype); 119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Changing the prototype will throw. 120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch prototype = [5]; 121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch assertThrows(() => {Reflect.setPrototypeOf(proxy2, prototype)}, TypeError); 122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch})(); 123