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