ECMAScript® 2024 Language Specification

Draft ECMA-262 / February 15, 2024

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. Assume a property named P is missing from an ordinary object O but exists on its [[Prototype]] object. If P refers to a data property on the [[Prototype]] object, O inherits it for get access, making it behave as if P was a property of O. If P refers to a writable data property on the [[Prototype]] object, set access of P on O creates a new data property named P on O. If P refers to a non-writable data property on the [[Prototype]] object, set access of P on O fails. If P refers to an accessor property on the [[Prototype]] object, the accessor is inherited by O 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 and returns a normal completion containing either an Object or null. 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) and returns an Object or null. 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) and returns a normal completion containing a Boolean. 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 Object or null) and returns a Boolean. It performs the following steps when called:

  1. Let current be O.[[Prototype]].
  2. If SameValue(V, current) is true, return true.
  3. Let extensible be O.[[Extensible]].
  4. If extensible is false, return false.
  5. Let p be V.
  6. Let done be false.
  7. Repeat, while done is false,
    1. If p is null, then
      1. Set done to true.
    2. Else if SameValue(p, O) is true, then
      1. 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]].
  8. Set O.[[Prototype]] to V.
  9. Return true.
Note

The loop in step 7 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 and returns a normal completion containing a Boolean. 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) and returns a Boolean. 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 and returns a normal completion containing true. 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) and returns true. 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) and returns a normal completion containing either a Property Descriptor or undefined. 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) and returns a Property Descriptor or undefined. It performs the following steps when called:

  1. If O does not have an own property with key P, return undefined.
  2. Let D be a newly created Property Descriptor with no fields.
  3. Let X be O's own property whose key is P.
  4. 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.
  5. 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.
  6. Set D.[[Enumerable]] to the value of X's [[Enumerable]] attribute.
  7. Set D.[[Configurable]] to the value of X's [[Configurable]] attribute.
  8. 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) and returns either a normal completion containing a Boolean or a throw completion. 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) and returns either a normal completion containing a Boolean or a throw completion. 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 or undefined) and returns a Boolean. It performs the following steps when called:

  1. Return ValidateAndApplyPropertyDescriptor(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 or undefined) and returns a Boolean. It returns true if and only if Desc can be applied as the property of an object with specified extensibility and current property current while upholding invariants. When such application is possible and O is not undefined, it is performed for the property named P (which is created if necessary). It performs the following steps when called:

  1. Assert: IsPropertyKey(P) is true.
  2. If current is undefined, then
    1. If extensible is false, return false.
    2. If O is undefined, return true.
    3. If IsAccessorDescriptor(Desc) is true, then
      1. Create an own accessor property named P of object O whose [[Get]], [[Set]], [[Enumerable]], and [[Configurable]] attributes are set to the value of the corresponding field in Desc if Desc has that field, or to the attribute's default value otherwise.
    4. Else,
      1. Create an own data property named P of object O whose [[Value]], [[Writable]], [[Enumerable]], and [[Configurable]] attributes are set to the value of the corresponding field in Desc if Desc has that field, or to the attribute's default value otherwise.
    5. Return true.
  3. Assert: current is a fully populated Property Descriptor.
  4. If Desc does not have any fields, return true.
  5. If current.[[Configurable]] is false, then
    1. If Desc has a [[Configurable]] field and Desc.[[Configurable]] is true, return false.
    2. If Desc has an [[Enumerable]] field and Desc.[[Enumerable]] is not current.[[Enumerable]], return false.
    3. If IsGenericDescriptor(Desc) is false and IsAccessorDescriptor(Desc) is not IsAccessorDescriptor(current), return false.
    4. If IsAccessorDescriptor(current) is true, then
      1. If Desc has a [[Get]] field and SameValue(Desc.[[Get]], current.[[Get]]) is false, return false.
      2. If Desc has a [[Set]] field and SameValue(Desc.[[Set]], current.[[Set]]) is false, return false.
    5. Else if current.[[Writable]] is false, then
      1. If Desc has a [[Writable]] field and Desc.[[Writable]] is true, return false.
      2. If Desc has a [[Value]] field and SameValue(Desc.[[Value]], current.[[Value]]) is false, return false.
  6. If O is not undefined, then
    1. If IsDataDescriptor(current) is true and IsAccessorDescriptor(Desc) is true, then
      1. If Desc has a [[Configurable]] field, let configurable be Desc.[[Configurable]]; else let configurable be current.[[Configurable]].
      2. If Desc has a [[Enumerable]] field, let enumerable be Desc.[[Enumerable]]; else let enumerable be current.[[Enumerable]].
      3. Replace the property named P of object O with an accessor property whose [[Configurable]] and [[Enumerable]] attributes are set to configurable and enumerable, respectively, and whose [[Get]] and [[Set]] attributes are set to the value of the corresponding field in Desc if Desc has that field, or to the attribute's default value otherwise.
    2. Else if IsAccessorDescriptor(current) is true and IsDataDescriptor(Desc) is true, then
      1. If Desc has a [[Configurable]] field, let configurable be Desc.[[Configurable]]; else let configurable be current.[[Configurable]].
      2. If Desc has a [[Enumerable]] field, let enumerable be Desc.[[Enumerable]]; else let enumerable be current.[[Enumerable]].
      3. Replace the property named P of object O with a data property whose [[Configurable]] and [[Enumerable]] attributes are set to configurable and enumerable, respectively, and whose [[Value]] and [[Writable]] attributes are set to the value of the corresponding field in Desc if Desc has that field, or to the attribute's default value otherwise.
    3. Else,
      1. For each field of Desc, set the corresponding attribute of the property named P of object O to the value of the field.
  7. Return true.

