9 Ordinary and Exotic Objects Behaviours

9.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 (are 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 that controls whether or not properties may be added to the object. If the value of the [[Extensible]] internal slot is false then additional properties may not be added to the object. In addition, if [[Extensible]] is false the value of the [[Prototype]] internal slot of the object may not be modified. Once the value of an object's [[Extensible]] internal slot has been set to false it may not be subsequently changed 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.

9.1.1 [[GetPrototypeOf]] ( )

When the [[GetPrototypeOf]] internal method of O is called the following steps are taken:

  1. Return the value of the [[Prototype]] internal slot of O.

9.1.2 [[SetPrototypeOf]] (V)

When the [[SetPrototypeOf]] internal method of O is called with argument V the following steps are taken:

  1. Assert: Either Type(V) is Object or Type(V) is Null.
  2. Let extensible be the value of the [[Extensible]] internal slot of O.
  3. Let current be the value of the [[Prototype]] internal slot of O.
  4. If SameValue(V, current), return true.
  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, let done be true.
    2. Else, if SameValue(p, O) is true, return false.
    3. Else,
      1. If the [[GetPrototypeOf]] internal method of p is not the ordinary object internal method defined in 9.1.1, let done be true.
      2. Else, let p be the value of p's [[Prototype]] internal slot.
  9. Set the value of the [[Prototype]] internal slot of O 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]].

9.1.3 [[IsExtensible]] ( )

When the [[IsExtensible]] internal method of O is called the following steps are taken:

  1. Return the value of the [[Extensible]] internal slot of O.

9.1.4 [[PreventExtensions]] ( )

When the [[PreventExtensions]] internal method of O is called the following steps are taken:

  1. Set the value of the [[Extensible]] internal slot of O to false.
  2. Return true.

9.1.5 [[GetOwnProperty]] (P)

When the [[GetOwnProperty]] internal method of O is called with property key P, the following steps are taken:

  1. Return OrdinaryGetOwnProperty(O, P).

9.1.5.1 OrdinaryGetOwnProperty (O, P)

When the abstract operation OrdinaryGetOwnProperty is called with Object O and with property key P, the following steps are taken:

  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 X is an accessor property, so
    1. Set D.[[Get]] to the value of X's [[Get]] attribute.
    2. 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.

9.1.6 [[DefineOwnProperty]] (P, Desc)

When the [[DefineOwnProperty]] internal method of O is called with property key P and Property Descriptor Desc, the following steps are taken:

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

9.1.6.1 OrdinaryDefineOwnProperty (O, P, Desc)

When the abstract operation OrdinaryDefineOwnProperty is called with Object O, property key P, and Property Descriptor Desc the following steps are taken:

  1. Let current be O.[[GetOwnProperty]](P).
  2. ReturnIfAbrupt(current).
  3. Let extensible be the value of the [[Extensible]] internal slot of O.
  4. Return ValidateAndApplyPropertyDescriptor(O, P, extensible, Desc, current).

9.1.6.2 IsCompatiblePropertyDescriptor (Extensible, Desc, Current)

When the abstract operation IsCompatiblePropertyDescriptor is called with Boolean value Extensible, and Property Descriptors Desc, and Current the following steps are taken:

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

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

When the abstract operation ValidateAndApplyPropertyDescriptor is called with Object O, property key P, Boolean value extensible, and Property Descriptors Desc, and current the following steps are taken:

This algorithm contains steps that test various fields of the Property Descriptor Desc for specific values. The fields that are tested in this manner need not actually exist in Desc. If a field is absent then its value is considered to be false.

NOTE 1 If undefined is passed as the O argument 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) 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 Desc must be an accessor Property Descriptor,
      1. 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. Return true, if every field in Desc is absent.
  4. Return true, if every field in Desc also occurs in current and the value of every field in Desc is the same value as the corresponding field in current when compared using the SameValue algorithm.
  5. If the [[Configurable]] field of current is false, then
    1. Return false, if the [[Configurable]] field of Desc is true.
    2. Return false, if the [[Enumerable]] field of Desc is present and the [[Enumerable]] fields of current and Desc are the Boolean negation of each other.
  6. If IsGenericDescriptor(Desc) is true, no further validation is required.
  7. Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) have different results, then
    1. Return false, if the [[Configurable]] field of current is 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.
  8. Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) are both true, then
    1. If the [[Configurable]] field of current is false, then
      1. Return false, if the [[Writable]] field of current is false and the [[Writable]] field of Desc is true.
      2. If the [[Writable]] field of current is false, then
        1. Return false, if the [[Value]] field of Desc is present and SameValue(Desc.[[Value]], current.[[Value]]) is false.
    2. Else the [[Configurable]] field of current is true, so any change is acceptable.
  9. Else IsAccessorDescriptor(current) and IsAccessorDescriptor(Desc) are both true,
    1. If the [[Configurable]] field of current is false, then
      1. Return false, if the [[Set]] field of Desc is present and SameValue(Desc.[[Set]], current.[[Set]]) is false.
      2. Return false, if the [[Get]] field of Desc is present and SameValue(Desc.[[Get]], current.[[Get]]) is false.
  10. 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.
  11. Return true.

NOTE 2 Step 8.b allows any field of Desc to be different from the corresponding field of current if current’s [[Configurable]] field is true. This even permits changing the [[Value]] of a property whose [[Writable]] attribute is false. This is allowed because a true [[Configurable]] attribute would permit an equivalent sequence of calls where [[Writable]] is first set to true, a new [[Value]] is set, and then [[Writable]] is set to false.

9.1.7 [[HasProperty]](P)

When the [[HasProperty]] internal method of O is called with property key P, the following steps are taken:

  1. Return OrdinaryHasProperty(O, P).

9.1.7.1 OrdinaryHasProperty (O, P)

When the abstract operation OrdinaryHasProperty is called with Object O and with property key P, the following steps are taken:

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

9.1.8 [[Get]] (P, Receiver)

When the [[Get]] internal method of O is called with property key P and ECMAScript language value Receiver the following steps are taken:

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

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

When the [[Set]] internal method of O is called with property key P, value V, and ECMAScript language value Receiver, the following steps are taken:

  1. Assert: IsPropertyKey(P) is true.
  2. Let ownDesc be O.[[GetOwnProperty]](P).
  3. ReturnIfAbrupt(ownDesc).
  4. If ownDesc is undefined, then
    1. Let parent be O.[[GetPrototypeOf]]().
    2. ReturnIfAbrupt(parent).
    3. If parent is not null, then
      1. Return parent.[[Set]](P, V, Receiver).
    4. Else,
      1. Let ownDesc be the PropertyDescriptor{[[Value]]: undefined, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}.
  5. 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. ReturnIfAbrupt(existingDescriptor).
    5. 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).
    6. Else Receiver does not currently have a property P,
      1. Return CreateDataProperty(Receiver, P, V).
  6. Assert: IsAccessorDescriptor(ownDesc) is true.
  7. Let setter be ownDesc.[[Set]].
  8. If setter is undefined, return false.
  9. Let setterResult be Call(setter, Receiver, «V»).
  10. ReturnIfAbrupt(setterResult).
  11. Return true.

9.1.10 [[Delete]] (P)

When the [[Delete]] internal method of O is called with property key P the following steps are taken:

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

9.1.11 [[Enumerate]] ()

When the [[Enumerate]] internal method of O is called the following steps are taken:

  1. Return an Iterator object (25.1.1.2) whose next method iterates over all the String-valued keys of enumerable properties of O. The Iterator object must inherit from %IteratorPrototype% (25.1.2). The mechanics and order of enumerating the properties is not specified but must conform to the rules specified below.

The iterator's next method processes object properties to determine whether the property key should be returned as an iterator value. Returned property keys do not include keys that are Symbols. Properties of the target object may be deleted during enumeration. A property that is deleted before it is processed by the iterator's next method is ignored. If new properties are added to the target object during enumeration, the newly added properties are not guaranteed to be processed in the active enumeration. A property name will be returned by the iterator's next method at most once in any enumeration.

Enumerating the properties of the target object includes enumerating properties of its prototype, and the prototype of the prototype, and so on, recursively; but a property of a prototype is not processed if it has the same name as a property that has already been processed by the iterator's next method. The values of [[Enumerable]] attributes are not considered when determining if a property of a prototype object has already been processed. The enumerable property names of prototype objects must be obtained as if by invoking the prototype object's [[Enumerate]] internal method. [[Enumerate]] must obtain the own property keys of the target object as if by calling its [[OwnPropertyKeys]] internal method. Property attributes of the target object must be obtained as if by calling its [[GetOwnProperty]] internal method.

NOTE The following is an informative definition of an ECMAScript generator function that conforms to these rules:

function* enumerate(obj) {
  let visited=new Set;
  for (let key of Reflect.ownKeys(obj)) {
      if (typeof key === "string") {
          let desc = Reflect.getOwnPropertyDescriptor(obj,key);
          if (desc) {
              visited.add(key);
              if (desc.enumerable) yield key;
          }
      }
  }
  let proto = Reflect.getPrototypeOf(obj)
  if (proto === null) return;
  for (let protoName of Reflect.enumerate(proto)) {
      if (!visited.has(protoName)) yield protoName;
  }
}

9.1.12 [[OwnPropertyKeys]] ( )

When the [[OwnPropertyKeys]] internal method of O is called the following steps are taken:

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

9.1.13 ObjectCreate(proto, internalSlotsList)

The abstract operation ObjectCreate with argument proto (an object or null) is used to specify the runtime creation of new ordinary objects. The optional argument internalSlotsList is a List of the names of additional internal slots that must be defined as part of the object. If the list is not provided, an empty List is used. This abstract operation performs the following steps:

  1. If internalSlotsList was not provided, let internalSlotsList be an empty List.
  2. Let obj be a newly created object with an internal slot for each name in internalSlotsList.
  3. Set obj's essential internal methods to the default ordinary object definitions specified in 9.1.
  4. Set the [[Prototype]] internal slot of obj to proto.
  5. Set the [[Extensible]] internal slot of obj to true.
  6. Return obj.

9.1.14 OrdinaryCreateFromConstructor ( constructor, intrinsicDefaultProto, internalSlotsList )

The abstract operation OrdinaryCreateFromConstructor 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]]. The optional internalSlotsList is a List of the names of additional internal slots that must be defined as part of the object. If the list is not provided, an empty List is used. This abstract operation performs the following steps:

  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. ReturnIfAbrupt(proto).
  4. Return ObjectCreate(proto, internalSlotsList).

9.1.15 GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto )

The abstract operation GetPrototypeFromConstructor 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]]. This abstract operation performs the following steps:

  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: IsConstructor (constructor) is true.
  3. Let proto be Get(constructor, "prototype").
  4. ReturnIfAbrupt(proto).
  5. If Type(proto) is not Object, then
    1. Let realm be GetFunctionRealm(constructor).
    2. ReturnIfAbrupt(realm).
    3. Let proto be realm’s intrinsic object named intrinsicDefaultProto.
  6. Return proto.

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

9.2 ECMAScript Function Objects

ECMAScript function objects encapsulate parameterized ECMAScript code closed over a lexical environment and support the dynamic evaluation of that code. An ECMAScript function object is an ordinary object and has the same internal slots and the same internal methods as other ordinary objects. The code of an ECMAScript function object may be either strict mode code (10.2.1) or non-strict mode code. An ECMAScript function object whose code is strict mode code is called a strict function. One whose code is not strict mode code is called a non-strict function.

ECMAScript function objects have the additional internal slots listed in Table 27.

Table 27 — Internal Slots of ECMAScript Function Objects
Internal Slot Type Description
[[Environment]] Lexical Environment The Lexical Environment that the function was closed over. Used as the outer environment when evaluating the code of the function.
[[FormalParameters]] Parse Node The root parse node of the source text that defines the function's formal parameter list.
[[FunctionKind]] String Either "normal", "classConstructor" or "generator".
[[ECMAScriptCode]] Parse Node The root parse node of the source text that defines the function's body.
[[ConstructorKind]] String Either "base" or "derived".
[[Realm]] Realm Record The Code Realm in which the function was created and which provides any intrinsic objects that are accessed when evaluating the function.
[[ThisMode]] (lexical, strict, global) Defines how this references are interpreted within the formal parameters and code body of the function. lexical means that this refers to the this value of a lexically enclosing function. strict means that the this value is used exactly as provided by an invocation of the function. global means that a this value of undefined is interpreted as a reference to the global object.
[[Strict]] Boolean true if this is a strict mode function, false if this is not a strict mode function.
[[HomeObject]] Object If the function uses super, this is the object whose [[GetPrototypeOf]] provides the object where super property lookups begin.

All ECMAScript function objects have the [[Call]] internal method defined here. ECMAScript functions that are also constructors in addition have the [[Construct]] internal method. ECMAScript function objects whose code is not strict mode code have the [[GetOwnProperty]] internal method defined here.

9.2.1 [[Call]] ( thisArgument, argumentsList)

