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 code 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. It is defined piecewise over the following productions:

IdentifierName :: IdentifierStart IdentifierName IdentifierPart
  1. Let idText be the source text matched by IdentifierName.
  2. Let idTextUnescaped be the result of replacing any occurrences of \ UnicodeEscapeSequence in idText with the code point represented by the UnicodeEscapeSequence.
  3. 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.

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 and nextIndex. 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 Set throws if len exceeds 232-1.
  4. Return len.
Elision : Elision ,
  1. Return the result of performing ArrayAccumulation for Elision with arguments array and nextIndex + 1.
ElementList : Elisionopt AssignmentExpression
  1. If Elision is present, then
    1. Set nextIndex to the result of performing ArrayAccumulation for Elision with arguments array and nextIndex.
    2. ReturnIfAbrupt(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 the result of performing ArrayAccumulation for Elision with arguments array and nextIndex.
    2. ReturnIfAbrupt(nextIndex).
  2. Return the result of performing ArrayAccumulation for SpreadElement with arguments array and nextIndex.
ElementList : ElementList , Elisionopt AssignmentExpression
  1. Set nextIndex to the result of performing ArrayAccumulation for ElementList with arguments array and nextIndex.
  2. ReturnIfAbrupt(nextIndex).
  3. If Elision is present, then
    1. Set nextIndex to the result of performing ArrayAccumulation for Elision with arguments array and nextIndex.
    2. ReturnIfAbrupt(nextIndex).
  4. Let initResult be the result of evaluating AssignmentExpression.
  5. Let initValue be ? GetValue(initResult).
  6. Let created be ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(nextIndex)), initValue).
  7. Return nextIndex + 1.
ElementList : ElementList , Elisionopt SpreadElement
  1. Set nextIndex to the result of performing ArrayAccumulation for ElementList with arguments array and nextIndex.
  2. ReturnIfAbrupt(nextIndex).
  3. If Elision is present, then
    1. Set nextIndex to the result of performing ArrayAccumulation for Elision with arguments array and nextIndex.
    2. ReturnIfAbrupt(nextIndex).
  4. Return the result of performing ArrayAccumulation for 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. Let len be the result of performing ArrayAccumulation for Elision with arguments array and 0.
    2. ReturnIfAbrupt(len).
  3. Return array.
ArrayLiteral : [ ElementList ]
  1. Let array be ! ArrayCreate(0).
  2. Let len be the result of performing ArrayAccumulation for ElementList with arguments array and 0.
  3. ReturnIfAbrupt(len).
  4. Return array.
ArrayLiteral : [ ElementList , Elisionopt ]
  1. Let array be ! ArrayCreate(0).
  2. Let nextIndex be the result of performing ArrayAccumulation for ElementList with arguments array and 0.
  3. ReturnIfAbrupt(nextIndex).
  4. If Elision is present, then
    1. Let len be the result of performing ArrayAccumulation for Elision with arguments array and nextIndex.
    2. ReturnIfAbrupt(len).
  5. 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
  • Always throw a Syntax Error if code matches 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 } ObjectLiteral : { 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. 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. 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 a List whose sole element is 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. It is defined piecewise over the following productions:

PropertyDefinitionList : PropertyDefinitionList , PropertyDefinition
  1. Perform ? PropertyDefinitionEvaluation of PropertyDefinitionList with argument object.
  2. Return the result of performing PropertyDefinitionEvaluation of PropertyDefinition with argument object.
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. Return ? CopyDataProperties(object, fromValue, excludedNames).
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. Return ! CreateDataPropertyOrThrow(object, propName, propValue).
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. Return ! object.[[SetPrototypeOf]](propValue).
    2. Return NormalCompletion(empty).
  9. Assert: object is an ordinary, extensible object with no non-configurable properties.
  10. Return ! CreateDataPropertyOrThrow(object, propKey, propValue).
PropertyDefinition : MethodDefinition
  1. Return ? MethodDefinitionEvaluation of MethodDefinition with arguments object and true.

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). 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. 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 a List whose sole element is 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 a List whose sole element is 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 a List whose sole element is 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). 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. It is defined piecewise over the following productions:

TemplateSpans : TemplateTail
  1. Return a new empty List.
