# 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

- It is a Syntax Error if IsStrict(this production) is true and the StringValue of Identifier is either "arguments" or "eval".

IdentifierReference : yield BindingIdentifier : yield LabelIdentifier : yield

- It is a Syntax Error if IsStrict(this production) is true.

IdentifierReference : await BindingIdentifier : await LabelIdentifier : await

- It is a Syntax Error if the goal symbol of the syntactic grammar is Module.

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 the StringValue of Identifier is "yield".
- It is a Syntax Error if this production has an [Await] parameter and the StringValue of Identifier is "await".

Identifier : IdentifierName but not ReservedWord

- It is a Syntax Error if IsStrict(this phrase) is true and the StringValue of IdentifierName is one of "implements", "interface", "let", "package", "private", "protected", "public", "static", or "yield".
- It is a Syntax Error if the goal symbol of the syntactic grammar is Module and the StringValue of IdentifierName is "await".
- It is a Syntax Error if the StringValue of IdentifierName is the StringValue of any ReservedWord except for `yield` or `await`.

Note

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

# 13.1.2 Static Semantics: StringValue

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

IdentifierName :: IdentifierStart IdentifierName IdentifierPart

1. Let idTextUnescaped be the IdentifierCodePoints of IdentifierName.
2. Return CodePointsToString(idTextUnescaped).

IdentifierReference : yield BindingIdentifier : yield LabelIdentifier : yield

1. Return "yield".

IdentifierReference : await BindingIdentifier : await LabelIdentifier : await

1. Return "await".

Identifier : IdentifierName but not ReservedWord

1. Return the StringValue of IdentifierName.

PrivateIdentifier :: # IdentifierName

1. Return the string-concatenation of 0x0023 (NUMBER SIGN) and the StringValue of IdentifierName.

ModuleExportName : StringLiteral

1. Return the SV of StringLiteral.

# 13.1.3 Runtime Semantics: Evaluation

IdentifierReference : Identifier

1. Return ? ResolveBinding(StringValue of Identifier).

IdentifierReference : yield

1. Return ? ResolveBinding("yield").

IdentifierReference : await

1. Return ? ResolveBinding("await").

Note 1

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

Note 2

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

# 13.2 Primary Expression

## Syntax

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

## Supplemental Syntax

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

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

# 13.2.1 The `this` Keyword

# 13.2.1.1 Runtime Semantics: Evaluation

PrimaryExpression : this

1. Return ? ResolveThisBinding().

# 13.2.2 Identifier Reference

See 13.1 for IdentifierReference.

# 13.2.3 Literals

## Syntax

Literal : NullLiteral BooleanLiteral NumericLiteral StringLiteral

# 13.2.3.1 Runtime Semantics: Evaluation

Literal : NullLiteral

1. Return null.

Literal : BooleanLiteral

1. If BooleanLiteral is the token `false`, return false.
2. If BooleanLiteral is the token `true`, return true.

Literal : NumericLiteral

1. Return the NumericValue of NumericLiteral as defined in 12.9.3.

Literal : StringLiteral

1. Return the SV of StringLiteral as defined in 12.9.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] : [ Elision opt ] [ ElementList[?Yield, ?Await] ] [ ElementList[?Yield, ?Await] , Elision opt ] ElementList[Yield, Await] : Elision opt AssignmentExpression[+In, ?Yield, ?Await] Elision opt SpreadElement[?Yield, ?Await] ElementList[?Yield, ?Await] , Elision opt AssignmentExpression[+In, ?Yield, ?Await] ElementList[?Yield, ?Await] , Elision opt SpreadElement[?Yield, ?Await] Elision : , Elision , SpreadElement[Yield, Await] : ... AssignmentExpression[+In, ?Yield, ?Await]

# 13.2.4.1 Runtime Semantics: ArrayAccumulation

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

Elision : ,

1. Let len be nextIndex + 1.
2. Perform ? Set(array, "length", 𝔽(len), true).
3. NOTE: The above step throws if len exceeds 232 - 1.
4. Return len.

Elision : Elision ,

1. Return ? ArrayAccumulation of Elision with arguments array and (nextIndex + 1).

ElementList : Elision opt AssignmentExpression

1. If Elision is present, then
   1. Set nextIndex to ? ArrayAccumulation of Elision with arguments array and nextIndex.
2. Let initResult be ? Evaluation of AssignmentExpression.
3. Let initValue be ? GetValue(initResult).
4. Perform ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(nextIndex)), initValue).
5. Return nextIndex + 1.

ElementList : Elision opt SpreadElement

1. If Elision is present, then
   1. Set nextIndex to ? ArrayAccumulation of Elision with arguments array and nextIndex.
2. Return ? ArrayAccumulation of SpreadElement with arguments array and nextIndex.

ElementList : ElementList , Elision opt AssignmentExpression

1. Set nextIndex to ? ArrayAccumulation of ElementList with arguments array and nextIndex.
2. If Elision is present, then
   1. Set nextIndex to ? ArrayAccumulation of Elision with arguments array and nextIndex.
3. Let initResult be ? Evaluation of AssignmentExpression.
4. Let initValue be ? GetValue(initResult).
5. Perform ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(nextIndex)), initValue).
6. Return nextIndex + 1.

ElementList : ElementList , Elision opt SpreadElement

1. Set nextIndex to ? ArrayAccumulation of ElementList with arguments array and nextIndex.
2. If Elision is present, then
   1. Set nextIndex to ? ArrayAccumulation of Elision with arguments array and nextIndex.
3. Return ? ArrayAccumulation of SpreadElement with arguments array and nextIndex.

SpreadElement : ... AssignmentExpression

1. Let spreadRef be ? Evaluation of AssignmentExpression.
2. Let spreadObj be ? GetValue(spreadRef).
3. Let iteratorRecord be ? GetIterator(spreadObj, sync).
4. Repeat,
   1. Let next be ? IteratorStepValue(iteratorRecord).
   2. If next is done, return nextIndex.
   3. Perform ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(nextIndex)), next).
   4. 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 : [ Elision opt ]

1. Let array be ! ArrayCreate(0).
2. If Elision is present, then
   1. Perform ? ArrayAccumulation of Elision with arguments array and 0.
3. Return array.

ArrayLiteral : [ ElementList ]

1. Let array be ! ArrayCreate(0).
2. Perform ? ArrayAccumulation of ElementList with arguments array and 0.
3. Return array.

ArrayLiteral : [ ElementList , Elision opt ]

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

# 13.2.5 Object Initializer

Note 1

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

## Syntax

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

MethodDefinition is defined in 15.4.

Note 3

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

# 13.2.5.1 Static Semantics: Early Errors

PropertyDefinition : MethodDefinition

- It is a Syntax Error if HasDirectSuper of MethodDefinition is true.
- It is a Syntax Error if the PrivateBoundIdentifiers of MethodDefinition is not empty.

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

PropertyDefinition : CoverInitializedName

- It is a Syntax Error if any source text is matched by this production.

Note 1

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

ObjectLiteral : { PropertyDefinitionList } { PropertyDefinitionList , }

- It is a Syntax Error if the PropertyNameList of PropertyDefinitionList contains any duplicate entries for "__proto__" and at least two of those entries were obtained from productions of the form PropertyDefinition : PropertyName : AssignmentExpression . This rule is not applied if this ObjectLiteral is contained within a Script that is being parsed for ParseJSON (see step 3 of ParseJSON).

Note 2

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

# 13.2.5.2 Static Semantics: IsComputedPropertyKey

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

PropertyName : LiteralPropertyName

1. Return false.

PropertyName : ComputedPropertyName

1. Return true.

# 13.2.5.3 Static Semantics: PropertyNameList

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

PropertyDefinitionList : PropertyDefinition

1. Let propName be the PropName of PropertyDefinition.
2. If propName is empty, return a new empty List.
3. Return « propName ».

PropertyDefinitionList : PropertyDefinitionList , PropertyDefinition

1. Let list be the PropertyNameList of PropertyDefinitionList.
2. Let propName be the 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 the 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 ? Evaluation of 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 (an Object) and returns either a normal completion containing unused or an abrupt completion. It is defined piecewise over the following productions:

PropertyDefinitionList : PropertyDefinitionList , PropertyDefinition