The [[Call]] internal method for an ECMAScript function object F is called with parameters thisArgument and argumentsList, a List of ECMAScript language values. The following steps are taken:

  1. Assert: F is an ECMAScript function object.
  2. If F's [[FunctionKind]] internal slot is "classConstructor", throw a TypeError exception.
  3. Let callerContext be the running execution context.
  4. Let calleeContext be PrepareForOrdinaryCall(F, undefined).
  5. Assert: calleeContext is now the running execution context.
  6. Perform OrdinaryCallBindThis(F, calleeContext, thisArgument).
  7. Let result be OrdinaryCallEvaluateBody(F, argumentsList).
  8. Remove calleeContext from the execution context stack and restore callerContext as the running execution context.
  9. If result.[[type]] is return, return NormalCompletion(result.[[value]]).
  10. ReturnIfAbrupt(result).
  11. Return NormalCompletion(undefined).

NOTE When calleeContext is removed from the execution context stack in step 8 it must not be destroyed if it is suspended and retained for later resumption by an accessible generator object.

9.2.1.1 PrepareForOrdinaryCall( F, newTarget )

When the abstract operation PrepareForOrdinaryCall is called with function object F and ECMAScript language value newTarget, the following steps are taken:

  1. Assert: Type(newTarget) is Undefined or Object.
  2. Let callerContext be the running execution context.
  3. Let calleeContext be a new ECMAScript code execution context.
  4. Set the Function of calleeContext to F.
  5. Let calleeRealm be the value of F’s [[Realm]] internal slot.
  6. Set the Realm of calleeContext to calleeRealm.
  7. Let localEnv be NewFunctionEnvironment(F, newTarget).
  8. Set the LexicalEnvironment of calleeContext to localEnv.
  9. Set the VariableEnvironment of calleeContext to localEnv.
  10. If callerContext is not already suspended, Suspend callerContext.
  11. Push calleeContext onto the execution context stack; calleeContext is now the running execution context.
  12. NOTE Any exception objects produced after this point are associated with calleeRealm.
  13. Return calleeContext.

9.2.1.2 OrdinaryCallBindThis ( F, calleeContext, thisArgument )

When the abstract operation OrdinaryCallBindThis is called with function object F, execution context calleeContext, and ECMAScript value thisArgument the following steps are taken:

  1. Let thisMode be the value of F's [[ThisMode]] internal slot.
  2. If thisMode is lexical, return NormalCompletion(undefined).
  3. Let calleeRealm be the value of F’s [[Realm]] internal slot.
  4. Let localEnv be the LexicalEnvironment of calleeContext.
  5. If thisMode is strict, let thisValue be thisArgument.
  6. Else
    1. if thisArgument is null or undefined, then
      1. Let thisValue be calleeRealm.[[globalThis]].
    2. Else
      1. Let thisValue be ToObject(thisArgument).
      2. Assert: thisValue is not an abrupt completion.
      3. NOTE ToObject produces wrapper objects using calleeRealm.
  7. Let envRec be localEnv's EnvironmentRecord.
  8. Assert: The next step never returns an abrupt completion because envRec.[[thisBindingStatus]] is not "uninitialized".
  9. Return envRec.BindThisValue(thisValue).

9.2.1.3 OrdinaryCallEvaluateBody ( F, argumentsList )

When the abstract operation OrdinaryCallEvaluateBody is called with function object F and List argumentsList the following steps are taken:

  1. Let status be FunctionDeclarationInstantiation(F, argumentsList).
  2. ReturnIfAbrupt(status)
  3. Return the result of EvaluateBody of the parsed code that is the value of F's [[ECMAScriptCode]] internal slot passing F as the argument.

9.2.2 [[Construct]] ( argumentsList, newTarget)

The [[Construct]] internal method for an ECMAScript Function object F is called with parameters argumentsList and newTarget. argumentsList is a possibly empty List of ECMAScript language values. The following steps are taken:

  1. Assert: F is an ECMAScript function object.
  2. Assert: Type(newTarget) is Object.
  3. Let callerContext be the running execution context.
  4. Let kind be F's [[ConstructorKind]] internal slot.
  5. If kind is "base", then
    1. Let thisArgument be OrdinaryCreateFromConstructor(newTarget, "%ObjectPrototype%").
    2. ReturnIfAbrupt(thisArgument).
  6. Let calleeContext be PrepareForOrdinaryCall(F, newTarget).
  7. Assert: calleeContext is now the running execution context.
  8. If kind is "base", perform OrdinaryCallBindThis(F, calleeContext, thisArgument).
  9. Let constructorEnv be the LexicalEnvironment of calleeContext.
  10. Let envRec be constructorEnv's EnvironmentRecord.
  11. Let result be OrdinaryCallEvaluateBody(F, argumentsList).
  12. Remove calleeContext from the execution context stack and restore callerContext as the running execution context.
  13. If result.[[type]] is return, then
    1. If Type(result.[[value]]) is Object, return NormalCompletion(result.[[value]]).
    2. If kind is "base", return NormalCompletion(thisArgument).
    3. If result.[[value]] is not undefined, throw a TypeError exception.
  14. Else, ReturnIfAbrupt(result).
  15. Return envRec.GetThisBinding().

9.2.3 FunctionAllocate (functionPrototype, strict [,functionKind] )

The abstract operation FunctionAllocate requires the two arguments functionPrototype and strict. It also accepts one optional argument, functionKind. FunctionAllocate performs the following steps:

  1. Assert: Type(functionPrototype) is Object.
  2. Assert: If functionKind is present, its value is either "normal", "non-constructor" or "generator".
  3. If functionKind is not present, let functionKind be "normal".
  4. If functionKind is "non-constructor", then
    1. Let functionKind be "normal".
    2. Let needsConstruct be false.
  5. Else let needsConstruct be true.
  6. Let F be a newly created ECMAScript function object with the internal slots listed in Table 27. All of those internal slots are initialized to undefined.
  7. Set F's essential internal methods to the default ordinary object definitions specified in 9.1.
  8. Set F's [[Call]] internal method to the definition specified in 9.2.1.
  9. If needsConstruct is true, then
    1. Set F's [[Construct]] internal method to the definition specified in 9.2.2.
    2. If functionKind is "generator", set the [[ConstructorKind]] internal slot of F to "derived".
    3. Else, set the [[ConstructorKind]] internal slot of F to "base".
    4. NOTE Generator functions are tagged as "derived" constructors to prevent [[Construct]] from preallocating a generator instance. Generator instance objects are allocated when EvaluateBody is applied to the GeneratorBody of a generator function.
  10. Set the [[Strict]] internal slot of F to strict.
  11. Set the [[FunctionKind]] internal slot of F to functionKind.
  12. Set the [[Prototype]] internal slot of F to functionPrototype.
  13. Set the [[Extensible]] internal slot of F to true.
  14. Set the [[Realm]] internal slot of F to the running execution context's Realm.
  15. Return F.

9.2.4 FunctionInitialize (F, kind, ParameterList, Body, Scope)

The abstract operation FunctionInitialize requires the arguments: a function object F, kind which is one of (Normal, Method, Arrow), a parameter list production specified by ParameterList, a body production specified by Body, a Lexical Environment specified by Scope. FunctionInitialize performs the following steps:

  1. Assert: F is an extensible object that does not have a length own property.
  2. Let len be the ExpectedArgumentCount of ParameterList.
  3. Let status be DefinePropertyOrThrow(F, "length", PropertyDescriptor{[[Value]]: len, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true}).
  4. Assert: status is not an abrupt completion.
  5. Let Strict be the value of the [[Strict]] internal slot of F.
  6. Set the [[Environment]] internal slot of F to the value of Scope.
  7. Set the [[FormalParameters]] internal slot of F to ParameterList .
  8. Set the [[ECMAScriptCode]] internal slot of F to Body.
  9. If kind is Arrow, set the [[ThisMode]] internal slot of F to lexical.
  10. Else if Strict is true, set the [[ThisMode]] internal slot of F to strict.
  11. Else set the [[ThisMode]] internal slot of F to global.
  12. Return F.

9.2.5 FunctionCreate (kind, ParameterList, Body, Scope, Strict, prototype)

The abstract operation FunctionCreate requires the arguments: kind which is one of (Normal, Method, Arrow), a parameter list production specified by ParameterList, a body production specified by Body, a Lexical Environment specified by Scope, a Boolean flag Strict, and optionally, an object prototype. FunctionCreate performs the following steps:

  1. If the prototype argument was not passed, then
    1. Let prototype be the intrinsic object %FunctionPrototype%.
  2. If kind is not Normal, let allocKind be "non-constructor".
  3. Else let allocKind be "normal".
  4. Let F be FunctionAllocate(prototype, Strict, allocKind).
  5. Return FunctionInitialize(F, kind, ParameterList, Body, Scope).

9.2.6 GeneratorFunctionCreate (kind, ParameterList, Body, Scope, Strict)

The abstract operation GeneratorFunctionCreate requires the arguments: kind which is one of (Normal, Method), a parameter list production specified by ParameterList, a body production specified by Body, a Lexical Environment specified by Scope, and a Boolean flag Strict. GeneratorFunctionCreate performs the following steps:

  1. Let functionPrototype be the intrinsic object %Generator%.
  2. Let F be FunctionAllocate(functionPrototype, Strict, "generator").
  3. Return FunctionInitialize(F, kind, ParameterList, Body, Scope).

9.2.7 AddRestrictedFunctionProperties ( F, realm )