TemplateSpans : TemplateMiddleList TemplateTail
  1. Return the result of SubstitutionEvaluation of TemplateMiddleList.
TemplateMiddleList : TemplateMiddle Expression
  1. Let subRef be the result of evaluating Expression.
  2. Let sub be ? GetValue(subRef).
  3. Return a List whose sole element is 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 code matches 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 code 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 code 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 code 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 code 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). 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). 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). 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 code matching 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). 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. Let result be Call(func, thisValue, argList).
  8. Assert: If result is not an abrupt completion, then Type(result) is an ECMAScript language type.
  9. Return result.

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 code 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 code 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. 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. 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 }.
  5. NOTE: This returns a Super Reference Record.

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. 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 a List whose sole element is 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 a List whose sole element is 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 the result of performing 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 the result of performing 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 the result of performing 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. 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 code 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 code 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 code 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 code 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 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). 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:

  • It must return a normal completion with a value of a List whose values are all Records with two fields, [[Key]] and [[Value]].
  • Each such Record's [[Key]] field must be a property key, i.e., IsPropertyKey must return true when applied to it.
  • Each such Record's [[Value]] field must be an ECMAScript value.

The default implementation of HostGetImportMetaProperties is to return NormalCompletion(« »).

13.3.12.1.2 HostFinalizeImportMeta ( importMeta, moduleRecord )

The host-defined abstract operation HostFinalizeImportMeta takes arguments importMeta (an Object) and moduleRecord (a Module Record). 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:

The default implementation of HostFinalizeImportMeta is to return NormalCompletion(empty).

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. Let newValue be ! Type(oldValue)::add(oldValue, Type(oldValue)::unit).
  4. Perform ? PutValue(lhs, newValue).
  5. 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. Let newValue be ! Type(oldValue)::subtract(oldValue, Type(oldValue)::unit).
  4. Perform ? PutValue(lhs, newValue).
  5. 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. Let newValue be ! Type(oldValue)::add(oldValue, Type(oldValue)::unit).
  4. Perform ? PutValue(expr, newValue).
  5. 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. Let newValue be ! Type(oldValue)::subtract(oldValue, Type(oldValue)::unit).
  4. Perform ? PutValue(expr, newValue).
  5. 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. Return a String according to Table 42.
Table 42: 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. Return ! T::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. Return ! T::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(privateName, rval) 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). 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 using rval as the argument.
  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 (a sequence of Unicode code points), and rval (an ECMAScript language value). It performs the following steps when called:

  1. Assert: opText is present in the table in step 8.
  2. 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.
  3. NOTE: At this point, it must be a numeric operation.
  4. Let lnum be ? ToNumeric(lval).
  5. Let rnum be ? ToNumeric(rval).
  6. If Type(lnum) is different from Type(rnum), throw a TypeError exception.
  7. Let T be Type(lnum).
  8. Let operation be the abstract operation associated with opText in the following table:
    opText operation
    ** T::exponentiate
    * T::multiply
    / T::divide
    % T::remainder
    + T::add
    - T::subtract
    << T::leftShift
    >> T::signedRightShift
    >>> T::unsignedRightShift
    & T::bitwiseAND
    ^ T::bitwiseXOR
    | T::bitwiseOR
  9. Return ? operation(lnum, rnum).
Note 1

No hint is provided in the calls to ToPrimitive in steps 2.a and 2.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 2.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). 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. It is defined piecewise over the following productions:

ObjectAssignmentPattern : { }
  1. Perform ? RequireObjectCoercible(value).
  2. Return NormalCompletion(empty).
ObjectAssignmentPattern : { AssignmentPropertyList } { AssignmentPropertyList , }
  1. Perform ? RequireObjectCoercible(value).
  2. Perform ? PropertyDestructuringAssignmentEvaluation for AssignmentPropertyList using value as the argument.
  3. Return NormalCompletion(empty).
ArrayAssignmentPattern : [ ]
  1. Let iteratorRecord be ? GetIterator(value).
  2. Return ? IteratorClose(iteratorRecord, NormalCompletion(empty)).