1. Perform ? PropertyDefinitionEvaluation of PropertyDefinitionList with argument object.
2. Perform ? PropertyDefinitionEvaluation of PropertyDefinition with argument object.
3. Return unused.

PropertyDefinition : ... AssignmentExpression

1. Let exprValue be ? Evaluation of AssignmentExpression.
2. Let fromValue be ? GetValue(exprValue).
3. Let excludedNames be a new empty List.
4. Perform ? CopyDataProperties(object, fromValue, excludedNames).
5. Return unused.

PropertyDefinition : IdentifierReference

1. Let propName be the StringValue of IdentifierReference.
2. Let exprValue be ? Evaluation of IdentifierReference.
3. Let propValue be ? GetValue(exprValue).
4. Assert: object is an ordinary, extensible object with no non-configurable properties.
5. Perform ! CreateDataPropertyOrThrow(object, propName, propValue).
6. Return unused.

PropertyDefinition : PropertyName : AssignmentExpression

1. Let propKey be ? Evaluation of PropertyName.
2. If this PropertyDefinition is contained within a Script that is being evaluated for ParseJSON (see step 6 of ParseJSON), then
   1. Let isProtoSetter be false.
3. Else if propKey is "__proto__" and IsComputedPropertyKey of PropertyName is false, then
   1. Let isProtoSetter be true.
4. Else,
   1. Let isProtoSetter be false.
5. If IsAnonymousFunctionDefinition(AssignmentExpression) is true and isProtoSetter is false, then
   1. Let propValue be ? NamedEvaluation of AssignmentExpression with argument propKey.
6. Else,
   1. Let exprValueRef be ? Evaluation of AssignmentExpression.
   2. Let propValue be ? GetValue(exprValueRef).
7. If isProtoSetter is true, then
   1. If propValue is an Object or propValue is null, then
      1. Perform ! object.[[SetPrototypeOf]](propValue).
   2. Return unused.
8. Assert: object is an ordinary, extensible object with no non-configurable properties.
9. Perform ! CreateDataPropertyOrThrow(object, propKey, propValue).
10. Return unused.

PropertyDefinition : MethodDefinition

1. Perform ? MethodDefinitionEvaluation of MethodDefinition with arguments object and true.
2. Return unused.

# 13.2.6 Function Defining Expressions

See 15.2 for PrimaryExpression : FunctionExpression .

See 15.5 for PrimaryExpression : GeneratorExpression .

See 15.7 for PrimaryExpression : ClassExpression .

See 15.8 for PrimaryExpression : AsyncFunctionExpression .

See 15.6 for PrimaryExpression : AsyncGeneratorExpression .

# 13.2.7 Regular Expression Literals

## Syntax

See 12.9.5.

# 13.2.7.1 Static Semantics: Early Errors

PrimaryExpression : RegularExpressionLiteral

- It is a Syntax Error if IsValidRegularExpressionLiteral(RegularExpressionLiteral) is false.

# 13.2.7.2 Static Semantics: IsValidRegularExpressionLiteral ( literal )

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

1. Let flags be the FlagText of literal.
2. If flags contains any code points other than `d`, `g`, `i`, `m`, `s`, `u`, `v`, or `y`, or if flags contains any code point more than once, return false.
3. If flags contains `u`, let u be true; else let u be false.
4. If flags contains `v`, let v be true; else let v be false.
5. Let patternText be the BodyText of literal.
6. If u is false and v 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.
7. Let parseResult be ParsePattern(patternText, u, v).
8. If parseResult is a Parse Node, return true.
9. 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

- It is a Syntax Error if the [Tagged] parameter was not set and NoSubstitutionTemplate Contains NotEscapeSequence.

TemplateLiteral[Yield, Await, Tagged] : SubstitutionTemplate[?Yield, ?Await, ?Tagged]

- It is a Syntax Error if the number of elements in the TemplateStrings of TemplateLiteral with argument false is greater than or equal to 232.

SubstitutionTemplate[Yield, Await, Tagged] : TemplateHead Expression[+In, ?Yield, ?Await] TemplateSpans[?Yield, ?Await, ?Tagged]

- It is a Syntax Error if the [Tagged] parameter was not set and TemplateHead Contains NotEscapeSequence.

TemplateSpans[Yield, Await, Tagged] : TemplateTail

- It is a Syntax Error if the [Tagged] parameter was not set and TemplateTail Contains NotEscapeSequence.

TemplateMiddleList[Yield, Await, Tagged] : TemplateMiddle Expression[+In, ?Yield, ?Await] TemplateMiddleList[?Yield, ?Await, ?Tagged] TemplateMiddle Expression[+In, ?Yield, ?Await]

- It is a Syntax Error if the [Tagged] parameter was not set and TemplateMiddle Contains NotEscapeSequence.

# 13.2.8.2 Static Semantics: TemplateStrings

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

TemplateLiteral : NoSubstitutionTemplate

1. Return « TemplateString(NoSubstitutionTemplate, raw) ».

SubstitutionTemplate : TemplateHead Expression TemplateSpans

1. Let head be « TemplateString(TemplateHead, raw) ».
2. Let tail be the TemplateStrings of TemplateSpans with argument raw.
3. Return the list-concatenation of head and tail.

TemplateSpans : TemplateTail

1. Return « TemplateString(TemplateTail, raw) ».

TemplateSpans : TemplateMiddleList TemplateTail

1. Let middle be the TemplateStrings of TemplateMiddleList with argument raw.
2. Let tail be « TemplateString(TemplateTail, raw) ».
3. Return the list-concatenation of middle and tail.

TemplateMiddleList : TemplateMiddle Expression

1. Return « TemplateString(TemplateMiddle, raw) ».

TemplateMiddleList : TemplateMiddleList TemplateMiddle Expression

1. Let front be the TemplateStrings of TemplateMiddleList with argument raw.
2. Let last be « TemplateString(TemplateMiddle, raw) ».
3. Return the list-concatenation of front and last.

# 13.2.8.3 Static Semantics: TemplateString ( templateToken, raw )

The abstract operation TemplateString takes arguments templateToken (a NoSubstitutionTemplate Parse Node, a TemplateHead Parse Node, a TemplateMiddle Parse Node, or a TemplateTail Parse Node) and raw (a Boolean) and returns a String or undefined. It performs the following steps when called:

1. If raw is true, then
   1. Let string be the TRV of templateToken.
2. Else,
   1. Let string be the TV of templateToken.
3. Return string.

Note

This operation returns undefined if raw is false and templateToken contains a NotEscapeSequence. In all other cases, it returns a String.

# 13.2.8.4 GetTemplateObject ( templateLiteral )

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

1. Let realm be the current Realm Record.
2. Let templateRegistry be realm.[[TemplateMap]].
3. For each element e of templateRegistry, do
   1. If e.[[Site]] is the same Parse Node as templateLiteral, then
      1. Return e.[[Array]].
4. Let rawStrings be the TemplateStrings of templateLiteral with argument true.
5. Assert: rawStrings is a List of Strings.
6. Let cookedStrings be the TemplateStrings of templateLiteral with argument false.
7. Let count be the number of elements in the List cookedStrings.
8. Assert: count ≤ 232 - 1.
9. Let template be ! ArrayCreate(count).
10. Let rawObj be ! ArrayCreate(count).
11. Let index be 0.
12. 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.
13. Perform ! SetIntegrityLevel(rawObj, frozen).
14. Perform ! DefinePropertyOrThrow(template, "raw", PropertyDescriptor { [[Value]]: rawObj, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }).
15. Perform ! SetIntegrityLevel(template, frozen).
16. Append the Record { [[Site]]: templateLiteral, [[Array]]: template } to realm.[[TemplateMap]].
17. 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.6). 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.5 Runtime Semantics: SubstitutionEvaluation

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

TemplateSpans : TemplateTail

1. Return a new empty List.

TemplateSpans : TemplateMiddleList TemplateTail

1. Return ? SubstitutionEvaluation of TemplateMiddleList.

TemplateMiddleList : TemplateMiddle Expression

1. Let subRef be ? Evaluation of Expression.
2. Let sub be ? GetValue(subRef).
3. Return « sub ».

TemplateMiddleList : TemplateMiddleList TemplateMiddle Expression

1. Let preceding be ? SubstitutionEvaluation of TemplateMiddleList.
2. Let nextRef be ? Evaluation of Expression.
3. Let next be ? GetValue(nextRef).
4. Return the list-concatenation of preceding and « next ».

