Annotated ECMAScript 5.1

‟Ex igne vita”

8 Types #

Algorithms within this specification manipulate values each of which has an associated type. The possible value types are exactly those defined in this clause. Types are further subclassified into ECMAScript language types and specification types.

An ECMAScript language type corresponds to values that are directly manipulated by an ECMAScript programmer using the ECMAScript language. The ECMAScript language types are Undefined, Null, Boolean, String, Number, and Object.

A specification type corresponds to meta-values that are used within algorithms to describe the semantics of ECMAScript language constructs and ECMAScript language types. The specification types are Reference, List, Completion, Property Descriptor, Property Identifier, Lexical Environment, and Environment Record. Specification type values are specification artefacts that do not necessarily correspond to any specific entity within an ECMAScript implementation. Specification type values may be used to describe intermediate results of ECMAScript expression evaluation but such values cannot be stored as properties of objects or values of ECMAScript language variables.

Within this specification, the notation “Type(x)” is used as shorthand for “the type of x” where “type” refers to the ECMAScript language and specification types defined in this clause.

8.1 The Undefined Type #

The Undefined type has exactly one value, called undefined. Any variable that has not been assigned a value has the value undefined.

8.2 The Null Type #

The Null type has exactly one value, called null.

8.3 The Boolean Type #

The Boolean type represents a logical entity having two values, called true and false.

8.4 The String Type #

The String type is the set of all finite ordered sequences of zero or more 16-bit unsigned integer values (“elements”). The String type is generally used to represent textual data in a running ECMAScript program, in which case each element in the String is treated as a code unit value (see Clause 6). Each element is regarded as occupying a position within the sequence. These positions are indexed with nonnegative integers. The first element (if any) is at position 0, the next element (if any) at position 1, and so on. The length of a String is the number of elements (i.e., 16-bit values) within it. The empty String has length zero and therefore contains no elements.

When a String contains actual textual data, each element is considered to be a single UTF-16 code unit. Whether or not this is the actual storage format of a String, the characters within a String are numbered by their initial code unit element position as though they were represented using UTF-16. All operations on Strings (except as otherwise stated) treat them as sequences of undifferentiated 16-bit unsigned integers; they do not ensure the resulting String is in normalised form, nor do they ensure language-sensitive results.

NOTE The rationale behind this design was to keep the implementation of Strings as simple and high-performing as possible. The intent is that textual data coming into the execution environment from outside (e.g., user input, text read from a file or received over the network, etc.) be converted to Unicode Normalised Form C before the running program sees it. Usually this would occur at the same time incoming text is converted from its original character encoding to Unicode (and would impose no additional overhead). Since it is recommended that ECMAScript source code be in Normalised Form C, string literals are guaranteed to be normalised (if source text is guaranteed to be normalised), as long as they do not contain any Unicode escape sequences.

8.5 The Number Type #

The Number type has exactly 18437736874454810627 (that is, 264253+3) values, representing the double-precision 64-bit format IEEE 754 values as specified in the IEEE Standard for Binary Floating-Point Arithmetic, except that the 9007199254740990 (that is, 2532) distinct “Not-a-Number” values of the IEEE Standard are represented in ECMAScript as a single special NaN value. (Note that the NaN value is produced by the program expression NaN.) In some implementations, external code might be able to detect a difference between various Not-a-Number values, but such behaviour is implementation-dependent; to ECMAScript code, all NaN values are indistinguishable from each other.

There are two other special values, called positive Infinity and negative Infinity. For brevity, these values are also referred to for expository purposes by the symbols + and −∞, respectively. (Note that these two infinite Number values are produced by the program expressions +Infinity (or simply Infinity) and -Infinity.)

The other 18437736874454810624 (that is, 264253) values are called the finite numbers. Half of these are positive numbers and half are negative numbers; for every finite positive Number value there is a corresponding negative value having the same magnitude.

Note that there is both a positive zero and a negative zero. For brevity, these values are also referred to for expository purposes by the symbols +0 and 0, respectively. (Note that these two different zero Number values are produced by the program expressions +0 (or simply 0) and -0.)

The 18437736874454810622 (that is, 2642532) finite nonzero values are of two kinds:

18428729675200069632 (that is, 264254) of them are normalised, having the form

s × m × 2e

where s is +1 or 1, m is a positive integer less than 253 but not less than 252, and e is an integer ranging from 1074 to 971, inclusive.

The remaining 9007199254740990 (that is, 2532) values are denormalised, having the form

s × m × 2e

where s is +1 or 1, m is a positive integer less than 252, and e is 1074.

Note that all the positive and negative integers whose magnitude is no greater than 253 are representable in the Number type (indeed, the integer 0 has two representations, +0 and -0).

A finite number has an odd significand if it is nonzero and the integer m used to express it (in one of the two forms shown above) is odd. Otherwise, it has an even significand.

