10.1 Ordinary Object Internal Methods and Internal Slots

All ordinary objects have an internal slot called [[Prototype]]. The value of this internal slot is either null or an object and is used for implementing inheritance. Data properties of the [[Prototype]] object are inherited (and visible as properties of the child object) for the purposes of get access, but not for set access. Accessor properties are inherited for both get access and set access.

Every ordinary object has a Boolean-valued [[Extensible]] internal slot which is used to fulfill the extensibility-related internal method invariants specified in 6.1.7.3. Namely, once the value of an object's [[Extensible]] internal slot has been set to false, it is no longer possible to add properties to the object, to modify the value of the object's [[Prototype]] internal slot, or to subsequently change the value of [[Extensible]] to true.

In the following algorithm descriptions, assume O is an ordinary object, P is a property key value, V is any ECMAScript language value, and Desc is a Property Descriptor record.

Each ordinary object internal method delegates to a similarly-named abstract operation. If such an abstract operation depends on another internal method, then the internal method is invoked on O rather than calling the similarly-named abstract operation directly. These semantics ensure that exotic objects have their overridden internal methods invoked when ordinary object internal methods are applied to them.

10.1.1 [[GetPrototypeOf]] ( )

The [[GetPrototypeOf]] internal method of an ordinary object O takes no arguments. It performs the following steps when called:

  1. Return ! OrdinaryGetPrototypeOf(O).

10.1.1.1 OrdinaryGetPrototypeOf ( O )

The abstract operation OrdinaryGetPrototypeOf takes argument O (an Object). It performs the following steps when called:

  1. Return O.[[Prototype]].

10.1.2 [[SetPrototypeOf]] ( V )

The [[SetPrototypeOf]] internal method of an ordinary object O takes argument V (an Object or null). It performs the following steps when called:

  1. Return ! OrdinarySetPrototypeOf(O, V).

10.1.2.1 OrdinarySetPrototypeOf ( O, V )

The abstract operation OrdinarySetPrototypeOf takes arguments O (an Object) and V (an ECMAScript language value). It performs the following steps when called:

  1. Assert: Either Type(V) is Object or Type(V) is Null.
  2. Let current be O.[[Prototype]].
  3. If SameValue(V, current) is true, return true.
  4. Let extensible be O.[[Extensible]].
  5. If extensible is false, return false.
  6. Let p be V.
  7. Let done be false.
  8. Repeat, while done is false,
    1. If p is null, set done to true.
    2. Else if SameValue(p, O) is true, return false.
    3. Else,
      1. If p.[[GetPrototypeOf]] is not the ordinary object internal method defined in 10.1.1, set done to true.
      2. Else, set p to p.[[Prototype]].
  9. Set O.[[Prototype]] to V.
  10. Return true.
Note

The loop in step 8 guarantees that there will be no circularities in any prototype chain that only includes objects that use the ordinary object definitions for [[GetPrototypeOf]] and [[SetPrototypeOf]].

10.1.3 [[IsExtensible]] ( )

The [[IsExtensible]] internal method of an ordinary object O takes no arguments. It performs the following steps when called:

  1. Return ! OrdinaryIsExtensible(O).

10.1.3.1 OrdinaryIsExtensible ( O )

The abstract operation OrdinaryIsExtensible takes argument O (an Object). It performs the following steps when called:

  1. Return O.[[Extensible]].

10.1.4 [[PreventExtensions]] ( )

The [[PreventExtensions]] internal method of an ordinary object O takes no arguments. It performs the following steps when called:

  1. Return ! OrdinaryPreventExtensions(O).

10.1.4.1 OrdinaryPreventExtensions ( O )

The abstract operation OrdinaryPreventExtensions takes argument O (an Object). It performs the following steps when called:

  1. Set O.[[Extensible]] to false.
  2. Return true.

10.1.5 [[GetOwnProperty]] ( P )

The [[GetOwnProperty]] internal method of an ordinary object O takes argument P (a property key). It performs the following steps when called:

  1. Return ! OrdinaryGetOwnProperty(O, P).

10.1.5.1 OrdinaryGetOwnProperty ( O, P )

The abstract operation OrdinaryGetOwnProperty takes arguments O (an Object) and P (a property key). It performs the following steps when called:

  1. Assert: IsPropertyKey(P) is true.
  2. If O does not have an own property with key P, return undefined.
  3. Let D be a newly created Property Descriptor with no fields.
  4. Let X be O's own property whose key is P.
  5. If X is a data property, then
    1. Set D.[[Value]] to the value of X's [[Value]] attribute.
    2. Set D.[[Writable]] to the value of X's [[Writable]] attribute.
  6. Else,
    1. Assert: X is an accessor property.
    2. Set D.[[Get]] to the value of X's [[Get]] attribute.
    3. Set D.[[Set]] to the value of X's [[Set]] attribute.
  7. Set D.[[Enumerable]] to the value of X's [[Enumerable]] attribute.
  8. Set D.[[Configurable]] to the value of X's [[Configurable]] attribute.
  9. Return D.

