13 ECMAScript Language: Expressions

13.1 Identifiers

Syntax

IdentifierReference[Yield, Await] : Identifier [~Yield] yield [~Await] await BindingIdentifier[Yield, Await] : Identifier yield await LabelIdentifier[Yield, Await] : Identifier [~Yield] yield [~Await] await Identifier : IdentifierName but not ReservedWord Note

yield and await are permitted as BindingIdentifier in the grammar, and prohibited with static semantics below, to prohibit automatic semicolon insertion in cases such as

let
await 0;

13.1.1 Static Semantics: Early Errors

BindingIdentifier : Identifier IdentifierReference : yield BindingIdentifier : yield LabelIdentifier : yield
  • It is a Syntax Error if the source text matched by this production is contained in strict mode code.
IdentifierReference : await BindingIdentifier : await LabelIdentifier : await BindingIdentifier[Yield, Await] : yield
  • It is a Syntax Error if this production has a [Yield] parameter.
BindingIdentifier[Yield, Await] : await
  • It is a Syntax Error if this production has an [Await] parameter.
IdentifierReference[Yield, Await] : Identifier BindingIdentifier[Yield, Await] : Identifier LabelIdentifier[Yield, Await] : Identifier
  • It is a Syntax Error if this production has a [Yield] parameter and StringValue of Identifier is "yield".
  • It is a Syntax Error if this production has an [Await] parameter and StringValue of Identifier is "await".
Identifier : IdentifierName but not ReservedWord Note

StringValue of IdentifierName normalizes any Unicode escape sequences in IdentifierName hence such escapes cannot be used to write an Identifier whose code point sequence is the same as a ReservedWord.

13.1.2 Static Semantics: StringValue

The syntax-directed operation StringValue takes no arguments and returns a String. It is defined piecewise over the following productions:

IdentifierName :: IdentifierStart IdentifierName IdentifierPart
  1. Let idTextUnescaped be IdentifierCodePoints of IdentifierName.
  2. Return CodePointsToString(idTextUnescaped).
IdentifierReference : yield BindingIdentifier : yield LabelIdentifier : yield
  1. Return "yield".
IdentifierReference : await BindingIdentifier : await LabelIdentifier : await
  1. Return "await".
Identifier : IdentifierName but not ReservedWord
  1. Return the StringValue of IdentifierName.
PrivateIdentifier :: # IdentifierName
  1. Return the string-concatenation of 0x0023 (NUMBER SIGN) and the StringValue of IdentifierName.
ModuleExportName : StringLiteral
  1. Return the SV of StringLiteral.

13.1.3 Runtime Semantics: Evaluation

IdentifierReference : Identifier
  1. Return ? ResolveBinding(StringValue of Identifier).
IdentifierReference : yield
  1. Return ? ResolveBinding("yield").
IdentifierReference : await
  1. Return ? ResolveBinding("await").
Note 1

The result of evaluating an IdentifierReference is always a value of type Reference.

Note 2

In non-strict code, the keyword yield may be used as an identifier. Evaluating the IdentifierReference resolves the binding of yield as if it was an Identifier. Early Error restriction ensures that such an evaluation only can occur for non-strict code.

13.2 Primary Expression

Syntax

PrimaryExpression[Yield, Await] : this IdentifierReference[?Yield, ?Await] Literal ArrayLiteral[?Yield, ?Await] ObjectLiteral[?Yield, ?Await] FunctionExpression ClassExpression[?Yield, ?Await] GeneratorExpression AsyncFunctionExpression AsyncGeneratorExpression RegularExpressionLiteral TemplateLiteral[?Yield, ?Await, ~Tagged] CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await] CoverParenthesizedExpressionAndArrowParameterList[Yield, Await] : ( Expression[+In, ?Yield, ?Await] ) ( Expression[+In, ?Yield, ?Await] , ) ( ) ( ... BindingIdentifier[?Yield, ?Await] ) ( ... BindingPattern[?Yield, ?Await] ) ( Expression[+In, ?Yield, ?Await] , ... BindingIdentifier[?Yield, ?Await] ) ( Expression[+In, ?Yield, ?Await] , ... BindingPattern[?Yield, ?Await] )

Supplemental Syntax

When processing an instance of the production
PrimaryExpression[Yield, Await] : CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await]
the interpretation of CoverParenthesizedExpressionAndArrowParameterList is refined using the following grammar:

ParenthesizedExpression[Yield, Await] : ( Expression[+In, ?Yield, ?Await] )

13.2.1 The this Keyword

13.2.1.1 Runtime Semantics: Evaluation

PrimaryExpression : this
  1. Return ? ResolveThisBinding().

13.2.2 Identifier Reference

See 13.1 for IdentifierReference.

13.2.3 Literals

Syntax

Literal : NullLiteral BooleanLiteral NumericLiteral StringLiteral

13.2.3.1 Runtime Semantics: Evaluation

Literal : NullLiteral
  1. Return null.
Literal : BooleanLiteral
  1. If BooleanLiteral is the token false, return false.
  2. If BooleanLiteral is the token true, return true.
Literal : NumericLiteral
  1. Return the NumericValue of NumericLiteral as defined in 12.8.3.
Literal : StringLiteral
  1. Return the SV of StringLiteral as defined in 12.8.4.2.

13.2.4 Array Initializer

Note

An ArrayLiteral is an expression describing the initialization of an Array, using a list, of zero or more expressions each of which represents an array element, enclosed in square brackets. The elements need not be literals; they are evaluated each time the array initializer is evaluated.

Array elements may be elided at the beginning, middle or end of the element list. Whenever a comma in the element list is not preceded by an AssignmentExpression (i.e., a comma at the beginning or after another comma), the missing array element contributes to the length of the Array and increases the index of subsequent elements. Elided array elements are not defined. If an element is elided at the end of an array, that element does not contribute to the length of the Array.

Syntax

ArrayLiteral[Yield, Await] : [ Elisionopt ] [ ElementList[?Yield, ?Await] ] [ ElementList[?Yield, ?Await] , Elisionopt ] ElementList[Yield, Await] : Elisionopt AssignmentExpression[+In, ?Yield, ?Await] Elisionopt SpreadElement[?Yield, ?Await] ElementList[?Yield, ?Await] , Elisionopt AssignmentExpression[+In, ?Yield, ?Await] ElementList[?Yield, ?Await] , Elisionopt SpreadElement[?Yield, ?Await] Elision : , Elision , SpreadElement[Yield, Await] : ... AssignmentExpression[+In, ?Yield, ?Await]

13.2.4.1 Runtime Semantics: ArrayAccumulation

The syntax-directed operation ArrayAccumulation takes arguments array (an Array) and nextIndex (an integer) and returns either a normal completion containing an integer or an abrupt completion. It is defined piecewise over the following productions:

Elision : ,
  1. Let len be nextIndex + 1.
  2. Perform ? Set(array, "length", 𝔽(len), true).
  3. NOTE: The above step throws if len exceeds 232-1.
  4. Return len.
Elision : Elision ,
  1. Return ? ArrayAccumulation of Elision with arguments array and (nextIndex + 1).
ElementList : Elisionopt AssignmentExpression
  1. If Elision is present, then
    1. Set nextIndex to ? ArrayAccumulation of Elision with arguments array and nextIndex.
  2. Let initResult be the result of evaluating AssignmentExpression.
  3. Let initValue be ? GetValue(initResult).
  4. Let created be ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(nextIndex)), initValue).
  5. Return nextIndex + 1.
ElementList : Elisionopt SpreadElement
  1. If Elision is present, then
    1. Set nextIndex to ? ArrayAccumulation of Elision with arguments array and nextIndex.
  2. Return ? ArrayAccumulation of SpreadElement with arguments array and nextIndex.
ElementList : ElementList , Elisionopt AssignmentExpression
  1. Set nextIndex to ? ArrayAccumulation of ElementList with arguments array and nextIndex.
  2. If Elision is present, then
    1. Set nextIndex to ? ArrayAccumulation of Elision with arguments array and nextIndex.
  3. Let initResult be the result of evaluating AssignmentExpression.
  4. Let initValue be ? GetValue(initResult).
  5. Let created be ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(nextIndex)), initValue).
  6. Return nextIndex + 1.
ElementList : ElementList , Elisionopt SpreadElement
  1. Set nextIndex to ? ArrayAccumulation of ElementList with arguments array and nextIndex.
  2. If Elision is present, then
    1. Set nextIndex to ? ArrayAccumulation of Elision with arguments array and nextIndex.
  3. Return ? ArrayAccumulation of SpreadElement with arguments array and nextIndex.
SpreadElement : ... AssignmentExpression
  1. Let spreadRef be the result of evaluating AssignmentExpression.
  2. Let spreadObj be ? GetValue(spreadRef).
  3. Let iteratorRecord be ? GetIterator(spreadObj).
  4. Repeat,
    1. Let next be ? IteratorStep(iteratorRecord).
    2. If next is false, return nextIndex.
    3. Let nextValue be ? IteratorValue(next).
    4. Perform ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(nextIndex)), nextValue).
    5. Set nextIndex to nextIndex + 1.
Note

CreateDataPropertyOrThrow is used to ensure that own properties are defined for the array even if the standard built-in Array prototype object has been modified in a manner that would preclude the creation of new own properties using [[Set]].

13.2.4.2 Runtime Semantics: Evaluation

ArrayLiteral : [ Elisionopt ]
  1. Let array be ! ArrayCreate(0).
  2. If Elision is present, then
    1. Perform ? ArrayAccumulation of Elision with arguments array and 0.
  3. Return array.
ArrayLiteral : [ ElementList ]
  1. Let array be ! ArrayCreate(0).
  2. Perform ? ArrayAccumulation of ElementList with arguments array and 0.
  3. Return array.
ArrayLiteral : [ ElementList , Elisionopt ]
  1. Let array be ! ArrayCreate(0).
  2. Let nextIndex be ? ArrayAccumulation of ElementList with arguments array and 0.
  3. If Elision is present, then
    1. Perform ? ArrayAccumulation of Elision with arguments array and nextIndex.
  4. Return array.

13.2.5 Object Initializer

Note 1

An object initializer is an expression describing the initialization of an Object, written in a form resembling a literal. It is a list of zero or more pairs of property keys and associated values, enclosed in curly brackets. The values need not be literals; they are evaluated each time the object initializer is evaluated.

Syntax

ObjectLiteral[Yield, Await] : { } { PropertyDefinitionList[?Yield, ?Await] } { PropertyDefinitionList[?Yield, ?Await] , } PropertyDefinitionList[Yield, Await] : PropertyDefinition[?Yield, ?Await] PropertyDefinitionList[?Yield, ?Await] , PropertyDefinition[?Yield, ?Await] PropertyDefinition[Yield, Await] : IdentifierReference[?Yield, ?Await] CoverInitializedName[?Yield, ?Await] PropertyName[?Yield, ?Await] : AssignmentExpression[+In, ?Yield, ?Await] MethodDefinition[?Yield, ?Await] ... AssignmentExpression[+In, ?Yield, ?Await] PropertyName[Yield, Await] : LiteralPropertyName ComputedPropertyName[?Yield, ?Await] LiteralPropertyName : IdentifierName StringLiteral NumericLiteral ComputedPropertyName[Yield, Await] : [ AssignmentExpression[+In, ?Yield, ?Await] ] CoverInitializedName[Yield, Await] : IdentifierReference[?Yield, ?Await] Initializer[+In, ?Yield, ?Await] Initializer[In, Yield, Await] : = AssignmentExpression[?In, ?Yield, ?Await] Note 2

MethodDefinition is defined in 15.4.

Note 3

In certain contexts, ObjectLiteral is used as a cover grammar for a more restricted secondary grammar. The CoverInitializedName production is necessary to fully cover these secondary grammars. However, use of this production results in an early Syntax Error in normal contexts where an actual ObjectLiteral is expected.

13.2.5.1 Static Semantics: Early Errors

PropertyDefinition : MethodDefinition

In addition to describing an actual object initializer the ObjectLiteral productions are also used as a cover grammar for ObjectAssignmentPattern and may be recognized as part of a CoverParenthesizedExpressionAndArrowParameterList. When ObjectLiteral appears in a context where ObjectAssignmentPattern is required the following Early Error rules are not applied. In addition, they are not applied when initially parsing a CoverParenthesizedExpressionAndArrowParameterList or CoverCallExpressionAndAsyncArrowHead.

PropertyDefinition : CoverInitializedName
  • It is a Syntax Error if any source text is matched by this production.
Note 1

This production exists so that ObjectLiteral can serve as a cover grammar for ObjectAssignmentPattern. It cannot occur in an actual object initializer.

ObjectLiteral : { PropertyDefinitionList } { PropertyDefinitionList , } Note 2

The List returned by PropertyNameList does not include property names defined using a ComputedPropertyName.

13.2.5.2 Static Semantics: IsComputedPropertyKey