In this specification, the phrase “the Number value for x” where x represents an exact nonzero real mathematical quantity (which might even be an irrational number such as π) means a Number value chosen in the following manner. Consider the set of all finite values of the Number type, with 0 removed and with two additional values added to it that are not representable in the Number type, namely 21024 (which is +1 × 253× 2971) and 21024 (which is 1 × 253× 2971). Choose the member of this set that is closest in value to x. If two values of the set are equally close, then the one with an even significand is chosen; for this purpose, the two extra values 21024 and 21024 are considered to have even significands. Finally, if 21024 was chosen, replace it with +; if 21024 was chosen, replace it with −∞; if +0 was chosen, replace it with 0 if and only if x is less than zero; any other chosen value is used unchanged. The result is the Number value for x. (This procedure corresponds exactly to the behaviour of the IEEE 754 “round to nearest” mode.)

Some ECMAScript operators deal only with integers in the range 231 through 2311, inclusive, or in the range 0 through 2321, inclusive. These operators accept any value of the Number type but first convert each such value to one of 232 integer values. See the descriptions of the ToInt32 and ToUint32 operators in 9.5 and 9.6, respectively.

8.6 The Object Type #

An Object is a collection of properties. Each property is either a named data property, a named accessor property, or an internal property:

There are two kinds of access for named (non-internal) properties: get and put, corresponding to retrieval and assignment, respectively.

8.6.1 Property Attributes #

Attributes are used in this specification to define and explain the state of named properties. A named data property associates a name with the attributes listed in Table 5

Table 5 — Attributes of a Named Data Property

Attribute Name

Value Domain

Description

[[Value]]

Any ECMAScript language type

The value retrieved by reading the property.

[[Writable]]

Boolean

If false, attempts by ECMAScript code to change the property’s [[Value]] attribute using [[Put]] will not succeed.

[[Enumerable]]

Boolean

If true, the property will be enumerated by a for-in enumeration (see 12.6.4). Otherwise, the property is said to be non-enumerable.

[[Configurable]]

Boolean

If false, attempts to delete the property, change the property to be an accessor property, or change its attributes (other than [[Value]]) will fail.

A named accessor property associates a name with the attributes listed in Table 6.

Table 6 — Attributes of a Named Accessor Property

Attribute Name

Value Domain

Description

[[Get]]

Object or Undefined

If the value is an Object it must be a function Object. The function’s [[Call]] internal method (8.6.2) is called with an empty arguments list to return the property value each time a get access of the property is performed.

[[Set]]

Object or Undefined

If the value is an Object it must be a function Object. The function’s [[Call]] internal method (8.6.2) is called with an arguments list containing the assigned value as its sole argument each time a set access of the property is performed. The effect of a property's [[Set]] internal method may, but is not required to, have an effect on the value returned by subsequent calls to the property's [[Get]] internal method.

[[Enumerable]]

Boolean

If true, the property is to be enumerated by a for-in enumeration (see 12.6.4). Otherwise, the property is said to be non-enumerable.

[[Configurable]]

Boolean

If false, attempts to delete the property, change the property to be a data property, or change its attributes will fail.

If the value of an attribute is not explicitly specified by this specification for a named property, the default value defined in Table 7 is used.

Table 7 — Default Attribute Values

Attribute Name

Default Value

[[Value]]

undefined

[[Get]]

undefined

[[Set]]

undefined

[[Writable]]

false

[[Enumerable]]

false

[[Configurable]]

false

8.6.2 Object Internal Properties and Methods #

This specification uses various internal properties to define the semantics of object values. These internal properties are not part of the ECMAScript language. They are defined by this specification purely for expository purposes. An implementation of ECMAScript must behave as if it produced and operated upon internal properties in the manner described here. The names of internal properties are enclosed in double square brackets [[ ]]. When an algorithm uses an internal property of an object and the object does not implement the indicated internal property, a TypeError exception is thrown.

The Table 8 summarises the internal properties used by this specification that are applicable to all ECMAScript objects. The Table 9 summarises the internal properties used by this specification that are only applicable to some ECMAScript objects. The descriptions in these tables indicates their behaviour for native ECMAScript objects, unless stated otherwise in this document for particular kinds of native ECMAScript objects. Host objects may support these internal properties with any implementation-dependent behaviour as long as it is consistent with the specific host object restrictions stated in this document.

The “Value Type Domain” columns of the following tables define the types of values associated with internal properties. The type names refer to the types defined in Clause 8 augmented by the following additional names. “any” means the value may be any ECMAScript language type. “primitive” means Undefined, Null, Boolean, String, or Number. SpecOp means the internal property is an internal method, an implementation provided procedure defined by an abstract operation specification. “SpecOp” is followed by a list of descriptive parameter names. If a parameter name is the same as a type name then the name describes the type of the parameter. If a “SpecOp” returns a value, its parameter list is followed by the symbol “→” and the type of the returned value.

Table 8 — Internal Properties Common to All Objects