# 13.2.8.6 Runtime Semantics: Evaluation

TemplateLiteral : NoSubstitutionTemplate

1. Return the TV of NoSubstitutionTemplate as defined in 12.9.6.

SubstitutionTemplate : TemplateHead Expression TemplateSpans

1. Let head be the TV of TemplateHead as defined in 12.9.6.
2. Let subRef be ? Evaluation of Expression.
3. Let sub be ? GetValue(subRef).
4. Let middle be ? ToString(sub).
5. Let tail be ? Evaluation of TemplateSpans.
6. 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.9.6.

TemplateSpans : TemplateMiddleList TemplateTail

1. Let head be ? Evaluation of TemplateMiddleList.
2. Let tail be the TV of TemplateTail as defined in 12.9.6.
3. Return the string-concatenation of head and tail.

TemplateMiddleList : TemplateMiddle Expression

1. Let head be the TV of TemplateMiddle as defined in 12.9.6.
2. Let subRef be ? Evaluation of 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 ? Evaluation of TemplateMiddleList.
2. Let middle be the TV of TemplateMiddle as defined in 12.9.6.
3. Let subRef be ? Evaluation of Expression.
4. Let sub be ? GetValue(subRef).
5. Let last be ? ToString(sub).
6. 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

- CoverParenthesizedExpressionAndArrowParameterList must cover a ParenthesizedExpression.

# 13.2.9.2 Runtime Semantics: Evaluation

PrimaryExpression : CoverParenthesizedExpressionAndArrowParameterList

1. Let expr be the ParenthesizedExpression that is covered by CoverParenthesizedExpressionAndArrowParameterList.
2. Return ? Evaluation of expr.

ParenthesizedExpression : ( Expression )

1. Return ? Evaluation of Expression. This may be of type Reference.

Note

This algorithm does not apply GetValue to Evaluation of 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] ,opt ) import ( AssignmentExpression[+In, ?Yield, ?Await] , AssignmentExpression[+In, ?Yield, ?Await] ,opt ) Arguments[Yield, Await] : ( ) ( ArgumentList[?Yield, ?Await] ) ( ArgumentList[?Yield, ?Await] , ) ArgumentList[Yield, Await] : AssignmentExpression[+In, ?Yield, ?Await] ... AssignmentExpression[+In, ?Yield, ?Await] ArgumentList[?Yield, ?Await] , AssignmentExpression[+In, ?Yield, ?Await] ArgumentList[?Yield, ?Await] , ... AssignmentExpression[+In, ?Yield, ?Await] OptionalExpression[Yield, Await] : MemberExpression[?Yield, ?Await] OptionalChain[?Yield, ?Await] CallExpression[?Yield, ?Await] OptionalChain[?Yield, ?Await] OptionalExpression[?Yield, ?Await] OptionalChain[?Yield, ?Await] OptionalChain[Yield, Await] : ?. Arguments[?Yield, ?Await] ?. [ Expression[+In, ?Yield, ?Await] ] ?. IdentifierName ?. TemplateLiteral[?Yield, ?Await, +Tagged] ?. PrivateIdentifier OptionalChain[?Yield, ?Await] Arguments[?Yield, ?Await] OptionalChain[?Yield, ?Await] [ Expression[+In, ?Yield, ?Await] ] OptionalChain[?Yield, ?Await] . IdentifierName OptionalChain[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged] OptionalChain[?Yield, ?Await] . PrivateIdentifier LeftHandSideExpression[Yield, Await] : NewExpression[?Yield, ?Await] CallExpression[?Yield, ?Await] OptionalExpression[?Yield, ?Await]

## Supplemental Syntax

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

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

# 13.3.1 Static Semantics

# 13.3.1.1 Static Semantics: Early Errors

OptionalChain : ?. TemplateLiteral OptionalChain TemplateLiteral

- It is a Syntax Error if any source text is matched by this production.

Note

This production exists in order to prevent automatic semicolon insertion rules (12.10) 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

- It is a Syntax Error if the syntactic goal symbol is not Module.

# 13.3.2 Property Accessors

Note

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

MemberExpression `.` IdentifierName
CallExpression `.` IdentifierName

or the bracket notation:

MemberExpression `[` Expression `]`
CallExpression `[` Expression `]`

The dot notation is explained by the following syntactic conversion:

MemberExpression `.` IdentifierName

is identical in its behaviour to

MemberExpression `[` <identifier-name-string> `]`

and similarly

CallExpression `.` IdentifierName

is identical in its behaviour to

CallExpression `[` <identifier-name-string> `]`

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

# 13.3.2.1 Runtime Semantics: Evaluation

MemberExpression : MemberExpression [ Expression ]

1. Let baseReference be ? Evaluation of MemberExpression.
2. Let baseValue be ? GetValue(baseReference).
3. Let strict be IsStrict(this MemberExpression).
4. Return ? EvaluatePropertyAccessWithExpressionKey(baseValue, Expression, strict).

MemberExpression : MemberExpression . IdentifierName

1. Let baseReference be ? Evaluation of MemberExpression.
2. Let baseValue be ? GetValue(baseReference).
3. Let strict be IsStrict(this MemberExpression).
4. Return EvaluatePropertyAccessWithIdentifierKey(baseValue, IdentifierName, strict).

MemberExpression : MemberExpression . PrivateIdentifier

1. Let baseReference be ? Evaluation of 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 ? Evaluation of CallExpression.
2. Let baseValue be ? GetValue(baseReference).
3. Let strict be IsStrict(this CallExpression).
4. Return ? EvaluatePropertyAccessWithExpressionKey(baseValue, Expression, strict).

CallExpression : CallExpression . IdentifierName

1. Let baseReference be ? Evaluation of CallExpression.
2. Let baseValue be ? GetValue(baseReference).
3. Let strict be IsStrict(this CallExpression).
4. Return EvaluatePropertyAccessWithIdentifierKey(baseValue, IdentifierName, strict).

CallExpression : CallExpression . PrivateIdentifier

1. Let baseReference be ? Evaluation of 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 (an Expression Parse Node), and strict (a Boolean) and returns either a normal completion containing a Reference Record or an abrupt completion. It performs the following steps when called:

1. Let propertyNameReference be ? Evaluation of expression.
2. Let propertyNameValue be ? GetValue(propertyNameReference).
3. NOTE: In most cases, ToPropertyKey will be performed on propertyNameValue immediately after this step. However, in the case of `a[b] = c`, it will not be performed until after evaluation of `c`.
4. Return the Reference Record { [[Base]]: baseValue, [[ReferencedName]]: propertyNameValue, [[Strict]]: strict, [[ThisValue]]: empty }.

# 13.3.4 EvaluatePropertyAccessWithIdentifierKey ( baseValue, identifierName, strict )

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

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

# 13.3.5 The `new` Operator

# 13.3.5.1 Runtime Semantics: Evaluation

NewExpression : new NewExpression

1. Return ? EvaluateNew(NewExpression, empty).

MemberExpression : new MemberExpression Arguments

1. Return ? EvaluateNew(MemberExpression, Arguments).

# 13.3.5.1.1 EvaluateNew ( constructExpr, arguments )

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