The syntax-directed operation IsComputedPropertyKey takes no arguments and returns a Boolean. It is defined piecewise over the following productions:

PropertyName : LiteralPropertyName
  1. Return false.
PropertyName : ComputedPropertyName
  1. Return true.

13.2.5.3 Static Semantics: PropertyNameList

The syntax-directed operation PropertyNameList takes no arguments and returns a List of Strings. It is defined piecewise over the following productions:

PropertyDefinitionList : PropertyDefinition
  1. Let propName be PropName of PropertyDefinition.
  2. If propName is empty, return a new empty List.
  3. Return « propName ».
PropertyDefinitionList : PropertyDefinitionList , PropertyDefinition
  1. Let list be PropertyNameList of PropertyDefinitionList.
  2. Let propName be PropName of PropertyDefinition.
  3. If propName is empty, return list.
  4. Return the list-concatenation of list and « propName ».

13.2.5.4 Runtime Semantics: Evaluation

ObjectLiteral : { }
  1. Return OrdinaryObjectCreate(%Object.prototype%).
ObjectLiteral : { PropertyDefinitionList } { PropertyDefinitionList , }
  1. Let obj be OrdinaryObjectCreate(%Object.prototype%).
  2. Perform ? PropertyDefinitionEvaluation of PropertyDefinitionList with argument obj.
  3. Return obj.
LiteralPropertyName : IdentifierName
  1. Return StringValue of IdentifierName.
LiteralPropertyName : StringLiteral
  1. Return the SV of StringLiteral.
LiteralPropertyName : NumericLiteral
  1. Let nbr be the NumericValue of NumericLiteral.
  2. Return ! ToString(nbr).
ComputedPropertyName : [ AssignmentExpression ]
  1. Let exprValue be the result of evaluating AssignmentExpression.
  2. Let propName be ? GetValue(exprValue).
  3. Return ? ToPropertyKey(propName).

13.2.5.5 Runtime Semantics: PropertyDefinitionEvaluation

The syntax-directed operation PropertyDefinitionEvaluation takes argument object and returns either a normal completion containing unused or an abrupt completion. It is defined piecewise over the following productions:

PropertyDefinitionList : PropertyDefinitionList , PropertyDefinition
  1. Perform ? PropertyDefinitionEvaluation of PropertyDefinitionList with argument object.
  2. Perform ? PropertyDefinitionEvaluation of PropertyDefinition with argument object.
  3. Return unused.
PropertyDefinition : ... AssignmentExpression
  1. Let exprValue be the result of evaluating AssignmentExpression.
  2. Let fromValue be ? GetValue(exprValue).
  3. Let excludedNames be a new empty List.
  4. Perform ? CopyDataProperties(object, fromValue, excludedNames).
  5. Return unused.
PropertyDefinition : IdentifierReference
  1. Let propName be StringValue of IdentifierReference.
  2. Let exprValue be the result of evaluating IdentifierReference.
  3. Let propValue be ? GetValue(exprValue).
  4. Assert: object is an ordinary, extensible object with no non-configurable properties.
  5. Perform ! CreateDataPropertyOrThrow(object, propName, propValue).
  6. Return unused.
PropertyDefinition : PropertyName : AssignmentExpression
  1. Let propKey be the result of evaluating PropertyName.
  2. ReturnIfAbrupt(propKey).
  3. If this PropertyDefinition is contained within a Script that is being evaluated for JSON.parse (see step 7 of JSON.parse), then
    1. Let isProtoSetter be false.
  4. Else if propKey is the String value "__proto__" and if IsComputedPropertyKey of PropertyName is false, then
    1. Let isProtoSetter be true.
  5. Else,
    1. Let isProtoSetter be false.
  6. If IsAnonymousFunctionDefinition(AssignmentExpression) is true and isProtoSetter is false, then
    1. Let propValue be ? NamedEvaluation of AssignmentExpression with argument propKey.
  7. Else,
    1. Let exprValueRef be the result of evaluating AssignmentExpression.
    2. Let propValue be ? GetValue(exprValueRef).
  8. If isProtoSetter is true, then
    1. If Type(propValue) is either Object or Null, then
      1. Perform ! object.[[SetPrototypeOf]](propValue).
    2. Return unused.
  9. Assert: object is an ordinary, extensible object with no non-configurable properties.
  10. Perform ! CreateDataPropertyOrThrow(object, propKey, propValue).
  11. Return unused.
PropertyDefinition : MethodDefinition
  1. Perform ? MethodDefinitionEvaluation of MethodDefinition with arguments object and true.
  2. Return unused.

13.2.6 Function Defining Expressions

See 15.2 for PrimaryExpression : FunctionExpression .

See 15.5 for PrimaryExpression : GeneratorExpression .

See 15.7 for PrimaryExpression : ClassExpression .

See 15.8 for PrimaryExpression : AsyncFunctionExpression .

See 15.6 for PrimaryExpression : AsyncGeneratorExpression .

13.2.7 Regular Expression Literals

Syntax

See 12.8.5.

13.2.7.1 Static Semantics: Early Errors

PrimaryExpression : RegularExpressionLiteral

13.2.7.2 Static Semantics: IsValidRegularExpressionLiteral ( literal )

The abstract operation IsValidRegularExpressionLiteral takes argument literal (a RegularExpressionLiteral Parse Node) and returns a Boolean. It determines if its argument is a valid regular expression literal. It performs the following steps when called:

  1. If FlagText of literal contains any code points other than g, i, m, s, u, or y, or if it contains the same code point more than once, return false.
  2. Let patternText be BodyText of literal.
  3. If FlagText of literal contains u, let u be true; else let u be false.
  4. If u is false, then
    1. Let stringValue be CodePointsToString(patternText).
    2. Set patternText to the sequence of code points resulting from interpreting each of the 16-bit elements of stringValue as a Unicode BMP code point. UTF-16 decoding is not applied to the elements.
  5. Let parseResult be ParsePattern(patternText, u).
  6. If parseResult is a Parse Node, return true; else return false.

13.2.7.3 Runtime Semantics: Evaluation

PrimaryExpression : RegularExpressionLiteral
  1. Let pattern be CodePointsToString(BodyText of RegularExpressionLiteral).
  2. Let flags be CodePointsToString(FlagText of RegularExpressionLiteral).
  3. Return ! RegExpCreate(pattern, flags).

13.2.8 Template Literals

Syntax

TemplateLiteral[Yield, Await, Tagged] : NoSubstitutionTemplate SubstitutionTemplate[?Yield, ?Await, ?Tagged] SubstitutionTemplate[Yield, Await, Tagged] : TemplateHead Expression[+In, ?Yield, ?Await] TemplateSpans[?Yield, ?Await, ?Tagged] TemplateSpans[Yield, Await, Tagged] : TemplateTail TemplateMiddleList[?Yield, ?Await, ?Tagged] TemplateTail TemplateMiddleList[Yield, Await, Tagged] : TemplateMiddle Expression[+In, ?Yield, ?Await] TemplateMiddleList[?Yield, ?Await, ?Tagged] TemplateMiddle Expression[+In, ?Yield, ?Await]

13.2.8.1 Static Semantics: Early Errors

TemplateLiteral[Yield, Await, Tagged] : NoSubstitutionTemplate TemplateLiteral[Yield, Await, Tagged] : SubstitutionTemplate[?Yield, ?Await, ?Tagged] SubstitutionTemplate[Yield, Await, Tagged] : TemplateHead Expression[+In, ?Yield, ?Await] TemplateSpans[?Yield, ?Await, ?Tagged] TemplateSpans[Yield, Await, Tagged] : TemplateTail TemplateMiddleList[Yield, Await, Tagged] : TemplateMiddle Expression[+In, ?Yield, ?Await] TemplateMiddleList[?Yield, ?Await, ?Tagged] TemplateMiddle Expression[+In, ?Yield, ?Await]

13.2.8.2 Static Semantics: TemplateStrings

The syntax-directed operation TemplateStrings takes argument raw and returns a List of Strings. It is defined piecewise over the following productions:

TemplateLiteral : NoSubstitutionTemplate
  1. If raw is false, then
    1. Let string be the TV of NoSubstitutionTemplate.
  2. Else,
    1. Let string be the TRV of NoSubstitutionTemplate.
  3. Return « string ».
SubstitutionTemplate : TemplateHead Expression TemplateSpans
  1. If raw is false, then
    1. Let head be the TV of TemplateHead.
  2. Else,
    1. Let head be the TRV of TemplateHead.
  3. Let tail be TemplateStrings of TemplateSpans with argument raw.
  4. Return the list-concatenation of « head » and tail.
TemplateSpans : TemplateTail
  1. If raw is false, then
    1. Let tail be the TV of TemplateTail.
  2. Else,
    1. Let tail be the TRV of TemplateTail.
  3. Return « tail ».
TemplateSpans : TemplateMiddleList TemplateTail
  1. Let middle be TemplateStrings of TemplateMiddleList with argument raw.
  2. If raw is false, then
    1. Let tail be the TV of TemplateTail.
  3. Else,
    1. Let tail be the TRV of TemplateTail.
  4. Return the list-concatenation of middle and « tail ».
TemplateMiddleList : TemplateMiddle Expression
  1. If raw is false, then
    1. Let string be the TV of TemplateMiddle.
  2. Else,
    1. Let string be the TRV of TemplateMiddle.
  3. Return « string ».
TemplateMiddleList : TemplateMiddleList TemplateMiddle Expression
  1. Let front be TemplateStrings of TemplateMiddleList with argument raw.
  2. If raw is false, then
    1. Let last be the TV of TemplateMiddle.
  3. Else,
    1. Let last be the TRV of TemplateMiddle.
  4. Return the list-concatenation of front and « last ».

13.2.8.3 GetTemplateObject ( templateLiteral )