Internal Property

Value Type Domain

Description

[[Prototype]]

Object or Null

The prototype of this object.

[[Class]]

String

A String value indicating a specification defined classification of objects.

[[Extensible]]

Boolean

If true, own properties may be added to the object.

[[Get]]

SpecOp(propertyName) any

Returns the value of the named property.

[[GetOwnProperty]]

SpecOp (propertyName)

Undefinedor Property Descriptor

Returns the Property Descriptor of the named own property of this object, or undefined if absent.

[[GetProperty]]

SpecOp (propertyName)

Undefinedor Property Descriptor

Returns the fully populated Property Descriptor of the named property of this object, or undefined if absent.

[[Put]]

SpecOp (propertyName, any, Boolean)

Sets the specified named property to the value of the second parameter. The flag controls failure handling.

[[CanPut]]

SpecOp (propertyName) Boolean

Returns a Boolean value indicating whether a [[Put]] operation with PropertyName can be performed.

[[HasProperty]]

SpecOp (propertyName) Boolean

Returns a Boolean value indicating whether the object already has a property with the given name.

[[Delete]]

SpecOp (propertyName, Boolean) Boolean

Removes the specified named own property from the object. The flag controls failure handling.

[[DefaultValue]]

SpecOp (Hint) primitive

Hint is a String. Returns a default value for the object.

[[DefineOwnProperty]]

SpecOp (propertyName, PropertyDescriptor, Boolean) Boolean

Creates or alters the named own property to have the state described by a Property Descriptor. The flag controls failure handling.

Every object (including host objects) must implement all of the internal properties listed in Table 8. However, the [[DefaultValue]] internal method may, for some objects, simply throw a TypeError exception.

All objects have an internal property called [[Prototype]]. The value of this property is either null or an object and is used for implementing inheritance. Whether or not a native object can have a host object as its [[Prototype]] depends on the implementation. Every [[Prototype]] chain must have finite length (that is, starting from any object, recursively accessing the [[Prototype]] internal property must eventually lead to a null value). Named data properties of the [[Prototype]] object are inherited (are visible as properties of the child object) for the purposes of get access, but not for put access. Named accessor properties are inherited for both get access and put access.

Every ECMAScript object has a Boolean-valued [[Extensible]] internal property that controls whether or not named properties may be added to the object. If the value of the [[Extensible]] internal property is false then additional named properties may not be added to the object. In addition, if [[Extensible]] is false the value of the [[Class]] and [[Prototype]] internal properties of the object may not be modified. Once the value of an [[Extensible]] internal property has been set to false it may not be subsequently changed to true.

NOTE This specification defines no ECMAScript language operators or built-in functions that permit a program to modify an object’s [[Class]] or [[Prototype]] internal properties or to change the value of [[Extensible]] from false to true. Implementation specific extensions that modify [[Class]], [[Prototype]] or [[Extensible]] must not violate the invariants defined in the preceding paragraph.

The value of the [[Class]] internal property is defined by this specification for every kind of built-in object. The value of the [[Class]] internal property of a host object may be any String value except one of "Arguments", "Array", "Boolean", "Date", "Error", "Function", "JSON", "Math", "Number", "Object", "RegExp", and "String". The value of a [[Class]] internal property is used internally to distinguish different kinds of objects. Note that this specification does not provide any means for a program to access that value except through Object.prototype.toString (see 15.2.4.2).

Unless otherwise specified, the common internal methods of native ECMAScript objects behave as described in 8.12. Array objects have a slightly different implementation of the [[DefineOwnProperty]] internal method (see 15.4.5.1) and String objects have a slightly different implementation of the [[GetOwnProperty]] internal method (see 15.5.5.2). Arguments objects (10.6) have different implementations of [[Get]], [[GetOwnProperty]], [[DefineOwnProperty]], and [[Delete]]. Function objects (15.3) have a different implementation of [[Get]].

Host objects may implement these internal methods in any manner unless specified otherwise; for example, one possibility is that [[Get]] and [[Put]] for a particular host object indeed fetch and store property values but [[HasProperty]] always generates false. However, if any specified manipulation of a host object's internal properties is not supported by an implementation, that manipulation must throw a TypeError exception when attempted.

The [[GetOwnProperty]] internal method of a host object must conform to the following invariants for each property of the host object:

The [[DefineOwnProperty]] internal method of a host object must not permit the addition of a new property to a host object if the [[Extensible]] internal property of that host object has been observed by ECMAScript code to be false.

If the [[Extensible]] internal property of that host object has been observed by ECMAScript code to be false then it must not subsequently become true.

Table 9 — Internal Properties Only Defined for Some Objects

Internal Property

Value Type Domain

Description

[[PrimitiveValue]]

primitive

Internal state information associated with this object. Of the standard built-in ECMAScript objects, only Boolean, Date, Number, and String objects implement [[PrimitiveValue]].

[[Construct]]