10.1.6 [[DefineOwnProperty]] ( P, Desc )

The [[DefineOwnProperty]] internal method of an ordinary object O takes arguments P (a property key) and Desc (a Property Descriptor). It performs the following steps when called:

  1. Return ? OrdinaryDefineOwnProperty(O, P, Desc).

10.1.6.1 OrdinaryDefineOwnProperty ( O, P, Desc )

The abstract operation OrdinaryDefineOwnProperty takes arguments O (an Object), P (a property key), and Desc (a Property Descriptor). It performs the following steps when called:

  1. Let current be ? O.[[GetOwnProperty]](P).
  2. Let extensible be ? IsExtensible(O).
  3. Return ValidateAndApplyPropertyDescriptor(O, P, extensible, Desc, current).

10.1.6.2 IsCompatiblePropertyDescriptor ( Extensible, Desc, Current )

The abstract operation IsCompatiblePropertyDescriptor takes arguments Extensible (a Boolean), Desc (a Property Descriptor), and Current (a Property Descriptor). It performs the following steps when called:

  1. Return ValidateAndApplyPropertyDescriptor(undefined, undefined, Extensible, Desc, Current).

10.1.6.3 ValidateAndApplyPropertyDescriptor ( O, P, extensible, Desc, current )

The abstract operation ValidateAndApplyPropertyDescriptor takes arguments O (an Object or undefined), P (a property key), extensible (a Boolean), Desc (a Property Descriptor), and current (a Property Descriptor). It performs the following steps when called:

Note

If undefined is passed as O, only validation is performed and no object updates are performed.

  1. Assert: If O is not undefined, then IsPropertyKey(P) is true.
  2. If current is undefined, then
    1. If extensible is false, return false.
    2. Assert: extensible is true.
    3. If IsGenericDescriptor(Desc) is true or IsDataDescriptor(Desc) is true, then
      1. If O is not undefined, create an own data property named P of object O whose [[Value]], [[Writable]], [[Enumerable]], and [[Configurable]] attribute values are described by Desc. If the value of an attribute field of Desc is absent, the attribute of the newly created property is set to its default value.
    4. Else,
      1. Assert: ! IsAccessorDescriptor(Desc) is true.
      2. If O is not undefined, create an own accessor property named P of object O whose [[Get]], [[Set]], [[Enumerable]], and [[Configurable]] attribute values are described by Desc. If the value of an attribute field of Desc is absent, the attribute of the newly created property is set to its default value.
    5. Return true.
  3. If every field in Desc is absent, return true.
  4. If current.[[Configurable]] is false, then
    1. If Desc.[[Configurable]] is present and its value is true, return false.
    2. If Desc.[[Enumerable]] is present and ! SameValue(Desc.[[Enumerable]], current.[[Enumerable]]) is false, return false.
  5. If ! IsGenericDescriptor(Desc) is true, then
    1. NOTE: No further validation is required.
  6. Else if ! SameValue(! IsDataDescriptor(current), ! IsDataDescriptor(Desc)) is false, then
    1. If current.[[Configurable]] is false, return false.
    2. If IsDataDescriptor(current) is true, then
      1. If O is not undefined, convert the property named P of object O from a data property to an accessor property. Preserve the existing values of the converted property's [[Configurable]] and [[Enumerable]] attributes and set the rest of the property's attributes to their default values.
    3. Else,
      1. If O is not undefined, convert the property named P of object O from an accessor property to a data property. Preserve the existing values of the converted property's [[Configurable]] and [[Enumerable]] attributes and set the rest of the property's attributes to their default values.
  7. Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) are both true, then
    1. If current.[[Configurable]] is false and current.[[Writable]] is false, then
      1. If Desc.[[Writable]] is present and Desc.[[Writable]] is true, return false.
      2. If Desc.[[Value]] is present and SameValue(Desc.[[Value]], current.[[Value]]) is false, return false.
      3. Return true.
  8. Else,
    1. Assert: ! IsAccessorDescriptor(current) and ! IsAccessorDescriptor(Desc) are both true.
    2. If current.[[Configurable]] is false, then
      1. If Desc.[[Set]] is present and SameValue(Desc.[[Set]], current.[[Set]]) is false, return false.
      2. If Desc.[[Get]] is present and SameValue(Desc.[[Get]], current.[[Get]]) is false, return false.
      3. Return true.
  9. If O is not undefined, then
    1. For each field of Desc that is present, set the corresponding attribute of the property named P of object O to the value of the field.
  10. Return true.