The abstract operation GetTemplateObject takes argument templateLiteral (a Parse Node) and returns an Array. It performs the following steps when called:

  1. Let realm be the current Realm Record.
  2. Let templateRegistry be realm.[[TemplateMap]].
  3. For each element e of templateRegistry, do
    1. If e.[[Site]] is the same Parse Node as templateLiteral, then
      1. Return e.[[Array]].
  4. Let rawStrings be TemplateStrings of templateLiteral with argument true.
  5. Let cookedStrings be TemplateStrings of templateLiteral with argument false.
  6. Let count be the number of elements in the List cookedStrings.
  7. Assert: count ≤ 232 - 1.
  8. Let template be ! ArrayCreate(count).
  9. Let rawObj be ! ArrayCreate(count).
  10. Let index be 0.
  11. Repeat, while index < count,
    1. Let prop be ! ToString(𝔽(index)).
    2. Let cookedValue be cookedStrings[index].
    3. Perform ! DefinePropertyOrThrow(template, prop, PropertyDescriptor { [[Value]]: cookedValue, [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: false }).
    4. Let rawValue be the String value rawStrings[index].
    5. Perform ! DefinePropertyOrThrow(rawObj, prop, PropertyDescriptor { [[Value]]: rawValue, [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: false }).
    6. Set index to index + 1.
  12. Perform ! SetIntegrityLevel(rawObj, frozen).
  13. Perform ! DefinePropertyOrThrow(template, "raw", PropertyDescriptor { [[Value]]: rawObj, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }).
  14. Perform ! SetIntegrityLevel(template, frozen).
  15. Append the Record { [[Site]]: templateLiteral, [[Array]]: template } to templateRegistry.
  16. Return template.
Note 1

The creation of a template object cannot result in an abrupt completion.

Note 2

Each TemplateLiteral in the program code of a realm is associated with a unique template object that is used in the evaluation of tagged Templates (13.2.8.5). The template objects are frozen and the same template object is used each time a specific tagged Template is evaluated. Whether template objects are created lazily upon first evaluation of the TemplateLiteral or eagerly prior to first evaluation is an implementation choice that is not observable to ECMAScript code.

Note 3

Future editions of this specification may define additional non-enumerable properties of template objects.

13.2.8.4 Runtime Semantics: SubstitutionEvaluation

The syntax-directed operation SubstitutionEvaluation takes no arguments and returns either a normal completion containing a List of ECMAScript language values or an abrupt completion. It is defined piecewise over the following productions:

TemplateSpans : TemplateTail
  1. Return a new empty List.
TemplateSpans : TemplateMiddleList TemplateTail
  1. Return ? SubstitutionEvaluation of TemplateMiddleList.
TemplateMiddleList : TemplateMiddle Expression
  1. Let subRef be the result of evaluating Expression.
  2. Let sub be ? GetValue(subRef).
  3. Return « sub ».
TemplateMiddleList : TemplateMiddleList TemplateMiddle Expression
  1. Let preceding be ? SubstitutionEvaluation of TemplateMiddleList.
  2. Let nextRef be the result of evaluating Expression.
  3. Let next be ? GetValue(nextRef).
  4. Return the list-concatenation of preceding and « next ».

13.2.8.5 Runtime Semantics: Evaluation

TemplateLiteral : NoSubstitutionTemplate
  1. Return the TV of NoSubstitutionTemplate as defined in 12.8.6.
SubstitutionTemplate : TemplateHead Expression TemplateSpans
  1. Let head be the TV of TemplateHead as defined in 12.8.6.
  2. Let subRef be the result of evaluating Expression.
  3. Let sub be ? GetValue(subRef).
  4. Let middle be ? ToString(sub).
  5. Let tail be the result of evaluating TemplateSpans.
  6. ReturnIfAbrupt(tail).
  7. Return the string-concatenation of head, middle, and tail.
Note 1

The string conversion semantics applied to the Expression value are like String.prototype.concat rather than the + operator.

TemplateSpans : TemplateTail
  1. Return the TV of TemplateTail as defined in 12.8.6.
TemplateSpans : TemplateMiddleList TemplateTail
  1. Let head be the result of evaluating TemplateMiddleList.
  2. ReturnIfAbrupt(head).
  3. Let tail be the TV of TemplateTail as defined in 12.8.6.
  4. Return the string-concatenation of head and tail.
TemplateMiddleList : TemplateMiddle Expression
  1. Let head be the TV of TemplateMiddle as defined in 12.8.6.
  2. Let subRef be the result of evaluating Expression.
  3. Let sub be ? GetValue(subRef).
  4. Let middle be ? ToString(sub).
  5. Return the string-concatenation of head and middle.
Note 2

The string conversion semantics applied to the Expression value are like String.prototype.concat rather than the + operator.

TemplateMiddleList : TemplateMiddleList TemplateMiddle Expression
  1. Let rest be the result of evaluating TemplateMiddleList.
  2. ReturnIfAbrupt(rest).
  3. Let middle be the TV of TemplateMiddle as defined in 12.8.6.
  4. Let subRef be the result of evaluating Expression.
  5. Let sub be ? GetValue(subRef).
  6. Let last be ? ToString(sub).
  7. Return the string-concatenation of rest, middle, and last.
Note 3

The string conversion semantics applied to the Expression value are like String.prototype.concat rather than the + operator.

13.2.9 The Grouping Operator

13.2.9.1 Static Semantics: Early Errors

PrimaryExpression : CoverParenthesizedExpressionAndArrowParameterList

13.2.9.2 Runtime Semantics: Evaluation

PrimaryExpression : CoverParenthesizedExpressionAndArrowParameterList
  1. Let expr be the ParenthesizedExpression that is covered by CoverParenthesizedExpressionAndArrowParameterList.
  2. Return the result of evaluating expr.
ParenthesizedExpression : ( Expression )
  1. Return the result of evaluating Expression. This may be of type Reference.
Note

This algorithm does not apply GetValue to the result of evaluating Expression. The principal motivation for this is so that operators such as delete and typeof may be applied to parenthesized expressions.

13.3 Left-Hand-Side Expressions

Syntax

MemberExpression[Yield, Await] : PrimaryExpression[?Yield, ?Await] MemberExpression[?Yield, ?Await] [ Expression[+In, ?Yield, ?Await] ] MemberExpression[?Yield, ?Await] . IdentifierName MemberExpression[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged] SuperProperty[?Yield, ?Await] MetaProperty new MemberExpression[?Yield, ?Await] Arguments[?Yield, ?Await] MemberExpression[?Yield, ?Await] . PrivateIdentifier SuperProperty[Yield, Await] : super [ Expression[+In, ?Yield, ?Await] ] super . IdentifierName MetaProperty : NewTarget ImportMeta NewTarget : new . target ImportMeta : import . meta NewExpression[Yield, Await] : MemberExpression[?Yield, ?Await] new NewExpression[?Yield, ?Await] CallExpression[Yield, Await] : CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await] SuperCall[?Yield, ?Await] ImportCall[?Yield, ?Await] CallExpression[?Yield, ?Await] Arguments[?Yield, ?Await] CallExpression[?Yield, ?Await] [ Expression[+In, ?Yield, ?Await] ] CallExpression[?Yield, ?Await] . IdentifierName CallExpression[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged] CallExpression[?Yield, ?Await] . PrivateIdentifier SuperCall[Yield, Await] : super Arguments[?Yield, ?Await] ImportCall[Yield, Await] : import ( AssignmentExpression[+In, ?Yield, ?Await] ) Arguments[Yield, Await] : ( ) ( ArgumentList[?Yield, ?Await] ) ( ArgumentList[?Yield, ?Await] , ) ArgumentList[Yield, Await] : AssignmentExpression[+In, ?Yield, ?Await] ... AssignmentExpression[+In, ?Yield, ?Await] ArgumentList[?Yield, ?Await] , AssignmentExpression[+In, ?Yield, ?Await] ArgumentList[?Yield, ?Await] , ... AssignmentExpression[+In, ?Yield, ?Await] OptionalExpression[Yield, Await] : MemberExpression[?Yield, ?Await] OptionalChain[?Yield, ?Await] CallExpression[?Yield, ?Await] OptionalChain[?Yield, ?Await] OptionalExpression[?Yield, ?Await] OptionalChain[?Yield, ?Await] OptionalChain[Yield, Await] : ?. Arguments[?Yield, ?Await] ?. [ Expression[+In, ?Yield, ?Await] ] ?. IdentifierName ?. TemplateLiteral[?Yield, ?Await, +Tagged] ?. PrivateIdentifier OptionalChain[?Yield, ?Await] Arguments[?Yield, ?Await] OptionalChain[?Yield, ?Await] [ Expression[+In, ?Yield, ?Await] ] OptionalChain[?Yield, ?Await] . IdentifierName OptionalChain[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged] OptionalChain[?Yield, ?Await] . PrivateIdentifier LeftHandSideExpression[Yield, Await] : NewExpression[?Yield, ?Await] CallExpression[?Yield, ?Await] OptionalExpression[?Yield, ?Await]

Supplemental Syntax

When processing an instance of the production
CallExpression : CoverCallExpressionAndAsyncArrowHead
the interpretation of CoverCallExpressionAndAsyncArrowHead is refined using the following grammar:

CallMemberExpression[Yield, Await] : MemberExpression[?Yield, ?Await] Arguments[?Yield, ?Await]

13.3.1 Static Semantics

13.3.1.1 Static Semantics: Early Errors

OptionalChain : ?. TemplateLiteral OptionalChain TemplateLiteral
  • It is a Syntax Error if any source text is matched by this production.
Note

This production exists in order to prevent automatic semicolon insertion rules (12.9) from being applied to the following code:

a?.b
`c`

so that it would be interpreted as two valid statements. The purpose is to maintain consistency with similar code without optional chaining:

a.b
`c`

which is a valid statement and where automatic semicolon insertion does not apply.

ImportMeta : import . meta

13.3.2 Property Accessors

Note

Properties are accessed by name, using either the dot notation:

or the bracket notation:

The dot notation is explained by the following syntactic conversion:

is identical in its behaviour to

MemberExpression [ <identifier-name-string> ]

and similarly

is identical in its behaviour to

CallExpression [ <identifier-name-string> ]

where <identifier-name-string> is the result of evaluating StringValue of IdentifierName.

13.3.2.1 Runtime Semantics: Evaluation

MemberExpression : MemberExpression [ Expression ]
  1. Let baseReference be the result of evaluating MemberExpression.
  2. Let baseValue be ? GetValue(baseReference).
  3. If the source text matched by this MemberExpression is strict mode code, let strict be true; else let strict be false.
  4. Return ? EvaluatePropertyAccessWithExpressionKey(baseValue, Expression, strict).
MemberExpression : MemberExpression . IdentifierName
  1. Let baseReference be the result of evaluating MemberExpression.
  2. Let baseValue be ? GetValue(baseReference).
  3. If the source text matched by this MemberExpression is strict mode code, let strict be true; else let strict be false.
  4. Return EvaluatePropertyAccessWithIdentifierKey(baseValue, IdentifierName, strict).
MemberExpression : MemberExpression . PrivateIdentifier
  1. Let baseReference be the result of evaluating MemberExpression.
  2. Let baseValue be ? GetValue(baseReference).
  3. Let fieldNameString be the StringValue of PrivateIdentifier.
  4. Return MakePrivateReference(baseValue, fieldNameString).
CallExpression : CallExpression [ Expression ]
  1. Let baseReference be the result of evaluating CallExpression.
  2. Let baseValue be ? GetValue(baseReference).
  3. If the source text matched by this CallExpression is strict mode code, let strict be true; else let strict be false.
  4. Return ? EvaluatePropertyAccessWithExpressionKey(baseValue, Expression, strict).
CallExpression : CallExpression . IdentifierName
  1. Let baseReference be the result of evaluating CallExpression.
  2. Let baseValue be ? GetValue(baseReference).
  3. If the source text matched by this CallExpression is strict mode code, let strict be true; else let strict be false.
  4. Return EvaluatePropertyAccessWithIdentifierKey(baseValue, IdentifierName, strict).
CallExpression : CallExpression . PrivateIdentifier
  1. Let baseReference be the result of evaluating CallExpression.
  2. Let baseValue be ? GetValue(baseReference).
  3. Let fieldNameString be the StringValue of PrivateIdentifier.
  4. Return MakePrivateReference(baseValue, fieldNameString).

13.3.3 EvaluatePropertyAccessWithExpressionKey ( baseValue, expression, strict )

The abstract operation EvaluatePropertyAccessWithExpressionKey takes arguments baseValue (an ECMAScript language value), expression (a Parse Node), and strict (a Boolean) and returns either a normal completion containing a Reference Record or an abrupt completion. It performs the following steps when called:

  1. Let propertyNameReference be the result of evaluating expression.
  2. Let propertyNameValue be ? GetValue(propertyNameReference).
  3. Let propertyKey be ? ToPropertyKey(propertyNameValue).
  4. Return the Reference Record { [[Base]]: baseValue, [[ReferencedName]]: propertyKey, [[Strict]]: strict, [[ThisValue]]: empty }.

13.3.4 EvaluatePropertyAccessWithIdentifierKey ( baseValue, identifierName, strict )

The abstract operation EvaluatePropertyAccessWithIdentifierKey takes arguments baseValue (an ECMAScript language value), identifierName (an IdentifierName Parse Node), and strict (a Boolean) and returns a Reference Record. It performs the following steps when called:

  1. Let propertyNameString be StringValue of identifierName.
  2. Return the Reference Record { [[Base]]: baseValue, [[ReferencedName]]: propertyNameString, [[Strict]]: strict, [[ThisValue]]: empty }.

13.3.5 The new Operator

13.3.5.1 Runtime Semantics: Evaluation

NewExpression : new NewExpression
  1. Return ? EvaluateNew(NewExpression, empty).
MemberExpression : new MemberExpression Arguments
  1. Return ? EvaluateNew(MemberExpression, Arguments).

13.3.5.1.1 EvaluateNew ( constructExpr, arguments )

The abstract operation EvaluateNew takes arguments constructExpr (a NewExpression Parse Node or a MemberExpression Parse Node) and arguments (empty or an Arguments Parse Node) and returns either a normal completion containing an ECMAScript language value or an abrupt completion. It performs the following steps when called:

  1. Let ref be the result of evaluating constructExpr.
  2. Let constructor be ? GetValue(ref).
  3. If arguments is empty, let argList be a new empty List.
  4. Else,
    1. Let argList be ? ArgumentListEvaluation of arguments.
  5. If IsConstructor(constructor) is false, throw a TypeError exception.
  6. Return ? Construct(constructor, argList).

13.3.6 Function Calls

13.3.6.1 Runtime Semantics: Evaluation

CallExpression : CoverCallExpressionAndAsyncArrowHead
  1. Let expr be the CallMemberExpression that is covered by CoverCallExpressionAndAsyncArrowHead.
  2. Let memberExpr be the MemberExpression of expr.
  3. Let arguments be the Arguments of expr.
  4. Let ref be the result of evaluating memberExpr.
  5. Let func be ? GetValue(ref).
  6. If ref is a Reference Record, IsPropertyReference(ref) is false, and ref.[[ReferencedName]] is "eval", then
    1. If SameValue(func, %eval%) is true, then
      1. Let argList be ? ArgumentListEvaluation of arguments.
      2. If argList has no elements, return undefined.
      3. Let evalArg be the first element of argList.
      4. If the source text matched by this CallExpression is strict mode code, let strictCaller be true. Otherwise let strictCaller be false.
      5. Let evalRealm be the current Realm Record.
      6. Return ? PerformEval(evalArg, evalRealm, strictCaller, true).
  7. Let thisCall be this CallExpression.
  8. Let tailCall be IsInTailPosition(thisCall).
  9. Return ? EvaluateCall(func, ref, arguments, tailCall).

A CallExpression evaluation that executes step 6.a.vi is a direct eval.

CallExpression : CallExpression Arguments
  1. Let ref be the result of evaluating CallExpression.
  2. Let func be ? GetValue(ref).
  3. Let thisCall be this CallExpression.
  4. Let tailCall be IsInTailPosition(thisCall).
  5. Return ? EvaluateCall(func, ref, Arguments, tailCall).

13.3.6.2 EvaluateCall ( func, ref, arguments, tailPosition )

The abstract operation EvaluateCall takes arguments func (an ECMAScript language value), ref (an ECMAScript language value or a Reference Record), arguments (a Parse Node), and tailPosition (a Boolean) and returns either a normal completion containing an ECMAScript language value or an abrupt completion. It performs the following steps when called:

  1. If ref is a Reference Record, then
    1. If IsPropertyReference(ref) is true, then
      1. Let thisValue be GetThisValue(ref).
    2. Else,
      1. Let refEnv be ref.[[Base]].
      2. Assert: refEnv is an Environment Record.
      3. Let thisValue be refEnv.WithBaseObject().
  2. Else,
    1. Let thisValue be undefined.
  3. Let argList be ? ArgumentListEvaluation of arguments.
  4. If Type(func) is not Object, throw a TypeError exception.
  5. If IsCallable(func) is false, throw a TypeError exception.
  6. If tailPosition is true, perform PrepareForTailCall().
  7. Return ? Call(func, thisValue, argList).

13.3.7 The super Keyword

13.3.7.1 Runtime Semantics: Evaluation

SuperProperty : super [ Expression ]
  1. Let env be GetThisEnvironment().
  2. Let actualThis be ? env.GetThisBinding().
  3. Let propertyNameReference be the result of evaluating Expression.
  4. Let propertyNameValue be ? GetValue(propertyNameReference).
  5. Let propertyKey be ? ToPropertyKey(propertyNameValue).
  6. If the source text matched by this SuperProperty is strict mode code, let strict be true; else let strict be false.
  7. Return ? MakeSuperPropertyReference(actualThis, propertyKey, strict).
SuperProperty : super . IdentifierName
  1. Let env be GetThisEnvironment().
  2. Let actualThis be ? env.GetThisBinding().
  3. Let propertyKey be StringValue of IdentifierName.
  4. If the source text matched by this SuperProperty is strict mode code, let strict be true; else let strict be false.
  5. Return ? MakeSuperPropertyReference(actualThis, propertyKey, strict).
SuperCall : super Arguments
  1. Let newTarget be GetNewTarget().
  2. Assert: Type(newTarget) is Object.
  3. Let func be GetSuperConstructor().
  4. Let argList be ? ArgumentListEvaluation of Arguments.
  5. If IsConstructor(func) is false, throw a TypeError exception.
  6. Let result be ? Construct(func, argList, newTarget).
  7. Let thisER be GetThisEnvironment().
  8. Perform ? thisER.BindThisValue(result).
  9. Let F be thisER.[[FunctionObject]].
  10. Assert: F is an ECMAScript function object.
  11. Perform ? InitializeInstanceElements(result, F).
  12. Return result.

13.3.7.2 GetSuperConstructor ( )

The abstract operation GetSuperConstructor takes no arguments and returns an ECMAScript language value. It performs the following steps when called:

  1. Let envRec be GetThisEnvironment().
  2. Assert: envRec is a function Environment Record.
  3. Let activeFunction be envRec.[[FunctionObject]].
  4. Assert: activeFunction is an ECMAScript function object.
  5. Let superConstructor be ! activeFunction.[[GetPrototypeOf]]().
  6. Return superConstructor.

13.3.7.3 MakeSuperPropertyReference ( actualThis, propertyKey, strict )

The abstract operation MakeSuperPropertyReference takes arguments actualThis, propertyKey, and strict and returns either a normal completion containing a Super Reference Record or an abrupt completion. It performs the following steps when called:

  1. Let env be GetThisEnvironment().
  2. Assert: env.HasSuperBinding() is true.
  3. Let baseValue be ? env.GetSuperBase().
  4. Return the Reference Record { [[Base]]: baseValue, [[ReferencedName]]: propertyKey, [[Strict]]: strict, [[ThisValue]]: actualThis }.

13.3.8 Argument Lists

Note

The evaluation of an argument list produces a List of values.

13.3.8.1 Runtime Semantics: ArgumentListEvaluation

The syntax-directed operation ArgumentListEvaluation takes no arguments and returns either a normal completion containing a List of ECMAScript language values or an abrupt completion. It is defined piecewise over the following productions:

Arguments : ( )
  1. Return a new empty List.
ArgumentList : AssignmentExpression
  1. Let ref be the result of evaluating AssignmentExpression.
  2. Let arg be ? GetValue(ref).
  3. Return « arg ».
ArgumentList : ... AssignmentExpression
  1. Let list be a new empty List.
  2. Let spreadRef be the result of evaluating AssignmentExpression.
  3. Let spreadObj be ? GetValue(spreadRef).
  4. Let iteratorRecord be ? GetIterator(spreadObj).
  5. Repeat,
    1. Let next be ? IteratorStep(iteratorRecord).
    2. If next is false, return list.
    3. Let nextArg be ? IteratorValue(next).
    4. Append nextArg as the last element of list.
ArgumentList : ArgumentList , AssignmentExpression
  1. Let precedingArgs be ? ArgumentListEvaluation of ArgumentList.
  2. Let ref be the result of evaluating AssignmentExpression.
  3. Let arg be ? GetValue(ref).
  4. Return the list-concatenation of precedingArgs and « arg ».
ArgumentList : ArgumentList , ... AssignmentExpression
  1. Let precedingArgs be ? ArgumentListEvaluation of ArgumentList.
  2. Let spreadRef be the result of evaluating AssignmentExpression.
  3. Let iteratorRecord be ? GetIterator(? GetValue(spreadRef)).
  4. Repeat,
    1. Let next be ? IteratorStep(iteratorRecord).
    2. If next is false, return precedingArgs.
    3. Let nextArg be ? IteratorValue(next).
    4. Append nextArg as the last element of precedingArgs.
TemplateLiteral : NoSubstitutionTemplate
  1. Let templateLiteral be this TemplateLiteral.
  2. Let siteObj be GetTemplateObject(templateLiteral).
  3. Return « siteObj ».
TemplateLiteral : SubstitutionTemplate
  1. Let templateLiteral be this TemplateLiteral.
  2. Let siteObj be GetTemplateObject(templateLiteral).
  3. Let remaining be ? ArgumentListEvaluation of SubstitutionTemplate.
  4. Return the list-concatenation of « siteObj » and remaining.
SubstitutionTemplate : TemplateHead Expression TemplateSpans
  1. Let firstSubRef be the result of evaluating Expression.
  2. Let firstSub be ? GetValue(firstSubRef).
  3. Let restSub be ? SubstitutionEvaluation of TemplateSpans.
  4. Assert: restSub is a possibly empty List.
  5. Return the list-concatenation of « firstSub » and restSub.

13.3.9 Optional Chains

Note
An optional chain is a chain of one or more property accesses and function calls, the first of which begins with the token ?..

13.3.9.1 Runtime Semantics: Evaluation

OptionalExpression : MemberExpression OptionalChain
  1. Let baseReference be the result of evaluating MemberExpression.
  2. Let baseValue be ? GetValue(baseReference).
  3. If baseValue is undefined or null, then
    1. Return undefined.
  4. Return ? ChainEvaluation of OptionalChain with arguments baseValue and baseReference.
OptionalExpression : CallExpression OptionalChain
  1. Let baseReference be the result of evaluating CallExpression.
  2. Let baseValue be ? GetValue(baseReference).
  3. If baseValue is undefined or null, then
    1. Return undefined.
  4. Return ? ChainEvaluation of OptionalChain with arguments baseValue and baseReference.
OptionalExpression : OptionalExpression OptionalChain
  1. Let baseReference be the result of evaluating OptionalExpression.
  2. Let baseValue be ? GetValue(baseReference).
  3. If baseValue is undefined or null, then
    1. Return undefined.
  4. Return ? ChainEvaluation of OptionalChain with arguments baseValue and baseReference.

13.3.9.2 Runtime Semantics: ChainEvaluation

The syntax-directed operation ChainEvaluation takes arguments baseValue and baseReference and returns either a normal completion containing an ECMAScript language value or an abrupt completion. It is defined piecewise over the following productions:

OptionalChain : ?. Arguments
  1. Let thisChain be this OptionalChain.
  2. Let tailCall be IsInTailPosition(thisChain).
  3. Return ? EvaluateCall(baseValue, baseReference, Arguments, tailCall).
OptionalChain : ?. [ Expression ]
  1. If the source text matched by this OptionalChain is strict mode code, let strict be true; else let strict be false.
  2. Return ? EvaluatePropertyAccessWithExpressionKey(baseValue, Expression, strict).
OptionalChain : ?. IdentifierName
  1. If the source text matched by this OptionalChain is strict mode code, let strict be true; else let strict be false.
  2. Return EvaluatePropertyAccessWithIdentifierKey(baseValue, IdentifierName, strict).
OptionalChain : ?. PrivateIdentifier
  1. Let fieldNameString be the StringValue of PrivateIdentifier.
  2. Return MakePrivateReference(baseValue, fieldNameString).
OptionalChain : OptionalChain Arguments
  1. Let optionalChain be OptionalChain.
  2. Let newReference be ? ChainEvaluation of optionalChain with arguments baseValue and baseReference.
  3. Let newValue be ? GetValue(newReference).
  4. Let thisChain be this OptionalChain.
  5. Let tailCall be IsInTailPosition(thisChain).
  6. Return ? EvaluateCall(newValue, newReference, Arguments, tailCall).
OptionalChain : OptionalChain [ Expression ]
  1. Let optionalChain be OptionalChain.
  2. Let newReference be ? ChainEvaluation of optionalChain with arguments baseValue and baseReference.
  3. Let newValue be ? GetValue(newReference).
  4. If the source text matched by this OptionalChain is strict mode code, let strict be true; else let strict be false.
  5. Return ? EvaluatePropertyAccessWithExpressionKey(newValue, Expression, strict).
OptionalChain : OptionalChain . IdentifierName
  1. Let optionalChain be OptionalChain.
  2. Let newReference be ? ChainEvaluation of optionalChain with arguments baseValue and baseReference.
  3. Let newValue be ? GetValue(newReference).
  4. If the source text matched by this OptionalChain is strict mode code, let strict be true; else let strict be false.
  5. Return EvaluatePropertyAccessWithIdentifierKey(newValue, IdentifierName, strict).
OptionalChain : OptionalChain . PrivateIdentifier
  1. Let optionalChain be OptionalChain.
  2. Let newReference be ? ChainEvaluation of optionalChain with arguments baseValue and baseReference.
  3. Let newValue be ? GetValue(newReference).
  4. Let fieldNameString be the StringValue of PrivateIdentifier.
  5. Return MakePrivateReference(newValue, fieldNameString).

13.3.10 Import Calls

13.3.10.1 Runtime Semantics: Evaluation

ImportCall : import ( AssignmentExpression )
  1. Let referencingScriptOrModule be GetActiveScriptOrModule().
  2. Let argRef be the result of evaluating AssignmentExpression.
  3. Let specifier be ? GetValue(argRef).
  4. Let promiseCapability be ! NewPromiseCapability(%Promise%).
  5. Let specifierString be Completion(ToString(specifier)).
  6. IfAbruptRejectPromise(specifierString, promiseCapability).
  7. Perform HostImportModuleDynamically(referencingScriptOrModule, specifierString, promiseCapability).
  8. Return promiseCapability.[[Promise]].

13.3.11 Tagged Templates

Note

A tagged template is a function call where the arguments of the call are derived from a TemplateLiteral (13.2.8). The actual arguments include a template object (13.2.8.3) and the values produced by evaluating the expressions embedded within the TemplateLiteral.

13.3.11.1 Runtime Semantics: Evaluation

MemberExpression : MemberExpression TemplateLiteral
  1. Let tagRef be the result of evaluating MemberExpression.
  2. Let tagFunc be ? GetValue(tagRef).
  3. Let thisCall be this MemberExpression.
  4. Let tailCall be IsInTailPosition(thisCall).
  5. Return ? EvaluateCall(tagFunc, tagRef, TemplateLiteral, tailCall).
CallExpression : CallExpression TemplateLiteral
  1. Let tagRef be the result of evaluating CallExpression.
  2. Let tagFunc be ? GetValue(tagRef).
  3. Let thisCall be this CallExpression.
  4. Let tailCall be IsInTailPosition(thisCall).
  5. Return ? EvaluateCall(tagFunc, tagRef, TemplateLiteral, tailCall).

13.3.12 Meta Properties

13.3.12.1 Runtime Semantics: Evaluation

NewTarget : new . target
  1. Return GetNewTarget().
ImportMeta : import . meta
  1. Let module be GetActiveScriptOrModule().
  2. Assert: module is a Source Text Module Record.
  3. Let importMeta be module.[[ImportMeta]].
  4. If importMeta is empty, then
    1. Set importMeta to OrdinaryObjectCreate(null).
    2. Let importMetaValues be HostGetImportMetaProperties(module).
    3. For each Record { [[Key]], [[Value]] } p of importMetaValues, do
      1. Perform ! CreateDataPropertyOrThrow(importMeta, p.[[Key]], p.[[Value]]).
    4. Perform HostFinalizeImportMeta(importMeta, module).
    5. Set module.[[ImportMeta]] to importMeta.
    6. Return importMeta.
  5. Else,
    1. Assert: Type(importMeta) is Object.
    2. Return importMeta.

13.3.12.1.1 HostGetImportMetaProperties ( moduleRecord )

The host-defined abstract operation HostGetImportMetaProperties takes argument moduleRecord (a Module Record) and returns a List of Records with fields [[Key]] (a property key) and [[Value]] (an ECMAScript language value). It allows hosts to provide property keys and values for the object returned from import.meta.

An implementation of HostGetImportMetaProperties must conform to the following requirements:

The default implementation of HostGetImportMetaProperties is to return a new empty List.

13.3.12.1.2 HostFinalizeImportMeta ( importMeta, moduleRecord )

The host-defined abstract operation HostFinalizeImportMeta takes arguments importMeta (an Object) and moduleRecord (a Module Record) and returns unused. It allows hosts to perform any extraordinary operations to prepare the object returned from import.meta.

Most hosts will be able to simply define HostGetImportMetaProperties, and leave HostFinalizeImportMeta with its default behaviour. However, HostFinalizeImportMeta provides an "escape hatch" for hosts which need to directly manipulate the object before it is exposed to ECMAScript code.

An implementation of HostFinalizeImportMeta must conform to the following requirements:

  • It must return unused.

The default implementation of HostFinalizeImportMeta is to return unused.

13.4 Update Expressions

Syntax

UpdateExpression[Yield, Await] : LeftHandSideExpression[?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] [no LineTerminator here] ++ LeftHandSideExpression[?Yield, ?Await] [no LineTerminator here] -- ++ UnaryExpression[?Yield, ?Await] -- UnaryExpression[?Yield, ?Await]

13.4.1 Static Semantics: Early Errors

UpdateExpression : LeftHandSideExpression ++ LeftHandSideExpression -- UpdateExpression : ++ UnaryExpression -- UnaryExpression

13.4.2 Postfix Increment Operator

13.4.2.1 Runtime Semantics: Evaluation

UpdateExpression : LeftHandSideExpression ++
  1. Let lhs be the result of evaluating LeftHandSideExpression.
  2. Let oldValue be ? ToNumeric(? GetValue(lhs)).
  3. If Type(oldValue) is Number, then
    1. Let newValue be Number::add(oldValue, 1𝔽).
  4. Else,
    1. Assert: Type(oldValue) is BigInt.
    2. Let newValue be BigInt::add(oldValue, 1).
  5. Perform ? PutValue(lhs, newValue).
  6. Return oldValue.

13.4.3 Postfix Decrement Operator

13.4.3.1 Runtime Semantics: Evaluation

UpdateExpression : LeftHandSideExpression --
  1. Let lhs be the result of evaluating LeftHandSideExpression.
  2. Let oldValue be ? ToNumeric(? GetValue(lhs)).
  3. If Type(oldValue) is Number, then
    1. Let newValue be Number::subtract(oldValue, 1𝔽).
  4. Else,
    1. Assert: Type(oldValue) is BigInt.
    2. Let newValue be BigInt::subtract(oldValue, 1).
  5. Perform ? PutValue(lhs, newValue).
  6. Return oldValue.

13.4.4 Prefix Increment Operator

13.4.4.1 Runtime Semantics: Evaluation

UpdateExpression : ++ UnaryExpression
  1. Let expr be the result of evaluating UnaryExpression.
  2. Let oldValue be ? ToNumeric(? GetValue(expr)).
  3. If Type(oldValue) is Number, then
    1. Let newValue be Number::add(oldValue, 1𝔽).
  4. Else,
    1. Assert: Type(oldValue) is BigInt.
    2. Let newValue be BigInt::add(oldValue, 1).
  5. Perform ? PutValue(expr, newValue).
  6. Return newValue.

13.4.5 Prefix Decrement Operator

13.4.5.1 Runtime Semantics: Evaluation

UpdateExpression : -- UnaryExpression
  1. Let expr be the result of evaluating UnaryExpression.
  2. Let oldValue be ? ToNumeric(? GetValue(expr)).
  3. If Type(oldValue) is Number, then
    1. Let newValue be Number::subtract(oldValue, 1𝔽).
  4. Else,
    1. Assert: Type(oldValue) is BigInt.
    2. Let newValue be BigInt::subtract(oldValue, 1).
  5. Perform ? PutValue(expr, newValue).
  6. Return newValue.

13.5 Unary Operators

Syntax

UnaryExpression[Yield, Await] : UpdateExpression[?Yield, ?Await] delete UnaryExpression[?Yield, ?Await] void UnaryExpression[?Yield, ?Await] typeof UnaryExpression[?Yield, ?Await] + UnaryExpression[?Yield, ?Await] - UnaryExpression[?Yield, ?Await] ~ UnaryExpression[?Yield, ?Await] ! UnaryExpression[?Yield, ?Await] [+Await] AwaitExpression[?Yield]

13.5.1 The delete Operator

13.5.1.1 Static Semantics: Early Errors

UnaryExpression : delete UnaryExpression Note

The last rule means that expressions such as delete (((foo))) produce early errors because of recursive application of the first rule.

13.5.1.2 Runtime Semantics: Evaluation

UnaryExpression : delete UnaryExpression
  1. Let ref be the result of evaluating UnaryExpression.
  2. ReturnIfAbrupt(ref).
  3. If ref is not a Reference Record, return true.
  4. If IsUnresolvableReference(ref) is true, then
    1. Assert: ref.[[Strict]] is false.
    2. Return true.
  5. If IsPropertyReference(ref) is true, then
    1. Assert: IsPrivateReference(ref) is false.
    2. If IsSuperReference(ref) is true, throw a ReferenceError exception.
    3. Let baseObj be ? ToObject(ref.[[Base]]).
    4. Let deleteStatus be ? baseObj.[[Delete]](ref.[[ReferencedName]]).
    5. If deleteStatus is false and ref.[[Strict]] is true, throw a TypeError exception.
    6. Return deleteStatus.
  6. Else,
    1. Let base be ref.[[Base]].
    2. Assert: base is an Environment Record.
    3. Return ? base.DeleteBinding(ref.[[ReferencedName]]).
Note 1

When a delete operator occurs within strict mode code, a SyntaxError exception is thrown if its UnaryExpression is a direct reference to a variable, function argument, or function name. In addition, if a delete operator occurs within strict mode code and the property to be deleted has the attribute { [[Configurable]]: false } (or otherwise cannot be deleted), a TypeError exception is thrown.

Note 2

The object that may be created in step 5.c is not accessible outside of the above abstract operation and the ordinary object [[Delete]] internal method. An implementation might choose to avoid the actual creation of that object.

13.5.2 The void Operator

13.5.2.1 Runtime Semantics: Evaluation

UnaryExpression : void UnaryExpression
  1. Let expr be the result of evaluating UnaryExpression.
  2. Perform ? GetValue(expr).
  3. Return undefined.
Note

GetValue must be called even though its value is not used because it may have observable side-effects.

13.5.3 The typeof Operator

13.5.3.1 Runtime Semantics: Evaluation

UnaryExpression : typeof UnaryExpression
  1. Let val be the result of evaluating UnaryExpression.
  2. If val is a Reference Record, then
    1. If IsUnresolvableReference(val) is true, return "undefined".
  3. Set val to ? GetValue(val).
  4. NOTE: This step is replaced in section B.3.6.3.
  5. Return a String according to Table 41.
Table 41: typeof Operator Results
Type of val Result
Undefined "undefined"
Null "object"
Boolean "boolean"
Number "number"
String "string"
Symbol "symbol"
BigInt "bigint"
Object (does not implement [[Call]]) "object"
Object (implements [[Call]]) "function"
Note

An additional entry related to [[IsHTMLDDA]] Internal Slot can be found in B.3.6.3.

13.5.4 Unary + Operator

Note

The unary + operator converts its operand to Number type.

13.5.4.1 Runtime Semantics: Evaluation

UnaryExpression : + UnaryExpression
  1. Let expr be the result of evaluating UnaryExpression.
  2. Return ? ToNumber(? GetValue(expr)).

13.5.5 Unary - Operator

Note

The unary - operator converts its operand to Number type and then negates it. Negating +0𝔽 produces -0𝔽, and negating -0𝔽 produces +0𝔽.

13.5.5.1 Runtime Semantics: Evaluation

UnaryExpression : - UnaryExpression
  1. Let expr be the result of evaluating UnaryExpression.
  2. Let oldValue be ? ToNumeric(? GetValue(expr)).
  3. Let T be Type(oldValue).
  4. If Type(oldValue) is Number, then
    1. Return Number::unaryMinus(oldValue).
  5. Else,
    1. Assert: Type(oldValue) is BigInt.
    2. Return BigInt::unaryMinus(oldValue).

13.5.6 Bitwise NOT Operator ( ~ )

13.5.6.1 Runtime Semantics: Evaluation

UnaryExpression : ~ UnaryExpression
  1. Let expr be the result of evaluating UnaryExpression.
  2. Let oldValue be ? ToNumeric(? GetValue(expr)).
  3. Let T be Type(oldValue).
  4. If Type(oldValue) is Number, then
    1. Return Number::bitwiseNOT(oldValue).
  5. Else,
    1. Assert: Type(oldValue) is BigInt.
    2. Return BigInt::bitwiseNOT(oldValue).

13.5.7 Logical NOT Operator ( ! )

13.5.7.1 Runtime Semantics: Evaluation

UnaryExpression : ! UnaryExpression
  1. Let expr be the result of evaluating UnaryExpression.
  2. Let oldValue be ToBoolean(? GetValue(expr)).
  3. If oldValue is true, return false.
  4. Return true.

13.6 Exponentiation Operator

Syntax

ExponentiationExpression[Yield, Await] : UnaryExpression[?Yield, ?Await] UpdateExpression[?Yield, ?Await] ** ExponentiationExpression[?Yield, ?Await]

13.6.1 Runtime Semantics: Evaluation

ExponentiationExpression : UpdateExpression ** ExponentiationExpression
  1. Return ? EvaluateStringOrNumericBinaryExpression(UpdateExpression, **, ExponentiationExpression).

13.7 Multiplicative Operators

Syntax

MultiplicativeExpression[Yield, Await] : ExponentiationExpression[?Yield, ?Await] MultiplicativeExpression[?Yield, ?Await] MultiplicativeOperator ExponentiationExpression[?Yield, ?Await] MultiplicativeOperator : one of * / % Note
  • The * operator performs multiplication, producing the product of its operands.
  • The / operator performs division, producing the quotient of its operands.
  • The % operator yields the remainder of its operands from an implied division.

13.7.1 Runtime Semantics: Evaluation

MultiplicativeExpression : MultiplicativeExpression MultiplicativeOperator ExponentiationExpression
  1. Let opText be the source text matched by MultiplicativeOperator.
  2. Return ? EvaluateStringOrNumericBinaryExpression(MultiplicativeExpression, opText, ExponentiationExpression).

13.8 Additive Operators

Syntax

AdditiveExpression[Yield, Await] : MultiplicativeExpression[?Yield, ?Await] AdditiveExpression[?Yield, ?Await] + MultiplicativeExpression[?Yield, ?Await] AdditiveExpression[?Yield, ?Await] - MultiplicativeExpression[?Yield, ?Await]

13.8.1 The Addition Operator ( + )

Note

The addition operator either performs string concatenation or numeric addition.

13.8.1.1 Runtime Semantics: Evaluation

AdditiveExpression : AdditiveExpression + MultiplicativeExpression
  1. Return ? EvaluateStringOrNumericBinaryExpression(AdditiveExpression, +, MultiplicativeExpression).

13.8.2 The Subtraction Operator ( - )

Note

The - operator performs subtraction, producing the difference of its operands.

13.8.2.1 Runtime Semantics: Evaluation

AdditiveExpression : AdditiveExpression - MultiplicativeExpression
  1. Return ? EvaluateStringOrNumericBinaryExpression(AdditiveExpression, -, MultiplicativeExpression).

13.9 Bitwise Shift Operators

Syntax

ShiftExpression[Yield, Await] : AdditiveExpression[?Yield, ?Await] ShiftExpression[?Yield, ?Await] << AdditiveExpression[?Yield, ?Await] ShiftExpression[?Yield, ?Await] >> AdditiveExpression[?Yield, ?Await] ShiftExpression[?Yield, ?Await] >>> AdditiveExpression[?Yield, ?Await]

13.9.1 The Left Shift Operator ( << )

Note

Performs a bitwise left shift operation on the left operand by the amount specified by the right operand.

13.9.1.1 Runtime Semantics: Evaluation

ShiftExpression : ShiftExpression << AdditiveExpression
  1. Return ? EvaluateStringOrNumericBinaryExpression(ShiftExpression, <<, AdditiveExpression).

13.9.2 The Signed Right Shift Operator ( >> )

Note

Performs a sign-filling bitwise right shift operation on the left operand by the amount specified by the right operand.

13.9.2.1 Runtime Semantics: Evaluation

ShiftExpression : ShiftExpression >> AdditiveExpression
  1. Return ? EvaluateStringOrNumericBinaryExpression(ShiftExpression, >>, AdditiveExpression).

13.9.3 The Unsigned Right Shift Operator ( >>> )

Note

Performs a zero-filling bitwise right shift operation on the left operand by the amount specified by the right operand.

13.9.3.1 Runtime Semantics: Evaluation

ShiftExpression : ShiftExpression >>> AdditiveExpression
  1. Return ? EvaluateStringOrNumericBinaryExpression(ShiftExpression, >>>, AdditiveExpression).

13.10 Relational Operators

Note 1

The result of evaluating a relational operator is always of type Boolean, reflecting whether the relationship named by the operator holds between its two operands.

Syntax

RelationalExpression[In, Yield, Await] : ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] < ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] > ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] <= ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] >= ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] instanceof ShiftExpression[?Yield, ?Await] [+In] RelationalExpression[+In, ?Yield, ?Await] in ShiftExpression[?Yield, ?Await] [+In] PrivateIdentifier in ShiftExpression[?Yield, ?Await] Note 2

