Source code

Revision control

Copy as Markdown

Other Tools

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// ES stage 4 proposal
function ObjectGetOwnPropertyDescriptors(O) {
// Step 1.
var obj = ToObject(O);
// Step 2.
var keys = std_Reflect_ownKeys(obj);
// Step 3.
var descriptors = {};
// Step 4.
for (var index = 0, len = keys.length; index < len; index++) {
var key = keys[index];
// Steps 4.a-b.
var desc = ObjectGetOwnPropertyDescriptor(obj, key);
// Step 4.c.
if (typeof desc !== "undefined") {
DefineDataProperty(descriptors, key, desc);
}
}
// Step 5.
return descriptors;
}
/* ES6 draft rev 32 (2015 Feb 2) 19.1.2.9. */
function ObjectGetPrototypeOf(obj) {
return std_Reflect_getPrototypeOf(ToObject(obj));
}
/* ES6 draft rev 32 (2015 Feb 2) 19.1.2.11. */
function ObjectIsExtensible(obj) {
return IsObject(obj) && std_Reflect_isExtensible(obj);
}
/* ES2015 19.1.3.5 Object.prototype.toLocaleString */
function Object_toLocaleString() {
// Step 1.
var O = this;
// Step 2.
return callContentFunction(O.toString, O);
}
// ES 2017 draft bb96899bb0d9ef9be08164a26efae2ee5f25e875 19.1.3.7
function Object_valueOf() {
// Step 1.
return ToObject(this);
}
// ES 2018 draft 19.1.3.2
function Object_hasOwnProperty(V) {
// Implement hasOwnProperty as a pseudo function that becomes a JSOp
// to easier add an inline cache for this.
return hasOwn(V, this);
}
// ES 2021 draft rev 0b988b7700de675331ac360d164c978d6ea452ec
// B.2.2.1.1 get Object.prototype.__proto__
function $ObjectProtoGetter() {
return std_Reflect_getPrototypeOf(ToObject(this));
}
SetCanonicalName($ObjectProtoGetter, "get __proto__");
// ES 2021 draft rev 0b988b7700de675331ac360d164c978d6ea452ec
// B.2.2.1.2 set Object.prototype.__proto__
function $ObjectProtoSetter(proto) {
return callFunction(std_Object_setProto, this, proto);
}
SetCanonicalName($ObjectProtoSetter, "set __proto__");
// ES7 draft (2016 March 8) B.2.2.3
function ObjectDefineSetter(name, setter) {
// Step 1.
var object = ToObject(this);
// Step 2.
if (!IsCallable(setter)) {
ThrowTypeError(JSMSG_BAD_GETTER_OR_SETTER, "setter");
}
// Step 4.
var key = TO_PROPERTY_KEY(name);
// Steps 3, 5.
DefineProperty(
object,
key,
ACCESSOR_DESCRIPTOR_KIND | ATTR_ENUMERABLE | ATTR_CONFIGURABLE,
null,
setter,
true
);
// Step 6. (implicit)
}
// ES7 draft (2016 March 8) B.2.2.2
function ObjectDefineGetter(name, getter) {
// Step 1.
var object = ToObject(this);
// Step 2.
if (!IsCallable(getter)) {
ThrowTypeError(JSMSG_BAD_GETTER_OR_SETTER, "getter");
}
// Step 4.
var key = TO_PROPERTY_KEY(name);
// Steps 3, 5.
DefineProperty(
object,
key,
ACCESSOR_DESCRIPTOR_KIND | ATTR_ENUMERABLE | ATTR_CONFIGURABLE,
getter,
null,
true
);
// Step 6. (implicit)
}
// ES7 draft (2016 March 8) B.2.2.5
function ObjectLookupSetter(name) {
// Step 1.
var object = ToObject(this);
// Step 2.
var key = TO_PROPERTY_KEY(name);
do {
// Step 3.a.
var desc = GetOwnPropertyDescriptorToArray(object, key);
// Step 3.b.
if (desc) {
// Step.b.i.
if (desc[PROP_DESC_ATTRS_AND_KIND_INDEX] & ACCESSOR_DESCRIPTOR_KIND) {
return desc[PROP_DESC_SETTER_INDEX];
}
// Step.b.i.
return undefined;
}
// Step 3.c.
object = std_Reflect_getPrototypeOf(object);
} while (object !== null);
// Step 3.d. (implicit)
}
// ES7 draft (2016 March 8) B.2.2.4
function ObjectLookupGetter(name) {
// Step 1.
var object = ToObject(this);
// Step 2.
var key = TO_PROPERTY_KEY(name);
do {
// Step 3.a.
var desc = GetOwnPropertyDescriptorToArray(object, key);
// Step 3.b.
if (desc) {
// Step.b.i.
if (desc[PROP_DESC_ATTRS_AND_KIND_INDEX] & ACCESSOR_DESCRIPTOR_KIND) {
return desc[PROP_DESC_GETTER_INDEX];
}
// Step.b.ii.
return undefined;
}
// Step 3.c.
object = std_Reflect_getPrototypeOf(object);
} while (object !== null);
// Step 3.d. (implicit)
}
// ES2017 draft rev 6859bb9ccaea9c6ede81d71e5320e3833b92cb3e
// 19.1.2.6 Object.getOwnPropertyDescriptor ( O, P )
function ObjectGetOwnPropertyDescriptor(obj, propertyKey) {
// Steps 1-3.
var desc = GetOwnPropertyDescriptorToArray(obj, propertyKey);
// Step 4 (Call to 6.2.4.4 FromPropertyDescriptor).
// 6.2.4.4 FromPropertyDescriptor, step 1.
if (!desc) {
return undefined;
}
// 6.2.4.4 FromPropertyDescriptor, steps 2-5, 8-11.
var attrsAndKind = desc[PROP_DESC_ATTRS_AND_KIND_INDEX];
if (attrsAndKind & DATA_DESCRIPTOR_KIND) {
return {
value: desc[PROP_DESC_VALUE_INDEX],
writable: !!(attrsAndKind & ATTR_WRITABLE),
enumerable: !!(attrsAndKind & ATTR_ENUMERABLE),
configurable: !!(attrsAndKind & ATTR_CONFIGURABLE),
};
}
// 6.2.4.4 FromPropertyDescriptor, steps 2-3, 6-11.
assert(
attrsAndKind & ACCESSOR_DESCRIPTOR_KIND,
"expected accessor property descriptor"
);
return {
get: desc[PROP_DESC_GETTER_INDEX],
set: desc[PROP_DESC_SETTER_INDEX],
enumerable: !!(attrsAndKind & ATTR_ENUMERABLE),
configurable: !!(attrsAndKind & ATTR_CONFIGURABLE),
};
}
// ES2017 draft rev 6859bb9ccaea9c6ede81d71e5320e3833b92cb3e
// 19.1.2.4 Object.defineProperty ( O, P, Attributes )
// 26.1.3 Reflect.defineProperty ( target, propertyKey, attributes )
function ObjectOrReflectDefineProperty(obj, propertyKey, attributes, strict) {
// Step 1.
if (!IsObject(obj)) {
ThrowTypeError(JSMSG_OBJECT_REQUIRED, DecompileArg(0, obj));
}
// Step 2.
propertyKey = TO_PROPERTY_KEY(propertyKey);
// Step 3 (Call to 6.2.4.5 ToPropertyDescriptor).
// 6.2.4.5 ToPropertyDescriptor, step 1.
if (!IsObject(attributes)) {
ThrowTypeError(
JSMSG_OBJECT_REQUIRED_PROP_DESC,
DecompileArg(2, attributes)
);
}
// 6.2.4.5 ToPropertyDescriptor, step 2.
var attrs = 0;
var hasValue = false;
var value;
var getter = null;
var setter = null;
// 6.2.4.5 ToPropertyDescriptor, steps 3-4.
if ("enumerable" in attributes) {
attrs |= attributes.enumerable ? ATTR_ENUMERABLE : ATTR_NONENUMERABLE;
}
// 6.2.4.5 ToPropertyDescriptor, steps 5-6.
if ("configurable" in attributes) {
attrs |= attributes.configurable ? ATTR_CONFIGURABLE : ATTR_NONCONFIGURABLE;
}
// 6.2.4.5 ToPropertyDescriptor, steps 7-8.
if ("value" in attributes) {
attrs |= DATA_DESCRIPTOR_KIND;
value = attributes.value;
hasValue = true;
}
// 6.2.4.5 ToPropertyDescriptor, steps 9-10.
if ("writable" in attributes) {
attrs |= DATA_DESCRIPTOR_KIND;
attrs |= attributes.writable ? ATTR_WRITABLE : ATTR_NONWRITABLE;
}
// 6.2.4.5 ToPropertyDescriptor, steps 11-12.
if ("get" in attributes) {
attrs |= ACCESSOR_DESCRIPTOR_KIND;
getter = attributes.get;
if (!IsCallable(getter) && getter !== undefined) {
ThrowTypeError(JSMSG_BAD_GET_SET_FIELD, "get");
}
}
// 6.2.4.5 ToPropertyDescriptor, steps 13-14.
if ("set" in attributes) {
attrs |= ACCESSOR_DESCRIPTOR_KIND;
setter = attributes.set;
if (!IsCallable(setter) && setter !== undefined) {
ThrowTypeError(JSMSG_BAD_GET_SET_FIELD, "set");
}
}
if (attrs & ACCESSOR_DESCRIPTOR_KIND) {
// 6.2.4.5 ToPropertyDescriptor, step 15.
if (attrs & DATA_DESCRIPTOR_KIND) {
ThrowTypeError(JSMSG_INVALID_DESCRIPTOR);
}
// Step 4 (accessor descriptor property).
return DefineProperty(obj, propertyKey, attrs, getter, setter, strict);
}
// Step 4 (data property descriptor with value).
if (hasValue) {
// Use the inlinable DefineDataProperty function when possible.
if (strict) {
if (
(attrs & (ATTR_ENUMERABLE | ATTR_CONFIGURABLE | ATTR_WRITABLE)) ===
(ATTR_ENUMERABLE | ATTR_CONFIGURABLE | ATTR_WRITABLE)
) {
DefineDataProperty(obj, propertyKey, value);
return true;
}
}
// The fifth argument is set to |null| to mark that |value| is present.
return DefineProperty(obj, propertyKey, attrs, value, null, strict);
}
// Step 4 (generic property descriptor or data property without value).
return DefineProperty(obj, propertyKey, attrs, undefined, undefined, strict);
}
// ES2017 draft rev 6859bb9ccaea9c6ede81d71e5320e3833b92cb3e
// 19.1.2.4 Object.defineProperty ( O, P, Attributes )
function ObjectDefineProperty(obj, propertyKey, attributes) {
// Steps 1-4.
if (!ObjectOrReflectDefineProperty(obj, propertyKey, attributes, true)) {
// Not standardized yet: https://github.com/tc39/ecma262/pull/688
return null;
}
// Step 5.
return obj;
}
// 1. Object.fromEntries ( iterable )
function ObjectFromEntries(iter) {
// We omit the usual step number comments here because they don't help.
// This implementation inlines AddEntriesFromIterator and
// CreateDataPropertyOnObject, so it looks more like the polyfill
// than the spec algorithm.
var obj = {};
for (var pair of allowContentIter(iter)) {
if (!IsObject(pair)) {
ThrowTypeError(JSMSG_INVALID_MAP_ITERABLE, "Object.fromEntries");
}
DefineDataProperty(obj, pair[0], pair[1]);
}
return obj;
}
// 1. Object.hasOwn ( O, P )
function ObjectHasOwn(O, P) {
// Step 1.
var obj = ToObject(O);
// Step 2-3.
return hasOwn(P, obj);
}
// Array Grouping proposal
//
// Object.groupBy ( items, callbackfn )
//
function ObjectGroupBy(items, callbackfn) {
// Step 1. (Call to GroupBy is inlined.)
// GroupBy, step 1.
if (IsNullOrUndefined(items)) {
ThrowTypeError(
JSMSG_UNEXPECTED_TYPE,
DecompileArg(0, items),
items === null ? "null" : "undefined"
);
}
// GroupBy, step 2.
if (!IsCallable(callbackfn)) {
ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(1, callbackfn));
}
// Step 2.
var obj = std_Object_create(null);
// GroupBy, step 3. (Not applicable in our implementation.)
// GroupBy, step 4.
var k = 0;
// GroupBy, steps 4 and 6.
for (var value of allowContentIter(items)) {
// GroupBy, step 6.a. (Not applicable)
assert(k < 2 ** 53 - 1, "out-of-memory happens before k exceeds 2^53 - 1");
// GroupBy, steps 6.b-d. (Implicit through for-of loop.)
// GroupBy, step 6.e.
var key = callContentFunction(callbackfn, undefined, value, k);
// GroupBy, step 6.f. (Implicit through for-of loop.)
// GroupBy, step 6.g.i.
key = TO_PROPERTY_KEY(key);
// GroupBy, step 6.g.ii. (Implicit through for-of loop.)
// GroupBy, step 6.h. (Not applicable)
// GroupBy, step 6.i. (Inlined call to AddValueToKeyedGroup.)
var elements = obj[key];
if (elements === undefined) {
DefineDataProperty(obj, key, [value]);
} else {
DefineDataProperty(elements, elements.length, value);
}
// GroupBy, step 6.j.
k += 1;
}
// Step 3. (Result object already populated in the previous loop.)
// Step 4.
return obj;
}