ArrayAssignmentPattern : [ Elision ]
  1. Let iteratorRecord be ? GetIterator(value).
  2. Let result be 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 IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord.
    2. If status is an abrupt completion, then
      1. Assert: iteratorRecord.[[Done]] is true.
      2. Return Completion(status).
  3. Let result be 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 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 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 Completion(status).
  4. If Elision is present, then
    1. Set status to the result of performing IteratorDestructuringAssignmentEvaluation of Elision with iteratorRecord as the argument.
    2. If status is an abrupt completion, then
      1. Assert: iteratorRecord.[[Done]] is true.
      2. Return Completion(status).
  5. If AssignmentRestElement is present, then
    1. Set status to the result of performing IteratorDestructuringAssignmentEvaluation of AssignmentRestElement with iteratorRecord as the argument.
  6. If iteratorRecord.[[Done]] is false, return ? IteratorClose(iteratorRecord, status).
  7. Return Completion(status).
ObjectAssignmentPattern : { AssignmentRestProperty }
  1. Perform ? RequireObjectCoercible(value).
  2. Let excludedNames be a new empty List.
  3. Return the result of performing RestDestructuringAssignmentEvaluation of AssignmentRestProperty with value and excludedNames as the arguments.
ObjectAssignmentPattern : { AssignmentPropertyList , AssignmentRestProperty }
  1. Perform ? RequireObjectCoercible(value).
  2. Let excludedNames be ? PropertyDestructuringAssignmentEvaluation of AssignmentPropertyList with argument value.
  3. Return the result of performing RestDestructuringAssignmentEvaluation of AssignmentRestProperty with arguments value and excludedNames.

13.15.5.3 Runtime Semantics: PropertyDestructuringAssignmentEvaluation

The syntax-directed operation PropertyDestructuringAssignmentEvaluation takes argument value. It collects a list of all destructured property names. 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 the result of performing NamedEvaluation for 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 a List whose sole element is P.
AssignmentProperty : PropertyName : AssignmentElement
  1. Let name be the result of evaluating PropertyName.
  2. ReturnIfAbrupt(name).
  3. Perform ? KeyedDestructuringAssignmentEvaluation of AssignmentElement with value and name as the arguments.
  4. Return a List whose sole element is name.

13.15.5.4 Runtime Semantics: RestDestructuringAssignmentEvaluation

The syntax-directed operation RestDestructuringAssignmentEvaluation takes arguments value and excludedNames. 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. It is defined piecewise over the following productions:

AssignmentElementList : AssignmentElisionElement
  1. Return the result of performing IteratorDestructuringAssignmentEvaluation of AssignmentElisionElement using iteratorRecord as the argument.
AssignmentElementList : AssignmentElementList , AssignmentElisionElement
  1. Perform ? IteratorDestructuringAssignmentEvaluation of AssignmentElementList using iteratorRecord as the argument.
  2. Return the result of performing IteratorDestructuringAssignmentEvaluation of AssignmentElisionElement using iteratorRecord as the argument.
AssignmentElisionElement : AssignmentElement
  1. Return the result of performing IteratorDestructuringAssignmentEvaluation of AssignmentElement with iteratorRecord as the argument.
AssignmentElisionElement : Elision AssignmentElement
  1. Perform ? IteratorDestructuringAssignmentEvaluation of Elision with iteratorRecord as the argument.
  2. Return the result of performing IteratorDestructuringAssignmentEvaluation of AssignmentElement with iteratorRecord as the argument.
Elision : ,
  1. If iteratorRecord.[[Done]] is false, then
    1. Let next be 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 NormalCompletion(empty).
Elision : Elision ,
  1. Perform ? IteratorDestructuringAssignmentEvaluation of Elision with iteratorRecord as the argument.
  2. If iteratorRecord.[[Done]] is false, then
    1. Let next be 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 NormalCompletion(empty).
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 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 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 the result of performing DestructuringAssignmentEvaluation of nestedAssignmentPattern with v as the argument.
  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 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 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 the result of performing DestructuringAssignmentEvaluation of nestedAssignmentPattern with A as the argument.

13.15.5.6 Runtime Semantics: KeyedDestructuringAssignmentEvaluation

The syntax-directed operation KeyedDestructuringAssignmentEvaluation takes arguments value and propertyName. 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 the result of performing DestructuringAssignmentEvaluation of assignmentPattern with rhsValue as the argument.
  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.