The [In] grammar parameter is needed to avoid confusing the in operator in a relational expression with the in operator in a for statement.

13.10.1 Runtime Semantics: Evaluation

RelationalExpression : RelationalExpression < ShiftExpression
  1. Let lref be the result of evaluating RelationalExpression.
  2. Let lval be ? GetValue(lref).
  3. Let rref be the result of evaluating ShiftExpression.
  4. Let rval be ? GetValue(rref).
  5. Let r be ? IsLessThan(lval, rval, true).
  6. If r is undefined, return false. Otherwise, return r.
RelationalExpression : RelationalExpression > ShiftExpression
  1. Let lref be the result of evaluating RelationalExpression.
  2. Let lval be ? GetValue(lref).
  3. Let rref be the result of evaluating ShiftExpression.
  4. Let rval be ? GetValue(rref).
  5. Let r be ? IsLessThan(rval, lval, false).
  6. If r is undefined, return false. Otherwise, return r.
RelationalExpression : RelationalExpression <= ShiftExpression
  1. Let lref be the result of evaluating RelationalExpression.
  2. Let lval be ? GetValue(lref).
  3. Let rref be the result of evaluating ShiftExpression.
  4. Let rval be ? GetValue(rref).
  5. Let r be ? IsLessThan(rval, lval, false).
  6. If r is true or undefined, return false. Otherwise, return true.
