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 6014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 7014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Check basic call to trap. 8014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 9014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar g_target, g_name, g_desc; 10014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar handler = { 11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch defineProperty: function(target, name, desc) { 12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch g_target = target; 13014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch g_name = name; 14014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch g_desc = desc; 15014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return true; 16014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 17014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 18014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar target = {} 19014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar proxy = new Proxy(target, handler); 20014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar desc = { value: 1, writable: true, configurable: true, enumerable: true }; 21014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochObject.defineProperty(proxy, "foo", desc); 22014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochassertSame(target, g_target); 23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochassertEquals("foo", g_name); 24014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochassertEquals(desc, g_desc); 25014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 26014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Check specific steps in the spec 27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 28014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Step 4: revoked handler 29014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar pair = Proxy.revocable(target, handler); 30014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochObject.defineProperty(proxy, "foo2", desc); 31014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochassertSame(target, g_target); 32014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochassertEquals("foo2", g_name); 33014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochassertEquals(desc, g_desc); 34014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochpair.revoke(); 35014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochassertThrows('Object.defineProperty(pair.proxy, "bar", desc);', TypeError); 36014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 37014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Step 6: Trap isn't callable. 38014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochhandler.defineProperty = 1; 39014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochassertThrows("Object.defineProperty(proxy, 'foo', {value: 2})", TypeError); 40014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 41014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Step 7: Trap is undefined. 42014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochhandler.defineProperty = undefined; 43014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochObject.defineProperty(proxy, "prop1", desc); 44014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochassertEquals(desc, Object.getOwnPropertyDescriptor(target, "prop1")); 45014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar target2 = {}; 46014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvar proxy2 = new Proxy(target2, {}); 47014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochObject.defineProperty(proxy2, "prop2", desc); 48014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochassertEquals(desc, Object.getOwnPropertyDescriptor(target2, "prop2")); 49014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 50014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Step 9: Property name is passed to the trap as a string. 51014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochhandler.defineProperty = function(t, name, d) { g_name = name; return true; }; 52014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochObject.defineProperty(proxy, 0, desc); 53014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochassertTrue(typeof g_name === "string"); 54014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochassertEquals("0", g_name); 55014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 56014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Step 10: Trap returns false. 57014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochhandler.defineProperty = function(t, n, d) { return false; } 58014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochassertThrows("Object.defineProperty(proxy, 'foo', desc)", TypeError); 59014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 60014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Step 15a: Trap returns true for adding a property to a non-extensible target. 61014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochhandler.defineProperty = function(t, n, d) { return true; } 62014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochObject.preventExtensions(target); 63014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochassertThrows("Object.defineProperty(proxy, 'foo', desc)", TypeError); 64014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 65014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Step 15b: Trap returns true for adding a non-configurable property. 66014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochtarget = {}; 67014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochproxy = new Proxy(target, handler); 68014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochdesc = {value: 1, writable: true, configurable: false, enumerable: true}; 69014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochassertThrows("Object.defineProperty(proxy, 'foo', desc)", TypeError); 70014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// No exception is thrown if a non-configurable property exists on the target. 71014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochObject.defineProperty(target, "nonconf", 72014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch {value: 1, writable: true, configurable: false}); 73014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochObject.defineProperty(proxy, "nonconf", {value: 2, configurable: false}); 74014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 75014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Step 16a: Trap returns true for non-compatible property descriptor. 76014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochObject.defineProperty(target, "foo", 77014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch {value: 1, writable: false, configurable: false}); 78014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochassertThrows("Object.defineProperty(proxy, 'foo', {value: 2})", TypeError); 79014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 80014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Step 16b: Trap returns true for overwriting a configurable property 81014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// with a non-configurable descriptor. 82014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochtarget.bar = "baz"; 83014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochassertThrows("Object.defineProperty(proxy, 'bar', {configurable: false})", 84014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TypeError); 85