OLD | NEW |
| (Empty) |
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 | |
8 function 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 } | |
20 TestMeta(); | |
21 | |
22 | |
23 function 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 } | |
52 TestBasic(); | |
53 | |
54 | |
55 function TestToObject() { | |
56 assertThrows(function() { Object.entries(); }, TypeError); | |
57 assertThrows(function() { Object.entries(null); }, TypeError); | |
58 assertThrows(function() { Object.entries(void 0); }, TypeError); | |
59 } | |
60 TestToObject(); | |
61 | |
62 | |
63 function 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 } | |
102 TestOrder(); | |
103 | |
104 | |
105 function 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 } | |
154 TestOrderWithDuplicates(); | |
155 | |
156 | |
157 function 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 } | |
178 TestPropertyFilter(); | |
179 | |
180 | |
181 function 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 } | |
212 TestWithProxy(); | |
213 | |
214 | |
215 function 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 } | |
249 TestMutateDuringEnumeration(); | |
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 })(); | |
OLD | NEW |