1. Let ref be ? Evaluation of constructExpr.
2. Let constructor be ? GetValue(ref).
3. If arguments is empty, then
   1. 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 ? Evaluation of 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 IsStrict(this CallExpression) is true, let strictCaller be true; else let strictCaller be false.
      5. Return ? PerformEval(evalArg, 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.v is a direct eval.

CallExpression : CallExpression Arguments

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

# 13.3.6.2 EvaluateCall ( func, ref, arguments, tailPosition )

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

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

# 13.3.7 The `super` Keyword

# 13.3.7.1 Runtime Semantics: Evaluation

SuperProperty : super [ Expression ]

1. Let env be GetThisEnvironment().
2. Let actualThis be ? env.GetThisBinding().
3. Let propertyNameReference be ? Evaluation of Expression.
4. Let propertyNameValue be ? GetValue(propertyNameReference).
5. Let strict be IsStrict(this SuperProperty).
6. NOTE: In most cases, ToPropertyKey will be performed on propertyNameValue immediately after this step. However, in the case of `super[b] = c`, it will not be performed until after evaluation of `c`.
7. Return MakeSuperPropertyReference(actualThis, propertyNameValue, strict).

SuperProperty : super . IdentifierName

1. Let env be GetThisEnvironment().
2. Let actualThis be ? env.GetThisBinding().
3. Let propertyKey be the StringValue of IdentifierName.
4. Let strict be IsStrict(this SuperProperty).
5. Return MakeSuperPropertyReference(actualThis, propertyKey, strict).

SuperCall : super Arguments

1. Let newTarget be GetNewTarget().
2. Assert: newTarget is a constructor.
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. Assert: thisER is a Function Environment Record.
9. Perform ? BindThisValue(thisER, result).
10. Let F be thisER.[[FunctionObject]].
11. Assert: F is an ECMAScript function object.
12. Perform ? InitializeInstanceElements(result, F).
13. Return result.

# 13.3.7.2 GetSuperConstructor ( )

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

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

# 13.3.7.3 MakeSuperPropertyReference ( actualThis, propertyKey, strict )

The abstract operation MakeSuperPropertyReference takes arguments actualThis (an ECMAScript language value), propertyKey (an ECMAScript language value), and strict (a Boolean) and returns a Super Reference Record. It performs the following steps when called:

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

# 13.3.8 Argument Lists

Note

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

# 13.3.8.1 Runtime Semantics: ArgumentListEvaluation

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

Arguments : ( )

1. Return a new empty List.

ArgumentList : AssignmentExpression

1. Let ref be ? Evaluation of AssignmentExpression.
2. Let arg be ? GetValue(ref).
3. Return « arg ».

ArgumentList : ... AssignmentExpression

1. Let list be a new empty List.
2. Let spreadRef be ? Evaluation of AssignmentExpression.
3. Let spreadObj be ? GetValue(spreadRef).
4. Let iteratorRecord be ? GetIterator(spreadObj, sync).
5. Repeat,
   1. Let next be ? IteratorStepValue(iteratorRecord).
   2. If next is done, return list.
   3. Append next to list.

ArgumentList : ArgumentList , AssignmentExpression

1. Let precedingArgs be ? ArgumentListEvaluation of ArgumentList.
2. Let ref be ? Evaluation of 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 ? Evaluation of AssignmentExpression.
3. Let iteratorRecord be ? GetIterator(? GetValue(spreadRef), sync).
4. Repeat,
   1. Let next be ? IteratorStepValue(iteratorRecord).
   2. If next is done, return precedingArgs.
   3. Append next to precedingArgs.

TemplateLiteral : NoSubstitutionTemplate

1. Let templateLiteral be this TemplateLiteral.
2. Let siteObj be GetTemplateObject(templateLiteral).
3. Return « siteObj ».

TemplateLiteral : SubstitutionTemplate

1. Let templateLiteral be this TemplateLiteral.
2. Let siteObj be GetTemplateObject(templateLiteral).
3. Let remaining be ? ArgumentListEvaluation of SubstitutionTemplate.
4. Return the list-concatenation of « siteObj » and remaining.

SubstitutionTemplate : TemplateHead Expression TemplateSpans

1. Let firstSubRef be ? Evaluation of 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 ? Evaluation of MemberExpression.
2. Let baseValue be ? GetValue(baseReference).
3. If baseValue is either undefined or null, then
   1. Return undefined.
4. Return ? ChainEvaluation of OptionalChain with arguments baseValue and baseReference.

OptionalExpression : CallExpression OptionalChain

1. Let baseReference be ? Evaluation of CallExpression.
2. Let baseValue be ? GetValue(baseReference).
3. If baseValue is either undefined or null, then
   1. Return undefined.
4. Return ? ChainEvaluation of OptionalChain with arguments baseValue and baseReference.

OptionalExpression : OptionalExpression OptionalChain

1. Let baseReference be ? Evaluation of OptionalExpression.
2. Let baseValue be ? GetValue(baseReference).
3. If baseValue is either undefined or null, then
   1. Return undefined.
4. Return ? ChainEvaluation of OptionalChain with arguments baseValue and baseReference.

# 13.3.9.2 Runtime Semantics: ChainEvaluation

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

OptionalChain : ?. Arguments

1. Let thisChain be this OptionalChain.
2. Let tailCall be IsInTailPosition(thisChain).
3. Return ? EvaluateCall(baseValue, baseReference, Arguments, tailCall).

OptionalChain : ?. [ Expression ]

1. Let strict be IsStrict(this OptionalChain).
2. Return ? EvaluatePropertyAccessWithExpressionKey(baseValue, Expression, strict).

OptionalChain : ?. IdentifierName

1. Let strict be IsStrict(this OptionalChain).
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. Let strict be IsStrict(this OptionalChain).
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. Let strict be IsStrict(this OptionalChain).
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 ,opt )

1. Return ? EvaluateImportCall(AssignmentExpression).

ImportCall : import ( AssignmentExpression , AssignmentExpression ,opt )

1. Return ? EvaluateImportCall(the first AssignmentExpression, the second AssignmentExpression).

# 13.3.10.2 EvaluateImportCall ( specifierExpression [ , optionsExpression ] )

The abstract operation EvaluateImportCall takes argument specifierExpression (a Parse Node) and optional argument optionsExpression (a Parse Node) and returns either a normal completion containing a Promise or an abrupt completion. It performs the following steps when called:

1. Let referrer be GetActiveScriptOrModule().
2. If referrer is null, set referrer to the current Realm Record.
3. Let specifierRef be ? Evaluation of specifierExpression.
4. Let specifier be ? GetValue(specifierRef).
5. If optionsExpression is present, then
   1. Let optionsRef be ? Evaluation of optionsExpression.
   2. Let options be ? GetValue(optionsRef).
6. Else,
   1. Let options be undefined.
7. Let promiseCapability be ! NewPromiseCapability(%Promise%).
8. Let specifierString be Completion(ToString(specifier)).
9. IfAbruptRejectPromise(specifierString, promiseCapability).
10. Let attributes be a new empty List.
11. If options is not undefined, then
    1. If options is not an Object, then
       1. Perform ! Call(promiseCapability.[[Reject]], undefined, « a newly created TypeError object »).
       2. Return promiseCapability.[[Promise]].
    2. Let attributesObj be Completion(Get(options, "with")).
    3. IfAbruptRejectPromise(attributesObj, promiseCapability).
    4. If attributesObj is not undefined, then
       1. If attributesObj is not an Object, then
          1. Perform ! Call(promiseCapability.[[Reject]], undefined, « a newly created TypeError object »).
          2. Return promiseCapability.[[Promise]].
       2. Let entries be Completion(EnumerableOwnProperties(attributesObj, key+value)).
       3. IfAbruptRejectPromise(entries, promiseCapability).
       4. For each element entry of entries, do
          1. Let key be ! Get(entry, "0").
          2. Let value be ! Get(entry, "1").
          3. If key is a String, then
             1. If value is not a String, then
                1. Perform ! Call(promiseCapability.[[Reject]], undefined, « a newly created TypeError object »).
                2. Return promiseCapability.[[Promise]].
             2. Append the ImportAttribute Record { [[Key]]: key, [[Value]]: value } to attributes.
    5. If AllImportAttributesSupported(attributes) is false, then
       1. Perform ! Call(promiseCapability.[[Reject]], undefined, « a newly created TypeError object »).
       2. Return promiseCapability.[[Promise]].
    6. Sort attributes according to the lexicographic order of their [[Key]] field, treating the value of each such field as a sequence of UTF-16 code unit values. NOTE: This sorting is observable only in that hosts are prohibited from changing behaviour based on the order in which attributes are enumerated.
12. Let moduleRequest be a new ModuleRequest Record { [[Specifier]]: specifierString, [[Attributes]]: attributes }.
13. Perform HostLoadImportedModule(referrer, moduleRequest, empty, promiseCapability).
14. Return promiseCapability.[[Promise]].

# 13.3.10.3 ContinueDynamicImport ( promiseCapability, moduleCompletion )

The abstract operation ContinueDynamicImport takes arguments promiseCapability (a PromiseCapability Record) and moduleCompletion (either a normal completion containing a Module Record or a throw completion) and returns unused. It completes the process of a dynamic import originally started by an `import()` call, resolving or rejecting the promise returned by that call as appropriate. It performs the following steps when called:

1. If moduleCompletion is an abrupt completion, then
   1. Perform ! Call(promiseCapability.[[Reject]], undefined, « moduleCompletion.[[Value]] »).
   2. Return unused.