10.1.7 [[HasProperty]] ( P )

The [[HasProperty]] internal method of an ordinary object O takes argument P (a property key). It performs the following steps when called:

  1. Return ? OrdinaryHasProperty(O, P).

10.1.7.1 OrdinaryHasProperty ( O, P )

The abstract operation OrdinaryHasProperty takes arguments O (an Object) and P (a property key). It performs the following steps when called:

  1. Assert: IsPropertyKey(P) is true.
  2. Let hasOwn be ? O.[[GetOwnProperty]](P).
  3. If hasOwn is not undefined, return true.
  4. Let parent be ? O.[[GetPrototypeOf]]().
  5. If parent is not null, then
    1. Return ? parent.[[HasProperty]](P).
  6. Return false.

10.1.8 [[Get]] ( P, Receiver )

The [[Get]] internal method of an ordinary object O takes arguments P (a property key) and Receiver (an ECMAScript language value). It performs the following steps when called:

  1. Return ? OrdinaryGet(O, P, Receiver).

10.1.8.1 OrdinaryGet ( O, P, Receiver )

The abstract operation OrdinaryGet takes arguments O (an Object), P (a property key), and Receiver (an ECMAScript language value). It performs the following steps when called:

  1. Assert: IsPropertyKey(P) is true.
  2. Let desc be ? O.[[GetOwnProperty]](P).
  3. If desc is undefined, then
    1. Let parent be ? O.[[GetPrototypeOf]]().
    2. If parent is null, return undefined.
    3. Return ? parent.[[Get]](P, Receiver).
  4. If IsDataDescriptor(desc) is true, return desc.[[Value]].
  5. Assert: IsAccessorDescriptor(desc) is true.
  6. Let getter be desc.[[Get]].
  7. If getter is undefined, return undefined.
  8. Return ? Call(getter, Receiver).

10.1.9 [[Set]] ( P, V, Receiver )

The [[Set]] internal method of an ordinary object O takes arguments P (a property key), V (an ECMAScript language value), and Receiver (an ECMAScript language value). It performs the following steps when called:

  1. Return ? OrdinarySet(O, P, V, Receiver).

10.1.9.1 OrdinarySet ( O, P, V, Receiver )

The abstract operation OrdinarySet takes arguments O (an Object), P (a property key), V (an ECMAScript language value), and Receiver (an ECMAScript language value). It performs the following steps when called:

  1. Assert: IsPropertyKey(P) is true.
  2. Let ownDesc be ? O.[[GetOwnProperty]](P).
  3. Return OrdinarySetWithOwnDescriptor(O, P, V, Receiver, ownDesc).

10.1.9.2 OrdinarySetWithOwnDescriptor ( O, P, V, Receiver, ownDesc )

The abstract operation OrdinarySetWithOwnDescriptor takes arguments O (an Object), P (a property key), V (an ECMAScript language value), Receiver (an ECMAScript language value), and ownDesc (a Property Descriptor or undefined). It performs the following steps when called:

  1. Assert: IsPropertyKey(P) is true.
  2. If ownDesc is undefined, then
    1. Let parent be ? O.[[GetPrototypeOf]]().
    2. If parent is not null, then
      1. Return ? parent.[[Set]](P, V, Receiver).
    3. Else,
      1. Set ownDesc to the PropertyDescriptor { [[Value]]: undefined, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }.
  3. If IsDataDescriptor(ownDesc) is true, then
    1. If ownDesc.[[Writable]] is false, return false.
    2. If Type(Receiver) is not Object, return false.
    3. Let existingDescriptor be ? Receiver.[[GetOwnProperty]](P).
    4. If existingDescriptor is not undefined, then
      1. If IsAccessorDescriptor(existingDescriptor) is true, return false.
      2. If existingDescriptor.[[Writable]] is false, return false.
      3. Let valueDesc be the PropertyDescriptor { [[Value]]: V }.
      4. Return ? Receiver.[[DefineOwnProperty]](P, valueDesc).
    5. Else,
      1. Assert: Receiver does not currently have a property P.
      2. Return ? CreateDataProperty(Receiver, P, V).
  4. Assert: IsAccessorDescriptor(ownDesc) is true.
  5. Let setter be ownDesc.[[Set]].
  6. If setter is undefined, return false.
  7. Perform ? Call(setter, Receiver, « V »).
  8. Return true.

10.1.10 [[Delete]] ( P )

The [[Delete]] internal method of an ordinary object O takes argument P (a property key). It performs the following steps when called:

  1. Return ? OrdinaryDelete(O, P).

10.1.10.1 OrdinaryDelete ( O, P )