SpecOp(a List of any) Object

Creates an object. Invoked via the new operator. The arguments to the SpecOp are the arguments passed to the new operator. Objects that implement this internal method are called constructors.

[[Call]]

SpecOp(any, a List of any) any or Reference

Executes code associated with the object. Invoked via a function call expression. The arguments to the SpecOp are a this object and a list containing the arguments passed to the function call expression. Objects that implement this internal method are callable. Only callable objects that are host objects may return Reference values.

[[HasInstance]]

SpecOp(any) Boolean

Returns a Boolean value indicating whether the argument is likely an Object that was constructed by this object. Of the standard built-in ECMAScript objects, only Function objects implement [[HasInstance]].

[[Scope]]

Lexical Environment

A lexical environment that defines the environment in which a Function object is executed. Of the standard built-in ECMAScript objects, only Function objects implement [[Scope]].

[[FormalParameters]]

List of Strings

A possibly empty List containing the identifier Strings of a Function’s FormalParameterList. Of the standard built-in ECMAScript objects, only Function objects implement [[FormalParameterList]].

[[Code]]

ECMAScript code

The ECMAScript code of a function. Of the standard built-in ECMAScript objects, only Function objects implement [[Code]].

[[TargetFunction]]

Object

The target function of a function object created using the standard built-in Function.prototype.bind method. Only ECMAScript objects created using Function.prototype.bind have a [[TargetFunction]] internal property.

[[BoundThis]]

any

The pre-bound this value of a function Object created using the standard built-in Function.prototype.bind method. Only ECMAScript objects created using Function.prototype.bind have a [[BoundThis]] internal property.

[[BoundArguments]]

List of any

The pre-bound argument values of a function Object created using the standard built-in Function.prototype.bind method. Only ECMAScript objects created using Function.prototype.bind have a [[BoundArguments]] internal property.

[[Match]]

SpecOp(String, index) MatchResult

Tests for a regular expression match and returns a MatchResult value (see 15.10.2.1). Of the standard built-in ECMAScript objects, only RegExp objects implement [[Match]].

[[ParameterMap]]

Object

Provides a mapping between the properties of an arguments object (see 10.6) and the formal parameters of the associated function. Only ECMAScript objects that are arguments objects have a [[ParameterMap]] internal property.

8.7 The Reference Specification Type #

The Reference type is used to explain the behaviour of such operators as delete, typeof, and the assignment operators. For example, the left-hand operand of an assignment is expected to produce a reference. The behaviour of assignment could, instead, be explained entirely in terms of a case analysis on the syntactic form of the left-hand operand of an assignment operator, but for one difficulty: function calls are permitted to return references. This possibility is admitted purely for the sake of host objects. No built-in ECMAScript function defined by this specification returns a reference and there is no provision for a user-defined function to return a reference. (Another reason not to use a syntactic case analysis is that it would be lengthy and awkward, affecting many parts of the specification.)

A Reference is a resolved name binding. A Reference consists of three components, the base value, the referenced name and the Boolean valued strict reference flag. The base value is either undefined, an Object, a Boolean, a String, a Number, or an environment record (10.2.1). A base value of undefined indicates that the reference could not be resolved to a binding. The referenced name is a String.

The following abstract operations are used in this specification to access the components of references:

The following abstract operations are used in this specification to operate on references:

8.7.1 GetValue (V) #

  1. If Type(V) is not Reference, return V.

  2. Let base be the result of calling GetBase(V).

  3. If IsUnresolvableReference(V), throw a ReferenceError exception.

  4. If IsPropertyReference(V), then

    1. If HasPrimitiveBase(V) is false, then let get be the [[Get]] internal method of base, otherwise let get be the special [[Get]] internal method defined below.

    2. Return the result of calling the get internal method using base as its this value, and passing GetReferencedName(V) for the argument.

  5. Else, base must be an environment record.

    1. Return the result of calling the GetBindingValue (see 10.2.1) concrete method of base passing GetReferencedName(V) and IsStrictReference(V) as arguments.

The following [[Get]] internal method is used by GetValue when V is a property reference with a primitive base value. It is called using base as its this value and with property P as its argument. The following steps are taken:

  1. Let O be ToObject(base).

  2. Let desc be the result of calling the [[GetProperty]] internal method of O with property name P.

  3. If desc is undefined, return undefined.

  4. If IsDataDescriptor(desc) is true, return desc.[[Value]].

  5. Otherwise, IsAccessorDescriptor(desc) must be true so, let getter be desc.[[Get]].

  6. If getter is undefined, return undefined.

  7. Return the result calling the [[Call]] internal method of getter providing base as the this value and providing no arguments.

NOTE The object that may be created in step 1 is not accessible outside of the above method. An implementation might choose to avoid the actual creation of the object. The only situation where such an actual property access that uses this internal method can have visible effect is when it invokes an accessor function.

