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 29. Instead they have the internal slots listed in Table 30, in addition to [[Prototype]] and [[Extensible]].

Table 30: 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 a List whose elements are the elements of boundArgs, followed by the elements of 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 a List whose elements are the elements of boundArgs, followed by the elements of 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 30, 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 index ≥ oldLen and oldLenDesc.[[Writable]] is false, return false.
    8. Let succeeded be ! OrdinaryDefineOwnProperty(A, P, Desc).
    9. If succeeded is false, return false.
    10. If index ≥ oldLen, then
      1. Set oldLenDesc.[[Value]] to index + 1𝔽.
      2. Let succeeded be OrdinaryDefineOwnProperty(A, "length", oldLenDesc).
      3. Assert: succeeded is true.
    11. Return true.
  4. Return OrdinaryDefineOwnProperty(A, P, Desc).

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 newLen is not the same value as numberLen, 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 newLen ≥ oldLen, 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. Let succeeded be ! 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. Let index be 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 steps be the steps of an ArgGetter function as specified below.
  2. Let length be the number of non-optional parameters of an ArgGetter function as specified below.
  3. Let getter be ! CreateBuiltinFunction(steps, length, "", « [[Name]], [[Env]] »).
  4. Set getter.[[Name]] to name.
  5. Set getter.[[Env]] to env.
  6. Return getter.

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

  1. Let f be the active function object.
  2. Let name be f.[[Name]].
  3. Let env be f.[[Env]].
  4. Return env.GetBindingValue(name, false).
Note

ArgGetter functions are never directly accessible to ECMAScript code.

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 steps be the steps of an ArgSetter function as specified below.
  2. Let length be the number of non-optional parameters of an ArgSetter function as specified below.
  3. Let setter be ! CreateBuiltinFunction(steps, length, "", « [[Name]], [[Env]] »).
  4. Set setter.[[Name]] to name.
  5. Set setter.[[Env]] to env.
  6. Return setter.

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

  1. Let f be the active function object.
  2. Let name be f.[[Name]].
  3. Let env be f.[[Env]].
  4. Return env.SetMutableBinding(name, value, false).
Note

ArgSetter functions are never directly accessible to ECMAScript code.

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 IsAccessorDescriptor(Desc) is true, return false.
      3. If Desc has a [[Configurable]] field and if Desc.[[Configurable]] is false, return false.
      4. If Desc has an [[Enumerable]] field and if Desc.[[Enumerable]] is false, 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 arguments 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 60 for arrayTypeName.
  6. Let indexedPosition be (ℝ(index) × elementSize) + offset.
  7. Let elementType be the Element Type value in Table 60 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 60 for arrayTypeName.
    4. Let indexedPosition be (ℝ(index) × elementSize) + offset.
    5. Let elementType be the Element Type value in Table 60 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 31.

Table 31: 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 IsAccessorDescriptor(Desc) is true, return false.
  5. If Desc.[[Writable]] is present and has value false, return false.
  6. If Desc.[[Enumerable]] is present and has value false, return false.
  7. If Desc.[[Configurable]] is present and has value true, 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 a copy of O.[[Exports]].
  2. Let symbolKeys be ! OrdinaryOwnPropertyKeys(O).
  3. Append all the entries of symbolKeys to the end of exports.
  4. Return exports.

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