2. Let module be moduleCompletion.[[Value]].
3. Let loadPromise be module.LoadRequestedModules().
4. Let rejectedClosure be a new Abstract Closure with parameters (reason) that captures promiseCapability and performs the following steps when called:
   1. Perform ! Call(promiseCapability.[[Reject]], undefined, « reason »).
   2. Return NormalCompletion(undefined).
5. Let onRejected be CreateBuiltinFunction(rejectedClosure, 1, "", « »).
6. Let linkAndEvaluateClosure be a new Abstract Closure with no parameters that captures module, promiseCapability, and onRejected and performs the following steps when called:
   1. Let link be Completion(module.Link()).
   2. If link is an abrupt completion, then
      1. Perform ! Call(promiseCapability.[[Reject]], undefined, « link.[[Value]] »).
      2. Return NormalCompletion(undefined).
   3. Let evaluatePromise be module.Evaluate().
   4. Let fulfilledClosure be a new Abstract Closure with no parameters that captures module and promiseCapability and performs the following steps when called:
      1. Let namespace be GetModuleNamespace(module).
      2. Perform ! Call(promiseCapability.[[Resolve]], undefined, « namespace »).
      3. Return NormalCompletion(undefined).
   5. Let onFulfilled be CreateBuiltinFunction(fulfilledClosure, 0, "", « »).
   6. Perform PerformPromiseThen(evaluatePromise, onFulfilled, onRejected).
   7. Return unused.
7. Let linkAndEvaluate be CreateBuiltinFunction(linkAndEvaluateClosure, 0, "", « »).
8. Perform PerformPromiseThen(loadPromise, linkAndEvaluate, onRejected).
9. Return unused.

# 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.4) 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 ? Evaluation of 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 ? Evaluation of 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. Assert: importMeta is an Object.
6. Return importMeta.

# 13.3.12.1.1 HostGetImportMetaProperties ( moduleRecord )

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

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

# 13.3.12.1.2 HostFinalizeImportMeta ( importMeta, moduleRecord )

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

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

The default implementation of HostFinalizeImportMeta is to return unused.

# 13.4 Update Expressions

## Syntax

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

# 13.4.1 Static Semantics: Early Errors

UpdateExpression : LeftHandSideExpression ++ LeftHandSideExpression --

- It is an early Syntax Error if the AssignmentTargetType of LeftHandSideExpression is invalid.

UpdateExpression : ++ UnaryExpression -- UnaryExpression

- It is an early Syntax Error if the AssignmentTargetType of UnaryExpression is invalid.

# 13.4.2 Postfix Increment Operator

# 13.4.2.1 Runtime Semantics: Evaluation

UpdateExpression : LeftHandSideExpression ++

1. Let lhs be ? Evaluation of LeftHandSideExpression.
2. If the AssignmentTargetType of LeftHandSideExpression is web-compat, throw a ReferenceError exception.
3. Let oldValue be ? ToNumeric(? GetValue(lhs)).
4. If oldValue is a Number, then
   1. Let newValue be Number::add(oldValue, 1𝔽).
5. Else,
   1. Assert: oldValue is a BigInt.
   2. Let newValue be BigInt::add(oldValue, 1ℤ).
6. Perform ? PutValue(lhs, newValue).
7. Return oldValue.

# 13.4.3 Postfix Decrement Operator

# 13.4.3.1 Runtime Semantics: Evaluation

UpdateExpression : LeftHandSideExpression --

1. Let lhs be ? Evaluation of LeftHandSideExpression.
2. If the AssignmentTargetType of LeftHandSideExpression is web-compat, throw a ReferenceError exception.
3. Let oldValue be ? ToNumeric(? GetValue(lhs)).
4. If oldValue is a Number, then
   1. Let newValue be Number::subtract(oldValue, 1𝔽).
5. Else,
   1. Assert: oldValue is a BigInt.
   2. Let newValue be BigInt::subtract(oldValue, 1ℤ).
6. Perform ? PutValue(lhs, newValue).
7. Return oldValue.

# 13.4.4 Prefix Increment Operator

# 13.4.4.1 Runtime Semantics: Evaluation

UpdateExpression : ++ UnaryExpression

1. Let expr be ? Evaluation of UnaryExpression.
2. If the AssignmentTargetType of UnaryExpression is web-compat, throw a ReferenceError exception.
3. Let oldValue be ? ToNumeric(? GetValue(expr)).
4. If oldValue is a Number, then
   1. Let newValue be Number::add(oldValue, 1𝔽).
5. Else,
   1. Assert: oldValue is a BigInt.
   2. Let newValue be BigInt::add(oldValue, 1ℤ).
6. Perform ? PutValue(expr, newValue).
7. Return newValue.

# 13.4.5 Prefix Decrement Operator

# 13.4.5.1 Runtime Semantics: Evaluation

UpdateExpression : -- UnaryExpression

1. Let expr be ? Evaluation of UnaryExpression.
2. If the AssignmentTargetType of UnaryExpression is web-compat, throw a ReferenceError exception.
3. Let oldValue be ? ToNumeric(? GetValue(expr)).
4. If oldValue is a Number, then
   1. Let newValue be Number::subtract(oldValue, 1𝔽).
5. Else,
   1. Assert: oldValue is a BigInt.
   2. Let newValue be BigInt::subtract(oldValue, 1ℤ).
6. Perform ? PutValue(expr, newValue).
7. 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

- It is a Syntax Error if IsStrict(the UnaryExpression) is true and the derived UnaryExpression is PrimaryExpression : IdentifierReference , MemberExpression : MemberExpression . PrivateIdentifier , CallExpression : CallExpression . PrivateIdentifier , OptionalChain : ?. PrivateIdentifier , or OptionalChain : OptionalChain . PrivateIdentifier .

- It is a Syntax Error if the derived UnaryExpression is
  PrimaryExpression : CoverParenthesizedExpressionAndArrowParameterList
  and CoverParenthesizedExpressionAndArrowParameterList ultimately derives a phrase that, if used in place of UnaryExpression, would produce a Syntax Error according to these rules. This rule is recursively applied.

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 ? Evaluation of UnaryExpression.
2. If ref is not a Reference Record, return true.
3. If IsUnresolvableReference(ref) is true, then
   1. Assert: ref.[[Strict]] is false.
   2. Return true.
4. 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. If ref.[[ReferencedName]] is not a property key, then
      1. Set ref.[[ReferencedName]] to ? ToPropertyKey(ref.[[ReferencedName]]).
   5. Let deleteStatus be ? baseObj.[[Delete]](ref.[[ReferencedName]]).
   6. If deleteStatus is false and ref.[[Strict]] is true, throw a TypeError exception.
   7. Return deleteStatus.
5. Let base be ref.[[Base]].
6. Assert: base is an Environment Record.
7. 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 4.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 ? Evaluation of 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 ? Evaluation of UnaryExpression.
2. If val is a Reference Record, then
   1. If IsUnresolvableReference(val) is true, return "undefined".
3. Set val to ? GetValue(val).
4. If val is undefined, return "undefined".
5. If val is null, return "object".
6. If val is a String, return "string".
7. If val is a Symbol, return "symbol".
8. If val is a Boolean, return "boolean".
9. If val is a Number, return "number".
10. If val is a BigInt, return "bigint".
11. Assert: val is an Object.
12. Normative Optional
    If the host is a web browser or otherwise supports The [[IsHTMLDDA]] Internal Slot, then
    1. If val has an [[IsHTMLDDA]] internal slot, return "undefined".
13. If val has a [[Call]] internal method, return "function".
14. Return "object".

# 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 ? Evaluation of UnaryExpression.
2. Return ? ToNumber(? GetValue(expr)).

# 13.5.5 Unary `-` Operator

Note

The unary `-` operator converts its operand to a numeric value 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 ? Evaluation of UnaryExpression.
2. Let oldValue be ? ToNumeric(? GetValue(expr)).
3. If oldValue is a Number, return Number::unaryMinus(oldValue).
4. Assert: oldValue is a BigInt.
5. Return BigInt::unaryMinus(oldValue).

# 13.5.6 Bitwise NOT Operator ( `~` )

# 13.5.6.1 Runtime Semantics: Evaluation

UnaryExpression : ~ UnaryExpression