8.7.2 PutValue (V, W) #

  1. If Type(V) is not Reference, throw a ReferenceError exception.

  2. Let base be the result of calling GetBase(V).

  3. If IsUnresolvableReference(V), then

    1. If IsStrictReference(V) is true, then

      1. Throw ReferenceError exception.

    2. Call the [[Put]] internal method of the global object, passing GetReferencedName(V) for the property name, W for the value, and false for the Throw flag.

  4. Else if IsPropertyReference(V), then

    1. If HasPrimitiveBase(V) is false, then let put be the [[Put]] internal method of base, otherwise let put be the special [[Put]] internal method defined below.

    2. Call the put internal method using base as its this value, and passing GetReferencedName(V) for the property name, W for the value, and IsStrictReference(V) for the Throw flag.

  5. Else base must be a reference whose base is an environment record. So,

    1. Call the SetMutableBinding (10.2.1) concrete method of base, passing GetReferencedName(V), W, and IsStrictReference(V) as arguments.

  6. Return.

The following [[Put]] internal method is used by PutValue when V is a property reference with a primitive base value. It is called using base as its this value and with property P, value W, and Boolean flag Throw as arguments. The following steps are taken:

  1. Let O be ToObject(base).

  2. If the result of calling the [[CanPut]] internal method of O with argument P is false, then

    1. If Throw is true, then throw a TypeError exception.

    2. Else return.

  3. Let ownDesc be the result of calling the [[GetOwnProperty]] internal method of O with argument P.

  4. If IsDataDescriptor(ownDesc) is true, then

    1. If Throw is true, then throw a TypeError exception.

    2. Else Return.

  5. Let desc be the result of calling the [[GetProperty]] internal method of O with argument P. This may be either an own or inherited accessor property descriptor or an inherited data property descriptor.

  6. If IsAccessorDescriptor(desc) is true, then

    1. Let setter be desc.[[Set]] which cannot be undefined.

    2. Call the [[Call]] internal method of setter providing base as the this value and an argument list containing only W.

  7. Else, this is a request to create an own property on the transient object O

    1. If Throw is true, then throw a TypeError exception.

  8. Return.

NOTE The object that may be created in step 1 is not accessible outside of the above method. An implementation might choose to avoid the actual creation of that transient object. The only situations where such an actual property assignment that uses this internal method can have visible effect are when it either invokes an accessor function or is in violation of a Throw predicated error check. When Throw is true any property assignment that would create a new property on the transient object throws an error.

8.8 The List Specification Type #

The List type is used to explain the evaluation of argument lists (see 11.2.4) in new expressions, in function calls, and in other algorithms where a simple list of values is needed. Values of the List type are simply ordered sequences of values. These sequences may be of any length.

8.9 The Completion Specification Type #

The Completion type is used to explain the behaviour of statements (break, continue, return and throw) that perform nonlocal transfers of control. Values of the Completion type are triples of the form (type, value, target), where type is one of normal, break, continue, return, or throw, value is any ECMAScript language value or empty, and target is any ECMAScript identifier or empty.

The term “abrupt completion” refers to any completion with a type other than normal.

8.10 The Property Descriptor and Property Identifier Specification Types #

The Property Descriptor type is used to explain the manipulation and reification of named property attributes. Values of the Property Descriptor type are records composed of named fields where each field’s name is an attribute name and its value is a corresponding attribute value as specified in 8.6.1. In addition, any field may be present or absent.

Property Descriptor values may be further classified as data property descriptors and accessor property descriptors based upon the existence or use of certain fields. A data property descriptor is one that includes any fields named either [[Value]] or [[Writable]]. An accessor property descriptor is one that includes any fields named either [[Get]] or [[Set]]. Any property descriptor may have fields named [[Enumerable]] and [[Configurable]]. A Property Descriptor value may not be both a data property descriptor and an accessor property descriptor; however, it may be neither. A generic property descriptor is a Property Descriptor value that is neither a data property descriptor nor an accessor property descriptor. A fully populated property descriptor is one that is either an accessor property descriptor or a data property descriptor and that has all of the fields that correspond to the property attributes defined in either 8.6.1 Table 5 or Table 6.

For notational convenience within this specification, an object literal-like syntax can be used to define a property descriptor value. For example, Property Descriptor {[[Value]]: 42, [[Writable]]: false, [[Configurable]]: true} defines a data property descriptor. Field name order is not significant. Any fields that are not explicitly listed are considered to be absent.

In specification text and algorithms, dot notation may be used to refer to a specific field of a Property Descriptor. For example, if D is a property descriptor then D.[[Value]] is shorthand for “the field of D named [[Value]]”.

The Property Identifier type is used to associate a property name with a Property Descriptor. Values of the Property Identifier type are pairs of the form (name, descriptor), where name is a String and descriptor is a Property Descriptor value.

The following abstract operations are used in this specification to operate upon Property Descriptor values:

8.10.1 IsAccessorDescriptor ( Desc ) #

