ECMAScript® 2024 Language Specification

Draft ECMA-262 / February 15, 2024

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] : [ Elisionopt ] [ ElementList[?Yield, ?Await] ] [ ElementList[?Yield, ?Await] , Elisionopt ] ElementList[Yield, Await] : Elisionopt AssignmentExpression[+In, ?Yield, ?Await] Elisionopt SpreadElement[?Yield, ?Await] ElementList[?Yield, ?Await] , Elisionopt AssignmentExpression[+In, ?Yield, ?Await] ElementList[?Yield, ?Await] , Elisionopt SpreadElement[?Yield, ?Await] Elision : , Elision , SpreadElement[Yield, Await] : ... AssignmentExpression[+In, ?Yield, ?Await]

13.2.4.1 Runtime Semantics: ArrayAccumulation

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

Elision : ,
  1. Let len be nextIndex + 1.
  2. Perform ? Set(array, "length", 𝔽(len), true).
  3. NOTE: The above step throws if len exceeds 232 - 1.
  4. Return len.
Elision : Elision ,
  1. Return ? ArrayAccumulation of Elision with arguments array and (nextIndex + 1).
ElementList : Elisionopt AssignmentExpression
  1. If Elision is present, then
    1. Set nextIndex to ? ArrayAccumulation of Elision with arguments array and nextIndex.
  2. Let initResult be ? Evaluation of AssignmentExpression.
  3. Let initValue be ? GetValue(initResult).
  4. Perform ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(nextIndex)), initValue).
  5. Return nextIndex + 1.
ElementList : Elisionopt SpreadElement
  1. If Elision is present, then
    1. Set nextIndex to ? ArrayAccumulation of Elision with arguments array and nextIndex.
  2. Return ? ArrayAccumulation of SpreadElement with arguments array and nextIndex.
ElementList : ElementList , Elisionopt AssignmentExpression
  1. Set nextIndex to ? ArrayAccumulation of ElementList with arguments array and nextIndex.
  2. If Elision is present, then
    1. Set nextIndex to ? ArrayAccumulation of Elision with arguments array and nextIndex.
  3. Let initResult be ? Evaluation of AssignmentExpression.
  4. Let initValue be ? GetValue(initResult).
  5. Perform ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(nextIndex)), initValue).
  6. Return nextIndex + 1.
ElementList : ElementList , Elisionopt SpreadElement
  1. Set nextIndex to ? ArrayAccumulation of ElementList with arguments array and nextIndex.
  2. If Elision is present, then
    1. Set nextIndex to ? ArrayAccumulation of Elision with arguments array and nextIndex.
  3. Return ? ArrayAccumulation of SpreadElement with arguments array and nextIndex.
SpreadElement : ... AssignmentExpression
  1. Let spreadRef be ? 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 : [ Elisionopt ]
  1. Let array be ! ArrayCreate(0).
  2. If Elision is present, then
    1. Perform ? ArrayAccumulation of Elision with arguments array and 0.
  3. Return array.
ArrayLiteral : [ ElementList ]
  1. Let array be ! ArrayCreate(0).
  2. Perform ? ArrayAccumulation of ElementList with arguments array and 0.
  3. Return array.
ArrayLiteral : [ ElementList , Elisionopt ]
  1. Let array be ! ArrayCreate(0).
  2. Let nextIndex be ? ArrayAccumulation of ElementList with arguments array and 0.
  3. If Elision is present, then
    1. Perform ? ArrayAccumulation of Elision with arguments array and nextIndex.
  4. Return array.

13.2.5 Object Initializer

Note 1

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

Syntax

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

MethodDefinition is defined in 15.4.

Note 3

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

13.2.5.1 Static Semantics: Early Errors

PropertyDefinition : MethodDefinition

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

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

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

ObjectLiteral : { PropertyDefinitionList } { PropertyDefinitionList , } Note 2

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

13.2.5.2 Static Semantics: IsComputedPropertyKey

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

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

13.2.5.3 Static Semantics: PropertyNameList

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

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

13.2.5.4 Runtime Semantics: Evaluation

ObjectLiteral : { }
  1. Return OrdinaryObjectCreate(%Object.prototype%).
ObjectLiteral : { PropertyDefinitionList } { PropertyDefinitionList , }
  1. Let obj be OrdinaryObjectCreate(%Object.prototype%).
  2. Perform ? PropertyDefinitionEvaluation of PropertyDefinitionList with argument obj.
  3. Return obj.
LiteralPropertyName : IdentifierName
  1. Return StringValue of IdentifierName.
LiteralPropertyName : StringLiteral
  1. Return the SV of StringLiteral.
LiteralPropertyName : NumericLiteral
  1. Let nbr be the NumericValue of NumericLiteral.
  2. Return ! ToString(nbr).
ComputedPropertyName : [ AssignmentExpression ]
  1. Let exprValue be ? 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 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 JSON.parse (see step 7 of JSON.parse), 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

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 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 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; else return false.

13.2.7.3 Runtime Semantics: Evaluation

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

13.2.8 Template Literals

Syntax

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

13.2.8.1 Static Semantics: Early Errors

TemplateLiteral[Yield, Await, Tagged] : NoSubstitutionTemplate TemplateLiteral[Yield, Await, Tagged] : SubstitutionTemplate[?Yield, ?Await, ?Tagged]
  • It is a Syntax Error if the number of elements in the result of 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] TemplateSpans[Yield, Await, Tagged] : TemplateTail TemplateMiddleList[Yield, Await, Tagged] : TemplateMiddle Expression[+In, ?Yield, ?Await] TemplateMiddleList[?Yield, ?Await, ?Tagged] TemplateMiddle Expression[+In, ?Yield, ?Await]

13.2.8.2 Static Semantics: TemplateStrings

The syntax-directed operation TemplateStrings takes argument raw (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 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 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 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 TemplateStrings of templateLiteral with argument true.
  5. Assert: rawStrings is a List of Strings.
  6. Let cookedStrings be 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

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.