Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 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 |
| 6 | |
| 7 | // Check basic call to trap. |
| 8 | |
| 9 | var g_target, g_name, g_desc; |
| 10 | var handler = { |
| 11 | defineProperty: function(target, name, desc) { |
| 12 | g_target = target; |
| 13 | g_name = name; |
| 14 | g_desc = desc; |
| 15 | return true; |
| 16 | } |
| 17 | } |
| 18 | var target = {} |
| 19 | var proxy = new Proxy(target, handler); |
| 20 | var desc = { value: 1, writable: true, configurable: true, enumerable: true }; |
| 21 | Object.defineProperty(proxy, "foo", desc); |
| 22 | assertSame(target, g_target); |
| 23 | assertEquals("foo", g_name); |
| 24 | assertEquals(desc, g_desc); |
| 25 | |
| 26 | // Check specific steps in the spec |
| 27 | |
| 28 | // Step 4: revoked handler |
| 29 | var pair = Proxy.revocable(target, handler); |
| 30 | Object.defineProperty(proxy, "foo2", desc); |
| 31 | assertSame(target, g_target); |
| 32 | assertEquals("foo2", g_name); |
| 33 | assertEquals(desc, g_desc); |
| 34 | pair.revoke(); |
| 35 | assertThrows('Object.defineProperty(pair.proxy, "bar", desc);', TypeError); |
| 36 | |
| 37 | // Step 6: Trap isn't callable. |
| 38 | handler.defineProperty = 1; |
| 39 | assertThrows("Object.defineProperty(proxy, 'foo', {value: 2})", TypeError); |
| 40 | |
| 41 | // Step 7: Trap is undefined. |
| 42 | handler.defineProperty = undefined; |
| 43 | Object.defineProperty(proxy, "prop1", desc); |
| 44 | assertEquals(desc, Object.getOwnPropertyDescriptor(target, "prop1")); |
| 45 | var target2 = {}; |
| 46 | var proxy2 = new Proxy(target2, {}); |
| 47 | Object.defineProperty(proxy2, "prop2", desc); |
| 48 | assertEquals(desc, Object.getOwnPropertyDescriptor(target2, "prop2")); |
| 49 | |
| 50 | // Step 9: Property name is passed to the trap as a string. |
| 51 | handler.defineProperty = function(t, name, d) { g_name = name; return true; }; |
| 52 | Object.defineProperty(proxy, 0, desc); |
| 53 | assertTrue(typeof g_name === "string"); |
| 54 | assertEquals("0", g_name); |
| 55 | |
| 56 | // Step 10: Trap returns false. |
| 57 | handler.defineProperty = function(t, n, d) { return false; } |
| 58 | assertThrows("Object.defineProperty(proxy, 'foo', desc)", TypeError); |
| 59 | |
| 60 | // Step 15a: Trap returns true for adding a property to a non-extensible target. |
| 61 | handler.defineProperty = function(t, n, d) { return true; } |
| 62 | Object.preventExtensions(target); |
| 63 | assertThrows("Object.defineProperty(proxy, 'foo', desc)", TypeError); |
| 64 | |
| 65 | // Step 15b: Trap returns true for adding a non-configurable property. |
| 66 | target = {}; |
| 67 | proxy = new Proxy(target, handler); |
| 68 | desc = {value: 1, writable: true, configurable: false, enumerable: true}; |
| 69 | assertThrows("Object.defineProperty(proxy, 'foo', desc)", TypeError); |
| 70 | // No exception is thrown if a non-configurable property exists on the target. |
| 71 | Object.defineProperty(target, "nonconf", |
| 72 | {value: 1, writable: true, configurable: false}); |
| 73 | Object.defineProperty(proxy, "nonconf", {value: 2, configurable: false}); |
| 74 | |
| 75 | // Step 16a: Trap returns true for non-compatible property descriptor. |
| 76 | Object.defineProperty(target, "foo", |
| 77 | {value: 1, writable: false, configurable: false}); |
| 78 | assertThrows("Object.defineProperty(proxy, 'foo', {value: 2})", TypeError); |
| 79 | |
| 80 | // Step 16b: Trap returns true for overwriting a configurable property |
| 81 | // with a non-configurable descriptor. |
| 82 | target.bar = "baz"; |
| 83 | assertThrows("Object.defineProperty(proxy, 'bar', {configurable: false})", |
| 84 | TypeError); |