1. Let expr be ? Evaluation of UnaryExpression.
2. Let oldValue be ? ToNumeric(? GetValue(expr)).
3. If oldValue is a Number, return Number::bitwiseNOT(oldValue).
4. Assert: oldValue is a BigInt.
5. Return BigInt::bitwiseNOT(oldValue).

# 13.5.7 Logical NOT Operator ( `!` )

# 13.5.7.1 Runtime Semantics: Evaluation

UnaryExpression : ! UnaryExpression

1. Let expr be ? Evaluation of 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 ? Evaluation of RelationalExpression.
2. Let lVal be ? GetValue(lRef).
3. Let rRef be ? Evaluation of ShiftExpression.
4. Let rVal be ? GetValue(rRef).
5. Let r be ? IsLessThan(lVal, rVal, true).
6. If r is undefined, return false.
7. Return r.

RelationalExpression : RelationalExpression > ShiftExpression

1. Let lRef be ? Evaluation of RelationalExpression.
2. Let lVal be ? GetValue(lRef).
3. Let rRef be ? Evaluation of ShiftExpression.
4. Let rVal be ? GetValue(rRef).
5. Let r be ? IsLessThan(rVal, lVal, false).
6. If r is undefined, return false.
7. Return r.

RelationalExpression : RelationalExpression <= ShiftExpression

1. Let lRef be ? Evaluation of RelationalExpression.
2. Let lVal be ? GetValue(lRef).
3. Let rRef be ? Evaluation of ShiftExpression.
4. Let rVal be ? GetValue(rRef).
5. Let r be ? IsLessThan(rVal, lVal, false).
6. If r is either true or undefined, return false.
7. Return true.

RelationalExpression : RelationalExpression >= ShiftExpression

1. Let lRef be ? Evaluation of RelationalExpression.
2. Let lVal be ? GetValue(lRef).
3. Let rRef be ? Evaluation of ShiftExpression.
4. Let rVal be ? GetValue(rRef).
5. Let r be ? IsLessThan(lVal, rVal, true).
6. If r is either true or undefined, return false.
7. Return true.

RelationalExpression : RelationalExpression instanceof ShiftExpression

1. Let lRef be ? Evaluation of RelationalExpression.
2. Let lVal be ? GetValue(lRef).
3. Let rRef be ? Evaluation of ShiftExpression.
4. Let rVal be ? GetValue(rRef).
5. Return ? InstanceofOperator(lVal, rVal).

RelationalExpression : RelationalExpression in ShiftExpression

1. Let lRef be ? Evaluation of RelationalExpression.
2. Let lVal be ? GetValue(lRef).
3. Let rRef be ? Evaluation of ShiftExpression.
4. Let rVal be ? GetValue(rRef).
5. If rVal is not an 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 ? Evaluation of ShiftExpression.
3. Let rVal be ? GetValue(rRef).
4. If rVal is not an Object, throw a TypeError exception.
5. Let privateEnv be the running execution context's PrivateEnvironment.
6. Assert: privateEnv is not null.
7. Let privateName be ResolvePrivateIdentifier(privateEnv, privateIdentifier).
8. If PrivateElementFind(rVal, privateName) is empty, return false.
9. Return true.

# 13.10.2 InstanceofOperator ( V, target )