When the abstract operation IsAccessorDescriptor is called with property descriptor Desc, the following steps are taken:

  1. If Desc is undefined, then return false.

  2. If both Desc.[[Get]] and Desc.[[Set]] are absent, then return false.

  3. Return true.

8.10.2 IsDataDescriptor ( Desc ) #

When the abstract operation IsDataDescriptor is called with property descriptor Desc, the following steps are taken:

  1. If Desc is undefined, then return false.

  2. If both Desc.[[Value]] and Desc.[[Writable]] are absent, then return false.

  3. Return true.

8.10.3 IsGenericDescriptor ( Desc ) #

When the abstract operation IsGenericDescriptor is called with property descriptor Desc, the following steps are taken:

  1. If Desc is undefined, then return false.

  2. If IsAccessorDescriptor(Desc) and IsDataDescriptor(Desc) are both false, then return true.

  3. Return false.

8.10.4 FromPropertyDescriptor ( Desc ) #

When the abstract operation FromPropertyDescriptor is called with property descriptor Desc, the following steps are taken:

The following algorithm assumes that Desc is a fully populated Property Descriptor, such as that returned from [[GetOwnProperty]] (see 8.12.1).

  1. If Desc is undefined, then return undefined.

  2. Let obj be the result of creating a new object as if by the expression new Object() where Object is the standard built-in constructor with that name.

  3. If IsDataDescriptor(Desc) is true, then

    1. Call the [[DefineOwnProperty]] internal method of obj with arguments "value", Property Descriptor {[[Value]]: Desc.[[Value]], [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.

    2. Call the [[DefineOwnProperty]] internal method of obj with arguments "writable", Property Descriptor {[[Value]]: Desc.[[Writable]], [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.

  4. Else, IsAccessorDescriptor(Desc) must be true, so

    1. Call the [[DefineOwnProperty]] internal method of obj with arguments "get", Property Descriptor {[[Value]]: Desc.[[Get]], [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.

    2. Call the [[DefineOwnProperty]] internal method of obj with arguments "set", Property Descriptor {[[Value]]: Desc.[[Set]], [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.

  5. Call the [[DefineOwnProperty]] internal method of obj with arguments "enumerable", Property Descriptor {[[Value]]: Desc.[[Enumerable]], [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.

  6. Call the [[DefineOwnProperty]] internal method of obj with arguments "configurable", Property Descriptor {[[Value]]: Desc.[[Configurable]], [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.

  7. Return obj.

8.10.5 ToPropertyDescriptor ( Obj ) #

When the abstract operation ToPropertyDescriptor is called with object Desc, the following steps are taken:

  1. If Type(Obj) is not Object throw a TypeError exception.

  2. Let desc be the result of creating a new Property Descriptor that initially has no fields.

  3. If the result of calling the [[HasProperty]] internal method of Obj with argument "enumerable" is true, then

    1. Let enum be the result of calling the [[Get]] internal method of Obj with "enumerable".

    2. Set the [[Enumerable]] field of desc to ToBoolean(enum).

  4. If the result of calling the [[HasProperty]] internal method of Obj with argument "configurable" is true, then

    1. Let conf be the result of calling the [[Get]] internal method of Obj with argument "configurable".

    2. Set the [[Configurable]] field of desc to ToBoolean(conf).

  5. If the result of calling the [[HasProperty]] internal method of Obj with argument "value" is true, then

    1. Let value be the result of calling the [[Get]] internal method of Obj with argument “value”.

    2. Set the [[Value]] field of desc to value.

  6. If the result of calling the [[HasProperty]] internal method of Obj with argument "writable" is true, then

    1. Let writable be the result of calling the [[Get]] internal method of Obj with argument "writable".

    2. Set the [[Writable]] field of desc to ToBoolean(writable).

  7. If the result of calling the [[HasProperty]] internal method of Obj with argument "get" is true, then

    1. Let getter be the result of calling the [[Get]] internal method of Obj with argument "get".

    2. If IsCallable(getter) is false and getter is not undefined, then throw a TypeError exception.

    3. Set the [[Get]] field of desc to getter.

  8. If the result of calling the [[HasProperty]] internal method of Obj with argument "set" is true, then

    1. Let setter be the result of calling the [[Get]] internal method of Obj with argument "set".

    2. If IsCallable(setter) is false and setter is not undefined, then throw a TypeError exception.

    3. Set the [[Set]] field of desc to setter.

  9. If either desc.[[Get]] or desc.[[Set]] are present, then

    1. If either desc.[[Value]] or desc.[[Writable]] are present, then throw a TypeError exception.

  10. Return desc.

8.11 The Lexical Environment and Environment Record Specification Types #

The Lexical Environment and Environment Record types are used to explain the behaviour of name resolution in nested functions and blocks. These types and the operations upon them are defined in Clause 10.

8.12 Algorithms for Object Internal Methods #

In the following algorithm descriptions, assume O is a native ECMAScript object, P is a String, Desc is a Property Description record, and Throw is a Boolean flag.

8.12.1 [[GetOwnProperty]] (P) #

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

  1. If O doesn’t have an own property with name P, return undefined.

  2. Let D be a newly created Property Descriptor with no fields.

  3. Let X be O’s own property named P.

  4. If X is a data property, then

    1. Set D.[[Value]] to the value of X’s [[Value]] attribute.

    2. Set D.[[Writable]] to the value of X’s [[Writable]] attribute

  5. Else X is an accessor property, so

    1. Set D.[[Get]] to the value of X’s [[Get]] attribute.

    2. Set D.[[Set]] to the value of X’s [[Set]] attribute.

  6. Set D.[[Enumerable]] to the value of X’s [[Enumerable]] attribute.

  7. Set D.[[Configurable]] to the value of X’s [[Configurable]] attribute.

  8. Return D.

However, if O is a String object it has a more elaborate [[GetOwnProperty]] internal method defined in 15.5.5.2.

8.12.2 [[GetProperty]] (P) #

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

  1. Let prop be the result of calling the [[GetOwnProperty]] internal method of O with property name P.

  2. If prop is not undefined, return prop.

  3. Let proto be the value of the [[Prototype]] internal property of O.

  4. If proto is null, return undefined.

  5. Return the result of calling the [[GetProperty]] internal method of proto with argument P.

8.12.3 [[Get]] (P) #

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

  1. Let desc be the result of calling the [[GetProperty]] internal method of O with property name P.

  2. If desc is undefined, return undefined.

  3. If IsDataDescriptor(desc) is true, return desc.[[Value]].

  4. Otherwise, IsAccessorDescriptor(desc) must be true so, let getter be desc.[[Get]].

  5. If getter is undefined, return undefined.

  6. Return the result calling the [[Call]] internal method of getter providing O as the this value and providing no arguments.

8.12.4 [[CanPut]] (P) #

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

  1. Let desc be the result of calling the [[GetOwnProperty]] internal method of O with argument P.

  2. If desc is not undefined, then

    1. If IsAccessorDescriptor(desc) is true, then

      1. If desc.[[Set]] is undefined, then return false.

      2. Else return true.

    2. Else, desc must be a DataDescriptor so return the value of desc.[[Writable]].

  3. Let proto be the [[Prototype]] internal property of O.

  4. If proto is null, then return the value of the [[Extensible]] internal property of O.

  5. Let inherited be the result of calling the [[GetProperty]] internal method of proto with property name P.

  6. If inherited is undefined, return the value of the [[Extensible]] internal property of O.

  7. If IsAccessorDescriptor(inherited) is true, then

    1. If inherited.[[Set]] is undefined, then return false.

    2. Else return true.

  8. Else, inherited must be a DataDescriptor

    1. If the [[Extensible]] internal property of O is false, return false.

    2. Else return the value of inherited.[[Writable]].

Host objects may define additional constraints upon [[Put]] operations. If possible, host objects should not allow [[Put]] operations in situations where this definition of [[CanPut]] returns false.

8.12.5 [[Put]] ( P, V, Throw ) #

When the [[Put]] internal method of O is called with property P, value V, and Boolean flag Throw, the following steps are taken:

  1. If the result of calling the [[CanPut]] internal method of O with argument P is false, then

    1. If Throw is true, then throw a TypeError exception.

    2. Else return.

  2. Let ownDesc be the result of calling the [[GetOwnProperty]] internal method of O with argument P.

  3. If IsDataDescriptor(ownDesc) is true, then

    1. Let valueDesc be the Property Descriptor {[[Value]]: V}.

    2. Call the [[DefineOwnProperty]] internal method of O passing P, valueDesc, and Throw as arguments.

    3. Return.

  4. Let desc be the result of calling the [[GetProperty]] internal method of O with argument P. This may be either an own or inherited accessor property descriptor or an inherited data property descriptor.

  5. If IsAccessorDescriptor(desc) is true, then

    1. Let setter be desc.[[Set]] which cannot be undefined.

    2. Call the [[Call]] internal method of setter providing O as the this value and providing V as the sole argument.

  6. Else, create a named data property named P on object O as follows

    1. Let newDesc be the Property Descriptor
      {[[Value]]: V, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}.

    2. Call the [[DefineOwnProperty]] internal method of O passing P, newDesc, and Throw as arguments.

  7. Return.

8.12.6 [[HasProperty]] (P) #

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

  1. Let desc be the result of calling the [[GetProperty]] internal method of O with property name P.

  2. If desc is undefined, then return false.

  3. Else return true.

8.12.7 [[Delete]] (P, Throw) #

When the [[Delete]] internal method of O is called with property name P and the Boolean flag Throw, the following steps are taken:

  1. Let desc be the result of calling the [[GetOwnProperty]] internal method of O with property name P.

  2. If desc is undefined, then return true.

  3. If desc.[[Configurable]] is true, then

    1. Remove the own property with name P from O.

    2. Return true.

  4. Else if Throw, then throw a TypeError exception.

  5. Return false.

8.12.8 [[DefaultValue]] (hint) #

When the [[DefaultValue]] internal method of O is called with hint String, the following steps are taken:

  1. Let toString be the result of calling the [[Get]] internal method of object O with argument "toString".

  2. If IsCallable(toString) is true then,

    1. Let str be the result of calling the [[Call]] internal method of toString, with O as the this value and an empty argument list.

    2. If str is a primitive value, return str.

  3. Let valueOf be the result of calling the [[Get]] internal method of object O with argument "valueOf".

  4. If IsCallable(valueOf) is true then,

    1. Let val be the result of calling the [[Call]] internal method of valueOf, with O as the this value and an empty argument list.

    2. If val is a primitive value, return val.

  5. Throw a TypeError exception.

When the [[DefaultValue]] internal method of O is called with hint Number, the following steps are taken:

  1. Let valueOf be the result of calling the [[Get]] internal method of object O with argument "valueOf".

  2. If IsCallable(valueOf) is true then,

    1. Let val be the result of calling the [[Call]] internal method of valueOf, with O as the this value and an empty argument list.

    2. If val is a primitive value, return val.

  3. Let toString be the result of calling the [[Get]] internal method of object O with argument "toString".

  4. If IsCallable(toString) is true then,

    1. Let str be the result of calling the [[Call]] internal method of toString, with O as the this value and an empty argument list.

    2. If str is a primitive value, return str.

  5. Throw a TypeError exception.

When the [[DefaultValue]] internal method of O is called with no hint, then it behaves as if the hint were Number, unless O is a Date object (see 15.9.6), in which case it behaves as if the hint were String.

The above specification of [[DefaultValue]] for native objects can return only primitive values. If a host object implements its own [[DefaultValue]] internal method, it must ensure that its [[DefaultValue]] internal method can return only primitive values.

8.12.9 [[DefineOwnProperty]] (P, Desc, Throw) #

In the following algorithm, the term “Reject” means “If Throw is true, then throw a TypeError exception, otherwise return false”. The algorithm contains steps that test various fields of the Property Descriptor Desc for specific values. The fields that are tested in this manner need not actually exist in Desc. If a field is absent then its value is considered to be false.

When the [[DefineOwnProperty]] internal method of O is called with property name P, property descriptor Desc, and Boolean flag Throw, the following steps are taken:

  1. Let current be the result of calling the [[GetOwnProperty]] internal method of O with property name P.

  2. Let extensible be the value of the [[Extensible]] internal property of O.

  3. If current is undefined and extensible is false, then Reject.

  4. If current is undefined and extensible is true, then

    1. If IsGenericDescriptor(Desc) or IsDataDescriptor(Desc) is true, then

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

    2. Else, Desc must be an accessor Property Descriptor so,

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

    3. Return true.

  5. Return true, if every field in Desc is absent.

  6. Return true, if every field in Desc also occurs in current and the value of every field in Desc is the same value as the corresponding field in current when compared using the SameValue algorithm (9.12).

  7. If the [[Configurable]] field of current is false then

    1. Reject, if the [[Configurable]] field of Desc is true.

    2. Reject, if the [[Enumerable]] field of Desc is present and the [[Enumerable]] fields of current and Desc are the Boolean negation of each other.

  8. If IsGenericDescriptor(Desc) is true, then no further validation is required.

  9. Else, if IsDataDescriptor(current) and IsDataDescriptor(Desc) have different results, then

    1. Reject, if the [[Configurable]] field of current is false.

    2. If IsDataDescriptor(current) is true, then

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

  10. Else, if IsDataDescriptor(current) and IsDataDescriptor(Desc) are both true, then

    1. If the [[Configurable]] field of current is false, then

      1. Reject, if the [[Writable]] field of current is false and the [[Writable]] field of Desc is true.

      2. If the [[Writable]] field of current is false, then

        1. Reject, if the [[Value]] field of Desc is present and SameValue(Desc.[[Value]], current.[[Value]]) is false.

    2. else, the [[Configurable]] field of current is true, so any change is acceptable.

  11. Else, IsAccessorDescriptor(current) and IsAccessorDescriptor(Desc) are both true so,

    1. If the [[Configurable]] field of current is false, then

      1. Reject, if the [[Set]] field of Desc is present and SameValue(Desc.[[Set]], current.[[Set]]) is false.

      2. Reject, if the [[Get]] field of Desc is present and SameValue(Desc.[[Get]], current.[[Get]]) is false.

  12. For each attribute field of Desc that is present, set the correspondingly named attribute of the property named P of object O to the value of the field.

  13. Return true.

However, if O is an Array object, it has a more elaborate [[DefineOwnProperty]] internal method defined in 15.4.5.1.

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