The abstract operation AddRestrictedFunctionProperties is called with a function object F and Realm Record realm as its argument. It performs the following steps:

  1. Assert: realm.[[intrinsics]].[[%ThrowTypeError%]] exists and has been initialized.
  2. Let thrower be realm.[[intrinsics]].[[%ThrowTypeError%]].
  3. Let status be DefinePropertyOrThrow(F, "caller", PropertyDescriptor {[[Get]]: thrower, [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: true}).
  4. Assert: status is not an abrupt completion.
  5. Return DefinePropertyOrThrow(F , "arguments", PropertyDescriptor {[[Get]]: thrower, [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: true}).
  6. Assert: The above returned value is not an abrupt completion.

9.2.7.1 %ThrowTypeError% ( )

The %ThrowTypeError% intrinsic is an anonymous built-in function object that is defined once for each Realm. When %ThrowTypeError% is called it performs the following steps:

  1. Throw a TypeError exception.

The value of the [[Extensible]] internal slot of a %ThrowTypeError% function is false.

The length property of a %ThrowTypeError% function has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

9.2.8 MakeConstructor (F, writablePrototype, prototype)

The abstract operation MakeConstructor requires a Function argument F and optionally, a Boolean writablePrototype and an object prototype. If prototype is provided it is assumed to already contain, if needed, a "constructor" property whose value is F. This operation converts F into a constructor by performing the following steps:

  1. Assert: F is an ECMAScript function object.
  2. Assert: F has a [[Construct]] internal method.
  3. Assert: F is an extensible object that does not have a prototype own property.
  4. If the writablePrototype argument was not provided, let writablePrototype be true.
  5. If the prototype argument was not provided, then
    1. Let prototype be ObjectCreate(%ObjectPrototype%).
    2. Let status be DefinePropertyOrThrow(prototype, "constructor", PropertyDescriptor{[[Value]]: F, [[Writable]]: writablePrototype, [[Enumerable]]: false, [[Configurable]]: true }).
    3. Assert: status is not an abrupt completion.
  6. Let status be DefinePropertyOrThrow(F, "prototype", PropertyDescriptor{[[Value]]: prototype, [[Writable]]: writablePrototype, [[Enumerable]]: false, [[Configurable]]: false}).
  7. Assert: status is not an abrupt completion.
  8. Return NormalCompletion(undefined).

9.2.9 MakeClassConstructor ( F)

The abstract operation MakeClassConstructor with argument F performs the following steps:

  1. Assert: F is an ECMAScript function object.
  2. Assert: F's [[FunctionKind]] internal slot is "normal".
  3. Set F's [[FunctionKind]] internal slot to "classConstructor".
  4. Return NormalCompletion(undefined).

9.2.10 MakeMethod ( F, homeObject)

The abstract operation MakeMethod with arguments F and homeObject configures F as a method by performing the following steps:

  1. Assert: F is an ECMAScript function object.
  2. Assert: Type(homeObject ) is Object.
  3. Set the [[HomeObject]] internal slot of F to homeObject.
  4. Return NormalCompletion(undefined).

9.2.11 SetFunctionName (F, name, prefix)

The abstract operation SetFunctionName requires a Function argument F, a String or Symbol argument name and optionally a String argument prefix. This operation adds a name property to F by performing the following steps:

  1. Assert: F is an extensible object that does not have a name own property.
  2. Assert: Type(name) is either Symbol or String.
  3. Assert: If prefix was passed then Type(prefix) is String.
  4. If Type(name) is Symbol, then
    1. Let description be name's [[Description]] value.
    2. If description is undefined, let name be the empty String.
    3. Else, let name be the concatenation of "[", description, and "]".
  5. If prefix was passed, then
    1. Let name be the concatenation of prefix, code unit 0x0020 (SPACE), and name.
  6. Return DefinePropertyOrThrow(F, "name", PropertyDescriptor{[[Value]]: name, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true}).
  7. Assert: the result is never an abrupt completion.

9.2.12 FunctionDeclarationInstantiation(func, argumentsList)

NOTE 1 When an execution context is established for evaluating an ECMAScript function a new function Environment Record is created and bindings for each formal parameter are instantiated in that Environment Record. Each declaration in the function body is also instantiated. If the function's formal parameters do not include any default value initializers then the body declarations are instantiated in the same Environment Record as the parameters. If default value parameter initializers exist, a second Environment Record is created for the body declarations. Formal parameters and functions are initialized as part of FunctionDeclarationInstantiation. All other bindings are initialized during evaluation of the function body.

FunctionDeclarationInstantiation is performed as follows using arguments func and argumentsList. func is the function object for which the execution context is being established.

  1. Let calleeContext be the running execution context.
  2. Let env be the LexicalEnvironment of calleeContext.
  3. Let envRec be env's EnvironmentRecord.
  4. Let code be the value of the [[ECMAScriptCode]] internal slot of func.
  5. Let strict be the value of the [[Strict]] internal slot of func.
  6. Let formals be the value of the [[FormalParameters]] internal slot of func.
  7. Let parameterNames be the BoundNames of formals.
  8. If parameterNames has any duplicate entries, let hasDuplicates be true. Otherwise, let hasDuplicates be false.
  9. Let simpleParameterList be IsSimpleParameterList of formals.
  10. Let hasParameterExpressions be ContainsExpression of formals.
  11. Let varNames be the VarDeclaredNames of code.
  12. Let varDeclarations be the VarScopedDeclarations of code.
  13. Let lexicalNames be the LexicallyDeclaredNames of code.
  14. Let functionNames be an empty List.
  15. Let functionsToInitialize be an empty List.
  16. For each d in varDeclarations, in reverse list order do
    1. If d is neither a VariableDeclaration or a ForBinding, then
      1. Assert: d is either a FunctionDeclaration or a GeneratorDeclaration.
      2. Let fn be the sole element of the BoundNames of d.
      3. If fn is not an element of functionNames, then
        1. Insert fn as the first element of functionNames.
        2. NOTE If there are multiple FunctionDeclarations or GeneratorDeclarations for the same name, the last declaration is used.
        3. Insert d as the first element of functionsToInitialize.
  17. Let argumentsObjectNeeded be true.
  18. If the value of the [[ThisMode]] internal slot of func is lexical, then
    1. NOTE Arrow functions never have an arguments objects.
    2. Let argumentsObjectNeeded be false.
  19. Else if "arguments" is an element of parameterNames, then
    1. Let argumentsObjectNeeded be false.
  20. Else if hasParameterExpressions is false, then
    1. If "arguments" is an element of functionNames or if "arguments" is an element of lexicalNames, then
      1. Let argumentsObjectNeeded be false.
  21. For each String paramName in parameterNames, do
    1. Let alreadyDeclared be envRec.HasBinding(paramName).
    2. NOTE Early errors ensure that duplicate parameter names can only occur in non-strict functions that do not have parameter default values or rest parameters.
    3. If alreadyDeclared is false, then
      1. Let status be envRec.CreateMutableBinding(paramName).
      2. If hasDuplicates is true, then
        1. Let status be envRec.InitializeBinding(paramName, undefined).
      3. Assert: status is never an abrupt completion for either of the above operations.
  22. If argumentsObjectNeeded is true, then
    1. If strict is true or if simpleParameterList is false, then
      1. Let ao be CreateUnmappedArgumentsObject(argumentsList).
    2. Else,
      1. NOTE mapped argument object is only provided for non-strict functions that don't have a rest parameter, any parameter default value initializers, or any destructured parameters .
      2. Let ao be CreateMappedArgumentsObject(func, formals, argumentsList, env).
    3. ReturnIfAbrupt(ao).
    4. If strict is true, then
      1. Let status be envRec.CreateImmutableBinding("arguments").
    5. Else,
      1. Let status be envRec.CreateMutableBinding("arguments").
    6. Assert: status is never an abrupt completion.
    7. Call envRec.InitializeBinding("arguments", ao).
    8. Append "arguments" to parameterNames.
  23. Let iteratorRecord be Record {[[iterator]]: CreateListIterator(argumentsList), [[done]]: false}.
  24. If hasDuplicates is true, then
    1. Let formalStatus be IteratorBindingInitialization for formals with iteratorRecord and undefined as arguments.
  25. Else,
    1. Let formalStatus be IteratorBindingInitialization for formals with iteratorRecord and env as arguments.
  26. ReturnIfAbrupt(formalStatus).
  27. If hasParameterExpressions is false, then
    1. NOTE Only a single lexical environment is needed for the parameters and top-level vars.
    2. Let instantiatedVarNames be a copy of the List parameterNames.
    3. For each n in varNames, do
      1. If n is not an element of instantiatedVarNames, then
        1. Append n to instantiatedVarNames.
        2. Let status be envRec.CreateMutableBinding(n).
        3. Assert: status is never an abrupt completion.
        4. Call envRec.InitializeBinding(n, undefined).
    4. Let varEnv be env.
    5. Let varEnvRec be envRec.
  28. Else,
    1. NOTE A separate Environment Record is needed to ensure that closures created by expressions in the formal parameter list do not have visibility of declarations in the function body.
    2. Let varEnv be NewDeclarativeEnvironment(env).
    3. Let varEnvRec be varEnv's EnvironmentRecord.
    4. Set the VariableEnvironment of calleeContext to varEnv.
    5. Let instantiatedVarNames be a new empty List.
    6. For each n in varNames, do
      1. If n is not an element of instantiatedVarNames, then
        1. Append n to instantiatedVarNames.
        2. Let status be varEnvRec.CreateMutableBinding(n).
        3. Assert: status is never an abrupt completion.
        4. If n is not an element of parameterNames or if n is an element of functionNames, let initialValue be undefined.
        5. else,
          1. Let initialValue be envRec.GetBindingValue(n, false).
          2. ReturnIfAbrupt(initialValue).
        6. Call varEnvRec.InitializeBinding(n, initialValue).
        7. NOTE vars whose names are the same as a formal parameter, initially have the same value as the corresponding initialized parameter.
  29. NOTE: Annex B.3.3 adds additional steps at this point.
  30. If strict is false, then
    1. Let lexEnv be NewDeclarativeEnvironment(varEnv).
    2. NOTE: Non-strict functions use a separate lexical Environment Record for top-level lexical declarations so that a direct eval (see 12.3.4.1) can determine whether any var scoped declarations introduced by the eval code conflict with pre-existing top-level lexically scoped declarations. This is not needed for strict functions because a strict direct eval always places all declarations into a new Environment Record.
  31. Else, let lexEnv be varEnv.
  32. Let lexEnvRec be lexEnv's EnvironmentRecord.
  33. Set the LexicalEnvironment of calleeContext to lexEnv.
  34. Let lexDeclarations be the LexicallyScopedDeclarations of code.
  35. For each element d in lexDeclarations do
    1. NOTE A lexically declared name cannot be the same as a function/generator declaration, formal parameter, or a var name. Lexically declared names are only instantiated here but not initialized.
    2. For each element dn of the BoundNames of d do
      1. If IsConstantDeclaration of d is true, then
        1. Let status be lexEnvRec.CreateImmutableBinding(dn, true).
      2. Else,
        1. Let status be lexEnvRec.CreateMutableBinding(dn, false).
    3. Assert: status is never an abrupt completion.
  36. For each parsed grammar phrase f in functionsToInitialize, do
    1. Let fn be the sole element of the BoundNames of f.
    2. Let fo be the result of performing InstantiateFunctionObject for f with argument lexEnv.
    3. Let status be varEnvRec.SetMutableBinding(fn, fo, false).
    4. Assert: status is never an abrupt completion.
  37. Return NormalCompletion(empty).

NOTE 2 B.3.3 provides an extension to the above algorithm that is necessary for backwards compatibility with web browser implementations of ECMAScript that predate ECMAScript 2015.

NOTE 3 Parameter Initializers may contain direct eval expressions (12.3.4.1). Any top level declarations of such evals are only visible to the eval code (10.2). The creation of the environment for such declarations is described in 14.1.18.

9.3 Built-in Function Objects

The built-in function objects defined in this specification may be implemented as either ECMAScript function objects (9.2) whose behaviour is provided using ECMAScript code or as implementation provided exotic function objects whose behaviour is provided in some other manner. In either case, the effect of calling such functions must conform to their specifications. An implementation may also provide additional built-in function objects that are not defined in this specification.

If a built-in function object is implemented as an exotic object it must have the ordinary object behaviour specified in 9.1. All such exotic function objects also have [[Prototype]], [[Extensible]], and [[Realm]] internal slots.

Unless otherwise specified every built-in function object has the %FunctionPrototype% object (19.2.3) as the initial value of its [[Prototype]] internal slot.

The behaviour specified for each built-in function via algorithm steps or other means is the specification of the function body behaviour for both [[Call]] and [[Construct]] invocations of the function. However, [[Construct]] invocation is not supported by all built-in functions. For each built-in function, when invoked with [[Call]], the [[Call]] thisArgument provides the this value, the [[Call]] argumentsList provides the named parameters, and the NewTarget value is undefined. When invoked with [[Construct]], the this value is uninitialized, the [[Construct]] argumentsList provides the named parameters, and the [[Construct]] newTarget parameter provides the NewTarget value. If the built-in function is implemented as an ECMAScript function object then this specified behaviour must be implemented by the ECMAScript code that is the body of the function. Built-in functions that are ECMAScript function objects must be strict mode functions. If a built-in constructor has any [[Call]] behaviour other than throwing a TypeError exception, an ECMAScript implementation of the function must be done in a manner that does not cause the function's [[FunctionKind]] internal slot to have the value "classConstructor".

Built-in function objects that are not identified as constructors do not implement the [[Construct]] internal method unless otherwise specified in the description of a particular function. When a built-in constructor is called as part of a new expression the argumentsList parameter of the invoked [[Construct]] internal method provides the values for the built-in constructor's named parameters.

Built-in functions that are not constructors do not have a prototype property unless otherwise specified in the description of a particular function.

If a built-in function object is not implemented as an ECMAScript function it must provide [[Call]] and [[Construct]] internal methods that conform to the following definitions:

9.3.1 [[Call]] ( thisArgument, argumentsList)

The [[Call]] internal method for a built-in function object F is called with parameters thisArgument and argumentsList, a List of ECMAScript language values. The following steps are taken:

  1. Let callerContext be the running execution context.
  2. If callerContext is not already suspended, Suspend callerContext.
  3. Let calleeContext be a new ECMAScript code execution context.
  4. Set the Function of calleeContext to F.
  5. Let calleeRealm be the value of F’s [[Realm]] internal slot.
  6. Set the Realm of calleeContext to calleeRealm.
  7. Perform any necessary implementation defined initialization of calleeContext.
  8. Push calleeContext onto the execution context stack; calleeContext is now the running execution context.
  9. Let result be the Completion Record that is the result of evaluating F in an implementation defined manner that conforms to the specification of F. thisArgument is the this value, argumentsList provides the named parameters, and the NewTarget value is undefined.
  10. Remove calleeContext from the execution context stack and restore callerContext as the running execution context.
  11. Return result.

NOTE When calleeContext is removed from the execution context stack it must not be destroyed if it has been suspended and retained by an accessible generator object for later resumption.

9.3.2 [[Construct]] (argumentsList, newTarget)

The [[Construct]] internal method for built-in function object F is called with parameters argumentsList and newTarget. The steps performed are the same as [[Call]] (see 9.3.1) except that step 9 is replaced by:

9. Let result be the Completion Record that is the result of evaluating F in an implementation defined manner that conforms to the specification of F. The this value is uninitialized, argumentsList provides the named parameters, and newTarget provides the NewTarget value.

9.3.3 CreateBuiltinFunction(realm, steps, prototype, internalSlotsList)

The abstract operation CreateBuiltinFunction takes arguments realm, prototype, and steps. The optional argument internalSlotsList is a List of the names of additional internal slots that must be defined as part of the object. If the list is not provided, an empty List is used. CreateBuiltinFunction returns a built-in function object created by the following steps:

  1. Assert: realm is a Realm Record.
  2. Assert: steps is either a set of algorithm steps or other definition of a functions behaviour provided in this specification.
  3. Let func be a new built-in function object that when called performs the action described by steps. The new function object has internal slots whose names are the elements of internalSlotsList. The initial value of each of those internal slots is undefined.
  4. Set the [[Realm]] internal slot of func to realm.
  5. Set the [[Prototype]] internal slot of func to prototype.
  6. Return func.

Each built-in function defined in this specification is created as if by calling the CreateBuiltinFunction abstract operation, unless otherwise specified.

9.4 Built-in Exotic Object Internal Methods and Slots

This specification defines several kinds of built-in exotic objects. These objects generally behave similar to ordinary objects except for a few specific situations. The following exotic objects use the ordinary object internal methods except where it is explicitly specified otherwise below:

9.4.1 Bound Function Exotic Objects

A bound function is an exotic object that wraps another function object. A bound function is callable (it has a [[Call]] internal method and may have a [[Construct]] internal method). Calling a bound function generally results in a call of its wrapped function.

Bound function objects do not have the internal slots of ECMAScript function objects defined in Table 27. Instead they have the internal slots defined in Table 28.

Table 28 — Internal Slots of Exotic Bound Function Objects
Internal Slot Type Description
[[BoundTargetFunction]] Callable Object The wrapped function object.
[[BoundThis]] Any The value that is always passed as the this value when calling the wrapped function.
[[BoundArguments]] List of Any A list of values whose elements are used as the first arguments to any call to the wrapped function.

Unlike ECMAScript function objects, bound function objects do not use an alternative definition of the [[GetOwnProperty]] internal methods. Bound function objects provide all of the essential internal methods as specified in 9.1. However, they use the following definitions for the essential internal methods of function objects.

9.4.1.1 [[Call]] ( thisArgument, argumentsList)

When the [[Call]] internal method of an exotic bound function object, F, which was created using the bind function is called with parameters thisArgument and argumentsList, a List of ECMAScript language values, the following steps are taken:

  1. Let target be the value of F’s [[BoundTargetFunction]] internal slot.
  2. Let boundThis be the value of F’s [[BoundThis]] internal slot.
  3. Let boundArgs be the value of F’s [[BoundArguments]] internal slot.
  4. Let args be a new list containing the same values as the list boundArgs in the same order followed by the same values as the list argumentsList in the same order.
  5. Return Call(target, boundThis, args).

9.4.1.2 [[Construct]] (argumentsList, newTarget)

When the [[Construct]] internal method of an exotic bound function object, F that was created using the bind function is called with a list of arguments argumentsList and newTarget, the following steps are taken:

  1. Let target be the value of F’s [[BoundTargetFunction]] internal slot.
  2. Assert: target has a [[Construct]] internal method.
  3. Let boundArgs be the value of F’s [[BoundArguments]] internal slot.
  4. Let args be a new list containing the same values as the list boundArgs in the same order followed by the same values as the list argumentsList in the same order.
  5. If SameValue(F, newTarget) is true, let newTarget be target.
  6. Return Construct(target, args, newTarget).

9.4.1.3 BoundFunctionCreate (targetFunction, boundThis, boundArgs)

The abstract operation BoundFunctionCreate with arguments targetFunction, boundThis and boundArgs is used to specify the creation of new Bound Function exotic objects. It performs the following steps:

  1. Assert: Type(targetFunction) is Object.
  2. Let proto be targetFunction.[[GetPrototypeOf]]().
  3. ReturnIfAbrupt(proto).
  4. Let obj be a newly created object.
  5. Set obj's essential internal methods to the default ordinary object definitions specified in 9.1.
  6. Set the [[Call]] internal method of obj as described in 9.4.1.1.
  7. If targetFunction has a [[Construct]] internal method, then
    1. Set the [[Construct]] internal method of obj as described in 9.4.1.2.
  8. Set the [[Prototype]] internal slot of obj to proto.
  9. Set the [[Extensible]] internal slot of obj to true.
  10. Set the [[BoundTargetFunction]] internal slot of obj to targetFunction.
  11. Set the [[BoundThis]] internal slot of obj to the value of boundThis.
  12. Set the [[BoundArguments]] internal slot of obj to boundArgs.
  13. Return obj.

9.4.2 Array Exotic Objects

An Array object is an exotic object that gives special treatment to array index property keys (see 6.1.7). A property whose property name is an array index is also called an element. Every Array object has a length property whose value is always a nonnegative integer less than 232. The value of the length property is numerically greater than the name of every own property whose name is an array index; whenever an own property of an Array object is created or changed, other properties are adjusted as necessary to maintain this invariant. Specifically, whenever an own property is added whose name is an array index, the value of the length property is changed, if necessary, to be one more than the numeric value of that array index; and whenever the value of the length property is changed, every own property whose name is an array index whose value is not smaller than the new length is deleted. This constraint applies only to own properties of an Array object and is unaffected by length or array index properties that may be inherited from its prototypes.

NOTE A String property name P is an array index if and only if ToString(ToUint32(P)) is equal to P and ToUint32(P) is not equal to 232−1.

Array exotic objects always have a non-configurable property named "length".

Array exotic objects provide an alternative definition for the [[DefineOwnProperty]] internal method. Except for that internal method, Array exotic objects provide all of the other essential internal methods as specified in 9.1.

9.4.2.1 [[DefineOwnProperty]] ( P, Desc)

When the [[DefineOwnProperty]] internal method of an Array exotic object A is called with property key P, and Property Descriptor Desc the following steps are taken:

  1. Assert: IsPropertyKey(P) is true.
  2. If P is "length", then
    1. Return ArraySetLength(A, Desc).
  3. Else if P is an array index, then
    1. Let oldLenDesc be OrdinaryGetOwnProperty(A, "length").
    2. Assert: oldLenDesc will never be undefined or an accessor descriptor because Array objects are created with a length data property that cannot be deleted or reconfigured.
    3. Let oldLen be oldLenDesc.[[Value]].
    4. Let index be ToUint32(P).
    5. Assert: index will never be an abrupt completion.
    6. If indexoldLen and oldLenDesc.[[Writable]] is false, return false.
    7. Let succeeded be OrdinaryDefineOwnProperty(A, P, Desc).
    8. Assert: succeeded is not an abrupt completion.
    9. If succeeded is false, return false.
    10. If indexoldLen
      1. Set oldLenDesc.[[Value]] to index + 1.
      2. Let succeeded be OrdinaryDefineOwnProperty(A, "length", oldLenDesc).
      3. Assert: succeeded is true.
    11. Return true.
  4. Return OrdinaryDefineOwnProperty(A, P, Desc).

9.4.2.2 ArrayCreate(length, proto)

The abstract operation ArrayCreate with argument length (a positive integer) and optional argument proto is used to specify the creation of new Array exotic objects. It performs the following steps:

  1. Assert: length is an integer Number ≥ 0.
  2. If length is −0, let length be +0.
  3. If length>232-1, throw a RangeError exception.
  4. If the proto argument was not passed, let proto be the intrinsic object %ArrayPrototype%.
  5. Let A be a newly created Array exotic object.
  6. Set A's essential internal methods except for [[DefineOwnProperty]] to the default ordinary object definitions specified in 9.1.
  7. Set the [[DefineOwnProperty]] internal method of A as specified in 9.4.2.1.
  8. Set the [[Prototype]] internal slot of A to proto.
  9. Set the [[Extensible]] internal slot of A to true.
  10. Perform OrdinaryDefineOwnProperty(A, "length", PropertyDescriptor{[[Value]]: length, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false}).
  11. Assert: the preceding step never produces an abrupt completion.
  12. Return A.

9.4.2.3 ArraySpeciesCreate(originalArray, length)

The abstract operation ArraySpeciesCreate with arguments originalArray and length is used to specify the creation of a new Array object using a constructor function that is derived from originalArray. It performs the following steps:

  1. Assert: length is an integer Number ≥ 0.
  2. If length is −0, let length be +0.
  3. Let C be undefined.
  4. Let isArray be IsArray(originalArray).
  5. ReturnIfAbrupt(isArray).
  6. If isArray is true, then
    1. Let C be Get(originalArray, "constructor").
    2. ReturnIfAbrupt(C).
    3. If IsConstructor(C) is true, then
      1. Let thisRealm be the running execution context's Realm.
      2. Let realmC be GetFunctionRealm(C).
      3. ReturnIfAbrupt(realmC).
      4. If thisRealm and realmC are not the same Realm Record, then
        1. If SameValue(C, realmC.[[intrinsics]].[[%Array%]]) is true, let C be undefined.
    4. If Type(C) is Object, then
      1. Let C be Get(C, @@species).
      2. ReturnIfAbrupt(C).
      3. If C is null, let C be undefined.
  7. If C is undefined, return ArrayCreate(length).
  8. If IsConstructor(C) is false, throw a TypeError exception.
  9. Return Construct(C, «length»).

NOTE If originalArray was created using the standard built-in Array constructor for a Realm that is not the Realm of the running execution context, then a new Array is created using the Realm of the running execution context. This maintains compatibility with Web browsers that have historically had that behaviour for the Array.prototype methods that now are defined using ArraySpeciesCreate.

9.4.2.4 ArraySetLength(A, Desc)

When the abstract operation ArraySetLength is called with an Array exotic object A, and Property Descriptor Desc the following steps are taken:

  1. If the [[Value]] field of Desc is absent, then
    1. Return OrdinaryDefineOwnProperty(A, "length", Desc).
  2. Let newLenDesc be a copy of Desc.
  3. Let newLen be ToUint32(Desc.[[Value]]).
  4. ReturnIfAbrupt(newLen).
  5. Let numberLen be ToNumber(Desc.[[Value]]).
  6. ReturnIfAbrupt(newLen).
  7. If newLennumberLen, throw a RangeError exception.
  8. Set newLenDesc.[[Value]] to newLen.
  9. Let oldLenDesc be OrdinaryGetOwnProperty(A, "length").
  10. Assert: oldLenDesc will never be undefined or an accessor descriptor because Array objects are created with a length data property that cannot be deleted or reconfigured.
  11. Let oldLen be oldLenDesc.[[Value]].
  12. If newLenoldLen, then
    1. Return OrdinaryDefineOwnProperty(A, "length", newLenDesc).
  13. If oldLenDesc.[[Writable]] is false, return false.
  14. If newLenDesc.[[Writable]] is absent or has the value true, let newWritable be true.
  15. Else,
    1. Need to defer setting the [[Writable]] attribute to false in case any elements cannot be deleted.
    2. Let newWritable be false.
    3. Set newLenDesc.[[Writable]] to true.
  16. Let succeeded be OrdinaryDefineOwnProperty(A, "length", newLenDesc).
  17. Assert: succeeded is not an abrupt completion.
  18. If succeeded is false, return false.
  19. While newLen < oldLen repeat,
    1. Set oldLen to oldLen – 1.
    2. Let deleteSucceeded be A.[[Delete]](ToString(oldLen)).
    3. Assert: deleteSucceeded is not an abrupt completion.
    4. If deleteSucceeded is false, then
      1. Set newLenDesc.[[Value]] to oldLen + 1.
      2. If newWritable is false, set newLenDesc.[[Writable]] to false.
      3. Let succeeded be OrdinaryDefineOwnProperty(A, "length", newLenDesc).
      4. Assert: succeeded is not an abrupt completion.
      5. Return false.
  20. If newWritable is false, then
    1. Return OrdinaryDefineOwnProperty(A, "length", PropertyDescriptor{[[Writable]]: false}). This call will always return true.
  21. Return true.

NOTE In steps 3 and 4, if Desc.[[Value]] is an object then its valueOf method is called twice. This is legacy behaviour that was specified with this effect starting with the 2nd Edition of this specification.

9.4.3 String Exotic Objects

A String object is an exotic object that encapsulates a String value and exposes virtual integer indexed data properties corresponding to the individual code unit elements of the String value. Exotic String objects always have a data property named "length" whose value is the number of code unit elements in the encapsulated String value. Both the code unit data properties and the "length" property are non-writable and non-configurable.

Exotic String objects have the same internal slots as ordinary objects. They also have a [[StringData]] internal slot.

Exotic String objects provide alternative definitions for the following internal methods. All of the other exotic String object essential internal methods that are not defined below are as specified in 9.1.

9.4.3.1 [[GetOwnProperty]] ( P )

When the [[GetOwnProperty]] internal method of an exotic String object S is called with property key P the following steps are taken:

  1. Assert: IsPropertyKey(P) is true.
  2. Let desc be OrdinaryGetOwnProperty(S, P).
  3. If desc is not undefined return desc.
  4. Return StringGetIndexProperty(S, P).

9.4.3.1.1 StringGetIndexProperty (S, P)

When the abstract operation StringGetIndexProperty is called with an exotic String object S and with property key P, the following steps are taken:

  1. If Type(P) is not String, return undefined.
  2. Let index be CanonicalNumericIndexString (P).
  3. Assert: index is not an abrupt completion.
  4. If index is undefined, return undefined.
  5. If IsInteger(index) is false, return undefined.
  6. If index = −0, return undefined.
  7. Let str be the String value of the [[StringData]] internal slot of S.
  8. Let len be the number of elements in str.
  9. If index < 0 or lenindex, return undefined.
  10. Let resultStr be a String value of length 1, containing one code unit from str, specifically the code unit at index index.
  11. Return a PropertyDescriptor{ [[Value]]: resultStr, [[Enumerable]]: true, [[Writable]]: false, [[Configurable]]: false }.

9.4.3.2 [[HasProperty]](P)

When the [[HasProperty]] internal method of an exotic String object S is called with property key P, the following steps are taken:

  1. Let elementDesc be StringGetIndexProperty(S, P).
  2. If elementDesc is not undefined, return true.
  3. Return OrdinaryHasProperty(S, P)..

9.4.3.3 [[OwnPropertyKeys]] ( )

When the [[OwnPropertyKeys]] internal method of a String exotic object O is called the following steps are taken:

  1. Let keys be a new empty List.
  2. Let str be the String value of the [[StringData]] internal slot of O.
  3. Let len be the number of elements in str.
  4. For each integer i starting with 0 such that i < len, in ascending order,
    1. Add ToString(i) as the last element of keys
  5. For each own property key P of O such that P is an integer index and ToInteger(P) ≥ len, in ascending numeric index order,
    1. Add P as the last element of keys.
  6. For each own property key P of O such that Type(P) is String and P is not an integer index, in property creation order,
    1. Add P as the last element of keys.
  7. For each own property key P of O such that Type(P) is Symbol, in property creation order,
    1. Add P as the last element of keys.
  8. Return keys.

9.4.3.4 StringCreate( value, prototype)

The abstract operation StringCreate with arguments value and prototype is used to specify the creation of new exotic String objects. It performs the following steps:

  1. ReturnIfAbrupt(prototype).
  2. Assert: Type(value) is String.
  3. Let S be a newly created String exotic object.
  4. Set the [[StringData]] internal slot of S to value.
  5. Set S's essential internal methods to the default ordinary object definitions specified in 9.1.
  6. Set the [[GetOwnProperty]] internal method of S as specified in 9.4.3.1.
  7. Set the [[HasProperty]] internal method of S as specified in 9.4.3.2.
  8. Set the [[OwnPropertyKeys]] internal method of S as specified in 9.4.3.3.
  9. Set the [[Prototype]] internal slot of S to prototype.
  10. Set the [[Extensible]] internal slot of S to true.
  11. Let length be the number of code unit elements in value.
  12. Let status be DefinePropertyOrThrow(S, "length", PropertyDescriptor{[[Value]]: length, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }).
  13. Assert: status is not an abrupt completion.
  14. Return S.

9.4.4 Arguments Exotic Objects

Most ECMAScript functions make an arguments objects available to their code. Depending upon the characteristics of the function definition, its argument object is either an ordinary object or an arguments exotic object. An arguments exotic object is an exotic object whose array index properties map to the formal parameters bindings of an invocation of its associated ECMAScript function.

Arguments exotic objects have the same internal slots as ordinary objects. They also have a [[ParameterMap]] internal slot. Ordinary arguments objects also have a [[ParameterMap]] internal slot whose value is always undefined. For ordinary argument objects the [[ParameterMap]] internal slot is only used by Object.prototype.toString (19.1.3.6) to identify them as such.

Arguments exotic objects provide alternative definitions for the following internal methods. All of the other exotic arguments object essential internal methods that are not defined below are as specified in 9.1

NOTE 1 For non-strict functions the integer indexed data properties of an arguments object whose numeric name values are less than the number of formal parameters of the corresponding function object initially share their values with the corresponding argument bindings in the function's execution context. This means that changing the property changes the corresponding value of the argument binding and vice-versa. This correspondence is broken if such a property is deleted and then redefined or if the property is changed into an accessor property. For strict mode functions, the values of the arguments object's properties are simply a copy of the arguments passed to the function and there is no dynamic linkage between the property values and the formal parameter values.

NOTE 2 The ParameterMap object and its property values are used as a device for specifying the arguments object correspondence to argument bindings. The ParameterMap object and the objects that are the values of its properties are not directly observable from ECMAScript code. An ECMAScript implementation does not need to actually create or use such objects to implement the specified semantics.

NOTE 3 Arguments objects for strict mode functions define non-configurable accessor properties named "caller" and "callee" which throw a TypeError exception on access. The "callee" property has a more specific meaning for non-strict functions and a "caller" property has historically been provided as an implementation-defined extension by some ECMAScript implementations. The strict mode definition of these properties exists to ensure that neither of them is defined in any other manner by conforming ECMAScript implementations.

9.4.4.1 [[GetOwnProperty]] (P)

The [[GetOwnProperty]] internal method of an arguments exotic object when called with a property key P performs the following steps:

  1. Let args be the arguments object.
  2. Let desc be OrdinaryGetOwnProperty(args, P).
  3. If desc is undefined, return desc.
  4. Let map be the value of the [[ParameterMap]] internal slot of the arguments object.
  5. Let isMapped be HasOwnProperty(map, P).
  6. Assert: isMapped is never an abrupt completion.
  7. If the value of isMapped is true, then
    1. Set desc.[[Value]] to Get(map, P).
  8. If IsDataDescriptor(desc) is true and P is "caller" and desc.[[Value]] is a strict mode Function object, throw a TypeError exception.
  9. Return desc.

If an implementation does not provide a built-in caller property for argument exotic objects then step 8 of this algorithm is must be skipped.

9.4.4.2 [[DefineOwnProperty]] (P, Desc)

The [[DefineOwnProperty]] internal method of an arguments exotic object when called with a property key P and Property Descriptor Desc performs the following steps:

  1. Let args be the arguments object.
  2. Let map be the value of the [[ParameterMap]] internal slot of the arguments object.
  3. Let isMapped be HasOwnProperty(map, P).
  4. Let allowed be OrdinaryDefineOwnProperty(args, P, Desc).
  5. ReturnIfAbrupt(allowed).
  6. If allowed is false, return false.
  7. If the value of isMapped is true, then
    1. If IsAccessorDescriptor(Desc) is true, then
      1. Call map.[[Delete]](P).
    2. Else
      1. If Desc.[[Value]] is present, then
        1. Let setStatus be Set(map, P, Desc.[[Value]], false).
        2. Assert: setStatus is true because formal parameters mapped by argument objects are always writable.
      2. If Desc.[[Writable]] is present and its value is false, then
        1. Call map.[[Delete]](P).
  8. Return true.

9.4.4.3 [[Get]] (P, Receiver)

The [[Get]] internal method of an arguments exotic object when called with a property key P and ECMAScript language value Receiver performs the following steps:

  1. Let args be the arguments object.
  2. Let map be the value of the [[ParameterMap]] internal slot of the arguments object.
  3. Let isMapped be HasOwnProperty(map, P).
  4. Assert: isMapped is not an abrupt completion.
  5. If the value of isMapped is false, then
    1. Return the result of calling the default ordinary object [[Get]] internal method (9.1.8) on args passing P and Receiver as the arguments.
  6. Else map contains a formal parameter mapping for P,
    1. Return Get(map, P).

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

The [[Set]] internal method of an arguments exotic object when called with property key P, value V, and ECMAScript language value Receiver performs the following steps:

  1. Let args be the arguments object.
  2. If SameValue(args, Receiver) is false, then
    1. Let isMapped be false.
  3. Else,
    1. Let map be the value of the [[ParameterMap]] internal slot of the arguments object.
    2. Let isMapped be HasOwnProperty(map, P).
    3. Assert: isMapped is not an abrupt completion.
  4. If isMapped is true, then
    1. Let setStatus be Set(map, P, V, false).
    2. Assert: setStatus is true because formal parameters mapped by argument objects are always writable.
  5. Return the result of calling the default ordinary object [[Set]] internal method (9.1.9) on args passing P, V and Receiver as the arguments.

9.4.4.5 [[Delete]] (P)

The [[Delete]] internal method of an arguments exotic object when called with a property key P performs the following steps:

  1. Let map be the value of the [[ParameterMap]] internal slot of the arguments object.
  2. Let isMapped be HasOwnProperty(map, P).
  3. Assert: isMapped is not an abrupt completion.
  4. Let result be the result of calling the default [[Delete]] internal method for ordinary objects (9.1.10) on the arguments object passing P as the argument.
  5. ReturnIfAbrupt(result).
  6. If result is true and the value of isMapped is true, then
    1. Call map.[[Delete]](P).
  7. Return result.

9.4.4.6 CreateUnmappedArgumentsObject(argumentsList)

The abstract operation CreateUnmappedArgumentsObject called with an argument argumentsList performs the following steps:

  1. Let len be the number of elements in argumentsList.
  2. Let obj be ObjectCreate(%ObjectPrototype%, «‍[[ParameterMap]]»).
  3. Set obj's [[ParameterMap]] internal slot to undefined.
  4. Perform DefinePropertyOrThrow(obj, "length", PropertyDescriptor{[[Value]]: len, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true}).
  5. Let index be 0.
  6. Repeat while index < len,
    1. Let val be argumentsList[index].
    2. Perform CreateDataProperty(obj, ToString(index), val).
    3. Let index be index + 1
  7. Perform DefinePropertyOrThrow(obj, @@iterator, PropertyDescriptor {[[Value]]:%ArrayProto_values%, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true}).
  8. Perform DefinePropertyOrThrow(obj, "caller", PropertyDescriptor {[[Get]]: %ThrowTypeError%, [[Set]]: %ThrowTypeError%, [[Enumerable]]: false, [[Configurable]]: false}).
  9. Perform DefinePropertyOrThrow(obj, "callee", PropertyDescriptor {[[Get]]: %ThrowTypeError%, [[Set]]: %ThrowTypeError%, [[Enumerable]]: false, [[Configurable]]: false}).
  10. Assert: the above property definitions will not produce an abrupt completion.
  11. Return obj

9.4.4.7 CreateMappedArgumentsObject ( func, formals, argumentsList, env )

The abstract operation CreateMappedArgumentsObject is called with object func, parsed grammar phrase formals, List argumentsList, and Environment Record env. The following steps are performed:

  1. Assert: formals does not contain a rest parameter, any binding patterns, or any initializers. It may contain duplicate identifiers.
  2. Let len be the number of elements in argumentsList.
  3. Let obj be a newly created arguments exotic object with a [[ParameterMap]] internal slot.
  4. Set the [[GetOwnProperty]] internal method of obj as specified in 9.4.4.1.
  5. Set the [[DefineOwnProperty]] internal method of obj as specified in 9.4.4.2.
  6. Set the [[Get]] internal method of obj as specified in 9.4.4.3.
  7. Set the [[Set]] internal method of obj as specified in 9.4.4.4.
  8. Set the [[Delete]] internal method of obj as specified in 9.4.4.5.
  9. Set the remainder of obj's essential internal methods to the default ordinary object definitions specified in 9.1.
  10. Set the [[Prototype]] internal slot of obj to %ObjectPrototype%.
  11. Set the [[Extensible]] internal slot of obj to true.
  12. Let parameterNames be the BoundNames of formals.
  13. Let numberOfParameters be the number of elements in parameterNames
  14. Let index be 0.
  15. Repeat while index < len ,
    1. Let val be argumentsList[index].
    2. Perform CreateDataProperty(obj, ToString(index), val).
    3. Let index be index + 1
  16. Perform DefinePropertyOrThrow(obj, "length", PropertyDescriptor{[[Value]]: len, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true}).
  17. Let map be ObjectCreate(null).
  18. Let mappedNames be an empty List.
  19. Let index be numberOfParameters − 1.
  20. Repeat while index ≥ 0 ,
    1. Let name be parameterNames[index].
    2. If name is not an element of mappedNames, then
      1. Add name as an element of the list mappedNames.
      2. If index < len, then
        1. Let g be MakeArgGetter(name, env).
        2. Let p be MakeArgSetter(name, env).
        3. Call map.[[DefineOwnProperty]](ToString(index), PropertyDescriptor{[[Set]]: p, [[Get]]: g, [[Enumerable]]: false, [[Configurable]]: true}).
    3. Let index be index − 1
  21. Set the [[ParameterMap]] internal slot of obj to map.
  22. Perform DefinePropertyOrThrow(obj, @@iterator, PropertyDescriptor {[[Value]]:%ArrayProto_values%, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true}).
  23. Perform DefinePropertyOrThrow(obj, "callee", PropertyDescriptor {[[Value]]: func, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true}).
  24. Assert: the above property definitions will not produce an abrupt completion.
  25. Return obj

9.4.4.7.1 MakeArgGetter ( name, env)

The abstract operation MakeArgGetter called with String name and Environment Record env creates a built-in function object that when executed returns the value bound for name in env. It performs the following steps:

  1. Let realm be the current Realm.
  2. Let steps be the steps of an ArgGetter function as specified below.
  3. Let getter be CreateBuiltinFunction(realm, steps, %FunctionPrototype%, «‍[[name]], [[env]]» ).
  4. Set getter’s [[name]] internal slot to name.
  5. Set getter’s [[env]] internal slot to env.
  6. Return getter.

An ArgGetter function is an anonymous built-in function with [[name]] and [[env]] internal slots. When an ArgGetter function f that expects no arguments is called it performs the following steps:

  1. Let name be the value of f’s [[name]] internal slot.
  2. Let env be the value of f’s [[env]] internal slot
  3. Return env.GetBindingValue(name, false).

NOTE ArgGetter functions are never directly accessible to ECMAScript code.

9.4.4.7.2 MakeArgSetter ( name, env)

The abstract operation MakeArgSetter called with String name and Environment Record env creates a built-in function object that when executed sets the value bound for name in env. It performs the following steps:

  1. Let realm be the current Realm.
  2. Let steps be the steps of an ArgSetter function as specified below.
  3. Let setter be CreateBuiltinFunction(realm, steps, %FunctionPrototype%, «‍[[name]], [[env]]» ).
  4. Set setter’s [[name]] internal slot to name.
  5. Set setter’s [[env]] internal slot to env.
  6. Return setter.

An ArgSetter function is an anonymous built-in function with [[name]] and [[env]] internal slots. When an ArgSetter function f is called with argument value it performs the following steps:

  1. Let name be the value of f’s [[name]] internal slot.
  2. Let env be the value of f’s [[env]] internal slot
  3. Return env.SetMutableBinding(name, value, false).

NOTE ArgSetter functions are never directly accessible to ECMAScript code.

9.4.5 Integer Indexed Exotic Objects

An Integer Indexed object is an exotic object that performs special handling of integer index property keys.

Integer Indexed exotic objects have the same internal slots as ordinary objects additionally [[ViewedArrayBuffer]], [[ArrayLength]], [[ByteOffset]], and [[TypedArrayName]] internal slots.

Integer Indexed Exotic objects provide alternative definitions for the following internal methods. All of the other Integer Indexed exotic object essential internal methods that are not defined below are as specified in 9.1.

9.4.5.1 [[GetOwnProperty]] ( P )

When the [[GetOwnProperty]] internal method of an Integer Indexed exotic object O is called with property key P the following steps are taken:

  1. Assert: IsPropertyKey(P) is true.
  2. Assert: O is an Object that has a [[ViewedArrayBuffer]] internal slot.
  3. If Type(P) is String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. Assert: numericIndex is not an abrupt completion.
    3. If numericIndex is not undefined, then
      1. Let value be IntegerIndexedElementGet (O, numericIndex).
      2. ReturnIfAbrupt(value).
      3. If value is undefined, return undefined.
      4. Return a PropertyDescriptor{ [[Value]]: value, [[Enumerable]]: true, [[Writable]]: true, [[Configurable]]: false }.
  4. Return OrdinaryGetOwnProperty(O, P).

9.4.5.2 [[HasProperty]](P)

When the [[HasProperty]] internal method of an Integer Indexed exotic object O is called with property key P, the following steps are taken:

  1. Assert: IsPropertyKey(P) is true.
  2. Assert: O is an Object that has a [[ViewedArrayBuffer]] internal slot.
  3. If Type(P) is String, then
    1. Let numericIndex be CanonicalNumericIndexString(P).
    2. Assert: numericIndex is not an abrupt completion.
    3. If numericIndex is not undefined, then
      1. Let buffer be the value of O's [[ViewedArrayBuffer]] internal slot.
      2. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
      3. If IsInteger(numericIndex) is false, return false
      4. If numericIndex = −0, return false.
      5. If numericIndex < 0, return false.
      6. If numericIndex ≥ the value of O's [[ArrayLength]] internal slot, return false.
      7. Return true.
  4. Return OrdinaryHasProperty(O, P).

9.4.5.3 [[DefineOwnProperty]] ( P, Desc)

When the [[DefineOwnProperty]] internal method of an Integer Indexed exotic object O is called with property key P, and Property Descriptor Desc the following steps are taken:

  1. Assert: IsPropertyKey(P) is true.
  2. Assert: O is an Object that has a [[ViewedArrayBuffer]] internal slot.
  3. If Type(P) is String, then
    1. Let numericIndex be CanonicalNumericIndexString (P).
    2. Assert: numericIndex is not an abrupt completion.
    3. If numericIndex is not undefined, then
      1. If IsInteger(numericIndex) is false, return false
      2. Let intIndex be numericIndex.
      3. If intIndex = −0, return false.
      4. If intIndex < 0, return false.
      5. Let length be the value of O's [[ArrayLength]] internal slot.
      6. If intIndexlength, return false.
      7. If IsAccessorDescriptor(Desc) is true, return false.
      8. If Desc has a [[Configurable]] field and if Desc.[[Configurable]] is true, return false.
      9. If Desc has an [[Enumerable]] field and if Desc.[[Enumerable]] is false, return false.
      10. If Desc has a [[Writable]] field and if Desc.[[Writable]] is false, return false.
      11. If Desc has a [[Value]] field, then
        1. Let value be Desc.[[Value]].
        2. Return IntegerIndexedElementSet (O, intIndex, value).
      12. Return true.
  4. Return OrdinaryDefineOwnProperty(O, P, Desc).

9.4.5.4 [[Get]] (P, Receiver)

When the [[Get]] internal method of an Integer Indexed exotic object O is called with property key P and ECMAScript language value Receiver the following steps are taken:

  1. Assert: IsPropertyKey(P) is true.
  2. If Type(P) is String and if SameValue(O, Receiver) is true, then
    1. Let numericIndex be CanonicalNumericIndexString (P).
    2. Assert: numericIndex is not an abrupt completion.
    3. If numericIndex is not undefined, then
      1. Return IntegerIndexedElementGet (O, numericIndex).
  3. Return the result of calling the default ordinary object [[Get]] internal method (9.1.8) on O passing P and Receiver as arguments.

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

When the [[Set]] internal method of an Integer Indexed exotic object O is called with property key P, value V, and ECMAScript language value Receiver, the following steps are taken:

  1. Assert: IsPropertyKey(P) is true.
  2. If Type(P) is String and if SameValue(O, Receiver) is true, then
    1. Let numericIndex be CanonicalNumericIndexString (P).
    2. Assert: numericIndex is not an abrupt completion.
    3. If numericIndex is not undefined, then
      1. Return IntegerIndexedElementSet (O, numericIndex, V).
  3. Return the result of calling the default ordinary object [[Set]] internal method (9.1.8) on O passing P, V, and Receiver as arguments.

9.4.5.6 [[OwnPropertyKeys]] ()

When the [[OwnPropertyKeys]] internal method of an Integer Indexed exotic object O is called the following steps are taken:

  1. Let keys be a new empty List.
  2. Assert: O is an Object that has [[ViewedArrayBuffer]], [[ArrayLength]], [[ByteOffset]], and [[TypedArrayName]] internal slots.
  3. Let len be the value of O's [[ArrayLength]] internal slot.
  4. For each integer i starting with 0 such that i < len, in ascending order,
    1. Add ToString(i) as the last element of keys.
  5. For each own property key P of O such that Type(P) is String and P is not an integer index, in property creation order
    1. Add P as the last element of keys.
  6. For each own property key P of O such that Type(P) is Symbol, in property creation order
    1. Add P as the last element of keys.
  7. Return keys.

9.4.5.7 IntegerIndexedObjectCreate (prototype, internalSlotsList)

The abstract operation IntegerIndexedObjectCreate with arguments prototype and internalSlotsList is used to specify the creation of new Integer Indexed exotic objects. The argument internalSlotsList is a List of the names of additional internal slots that must be defined as part of the object. IntegerIndexedObjectCreate performs the following steps:

  1. Let A be a newly created object with an internal slot for each name in internalSlotsList.
  2. Set A's essential internal methods to the default ordinary object definitions specified in 9.1.
  3. Set the [[GetOwnProperty]] internal method of A as specified in 9.4.5.1.
  4. Set the [[HasProperty]] internal method of A as specified in 9.4.5.2.
  5. Set the [[DefineOwnProperty]] internal method of A as specified in 9.4.5.3.
  6. Set the [[Get]] internal method of A as specified in 9.4.5.4.
  7. Set the [[Set]] internal method of A as specified in 9.4.5.5.
  8. Set the [[OwnPropertyKeys]] internal method of A as specified in 9.4.5.6.
  9. Set the [[Prototype]] internal slot of A to prototype.
  10. Set the [[Extensible]] internal slot of A to true.
  11. Return A.

9.4.5.8 IntegerIndexedElementGet ( O, index )

The abstract operation IntegerIndexedElementGet with arguments O and index performs the following steps:

  1. Assert: Type(index) is Number.
  2. Assert: O is an Object that has [[ViewedArrayBuffer]], [[ArrayLength]], [[ByteOffset]], and [[TypedArrayName]] internal slots.
  3. Let buffer be the value of O's [[ViewedArrayBuffer]] internal slot.
  4. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
  5. If IsInteger(index) is false, return undefined
  6. If index = −0, return undefined.
  7. Let length be the value of O's [[ArrayLength]] internal slot.
  8. If index < 0 or indexlength, return undefined.
  9. Let offset be the value of O's [[ByteOffset]] internal slot.
  10. Let arrayTypeName be the String value of O's [[TypedArrayName]] internal slot.
  11. Let elementSize be the Number value of the Element Size value specified in Table 49 for arrayTypeName.
  12. Let indexedPosition = (index × elementSize) + offset.
  13. Let elementType be the String value of the Element Type value in Table 49 for arrayTypeName.
  14. Return GetValueFromBuffer(buffer, indexedPosition, elementType).

9.4.5.9 IntegerIndexedElementSet ( O, index, value )

The abstract operation IntegerIndexedElementSet with arguments O, index, and value performs the following steps:

  1. Assert: Type(index) is Number.
  2. Assert: O is an Object that has [[ViewedArrayBuffer]], [[ArrayLength]], [[ByteOffset]], and [[TypedArrayName]] internal slots.
  3. Let numValue be ToNumber(value).
  4. ReturnIfAbrupt(numValue).
  5. Let buffer be the value of O's [[ViewedArrayBuffer]] internal slot.
  6. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
  7. If IsInteger(index) is false, return false
  8. If index = −0, return false.
  9. Let length be the value of O's [[ArrayLength]] internal slot.
  10. If index < 0 or indexlength, return false.
  11. Let offset be the value of O's [[ByteOffset]] internal slot.
  12. Let arrayTypeName be the String value of O's [[TypedArrayName]] internal slot.
  13. Let elementSize be the Number value of the Element Size value specified in Table 49 for arrayTypeName.
  14. Let indexedPosition = (index × elementSize) + offset.
  15. Let elementType be the String value of the Element Type value in Table 49 for arrayTypeName.
  16. Perform SetValueInBuffer(buffer, indexedPosition, elementType, numValue).
  17. Return true.

9.4.6 Module Namespace Exotic Objects

A module namespace object is an exotic object that exposes the bindings exported from an ECMAScript Module (See 15.2.3). There is a one-to-one correspondence between the String-keyed own properties of a module namespace exotic object and the binding names exported by the Module. The exported bindings include any bindings that are indirectly exported using export * export items. Each String-valued own property key is the StringValue of the corresponding exported binding name. These are the only String-keyed properties of a module namespace exotic object. Each such property has the attributes {[[Configurable]]: false, [[Enumerable]]: true}. Module namespace objects are not extensible.

Module namespace objects have the internal slots defined in Table 29.

Table 29 — Internal Slots of Module Namespace Exotic Objects
Internal Slot Type Description
[[Module]] Module Record The Module Record whose exports this namespace exposes.
[[Exports]] List of String A List containing the String values of the exported names exposed as own properties of this object. The list is ordered as if an Array of those String values had been sorted using Array.prototype.sort using SortCompare as comparefn.

Module namespace exotic objects provide alternative definitions for all of the internal methods.

9.4.6.1 [[GetPrototypeOf]] ( )

When the [[GetPrototypeOf]] internal method of a module namespace exotic object O is called the following steps are taken:

  1. Return null.

9.4.6.2 [[SetPrototypeOf]] (V)

When the [[SetPrototypeOf]] internal method of a module namespace exotic object O is called with argument V the following steps are taken:

  1. Assert: Either Type(V) is Object or Type(V) is Null.
  2. Return false.

9.4.6.3 [[IsExtensible]] ( )

When the [[IsExtensible]] internal method of a module namespace exotic object O is called the following steps are taken:

  1. Return false.

9.4.6.4 [[PreventExtensions]] ( )

When the [[PreventExtensions]] internal method of a module namespace exotic object O is called the following steps are taken:

  1. Return true.

9.4.6.5 [[GetOwnProperty]] (P)

When the [[GetOwnProperty]] internal method of a module namespace exotic object O is called with property key P, the following steps are taken:

  1. If Type(P) is Symbol, return OrdinaryGetOwnProperty(O, P).
  2. Let exports be the value of O's [[Exports]] internal slot.
  3. If P is not an element of exports, return undefined.
  4. Let value be O.[[Get]](P, O).
  5. ReturnIfAbrupt(value).
  6. Return PropertyDescriptor{[[Value]]: value, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: false }.

9.4.6.6 [[DefineOwnProperty]] (P, Desc)

When the [[DefineOwnProperty]] internal method of a module namespace exotic object O is called with property key P and Property Descriptor Desc, the following steps are taken:

  1. Return false.

9.4.6.7 [[HasProperty]] (P)

When the [[HasProperty]] internal method of a module namespace exotic object O is called with property key P, the following steps are taken:

  1. If Type(P) is Symbol, return OrdinaryHasProperty(O, P).
  2. Let exports be the value of O's [[Exports]] internal slot.
  3. If P is an element of exports, return true.
  4. Return false.

9.4.6.8 [[Get]] (P, Receiver)

When the [[Get]] internal method of a module namespace exotic object O is called with property key P and ECMAScript language value Receiver the following steps are taken:

  1. Assert: IsPropertyKey(P) is true.
  2. If Type(P) is Symbol, then
    1. Return the result of calling the default ordinary object [[Get]] internal method (9.1.8) on O passing P and Receiver as arguments.
  3. Let exports be the value of O's [[Exports]] internal slot.
  4. If P is not an element of exports, return undefined.
  5. Let m be the value of O's [[Module]] internal slot.
  6. Let binding be m.ResolveExport(P, «», «»).
  7. ReturnIfAbrupt(binding).
  8. Assert: binding is neither null nor "ambiguous".
  9. Let targetModule be binding.[[module]],
  10. Assert: targetModule is not undefined.
  11. Let targetEnv be targetModule.[[Environment]].
  12. If targetEnv is undefined, throw a ReferenceError exception.
  13. Let targetEnvRec be targetEnv's EnvironmentRecord.
  14. Return targetEnvRec.GetBindingValue(binding.[[bindingName]], true).

NOTE ResolveExport is idempotent and side-effect free. An implementation might choose to pre-compute or cache the ResolveExport results for the [[Exports]] of each module namespace exotic object.

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

When the [[Set]] internal method of a module namespace exotic object O is called with property key P, value V, and ECMAScript language value Receiver, the following steps are taken:

  1. Return false.

9.4.6.10 [[Delete]] (P)

When the [[Delete]] internal method of a module namespace exotic object O is called with property key P the following steps are taken:

  1. Assert: IsPropertyKey(P) is true.
  2. Let exports be the value of O's [[Exports]] internal slot.
  3. If P is an element of exports, return false.
  4. Return true.

9.4.6.11 [[Enumerate]] ()

When the [[Enumerate]] internal method of a module namespace exotic object O is called the following steps are taken:

  1. Let exports be the value of O's [[Exports]] internal slot.
  2. Return CreateListIterator(exports).

9.4.6.12 [[OwnPropertyKeys]] ( )

When the [[OwnPropertyKeys]] internal method of a module namespace exotic object O is called the following steps are taken:

  1. Let exports be a copy of the value of O's [[Exports]] internal slot.
  2. Let symbolKeys be the result of calling the default ordinary object [[OwnPropertyKeys]] internal method (9.1.12) on O passing no arguments.
  3. Append all the entries of symbolKeys to the end of exports.
  4. Return exports.

9.4.6.13 ModuleNamespaceCreate (module, exports)

The abstract operation ModuleNamespaceCreate with arguments module, and exports is used to specify the creation of new module namespace exotic objects. It performs the following steps:

  1. Assert: module is a Module Record (see 15.2.1.15).
  2. Assert: module.[[Namespace]] is undefined.
  3. Assert: exports is a List of String values.
  4. Let M be a newly created object.
  5. Set M's essential internal methods to the definitions specified in 9.4.6.
  6. Set M's [[Module]] internal slot to module.
  7. Set M's [[Exports]] internal slot to exports.
  8. Create own properties of M corresponding to the definitions in 26.3.
  9. Set module.[[Namespace]] to M.
  10. Return M.

9.5 Proxy Object Internal Methods and Internal Slots

A proxy object is an exotic object whose essential internal methods are partially implemented using ECMAScript code. Every proxy objects has an internal slot called [[ProxyHandler]]. The value of [[ProxyHandler]] is an object, called the proxy's handler object, or null. Methods (see Table 30) of a handler object may be used to augment the implementation for one or more of the proxy object's internal methods. Every proxy object also has an internal slot called [[ProxyTarget]] whose value is either an object or the null value. This object is called the proxy's target object.

Table 30 — Proxy Handler Methods
Internal Method Handler Method
[[GetPrototypeOf]] getPrototypeOf
[[SetPrototypeOf]] setPrototypeOf
[[IsExtensible]] isExtensible
[[PreventExtensions]] preventExtensions
[[GetOwnProperty]] getOwnPropertyDescriptor
[[HasProperty]] has
[[Get]] get
[[Set]] set
[[Delete]] deleteProperty
[[DefineOwnProperty]] defineProperty
[[Enumerate]] enumerate
[[OwnPropertyKeys]] ownKeys
[[Call]] apply
[[Construct]] construct

When a handler method is called to provide the implementation of a proxy object internal method, the handler method is passed the proxy's target object as a parameter. A proxy's handler object does not necessarily have a method corresponding to every essential internal method. Invoking an internal method on the proxy results in the invocation of the corresponding internal method on the proxy's target object if the handler object does not have a method corresponding to the internal trap.

The [[ProxyHandler]] and [[ProxyTarget]] internal slots of a proxy object are always initialized when the object is created and typically may not be modified. Some proxy objects are created in a manner that permits them to be subsequently revoked. When a proxy is revoked, its [[ProxyHander]] and [[ProxyTarget]] internal slots are set to null causing subsequent invocations of internal methods on that proxy object to throw a TypeError exception.

Because proxy objects permit the implementation of internal methods to be provided by arbitrary ECMAScript code, it is possible to define a proxy object whose handler methods violates the invariants defined in 6.1.7.3. Some of the internal method invariants defined in 6.1.7.3 are essential integrity invariants. These invariants are explicitly enforced by the proxy object internal methods specified in this section. An ECMAScript implementation must be robust in the presence of all possible invariant violations.

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

9.5.1 [[GetPrototypeOf]] ( )

When the [[GetPrototypeOf]] internal method of a Proxy exotic object O is called the following steps are taken:

  1. Let handler be the value of the [[ProxyHandler]] internal slot of O.
  2. If handler is null, throw a TypeError exception.
  3. Assert: Type(handler) is Object.
  4. Let target be the value of the [[ProxyTarget]] internal slot of O.
  5. Let trap be GetMethod(handler, "getPrototypeOf").
  6. ReturnIfAbrupt(trap).
  7. If trap is undefined, then
    1. Return target.[[GetPrototypeOf]]().
  8. Let handlerProto be Call(trap, handler, «target»).
  9. ReturnIfAbrupt(handlerProto).
  10. If Type(handlerProto) is neither Object nor Null, throw a TypeError exception.
  11. Let extensibleTarget be IsExtensible(target).
  12. ReturnIfAbrupt(extensibleTarget).
  13. If extensibleTarget is true, return handlerProto.
  14. Let targetProto be target.[[GetPrototypeOf]]().
  15. ReturnIfAbrupt(targetProto).
  16. If SameValue(handlerProto, targetProto) is false, throw a TypeError exception.
  17. Return handlerProto.

NOTE [[GetPrototypeOf]] for proxy objects enforces the following invariant:

  • The result of [[GetPrototypeOf]] must be either an Object or null.

  • If the target object is not extensible, [[GetPrototypeOf]] applied to the proxy object must return the same value as [[GetPrototypeOf]] applied to the proxy object's target object.

9.5.2 [[SetPrototypeOf]] (V)

When the [[SetPrototypeOf]] internal method of a Proxy exotic object O is called with argument V the following steps are taken:

  1. Assert: Either Type(V) is Object or Type(V) is Null.
  2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
  3. If handler is null, throw a TypeError exception.
  4. Assert: Type(handler) is Object.
  5. Let target be the value of the [[ProxyTarget]] internal slot of O.
  6. Let trap be GetMethod(handler, "setPrototypeOf").
  7. ReturnIfAbrupt(trap).
  8. If trap is undefined, then
    1. Return target.[[SetPrototypeOf]](V).
  9. Let booleanTrapResult be ToBoolean(Call(trap, handler, «target, V»)).
  10. ReturnIfAbrupt(booleanTrapResult).
  11. Let extensibleTarget be IsExtensible(target).
  12. ReturnIfAbrupt(extensibleTarget).
  13. If extensibleTarget is true, return booleanTrapResult.
  14. Let targetProto be target.[[GetPrototypeOf]]().
  15. ReturnIfAbrupt(targetProto).
  16. If booleanTrapResult is true and SameValue(V, targetProto) is false, throw a TypeError exception.
  17. Return booleanTrapResult.

NOTE [[SetPrototypeOf]] for proxy objects enforces the following invariant:

  • The result of [[SetPrototypeOf]] is a Boolean value.

  • If the target object is not extensible, the argument value must be the same as the result of [[GetPrototypeOf]] applied to target object.

9.5.3 [[IsExtensible]] ( )

When the [[IsExtensible]] internal method of a Proxy exotic object O is called the following steps are taken:

  1. Let handler be the value of the [[ProxyHandler]] internal slot of O.
  2. If handler is null, throw a TypeError exception.
  3. Assert: Type(handler) is Object.
  4. Let target be the value of the [[ProxyTarget]] internal slot of O.
  5. Let trap be GetMethod(handler, "isExtensible").
  6. ReturnIfAbrupt(trap).
  7. If trap is undefined, then
    1. Return target.[[IsExtensible]]().
  8. Let booleanTrapResult be ToBoolean(Call(trap, handler, «target»)).
  9. ReturnIfAbrupt(booleanTrapResult).
  10. Let targetResult be target.[[IsExtensible]]().
  11. ReturnIfAbrupt(targetResult).
  12. If SameValue(booleanTrapResult, targetResult) is false, throw a TypeError exception.
  13. Return booleanTrapResult.

NOTE [[IsExtensible]] for proxy objects enforces the following invariant:

  • The result of [[IsExtensible]] is a Boolean value.

  • [[IsExtensible]] applied to the proxy object must return the same value as [[IsExtensible]] applied to the proxy object's target object with the same argument.

9.5.4 [[PreventExtensions]] ( )

When the [[PreventExtensions]] internal method of a Proxy exotic object O is called the following steps are taken:

  1. Let handler be the value of the [[ProxyHandler]] internal slot of O.
  2. If handler is null, throw a TypeError exception.
  3. Assert: Type(handler) is Object.
  4. Let target be the value of the [[ProxyTarget]] internal slot of O.
  5. Let trap be GetMethod(handler, "preventExtensions").
  6. ReturnIfAbrupt(trap).
  7. If trap is undefined, then
    1. Return target.[[PreventExtensions]]().
  8. Let booleanTrapResult be ToBoolean(Call(trap, handler, «target»)).
  9. ReturnIfAbrupt(booleanTrapResult).
  10. If booleanTrapResult is true, then
    1. Let targetIsExtensible be target.[[IsExtensible]]().
    2. ReturnIfAbrupt(targetIsExtensible).
    3. If targetIsExtensible is true, throw a TypeError exception.
  11. Return booleanTrapResult.

NOTE [[PreventExtensions]] for proxy objects enforces the following invariant:

  • The result of [[PreventExtensions]] is a Boolean value.

  • [[PreventExtensions]] applied to the proxy object only returns true if [[IsExtensible]] applied to the proxy object's target object is false.

9.5.5 [[GetOwnProperty]] (P)

When the [[GetOwnProperty]] internal method of a Proxy exotic object O is called with property key P, the following steps are taken:

  1. Assert: IsPropertyKey(P) is true.
  2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
  3. If handler is null, throw a TypeError exception.
  4. Assert: Type(handler) is Object.
  5. Let target be the value of the [[ProxyTarget]] internal slot of O.
  6. Let trap be GetMethod(handler, "getOwnPropertyDescriptor").
  7. ReturnIfAbrupt(trap).
  8. If trap is undefined, then
    1. Return target.[[GetOwnProperty]](P).
  9. Let trapResultObj be Call(trap, handler, «target, P»).
  10. ReturnIfAbrupt(trapResultObj).
  11. If Type(trapResultObj) is neither Object nor Undefined, throw a TypeError exception.
  12. Let targetDesc be target.[[GetOwnProperty]](P).
  13. ReturnIfAbrupt(targetDesc).
  14. If trapResultObj is undefined, then
    1. If targetDesc is undefined, return undefined.
    2. If targetDesc.[[Configurable]] is false, throw a TypeError exception.
    3. Let extensibleTarget be IsExtensible(target).
    4. ReturnIfAbrupt(extensibleTarget).
    5. Assert: Type(extensibleTarget) is Boolean.
    6. If extensibleTarget is false, throw a TypeError exception.
    7. Return undefined.
  15. Let extensibleTarget be IsExtensible(target).
  16. ReturnIfAbrupt(extensibleTarget).
  17. Let resultDesc be ToPropertyDescriptor(trapResultObj).
  18. ReturnIfAbrupt(resultDesc).
  19. Call CompletePropertyDescriptor(resultDesc).
  20. Let valid be IsCompatiblePropertyDescriptor (extensibleTarget, resultDesc, targetDesc).
  21. If valid is false, throw a TypeError exception.
  22. If resultDesc.[[Configurable]] is false, then
    1. If targetDesc is undefined or targetDesc.[[Configurable]] is true, then
      1. Throw a TypeError exception.
  23. Return resultDesc.

NOTE [[GetOwnProperty]] for proxy objects enforces the following invariants:

  • The result of [[GetOwnProperty]] must be either an Object or undefined.

  • A property cannot be reported as non-existent, if it exists as a non-configurable own property of the target object.

  • A property cannot be reported as non-existent, if it exists as an own property of the target object and the target object is not extensible.

  • A property cannot be reported as existent, if it does not exists as an own property of the target object and the target object is not extensible.

  • A property cannot be reported as non-configurable, if it does not exists as an own property of the target object or if it exists as a configurable own property of the target object.

9.5.6 [[DefineOwnProperty]] (P, Desc)

When the [[DefineOwnProperty]] internal method of a Proxy exotic object O is called with property key P and Property Descriptor Desc, the following steps are taken:

  1. Assert: IsPropertyKey(P) is true.
  2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
  3. If handler is null, throw a TypeError exception.
  4. Assert: Type(handler) is Object.
  5. Let target be the value of the [[ProxyTarget]] internal slot of O.
  6. Let trap be GetMethod(handler, "defineProperty").
  7. ReturnIfAbrupt(trap).
  8. If trap is undefined, then
    1. Return target.[[DefineOwnProperty]](P, Desc).
  9. Let descObj be FromPropertyDescriptor(Desc).
  10. Let booleanTrapResult be ToBoolean(Call(trap, handler, «target, P, descObj»)).
  11. ReturnIfAbrupt(booleanTrapResult).
  12. If booleanTrapResult is false, return false.
  13. Let targetDesc be target.[[GetOwnProperty]](P).
  14. ReturnIfAbrupt(targetDesc).
  15. Let extensibleTarget be IsExtensible(target).
  16. ReturnIfAbrupt(extensibleTarget).
  17. If Desc has a [[Configurable]] field and if Desc.[[Configurable]] is false, then
    1. Let settingConfigFalse be true.
  18. Else let settingConfigFalse be false.
  19. If targetDesc is undefined, then
    1. If extensibleTarget is false, throw a TypeError exception.
    2. If settingConfigFalse is true, throw a TypeError exception.
  20. Else targetDesc is not undefined,
    1. If IsCompatiblePropertyDescriptor(extensibleTarget, Desc , targetDesc) is false, throw a TypeError exception.
    2. If settingConfigFalse is true and targetDesc.[[Configurable]] is true, throw a TypeError exception.
  21. Return true.

NOTE [[DefineOwnProperty]] for proxy objects enforces the following invariants:

  • The result of [[DefineOwnProperty]] is a Boolean value.

  • A property cannot be added, if the target object is not extensible.

  • A property cannot be non-configurable, unless there exists a corresponding non-configurable own property of the target object.

  • If a property has a corresponding target object property then applying the Property Descriptor of the property to the target object using [[DefineOwnProperty]] will not throw an exception.

9.5.7 [[HasProperty]] (P)

When the [[HasProperty]] internal method of a Proxy exotic object O is called with property key P, the following steps are taken:

  1. Assert: IsPropertyKey(P) is true.
  2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
  3. If handler is null, throw a TypeError exception.
  4. Assert: Type(handler) is Object.
  5. Let target be the value of the [[ProxyTarget]] internal slot of O.
  6. Let trap be GetMethod(handler, "has").
  7. ReturnIfAbrupt(trap).
  8. If trap is undefined, then
    1. Return target.[[HasProperty]](P).
  9. Let booleanTrapResult be ToBoolean(Call(trap, handler, «target, P»)).
  10. ReturnIfAbrupt(booleanTrapResult).
  11. If booleanTrapResult is false, then
    1. Let targetDesc be target.[[GetOwnProperty]](P).
    2. ReturnIfAbrupt(targetDesc).
    3. If targetDesc is not undefined, then
      1. If targetDesc.[[Configurable]] is false, throw a TypeError exception.
      2. Let extensibleTarget be IsExtensible(target).
      3. ReturnIfAbrupt(extensibleTarget).
      4. If extensibleTarget is false, throw a TypeError exception.
  12. Return booleanTrapResult.

NOTE [[HasProperty]] for proxy objects enforces the following invariants:

  • The result of [[HasProperty]] is a Boolean value.

  • A property cannot be reported as non-existent, if it exists as a non-configurable own property of the target object.

  • A property cannot be reported as non-existent, if it exists as an own property of the target object and the target object is not extensible.

9.5.8 [[Get]] (P, Receiver)

When the [[Get]] internal method of a Proxy exotic object O is called with property key P and ECMAScript language value Receiver the following steps are taken:

  1. Assert: IsPropertyKey(P) is true.
  2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
  3. If handler is null, throw a TypeError exception.
  4. Assert: Type(handler) is Object.
  5. Let target be the value of the [[ProxyTarget]] internal slot of O.
  6. Let trap be GetMethod(handler, "get").
  7. ReturnIfAbrupt(trap).
  8. If trap is undefined, then
    1. Return target.[[Get]](P, Receiver).
  9. Let trapResult be Call(trap, handler, «target, P, Receiver»).
  10. ReturnIfAbrupt(trapResult).
  11. Let targetDesc be target.[[GetOwnProperty]](P).
  12. ReturnIfAbrupt(targetDesc).
  13. If targetDesc is not undefined, then
    1. If IsDataDescriptor(targetDesc) and targetDesc.[[Configurable]] is false and targetDesc.[[Writable]] is false, then
      1. If SameValue(trapResult, targetDesc.[[Value]]) is false, throw a TypeError exception.
    2. If IsAccessorDescriptor(targetDesc) and targetDesc.[[Configurable]] is false and targetDesc.[[Get]] is undefined, then
      1. If trapResult is not undefined, throw a TypeError exception.
  14. Return trapResult.

NOTE [[Get]] for proxy objects enforces the following invariants:

  • The value reported for a property must be the same as the value of the corresponding target object property if the target object property is a non-writable, non-configurable own data property.

  • The value reported for a property must be undefined if the corresponding target object property is a non-configurable own accessor property that has undefined as its [[Get]] attribute.

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

When the [[Set]] internal method of a Proxy exotic object O is called with property key P, value V, and ECMAScript language value Receiver, the following steps are taken:

  1. Assert: IsPropertyKey(P) is true.
  2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
  3. If handler is null, throw a TypeError exception.
  4. Assert: Type(handler) is Object.
  5. Let target be the value of the [[ProxyTarget]] internal slot of O.
  6. Let trap be GetMethod(handler, "set").
  7. ReturnIfAbrupt(trap).
  8. If trap is undefined, then
    1. Return target.[[Set]](P, V, Receiver).
  9. Let booleanTrapResult be ToBoolean(Call(trap, handler, «target, P, V, Receiver»)).
  10. ReturnIfAbrupt(booleanTrapResult).
  11. If booleanTrapResult is false, return false.
  12. Let targetDesc be target.[[GetOwnProperty]](P).
  13. ReturnIfAbrupt(targetDesc).
  14. If targetDesc is not undefined, then
    1. If IsDataDescriptor(targetDesc) and targetDesc.[[Configurable]] is false and targetDesc.[[Writable]] is false, then
      1. If SameValue(V, targetDesc.[[Value]]) is false, throw a TypeError exception.
    2. If IsAccessorDescriptor(targetDesc) and targetDesc.[[Configurable]] is false, then
      1. If targetDesc.[[Set]] is undefined, throw a TypeError exception.
  15. Return true.

NOTE [[Set]] for proxy objects enforces the following invariants:

  • The result of [[Set]] is a Boolean value.

  • Cannot change the value of a property to be different from the value of the corresponding target object property if the corresponding target object property is a non-writable, non-configurable own data property.

  • Cannot set the value of a property if the corresponding target object property is a non-configurable own accessor property that has undefined as its [[Set]] attribute.

9.5.10 [[Delete]] (P)

When the [[Delete]] internal method of a Proxy exotic object O is called with property key P the following steps are taken:

  1. Assert: IsPropertyKey(P) is true.
  2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
  3. If handler is null, throw a TypeError exception.
  4. Assert: Type(handler) is Object.
  5. Let target be the value of the [[ProxyTarget]] internal slot of O.
  6. Let trap be GetMethod(handler, "deleteProperty").
  7. ReturnIfAbrupt(trap).
  8. If trap is undefined, then
    1. Return target.[[Delete]](P).
  9. Let booleanTrapResult be ToBoolean(Call(trap, handler, «target, P»)).
  10. ReturnIfAbrupt(booleanTrapResult).
  11. If booleanTrapResult is false, return false.
  12. Let targetDesc be target.[[GetOwnProperty]](P).
  13. ReturnIfAbrupt(targetDesc).
  14. If targetDesc is undefined, return true.
  15. If targetDesc.[[Configurable]] is false, throw a TypeError exception.
  16. Return true.

NOTE [[Delete]] for proxy objects enforces the following invariant:

  • The result of [[Delete]] is a Boolean value.
  • A property cannot be reported as deleted, if it exists as a non-configurable own property of the target object.

9.5.11 [[Enumerate]] ()

When the [[Enumerate]] internal method of a Proxy exotic object O is called the following steps are taken:

  1. Let handler be the value of the [[ProxyHandler]] internal slot of O.
  2. If handler is null, throw a TypeError exception.
  3. Assert: Type(handler) is Object.
  4. Let target be the value of the [[ProxyTarget]] internal slot of O.
  5. Let trap be GetMethod(handler, "enumerate").
  6. ReturnIfAbrupt(trap).
  7. If trap is undefined, then
    1. Return target.[[Enumerate]]().
  8. Let trapResult be Call(trap, handler, «target»).
  9. ReturnIfAbrupt(trapResult).
  10. If Type(trapResult) is not Object, throw a TypeError exception.
  11. Return trapResult.

NOTE [[Enumerate]] for proxy objects enforces the following invariants:

  • The result of [[Enumerate]] must be an Object.

9.5.12 [[OwnPropertyKeys]] ( )

When the [[OwnPropertyKeys]] internal method of a Proxy exotic object O is called the following steps are taken:

  1. Let handler be the value of the [[ProxyHandler]] internal slot of O.
  2. If handler is null, throw a TypeError exception.
  3. Assert: Type(handler) is Object.
  4. Let target be the value of the [[ProxyTarget]] internal slot of O.
  5. Let trap be GetMethod(handler, "ownKeys").
  6. ReturnIfAbrupt(trap).
  7. If trap is undefined, then
    1. Return target.[[OwnPropertyKeys]]().
  8. Let trapResultArray be Call(trap, handler, «target»).
  9. Let trapResult be CreateListFromArrayLike(trapResultArray, «‍String, Symbol»).
  10. ReturnIfAbrupt(trapResult).
  11. Let extensibleTarget be IsExtensible(target).
  12. ReturnIfAbrupt(extensibleTarget).
  13. Let targetKeys be target.[[OwnPropertyKeys]]().
  14. ReturnIfAbrupt(targetKeys).
  15. Assert: targetKeys is a List containing only String and Symbol values.
  16. Let targetConfigurableKeys be an empty List.
  17. Let targetNonconfigurableKeys be an empty List.
  18. Repeat, for each element key of targetKeys,
    1. Let desc be target.[[GetOwnProperty]](key).
    2. ReturnIfAbrupt(desc).
    3. If desc is not undefined and desc.[[Configurable]] is false, then
      1. Append key as an element of targetNonconfigurableKeys.
    4. Else,
      1. Append key as an element of targetConfigurableKeys.
  19. If extensibleTarget is true and targetNonconfigurableKeys is empty, then
    1. Return trapResult.
  20. Let uncheckedResultKeys be a new List which is a copy of trapResult.
  21. Repeat, for each key that is an element of targetNonconfigurableKeys,
    1. If key is not an element of uncheckedResultKeys, throw a TypeError exception.
    2. Remove key from uncheckedResultKeys
  22. If extensibleTarget is true, return trapResult.
  23. Repeat, for each key that is an element of targetConfigurableKeys,
    1. If key is not an element of uncheckedResultKeys, throw a TypeError exception.
    2. Remove key from uncheckedResultKeys
  24. If uncheckedResultKeys is not empty, throw a TypeError exception.
  25. Return trapResult.

NOTE [[OwnPropertyKeys]] for proxy objects enforces the following invariants:

  • The result of [[OwnPropertyKeys]] is a List.

  • The Type of each result List element is either String or Symbol.

  • The result List must contain the keys of all non-configurable own properties of the target object.

  • If the target object is not extensible, then the result List must contain all the keys of the own properties of the target object and no other values.

9.5.13 [[Call]] (thisArgument, argumentsList)

The [[Call]] internal method of a Proxy exotic object O is called with parameters thisArgument and argumentsList, a List of ECMAScript language values. The following steps are taken:

  1. Let handler be the value of the [[ProxyHandler]] internal slot of O.
  2. If handler is null, throw a TypeError exception.
  3. Assert: Type(handler) is Object.
  4. Let target be the value of the [[ProxyTarget]] internal slot of O.
  5. Let trap be GetMethod(handler, "apply").
  6. ReturnIfAbrupt(trap).
  7. If trap is undefined, then
    1. Return Call(target, thisArgument, argumentsList).
  8. Let argArray be CreateArrayFromList(argumentsList).
  9. Return Call(trap, handler, «target, thisArgument, argArray»).

NOTE A Proxy exotic object only has a [[Call]] internal method if the initial value of its [[ProxyTarget]] internal slot is an object that has a [[Call]] internal method.

9.5.14 [[Construct]] ( argumentsList, newTarget)

The [[Construct]] internal method of a Proxy exotic object O is called with parameters argumentsList which is a possibly empty List of ECMAScript language values and newTarget. The following steps are taken:

  1. Let handler be the value of the [[ProxyHandler]] internal slot of O.
  2. If handler is null, throw a TypeError exception.
  3. Assert: Type(handler) is Object.
  4. Let target be the value of the [[ProxyTarget]] internal slot of O.
  5. Let trap be GetMethod(handler, "construct").
  6. ReturnIfAbrupt(trap).
  7. If trap is undefined, then
    1. Assert: target has a [[Construct]] internal method.
    2. Return Construct(target, argumentsList, newTarget).
  8. Let argArray be CreateArrayFromList(argumentsList).
  9. Let newObj be Call(trap, handler, «target, argArray, newTarget »).
  10. ReturnIfAbrupt(newObj).
  11. If Type(newObj) is not Object, throw a TypeError exception.
  12. Return newObj.

NOTE 1 A Proxy exotic object only has a [[Construct]] internal method if the initial value of its [[ProxyTarget]] internal slot is an object that has a [[Construct]] internal method.

NOTE 2 [[Construct]] for proxy objects enforces the following invariants:

  • The result of [[Construct]] must be an Object.

9.5.15 ProxyCreate(target, handler)

The abstract operation ProxyCreate with arguments target and handler is used to specify the creation of new Proxy exotic objects. It performs the following steps:

  1. If Type(target) is not Object, throw a TypeError exception.
  2. If target is a Proxy exotic object and the value of the [[ProxyHandler]] internal slot of target is null, throw a TypeError exception.
  3. If Type(handler) is not Object, throw a TypeError exception.
  4. If handler is a Proxy exotic object and the value of the [[ProxyHandler]] internal slot of handler is null, throw a TypeError exception.
  5. Let P be a newly created object.
  6. Set P's essential internal methods (except for [[Call]] and [[Construct]]) to the definitions specified in 9.5.
  7. If IsCallable(target) is true, then
    1. Set the [[Call]] internal method of P as specified in 9.5.13.
    2. If target has a [[Construct]] internal method, then
      1. Set the [[Construct]] internal method of P as specified in 9.5.14.
  8. Set the [[ProxyTarget]] internal slot of P to target.
  9. Set the [[ProxyHandler]] internal slot of P to handler.
  10. Return P.