The abstract operation InstanceofOperator takes arguments V (an ECMAScript language value) and target (an ECMAScript language value) and returns either a normal completion containing a Boolean or a throw completion. It implements the generic algorithm for determining if V is an instance of target either by consulting target's %Symbol.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 target is not an Object, throw a TypeError exception.
2. Let instOfHandler be ? GetMethod(target, %Symbol.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 %Symbol.hasInstance% method to define the `instanceof` operator semantics. If an object does not define or inherit %Symbol.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 ? Evaluation of EqualityExpression.
2. Let lVal be ? GetValue(lRef).
3. Let rRef be ? Evaluation of RelationalExpression.
4. Let rVal be ? GetValue(rRef).
5. Return ? IsLooselyEqual(rVal, lVal).

EqualityExpression : EqualityExpression != RelationalExpression

1. Let lRef be ? Evaluation of EqualityExpression.
2. Let lVal be ? GetValue(lRef).
3. Let rRef be ? Evaluation of RelationalExpression.
4. Let rVal be ? GetValue(rRef).
5. Let r be ? IsLooselyEqual(rVal, lVal).
6. If r is true, return false.
7. Return true.

EqualityExpression : EqualityExpression === RelationalExpression

1. Let lRef be ? Evaluation of EqualityExpression.
2. Let lVal be ? GetValue(lRef).
3. Let rRef be ? Evaluation of RelationalExpression.
4. Let rVal be ? GetValue(rRef).
5. Return IsStrictlyEqual(rVal, lVal).

EqualityExpression : EqualityExpression !== RelationalExpression

1. Let lRef be ? Evaluation of EqualityExpression.
2. Let lVal be ? GetValue(lRef).
3. Let rRef be ? Evaluation of RelationalExpression.
4. Let rVal be ? GetValue(rRef).
5. Let r be IsStrictlyEqual(rVal, lVal).
6. If r is true, return false.
7. Return true.

Note 1

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 2

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 3

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 ? Evaluation of LogicalANDExpression.
2. Let lVal be ? GetValue(lRef).
3. If ToBoolean(lVal) is false, return lVal.
4. Let rRef be ? Evaluation of BitwiseORExpression.
5. Return ? GetValue(rRef).

LogicalORExpression : LogicalORExpression || LogicalANDExpression

1. Let lRef be ? Evaluation of LogicalORExpression.
2. Let lVal be ? GetValue(lRef).
3. If ToBoolean(lVal) is true, return lVal.
4. Let rRef be ? Evaluation of LogicalANDExpression.
5. Return ? GetValue(rRef).

CoalesceExpression : CoalesceExpressionHead ?? BitwiseORExpression

1. Let lRef be ? Evaluation of CoalesceExpressionHead.
2. Let lVal be ? GetValue(lRef).
3. If lVal is neither undefined nor null, return lVal.
4. Let rRef be ? Evaluation of BitwiseORExpression.
5. Return ? GetValue(rRef).

# 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 ? Evaluation of ShortCircuitExpression.
2. Let lVal be ToBoolean(? GetValue(lRef)).
3. If lVal is true, then
   1. Let trueRef be ? Evaluation of the first AssignmentExpression.
   2. Return ? GetValue(trueRef).
4. Let falseRef be ? Evaluation of the second AssignmentExpression.
5. 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 either an ObjectLiteral or an ArrayLiteral, LeftHandSideExpression must cover an AssignmentPattern.
- If LeftHandSideExpression is neither an ObjectLiteral nor an ArrayLiteral, it is a Syntax Error if the AssignmentTargetType of LeftHandSideExpression is invalid.

AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression

- It is a Syntax Error if the AssignmentTargetType of LeftHandSideExpression is invalid.

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

- It is a Syntax Error if the AssignmentTargetType of LeftHandSideExpression is not simple.

# 13.15.2 Runtime Semantics: Evaluation

AssignmentExpression : LeftHandSideExpression = AssignmentExpression

1. If LeftHandSideExpression is neither an ObjectLiteral nor an ArrayLiteral, then
   1. Let lRef be ? Evaluation of LeftHandSideExpression.
   2. If the AssignmentTargetType of LeftHandSideExpression is web-compat, throw a ReferenceError exception.
   3. If IsAnonymousFunctionDefinition(AssignmentExpression) is true and IsIdentifierRef of LeftHandSideExpression is true, then
      1. Let lhs be the StringValue of LeftHandSideExpression.
      2. Let rVal be ? NamedEvaluation of AssignmentExpression with argument lhs.
   4. Else,
      1. Let rRef be ? Evaluation of 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 ? Evaluation of AssignmentExpression.
4. Let rVal be ? GetValue(rRef).
5. Perform ? DestructuringAssignmentEvaluation of assignmentPattern with argument rVal.
6. Return rVal.

AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression

1. Let lRef be ? Evaluation of LeftHandSideExpression.
2. If the AssignmentTargetType of LeftHandSideExpression is web-compat, throw a ReferenceError exception.
3. Let lVal be ? GetValue(lRef).
4. Let rRef be ? Evaluation of AssignmentExpression.
5. Let rVal be ? GetValue(rRef).
6. Let assignmentOpText be the source text matched by AssignmentOperator.
7. Let opText be the sequence of Unicode code points associated with assignmentOpText in the following table:

   assignmentOpText | opText
   --- | ---
   `**=` | `**`
   `*=` | `*`
   `/=` | `/`
   `%=` | `%`
   `+=` | `+`
   `-=` | `-`
   `<<=` | `<<`
   `>>=` | `>>`
   `>>>=` | `>>>`
   `&=` | `&`
   `^=` | `^`
   `|=` | `|`

8. Let r be ? ApplyStringOrNumericBinaryOperator(lVal, opText, rVal).
9. Perform ? PutValue(lRef, r).
10. Return r.

AssignmentExpression : LeftHandSideExpression &&= AssignmentExpression

1. Let lRef be ? Evaluation of LeftHandSideExpression.
2. Let lVal be ? GetValue(lRef).
3. If ToBoolean(lVal) is false, return lVal.
4. If IsAnonymousFunctionDefinition(AssignmentExpression) is true and IsIdentifierRef of LeftHandSideExpression is true, then
   1. Let lhs be the StringValue of LeftHandSideExpression.
   2. Let rVal be ? NamedEvaluation of AssignmentExpression with argument lhs.
5. Else,
   1. Let rRef be ? Evaluation of AssignmentExpression.
   2. Let rVal be ? GetValue(rRef).
6. Perform ? PutValue(lRef, rVal).
7. Return rVal.

AssignmentExpression : LeftHandSideExpression ||= AssignmentExpression

1. Let lRef be ? Evaluation of LeftHandSideExpression.
2. Let lVal be ? GetValue(lRef).
3. If ToBoolean(lVal) is true, return lVal.
4. If IsAnonymousFunctionDefinition(AssignmentExpression) is true and IsIdentifierRef of LeftHandSideExpression is true, then
   1. Let lhs be the StringValue of LeftHandSideExpression.
   2. Let rVal be ? NamedEvaluation of AssignmentExpression with argument lhs.
5. Else,
   1. Let rRef be ? Evaluation of AssignmentExpression.
   2. Let rVal be ? GetValue(rRef).
6. Perform ? PutValue(lRef, rVal).
7. Return rVal.

AssignmentExpression : LeftHandSideExpression ??= AssignmentExpression

1. Let lRef be ? Evaluation of 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 lhs be the StringValue of LeftHandSideExpression.
   2. Let rVal be ? NamedEvaluation of AssignmentExpression with argument lhs.
5. Else,
   1. Let rRef be ? Evaluation of 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, 3, 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 9, 6, 6, 6 is a reference to a data property with the attribute value { [[Writable]]: false }, to an accessor property with the attribute value { [[Set]]: undefined }, or to a non-existent property of an object for which the IsExtensible predicate returns the value false. In these cases a TypeError exception is thrown.

# 13.15.3 ApplyStringOrNumericBinaryOperator ( lVal, opText, rVal )

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

1. If opText is `+`, then
   1. Let lPrim be ? ToPrimitive(lVal).
   2. Let rPrim be ? ToPrimitive(rVal).
   3. If lPrim is a String or rPrim is a String, then
      1. Let lStr be ? ToString(lPrim).
      2. Let rStr be ? ToString(rPrim).
      3. Return the string-concatenation of lStr and rStr.
   4. Set lVal to lPrim.
   5. Set rVal to rPrim.
2. NOTE: At this point, it must be a numeric operation.
3. Let lNum be ? ToNumeric(lVal).
4. Let rNum be ? ToNumeric(rVal).
5. If SameType(lNum, rNum) is false, throw a TypeError exception.
6. If lNum is a BigInt, then
   1. If opText is `**`, return ? BigInt::exponentiate(lNum, rNum).
   2. If opText is `/`, return ? BigInt::divide(lNum, rNum).
   3. If opText is `%`, return ? BigInt::remainder(lNum, rNum).
   4. If opText is `>>>`, return ? BigInt::unsignedRightShift(lNum, rNum).
   5. Let operation be the abstract operation associated with opText in the following table:

      opText | operation
      --- | ---
      `*` | BigInt::multiply
      `+` | BigInt::add
      `-` | BigInt::subtract
      `<<` | BigInt::leftShift
      `>>` | BigInt::signedRightShift
      `&` | BigInt::bitwiseAND
      `^` | BigInt::bitwiseXOR
      `|` | BigInt::bitwiseOR

7. Else,
   1. Assert: lNum is a Number.
   2. Let operation be the abstract operation associated with opText in the following table:

      opText | operation
      --- | ---
      `**` | Number::exponentiate
      `*` | Number::multiply
      `/` | Number::divide
      `%` | Number::remainder
      `+` | Number::add
      `-` | Number::subtract
      `<<` | Number::leftShift
      `>>` | Number::signedRightShift
      `>>>` | Number::unsignedRightShift
      `&` | Number::bitwiseAND
      `^` | Number::bitwiseXOR
      `|` | Number::bitwiseOR

8. Return operation(lNum, rNum).

Note 1

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

Note 2

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

# 13.15.4 EvaluateStringOrNumericBinaryExpression ( leftOperand, opText, rightOperand )

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

1. Let lRef be ? Evaluation of leftOperand.
2. Let lVal be ? GetValue(lRef).
3. Let rRef be ? Evaluation of 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] : [ Elision opt AssignmentRestElement[?Yield, ?Await]opt ] [ AssignmentElementList[?Yield, ?Await] ] [ AssignmentElementList[?Yield, ?Await] , Elision opt 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] : Elision opt 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 Initializer opt

- It is a Syntax Error if the AssignmentTargetType of IdentifierReference is not simple.

AssignmentRestProperty : ... DestructuringAssignmentTarget

- It is a Syntax Error if DestructuringAssignmentTarget is either an ArrayLiteral or an ObjectLiteral.

DestructuringAssignmentTarget : LeftHandSideExpression

- If LeftHandSideExpression is either an ObjectLiteral or an ArrayLiteral, LeftHandSideExpression must cover an AssignmentPattern.
- If LeftHandSideExpression is neither an ObjectLiteral nor an ArrayLiteral, it is a Syntax Error if the AssignmentTargetType of LeftHandSideExpression is not simple.

# 13.15.5.2 Runtime Semantics: DestructuringAssignmentEvaluation

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

ObjectAssignmentPattern : { }

1. Perform ? RequireObjectCoercible(value).
2. Return unused.

ObjectAssignmentPattern : { AssignmentPropertyList } { AssignmentPropertyList , }

1. Perform ? RequireObjectCoercible(value).
2. Perform ? PropertyDestructuringAssignmentEvaluation of AssignmentPropertyList with argument value.
3. Return unused.

ObjectAssignmentPattern : { AssignmentRestProperty }

1. Perform ? RequireObjectCoercible(value).
2. Let excludedNames be a new empty List.
3. Return ? RestDestructuringAssignmentEvaluation of AssignmentRestProperty with arguments value and excludedNames.

ObjectAssignmentPattern : { AssignmentPropertyList , AssignmentRestProperty }

1. Perform ? RequireObjectCoercible(value).
2. Let excludedNames be ? PropertyDestructuringAssignmentEvaluation of AssignmentPropertyList with argument value.
3. Return ? RestDestructuringAssignmentEvaluation of AssignmentRestProperty with arguments value and excludedNames.

ArrayAssignmentPattern : [ ]

1. Let iteratorRecord be ? GetIterator(value, sync).
2. Return ? IteratorClose(iteratorRecord, NormalCompletion(unused)).

ArrayAssignmentPattern : [ Elision ]

1. Let iteratorRecord be ? GetIterator(value, sync).
2. Let result be Completion(IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord).
3. If iteratorRecord.[[Done]] is false, return ? IteratorClose(iteratorRecord, result).
4. Return result.

ArrayAssignmentPattern : [ Elision opt AssignmentRestElement ]

1. Let iteratorRecord be ? GetIterator(value, sync).
2. If Elision is present, then
   1. Let status be Completion(IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord).
   2. If status is an abrupt completion, then
      1. Assert: iteratorRecord.[[Done]] is true.
      2. Return ? status.
3. Let result be Completion(IteratorDestructuringAssignmentEvaluation of AssignmentRestElement with argument iteratorRecord).
4. If iteratorRecord.[[Done]] is false, return ? IteratorClose(iteratorRecord, result).
5. Return result.