10.1.7 [[HasProperty]] ( P )

The [[HasProperty]] internal method of an ordinary object O takes argument P (a property key) and returns either a normal completion containing a Boolean or a throw completion. 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) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

  1. Let hasOwn be ? O.[[GetOwnProperty]](P).
  2. If hasOwn is not undefined, return true.
  3. Let parent be ? O.[[GetPrototypeOf]]().
  4. If parent is not null, then
    1. Return ? parent.[[HasProperty]](P).
  5. 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) and returns either a normal completion containing an ECMAScript language value or a throw completion. 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) and returns either a normal completion containing an ECMAScript language value or a throw completion. It performs the following steps when called:

  1. Let desc be ? O.[[GetOwnProperty]](P).
  2. If desc is undefined, then
    1. Let parent be ? O.[[GetPrototypeOf]]().
    2. If parent is null, return undefined.
    3. Return ? parent.[[Get]](P, Receiver).
  3. If IsDataDescriptor(desc) is true, return desc.[[Value]].
  4. Assert: IsAccessorDescriptor(desc) is true.
  5. Let getter be desc.[[Get]].
  6. If getter is undefined, return undefined.
  7. 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) and returns either a normal completion containing a Boolean or a throw completion. 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) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

  1. Let ownDesc be ? O.[[GetOwnProperty]](P).
  2. 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) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

  1. 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 }.
  2. If IsDataDescriptor(ownDesc) is true, then
    1. If ownDesc.[[Writable]] is false, return false.
    2. If Receiver is not an 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).
  3. Assert: IsAccessorDescriptor(ownDesc) is true.
  4. Let setter be ownDesc.[[Set]].
  5. If setter is undefined, return false.
  6. Perform ? Call(setter, Receiver, « V »).
  7. Return true.

10.1.10 [[Delete]] ( P )

The [[Delete]] internal method of an ordinary object O takes argument P (a property key) and returns either a normal completion containing a Boolean or a throw completion. 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) and returns either a normal completion containing a Boolean or a throw completion. It performs the following steps when called:

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

10.1.11 [[OwnPropertyKeys]] ( )

The [[OwnPropertyKeys]] internal method of an ordinary object O takes no arguments and returns a normal completion containing a List of property keys. 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) and returns a List of property keys. 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. Append P to keys.
  3. For each own property key P of O such that P is a String and P is not an array index, in ascending chronological order of property creation, do
    1. Append P to keys.
  4. For each own property key P of O such that P is a Symbol, in ascending chronological order of property creation, do
    1. Append P to 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) and returns an Object. 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, set internalSlotsList to the list-concatenation of internalSlotsList and additionalInternalSlotsList.
  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 (a constructor) and intrinsicDefaultProto (a String) and optional argument internalSlotsList (a List of names of internal slots) and returns either a normal completion containing an Object or a throw completion. 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 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. If internalSlotsList is present, let slotsList be internalSlotsList.
  4. Else, let slotsList be a new empty List.
  5. Return OrdinaryObjectCreate(proto, slotsList).

10.1.14 GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto )

The abstract operation GetPrototypeFromConstructor takes arguments constructor (a function object) and intrinsicDefaultProto (a String) and returns either a normal completion containing an Object or a throw completion. 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 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 ? Get(constructor, "prototype").
  3. If proto is not an Object, then
    1. Let realm be ? GetFunctionRealm(constructor).
    2. Set proto to realm's intrinsic object named intrinsicDefaultProto.
  4. 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 (an ECMAScript language value) and internalSlot (an internal slot name) and returns either a normal completion containing unused or a throw completion. It throws an exception unless O is an Object and has the given internal slot. It performs the following steps when called:

  1. If O is not an Object, throw a TypeError exception.
  2. If O does not have an internalSlot internal slot, throw a TypeError exception.
  3. Return unused.