• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2016 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-object-values-entries
6// Flags: --allow-natives-syntax
7
8function TestMeta() {
9  assertEquals(1, Object.entries.length);
10  assertEquals(Function.prototype, Object.getPrototypeOf(Object.entries));
11  assertEquals("entries", Object.entries.name);
12
13  var descriptor = Object.getOwnPropertyDescriptor(Object, "entries");
14  assertTrue(descriptor.writable);
15  assertFalse(descriptor.enumerable);
16  assertTrue(descriptor.configurable);
17
18  assertThrows(() => new Object.entries({}), TypeError);
19}
20TestMeta();
21
22
23function TestBasic() {
24  var x = 16;
25  var O = {
26    d: 1,
27    c: 3,
28    [Symbol.iterator]: void 0,
29    0: 123,
30    1000: 456,
31    [x * x]: "ducks",
32    [`0x${(x * x).toString(16)}`]: "quack"
33  };
34  O.a = 2;
35  O.b = 4;
36  Object.defineProperty(O, "HIDDEN", { enumerable: false, value: NaN });
37  assertEquals([
38    ["0", 123],
39    ["256", "ducks"],
40    ["1000", 456],
41    ["d", 1],
42    ["c", 3],
43    ["0x100", "quack"],
44    ["a", 2],
45    ["b", 4]
46  ], Object.entries(O));
47  assertEquals(Object.entries(O), Object.keys(O).map(key => [key, O[key]]));
48
49  assertTrue(Array.isArray(Object.entries({})));
50  assertEquals(0, Object.entries({}).length);
51}
52TestBasic();
53
54
55function TestToObject() {
56  assertThrows(function() { Object.entries(); }, TypeError);
57  assertThrows(function() { Object.entries(null); }, TypeError);
58  assertThrows(function() { Object.entries(void 0); }, TypeError);
59}
60TestToObject();
61
62
63function TestOrder() {
64  var O = {
65    a: 1,
66    [Symbol.iterator]: null
67  };
68  O[456] = 123;
69  Object.defineProperty(O, "HIDDEN", { enumerable: false, value: NaN });
70  var priv = %CreatePrivateSymbol("Secret");
71  O[priv] = 56;
72
73  var log = [];
74  var P = new Proxy(O, {
75    ownKeys(target) {
76      log.push("[[OwnPropertyKeys]]");
77      return Reflect.ownKeys(target);
78    },
79    get(target, name) {
80      log.push(`[[Get]](${JSON.stringify(name)})`);
81      return Reflect.get(target, name);
82    },
83    getOwnPropertyDescriptor(target, name) {
84      log.push(`[[GetOwnProperty]](${JSON.stringify(name)})`);
85      return Reflect.getOwnPropertyDescriptor(target, name);
86    },
87    set(target, name, value) {
88      assertUnreachable();
89    }
90  });
91
92  assertEquals([["456", 123], ["a", 1]], Object.entries(P));
93  assertEquals([
94    "[[OwnPropertyKeys]]",
95    "[[GetOwnProperty]](\"456\")",
96    "[[Get]](\"456\")",
97    "[[GetOwnProperty]](\"a\")",
98    "[[Get]](\"a\")",
99    "[[GetOwnProperty]](\"HIDDEN\")"
100  ], log);
101}
102TestOrder();
103
104
105function TestOrderWithDuplicates() {
106  var O = {
107    a: 1,
108    [Symbol.iterator]: null
109  };
110  O[456] = 123;
111  Object.defineProperty(O, "HIDDEN", { enumerable: false, value: NaN });
112  var priv = %CreatePrivateSymbol("Secret");
113  O[priv] = 56;
114
115  var log = [];
116  var P = new Proxy(O, {
117    ownKeys(target) {
118      log.push("[[OwnPropertyKeys]]");
119      return ["a", Symbol.iterator, "a", "456", "HIDDEN", "HIDDEN", "456"];
120    },
121    get(target, name) {
122      log.push(`[[Get]](${JSON.stringify(name)})`);
123      return Reflect.get(target, name);
124    },
125    getOwnPropertyDescriptor(target, name) {
126      log.push(`[[GetOwnProperty]](${JSON.stringify(name)})`);
127      return Reflect.getOwnPropertyDescriptor(target, name);
128    },
129    set(target, name, value) {
130      assertUnreachable();
131    }
132  });
133
134  assertEquals([
135    ["a", 1],
136    ["a", 1],
137    ["456", 123],
138    ["456", 123]
139  ], Object.entries(P));
140  assertEquals([
141    "[[OwnPropertyKeys]]",
142    "[[GetOwnProperty]](\"a\")",
143    "[[Get]](\"a\")",
144    "[[GetOwnProperty]](\"a\")",
145    "[[Get]](\"a\")",
146    "[[GetOwnProperty]](\"456\")",
147    "[[Get]](\"456\")",
148    "[[GetOwnProperty]](\"HIDDEN\")",
149    "[[GetOwnProperty]](\"HIDDEN\")",
150    "[[GetOwnProperty]](\"456\")",
151    "[[Get]](\"456\")"
152  ], log);
153}
154TestOrderWithDuplicates();
155
156
157function TestPropertyFilter() {
158  var object = { prop3: 30 };
159  object[2] = 40;
160  object["prop4"] = 50;
161  Object.defineProperty(object, "prop5", { value: 60, enumerable: true });
162  Object.defineProperty(object, "prop6", { value: 70, enumerable: false });
163  Object.defineProperty(object, "prop7", {
164      enumerable: true, get() { return 80; }});
165  var sym = Symbol("prop8");
166  object[sym] = 90;
167
168  values = Object.entries(object);
169  assertEquals(5, values.length);
170  assertEquals([
171    [ "2", 40 ],
172    [ "prop3", 30 ],
173    [ "prop4", 50 ],
174    [ "prop5", 60 ],
175    [ "prop7", 80 ]
176  ], values);
177}
178TestPropertyFilter();
179
180
181function TestWithProxy() {
182  var obj1 = {prop1:10};
183  var proxy1 = new Proxy(obj1, { });
184  assertEquals([ [ "prop1", 10 ] ], Object.entries(proxy1));
185
186  var obj2 = {};
187  Object.defineProperty(obj2, "prop2", { value: 20, enumerable: true });
188  Object.defineProperty(obj2, "prop3", {
189      get() { return 30; }, enumerable: true });
190  var proxy2 = new Proxy(obj2, {
191    getOwnPropertyDescriptor(target, name) {
192      return Reflect.getOwnPropertyDescriptor(target, name);
193    }
194  });
195  assertEquals([ [ "prop2", 20 ], [ "prop3", 30 ] ], Object.entries(proxy2));
196
197  var obj3 = {};
198  var count = 0;
199  var proxy3 = new Proxy(obj3, {
200    get(target, property, receiver) {
201      return count++ * 5;
202    },
203    getOwnPropertyDescriptor(target, property) {
204      return { configurable: true, enumerable: true };
205    },
206    ownKeys(target) {
207      return [ "prop0", "prop1", Symbol("prop2"), Symbol("prop5") ];
208    }
209  });
210  assertEquals([ [ "prop0", 0 ], [ "prop1", 5 ] ], Object.entries(proxy3));
211}
212TestWithProxy();
213
214
215function TestMutateDuringEnumeration() {
216  var aDeletesB = {
217    get a() {
218      delete this.b;
219      return 1;
220    },
221    b: 2
222  };
223  assertEquals([ [ "a", 1 ] ], Object.entries(aDeletesB));
224
225  var aRemovesB = {
226    get a() {
227      Object.defineProperty(this, "b", { enumerable: false });
228      return 1;
229    },
230    b: 2
231  };
232  assertEquals([ [ "a", 1 ] ], Object.entries(aRemovesB));
233
234  var aAddsB = { get a() { this.b = 2; return 1; } };
235  assertEquals([ [ "a", 1 ] ], Object.entries(aAddsB));
236
237  var aMakesBEnumerable = {};
238  Object.defineProperty(aMakesBEnumerable, "a", {
239    get() {
240      Object.defineProperty(this, "b", { enumerable: true });
241      return 1;
242    },
243    enumerable: true
244  });
245  Object.defineProperty(aMakesBEnumerable, "b", {
246      value: 2, configurable:true, enumerable: false });
247  assertEquals([ [ "a", 1 ], [ "b", 2 ] ], Object.entries(aMakesBEnumerable));
248}
249TestMutateDuringEnumeration();
250
251
252(function TestElementKinds() {
253  var O1 = { name: "1" }, O2 = { name: "2" }, O3 = { name: "3" };
254  var PI = 3.141592653589793;
255  var E = 2.718281828459045;
256  function fastSloppyArguments(a, b, c) {
257    delete arguments[0];
258    arguments[0] = a;
259    return arguments;
260  }
261
262  function slowSloppyArguments(a, b, c) {
263    delete arguments[0];
264    arguments[0] = a;
265    Object.defineProperties(arguments, {
266      0: {
267        enumerable: true,
268        value: a
269      },
270      9999: {
271        enumerable: false,
272        value: "Y"
273      }
274    });
275    arguments[10000] = "X";
276    return arguments;
277  }
278
279  var element_kinds = {
280    FAST_SMI_ELEMENTS: [ [1, 2, 3], [ ["0", 1], ["1", 2], ["2", 3] ] ],
281    FAST_HOLEY_SMI_ELEMENTS: [ [, , 3], [ ["2", 3] ] ],
282    FAST_ELEMENTS: [ [O1, O2, O3], [ ["0", O1], ["1", O2], ["2", O3] ] ],
283    FAST_HOLEY_ELEMENTS: [ [, , O3], [ ["2", O3] ] ],
284    FAST_DOUBLE_ELEMENTS: [ [E, NaN, PI], [ ["0", E], ["1", NaN], ["2", PI] ] ],
285    FAST_HOLEY_DOUBLE_ELEMENTS: [ [, , NaN], [ ["2", NaN] ] ],
286
287    DICTIONARY_ELEMENTS: [ Object.defineProperties({ 10000: "world" }, {
288        100: { enumerable: true, value: "hello" },
289        99: { enumerable: false, value: "nope" }
290      }), [ ["100", "hello"], ["10000", "world" ] ] ],
291    FAST_SLOPPY_ARGUMENTS_ELEMENTS: [
292        fastSloppyArguments("a", "b", "c"),
293        [ ["0", "a"], ["1", "b"], ["2", "c"] ] ],
294    SLOW_SLOPPY_ARGUMENTS_ELEMENTS: [
295        slowSloppyArguments("a", "b", "c"),
296        [ ["0", "a"], ["1", "b"], ["2", "c"], ["10000", "X"] ] ],
297
298    FAST_STRING_WRAPPER_ELEMENTS: [ new String("str"),
299        [ ["0", "s"], ["1", "t"], ["2", "r"]] ],
300    SLOW_STRING_WRAPPER_ELEMENTS: [
301        Object.defineProperties(new String("str"), {
302          10000: { enumerable: false, value: "X" },
303          9999: { enumerable: true, value: "Y" }
304        }), [["0", "s"], ["1", "t"], ["2", "r"], ["9999", "Y"]] ],
305  };
306
307  for (let [kind, [object, expected]] of Object.entries(element_kinds)) {
308    let result1 = Object.entries(object);
309    assertEquals(expected, result1, `fast Object.entries() with ${kind}`);
310
311    let proxy = new Proxy(object, {});
312    let result2 = Object.entries(proxy);
313    assertEquals(result1, result2, `slow Object.entries() with ${kind}`);
314  }
315})();
316