ArrayAssignmentPattern : [ AssignmentElementList ]

1. Let iteratorRecord be ? GetIterator(value, sync).
2. Let result be Completion(IteratorDestructuringAssignmentEvaluation of AssignmentElementList with argument iteratorRecord).
3. If iteratorRecord.[[Done]] is false, return ? IteratorClose(iteratorRecord, result).
4. Return result.

ArrayAssignmentPattern : [ AssignmentElementList , Elision opt AssignmentRestElement opt ]

1. Let iteratorRecord be ? GetIterator(value, sync).
2. Let status be Completion(IteratorDestructuringAssignmentEvaluation of AssignmentElementList with argument iteratorRecord).
3. If status is an abrupt completion, then
   1. If iteratorRecord.[[Done]] is false, return ? IteratorClose(iteratorRecord, status).
   2. Return ? status.
4. If Elision is present, then
   1. Set status to Completion(IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord).
   2. If status is an abrupt completion, then
      1. Assert: iteratorRecord.[[Done]] is true.
      2. Return ? status.
5. If AssignmentRestElement is present, then
   1. Set status to Completion(IteratorDestructuringAssignmentEvaluation of AssignmentRestElement with argument iteratorRecord).
6. If iteratorRecord.[[Done]] is false, return ? IteratorClose(iteratorRecord, status).
7. Return ? status.

# 13.15.5.3 Runtime Semantics: PropertyDestructuringAssignmentEvaluation

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

AssignmentPropertyList : AssignmentPropertyList , AssignmentProperty

1. Let propertyNames be ? PropertyDestructuringAssignmentEvaluation of AssignmentPropertyList with argument value.
2. Let nextNames be ? PropertyDestructuringAssignmentEvaluation of AssignmentProperty with argument value.
3. Return the list-concatenation of propertyNames and nextNames.

AssignmentProperty : IdentifierReference Initializer opt

1. Let P be the StringValue of IdentifierReference.
2. Let lRef be ? ResolveBinding(P).
3. Let v be ? GetV(value, P).
4. If Initializer is present and v is undefined, then
   1. If IsAnonymousFunctionDefinition(Initializer) is true, then
      1. Set v to ? NamedEvaluation of Initializer with argument P.
   2. Else,
      1. Let defaultValue be ? Evaluation of Initializer.
      2. Set v to ? GetValue(defaultValue).
5. Perform ? PutValue(lRef, v).
6. Return « P ».

AssignmentProperty : PropertyName : AssignmentElement

1. Let name be ? Evaluation of PropertyName.
2. Perform ? KeyedDestructuringAssignmentEvaluation of AssignmentElement with arguments value and name.
3. Return « name ».

# 13.15.5.4 Runtime Semantics: RestDestructuringAssignmentEvaluation

The syntax-directed operation RestDestructuringAssignmentEvaluation takes arguments value (an ECMAScript language value) and excludedNames (a List of property keys) and returns either a normal completion containing unused or an abrupt completion. It is defined piecewise over the following productions:

AssignmentRestProperty : ... DestructuringAssignmentTarget

1. Let lRef be ? Evaluation of DestructuringAssignmentTarget.
2. Let restObj be OrdinaryObjectCreate(%Object.prototype%).
3. Perform ? CopyDataProperties(restObj, value, excludedNames).
4. Return ? PutValue(lRef, restObj).

# 13.15.5.5 Runtime Semantics: IteratorDestructuringAssignmentEvaluation

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

AssignmentElementList : AssignmentElisionElement

1. Return ? IteratorDestructuringAssignmentEvaluation of AssignmentElisionElement with argument iteratorRecord.

AssignmentElementList : AssignmentElementList , AssignmentElisionElement

1. Perform ? IteratorDestructuringAssignmentEvaluation of AssignmentElementList with argument iteratorRecord.
2. Return ? IteratorDestructuringAssignmentEvaluation of AssignmentElisionElement with argument iteratorRecord.

AssignmentElisionElement : AssignmentElement

1. Return ? IteratorDestructuringAssignmentEvaluation of AssignmentElement with argument iteratorRecord.

AssignmentElisionElement : Elision AssignmentElement

1. Perform ? IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord.
2. Return ? IteratorDestructuringAssignmentEvaluation of AssignmentElement with argument iteratorRecord.

Elision : ,

1. If iteratorRecord.[[Done]] is false, then
   1. Perform ? IteratorStep(iteratorRecord).
2. Return unused.

Elision : Elision ,

1. Perform ? IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord.
2. If iteratorRecord.[[Done]] is false, then
   1. Perform ? IteratorStep(iteratorRecord).
3. Return unused.

AssignmentElement : DestructuringAssignmentTarget Initializer opt

1. If DestructuringAssignmentTarget is neither an ObjectLiteral nor an ArrayLiteral, then
   1. Let lRef be ? Evaluation of DestructuringAssignmentTarget.
2. Let value be undefined.
3. If iteratorRecord.[[Done]] is false, then
   1. Let next be ? IteratorStepValue(iteratorRecord).
   2. If next is not done, then
      1. Set value to next.
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 target be the StringValue of DestructuringAssignmentTarget.
      2. Let v be ? NamedEvaluation of Initializer with argument target.
   2. Else,
      1. Let defaultValue be ? Evaluation of Initializer.
      2. Let v be ? GetValue(defaultValue).
5. Else,
   1. Let v be value.
6. If DestructuringAssignmentTarget is either an ObjectLiteral or an ArrayLiteral, then
   1. Let nestedAssignmentPattern be the AssignmentPattern that is covered by DestructuringAssignmentTarget.
   2. Return ? DestructuringAssignmentEvaluation of nestedAssignmentPattern with argument v.
7. Return ? PutValue(lRef, v).

Note

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

AssignmentRestElement : ... DestructuringAssignmentTarget

1. If DestructuringAssignmentTarget is neither an ObjectLiteral nor an ArrayLiteral, then
   1. Let lRef be ? Evaluation of DestructuringAssignmentTarget.
2. Let A be ! ArrayCreate(0).
3. Let n be 0.
4. Repeat, while iteratorRecord.[[Done]] is false,
   1. Let next be ? IteratorStepValue(iteratorRecord).
   2. If next is not done, then
      1. Perform ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(n)), next).
      2. Set n to n + 1.
5. If DestructuringAssignmentTarget is neither an ObjectLiteral nor an ArrayLiteral, then
   1. Return ? PutValue(lRef, A).
6. Let nestedAssignmentPattern be the AssignmentPattern that is covered by DestructuringAssignmentTarget.
7. Return ? DestructuringAssignmentEvaluation of nestedAssignmentPattern with argument A.

# 13.15.5.6 Runtime Semantics: KeyedDestructuringAssignmentEvaluation

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

AssignmentElement : DestructuringAssignmentTarget Initializer opt

1. If DestructuringAssignmentTarget is neither an ObjectLiteral nor an ArrayLiteral, then
   1. Let lRef be ? Evaluation of DestructuringAssignmentTarget.
2. Let v be ? GetV(value, propertyName).
3. If Initializer is present and v is undefined, then
   1. If IsAnonymousFunctionDefinition(Initializer) is true and IsIdentifierRef of DestructuringAssignmentTarget is true, then
      1. Let target be the StringValue of DestructuringAssignmentTarget.
      2. Let rhsValue be ? NamedEvaluation of Initializer with argument target.
   2. Else,
      1. Let defaultValue be ? Evaluation of Initializer.
      2. Let rhsValue be ? GetValue(defaultValue).
4. Else,
   1. Let rhsValue be v.
5. If DestructuringAssignmentTarget is either an ObjectLiteral or an ArrayLiteral, then
   1. Let assignmentPattern be the AssignmentPattern that is covered by DestructuringAssignmentTarget.
   2. Return ? DestructuringAssignmentEvaluation of assignmentPattern with argument rhsValue.
6. Return ? PutValue(lRef, rhsValue).

# 13.16 Comma Operator ( `,` )

## Syntax

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

# 13.16.1 Runtime Semantics: Evaluation

Expression : Expression , AssignmentExpression

1. Let lRef be ? Evaluation of Expression.
2. Perform ? GetValue(lRef).
3. Let rRef be ? Evaluation of AssignmentExpression.
4. Return ? GetValue(rRef).

Note

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