10 Ordinary and Exotic Objects Behaviours

10.1 Ordinary Object Internal Methods and Internal Slots

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

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

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

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

10.1.1 [[GetPrototypeOf]] ( )

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

  1. Return ! OrdinaryGetPrototypeOf(O).

10.1.1.1 OrdinaryGetPrototypeOf ( O )

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

  1. Return O.[[Prototype]].

10.1.2 [[SetPrototypeOf]] ( V )

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

  1. Return ! OrdinarySetPrototypeOf(O, V).

10.1.2.1 OrdinarySetPrototypeOf ( O, V )

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

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

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

10.1.3 [[IsExtensible]] ( )

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

  1. Return ! OrdinaryIsExtensible(O).

10.1.3.1 OrdinaryIsExtensible ( O )

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

  1. Return O.[[Extensible]].

10.1.4 [[PreventExtensions]] ( )

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

  1. Return ! OrdinaryPreventExtensions(O).

10.1.4.1 OrdinaryPreventExtensions ( O )

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

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

10.1.5 [[GetOwnProperty]] ( P )

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

  1. Return ! OrdinaryGetOwnProperty(O, P).

10.1.5.1 OrdinaryGetOwnProperty ( O, P )

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

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

10.1.6 [[DefineOwnProperty]] ( P, Desc )

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

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

10.1.6.1 OrdinaryDefineOwnProperty ( O, P, Desc )

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

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

10.1.6.2 IsCompatiblePropertyDescriptor ( Extensible, Desc, Current )

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

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

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

The abstract operation ValidateAndApplyPropertyDescriptor takes arguments O (an Object or undefined), P (a property key), extensible (a Boolean), Desc (a Property Descriptor), and current (a Property Descriptor).

Note

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

It performs the following steps when called:

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

10.1.7 [[HasProperty]] ( P )

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

  1. Return ? OrdinaryHasProperty(O, P).

10.1.7.1 OrdinaryHasProperty ( O, P )

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

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

10.1.8 [[Get]] ( P, Receiver )

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

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

10.1.8.1 OrdinaryGet ( O, P, Receiver )

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

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

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

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

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

10.1.9.1 OrdinarySet ( O, P, V, Receiver )

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

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

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

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

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

10.1.10 [[Delete]] ( P )

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

  1. Return ? OrdinaryDelete(O, P).

10.1.10.1 OrdinaryDelete ( O, P )

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

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

10.1.11 [[OwnPropertyKeys]] ( )

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

  1. Return ! OrdinaryOwnPropertyKeys(O).

10.1.11.1 OrdinaryOwnPropertyKeys ( O )

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

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

10.1.12 OrdinaryObjectCreate ( proto [ , additionalInternalSlotsList ] )

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

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

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

10.1.13 OrdinaryCreateFromConstructor ( constructor, intrinsicDefaultProto [ , internalSlotsList ] )

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

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

10.1.14 GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto )

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

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

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

10.1.15 RequireInternalSlot ( O, internalSlot )

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

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

10.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 (11.2.2) or non-strict 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.

In addition to [[Extensible]] and [[Prototype]], ECMAScript function objects also have the internal slots listed in Table 33.

