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