RelationalExpression : RelationalExpression >= ShiftExpression
  1. Let lref be the result of evaluating RelationalExpression.
  2. Let lval be ? GetValue(lref).
  3. Let rref be the result of evaluating ShiftExpression.
  4. Let rval be ? GetValue(rref).
  5. Let r be ? IsLessThan(lval, rval, true).
  6. If r is true or undefined, return false. Otherwise, return true.
RelationalExpression : RelationalExpression instanceof ShiftExpression
  1. Let lref be the result of evaluating RelationalExpression.
  2. Let lval be ? GetValue(lref).
  3. Let rref be the result of evaluating ShiftExpression.
  4. Let rval be ? GetValue(rref).
  5. Return ? InstanceofOperator(lval, rval).
RelationalExpression : RelationalExpression in ShiftExpression
  1. Let lref be the result of evaluating RelationalExpression.
  2. Let lval be ? GetValue(lref).
  3. Let rref be the result of evaluating ShiftExpression.
  4. Let rval be ? GetValue(rref).
  5. If Type(rval) is not Object, throw a TypeError exception.
  6. Return ? HasProperty(rval, ? ToPropertyKey(lval)).
RelationalExpression : PrivateIdentifier in ShiftExpression
  1. Let privateIdentifier be the StringValue of PrivateIdentifier.
  2. Let rref be the result of evaluating ShiftExpression.
  3. Let rval be ? GetValue(rref).
  4. If Type(rval) is not Object, throw a TypeError exception.
  5. Let privateEnv be the running execution context's PrivateEnvironment.
  6. Let privateName be ResolvePrivateIdentifier(privateEnv, privateIdentifier).
  7. If PrivateElementFind(rval, privateName) is not empty, return true.
  8. Return false.