Table 33: Internal Slots of ECMAScript Function Objects
Internal Slot Type Description
[[Environment]] Environment Record The Environment Record that the function was closed over. Used as the outer environment when evaluating the code of the function.
[[PrivateEnvironment]] PrivateEnvironment Record | null The PrivateEnvironment Record for Private Names that the function was closed over. null if this function is not syntactically contained within a class. Used as the outer PrivateEnvironment for inner classes 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.
[[ECMAScriptCode]] Parse Node The root parse node of the source text that defines the function's body.
[[ConstructorKind]] base | derived Whether or not the function is a derived class constructor.
[[Realm]] Realm Record The realm in which the function was created and which provides any intrinsic objects that are accessed when evaluating the function.
[[ScriptOrModule]] Script Record or Module Record The script or module in which the function was created.
[[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 or null is interpreted as a reference to the global object, and any other this value is first passed to ToObject.
[[Strict]] Boolean true if this is a strict function, false if this is a non-strict function.
[[HomeObject]] Object If the function uses super, this is the object whose [[GetPrototypeOf]] provides the object where super property lookups begin.
[[SourceText]] sequence of Unicode code points The source text that defines the function.
[[Fields]] List of ClassFieldDefinition Records If the function is a class, this is a list of Records representing the non-static fields and corresponding initializers of the class.
[[PrivateMethods]] List of PrivateElements If the function is a class, this is a list representing the non-static private methods and accessors of the class.
[[ClassFieldInitializerName]] String | Symbol | Private Name | empty If the function is created as the initializer of a class field, the name to use for NamedEvaluation of the field; empty otherwise.
[[IsClassConstructor]] Boolean Indicates whether the function is a class constructor. (If true, invoking the function's [[Call]] will immediately throw a TypeError exception.)

All ECMAScript function objects have the [[Call]] internal method defined here. ECMAScript functions that are also constructors in addition have the [[Construct]] internal method.

10.2.1 [[Call]] ( thisArgument, argumentsList )

The [[Call]] internal method of an ECMAScript function object F takes arguments thisArgument (an ECMAScript language value) and argumentsList (a List of ECMAScript language values). It performs the following steps when called:

  1. Assert: F is an ECMAScript function object.
  2. Let callerContext be the running execution context.
  3. Let calleeContext be PrepareForOrdinaryCall(F, undefined).
  4. Assert: calleeContext is now the running execution context.
  5. If F.[[IsClassConstructor]] is true, then
    1. Let error be a newly created TypeError object.
    2. NOTE: error is created in calleeContext with F's associated Realm Record.
    3. Remove calleeContext from the execution context stack and restore callerContext as the running execution context.
    4. Return ThrowCompletion(error).
  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.

10.2.1.1 PrepareForOrdinaryCall ( F, newTarget )

The abstract operation PrepareForOrdinaryCall takes arguments F (a function object) and newTarget (an ECMAScript language value). It performs the following steps when called:

  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 F.[[Realm]].
  6. Set the Realm of calleeContext to calleeRealm.
  7. Set the ScriptOrModule of calleeContext to F.[[ScriptOrModule]].
  8. Let localEnv be NewFunctionEnvironment(F, newTarget).
  9. Set the LexicalEnvironment of calleeContext to localEnv.
  10. Set the VariableEnvironment of calleeContext to localEnv.
  11. Set the PrivateEnvironment of calleeContext to F.[[PrivateEnvironment]].
  12. If callerContext is not already suspended, suspend callerContext.
  13. Push calleeContext onto the execution context stack; calleeContext is now the running execution context.
  14. NOTE: Any exception objects produced after this point are associated with calleeRealm.
  15. Return calleeContext.

10.2.1.2 OrdinaryCallBindThis ( F, calleeContext, thisArgument )

The abstract operation OrdinaryCallBindThis takes arguments F (a function object), calleeContext (an execution context), and thisArgument (an ECMAScript language value). It performs the following steps when called:

  1. Let thisMode be F.[[ThisMode]].
  2. If thisMode is lexical, return NormalCompletion(undefined).
  3. Let calleeRealm be F.[[Realm]].
  4. Let localEnv be the LexicalEnvironment of calleeContext.
  5. If thisMode is strict, let thisValue be thisArgument.
  6. Else,
    1. If thisArgument is undefined or null, then
      1. Let globalEnv be calleeRealm.[[GlobalEnv]].
      2. Assert: globalEnv is a global Environment Record.
      3. Let thisValue be globalEnv.[[GlobalThisValue]].
    2. Else,
      1. Let thisValue be ! ToObject(thisArgument).
      2. NOTE: ToObject produces wrapper objects using calleeRealm.
  7. Assert: localEnv is a function Environment Record.
  8. Assert: The next step never returns an abrupt completion because localEnv.[[ThisBindingStatus]] is not initialized.
  9. Return localEnv.BindThisValue(thisValue).

10.2.1.3 Runtime Semantics: EvaluateBody

With parameters functionObject and argumentsList (a List).

FunctionBody : FunctionStatementList
  1. Return ? EvaluateFunctionBody of FunctionBody with arguments functionObject and argumentsList.
ConciseBody : ExpressionBody
  1. Return ? EvaluateConciseBody of ConciseBody with arguments functionObject and argumentsList.
GeneratorBody : FunctionBody
  1. Return ? EvaluateGeneratorBody of GeneratorBody with arguments functionObject and argumentsList.
AsyncGeneratorBody : FunctionBody
  1. Return ? EvaluateAsyncGeneratorBody of AsyncGeneratorBody with arguments functionObject and argumentsList.
AsyncFunctionBody : FunctionBody
  1. Return ? EvaluateAsyncFunctionBody of AsyncFunctionBody with arguments functionObject and argumentsList.
AsyncConciseBody : ExpressionBody
  1. Return ? EvaluateAsyncConciseBody of AsyncConciseBody with arguments functionObject and argumentsList.
Initializer : = AssignmentExpression
  1. Assert: argumentsList is empty.
  2. Assert: functionObject.[[ClassFieldInitializerName]] is not empty.
  3. If IsAnonymousFunctionDefinition(AssignmentExpression) is true, then
    1. Let value be NamedEvaluation of Initializer with argument functionObject.[[ClassFieldInitializerName]].
  4. Else,
    1. Let rhs be the result of evaluating AssignmentExpression.
    2. Let value be ? GetValue(rhs).
  5. Return Completion { [[Type]]: return, [[Value]]: value, [[Target]]: empty }.
Note

Even though field initializers constitute a function boundary, calling FunctionDeclarationInstantiation does not have any observable effect and so is omitted.

10.2.1.4 OrdinaryCallEvaluateBody ( F, argumentsList )

The abstract operation OrdinaryCallEvaluateBody takes arguments F (a function object) and argumentsList (a List). It performs the following steps when called:

  1. Return the result of EvaluateBody of the parsed code that is F.[[ECMAScriptCode]] passing F and argumentsList as the arguments.

10.2.2 [[Construct]] ( argumentsList, newTarget )

The [[Construct]] internal method of an ECMAScript function object F takes arguments argumentsList (a List of ECMAScript language values) and newTarget (a constructor). It performs the following steps when called:

  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.[[ConstructorKind]].
  5. If kind is base, then
    1. Let thisArgument be ? OrdinaryCreateFromConstructor(newTarget, "%Object.prototype%").
  6. Let calleeContext be PrepareForOrdinaryCall(F, newTarget).
  7. Assert: calleeContext is now the running execution context.
  8. If kind is base, then
    1. Perform OrdinaryCallBindThis(F, calleeContext, thisArgument).
    2. Let initializeResult be InitializeInstanceElements(thisArgument, F).
    3. If initializeResult is an abrupt completion, then
      1. Remove calleeContext from the execution context stack and restore callerContext as the running execution context.
      2. Return Completion(initializeResult).
  9. Let constructorEnv be the LexicalEnvironment of calleeContext.
  10. Let result be OrdinaryCallEvaluateBody(F, argumentsList).
  11. Remove calleeContext from the execution context stack and restore callerContext as the running execution context.
  12. 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.
  13. Else, ReturnIfAbrupt(result).
  14. Return ? constructorEnv.GetThisBinding().

10.2.3 OrdinaryFunctionCreate ( functionPrototype, sourceText, ParameterList, Body, thisMode, Scope, PrivateScope )

The abstract operation OrdinaryFunctionCreate takes arguments functionPrototype (an Object), sourceText (a sequence of Unicode code points), ParameterList (a Parse Node), Body (a Parse Node), thisMode (either lexical-this or non-lexical-this), Scope (an Environment Record), and PrivateScope (a PrivateEnvironment Record or null). sourceText is the source text of the syntactic definition of the function to be created. It performs the following steps when called:

  1. Assert: Type(functionPrototype) is Object.
  2. Let internalSlotsList be the internal slots listed in Table 33.
  3. Let F be ! OrdinaryObjectCreate(functionPrototype, internalSlotsList).
  4. Set F.[[Call]] to the definition specified in 10.2.1.
  5. Set F.[[SourceText]] to sourceText.
  6. Set F.[[FormalParameters]] to ParameterList.
  7. Set F.[[ECMAScriptCode]] to Body.
  8. If the source text matching Body is strict mode code, let Strict be true; else let Strict be false.
  9. Set F.[[Strict]] to Strict.
  10. If thisMode is lexical-this, set F.[[ThisMode]] to lexical.
  11. Else if Strict is true, set F.[[ThisMode]] to strict.
  12. Else, set F.[[ThisMode]] to global.
  13. Set F.[[IsClassConstructor]] to false.
  14. Set F.[[Environment]] to Scope.
  15. Set F.[[PrivateEnvironment]] to PrivateScope.
  16. Set F.[[ScriptOrModule]] to GetActiveScriptOrModule().
  17. Set F.[[Realm]] to the current Realm Record.
  18. Set F.[[HomeObject]] to undefined.
  19. Set F.[[Fields]] to a new empty List.
  20. Set F.[[PrivateMethods]] to a new empty List.
  21. Set F.[[ClassFieldInitializerName]] to empty.
  22. Let len be the ExpectedArgumentCount of ParameterList.
  23. Perform ! SetFunctionLength(F, len).
  24. Return F.

10.2.4 AddRestrictedFunctionProperties ( F, realm )

The abstract operation AddRestrictedFunctionProperties takes arguments F (a function object) and realm (a Realm Record). It performs the following steps when called:

  1. Assert: realm.[[Intrinsics]].[[%ThrowTypeError%]] exists and has been initialized.
  2. Let thrower be realm.[[Intrinsics]].[[%ThrowTypeError%]].
  3. Perform ! DefinePropertyOrThrow(F, "caller", PropertyDescriptor { [[Get]]: thrower, [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: true }).
  4. Return ! DefinePropertyOrThrow(F, "arguments", PropertyDescriptor { [[Get]]: thrower, [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: true }).

10.2.4.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 }.

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

10.2.5 MakeConstructor ( F [ , writablePrototype [ , prototype ] ] )

The abstract operation MakeConstructor takes argument F (a function object) and optional arguments writablePrototype (a Boolean) and prototype (an Object). It converts F into a constructor. It performs the following steps when called:

  1. Assert: F is an ECMAScript function object or a built-in function object.
  2. If F is an ECMAScript function object, then
    1. Assert: IsConstructor(F) is false.
    2. Assert: F is an extensible object that does not have a "prototype" own property.
    3. Set F.[[Construct]] to the definition specified in 10.2.2.
  3. Set F.[[ConstructorKind]] to base.
  4. If writablePrototype is not present, set writablePrototype to true.
  5. If prototype is not present, then
    1. Set prototype to ! OrdinaryObjectCreate(%Object.prototype%).
    2. Perform ! DefinePropertyOrThrow(prototype, "constructor", PropertyDescriptor { [[Value]]: F, [[Writable]]: writablePrototype, [[Enumerable]]: false, [[Configurable]]: true }).
  6. Perform ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: writablePrototype, [[Enumerable]]: false, [[Configurable]]: false }).
  7. Return NormalCompletion(undefined).

10.2.6 MakeClassConstructor ( F )

The abstract operation MakeClassConstructor takes argument F. It performs the following steps when called:

  1. Assert: F is an ECMAScript function object.
  2. Assert: F.[[IsClassConstructor]] is false.
  3. Set F.[[IsClassConstructor]] to true.
  4. Return NormalCompletion(undefined).

10.2.7 MakeMethod ( F, homeObject )

The abstract operation MakeMethod takes arguments F and homeObject. It configures F as a method. It performs the following steps when called:

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

10.2.8 DefineMethodProperty ( key, homeObject, closure, enumerable )

The abstract operation DefineMethodProperty takes arguments key (a property key or Private Name), homeObject (an Object), closure (a function object), and enumerable (a Boolean). It performs the following steps when called:

  1. Perform ! SetFunctionName(closure, key).
  2. If key is a Private Name, then
    1. Return PrivateElement { [[Key]]: key, [[Kind]]: method, [[Value]]: closure }.
  3. Else,
    1. Let desc be the PropertyDescriptor { [[Value]]: closure, [[Writable]]: true, [[Enumerable]]: enumerable, [[Configurable]]: true }.
    2. Perform ? DefinePropertyOrThrow(homeObject, key, desc).
    3. Return empty.

10.2.9 SetFunctionName ( F, name [ , prefix ] )

The abstract operation SetFunctionName takes arguments F (a function object) and name (a property key or Private Name) and optional argument prefix (a String). It adds a "name" property to F. It performs the following steps when called:

  1. Assert: F is an extensible object that does not have a "name" own property.
  2. If Type(name) is Symbol, then
    1. Let description be name's [[Description]] value.
    2. If description is undefined, set name to the empty String.
    3. Else, set name to the string-concatenation of "[", description, and "]".
  3. Else if name is a Private Name, then
    1. Set name to name.[[Description]].
  4. If F has an [[InitialName]] internal slot, then
    1. Set F.[[InitialName]] to name.
  5. If prefix is present, then
    1. Set name to the string-concatenation of prefix, the code unit 0x0020 (SPACE), and name.
    2. If F has an [[InitialName]] internal slot, then
      1. Optionally, set F.[[InitialName]] to name.
  6. Return ! DefinePropertyOrThrow(F, "name", PropertyDescriptor { [[Value]]: name, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }).

10.2.10 SetFunctionLength ( F, length )

The abstract operation SetFunctionLength takes arguments F (a function object) and length (a non-negative integer or +∞). It adds a "length" property to F. It performs the following steps when called:

  1. Assert: F is an extensible object that does not have a "length" own property.
  2. Return ! DefinePropertyOrThrow(F, "length", PropertyDescriptor { [[Value]]: 𝔽(length), [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }).

10.2.11 FunctionDeclarationInstantiation ( func, argumentsList )

The abstract operation FunctionDeclarationInstantiation takes arguments func (a function object) and argumentsList. func is the function object for which the execution context is being established.

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.

It performs the following steps when called:

  1. Let calleeContext be the running execution context.
  2. Let code be func.[[ECMAScriptCode]].
  3. Let strict be func.[[Strict]].
  4. Let formals be func.[[FormalParameters]].
  5. Let parameterNames be the BoundNames of formals.
  6. If parameterNames has any duplicate entries, let hasDuplicates be true. Otherwise, let hasDuplicates be false.
  7. Let simpleParameterList be IsSimpleParameterList of formals.
  8. Let hasParameterExpressions be ContainsExpression of formals.
  9. Let varNames be the VarDeclaredNames of code.
  10. Let varDeclarations be the VarScopedDeclarations of code.
  11. Let lexicalNames be the LexicallyDeclaredNames of code.
  12. Let functionNames be a new empty List.
  13. Let functionsToInitialize be a new empty List.
  14. For each element d of varDeclarations, in reverse List order, do
    1. If d is neither a VariableDeclaration nor a ForBinding nor a BindingIdentifier, then
      1. Assert: d is either a FunctionDeclaration, a GeneratorDeclaration, an AsyncFunctionDeclaration, or an AsyncGeneratorDeclaration.
      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 function declarations for the same name, the last declaration is used.
        3. Insert d as the first element of functionsToInitialize.
  15. Let argumentsObjectNeeded be true.
  16. If func.[[ThisMode]] is lexical, then
    1. NOTE: Arrow functions never have an arguments objects.
    2. Set argumentsObjectNeeded to false.
  17. Else if "arguments" is an element of parameterNames, then
    1. Set argumentsObjectNeeded to false.
  18. Else if hasParameterExpressions is false, then
    1. If "arguments" is an element of functionNames or if "arguments" is an element of lexicalNames, then
      1. Set argumentsObjectNeeded to false.
  19. If strict is true or if hasParameterExpressions is false, then
    1. NOTE: Only a single Environment Record is needed for the parameters and top-level vars.
    2. Let env be the LexicalEnvironment of calleeContext.
  20. Else,
    1. NOTE: A separate Environment Record is needed to ensure that bindings created by direct eval calls in the formal parameter list are outside the environment where parameters are declared.
    2. Let calleeEnv be the LexicalEnvironment of calleeContext.
    3. Let env be NewDeclarativeEnvironment(calleeEnv).
    4. Assert: The VariableEnvironment of calleeContext is calleeEnv.
    5. Set the LexicalEnvironment of calleeContext to env.
  21. For each String paramName of parameterNames, do
    1. Let alreadyDeclared be env.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. Perform ! env.CreateMutableBinding(paramName, false).
      2. If hasDuplicates is true, then
        1. Perform ! env.InitializeBinding(paramName, undefined).
  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: A 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. If strict is true, then
      1. Perform ! env.CreateImmutableBinding("arguments", false).
    4. Else,
      1. Perform ! env.CreateMutableBinding("arguments", false).
    5. Call env.InitializeBinding("arguments", ao).
    6. Let parameterBindings be the list-concatenation of parameterNames and « "arguments" ».
  23. Else,
    1. Let parameterBindings be parameterNames.
  24. Let iteratorRecord be CreateListIteratorRecord(argumentsList).
  25. If hasDuplicates is true, then
    1. Perform ? IteratorBindingInitialization for formals with iteratorRecord and undefined as arguments.
  26. Else,
    1. Perform ? IteratorBindingInitialization for formals with iteratorRecord and env as arguments.
  27. If hasParameterExpressions is false, then
    1. NOTE: Only a single Environment Record is needed for the parameters and top-level vars.
    2. Let instantiatedVarNames be a copy of the List parameterBindings.
    3. For each element n of varNames, do
      1. If n is not an element of instantiatedVarNames, then
        1. Append n to instantiatedVarNames.
        2. Perform ! env.CreateMutableBinding(n, false).
        3. Call env.InitializeBinding(n, undefined).
    4. Let varEnv be env.
  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. Set the VariableEnvironment of calleeContext to varEnv.
    4. Let instantiatedVarNames be a new empty List.
    5. For each element n of varNames, do
      1. If n is not an element of instantiatedVarNames, then
        1. Append n to instantiatedVarNames.
        2. Perform ! varEnv.CreateMutableBinding(n, false).
        3. If n is not an element of parameterBindings or if n is an element of functionNames, let initialValue be undefined.
        4. Else,
          1. Let initialValue be ! env.GetBindingValue(n, false).
        5. Call varEnv.InitializeBinding(n, initialValue).
        6. NOTE: A var with the same name as a formal parameter initially has the same value as the corresponding initialized parameter.
  29. NOTE: Annex B.3.2.1 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 Environment Record for top-level lexical declarations so that a direct eval 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. Set the LexicalEnvironment of calleeContext to lexEnv.
  33. Let lexDeclarations be the LexicallyScopedDeclarations of code.
  34. For each element d of 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. Perform ! lexEnv.CreateImmutableBinding(dn, true).
      2. Else,
        1. Perform ! lexEnv.CreateMutableBinding(dn, false).
  35. Let privateEnv be the PrivateEnvironment of calleeContext.
  36. For each Parse Node f of functionsToInitialize, do
    1. Let fn be the sole element of the BoundNames of f.
    2. Let fo be InstantiateFunctionObject of f with arguments lexEnv and privateEnv.
    3. Perform ! varEnv.SetMutableBinding(fn, fo, false).
  37. Return NormalCompletion(empty).
Note 2

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

10.3 Built-in Function Objects

The built-in function objects defined in this specification may be implemented as either ECMAScript function objects (10.2) whose behaviour is provided using ECMAScript code or as implementation provided function exotic 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 ECMAScript function object, it must have all the internal slots described in 10.2 ([[Prototype]], [[Extensible]], and the slots listed in Table 33), plus [[InitialName]]. The value of the [[InitialName]] internal slot is a String value that is the initial name of the function. It is used by 20.2.3.5.

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

Unless otherwise specified every built-in function object has the %Function.prototype% object 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 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 [[IsClassConstructor]] internal slot to have the value true.

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:

10.3.1 [[Call]] ( thisArgument, argumentsList )

The [[Call]] internal method of a built-in function object F takes arguments thisArgument (an ECMAScript language value) and argumentsList (a List of ECMAScript language values). It performs the following steps when called:

  1. Let callerContext be the running execution context.
  2. If callerContext is not already suspended, suspend callerContext.
  3. Let calleeContext be a new execution context.
  4. Set the Function of calleeContext to F.
  5. Let calleeRealm be F.[[Realm]].
  6. Set the Realm of calleeContext to calleeRealm.
  7. Set the ScriptOrModule of calleeContext to null.
  8. Perform any necessary implementation-defined initialization of calleeContext.
  9. Push calleeContext onto the execution context stack; calleeContext is now the running execution context.
  10. Let result be the Completion Record that is the result of evaluating F in a manner that conforms to the specification of F. thisArgument is the this value, argumentsList provides the named parameters, and the NewTarget value is undefined.
  11. Remove calleeContext from the execution context stack and restore callerContext as the running execution context.
  12. 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.

10.3.2 [[Construct]] ( argumentsList, newTarget )

The [[Construct]] internal method of a built-in function object F takes arguments argumentsList (a List of ECMAScript language values) and newTarget (a constructor). The steps performed are the same as [[Call]] (see 10.3.1) except that step 10 is replaced by:

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

10.3.3 CreateBuiltinFunction ( behaviour, length, name, additionalInternalSlotsList [ , realm [ , prototype [ , prefix ] ] ] )

The abstract operation CreateBuiltinFunction takes arguments behaviour, length (a non-negative integer or +∞), name (a property key), and additionalInternalSlotsList (a List of names of internal slots) and optional arguments realm (a Realm Record), prototype (an Object or null), and prefix (a String). additionalInternalSlotsList contains the names of additional internal slots that must be defined as part of the object. This operation creates a built-in function object. It performs the following steps when called:

  1. Assert: behaviour is either an Abstract Closure, a set of algorithm steps, or some other definition of a function's behaviour provided in this specification.
  2. If realm is not present, set realm to the current Realm Record.
  3. Assert: realm is a Realm Record.
  4. If prototype is not present, set prototype to realm.[[Intrinsics]].[[%Function.prototype%]].
  5. Let internalSlotsList be a List containing the names of all the internal slots that 10.3 requires for the built-in function object that is about to be created.
  6. Append to internalSlotsList the elements of additionalInternalSlotsList.
  7. Let func be a new built-in function object that, when called, performs the action described by behaviour using the provided arguments as the values of the corresponding parameters specified by behaviour. The new function object has internal slots whose names are the elements of internalSlotsList, and an [[InitialName]] internal slot.
  8. Set func.[[Prototype]] to prototype.
  9. Set func.[[Extensible]] to true.
  10. Set func.[[Realm]] to realm.
  11. Set func.[[InitialName]] to null.
  12. Perform ! SetFunctionLength(func, length).
  13. If prefix is not present, then
    1. Perform ! SetFunctionName(func, name).
  14. Else,
    1. Perform ! SetFunctionName(func, name, prefix).
  15. Return func.

Each built-in function defined in this specification is created by calling the CreateBuiltinFunction abstract operation.

10.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:

10.4.1 Bound Function Exotic Objects

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

An object is a bound function exotic object if its [[Call]] and (if applicable) [[Construct]] internal methods use the following implementations, and its other essential internal methods use the definitions found in 10.1. These methods are installed in BoundFunctionCreate.

Bound function exotic objects do not have the internal slots of ECMAScript function objects listed in Table 33. Instead they have the internal slots listed in Table 34, in addition to [[Prototype]] and [[Extensible]].

Table 34: Internal Slots of Bound Function Exotic 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.

10.4.1.1 [[Call]] ( thisArgument, argumentsList )

The [[Call]] internal method of a bound function exotic object F takes arguments thisArgument (an ECMAScript language value) and argumentsList (a List of ECMAScript language values). It performs the following steps when called:

  1. Let target be F.[[BoundTargetFunction]].
  2. Let boundThis be F.[[BoundThis]].
  3. Let boundArgs be F.[[BoundArguments]].
  4. Let args be the list-concatenation of boundArgs and argumentsList.
  5. Return ? Call(target, boundThis, args).

10.4.1.2 [[Construct]] ( argumentsList, newTarget )

The [[Construct]] internal method of a bound function exotic object F takes arguments argumentsList (a List of ECMAScript language values) and newTarget (a constructor). It performs the following steps when called:

  1. Let target be F.[[BoundTargetFunction]].
  2. Assert: IsConstructor(target) is true.
  3. Let boundArgs be F.[[BoundArguments]].
  4. Let args be the list-concatenation of boundArgs and argumentsList.
  5. If SameValue(F, newTarget) is true, set newTarget to target.
  6. Return ? Construct(target, args, newTarget).

10.4.1.3 BoundFunctionCreate ( targetFunction, boundThis, boundArgs )

The abstract operation BoundFunctionCreate takes arguments targetFunction, boundThis, and boundArgs. It is used to specify the creation of new bound function exotic objects. It performs the following steps when called:

  1. Assert: Type(targetFunction) is Object.
  2. Let proto be ? targetFunction.[[GetPrototypeOf]]().
  3. Let internalSlotsList be the internal slots listed in Table 34, plus [[Prototype]] and [[Extensible]].
  4. Let obj be ! MakeBasicObject(internalSlotsList).
  5. Set obj.[[Prototype]] to proto.
  6. Set obj.[[Call]] as described in 10.4.1.1.
  7. If IsConstructor(targetFunction) is true, then
    1. Set obj.[[Construct]] as described in 10.4.1.2.
  8. Set obj.[[BoundTargetFunction]] to targetFunction.
  9. Set obj.[[BoundThis]] to boundThis.
  10. Set obj.[[BoundArguments]] to boundArgs.
  11. Return obj.

10.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 non-configurable "length" property whose value is always a non-negative integral Number whose mathematical value is 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)) equals P and ToUint32(P) is not the same value as 𝔽(232 - 1).

An object is an Array exotic object (or simply, an Array object) if its [[DefineOwnProperty]] internal method uses the following implementation, and its other essential internal methods use the definitions found in 10.1. These methods are installed in ArrayCreate.

10.4.2.1 [[DefineOwnProperty]] ( P, Desc )

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

  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: ! IsDataDescriptor(oldLenDesc) is true.
    3. Assert: oldLenDesc.[[Configurable]] is false.
    4. Let oldLen be oldLenDesc.[[Value]].
    5. Assert: oldLen is a non-negative integral Number.
    6. Let index be ! ToUint32(P).
    7. If indexoldLen and oldLenDesc.[[Writable]] is false, return false.
    8. Let succeeded be ! OrdinaryDefineOwnProperty(A, P, Desc).
    9. If succeeded is false, return false.
    10. If indexoldLen, then
      1. Set oldLenDesc.[[Value]] to index + 1𝔽.
      2. Set succeeded to OrdinaryDefineOwnProperty(A, "length", oldLenDesc).
      3. Assert: succeeded is true.
    11. Return true.
  4. Return OrdinaryDefineOwnProperty(A, P, Desc).

10.4.2.2 ArrayCreate ( length [ , proto ] )

The abstract operation ArrayCreate takes argument length (a non-negative integer) and optional argument proto. It is used to specify the creation of new Array exotic objects. It performs the following steps when called:

  1. If length > 232 - 1, throw a RangeError exception.
  2. If proto is not present, set proto to %Array.prototype%.
  3. Let A be ! MakeBasicObject(« [[Prototype]], [[Extensible]] »).
  4. Set A.[[Prototype]] to proto.
  5. Set A.[[DefineOwnProperty]] as specified in 10.4.2.1.
  6. Perform ! OrdinaryDefineOwnProperty(A, "length", PropertyDescriptor { [[Value]]: 𝔽(length), [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }).
  7. Return A.

10.4.2.3 ArraySpeciesCreate ( originalArray, length )

The abstract operation ArraySpeciesCreate takes arguments originalArray and length (a non-negative integer). It 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 when called:

  1. Let isArray be ? IsArray(originalArray).
  2. If isArray is false, return ? ArrayCreate(length).
  3. Let C be ? Get(originalArray, "constructor").
  4. If IsConstructor(C) is true, then
    1. Let thisRealm be the current Realm Record.
    2. Let realmC be ? GetFunctionRealm(C).
    3. If thisRealm and realmC are not the same Realm Record, then
      1. If SameValue(C, realmC.[[Intrinsics]].[[%Array%]]) is true, set C to undefined.
  5. If Type(C) is Object, then
    1. Set C to ? Get(C, @@species).
    2. If C is null, set C to undefined.
  6. If C is undefined, return ? ArrayCreate(length).
  7. If IsConstructor(C) is false, throw a TypeError exception.
  8. 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.

10.4.2.4 ArraySetLength ( A, Desc )

The abstract operation ArraySetLength takes arguments A (an Array object) and Desc (a Property Descriptor). It performs the following steps when called:

  1. If Desc.[[Value]] 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. Let numberLen be ? ToNumber(Desc.[[Value]]).
  5. If SameValueZero(newLen, numberLen) is false, throw a RangeError exception.
  6. Set newLenDesc.[[Value]] to newLen.
  7. Let oldLenDesc be OrdinaryGetOwnProperty(A, "length").
  8. Assert: ! IsDataDescriptor(oldLenDesc) is true.
  9. Assert: oldLenDesc.[[Configurable]] is false.
  10. Let oldLen be oldLenDesc.[[Value]].
  11. If newLenoldLen, then
    1. Return OrdinaryDefineOwnProperty(A, "length", newLenDesc).
  12. If oldLenDesc.[[Writable]] is false, return false.
  13. If newLenDesc.[[Writable]] is absent or has the value true, let newWritable be true.
  14. Else,
    1. NOTE: Setting the [[Writable]] attribute to false is deferred in case any elements cannot be deleted.
    2. Let newWritable be false.
    3. Set newLenDesc.[[Writable]] to true.
  15. Let succeeded be ! OrdinaryDefineOwnProperty(A, "length", newLenDesc).
  16. If succeeded is false, return false.
  17. For each own property key P of A that is an array index, whose numeric value is greater than or equal to newLen, in descending numeric index order, do
    1. Let deleteSucceeded be ! A.[[Delete]](P).
    2. If deleteSucceeded is false, then
      1. Set newLenDesc.[[Value]] to ! ToUint32(P) + 1𝔽.
      2. If newWritable is false, set newLenDesc.[[Writable]] to false.
      3. Perform ! OrdinaryDefineOwnProperty(A, "length", newLenDesc).
      4. Return false.
  18. If newWritable is false, then
    1. Set succeeded to ! OrdinaryDefineOwnProperty(A, "length", PropertyDescriptor { [[Writable]]: false }).
    2. Assert: succeeded is true.
  19. 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.

10.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. String exotic 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.

An object is a String exotic object (or simply, a String object) if its [[GetOwnProperty]], [[DefineOwnProperty]], and [[OwnPropertyKeys]] internal methods use the following implementations, and its other essential internal methods use the definitions found in 10.1. These methods are installed in StringCreate.

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

10.4.3.1 [[GetOwnProperty]] ( P )

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

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

10.4.3.2 [[DefineOwnProperty]] ( P, Desc )

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

  1. Assert: IsPropertyKey(P) is true.
  2. Let stringDesc be ! StringGetOwnProperty(S, P).
  3. If stringDesc is not undefined, then
    1. Let extensible be S.[[Extensible]].
    2. Return ! IsCompatiblePropertyDescriptor(extensible, Desc, stringDesc).
  4. Return ! OrdinaryDefineOwnProperty(S, P, Desc).

10.4.3.3 [[OwnPropertyKeys]] ( )

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

  1. Let keys be a new empty List.
  2. Let str be O.[[StringData]].
  3. Assert: Type(str) is String.
  4. Let len be the length of str.
  5. For each integer i starting with 0 such that i < len, in ascending order, do
    1. Add ! ToString(𝔽(i)) as the last element of keys.
  6. For each own property key P of O such that P is an array index and ! ToIntegerOrInfinity(P) ≥ len, in ascending numeric index order, do
    1. Add P as the last element of keys.
  7. For each own property key P of O such that Type(P) is String and P is not an array index, in ascending chronological order of property creation, do
    1. Add P as the last element of keys.
  8. For each own property key P of O such that Type(P) is Symbol, in ascending chronological order of property creation, do
    1. Add P as the last element of keys.
  9. Return keys.

10.4.3.4 StringCreate ( value, prototype )

The abstract operation StringCreate takes arguments value (a String) and prototype. It is used to specify the creation of new String exotic objects. It performs the following steps when called:

  1. Let S be ! MakeBasicObject(« [[Prototype]], [[Extensible]], [[StringData]] »).
  2. Set S.[[Prototype]] to prototype.
  3. Set S.[[StringData]] to value.
  4. Set S.[[GetOwnProperty]] as specified in 10.4.3.1.
  5. Set S.[[DefineOwnProperty]] as specified in 10.4.3.2.
  6. Set S.[[OwnPropertyKeys]] as specified in 10.4.3.3.
  7. Let length be the number of code unit elements in value.
  8. Perform ! DefinePropertyOrThrow(S, "length", PropertyDescriptor { [[Value]]: 𝔽(length), [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }).
  9. Return S.

10.4.3.5 StringGetOwnProperty ( S, P )

The abstract operation StringGetOwnProperty takes arguments S and P. It performs the following steps when called:

  1. Assert: S is an Object that has a [[StringData]] internal slot.
  2. Assert: IsPropertyKey(P) is true.
  3. If Type(P) is not String, return undefined.
  4. Let index be ! CanonicalNumericIndexString(P).
  5. If index is undefined, return undefined.
  6. If IsIntegralNumber(index) is false, return undefined.
  7. If index is -0𝔽, return undefined.
  8. Let str be S.[[StringData]].
  9. Assert: Type(str) is String.
  10. Let len be the length of str.
  11. If (index) < 0 or len(index), return undefined.
  12. Let resultStr be the String value of length 1, containing one code unit from str, specifically the code unit at index (index).
  13. Return the PropertyDescriptor { [[Value]]: resultStr, [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: false }.

10.4.4 Arguments Exotic Objects

Most ECMAScript functions make an arguments object available to their code. Depending upon the characteristics of the function definition, its arguments 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.

An object is an arguments exotic object if its internal methods use the following implementations, with the ones not specified here using those found in 10.1. These methods are installed in CreateMappedArgumentsObject.

Note 1

While CreateUnmappedArgumentsObject is grouped into this clause, it creates an ordinary object, not an arguments exotic object.

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 (20.1.3.6) to identify them as such.

Note 2

The integer-indexed data properties of an arguments exotic 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. If the arguments object is an ordinary object, the values of its 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 3

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 4

Ordinary arguments objects define a non-configurable accessor property named "callee" which throws a TypeError exception on access. The "callee" property has a more specific meaning for arguments exotic objects, which are created only for some class of non-strict functions. The definition of this property in the ordinary variant exists to ensure that it is not defined in any other manner by conforming ECMAScript implementations.

Note 5

ECMAScript implementations of arguments exotic objects have historically contained an accessor property named "caller". Prior to ECMAScript 2017, this specification included the definition of a throwing "caller" property on ordinary arguments objects. Since implementations do not contain this extension any longer, ECMAScript 2017 dropped the requirement for a throwing "caller" accessor.

10.4.4.1 [[GetOwnProperty]] ( P )

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

  1. Let desc be OrdinaryGetOwnProperty(args, P).
  2. If desc is undefined, return desc.
  3. Let map be args.[[ParameterMap]].
  4. Let isMapped be ! HasOwnProperty(map, P).
  5. If isMapped is true, then
    1. Set desc.[[Value]] to Get(map, P).
  6. Return desc.

10.4.4.2 [[DefineOwnProperty]] ( P, Desc )

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

  1. Let map be args.[[ParameterMap]].
  2. Let isMapped be HasOwnProperty(map, P).
  3. Let newArgDesc be Desc.
  4. If isMapped is true and IsDataDescriptor(Desc) is true, then
    1. If Desc.[[Value]] is not present and Desc.[[Writable]] is present and its value is false, then
      1. Set newArgDesc to a copy of Desc.
      2. Set newArgDesc.[[Value]] to Get(map, P).
  5. Let allowed be ? OrdinaryDefineOwnProperty(args, P, newArgDesc).
  6. If allowed is false, return false.
  7. If 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.

10.4.4.3 [[Get]] ( P, Receiver )

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

  1. Let map be args.[[ParameterMap]].
  2. Let isMapped be ! HasOwnProperty(map, P).
  3. If isMapped is false, then
    1. Return ? OrdinaryGet(args, P, Receiver).
  4. Else,
    1. Assert: map contains a formal parameter mapping for P.
    2. Return Get(map, P).

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

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

  1. If SameValue(args, Receiver) is false, then
    1. Let isMapped be false.
  2. Else,
    1. Let map be args.[[ParameterMap]].
    2. Let isMapped be ! HasOwnProperty(map, P).
  3. 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.
  4. Return ? OrdinarySet(args, P, V, Receiver).

10.4.4.5 [[Delete]] ( P )

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

  1. Let map be args.[[ParameterMap]].
  2. Let isMapped be ! HasOwnProperty(map, P).
  3. Let result be ? OrdinaryDelete(args, P).
  4. If result is true and isMapped is true, then
    1. Call map.[[Delete]](P).
  5. Return result.

10.4.4.6 CreateUnmappedArgumentsObject ( argumentsList )

The abstract operation CreateUnmappedArgumentsObject takes argument argumentsList. It performs the following steps when called:

  1. Let len be the number of elements in argumentsList.
  2. Let obj be ! OrdinaryObjectCreate(%Object.prototype%, « [[ParameterMap]] »).
  3. Set obj.[[ParameterMap]] 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 ! CreateDataPropertyOrThrow(obj, ! ToString(𝔽(index)), val).
    3. Set index to index + 1.
  7. Perform ! DefinePropertyOrThrow(obj, @@iterator, PropertyDescriptor { [[Value]]: %Array.prototype.values%, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }).
  8. Perform ! DefinePropertyOrThrow(obj, "callee", PropertyDescriptor { [[Get]]: %ThrowTypeError%, [[Set]]: %ThrowTypeError%, [[Enumerable]]: false, [[Configurable]]: false }).
  9. Return obj.

10.4.4.7 CreateMappedArgumentsObject ( func, formals, argumentsList, env )

The abstract operation CreateMappedArgumentsObject takes arguments func (an Object), formals (a Parse Node), argumentsList (a List), and env (an Environment Record). It performs the following steps when called:

  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 ! MakeBasicObject(« [[Prototype]], [[Extensible]], [[ParameterMap]] »).
  4. Set obj.[[GetOwnProperty]] as specified in 10.4.4.1.
  5. Set obj.[[DefineOwnProperty]] as specified in 10.4.4.2.
  6. Set obj.[[Get]] as specified in 10.4.4.3.
  7. Set obj.[[Set]] as specified in 10.4.4.4.
  8. Set obj.[[Delete]] as specified in 10.4.4.5.
  9. Set obj.[[Prototype]] to %Object.prototype%.
  10. Let map be ! OrdinaryObjectCreate(null).
  11. Set obj.[[ParameterMap]] to map.
  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 ! CreateDataPropertyOrThrow(obj, ! ToString(𝔽(index)), val).
    3. Set index to index + 1.
  16. Perform ! DefinePropertyOrThrow(obj, "length", PropertyDescriptor { [[Value]]: 𝔽(len), [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }).
  17. Let mappedNames be a new empty List.
  18. Set index to numberOfParameters - 1.
  19. 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. Perform map.[[DefineOwnProperty]](! ToString(𝔽(index)), PropertyDescriptor { [[Set]]: p, [[Get]]: g, [[Enumerable]]: false, [[Configurable]]: true }).
    3. Set index to index - 1.
  20. Perform ! DefinePropertyOrThrow(obj, @@iterator, PropertyDescriptor { [[Value]]: %Array.prototype.values%, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }).
  21. Perform ! DefinePropertyOrThrow(obj, "callee", PropertyDescriptor { [[Value]]: func, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }).
  22. Return obj.

10.4.4.7.1 MakeArgGetter ( name, env )

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

  1. Let getterClosure be a new Abstract Closure with no parameters that captures name and env and performs the following steps when called:
    1. Return env.GetBindingValue(name, false).
  2. Let getter be ! CreateBuiltinFunction(getterClosure, 0, "", « »).
  3. NOTE: getter is never directly accessible to ECMAScript code.
  4. Return getter.

10.4.4.7.2 MakeArgSetter ( name, env )

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

  1. Let setterClosure be a new Abstract Closure with parameters (value) that captures name and env and performs the following steps when called:
    1. Return env.SetMutableBinding(name, value, false).
  2. Let setter be ! CreateBuiltinFunction(setterClosure, 1, "", « »).
  3. NOTE: setter is never directly accessible to ECMAScript code.
  4. Return setter.

10.4.5 Integer-Indexed Exotic Objects

An Integer-Indexed exotic 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 and additionally [[ViewedArrayBuffer]], [[ArrayLength]], [[ByteOffset]], [[ContentType]], and [[TypedArrayName]] internal slots.

An object is an Integer-Indexed exotic object if its [[GetOwnProperty]], [[HasProperty]], [[DefineOwnProperty]], [[Get]], [[Set]], [[Delete]], and [[OwnPropertyKeys]] internal methods use the definitions in this section, and its other essential internal methods use the definitions found in 10.1. These methods are installed by IntegerIndexedObjectCreate.

10.4.5.1 [[GetOwnProperty]] ( P )

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

  1. Assert: IsPropertyKey(P) is true.
  2. Assert: O is an Integer-Indexed exotic object.
  3. If Type(P) is String, then
    1. Let numericIndex be ! CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. Let value be ! IntegerIndexedElementGet(O, numericIndex).
      2. If value is undefined, return undefined.
      3. Return the PropertyDescriptor { [[Value]]: value, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }.
  4. Return OrdinaryGetOwnProperty(O, P).

10.4.5.2 [[HasProperty]] ( P )

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

  1. Assert: IsPropertyKey(P) is true.
  2. Assert: O is an Integer-Indexed exotic object.
  3. If Type(P) is String, then
    1. Let numericIndex be ! CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, return ! IsValidIntegerIndex(O, numericIndex).
  4. Return ? OrdinaryHasProperty(O, P).

10.4.5.3 [[DefineOwnProperty]] ( P, Desc )

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

  1. Assert: IsPropertyKey(P) is true.
  2. Assert: O is an Integer-Indexed exotic object.
  3. If Type(P) is String, then
    1. Let numericIndex be ! CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. If ! IsValidIntegerIndex(O, numericIndex) is false, return false.
      2. If Desc has a [[Configurable]] field and if Desc.[[Configurable]] is false, return false.
      3. If Desc has an [[Enumerable]] field and if Desc.[[Enumerable]] is false, return false.
      4. If ! IsAccessorDescriptor(Desc) is true, return false.
      5. If Desc has a [[Writable]] field and if Desc.[[Writable]] is false, return false.
      6. If Desc has a [[Value]] field, perform ? IntegerIndexedElementSet(O, numericIndex, Desc.[[Value]]).
      7. Return true.
  4. Return ! OrdinaryDefineOwnProperty(O, P, Desc).

10.4.5.4 [[Get]] ( P, Receiver )

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

  1. Assert: IsPropertyKey(P) is true.
  2. If Type(P) is String, then
    1. Let numericIndex be ! CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. Return ! IntegerIndexedElementGet(O, numericIndex).
  3. Return ? OrdinaryGet(O, P, Receiver).

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

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

  1. Assert: IsPropertyKey(P) is true.
  2. If Type(P) is String, then
    1. Let numericIndex be ! CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. Perform ? IntegerIndexedElementSet(O, numericIndex, V).
      2. Return true.
  3. Return ? OrdinarySet(O, P, V, Receiver).

10.4.5.6 [[Delete]] ( P )

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

  1. Assert: IsPropertyKey(P) is true.
  2. Assert: O is an Integer-Indexed exotic object.
  3. If Type(P) is String, then
    1. Let numericIndex be ! CanonicalNumericIndexString(P).
    2. If numericIndex is not undefined, then
      1. If ! IsValidIntegerIndex(O, numericIndex) is false, return true; else return false.
  4. Return ? OrdinaryDelete(O, P).

10.4.5.7 [[OwnPropertyKeys]] ( )

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

  1. Let keys be a new empty List.
  2. Assert: O is an Integer-Indexed exotic object.
  3. If IsDetachedBuffer(O.[[ViewedArrayBuffer]]) is false, then
    1. For each integer i starting with 0 such that i < O.[[ArrayLength]], in ascending order, do
      1. Add ! ToString(𝔽(i)) as the last element of keys.
  4. For each own property key P of O such that Type(P) is String and P is not an integer index, in ascending chronological order of property creation, do
    1. Add P as the last element of keys.
  5. For each own property key P of O such that Type(P) is Symbol, in ascending chronological order of property creation, do
    1. Add P as the last element of keys.
  6. Return keys.

10.4.5.8 IntegerIndexedObjectCreate ( prototype )

The abstract operation IntegerIndexedObjectCreate takes argument prototype. It is used to specify the creation of new Integer-Indexed exotic objects. It performs the following steps when called:

  1. Let internalSlotsList be « [[Prototype]], [[Extensible]], [[ViewedArrayBuffer]], [[TypedArrayName]], [[ContentType]], [[ByteLength]], [[ByteOffset]], [[ArrayLength]] ».
  2. Let A be ! MakeBasicObject(internalSlotsList).
  3. Set A.[[GetOwnProperty]] as specified in 10.4.5.1.
  4. Set A.[[HasProperty]] as specified in 10.4.5.2.
  5. Set A.[[DefineOwnProperty]] as specified in 10.4.5.3.
  6. Set A.[[Get]] as specified in 10.4.5.4.
  7. Set A.[[Set]] as specified in 10.4.5.5.
  8. Set A.[[Delete]] as specified in 10.4.5.6.
  9. Set A.[[OwnPropertyKeys]] as specified in 10.4.5.7.
  10. Set A.[[Prototype]] to prototype.
  11. Return A.

10.4.5.9 IsValidIntegerIndex ( O, index )

The abstract operation IsValidIntegerIndex takes arguments O and index (a Number). It performs the following steps when called:

  1. Assert: O is an Integer-Indexed exotic object.
  2. If IsDetachedBuffer(O.[[ViewedArrayBuffer]]) is true, return false.
  3. If ! IsIntegralNumber(index) is false, return false.
  4. If index is -0𝔽, return false.
  5. If (index) < 0 or (index) ≥ O.[[ArrayLength]], return false.
  6. Return true.

10.4.5.10 IntegerIndexedElementGet ( O, index )

The abstract operation IntegerIndexedElementGet takes arguments O and index (a Number). It performs the following steps when called:

  1. Assert: O is an Integer-Indexed exotic object.
  2. If ! IsValidIntegerIndex(O, index) is false, return undefined.
  3. Let offset be O.[[ByteOffset]].
  4. Let arrayTypeName be the String value of O.[[TypedArrayName]].
  5. Let elementSize be the Element Size value specified in Table 63 for arrayTypeName.
  6. Let indexedPosition be ((index) × elementSize) + offset.
  7. Let elementType be the Element Type value in Table 63 for arrayTypeName.
  8. Return GetValueFromBuffer(O.[[ViewedArrayBuffer]], indexedPosition, elementType, true, Unordered).

10.4.5.11 IntegerIndexedElementSet ( O, index, value )

The abstract operation IntegerIndexedElementSet takes arguments O, index (a Number), and value. It performs the following steps when called:

  1. Assert: O is an Integer-Indexed exotic object.
  2. If O.[[ContentType]] is BigInt, let numValue be ? ToBigInt(value).
  3. Otherwise, let numValue be ? ToNumber(value).
  4. If ! IsValidIntegerIndex(O, index) is true, then
    1. Let offset be O.[[ByteOffset]].
    2. Let arrayTypeName be the String value of O.[[TypedArrayName]].
    3. Let elementSize be the Element Size value specified in Table 63 for arrayTypeName.
    4. Let indexedPosition be ((index) × elementSize) + offset.
    5. Let elementType be the Element Type value in Table 63 for arrayTypeName.
    6. Perform SetValueInBuffer(O.[[ViewedArrayBuffer]], indexedPosition, elementType, numValue, true, Unordered).
  5. Return NormalCompletion(undefined).
Note

This operation always appears to succeed, but it has no effect when attempting to write past the end of a TypedArray or to a TypedArray which is backed by a detached ArrayBuffer.

10.4.6 Module Namespace Exotic Objects

A module namespace exotic object is an exotic object that exposes the bindings exported from an ECMAScript Module (See 16.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 { [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: false }. Module namespace exotic objects are not extensible.

An object is a module namespace exotic object if its [[SetPrototypeOf]], [[IsExtensible]], [[PreventExtensions]], [[GetOwnProperty]], [[DefineOwnProperty]], [[HasProperty]], [[Get]], [[Set]], [[Delete]], and [[OwnPropertyKeys]] internal methods use the definitions in this section, and its other essential internal methods use the definitions found in 10.1. These methods are installed by ModuleNamespaceCreate.

Module namespace exotic objects have the internal slots defined in Table 35.

Table 35: 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 whose elements are 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 undefined as comparefn.
[[Prototype]] Null This slot always contains the value null (see 10.4.6.1).

Module namespace exotic objects provide alternative definitions for all of the internal methods except [[GetPrototypeOf]], which behaves as defined in 10.1.1.

10.4.6.1 [[SetPrototypeOf]] ( V )

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

  1. Return ? SetImmutablePrototype(O, V).

10.4.6.2 [[IsExtensible]] ( )

The [[IsExtensible]] internal method of a module namespace exotic object takes no arguments. It performs the following steps when called:

  1. Return false.

10.4.6.3 [[PreventExtensions]] ( )

The [[PreventExtensions]] internal method of a module namespace exotic object takes no arguments. It performs the following steps when called:

  1. Return true.

10.4.6.4 [[GetOwnProperty]] ( P )

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

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

10.4.6.5 [[DefineOwnProperty]] ( P, Desc )

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

  1. If Type(P) is Symbol, return OrdinaryDefineOwnProperty(O, P, Desc).
  2. Let current be ? O.[[GetOwnProperty]](P).
  3. If current is undefined, return false.
  4. If Desc.[[Configurable]] is present and has value true, return false.
  5. If Desc.[[Enumerable]] is present and has value false, return false.
  6. If ! IsAccessorDescriptor(Desc) is true, return false.
  7. If Desc.[[Writable]] is present and has value false, return false.
  8. If Desc.[[Value]] is present, return SameValue(Desc.[[Value]], current.[[Value]]).
  9. Return true.

10.4.6.6 [[HasProperty]] ( P )

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

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

10.4.6.7 [[Get]] ( P, Receiver )

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

  1. Assert: IsPropertyKey(P) is true.
  2. If Type(P) is Symbol, then
    1. Return ? OrdinaryGet(O, P, Receiver).
  3. Let exports be O.[[Exports]].
  4. If P is not an element of exports, return undefined.
  5. Let m be O.[[Module]].
  6. Let binding be ! m.ResolveExport(P).
  7. Assert: binding is a ResolvedBinding Record.
  8. Let targetModule be binding.[[Module]].
  9. Assert: targetModule is not undefined.
  10. If binding.[[BindingName]] is "*namespace*", then
    1. Return ? GetModuleNamespace(targetModule).
  11. Let targetEnv be targetModule.[[Environment]].
  12. If targetEnv is undefined, throw a ReferenceError exception.
  13. Return ? targetEnv.GetBindingValue(binding.[[BindingName]], true).
Note

ResolveExport is side-effect free. Each time this operation is called with a specific exportName, resolveSet pair as arguments it must return the same result. An implementation might choose to pre-compute or cache the ResolveExport results for the [[Exports]] of each module namespace exotic object.

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

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

  1. Return false.

10.4.6.9 [[Delete]] ( P )

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

  1. Assert: IsPropertyKey(P) is true.
  2. If Type(P) is Symbol, then
    1. Return ? OrdinaryDelete(O, P).
  3. Let exports be O.[[Exports]].
  4. If P is an element of exports, return false.
  5. Return true.

10.4.6.10 [[OwnPropertyKeys]] ( )

The [[OwnPropertyKeys]] internal method of a module namespace exotic object O takes no arguments. It performs the following steps when called:

  1. Let exports be O.[[Exports]].
  2. Let symbolKeys be ! OrdinaryOwnPropertyKeys(O).
  3. Return the list-concatenation of exports and symbolKeys.

10.4.6.11 ModuleNamespaceCreate ( module, exports )

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

  1. Assert: module is a Module Record.
  2. Assert: module.[[Namespace]] is undefined.
  3. Assert: exports is a List of String values.
  4. Let internalSlotsList be the internal slots listed in Table 35.
  5. Let M be ! MakeBasicObject(internalSlotsList).
  6. Set M's essential internal methods to the definitions specified in 10.4.6.
  7. Set M.[[Prototype]] to null.
  8. Set M.[[Module]] to module.
  9. Let sortedExports be a List whose elements are the elements of exports ordered as if an Array of the same values had been sorted using %Array.prototype.sort% using undefined as comparefn.
  10. Set M.[[Exports]] to sortedExports.
  11. Create own properties of M corresponding to the definitions in 28.3.
  12. Set module.[[Namespace]] to M.
  13. Return M.

10.4.7 Immutable Prototype Exotic Objects

An immutable prototype exotic object is an exotic object that has a [[Prototype]] internal slot that will not change once it is initialized.

An object is an immutable prototype exotic object if its [[SetPrototypeOf]] internal method uses the following implementation. (Its other essential internal methods may use any implementation, depending on the specific immutable prototype exotic object in question.)

Note

Unlike other exotic objects, there is not a dedicated creation abstract operation provided for immutable prototype exotic objects. This is because they are only used by %Object.prototype% and by host environments, and in host environments, the relevant objects are potentially exotic in other ways and thus need their own dedicated creation operation.

10.4.7.1 [[SetPrototypeOf]] ( V )

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

  1. Return ? SetImmutablePrototype(O, V).

10.4.7.2 SetImmutablePrototype ( O, V )

The abstract operation SetImmutablePrototype takes arguments O and V. It performs the following steps when called:

  1. Assert: Either Type(V) is Object or Type(V) is Null.
  2. Let current be ? O.[[GetPrototypeOf]]().
  3. If SameValue(V, current) is true, return true.
  4. Return false.

10.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 object has an internal slot called [[ProxyHandler]]. The value of [[ProxyHandler]] is an object, called the proxy's handler object, or null. Methods (see Table 36) 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.

An object is a Proxy exotic object if its essential internal methods (including [[Call]] and [[Construct]], if applicable) use the definitions in this section. These internal methods are installed in ProxyCreate.

Table 36: Proxy Handler Methods
Internal Method Handler Method
[[GetPrototypeOf]] getPrototypeOf
[[SetPrototypeOf]] setPrototypeOf
[[IsExtensible]] isExtensible
[[PreventExtensions]] preventExtensions
[[GetOwnProperty]] getOwnPropertyDescriptor
[[DefineOwnProperty]] defineProperty
[[HasProperty]] has
[[Get]] get
[[Set]] set
[[Delete]] deleteProperty
[[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 [[ProxyHandler]] 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.

10.5.1 [[GetPrototypeOf]] ( )

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

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

[[GetPrototypeOf]] for proxy objects enforces the following invariants:

  • 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.

10.5.2 [[SetPrototypeOf]] ( V )

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

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

[[SetPrototypeOf]] for proxy objects enforces the following invariants:

  • 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.

10.5.3 [[IsExtensible]] ( )

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

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

[[IsExtensible]] for proxy objects enforces the following invariants:

  • 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.

10.5.4 [[PreventExtensions]] ( )

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

  1. Let handler be O.[[ProxyHandler]].
  2. If handler is null, throw a TypeError exception.
  3. Assert: Type(handler) is Object.
  4. Let target be O.[[ProxyTarget]].
  5. Let trap be ? GetMethod(handler, "preventExtensions").
  6. If trap is undefined, then
    1. Return ? target.[[PreventExtensions]]().
  7. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target »)).
  8. If booleanTrapResult is true, then
    1. Let extensibleTarget be ? IsExtensible(target).
    2. If extensibleTarget is true, throw a TypeError exception.
  9. Return booleanTrapResult.
Note

[[PreventExtensions]] for proxy objects enforces the following invariants:

  • 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.

10.5.5 [[GetOwnProperty]] ( P )

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

  1. Assert: IsPropertyKey(P) is true.
  2. Let handler be O.[[ProxyHandler]].
  3. If handler is null, throw a TypeError exception.
  4. Assert: Type(handler) is Object.
  5. Let target be O.[[ProxyTarget]].
  6. Let trap be ? GetMethod(handler, "getOwnPropertyDescriptor").
  7. If trap is undefined, then
    1. Return ? target.[[GetOwnProperty]](P).
  8. Let trapResultObj be ? Call(trap, handler, « target, P »).
  9. If Type(trapResultObj) is neither Object nor Undefined, throw a TypeError exception.
  10. Let targetDesc be ? target.[[GetOwnProperty]](P).
  11. 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. If extensibleTarget is false, throw a TypeError exception.
    5. Return undefined.
  12. Let extensibleTarget be ? IsExtensible(target).
  13. Let resultDesc be ? ToPropertyDescriptor(trapResultObj).
  14. Call CompletePropertyDescriptor(resultDesc).
  15. Let valid be IsCompatiblePropertyDescriptor(extensibleTarget, resultDesc, targetDesc).
  16. If valid is false, throw a TypeError exception.
  17. If resultDesc.[[Configurable]] is false, then
    1. If targetDesc is undefined or targetDesc.[[Configurable]] is true, then
      1. Throw a TypeError exception.
    2. If resultDesc has a [[Writable]] field and resultDesc.[[Writable]] is false, then
      1. If targetDesc.[[Writable]] is true, throw a TypeError exception.
  18. 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 the target object is not extensible, unless it does not exist as an own property of the target object.
  • A property cannot be reported as existent, if the target object is not extensible, unless it exists as an own property of the target object.
  • A property cannot be reported as non-configurable, unless it exists as a non-configurable own property of the target object.
  • A property cannot be reported as both non-configurable and non-writable, unless it exists as a non-configurable, non-writable own property of the target object.

10.5.6 [[DefineOwnProperty]] ( P, Desc )

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

  1. Assert: IsPropertyKey(P) is true.
  2. Let handler be O.[[ProxyHandler]].
  3. If handler is null, throw a TypeError exception.
  4. Assert: Type(handler) is Object.
  5. Let target be O.[[ProxyTarget]].
  6. Let trap be ? GetMethod(handler, "defineProperty").
  7. If trap is undefined, then
    1. Return ? target.[[DefineOwnProperty]](P, Desc).
  8. Let descObj be FromPropertyDescriptor(Desc).
  9. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, P, descObj »)).
  10. If booleanTrapResult is false, return false.
  11. Let targetDesc be ? target.[[GetOwnProperty]](P).
  12. Let extensibleTarget be ? IsExtensible(target).
  13. If Desc has a [[Configurable]] field and if Desc.[[Configurable]] is false, then
    1. Let settingConfigFalse be true.
  14. Else, let settingConfigFalse be false.
  15. If targetDesc is undefined, then
    1. If extensibleTarget is false, throw a TypeError exception.
    2. If settingConfigFalse is true, throw a TypeError exception.
  16. Else,
    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.
    3. If IsDataDescriptor(targetDesc) is true, targetDesc.[[Configurable]] is false, and targetDesc.[[Writable]] is true, then
      1. If Desc has a [[Writable]] field and Desc.[[Writable]] is false, throw a TypeError exception.
  17. 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.
  • A non-configurable property cannot be non-writable, unless there exists a corresponding non-configurable, non-writable 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.

10.5.7 [[HasProperty]] ( P )

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

  1. Assert: IsPropertyKey(P) is true.
  2. Let handler be O.[[ProxyHandler]].
  3. If handler is null, throw a TypeError exception.
  4. Assert: Type(handler) is Object.
  5. Let target be O.[[ProxyTarget]].
  6. Let trap be ? GetMethod(handler, "has").
  7. If trap is undefined, then
    1. Return ? target.[[HasProperty]](P).
  8. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, P »)).
  9. If booleanTrapResult is false, then
    1. Let targetDesc be ? target.[[GetOwnProperty]](P).
    2. If targetDesc is not undefined, then
      1. If targetDesc.[[Configurable]] is false, throw a TypeError exception.
      2. Let extensibleTarget be ? IsExtensible(target).
      3. If extensibleTarget is false, throw a TypeError exception.
  10. 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.

10.5.8 [[Get]] ( P, Receiver )

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

  1. Assert: IsPropertyKey(P) is true.
  2. Let handler be O.[[ProxyHandler]].
  3. If handler is null, throw a TypeError exception.
  4. Assert: Type(handler) is Object.
  5. Let target be O.[[ProxyTarget]].
  6. Let trap be ? GetMethod(handler, "get").
  7. If trap is undefined, then
    1. Return ? target.[[Get]](P, Receiver).
  8. Let trapResult be ? Call(trap, handler, « target, P, Receiver »).
  9. Let targetDesc be ? target.[[GetOwnProperty]](P).
  10. If targetDesc is not undefined and targetDesc.[[Configurable]] is false, then
    1. If IsDataDescriptor(targetDesc) is true and targetDesc.[[Writable]] is false, then
      1. If SameValue(trapResult, targetDesc.[[Value]]) is false, throw a TypeError exception.
    2. If IsAccessorDescriptor(targetDesc) is true and targetDesc.[[Get]] is undefined, then
      1. If trapResult is not undefined, throw a TypeError exception.
  11. 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.

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

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

  1. Assert: IsPropertyKey(P) is true.
  2. Let handler be O.[[ProxyHandler]].
  3. If handler is null, throw a TypeError exception.
  4. Assert: Type(handler) is Object.
  5. Let target be O.[[ProxyTarget]].
  6. Let trap be ? GetMethod(handler, "set").
  7. If trap is undefined, then
    1. Return ? target.[[Set]](P, V, Receiver).
  8. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, P, V, Receiver »)).
  9. If booleanTrapResult is false, return false.
  10. Let targetDesc be ? target.[[GetOwnProperty]](P).
  11. If targetDesc is not undefined and targetDesc.[[Configurable]] is false, then
    1. If IsDataDescriptor(targetDesc) is true and targetDesc.[[Writable]] is false, then
      1. If SameValue(V, targetDesc.[[Value]]) is false, throw a TypeError exception.
    2. If IsAccessorDescriptor(targetDesc) is true, then
      1. If targetDesc.[[Set]] is undefined, throw a TypeError exception.
  12. 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.

10.5.10 [[Delete]] ( P )

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

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

[[Delete]] for proxy objects enforces the following invariants:

  • 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.
  • A property cannot be reported as deleted, if it exists as an own property of the target object and the target object is non-extensible.

10.5.11 [[OwnPropertyKeys]] ( )

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

  1. Let handler be O.[[ProxyHandler]].
  2. If handler is null, throw a TypeError exception.
  3. Assert: Type(handler) is Object.
  4. Let target be O.[[ProxyTarget]].
  5. Let trap be ? GetMethod(handler, "ownKeys").
  6. If trap is undefined, then
    1. Return ? target.[[OwnPropertyKeys]]().
  7. Let trapResultArray be ? Call(trap, handler, « target »).
  8. Let trapResult be ? CreateListFromArrayLike(trapResultArray, « String, Symbol »).
  9. If trapResult contains any duplicate entries, throw a TypeError exception.
  10. Let extensibleTarget be ? IsExtensible(target).
  11. Let targetKeys be ? target.[[OwnPropertyKeys]]().
  12. Assert: targetKeys is a List whose elements are only String and Symbol values.
  13. Assert: targetKeys contains no duplicate entries.
  14. Let targetConfigurableKeys be a new empty List.
  15. Let targetNonconfigurableKeys be a new empty List.
  16. For each element key of targetKeys, do
    1. Let desc be ? target.[[GetOwnProperty]](key).
    2. If desc is not undefined and desc.[[Configurable]] is false, then
      1. Append key as an element of targetNonconfigurableKeys.
    3. Else,
      1. Append key as an element of targetConfigurableKeys.
  17. If extensibleTarget is true and targetNonconfigurableKeys is empty, then
    1. Return trapResult.
  18. Let uncheckedResultKeys be a List whose elements are the elements of trapResult.
  19. For each element key of targetNonconfigurableKeys, do
    1. If key is not an element of uncheckedResultKeys, throw a TypeError exception.
    2. Remove key from uncheckedResultKeys.
  20. If extensibleTarget is true, return trapResult.
  21. For each element key of targetConfigurableKeys, do
    1. If key is not an element of uncheckedResultKeys, throw a TypeError exception.
    2. Remove key from uncheckedResultKeys.
  22. If uncheckedResultKeys is not empty, throw a TypeError exception.
  23. Return trapResult.
Note

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

  • The result of [[OwnPropertyKeys]] is a List.
  • The returned List contains no duplicate entries.
  • 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.

10.5.12 [[Call]] ( thisArgument, argumentsList )

The [[Call]] internal method of a Proxy exotic object O takes arguments thisArgument (an ECMAScript language value) and argumentsList (a List of ECMAScript language values). It performs the following steps when called:

  1. Let handler be O.[[ProxyHandler]].
  2. If handler is null, throw a TypeError exception.
  3. Assert: Type(handler) is Object.
  4. Let target be O.[[ProxyTarget]].
  5. Let trap be ? GetMethod(handler, "apply").
  6. If trap is undefined, then
    1. Return ? Call(target, thisArgument, argumentsList).
  7. Let argArray be ! CreateArrayFromList(argumentsList).
  8. 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.

10.5.13 [[Construct]] ( argumentsList, newTarget )

The [[Construct]] internal method of a Proxy exotic object O takes arguments argumentsList (a List of ECMAScript language values) and newTarget (a constructor). It performs the following steps when called:

  1. Let handler be O.[[ProxyHandler]].
  2. If handler is null, throw a TypeError exception.
  3. Assert: Type(handler) is Object.
  4. Let target be O.[[ProxyTarget]].
  5. Assert: IsConstructor(target) is true.
  6. Let trap be ? GetMethod(handler, "construct").
  7. If trap is undefined, then
    1. Return ? Construct(target, argumentsList, newTarget).
  8. Let argArray be ! CreateArrayFromList(argumentsList).
  9. Let newObj be ? Call(trap, handler, « target, argArray, newTarget »).
  10. If Type(newObj) is not Object, throw a TypeError exception.
  11. 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.

10.5.14 ProxyCreate ( target, handler )

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

  1. If Type(target) is not Object, throw a TypeError exception.
  2. If Type(handler) is not Object, throw a TypeError exception.
  3. Let P be ! MakeBasicObject(« [[ProxyHandler]], [[ProxyTarget]] »).
  4. Set P's essential internal methods, except for [[Call]] and [[Construct]], to the definitions specified in 10.5.
  5. If IsCallable(target) is true, then
    1. Set P.[[Call]] as specified in 10.5.12.
    2. If IsConstructor(target) is true, then
      1. Set P.[[Construct]] as specified in 10.5.13.
  6. Set P.[[ProxyTarget]] to target.
  7. Set P.[[ProxyHandler]] to handler.
  8. Return P.