blob: 101988a052520287df361de21d8bb642866796fd [file] [log] [blame]
Ben Murdoch097c5b22016-05-18 11:27:45 +01001// 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
Ben Murdochda12d292016-06-02 14:46:10 +01005// Flags: --harmony-object-values-entries
Ben Murdoch097c5b22016-05-18 11:27:45 +01006// 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();
Ben Murdochda12d292016-06-02 14:46:10 +0100250
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})();