13.10.2 InstanceofOperator ( V, target )

The abstract operation InstanceofOperator takes arguments V (an ECMAScript language value) and target (an ECMAScript language value) and returns either a normal completion containing a Boolean or an abrupt completion. It implements the generic algorithm for determining if V is an instance of target either by consulting target's @@hasInstance method or, if absent, determining whether the value of target's "prototype" property is present in V's prototype chain. It performs the following steps when called:

  1. If Type(target) is not Object, throw a TypeError exception.
  2. Let instOfHandler be ? GetMethod(target, @@hasInstance).
  3. If instOfHandler is not undefined, then
    1. Return ToBoolean(? Call(instOfHandler, target, « V »)).
  4. If IsCallable(target) is false, throw a TypeError exception.
  5. Return ? OrdinaryHasInstance(target, V).
Note

Steps 4 and 5 provide compatibility with previous editions of ECMAScript that did not use a @@hasInstance method to define the instanceof operator semantics. If an object does not define or inherit @@hasInstance it uses the default instanceof semantics.

13.11 Equality Operators

Note

The result of evaluating an equality operator is always of type Boolean, reflecting whether the relationship named by the operator holds between its two operands.

Syntax

EqualityExpression[In, Yield, Await] : RelationalExpression[?In, ?Yield, ?Await] EqualityExpression[?In, ?Yield, ?Await] == RelationalExpression[?In, ?Yield, ?Await] EqualityExpression[?In, ?Yield, ?Await] != RelationalExpression[?In, ?Yield, ?Await] EqualityExpression[?In, ?Yield, ?Await] === RelationalExpression[?In, ?Yield, ?Await] EqualityExpression[?In, ?Yield, ?Await] !== RelationalExpression[?In, ?Yield, ?Await]

13.11.1 Runtime Semantics: Evaluation

EqualityExpression : EqualityExpression == RelationalExpression
  1. Let lref be the result of evaluating EqualityExpression.
  2. Let lval be ? GetValue(lref).
  3. Let rref be the result of evaluating RelationalExpression.
  4. Let rval be ? GetValue(rref).
  5. Return ? IsLooselyEqual(rval, lval).
EqualityExpression : EqualityExpression != RelationalExpression
  1. Let lref be the result of evaluating EqualityExpression.
  2. Let lval be ? GetValue(lref).
  3. Let rref be the result of evaluating RelationalExpression.
  4. Let rval be ? GetValue(rref).
  5. Let r be ? IsLooselyEqual(rval, lval).
  6. If r is true, return false. Otherwise, return true.
EqualityExpression : EqualityExpression === RelationalExpression
  1. Let lref be the result of evaluating EqualityExpression.
  2. Let lval be ? GetValue(lref).
  3. Let rref be the result of evaluating RelationalExpression.
  4. Let rval be ? GetValue(rref).
  5. Return IsStrictlyEqual(rval, lval).
EqualityExpression : EqualityExpression !== RelationalExpression
  1. Let lref be the result of evaluating EqualityExpression.
  2. Let lval be ? GetValue(lref).
  3. Let rref be the result of evaluating RelationalExpression.
  4. Let rval be ? GetValue(rref).
  5. Let r be IsStrictlyEqual(rval, lval).
  6. If r is true, return false. Otherwise, return true.
Note 1

Given the above definition of equality:

  • String comparison can be forced by: `${a}` == `${b}`.
  • Numeric comparison can be forced by: +a == +b.
  • Boolean comparison can be forced by: !a == !b.
Note 2

The equality operators maintain the following invariants:

  • A != B is equivalent to !(A == B).
  • A == B is equivalent to B == A, except in the order of evaluation of A and B.
Note 3

The equality operator is not always transitive. For example, there might be two distinct String objects, each representing the same String value; each String object would be considered equal to the String value by the == operator, but the two String objects would not be equal to each other. For example:

  • new String("a") == "a" and "a" == new String("a") are both true.
  • new String("a") == new String("a") is false.
Note 4

Comparison of Strings uses a simple equality test on sequences of code unit values. There is no attempt to use the more complex, semantically oriented definitions of character or string equality and collating order defined in the Unicode specification. Therefore Strings values that are canonically equal according to the Unicode Standard could test as unequal. In effect this algorithm assumes that both Strings are already in normalized form.

13.12 Binary Bitwise Operators

Syntax

BitwiseANDExpression[In, Yield, Await] : EqualityExpression[?In, ?Yield, ?Await] BitwiseANDExpression[?In, ?Yield, ?Await] & EqualityExpression[?In, ?Yield, ?Await] BitwiseXORExpression[In, Yield, Await] : BitwiseANDExpression[?In, ?Yield, ?Await] BitwiseXORExpression[?In, ?Yield, ?Await] ^ BitwiseANDExpression[?In, ?Yield, ?Await] BitwiseORExpression[In, Yield, Await] : BitwiseXORExpression[?In, ?Yield, ?Await] BitwiseORExpression[?In, ?Yield, ?Await] | BitwiseXORExpression[?In, ?Yield, ?Await]

13.12.1 Runtime Semantics: Evaluation

BitwiseANDExpression : BitwiseANDExpression & EqualityExpression
  1. Return ? EvaluateStringOrNumericBinaryExpression(BitwiseANDExpression, &, EqualityExpression).
BitwiseXORExpression : BitwiseXORExpression ^ BitwiseANDExpression
  1. Return ? EvaluateStringOrNumericBinaryExpression(BitwiseXORExpression, ^, BitwiseANDExpression).
BitwiseORExpression : BitwiseORExpression | BitwiseXORExpression
  1. Return ? EvaluateStringOrNumericBinaryExpression(BitwiseORExpression, |, BitwiseXORExpression).

13.13 Binary Logical Operators

Syntax

LogicalANDExpression[In, Yield, Await] : BitwiseORExpression[?In, ?Yield, ?Await] LogicalANDExpression[?In, ?Yield, ?Await] && BitwiseORExpression[?In, ?Yield, ?Await] LogicalORExpression[In, Yield, Await] : LogicalANDExpression[?In, ?Yield, ?Await] LogicalORExpression[?In, ?Yield, ?Await] || LogicalANDExpression[?In, ?Yield, ?Await] CoalesceExpression[In, Yield, Await] : CoalesceExpressionHead[?In, ?Yield, ?Await] ?? BitwiseORExpression[?In, ?Yield, ?Await] CoalesceExpressionHead[In, Yield, Await] : CoalesceExpression[?In, ?Yield, ?Await] BitwiseORExpression[?In, ?Yield, ?Await] ShortCircuitExpression[In, Yield, Await] : LogicalORExpression[?In, ?Yield, ?Await] CoalesceExpression[?In, ?Yield, ?Await] Note

The value produced by a && or || operator is not necessarily of type Boolean. The value produced will always be the value of one of the two operand expressions.

13.13.1 Runtime Semantics: Evaluation

LogicalANDExpression : LogicalANDExpression && BitwiseORExpression
  1. Let lref be the result of evaluating LogicalANDExpression.
  2. Let lval be ? GetValue(lref).
  3. Let lbool be ToBoolean(lval).
  4. If lbool is false, return lval.
  5. Let rref be the result of evaluating BitwiseORExpression.
  6. Return ? GetValue(rref).
LogicalORExpression : LogicalORExpression || LogicalANDExpression
  1. Let lref be the result of evaluating LogicalORExpression.
  2. Let lval be ? GetValue(lref).
  3. Let lbool be ToBoolean(lval).
  4. If lbool is true, return lval.
  5. Let rref be the result of evaluating LogicalANDExpression.
  6. Return ? GetValue(rref).
CoalesceExpression : CoalesceExpressionHead ?? BitwiseORExpression
  1. Let lref be the result of evaluating CoalesceExpressionHead.
  2. Let lval be ? GetValue(lref).
  3. If lval is undefined or null, then
    1. Let rref be the result of evaluating BitwiseORExpression.
    2. Return ? GetValue(rref).
  4. Otherwise, return lval.