The abstract operation OrdinaryDelete takes arguments O (an Object) and P (a property key). It performs the following steps when called:

  1. Assert: IsPropertyKey(P) is true.
  2. Let desc be ? O.[[GetOwnProperty]](P).
  3. If desc is undefined, return true.
  4. If desc.[[Configurable]] is true, then
    1. Remove the own property with name P from O.
    2. Return true.
  5. Return false.

10.1.11 [[OwnPropertyKeys]] ( )

The [[OwnPropertyKeys]] internal method of an ordinary object O takes no arguments. It performs the following steps when called:

  1. Return ! OrdinaryOwnPropertyKeys(O).

10.1.11.1 OrdinaryOwnPropertyKeys ( O )

The abstract operation OrdinaryOwnPropertyKeys takes argument O (an Object). It performs the following steps when called:

  1. Let keys be a new empty List.
  2. For each own property key P of O such that P is an array index, in ascending numeric index order, do
    1. Add P as the last element of keys.
  3. For each own property key P of O such that Type(P) is String and P is not an array index, in ascending chronological order of property creation, do
    1. Add P as the last element of keys.
  4. For each own property key P of O such that Type(P) is Symbol, in ascending chronological order of property creation, do
    1. Add P as the last element of keys.
  5. Return keys.

10.1.12 OrdinaryObjectCreate ( proto [ , additionalInternalSlotsList ] )

The abstract operation OrdinaryObjectCreate takes argument proto (an Object or null) and optional argument additionalInternalSlotsList (a List of names of internal slots). It is used to specify the runtime creation of new ordinary objects. additionalInternalSlotsList contains the names of additional internal slots that must be defined as part of the object, beyond [[Prototype]] and [[Extensible]]. If additionalInternalSlotsList is not provided, a new empty List is used. It performs the following steps when called:

  1. Let internalSlotsList be « [[Prototype]], [[Extensible]] ».
  2. If additionalInternalSlotsList is present, append each of its elements to internalSlotsList.
  3. Let O be ! MakeBasicObject(internalSlotsList).
  4. Set O.[[Prototype]] to proto.
  5. Return O.
Note

Although OrdinaryObjectCreate does little more than call MakeBasicObject, its use communicates the intention to create an ordinary object, and not an exotic one. Thus, within this specification, it is not called by any algorithm that subsequently modifies the internal methods of the object in ways that would make the result non-ordinary. Operations that create exotic objects invoke MakeBasicObject directly.

10.1.13 OrdinaryCreateFromConstructor ( constructor, intrinsicDefaultProto [ , internalSlotsList ] )

The abstract operation OrdinaryCreateFromConstructor takes arguments constructor and intrinsicDefaultProto and optional argument internalSlotsList (a List of names of internal slots). It creates an ordinary object whose [[Prototype]] value is retrieved from a constructor's "prototype" property, if it exists. Otherwise the intrinsic named by intrinsicDefaultProto is used for [[Prototype]]. internalSlotsList contains the names of additional internal slots that must be defined as part of the object. If internalSlotsList is not provided, a new empty List is used. It performs the following steps when called:

  1. Assert: intrinsicDefaultProto is a String value that is this specification's name of an intrinsic object. The corresponding object must be an intrinsic that is intended to be used as the [[Prototype]] value of an object.
  2. Let proto be ? GetPrototypeFromConstructor(constructor, intrinsicDefaultProto).
  3. Return ! OrdinaryObjectCreate(proto, internalSlotsList).

10.1.14 GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto )

The abstract operation GetPrototypeFromConstructor takes arguments constructor and intrinsicDefaultProto. It determines the [[Prototype]] value that should be used to create an object corresponding to a specific constructor. The value is retrieved from the constructor's "prototype" property, if it exists. Otherwise the intrinsic named by intrinsicDefaultProto is used for [[Prototype]]. It performs the following steps when called:

  1. Assert: intrinsicDefaultProto is a String value that is this specification's name of an intrinsic object. The corresponding object must be an intrinsic that is intended to be used as the [[Prototype]] value of an object.
  2. Assert: IsCallable(constructor) is true.
  3. Let proto be ? Get(constructor, "prototype").
  4. If Type(proto) is not Object, then
    1. Let realm be ? GetFunctionRealm(constructor).
    2. Set proto to realm's intrinsic object named intrinsicDefaultProto.
  5. Return proto.
Note

If constructor does not supply a [[Prototype]] value, the default value that is used is obtained from the realm of the constructor function rather than from the running execution context.

10.1.15 RequireInternalSlot ( O, internalSlot )

The abstract operation RequireInternalSlot takes arguments O and internalSlot. It throws an exception unless O is an Object and has the given internal slot. It performs the following steps when called:

  1. If Type(O) is not Object, throw a TypeError exception.
  2. If O does not have an internalSlot internal slot, throw a TypeError exception.