| 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 |