13.14 Conditional Operator ( ? : )

Syntax

ConditionalExpression[In, Yield, Await] : ShortCircuitExpression[?In, ?Yield, ?Await] ShortCircuitExpression[?In, ?Yield, ?Await] ? AssignmentExpression[+In, ?Yield, ?Await] : AssignmentExpression[?In, ?Yield, ?Await] Note

The grammar for a ConditionalExpression in ECMAScript is slightly different from that in C and Java, which each allow the second subexpression to be an Expression but restrict the third expression to be a ConditionalExpression. The motivation for this difference in ECMAScript is to allow an assignment expression to be governed by either arm of a conditional and to eliminate the confusing and fairly useless case of a comma expression as the centre expression.

13.14.1 Runtime Semantics: Evaluation

ConditionalExpression : ShortCircuitExpression ? AssignmentExpression : AssignmentExpression
  1. Let lref be the result of evaluating ShortCircuitExpression.
  2. Let lval be ToBoolean(? GetValue(lref)).
  3. If lval is true, then
    1. Let trueRef be the result of evaluating the first AssignmentExpression.
    2. Return ? GetValue(trueRef).
  4. Else,
    1. Let falseRef be the result of evaluating the second AssignmentExpression.
    2. Return ? GetValue(falseRef).

13.15 Assignment Operators

Syntax

AssignmentExpression[In, Yield, Await] : ConditionalExpression[?In, ?Yield, ?Await] [+Yield] YieldExpression[?In, ?Await] ArrowFunction[?In, ?Yield, ?Await] AsyncArrowFunction[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] = AssignmentExpression[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] AssignmentOperator AssignmentExpression[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] &&= AssignmentExpression[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] ||= AssignmentExpression[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] ??= AssignmentExpression[?In, ?Yield, ?Await] AssignmentOperator : one of *= /= %= += -= <<= >>= >>>= &= ^= |= **=

13.15.1 Static Semantics: Early Errors

AssignmentExpression : LeftHandSideExpression = AssignmentExpression

If LeftHandSideExpression is an ObjectLiteral or an ArrayLiteral, the following Early Error rules are applied:

If LeftHandSideExpression is neither an ObjectLiteral nor an ArrayLiteral, the following Early Error rule is applied:

AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression LeftHandSideExpression &&= AssignmentExpression LeftHandSideExpression ||= AssignmentExpression LeftHandSideExpression ??= AssignmentExpression

13.15.2 Runtime Semantics: Evaluation

AssignmentExpression : LeftHandSideExpression = AssignmentExpression
  1. If LeftHandSideExpression is neither an ObjectLiteral nor an ArrayLiteral, then
    1. Let lref be the result of evaluating LeftHandSideExpression.
    2. ReturnIfAbrupt(lref).
    3. If IsAnonymousFunctionDefinition(AssignmentExpression) and IsIdentifierRef of LeftHandSideExpression are both true, then
      1. Let rval be ? NamedEvaluation of AssignmentExpression with argument lref.[[ReferencedName]].
    4. Else,
      1. Let rref be the result of evaluating AssignmentExpression.
      2. Let rval be ? GetValue(rref).
    5. Perform ? PutValue(lref, rval).
    6. Return rval.
  2. Let assignmentPattern be the AssignmentPattern that is covered by LeftHandSideExpression.
  3. Let rref be the result of evaluating AssignmentExpression.
  4. Let rval be ? GetValue(rref).
  5. Perform ? DestructuringAssignmentEvaluation of assignmentPattern with argument rval.
  6. Return rval.
AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression
  1. Let lref be the result of evaluating LeftHandSideExpression.
  2. Let lval be ? GetValue(lref).
  3. Let rref be the result of evaluating AssignmentExpression.
  4. Let rval be ? GetValue(rref).
  5. Let assignmentOpText be the source text matched by AssignmentOperator.
  6. Let opText be the sequence of Unicode code points associated with assignmentOpText in the following table:
    assignmentOpText opText
    **= **
    *= *
    /= /
    %= %
    += +
    -= -
    <<= <<
    >>= >>
    >>>= >>>
    &= &
    ^= ^
    |= |
  7. Let r be ? ApplyStringOrNumericBinaryOperator(lval, opText, rval).
  8. Perform ? PutValue(lref, r).
  9. Return r.
AssignmentExpression : LeftHandSideExpression &&= AssignmentExpression
  1. Let lref be the result of evaluating LeftHandSideExpression.
  2. Let lval be ? GetValue(lref).
  3. Let lbool be ToBoolean(lval).
  4. If lbool is false, return lval.
  5. If IsAnonymousFunctionDefinition(AssignmentExpression) is true and IsIdentifierRef of LeftHandSideExpression is true, then
    1. Let rval be ? NamedEvaluation of AssignmentExpression with argument lref.[[ReferencedName]].
  6. Else,
    1. Let rref be the result of evaluating AssignmentExpression.
    2. Let rval be ? GetValue(rref).
  7. Perform ? PutValue(lref, rval).
  8. Return rval.
AssignmentExpression : LeftHandSideExpression ||= AssignmentExpression
  1. Let lref be the result of evaluating LeftHandSideExpression.
  2. Let lval be ? GetValue(lref).
  3. Let lbool be ToBoolean(lval).
  4. If lbool is true, return lval.
  5. If IsAnonymousFunctionDefinition(AssignmentExpression) is true and IsIdentifierRef of LeftHandSideExpression is true, then
    1. Let rval be ? NamedEvaluation of AssignmentExpression with argument lref.[[ReferencedName]].
  6. Else,
    1. Let rref be the result of evaluating AssignmentExpression.
    2. Let rval be ? GetValue(rref).
  7. Perform ? PutValue(lref, rval).
  8. Return rval.
AssignmentExpression : LeftHandSideExpression ??= AssignmentExpression
  1. Let lref be the result of evaluating LeftHandSideExpression.
  2. Let lval be ? GetValue(lref).
  3. If lval is neither undefined nor null, return lval.
  4. If IsAnonymousFunctionDefinition(AssignmentExpression) is true and IsIdentifierRef of LeftHandSideExpression is true, then
    1. Let rval be ? NamedEvaluation of AssignmentExpression with argument lref.[[ReferencedName]].
  5. Else,
    1. Let rref be the result of evaluating AssignmentExpression.
    2. Let rval be ? GetValue(rref).
  6. Perform ? PutValue(lref, rval).
  7. Return rval.
Note

When this expression occurs within strict mode code, it is a runtime error if lref in step 1.e, 2, 2, 2, 2 is an unresolvable reference. If it is, a ReferenceError exception is thrown. Additionally, it is a runtime error if the lref in step 8, 7, 7, 6 is a reference to a data property with the attribute value { [[Writable]]: false }, to an accessor property with the attribute value { [[Set]]: undefined }, or to a non-existent property of an object for which the IsExtensible predicate returns the value false. In these cases a TypeError exception is thrown.

13.15.3 ApplyStringOrNumericBinaryOperator ( lval, opText, rval )

The abstract operation ApplyStringOrNumericBinaryOperator takes arguments lval (an ECMAScript language value), opText (**, *, /, %, +, -, <<, >>, >>>, &, ^, or |), and rval (an ECMAScript language value) and returns either a normal completion containing either a String, a BigInt, or a Number, or an abrupt completion. It performs the following steps when called:

  1. If opText is +, then
    1. Let lprim be ? ToPrimitive(lval).
    2. Let rprim be ? ToPrimitive(rval).
    3. If Type(lprim) is String or Type(rprim) is String, then
      1. Let lstr be ? ToString(lprim).
      2. Let rstr be ? ToString(rprim).
      3. Return the string-concatenation of lstr and rstr.
    4. Set lval to lprim.
    5. Set rval to rprim.
  2. NOTE: At this point, it must be a numeric operation.
  3. Let lnum be ? ToNumeric(lval).
  4. Let rnum be ? ToNumeric(rval).
  5. If Type(lnum) is different from Type(rnum), throw a TypeError exception.
  6. If Type(lnum) is BigInt, then
    1. If opText is **, return ? BigInt::exponentiate(lnum, rnum).
    2. If opText is /, return ? BigInt::divide(lnum, rnum).
    3. If opText is %, return ? BigInt::remainder(lnum, rnum).
    4. If opText is >>>, return ? BigInt::unsignedRightShift(lnum, rnum).
  7. Let operation be the abstract operation associated with opText and Type(lnum) in the following table:
    opText Type(lnum) operation
    ** Number Number::exponentiate
    * Number Number::multiply
    * BigInt BigInt::multiply
    / Number Number::divide
    % Number Number::remainder
    + Number Number::add
    + BigInt BigInt::add
    - Number Number::subtract
    - BigInt BigInt::subtract
    << Number Number::leftShift
    << BigInt BigInt::leftShift
    >> Number Number::signedRightShift
    >> BigInt BigInt::signedRightShift
    >>> Number Number::unsignedRightShift
    & Number Number::bitwiseAND
    & BigInt BigInt::bitwiseAND
    ^ Number Number::bitwiseXOR
    ^ BigInt BigInt::bitwiseXOR
    | Number Number::bitwiseOR
    | BigInt BigInt::bitwiseOR
  8. Return operation(lnum, rnum).
Note 1

No hint is provided in the calls to ToPrimitive in steps 1.a and 1.b. All standard objects except Dates handle the absence of a hint as if number were given; Dates handle the absence of a hint as if string were given. Exotic objects may handle the absence of a hint in some other manner.

Note 2

Step 1.c differs from step 3 of the IsLessThan algorithm, by using the logical-or operation instead of the logical-and operation.

13.15.4 EvaluateStringOrNumericBinaryExpression ( leftOperand, opText, rightOperand )

The abstract operation EvaluateStringOrNumericBinaryExpression takes arguments leftOperand (a Parse Node), opText (a sequence of Unicode code points), and rightOperand (a Parse Node) and returns either a normal completion containing either a String, a BigInt, or a Number, or an abrupt completion. It performs the following steps when called:

  1. Let lref be the result of evaluating leftOperand.
  2. Let lval be ? GetValue(lref).
  3. Let rref be the result of evaluating rightOperand.
  4. Let rval be ? GetValue(rref).
  5. Return ? ApplyStringOrNumericBinaryOperator(lval, opText, rval).

13.15.5 Destructuring Assignment

Supplemental Syntax

In certain circumstances when processing an instance of the production
AssignmentExpression : LeftHandSideExpression = AssignmentExpression
the interpretation of LeftHandSideExpression is refined using the following grammar:

