Object.js (11376B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 // ES stage 4 proposal 6 function ObjectGetOwnPropertyDescriptors(O) { 7 // Step 1. 8 var obj = ToObject(O); 9 10 // Step 2. 11 var keys = std_Reflect_ownKeys(obj); 12 13 // Step 3. 14 var descriptors = {}; 15 16 // Step 4. 17 for (var index = 0, len = keys.length; index < len; index++) { 18 var key = keys[index]; 19 20 // Steps 4.a-b. 21 var desc = ObjectGetOwnPropertyDescriptor(obj, key); 22 23 // Step 4.c. 24 if (typeof desc !== "undefined") { 25 DefineDataProperty(descriptors, key, desc); 26 } 27 } 28 29 // Step 5. 30 return descriptors; 31 } 32 33 /* ES6 draft rev 32 (2015 Feb 2) 19.1.2.9. */ 34 function ObjectGetPrototypeOf(obj) { 35 return std_Reflect_getPrototypeOf(ToObject(obj)); 36 } 37 38 /* ES6 draft rev 32 (2015 Feb 2) 19.1.2.11. */ 39 function ObjectIsExtensible(obj) { 40 return IsObject(obj) && std_Reflect_isExtensible(obj); 41 } 42 43 /* ES2015 19.1.3.5 Object.prototype.toLocaleString */ 44 function Object_toLocaleString() { 45 // Step 1. 46 var O = this; 47 48 // Step 2. 49 return callContentFunction(O.toString, O); 50 } 51 52 // ES 2017 draft bb96899bb0d9ef9be08164a26efae2ee5f25e875 19.1.3.7 53 function Object_valueOf() { 54 // Step 1. 55 return ToObject(this); 56 } 57 58 // ES 2018 draft 19.1.3.2 59 function Object_hasOwnProperty(V) { 60 // Implement hasOwnProperty as a pseudo function that becomes a JSOp 61 // to easier add an inline cache for this. 62 return hasOwn(V, this); 63 } 64 65 // ES 2021 draft rev 0b988b7700de675331ac360d164c978d6ea452ec 66 // B.2.2.1.1 get Object.prototype.__proto__ 67 function $ObjectProtoGetter() { 68 return std_Reflect_getPrototypeOf(ToObject(this)); 69 } 70 SetCanonicalName($ObjectProtoGetter, "get __proto__"); 71 72 // ES 2021 draft rev 0b988b7700de675331ac360d164c978d6ea452ec 73 // B.2.2.1.2 set Object.prototype.__proto__ 74 function $ObjectProtoSetter(proto) { 75 return callFunction(std_Object_setProto, this, proto); 76 } 77 SetCanonicalName($ObjectProtoSetter, "set __proto__"); 78 79 // ES7 draft (2016 March 8) B.2.2.3 80 function ObjectDefineSetter(name, setter) { 81 // Step 1. 82 var object = ToObject(this); 83 84 // Step 2. 85 if (!IsCallable(setter)) { 86 ThrowTypeError(JSMSG_BAD_GETTER_OR_SETTER, "setter"); 87 } 88 89 // Step 4. 90 var key = TO_PROPERTY_KEY(name); 91 92 // Steps 3, 5. 93 DefineProperty( 94 object, 95 key, 96 ACCESSOR_DESCRIPTOR_KIND | ATTR_ENUMERABLE | ATTR_CONFIGURABLE, 97 null, 98 setter, 99 true 100 ); 101 102 // Step 6. (implicit) 103 } 104 105 // ES7 draft (2016 March 8) B.2.2.2 106 function ObjectDefineGetter(name, getter) { 107 // Step 1. 108 var object = ToObject(this); 109 110 // Step 2. 111 if (!IsCallable(getter)) { 112 ThrowTypeError(JSMSG_BAD_GETTER_OR_SETTER, "getter"); 113 } 114 115 // Step 4. 116 var key = TO_PROPERTY_KEY(name); 117 118 // Steps 3, 5. 119 DefineProperty( 120 object, 121 key, 122 ACCESSOR_DESCRIPTOR_KIND | ATTR_ENUMERABLE | ATTR_CONFIGURABLE, 123 getter, 124 null, 125 true 126 ); 127 128 // Step 6. (implicit) 129 } 130 131 // ES7 draft (2016 March 8) B.2.2.5 132 function ObjectLookupSetter(name) { 133 // Step 1. 134 var object = ToObject(this); 135 136 // Step 2. 137 var key = TO_PROPERTY_KEY(name); 138 139 do { 140 // Step 3.a. 141 var desc = GetOwnPropertyDescriptorToArray(object, key); 142 143 // Step 3.b. 144 if (desc) { 145 // Step.b.i. 146 if (desc[PROP_DESC_ATTRS_AND_KIND_INDEX] & ACCESSOR_DESCRIPTOR_KIND) { 147 return desc[PROP_DESC_SETTER_INDEX]; 148 } 149 150 // Step.b.i. 151 return undefined; 152 } 153 154 // Step 3.c. 155 object = std_Reflect_getPrototypeOf(object); 156 } while (object !== null); 157 158 // Step 3.d. (implicit) 159 } 160 161 // ES7 draft (2016 March 8) B.2.2.4 162 function ObjectLookupGetter(name) { 163 // Step 1. 164 var object = ToObject(this); 165 166 // Step 2. 167 var key = TO_PROPERTY_KEY(name); 168 169 do { 170 // Step 3.a. 171 var desc = GetOwnPropertyDescriptorToArray(object, key); 172 173 // Step 3.b. 174 if (desc) { 175 // Step.b.i. 176 if (desc[PROP_DESC_ATTRS_AND_KIND_INDEX] & ACCESSOR_DESCRIPTOR_KIND) { 177 return desc[PROP_DESC_GETTER_INDEX]; 178 } 179 180 // Step.b.ii. 181 return undefined; 182 } 183 184 // Step 3.c. 185 object = std_Reflect_getPrototypeOf(object); 186 } while (object !== null); 187 188 // Step 3.d. (implicit) 189 } 190 191 // ES2017 draft rev 6859bb9ccaea9c6ede81d71e5320e3833b92cb3e 192 // 19.1.2.6 Object.getOwnPropertyDescriptor ( O, P ) 193 function ObjectGetOwnPropertyDescriptor(obj, propertyKey) { 194 // Steps 1-3. 195 var desc = GetOwnPropertyDescriptorToArray(obj, propertyKey); 196 197 // Step 4 (Call to 6.2.4.4 FromPropertyDescriptor). 198 199 // 6.2.4.4 FromPropertyDescriptor, step 1. 200 if (!desc) { 201 return undefined; 202 } 203 204 // 6.2.4.4 FromPropertyDescriptor, steps 2-5, 8-11. 205 var attrsAndKind = desc[PROP_DESC_ATTRS_AND_KIND_INDEX]; 206 if (attrsAndKind & DATA_DESCRIPTOR_KIND) { 207 return { 208 value: desc[PROP_DESC_VALUE_INDEX], 209 writable: !!(attrsAndKind & ATTR_WRITABLE), 210 enumerable: !!(attrsAndKind & ATTR_ENUMERABLE), 211 configurable: !!(attrsAndKind & ATTR_CONFIGURABLE), 212 }; 213 } 214 215 // 6.2.4.4 FromPropertyDescriptor, steps 2-3, 6-11. 216 assert( 217 attrsAndKind & ACCESSOR_DESCRIPTOR_KIND, 218 "expected accessor property descriptor" 219 ); 220 return { 221 get: desc[PROP_DESC_GETTER_INDEX], 222 set: desc[PROP_DESC_SETTER_INDEX], 223 enumerable: !!(attrsAndKind & ATTR_ENUMERABLE), 224 configurable: !!(attrsAndKind & ATTR_CONFIGURABLE), 225 }; 226 } 227 228 // ES2017 draft rev 6859bb9ccaea9c6ede81d71e5320e3833b92cb3e 229 // 19.1.2.4 Object.defineProperty ( O, P, Attributes ) 230 // 26.1.3 Reflect.defineProperty ( target, propertyKey, attributes ) 231 function ObjectOrReflectDefineProperty(obj, propertyKey, attributes, strict) { 232 // Step 1. 233 if (!IsObject(obj)) { 234 ThrowTypeError(JSMSG_OBJECT_REQUIRED, DecompileArg(0, obj)); 235 } 236 237 // Step 2. 238 propertyKey = TO_PROPERTY_KEY(propertyKey); 239 240 // Step 3 (Call to 6.2.4.5 ToPropertyDescriptor). 241 242 // 6.2.4.5 ToPropertyDescriptor, step 1. 243 if (!IsObject(attributes)) { 244 ThrowTypeError( 245 JSMSG_OBJECT_REQUIRED_PROP_DESC, 246 DecompileArg(2, attributes) 247 ); 248 } 249 250 // 6.2.4.5 ToPropertyDescriptor, step 2. 251 var attrs = 0; 252 var hasValue = false; 253 var value; 254 var getter = null; 255 var setter = null; 256 257 // 6.2.4.5 ToPropertyDescriptor, steps 3-4. 258 if ("enumerable" in attributes) { 259 attrs |= attributes.enumerable ? ATTR_ENUMERABLE : ATTR_NONENUMERABLE; 260 } 261 262 // 6.2.4.5 ToPropertyDescriptor, steps 5-6. 263 if ("configurable" in attributes) { 264 attrs |= attributes.configurable ? ATTR_CONFIGURABLE : ATTR_NONCONFIGURABLE; 265 } 266 267 // 6.2.4.5 ToPropertyDescriptor, steps 7-8. 268 if ("value" in attributes) { 269 attrs |= DATA_DESCRIPTOR_KIND; 270 value = attributes.value; 271 hasValue = true; 272 } 273 274 // 6.2.4.5 ToPropertyDescriptor, steps 9-10. 275 if ("writable" in attributes) { 276 attrs |= DATA_DESCRIPTOR_KIND; 277 attrs |= attributes.writable ? ATTR_WRITABLE : ATTR_NONWRITABLE; 278 } 279 280 // 6.2.4.5 ToPropertyDescriptor, steps 11-12. 281 if ("get" in attributes) { 282 attrs |= ACCESSOR_DESCRIPTOR_KIND; 283 getter = attributes.get; 284 if (!IsCallable(getter) && getter !== undefined) { 285 ThrowTypeError(JSMSG_BAD_GET_SET_FIELD, "get"); 286 } 287 } 288 289 // 6.2.4.5 ToPropertyDescriptor, steps 13-14. 290 if ("set" in attributes) { 291 attrs |= ACCESSOR_DESCRIPTOR_KIND; 292 setter = attributes.set; 293 if (!IsCallable(setter) && setter !== undefined) { 294 ThrowTypeError(JSMSG_BAD_GET_SET_FIELD, "set"); 295 } 296 } 297 298 if (attrs & ACCESSOR_DESCRIPTOR_KIND) { 299 // 6.2.4.5 ToPropertyDescriptor, step 15. 300 if (attrs & DATA_DESCRIPTOR_KIND) { 301 ThrowTypeError(JSMSG_INVALID_DESCRIPTOR); 302 } 303 304 // Step 4 (accessor descriptor property). 305 return DefineProperty(obj, propertyKey, attrs, getter, setter, strict); 306 } 307 308 // Step 4 (data property descriptor with value). 309 if (hasValue) { 310 // Use the inlinable DefineDataProperty function when possible. 311 if (strict) { 312 if ( 313 (attrs & (ATTR_ENUMERABLE | ATTR_CONFIGURABLE | ATTR_WRITABLE)) === 314 (ATTR_ENUMERABLE | ATTR_CONFIGURABLE | ATTR_WRITABLE) 315 ) { 316 DefineDataProperty(obj, propertyKey, value); 317 return true; 318 } 319 } 320 321 // The fifth argument is set to |null| to mark that |value| is present. 322 return DefineProperty(obj, propertyKey, attrs, value, null, strict); 323 } 324 325 // Step 4 (generic property descriptor or data property without value). 326 return DefineProperty(obj, propertyKey, attrs, undefined, undefined, strict); 327 } 328 329 // ES2017 draft rev 6859bb9ccaea9c6ede81d71e5320e3833b92cb3e 330 // 19.1.2.4 Object.defineProperty ( O, P, Attributes ) 331 function ObjectDefineProperty(obj, propertyKey, attributes) { 332 // Steps 1-4. 333 if (!ObjectOrReflectDefineProperty(obj, propertyKey, attributes, true)) { 334 // Not standardized yet: https://github.com/tc39/ecma262/pull/688 335 return null; 336 } 337 338 // Step 5. 339 return obj; 340 } 341 342 // Proposal https://tc39.github.io/proposal-object-from-entries/ 343 // 1. Object.fromEntries ( iterable ) 344 function ObjectFromEntries(iter) { 345 // We omit the usual step number comments here because they don't help. 346 // This implementation inlines AddEntriesFromIterator and 347 // CreateDataPropertyOnObject, so it looks more like the polyfill 348 // <https://github.com/tc39/proposal-object-from-entries/blob/master/polyfill.js> 349 // than the spec algorithm. 350 var obj = {}; 351 352 for (var pair of allowContentIter(iter)) { 353 if (!IsObject(pair)) { 354 ThrowTypeError(JSMSG_INVALID_MAP_ITERABLE, "Object.fromEntries"); 355 } 356 DefineDataProperty(obj, pair[0], pair[1]); 357 } 358 359 return obj; 360 } 361 362 // Proposal https://github.com/tc39/proposal-accessible-object-hasownproperty 363 // 1. Object.hasOwn ( O, P ) 364 function ObjectHasOwn(O, P) { 365 // Step 1. 366 var obj = ToObject(O); 367 // Step 2-3. 368 return hasOwn(P, obj); 369 } 370 371 // Array Grouping proposal 372 // 373 // Object.groupBy ( items, callbackfn ) 374 // 375 // https://tc39.es/proposal-array-grouping/#sec-object.groupby 376 function ObjectGroupBy(items, callbackfn) { 377 // Step 1. (Call to GroupBy is inlined.) 378 379 // GroupBy, step 1. 380 if (IsNullOrUndefined(items)) { 381 ThrowTypeError( 382 JSMSG_UNEXPECTED_TYPE, 383 DecompileArg(0, items), 384 items === null ? "null" : "undefined" 385 ); 386 } 387 388 // GroupBy, step 2. 389 if (!IsCallable(callbackfn)) { 390 ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(1, callbackfn)); 391 } 392 393 // Step 2. 394 var obj = std_Object_create(null); 395 396 // GroupBy, step 3. (Not applicable in our implementation.) 397 398 // GroupBy, step 4. 399 var k = 0; 400 401 // GroupBy, steps 4 and 6. 402 for (var value of allowContentIter(items)) { 403 // GroupBy, step 6.a. (Not applicable) 404 assert(k < 2 ** 53 - 1, "out-of-memory happens before k exceeds 2^53 - 1"); 405 406 // GroupBy, steps 6.b-d. (Implicit through for-of loop.) 407 408 // GroupBy, step 6.e. 409 var key = callContentFunction(callbackfn, undefined, value, k); 410 411 // GroupBy, step 6.f. (Implicit through for-of loop.) 412 413 // GroupBy, step 6.g.i. 414 key = TO_PROPERTY_KEY(key); 415 416 // GroupBy, step 6.g.ii. (Implicit through for-of loop.) 417 418 // GroupBy, step 6.h. (Not applicable) 419 420 // GroupBy, step 6.i. (Inlined call to AddValueToKeyedGroup.) 421 var elements = obj[key]; 422 if (elements === undefined) { 423 DefineDataProperty(obj, key, [value]); 424 } else { 425 DefineDataProperty(elements, elements.length, value); 426 } 427 428 // GroupBy, step 6.j. 429 k += 1; 430 } 431 432 // Step 3. (Result object already populated in the previous loop.) 433 434 // Step 4. 435 return obj; 436 }