AssignmentPattern[Yield, Await] : ObjectAssignmentPattern[?Yield, ?Await] ArrayAssignmentPattern[?Yield, ?Await] ObjectAssignmentPattern[Yield, Await] : { } { AssignmentRestProperty[?Yield, ?Await] } { AssignmentPropertyList[?Yield, ?Await] } { AssignmentPropertyList[?Yield, ?Await] , AssignmentRestProperty[?Yield, ?Await]opt } ArrayAssignmentPattern[Yield, Await] : [ Elisionopt AssignmentRestElement[?Yield, ?Await]opt ] [ AssignmentElementList[?Yield, ?Await] ] [ AssignmentElementList[?Yield, ?Await] , Elisionopt AssignmentRestElement[?Yield, ?Await]opt ] AssignmentRestProperty[Yield, Await] : ... DestructuringAssignmentTarget[?Yield, ?Await] AssignmentPropertyList[Yield, Await] : AssignmentProperty[?Yield, ?Await] AssignmentPropertyList[?Yield, ?Await] , AssignmentProperty[?Yield, ?Await] AssignmentElementList[Yield, Await] : AssignmentElisionElement[?Yield, ?Await] AssignmentElementList[?Yield, ?Await] , AssignmentElisionElement[?Yield, ?Await] AssignmentElisionElement[Yield, Await] : Elisionopt AssignmentElement[?Yield, ?Await] AssignmentProperty[Yield, Await] : IdentifierReference[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt PropertyName[?Yield, ?Await] : AssignmentElement[?Yield, ?Await] AssignmentElement[Yield, Await] : DestructuringAssignmentTarget[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt AssignmentRestElement[Yield, Await] : ... DestructuringAssignmentTarget[?Yield, ?Await] DestructuringAssignmentTarget[Yield, Await] : LeftHandSideExpression[?Yield, ?Await]

13.15.5.1 Static Semantics: Early Errors

AssignmentProperty : IdentifierReference Initializeropt AssignmentRestProperty : ... DestructuringAssignmentTarget DestructuringAssignmentTarget : LeftHandSideExpression

If LeftHandSideExpression is an ObjectLiteral or an ArrayLiteral, the following Early Error rules are applied:

If LeftHandSideExpression is neither an ObjectLiteral nor an ArrayLiteral, the following Early Error rule is applied:

13.15.5.2 Runtime Semantics: DestructuringAssignmentEvaluation

The syntax-directed operation DestructuringAssignmentEvaluation takes argument value and returns either a normal completion containing unused or an abrupt completion. It is defined piecewise over the following productions:

ObjectAssignmentPattern : { }
  1. Perform ? RequireObjectCoercible(value).
  2. Return unused.
ObjectAssignmentPattern : { AssignmentPropertyList } { AssignmentPropertyList , }
  1. Perform ? RequireObjectCoercible(value).
  2. Perform ? PropertyDestructuringAssignmentEvaluation of AssignmentPropertyList with argument value.
  3. Return unused.
ObjectAssignmentPattern : { AssignmentRestProperty }
  1. Perform ? RequireObjectCoercible(value).
  2. Let excludedNames be a new empty List.
  3. Return ? RestDestructuringAssignmentEvaluation of AssignmentRestProperty with arguments value and excludedNames.
ObjectAssignmentPattern : { AssignmentPropertyList , AssignmentRestProperty }
  1. Perform ? RequireObjectCoercible(value).
  2. Let excludedNames be ? PropertyDestructuringAssignmentEvaluation of AssignmentPropertyList with argument value.
  3. Return ? RestDestructuringAssignmentEvaluation of AssignmentRestProperty with arguments value and excludedNames.
ArrayAssignmentPattern : [ ]
  1. Let iteratorRecord be ? GetIterator(value).
  2. Return ? IteratorClose(iteratorRecord, NormalCompletion(unused)).
ArrayAssignmentPattern : [ Elision ]
  1. Let iteratorRecord be ? GetIterator(value).
  2. Let result be Completion(IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord).
  3. If iteratorRecord.[[Done]] is false, return ? IteratorClose(iteratorRecord, result).
  4. Return result.
ArrayAssignmentPattern : [ Elisionopt AssignmentRestElement ]
  1. Let iteratorRecord be ? GetIterator(value).
  2. If Elision is present, then
    1. Let status be Completion(IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord).
    2. If status is an abrupt completion, then
      1. Assert: iteratorRecord.[[Done]] is true.
      2. Return ? status.
  3. Let result be Completion(IteratorDestructuringAssignmentEvaluation of AssignmentRestElement with argument iteratorRecord).
  4. If iteratorRecord.[[Done]] is false, return ? IteratorClose(iteratorRecord, result).
  5. Return result.
ArrayAssignmentPattern : [ AssignmentElementList ]
  1. Let iteratorRecord be ? GetIterator(value).
  2. Let result be Completion(IteratorDestructuringAssignmentEvaluation of AssignmentElementList with argument iteratorRecord).
  3. If iteratorRecord.[[Done]] is false, return ? IteratorClose(iteratorRecord, result).
  4. Return result.
ArrayAssignmentPattern : [ AssignmentElementList , Elisionopt AssignmentRestElementopt ]
  1. Let iteratorRecord be ? GetIterator(value).
  2. Let status be Completion(IteratorDestructuringAssignmentEvaluation of AssignmentElementList with argument iteratorRecord).
  3. If status is an abrupt completion, then
    1. If iteratorRecord.[[Done]] is false, return ? IteratorClose(iteratorRecord, status).
    2. Return ? status.
  4. If Elision is present, then
    1. Set status to Completion(IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord).
    2. If status is an abrupt completion, then
      1. Assert: iteratorRecord.[[Done]] is true.
      2. Return ? status.
  5. If AssignmentRestElement is present, then
    1. Set status to Completion(IteratorDestructuringAssignmentEvaluation of AssignmentRestElement with argument iteratorRecord).
  6. If iteratorRecord.[[Done]] is false, return ? IteratorClose(iteratorRecord, status).
  7. Return ? status.

13.15.5.3 Runtime Semantics: PropertyDestructuringAssignmentEvaluation

The syntax-directed operation PropertyDestructuringAssignmentEvaluation takes argument value and returns either a normal completion containing a List of property keys or an abrupt completion. It collects a list of all destructured property keys. It is defined piecewise over the following productions:

AssignmentPropertyList : AssignmentPropertyList , AssignmentProperty
  1. Let propertyNames be ? PropertyDestructuringAssignmentEvaluation of AssignmentPropertyList with argument value.
  2. Let nextNames be ? PropertyDestructuringAssignmentEvaluation of AssignmentProperty with argument value.
  3. Return the list-concatenation of propertyNames and nextNames.
AssignmentProperty : IdentifierReference Initializeropt
  1. Let P be StringValue of IdentifierReference.
  2. Let lref be ? ResolveBinding(P).
  3. Let v be ? GetV(value, P).
  4. If Initializeropt is present and v is undefined, then
    1. If IsAnonymousFunctionDefinition(Initializer) is true, then
      1. Set v to ? NamedEvaluation of Initializer with argument P.
    2. Else,
      1. Let defaultValue be the result of evaluating Initializer.
      2. Set v to ? GetValue(defaultValue).
  5. Perform ? PutValue(lref, v).
  6. Return « P ».
AssignmentProperty : PropertyName : AssignmentElement
  1. Let name be the result of evaluating PropertyName.
  2. ReturnIfAbrupt(name).
  3. Perform ? KeyedDestructuringAssignmentEvaluation of AssignmentElement with arguments value and name.
  4. Return « name ».

13.15.5.4 Runtime Semantics: RestDestructuringAssignmentEvaluation

The syntax-directed operation RestDestructuringAssignmentEvaluation takes arguments value and excludedNames and returns either a normal completion containing unused or an abrupt completion. It is defined piecewise over the following productions:

AssignmentRestProperty : ... DestructuringAssignmentTarget
  1. Let lref be the result of evaluating DestructuringAssignmentTarget.
  2. ReturnIfAbrupt(lref).
  3. Let restObj be OrdinaryObjectCreate(%Object.prototype%).
  4. Perform ? CopyDataProperties(restObj, value, excludedNames).
  5. Return ? PutValue(lref, restObj).

13.15.5.5 Runtime Semantics: IteratorDestructuringAssignmentEvaluation

The syntax-directed operation IteratorDestructuringAssignmentEvaluation takes argument iteratorRecord and returns either a normal completion containing unused or an abrupt completion. It is defined piecewise over the following productions:

AssignmentElementList : AssignmentElisionElement
  1. Return ? IteratorDestructuringAssignmentEvaluation of AssignmentElisionElement with argument iteratorRecord.
AssignmentElementList : AssignmentElementList , AssignmentElisionElement
  1. Perform ? IteratorDestructuringAssignmentEvaluation of AssignmentElementList with argument iteratorRecord.
  2. Return ? IteratorDestructuringAssignmentEvaluation of AssignmentElisionElement with argument iteratorRecord.
AssignmentElisionElement : AssignmentElement
  1. Return ? IteratorDestructuringAssignmentEvaluation of AssignmentElement with argument iteratorRecord.
AssignmentElisionElement : Elision AssignmentElement
  1. Perform ? IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord.
  2. Return ? IteratorDestructuringAssignmentEvaluation of AssignmentElement with argument iteratorRecord.
Elision : ,
  1. If iteratorRecord.[[Done]] is false, then
    1. Let next be Completion(IteratorStep(iteratorRecord)).
    2. If next is an abrupt completion, set iteratorRecord.[[Done]] to true.
    3. ReturnIfAbrupt(next).
    4. If next is false, set iteratorRecord.[[Done]] to true.
  2. Return unused.
Elision : Elision ,
  1. Perform ? IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord.
  2. If iteratorRecord.[[Done]] is false, then
    1. Let next be Completion(IteratorStep(iteratorRecord)).
    2. If next is an abrupt completion, set iteratorRecord.[[Done]] to true.
    3. ReturnIfAbrupt(next).
    4. If next is false, set iteratorRecord.[[Done]] to true.
  3. Return unused.
AssignmentElement : DestructuringAssignmentTarget Initializeropt
  1. If DestructuringAssignmentTarget is neither an ObjectLiteral nor an ArrayLiteral, then
    1. Let lref be the result of evaluating DestructuringAssignmentTarget.
    2. ReturnIfAbrupt(lref).
  2. If iteratorRecord.[[Done]] is false, then
    1. Let next be Completion(IteratorStep(iteratorRecord)).
    2. If next is an abrupt completion, set iteratorRecord.[[Done]] to true.
    3. ReturnIfAbrupt(next).
    4. If next is false, set iteratorRecord.[[Done]] to true.
    5. Else,
      1. Let value be Completion(IteratorValue(next)).
      2. If value is an abrupt completion, set iteratorRecord.[[Done]] to true.
      3. ReturnIfAbrupt(value).
  3. If iteratorRecord.[[Done]] is true, let value be undefined.
  4. If Initializer is present and value is undefined, then
    1. If IsAnonymousFunctionDefinition(Initializer) is true and IsIdentifierRef of DestructuringAssignmentTarget is true, then
      1. Let v be ? NamedEvaluation of Initializer with argument lref.[[ReferencedName]].
    2. Else,
      1. Let defaultValue be the result of evaluating Initializer.
      2. Let v be ? GetValue(defaultValue).
  5. Else, let v be value.
  6. If DestructuringAssignmentTarget is an ObjectLiteral or an ArrayLiteral, then
    1. Let nestedAssignmentPattern be the AssignmentPattern that is covered by DestructuringAssignmentTarget.
    2. Return ? DestructuringAssignmentEvaluation of nestedAssignmentPattern with argument v.
  7. Return ? PutValue(lref, v).
Note

Left to right evaluation order is maintained by evaluating a DestructuringAssignmentTarget that is not a destructuring pattern prior to accessing the iterator or evaluating the Initializer.

AssignmentRestElement : ... DestructuringAssignmentTarget
  1. If DestructuringAssignmentTarget is neither an ObjectLiteral nor an ArrayLiteral, then
    1. Let lref be the result of evaluating DestructuringAssignmentTarget.
    2. ReturnIfAbrupt(lref).
  2. Let A be ! ArrayCreate(0).
  3. Let n be 0.
  4. Repeat, while iteratorRecord.[[Done]] is false,
    1. Let next be Completion(IteratorStep(iteratorRecord)).
    2. If next is an abrupt completion, set iteratorRecord.[[Done]] to true.
    3. ReturnIfAbrupt(next).
    4. If next is false, set iteratorRecord.[[Done]] to true.
    5. Else,
      1. Let nextValue be Completion(IteratorValue(next)).
      2. If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true.
      3. ReturnIfAbrupt(nextValue).
      4. Perform ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(n)), nextValue).
      5. Set n to n + 1.
  5. If DestructuringAssignmentTarget is neither an ObjectLiteral nor an ArrayLiteral, then
    1. Return ? PutValue(lref, A).
  6. Let nestedAssignmentPattern be the AssignmentPattern that is covered by DestructuringAssignmentTarget.
  7. Return ? DestructuringAssignmentEvaluation of nestedAssignmentPattern with argument A.

13.15.5.6 Runtime Semantics: KeyedDestructuringAssignmentEvaluation

The syntax-directed operation KeyedDestructuringAssignmentEvaluation takes arguments value and propertyName and returns either a normal completion containing unused or an abrupt completion. It is defined piecewise over the following productions:

AssignmentElement : DestructuringAssignmentTarget Initializeropt
  1. If DestructuringAssignmentTarget is neither an ObjectLiteral nor an ArrayLiteral, then
    1. Let lref be the result of evaluating DestructuringAssignmentTarget.
    2. ReturnIfAbrupt(lref).
  2. Let v be ? GetV(value, propertyName).
  3. If Initializer is present and v is undefined, then
    1. If IsAnonymousFunctionDefinition(Initializer) and IsIdentifierRef of DestructuringAssignmentTarget are both true, then
      1. Let rhsValue be ? NamedEvaluation of Initializer with argument lref.[[ReferencedName]].
    2. Else,
      1. Let defaultValue be the result of evaluating Initializer.
      2. Let rhsValue be ? GetValue(defaultValue).
  4. Else, let rhsValue be v.
  5. If DestructuringAssignmentTarget is an ObjectLiteral or an ArrayLiteral, then
    1. Let assignmentPattern be the AssignmentPattern that is covered by DestructuringAssignmentTarget.
    2. Return ? DestructuringAssignmentEvaluation of assignmentPattern with argument rhsValue.
  6. Return ? PutValue(lref, rhsValue).

13.16 Comma Operator ( , )

Syntax

Expression[In, Yield, Await] : AssignmentExpression[?In, ?Yield, ?Await] Expression[?In, ?Yield, ?Await] , AssignmentExpression[?In, ?Yield, ?Await]

13.16.1 Runtime Semantics: Evaluation

Expression : Expression , AssignmentExpression
  1. Let lref be the result of evaluating Expression.
  2. Perform ? GetValue(lref).
  3. Let rref be the result of evaluating AssignmentExpression.
  4. Return ? GetValue(rref).
Note

GetValue must be called even though its value is not used because it may have observable side-effects.