14 ECMAScript Language: Statements and Declarations

Syntax

Statement[Yield, Await, Return] : BlockStatement[?Yield, ?Await, ?Return] VariableStatement[?Yield, ?Await] EmptyStatement ExpressionStatement[?Yield, ?Await] IfStatement[?Yield, ?Await, ?Return] BreakableStatement[?Yield, ?Await, ?Return] ContinueStatement[?Yield, ?Await] BreakStatement[?Yield, ?Await] [+Return]ReturnStatement[?Yield, ?Await] WithStatement[?Yield, ?Await, ?Return] LabelledStatement[?Yield, ?Await, ?Return] ThrowStatement[?Yield, ?Await] TryStatement[?Yield, ?Await, ?Return] DebuggerStatement Declaration[Yield, Await] : HoistableDeclaration[?Yield, ?Await, ~Default] ClassDeclaration[?Yield, ?Await, ~Default] LexicalDeclaration[+In, ?Yield, ?Await] HoistableDeclaration[Yield, Await, Default] : FunctionDeclaration[?Yield, ?Await, ?Default] GeneratorDeclaration[?Yield, ?Await, ?Default] AsyncFunctionDeclaration[?Yield, ?Await, ?Default] AsyncGeneratorDeclaration[?Yield, ?Await, ?Default] BreakableStatement[Yield, Await, Return] : IterationStatement[?Yield, ?Await, ?Return] SwitchStatement[?Yield, ?Await, ?Return]

14.1 Statement Semantics

14.1.1 Runtime Semantics: Evaluation

HoistableDeclaration : GeneratorDeclaration AsyncFunctionDeclaration AsyncGeneratorDeclaration
  1. Return NormalCompletion(empty).
HoistableDeclaration : FunctionDeclaration
  1. Return the result of evaluating FunctionDeclaration.
BreakableStatement : IterationStatement SwitchStatement
  1. Let newLabelSet be a new empty List.
  2. Return the result of performing LabelledEvaluation of this BreakableStatement with argument newLabelSet.

14.2 Block

Syntax

BlockStatement[Yield, Await, Return] : Block[?Yield, ?Await, ?Return] Block[Yield, Await, Return] : { StatementList[?Yield, ?Await, ?Return]opt } StatementList[Yield, Await, Return] : StatementListItem[?Yield, ?Await, ?Return] StatementList[?Yield, ?Await, ?Return] StatementListItem[?Yield, ?Await, ?Return] StatementListItem[Yield, Await, Return] : Statement[?Yield, ?Await, ?Return] Declaration[?Yield, ?Await]

14.2.1 Static Semantics: Early Errors

Block : { StatementList }

14.2.2 Runtime Semantics: Evaluation

Block : { }
  1. Return NormalCompletion(empty).
Block : { StatementList }
  1. Let oldEnv be the running execution context's LexicalEnvironment.
  2. Let blockEnv be NewDeclarativeEnvironment(oldEnv).
  3. Perform BlockDeclarationInstantiation(StatementList, blockEnv).
  4. Set the running execution context's LexicalEnvironment to blockEnv.
  5. Let blockValue be the result of evaluating StatementList.
  6. Set the running execution context's LexicalEnvironment to oldEnv.
  7. Return blockValue.
Note 1

No matter how control leaves the Block the LexicalEnvironment is always restored to its former state.

StatementList : StatementList StatementListItem
  1. Let sl be the result of evaluating StatementList.
  2. ReturnIfAbrupt(sl).
  3. Let s be the result of evaluating StatementListItem.
  4. Return Completion(UpdateEmpty(s, sl)).
Note 2

The value of a StatementList is the value of the last value-producing item in the StatementList. For example, the following calls to the eval function all return the value 1:

eval("1;;;;;")
eval("1;{}")
eval("1;var a;")

14.2.3 BlockDeclarationInstantiation ( code, env )

The abstract operation BlockDeclarationInstantiation takes arguments code (a Parse Node) and env (a declarative Environment Record). code is the Parse Node corresponding to the body of the block. env is the Environment Record in which bindings are to be created.

Note

When a Block or CaseBlock is evaluated a new declarative Environment Record is created and bindings for each block scoped variable, constant, function, or class declared in the block are instantiated in the Environment Record.

It performs the following steps when called:

  1. Let declarations be the LexicallyScopedDeclarations of code.
  2. Let privateEnv be the running execution context's PrivateEnvironment.
  3. For each element d of declarations, do
    1. For each element dn of the BoundNames of d, do
      1. If IsConstantDeclaration of d is true, then
        1. Perform ! env.CreateImmutableBinding(dn, true).
      2. Else,
        1. Perform ! env.CreateMutableBinding(dn, false). NOTE: This step is replaced in section B.3.2.6.
    2. If d is a FunctionDeclaration, a GeneratorDeclaration, an AsyncFunctionDeclaration, or an AsyncGeneratorDeclaration, then
      1. Let fn be the sole element of the BoundNames of d.
      2. Let fo be InstantiateFunctionObject of d with arguments env and privateEnv.
      3. Perform env.InitializeBinding(fn, fo). NOTE: This step is replaced in section B.3.2.6.

14.3 Declarations and the Variable Statement

14.3.1 Let and Const Declarations

Note

let and const declarations define variables that are scoped to the running execution context's LexicalEnvironment. The variables are created when their containing Environment Record is instantiated but may not be accessed in any way until the variable's LexicalBinding is evaluated. A variable defined by a LexicalBinding with an Initializer is assigned the value of its Initializer's AssignmentExpression when the LexicalBinding is evaluated, not when the variable is created. If a LexicalBinding in a let declaration does not have an Initializer the variable is assigned the value undefined when the LexicalBinding is evaluated.

Syntax

LexicalDeclaration[In, Yield, Await] : LetOrConst BindingList[?In, ?Yield, ?Await] ; LetOrConst : let const BindingList[In, Yield, Await] : LexicalBinding[?In, ?Yield, ?Await] BindingList[?In, ?Yield, ?Await] , LexicalBinding[?In, ?Yield, ?Await] LexicalBinding[In, Yield, Await] : BindingIdentifier[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]opt BindingPattern[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]

14.3.1.1 Static Semantics: Early Errors

LexicalDeclaration : LetOrConst BindingList ; LexicalBinding : BindingIdentifier Initializeropt

14.3.1.2 Runtime Semantics: Evaluation

LexicalDeclaration : LetOrConst BindingList ;
  1. Let next be the result of evaluating BindingList.
  2. ReturnIfAbrupt(next).
  3. Return NormalCompletion(empty).
BindingList : BindingList , LexicalBinding
  1. Let next be the result of evaluating BindingList.
  2. ReturnIfAbrupt(next).
  3. Return the result of evaluating LexicalBinding.
LexicalBinding : BindingIdentifier
  1. Let lhs be ResolveBinding(StringValue of BindingIdentifier).
  2. Return InitializeReferencedBinding(lhs, undefined).
Note

A static semantics rule ensures that this form of LexicalBinding never occurs in a const declaration.

LexicalBinding : BindingIdentifier Initializer
  1. Let bindingId be StringValue of BindingIdentifier.
  2. Let lhs be ResolveBinding(bindingId).
  3. If IsAnonymousFunctionDefinition(Initializer) is true, then
    1. Let value be NamedEvaluation of Initializer with argument bindingId.
  4. Else,
    1. Let rhs be the result of evaluating Initializer.
    2. Let value be ? GetValue(rhs).
  5. Return InitializeReferencedBinding(lhs, value).
LexicalBinding : BindingPattern Initializer
  1. Let rhs be the result of evaluating Initializer.
  2. Let value be ? GetValue(rhs).
  3. Let env be the running execution context's LexicalEnvironment.
  4. Return the result of performing BindingInitialization for BindingPattern using value and env as the arguments.

14.3.2 Variable Statement

Note

A var statement declares variables that are scoped to the running execution context's VariableEnvironment. Var variables are created when their containing Environment Record is instantiated and are initialized to undefined when created. Within the scope of any VariableEnvironment a common BindingIdentifier may appear in more than one VariableDeclaration but those declarations collectively define only one variable. A variable defined by a VariableDeclaration with an Initializer is assigned the value of its Initializer's AssignmentExpression when the VariableDeclaration is executed, not when the variable is created.

Syntax

VariableStatement[Yield, Await] : var VariableDeclarationList[+In, ?Yield, ?Await] ; VariableDeclarationList[In, Yield, Await] : VariableDeclaration[?In, ?Yield, ?Await] VariableDeclarationList[?In, ?Yield, ?Await] , VariableDeclaration[?In, ?Yield, ?Await] VariableDeclaration[In, Yield, Await] : BindingIdentifier[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]opt BindingPattern[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]

14.3.2.1 Runtime Semantics: Evaluation

VariableStatement : var VariableDeclarationList ;
  1. Let next be the result of evaluating VariableDeclarationList.
  2. ReturnIfAbrupt(next).
  3. Return NormalCompletion(empty).
VariableDeclarationList : VariableDeclarationList , VariableDeclaration
  1. Let next be the result of evaluating VariableDeclarationList.
  2. ReturnIfAbrupt(next).
  3. Return the result of evaluating VariableDeclaration.
VariableDeclaration : BindingIdentifier
  1. Return NormalCompletion(empty).
VariableDeclaration : BindingIdentifier Initializer
  1. Let bindingId be StringValue of BindingIdentifier.
  2. Let lhs be ? ResolveBinding(bindingId).
  3. If IsAnonymousFunctionDefinition(Initializer) is true, then
    1. Let value be NamedEvaluation of Initializer with argument bindingId.
  4. Else,
    1. Let rhs be the result of evaluating Initializer.
    2. Let value be ? GetValue(rhs).
  5. Return ? PutValue(lhs, value).
Note

If a VariableDeclaration is nested within a with statement and the BindingIdentifier in the VariableDeclaration is the same as a property name of the binding object of the with statement's object Environment Record, then step 5 will assign value to the property instead of assigning to the VariableEnvironment binding of the Identifier.

VariableDeclaration : BindingPattern Initializer
  1. Let rhs be the result of evaluating Initializer.
  2. Let rval be ? GetValue(rhs).
  3. Return the result of performing BindingInitialization for BindingPattern passing rval and undefined as arguments.

14.3.3 Destructuring Binding Patterns

Syntax

BindingPattern[Yield, Await] : ObjectBindingPattern[?Yield, ?Await] ArrayBindingPattern[?Yield, ?Await] ObjectBindingPattern[Yield, Await] : { } { BindingRestProperty[?Yield, ?Await] } { BindingPropertyList[?Yield, ?Await] } { BindingPropertyList[?Yield, ?Await] , BindingRestProperty[?Yield, ?Await]opt } ArrayBindingPattern[Yield, Await] : [ Elisionopt BindingRestElement[?Yield, ?Await]opt ] [ BindingElementList[?Yield, ?Await] ] [ BindingElementList[?Yield, ?Await] , Elisionopt BindingRestElement[?Yield, ?Await]opt ] BindingRestProperty[Yield, Await] : ... BindingIdentifier[?Yield, ?Await] BindingPropertyList[Yield, Await] : BindingProperty[?Yield, ?Await] BindingPropertyList[?Yield, ?Await] , BindingProperty[?Yield, ?Await] BindingElementList[Yield, Await] : BindingElisionElement[?Yield, ?Await] BindingElementList[?Yield, ?Await] , BindingElisionElement[?Yield, ?Await] BindingElisionElement[Yield, Await] : Elisionopt BindingElement[?Yield, ?Await] BindingProperty[Yield, Await] : SingleNameBinding[?Yield, ?Await] PropertyName[?Yield, ?Await] : BindingElement[?Yield, ?Await] BindingElement[Yield, Await] : SingleNameBinding[?Yield, ?Await] BindingPattern[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt SingleNameBinding[Yield, Await] : BindingIdentifier[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt BindingRestElement[Yield, Await] : ... BindingIdentifier[?Yield, ?Await] ... BindingPattern[?Yield, ?Await]

14.3.3.1 Runtime Semantics: PropertyBindingInitialization

The syntax-directed operation PropertyBindingInitialization takes arguments value and environment. It collects a list of all bound property names rather than just empty completion. It is defined piecewise over the following productions:

BindingPropertyList : BindingPropertyList , BindingProperty
  1. Let boundNames be ? PropertyBindingInitialization of BindingPropertyList with arguments value and environment.
  2. Let nextNames be ? PropertyBindingInitialization of BindingProperty with arguments value and environment.
  3. Return the list-concatenation of boundNames and nextNames.
BindingProperty : SingleNameBinding
  1. Let name be the string that is the only element of BoundNames of SingleNameBinding.
  2. Perform ? KeyedBindingInitialization for SingleNameBinding using value, environment, and name as the arguments.
  3. Return a List whose sole element is name.
BindingProperty : PropertyName : BindingElement
  1. Let P be the result of evaluating PropertyName.
  2. ReturnIfAbrupt(P).
  3. Perform ? KeyedBindingInitialization of BindingElement with value, environment, and P as the arguments.
  4. Return a List whose sole element is P.

14.3.3.2 Runtime Semantics: RestBindingInitialization

The syntax-directed operation RestBindingInitialization takes arguments value, environment, and excludedNames. It is defined piecewise over the following productions:

BindingRestProperty : ... BindingIdentifier
  1. Let lhs be ? ResolveBinding(StringValue of BindingIdentifier, environment).
  2. Let restObj be ! OrdinaryObjectCreate(%Object.prototype%).
  3. Perform ? CopyDataProperties(restObj, value, excludedNames).
  4. If environment is undefined, return PutValue(lhs, restObj).
  5. Return InitializeReferencedBinding(lhs, restObj).

14.3.3.3 Runtime Semantics: KeyedBindingInitialization

The syntax-directed operation KeyedBindingInitialization takes arguments value, environment, and propertyName.

Note

When undefined is passed for environment it indicates that a PutValue operation should be used to assign the initialization value. This is the case for formal parameter lists of non-strict functions. In that case the formal parameter bindings are preinitialized in order to deal with the possibility of multiple parameters with the same name.

It is defined piecewise over the following productions:

BindingElement : BindingPattern Initializeropt
  1. Let v be ? GetV(value, propertyName).
  2. If Initializer is present and v is undefined, then
    1. Let defaultValue be the result of evaluating Initializer.
    2. Set v to ? GetValue(defaultValue).
  3. Return the result of performing BindingInitialization for BindingPattern passing v and environment as arguments.
SingleNameBinding : BindingIdentifier Initializeropt
  1. Let bindingId be StringValue of BindingIdentifier.
  2. Let lhs be ? ResolveBinding(bindingId, environment).
  3. Let v be ? GetV(value, propertyName).
  4. If Initializer is present and v is undefined, then
    1. If IsAnonymousFunctionDefinition(Initializer) is true, then
      1. Set v to the result of performing NamedEvaluation for Initializer with argument bindingId.
    2. Else,
      1. Let defaultValue be the result of evaluating Initializer.
      2. Set v to ? GetValue(defaultValue).
  5. If environment is undefined, return ? PutValue(lhs, v).
  6. Return InitializeReferencedBinding(lhs, v).

14.4 Empty Statement

Syntax

EmptyStatement : ;

14.4.1 Runtime Semantics: Evaluation

EmptyStatement : ;
  1. Return NormalCompletion(empty).

14.5 Expression Statement

Syntax

ExpressionStatement[Yield, Await] : [lookahead ∉ { {, function, async [no LineTerminator here] function, class, let [ }] Expression[+In, ?Yield, ?Await] ; Note

An ExpressionStatement cannot start with a U+007B (LEFT CURLY BRACKET) because that might make it ambiguous with a Block. An ExpressionStatement cannot start with the function or class keywords because that would make it ambiguous with a FunctionDeclaration, a GeneratorDeclaration, or a ClassDeclaration. An ExpressionStatement cannot start with async function because that would make it ambiguous with an AsyncFunctionDeclaration or a AsyncGeneratorDeclaration. An ExpressionStatement cannot start with the two token sequence let [ because that would make it ambiguous with a let LexicalDeclaration whose first LexicalBinding was an ArrayBindingPattern.

14.5.1 Runtime Semantics: Evaluation

ExpressionStatement : Expression ;
  1. Let exprRef be the result of evaluating Expression.
  2. Return ? GetValue(exprRef).

14.6 The if Statement

Syntax

IfStatement[Yield, Await, Return] : if ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] else Statement[?Yield, ?Await, ?Return] if ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] [lookahead ≠ else] Note
The lookahead-restriction [lookahead ≠ else] resolves the classic "dangling else" problem in the usual way. That is, when the choice of associated if is otherwise ambiguous, the else is associated with the nearest (innermost) of the candidate ifs

14.6.1 Static Semantics: Early Errors

IfStatement : if ( Expression ) Statement else Statement IfStatement : if ( Expression ) Statement Note

It is only necessary to apply this rule if the extension specified in B.3.1 is implemented.

14.6.2 Runtime Semantics: Evaluation

IfStatement : if ( Expression ) Statement else Statement
  1. Let exprRef be the result of evaluating Expression.
  2. Let exprValue be ! ToBoolean(? GetValue(exprRef)).
  3. If exprValue is true, then
    1. Let stmtCompletion be the result of evaluating the first Statement.
  4. Else,
    1. Let stmtCompletion be the result of evaluating the second Statement.
  5. Return Completion(UpdateEmpty(stmtCompletion, undefined)).
IfStatement : if ( Expression ) Statement
  1. Let exprRef be the result of evaluating Expression.
  2. Let exprValue be ! ToBoolean(? GetValue(exprRef)).
  3. If exprValue is false, then
    1. Return NormalCompletion(undefined).
  4. Else,
    1. Let stmtCompletion be the result of evaluating Statement.
    2. Return Completion(UpdateEmpty(stmtCompletion, undefined)).

14.7 Iteration Statements

Syntax

IterationStatement[Yield, Await, Return] : DoWhileStatement[?Yield, ?Await, ?Return] WhileStatement[?Yield, ?Await, ?Return] ForStatement[?Yield, ?Await, ?Return] ForInOfStatement[?Yield, ?Await, ?Return]

14.7.1 Semantics

14.7.1.1 LoopContinues ( completion, labelSet )

The abstract operation LoopContinues takes arguments completion and labelSet. It performs the following steps when called:

  1. If completion.[[Type]] is normal, return true.
  2. If completion.[[Type]] is not continue, return false.
  3. If completion.[[Target]] is empty, return true.
  4. If completion.[[Target]] is an element of labelSet, return true.
  5. Return false.
Note

Within the Statement part of an IterationStatement a ContinueStatement may be used to begin a new iteration.

14.7.1.2 Runtime Semantics: LoopEvaluation

The syntax-directed operation LoopEvaluation takes argument labelSet. It is defined piecewise over the following productions:

IterationStatement : DoWhileStatement
  1. Return ? DoWhileLoopEvaluation of DoWhileStatement with argument labelSet.
IterationStatement : WhileStatement
  1. Return ? WhileLoopEvaluation of WhileStatement with argument labelSet.
IterationStatement : ForStatement
  1. Return ? ForLoopEvaluation of ForStatement with argument labelSet.
IterationStatement : ForInOfStatement
  1. Return ? ForInOfLoopEvaluation of ForInOfStatement with argument labelSet.

14.7.2 The do-while Statement

Syntax

DoWhileStatement[Yield, Await, Return] : do Statement[?Yield, ?Await, ?Return] while ( Expression[+In, ?Yield, ?Await] ) ;

14.7.2.1 Static Semantics: Early Errors

DoWhileStatement : do Statement while ( Expression ) ; Note

It is only necessary to apply this rule if the extension specified in B.3.1 is implemented.

14.7.2.2 Runtime Semantics: DoWhileLoopEvaluation

The syntax-directed operation DoWhileLoopEvaluation takes argument labelSet. It is defined piecewise over the following productions:

DoWhileStatement : do Statement while ( Expression ) ;
  1. Let V be undefined.
  2. Repeat,
    1. Let stmtResult be the result of evaluating Statement.
    2. If LoopContinues(stmtResult, labelSet) is false, return Completion(UpdateEmpty(stmtResult, V)).
    3. If stmtResult.[[Value]] is not empty, set V to stmtResult.[[Value]].
    4. Let exprRef be the result of evaluating Expression.
    5. Let exprValue be ? GetValue(exprRef).
    6. If ! ToBoolean(exprValue) is false, return NormalCompletion(V).

14.7.3 The while Statement

Syntax

WhileStatement[Yield, Await, Return] : while ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return]

14.7.3.1 Static Semantics: Early Errors

WhileStatement : while ( Expression ) Statement Note

It is only necessary to apply this rule if the extension specified in B.3.1 is implemented.

14.7.3.2 Runtime Semantics: WhileLoopEvaluation

The syntax-directed operation WhileLoopEvaluation takes argument labelSet. It is defined piecewise over the following productions:

WhileStatement : while ( Expression ) Statement
  1. Let V be undefined.
  2. Repeat,
    1. Let exprRef be the result of evaluating Expression.
    2. Let exprValue be ? GetValue(exprRef).
    3. If ! ToBoolean(exprValue) is false, return NormalCompletion(V).
    4. Let stmtResult be the result of evaluating Statement.
    5. If LoopContinues(stmtResult, labelSet) is false, return Completion(UpdateEmpty(stmtResult, V)).
    6. If stmtResult.[[Value]] is not empty, set V to stmtResult.[[Value]].

14.7.4 The for Statement

Syntax

ForStatement[Yield, Await, Return] : for ( [lookahead ≠ let [] Expression[~In, ?Yield, ?Await]opt ; Expression[+In, ?Yield, ?Await]opt ; Expression[+In, ?Yield, ?Await]opt ) Statement[?Yield, ?Await, ?Return] for ( var VariableDeclarationList[~In, ?Yield, ?Await] ; Expression[+In, ?Yield, ?Await]opt ; Expression[+In, ?Yield, ?Await]opt ) Statement[?Yield, ?Await, ?Return] for ( LexicalDeclaration[~In, ?Yield, ?Await] Expression[+In, ?Yield, ?Await]opt ; Expression[+In, ?Yield, ?Await]opt ) Statement[?Yield, ?Await, ?Return]

14.7.4.1 Static Semantics: Early Errors

ForStatement : for ( Expressionopt ; Expressionopt ; Expressionopt ) Statement for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement Note

It is only necessary to apply this rule if the extension specified in B.3.1 is implemented.

ForStatement : for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement

14.7.4.2 Runtime Semantics: ForLoopEvaluation

The syntax-directed operation ForLoopEvaluation takes argument labelSet. It is defined piecewise over the following productions:

ForStatement : for ( Expressionopt ; Expressionopt ; Expressionopt ) Statement
  1. If the first Expression is present, then
    1. Let exprRef be the result of evaluating the first Expression.
    2. Perform ? GetValue(exprRef).
  2. Return ? ForBodyEvaluation(the second Expression, the third Expression, Statement, « », labelSet).
ForStatement : for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement
  1. Let varDcl be the result of evaluating VariableDeclarationList.
  2. ReturnIfAbrupt(varDcl).
  3. Return ? ForBodyEvaluation(the first Expression, the second Expression, Statement, « », labelSet).
ForStatement : for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement
  1. Let oldEnv be the running execution context's LexicalEnvironment.
  2. Let loopEnv be NewDeclarativeEnvironment(oldEnv).
  3. Let isConst be IsConstantDeclaration of LexicalDeclaration.
  4. Let boundNames be the BoundNames of LexicalDeclaration.
  5. For each element dn of boundNames, do
    1. If isConst is true, then
      1. Perform ! loopEnv.CreateImmutableBinding(dn, true).
    2. Else,
      1. Perform ! loopEnv.CreateMutableBinding(dn, false).
  6. Set the running execution context's LexicalEnvironment to loopEnv.
  7. Let forDcl be the result of evaluating LexicalDeclaration.
  8. If forDcl is an abrupt completion, then
    1. Set the running execution context's LexicalEnvironment to oldEnv.
    2. Return Completion(forDcl).
  9. If isConst is false, let perIterationLets be boundNames; otherwise let perIterationLets be « ».
  10. Let bodyResult be ForBodyEvaluation(the first Expression, the second Expression, Statement, perIterationLets, labelSet).
  11. Set the running execution context's LexicalEnvironment to oldEnv.
  12. Return Completion(bodyResult).

14.7.4.3 ForBodyEvaluation ( test, increment, stmt, perIterationBindings, labelSet )

The abstract operation ForBodyEvaluation takes arguments test, increment, stmt, perIterationBindings, and labelSet. It performs the following steps when called:

  1. Let V be undefined.
  2. Perform ? CreatePerIterationEnvironment(perIterationBindings).
  3. Repeat,
    1. If test is not [empty], then
      1. Let testRef be the result of evaluating test.
      2. Let testValue be ? GetValue(testRef).
      3. If ! ToBoolean(testValue) is false, return NormalCompletion(V).
    2. Let result be the result of evaluating stmt.
    3. If LoopContinues(result, labelSet) is false, return Completion(UpdateEmpty(result, V)).
    4. If result.[[Value]] is not empty, set V to result.[[Value]].
    5. Perform ? CreatePerIterationEnvironment(perIterationBindings).
    6. If increment is not [empty], then
      1. Let incRef be the result of evaluating increment.
      2. Perform ? GetValue(incRef).

14.7.4.4 CreatePerIterationEnvironment ( perIterationBindings )

The abstract operation CreatePerIterationEnvironment takes argument perIterationBindings. It performs the following steps when called:

  1. If perIterationBindings has any elements, then
    1. Let lastIterationEnv be the running execution context's LexicalEnvironment.
    2. Let outer be lastIterationEnv.[[OuterEnv]].
    3. Assert: outer is not null.
    4. Let thisIterationEnv be NewDeclarativeEnvironment(outer).
    5. For each element bn of perIterationBindings, do
      1. Perform ! thisIterationEnv.CreateMutableBinding(bn, false).
      2. Let lastValue be ? lastIterationEnv.GetBindingValue(bn, true).
      3. Perform thisIterationEnv.InitializeBinding(bn, lastValue).
    6. Set the running execution context's LexicalEnvironment to thisIterationEnv.
  2. Return undefined.

14.7.5 The for-in, for-of, and for-await-of Statements

Syntax

ForInOfStatement[Yield, Await, Return] : for ( [lookahead ≠ let [] LeftHandSideExpression[?Yield, ?Await] in Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( var ForBinding[?Yield, ?Await] in Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( ForDeclaration[?Yield, ?Await] in Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( [lookahead ∉ { let, async of }] LeftHandSideExpression[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( var ForBinding[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( ForDeclaration[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] [+Await] for await ( [lookahead ≠ let] LeftHandSideExpression[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] [+Await] for await ( var ForBinding[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] [+Await] for await ( ForDeclaration[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] ForDeclaration[Yield, Await] : LetOrConst ForBinding[?Yield, ?Await] ForBinding[Yield, Await] : BindingIdentifier[?Yield, ?Await] BindingPattern[?Yield, ?Await] Note

This section is extended by Annex B.3.5.

14.7.5.1 Static Semantics: Early Errors

ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement for ( var ForBinding in Expression ) Statement for ( ForDeclaration in Expression ) Statement for ( LeftHandSideExpression of AssignmentExpression ) Statement for ( var ForBinding of AssignmentExpression ) Statement for ( ForDeclaration of AssignmentExpression ) Statement for await ( LeftHandSideExpression of AssignmentExpression ) Statement for await ( var ForBinding of AssignmentExpression ) Statement for await ( ForDeclaration of AssignmentExpression ) Statement Note

It is only necessary to apply this rule if the extension specified in B.3.1 is implemented.

ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement for ( LeftHandSideExpression of AssignmentExpression ) Statement for await ( LeftHandSideExpression of AssignmentExpression ) Statement

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

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

ForInOfStatement : for ( ForDeclaration in Expression ) Statement for ( ForDeclaration of AssignmentExpression ) Statement for await ( ForDeclaration of AssignmentExpression ) Statement

14.7.5.2 Static Semantics: IsDestructuring

The syntax-directed operation IsDestructuring takes no arguments. It is defined piecewise over the following productions:

MemberExpression : PrimaryExpression
  1. If PrimaryExpression is either an ObjectLiteral or an ArrayLiteral, return true.
  2. Return false.
MemberExpression : MemberExpression [ Expression ] MemberExpression . IdentifierName MemberExpression TemplateLiteral SuperProperty MetaProperty new MemberExpression Arguments MemberExpression . PrivateIdentifier NewExpression : new NewExpression LeftHandSideExpression : CallExpression OptionalExpression
  1. Return false.
ForDeclaration : LetOrConst ForBinding
  1. Return IsDestructuring of ForBinding.
ForBinding : BindingIdentifier
  1. Return false.
ForBinding : BindingPattern
  1. Return true.
Note

This section is extended by Annex B.3.5.

14.7.5.3 Runtime Semantics: ForDeclarationBindingInitialization

The syntax-directed operation ForDeclarationBindingInitialization takes arguments value and environment.

Note

undefined is passed for environment to indicate that a PutValue operation should be used to assign the initialization value. This is the case for var statements and the formal parameter lists of some non-strict functions (see 10.2.11). In those cases a lexical binding is hoisted and preinitialized prior to evaluation of its initializer.

It is defined piecewise over the following productions:

ForDeclaration : LetOrConst ForBinding
  1. Return the result of performing BindingInitialization for ForBinding passing value and environment as the arguments.

14.7.5.4 Runtime Semantics: ForDeclarationBindingInstantiation

The syntax-directed operation ForDeclarationBindingInstantiation takes argument environment. It is defined piecewise over the following productions:

ForDeclaration : LetOrConst ForBinding
  1. Assert: environment is a declarative Environment Record.
  2. For each element name of the BoundNames of ForBinding, do
    1. If IsConstantDeclaration of LetOrConst is true, then
      1. Perform ! environment.CreateImmutableBinding(name, true).
    2. Else,
      1. Perform ! environment.CreateMutableBinding(name, false).

14.7.5.5 Runtime Semantics: ForInOfLoopEvaluation

The syntax-directed operation ForInOfLoopEvaluation takes argument labelSet. It is defined piecewise over the following productions:

ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement
  1. Let keyResult be ? ForIn/OfHeadEvaluation(« », Expression, enumerate).
  2. Return ? ForIn/OfBodyEvaluation(LeftHandSideExpression, Statement, keyResult, enumerate, assignment, labelSet).
ForInOfStatement : for ( var ForBinding in Expression ) Statement
  1. Let keyResult be ? ForIn/OfHeadEvaluation(« », Expression, enumerate).
  2. Return ? ForIn/OfBodyEvaluation(ForBinding, Statement, keyResult, enumerate, varBinding, labelSet).
ForInOfStatement : for ( ForDeclaration in Expression ) Statement
  1. Let keyResult be ? ForIn/OfHeadEvaluation(BoundNames of ForDeclaration, Expression, enumerate).
  2. Return ? ForIn/OfBodyEvaluation(ForDeclaration, Statement, keyResult, enumerate, lexicalBinding, labelSet).
ForInOfStatement : for ( LeftHandSideExpression of AssignmentExpression ) Statement
  1. Let keyResult be ? ForIn/OfHeadEvaluation(« », AssignmentExpression, iterate).
  2. Return ? ForIn/OfBodyEvaluation(LeftHandSideExpression, Statement, keyResult, iterate, assignment, labelSet).
ForInOfStatement : for ( var ForBinding of AssignmentExpression ) Statement
  1. Let keyResult be ? ForIn/OfHeadEvaluation(« », AssignmentExpression, iterate).
  2. Return ? ForIn/OfBodyEvaluation(ForBinding, Statement, keyResult, iterate, varBinding, labelSet).
ForInOfStatement : for ( ForDeclaration of AssignmentExpression ) Statement
  1. Let keyResult be ? ForIn/OfHeadEvaluation(BoundNames of ForDeclaration, AssignmentExpression, iterate).
  2. Return ? ForIn/OfBodyEvaluation(ForDeclaration, Statement, keyResult, iterate, lexicalBinding, labelSet).
ForInOfStatement : for await ( LeftHandSideExpression of AssignmentExpression ) Statement
  1. Let keyResult be ? ForIn/OfHeadEvaluation(« », AssignmentExpression, async-iterate).
  2. Return ? ForIn/OfBodyEvaluation(LeftHandSideExpression, Statement, keyResult, iterate, assignment, labelSet, async).
ForInOfStatement : for await ( var ForBinding of AssignmentExpression ) Statement
  1. Let keyResult be ? ForIn/OfHeadEvaluation(« », AssignmentExpression, async-iterate).
  2. Return ? ForIn/OfBodyEvaluation(ForBinding, Statement, keyResult, iterate, varBinding, labelSet, async).
ForInOfStatement : for await ( ForDeclaration of AssignmentExpression ) Statement
  1. Let keyResult be ? ForIn/OfHeadEvaluation(BoundNames of ForDeclaration, AssignmentExpression, async-iterate).
  2. Return ? ForIn/OfBodyEvaluation(ForDeclaration, Statement, keyResult, iterate, lexicalBinding, labelSet, async).
Note

This section is extended by Annex B.3.5.

14.7.5.6 ForIn/OfHeadEvaluation ( uninitializedBoundNames, expr, iterationKind )

The abstract operation ForIn/OfHeadEvaluation takes arguments uninitializedBoundNames, expr, and iterationKind (enumerate, iterate, or async-iterate). It performs the following steps when called:

  1. Let oldEnv be the running execution context's LexicalEnvironment.
  2. If uninitializedBoundNames is not an empty List, then
    1. Assert: uninitializedBoundNames has no duplicate entries.
    2. Let newEnv be NewDeclarativeEnvironment(oldEnv).
    3. For each String name of uninitializedBoundNames, do
      1. Perform ! newEnv.CreateMutableBinding(name, false).
    4. Set the running execution context's LexicalEnvironment to newEnv.
  3. Let exprRef be the result of evaluating expr.
  4. Set the running execution context's LexicalEnvironment to oldEnv.
  5. Let exprValue be ? GetValue(exprRef).
  6. If iterationKind is enumerate, then
    1. If exprValue is undefined or null, then
      1. Return Completion { [[Type]]: break, [[Value]]: empty, [[Target]]: empty }.
    2. Let obj be ! ToObject(exprValue).
    3. Let iterator be ? EnumerateObjectProperties(obj).
    4. Let nextMethod be ! GetV(iterator, "next").
    5. Return the Record { [[Iterator]]: iterator, [[NextMethod]]: nextMethod, [[Done]]: false }.
  7. Else,
    1. Assert: iterationKind is iterate or async-iterate.
    2. If iterationKind is async-iterate, let iteratorHint be async.
    3. Else, let iteratorHint be sync.
    4. Return ? GetIterator(exprValue, iteratorHint).

14.7.5.7 ForIn/OfBodyEvaluation ( lhs, stmt, iteratorRecord, iterationKind, lhsKind, labelSet [ , iteratorKind ] )

The abstract operation ForIn/OfBodyEvaluation takes arguments lhs, stmt, iteratorRecord, iterationKind, lhsKind (assignment, varBinding, or lexicalBinding), and labelSet and optional argument iteratorKind (sync or async). It performs the following steps when called:

  1. If iteratorKind is not present, set iteratorKind to sync.
  2. Let oldEnv be the running execution context's LexicalEnvironment.
  3. Let V be undefined.
  4. Let destructuring be IsDestructuring of lhs.
  5. If destructuring is true and if lhsKind is assignment, then
    1. Assert: lhs is a LeftHandSideExpression.
    2. Let assignmentPattern be the AssignmentPattern that is covered by lhs.
  6. Repeat,
    1. Let nextResult be ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]]).
    2. If iteratorKind is async, set nextResult to ? Await(nextResult).
    3. If Type(nextResult) is not Object, throw a TypeError exception.
    4. Let done be ? IteratorComplete(nextResult).
    5. If done is true, return NormalCompletion(V).
    6. Let nextValue be ? IteratorValue(nextResult).
    7. If lhsKind is either assignment or varBinding, then
      1. If destructuring is false, then
        1. Let lhsRef be the result of evaluating lhs. (It may be evaluated repeatedly.)
    8. Else,
      1. Assert: lhsKind is lexicalBinding.
      2. Assert: lhs is a ForDeclaration.
      3. Let iterationEnv be NewDeclarativeEnvironment(oldEnv).
      4. Perform ForDeclarationBindingInstantiation for lhs passing iterationEnv as the argument.
      5. Set the running execution context's LexicalEnvironment to iterationEnv.
      6. If destructuring is false, then
        1. Assert: lhs binds a single name.
        2. Let lhsName be the sole element of BoundNames of lhs.
        3. Let lhsRef be ! ResolveBinding(lhsName).
    9. If destructuring is false, then
      1. If lhsRef is an abrupt completion, then
        1. Let status be lhsRef.
      2. Else if lhsKind is lexicalBinding, then
        1. Let status be InitializeReferencedBinding(lhsRef, nextValue).
      3. Else,
        1. Let status be PutValue(lhsRef, nextValue).
    10. Else,
      1. If lhsKind is assignment, then
        1. Let status be DestructuringAssignmentEvaluation of assignmentPattern with argument nextValue.
      2. Else if lhsKind is varBinding, then
        1. Assert: lhs is a ForBinding.
        2. Let status be BindingInitialization of lhs with arguments nextValue and undefined.
      3. Else,
        1. Assert: lhsKind is lexicalBinding.
        2. Assert: lhs is a ForDeclaration.
        3. Let status be ForDeclarationBindingInitialization of lhs with arguments nextValue and iterationEnv.
    11. If status is an abrupt completion, then
      1. Set the running execution context's LexicalEnvironment to oldEnv.
      2. If iteratorKind is async, return ? AsyncIteratorClose(iteratorRecord, status).
      3. If iterationKind is enumerate, then
        1. Return status.
      4. Else,
        1. Assert: iterationKind is iterate.
        2. Return ? IteratorClose(iteratorRecord, status).
    12. Let result be the result of evaluating stmt.
    13. Set the running execution context's LexicalEnvironment to oldEnv.
    14. If LoopContinues(result, labelSet) is false, then
      1. If iterationKind is enumerate, then
        1. Return Completion(UpdateEmpty(result, V)).
      2. Else,
        1. Assert: iterationKind is iterate.
        2. Set status to UpdateEmpty(result, V).
        3. If iteratorKind is async, return ? AsyncIteratorClose(iteratorRecord, status).
        4. Return ? IteratorClose(iteratorRecord, status).
    15. If result.[[Value]] is not empty, set V to result.[[Value]].

14.7.5.8 Runtime Semantics: Evaluation

BindingIdentifier : Identifier yield await
  1. Let bindingId be StringValue of BindingIdentifier.
  2. Return ? ResolveBinding(bindingId).

14.7.5.9 EnumerateObjectProperties ( O )

The abstract operation EnumerateObjectProperties takes argument O (an Object). It performs the following steps when called:

  1. Return an Iterator object (27.1.1.2) whose next method iterates over all the String-valued keys of enumerable properties of O. The iterator object is never directly accessible to ECMAScript code. The mechanics and order of enumerating the properties is not specified but must conform to the rules specified below.

The iterator's throw and return methods are null and are never invoked. The iterator's next method processes object properties to determine whether the property key should be returned as an iterator value. Returned property keys do not include keys that are Symbols. Properties of the target object may be deleted during enumeration. A property that is deleted before it is processed by the iterator's next method is ignored. If new properties are added to the target object during enumeration, the newly added properties are not guaranteed to be processed in the active enumeration. A property name will be returned by the iterator's next method at most once in any enumeration.

Enumerating the properties of the target object includes enumerating properties of its prototype, and the prototype of the prototype, and so on, recursively; but a property of a prototype is not processed if it has the same name as a property that has already been processed by the iterator's next method. The values of [[Enumerable]] attributes are not considered when determining if a property of a prototype object has already been processed. The enumerable property names of prototype objects must be obtained by invoking EnumerateObjectProperties passing the prototype object as the argument. EnumerateObjectProperties must obtain the own property keys of the target object by calling its [[OwnPropertyKeys]] internal method. Property attributes of the target object must be obtained by calling its [[GetOwnProperty]] internal method.

In addition, if neither O nor any object in its prototype chain is a Proxy exotic object, Integer-Indexed exotic object, module namespace exotic object, or implementation provided exotic object, then the iterator must behave as would the iterator given by CreateForInIterator(O) until one of the following occurs:

  • the value of the [[Prototype]] internal slot of O or an object in its prototype chain changes,
  • a property is removed from O or an object in its prototype chain,
  • a property is added to an object in O's prototype chain, or
  • the value of the [[Enumerable]] attribute of a property of O or an object in its prototype chain changes.
Note 1

ECMAScript implementations are not required to implement the algorithm in 14.7.5.10.2.1 directly. They may choose any implementation whose behaviour will not deviate from that algorithm unless one of the constraints in the previous paragraph is violated.

The following is an informative definition of an ECMAScript generator function that conforms to these rules:

function* EnumerateObjectProperties(obj) {
  const visited = new Set();
  for (const key of Reflect.ownKeys(obj)) {
    if (typeof key === "symbol") continue;
    const desc = Reflect.getOwnPropertyDescriptor(obj, key);
    if (desc) {
      visited.add(key);
      if (desc.enumerable) yield key;
    }
  }
  const proto = Reflect.getPrototypeOf(obj);
  if (proto === null) return;
  for (const protoKey of EnumerateObjectProperties(proto)) {
    if (!visited.has(protoKey)) yield protoKey;
  }
}
Note 2
The list of exotic objects for which implementations are not required to match CreateForInIterator was chosen because implementations historically differed in behaviour for those cases, and agreed in all others.

14.7.5.10 For-In Iterator Objects

A For-In Iterator is an object that represents a specific iteration over some specific object. For-In Iterator objects are never directly accessible to ECMAScript code; they exist solely to illustrate the behaviour of EnumerateObjectProperties.

14.7.5.10.1 CreateForInIterator ( object )

The abstract operation CreateForInIterator takes argument object (an Object). It is used to create a For-In Iterator object which iterates over the own and inherited enumerable string properties of object in a specific order. It performs the following steps when called:

  1. Let iterator be ! OrdinaryObjectCreate(%ForInIteratorPrototype%, « [[Object]], [[ObjectWasVisited]], [[VisitedKeys]], [[RemainingKeys]] »).
  2. Set iterator.[[Object]] to object.
  3. Set iterator.[[ObjectWasVisited]] to false.
  4. Set iterator.[[VisitedKeys]] to a new empty List.
  5. Set iterator.[[RemainingKeys]] to a new empty List.
  6. Return iterator.

14.7.5.10.2 The %ForInIteratorPrototype% Object

The %ForInIteratorPrototype% object:

  • has properties that are inherited by all For-In Iterator Objects.
  • is an ordinary object.
  • has a [[Prototype]] internal slot whose value is %IteratorPrototype%.
  • is never directly accessible to ECMAScript code.
  • has the following properties:

14.7.5.10.2.1 %ForInIteratorPrototype%.next ( )

  1. Let O be the this value.
  2. Assert: Type(O) is Object.
  3. Assert: O has all of the internal slots of a For-In Iterator Instance (14.7.5.10.3).
  4. Let object be O.[[Object]].
  5. Let visited be O.[[VisitedKeys]].
  6. Let remaining be O.[[RemainingKeys]].
  7. Repeat,
    1. If O.[[ObjectWasVisited]] is false, then
      1. Let keys be ? object.[[OwnPropertyKeys]]().
      2. For each element key of keys, do
        1. If Type(key) is String, then
          1. Append key to remaining.
      3. Set O.[[ObjectWasVisited]] to true.
    2. Repeat, while remaining is not empty,
      1. Let r be the first element of remaining.
      2. Remove the first element from remaining.
      3. If there does not exist an element v of visited such that SameValue(r, v) is true, then
        1. Let desc be ? object.[[GetOwnProperty]](r).
        2. If desc is not undefined, then
          1. Append r to visited.
          2. If desc.[[Enumerable]] is true, return CreateIterResultObject(r, false).
    3. Set object to ? object.[[GetPrototypeOf]]().
    4. Set O.[[Object]] to object.
    5. Set O.[[ObjectWasVisited]] to false.
    6. If object is null, return CreateIterResultObject(undefined, true).

14.7.5.10.3 Properties of For-In Iterator Instances

For-In Iterator instances are ordinary objects that inherit properties from the %ForInIteratorPrototype% intrinsic object. For-In Iterator instances are initially created with the internal slots listed in Table 43.

Table 43: Internal Slots of For-In Iterator Instances
Internal Slot Description
[[Object]] The Object value whose properties are being iterated.
[[ObjectWasVisited]] true if the iterator has invoked [[OwnPropertyKeys]] on [[Object]], false otherwise.
[[VisitedKeys]] A list of String values which have been emitted by this iterator thus far.
[[RemainingKeys]] A list of String values remaining to be emitted for the current object, before iterating the properties of its prototype (if its prototype is not null).

14.8 The continue Statement

Syntax

ContinueStatement[Yield, Await] : continue ; continue [no LineTerminator here] LabelIdentifier[?Yield, ?Await] ;

14.8.1 Static Semantics: Early Errors

ContinueStatement : continue ; continue LabelIdentifier ;
  • It is a Syntax Error if this ContinueStatement is not nested, directly or indirectly (but not crossing function or static initialization block boundaries), within an IterationStatement.

14.8.2 Runtime Semantics: Evaluation

ContinueStatement : continue ;
  1. Return Completion { [[Type]]: continue, [[Value]]: empty, [[Target]]: empty }.
ContinueStatement : continue LabelIdentifier ;
  1. Let label be the StringValue of LabelIdentifier.
  2. Return Completion { [[Type]]: continue, [[Value]]: empty, [[Target]]: label }.

14.9 The break Statement

Syntax

BreakStatement[Yield, Await] : break ; break [no LineTerminator here] LabelIdentifier[?Yield, ?Await] ;

14.9.1 Static Semantics: Early Errors

BreakStatement : break ;

14.9.2 Runtime Semantics: Evaluation

BreakStatement : break ;
  1. Return Completion { [[Type]]: break, [[Value]]: empty, [[Target]]: empty }.
BreakStatement : break LabelIdentifier ;
  1. Let label be the StringValue of LabelIdentifier.
  2. Return Completion { [[Type]]: break, [[Value]]: empty, [[Target]]: label }.

14.10 The return Statement

Syntax

ReturnStatement[Yield, Await] : return ; return [no LineTerminator here] Expression[+In, ?Yield, ?Await] ; Note

A return statement causes a function to cease execution and, in most cases, returns a value to the caller. If Expression is omitted, the return value is undefined. Otherwise, the return value is the value of Expression. A return statement may not actually return a value to the caller depending on surrounding context. For example, in a try block, a return statement's completion record may be replaced with another completion record during evaluation of the finally block.

14.10.1 Runtime Semantics: Evaluation

ReturnStatement : return ;
  1. Return Completion { [[Type]]: return, [[Value]]: undefined, [[Target]]: empty }.
ReturnStatement : return Expression ;
  1. Let exprRef be the result of evaluating Expression.
  2. Let exprValue be ? GetValue(exprRef).
  3. If ! GetGeneratorKind() is async, set exprValue to ? Await(exprValue).
  4. Return Completion { [[Type]]: return, [[Value]]: exprValue, [[Target]]: empty }.

14.11 The with Statement

Note 1

Use of the Legacy with statement is discouraged in new ECMAScript code. Consider alternatives that are permitted in both strict mode code and non-strict code, such as destructuring assignment.

Syntax

WithStatement[Yield, Await, Return] : with ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] Note 2

The with statement adds an object Environment Record for a computed object to the lexical environment of the running execution context. It then executes a statement using this augmented lexical environment. Finally, it restores the original lexical environment.

14.11.1 Static Semantics: Early Errors

WithStatement : with ( Expression ) Statement Note

It is only necessary to apply the second rule if the extension specified in B.3.1 is implemented.

14.11.2 Runtime Semantics: Evaluation

WithStatement : with ( Expression ) Statement
  1. Let val be the result of evaluating Expression.
  2. Let obj be ? ToObject(? GetValue(val)).
  3. Let oldEnv be the running execution context's LexicalEnvironment.
  4. Let newEnv be NewObjectEnvironment(obj, true, oldEnv).
  5. Set the running execution context's LexicalEnvironment to newEnv.
  6. Let C be the result of evaluating Statement.
  7. Set the running execution context's LexicalEnvironment to oldEnv.
  8. Return Completion(UpdateEmpty(C, undefined)).
Note

No matter how control leaves the embedded Statement, whether normally or by some form of abrupt completion or exception, the LexicalEnvironment is always restored to its former state.

14.12 The switch Statement

Syntax

SwitchStatement[Yield, Await, Return] : switch ( Expression[+In, ?Yield, ?Await] ) CaseBlock[?Yield, ?Await, ?Return] CaseBlock[Yield, Await, Return] : { CaseClauses[?Yield, ?Await, ?Return]opt } { CaseClauses[?Yield, ?Await, ?Return]opt DefaultClause[?Yield, ?Await, ?Return] CaseClauses[?Yield, ?Await, ?Return]opt } CaseClauses[Yield, Await, Return] : CaseClause[?Yield, ?Await, ?Return] CaseClauses[?Yield, ?Await, ?Return] CaseClause[?Yield, ?Await, ?Return] CaseClause[Yield, Await, Return] : case Expression[+In, ?Yield, ?Await] : StatementList[?Yield, ?Await, ?Return]opt DefaultClause[Yield, Await, Return] : default : StatementList[?Yield, ?Await, ?Return]opt

14.12.1 Static Semantics: Early Errors

SwitchStatement : switch ( Expression ) CaseBlock

14.12.2 Runtime Semantics: CaseBlockEvaluation

The syntax-directed operation CaseBlockEvaluation takes argument input. It is defined piecewise over the following productions:

CaseBlock : { }
  1. Return NormalCompletion(undefined).
CaseBlock : { CaseClauses }
  1. Let V be undefined.
  2. Let A be the List of CaseClause items in CaseClauses, in source text order.
  3. Let found be false.
  4. For each CaseClause C of A, do
    1. If found is false, then
      1. Set found to ? CaseClauseIsSelected(C, input).
    2. If found is true, then
      1. Let R be the result of evaluating C.
      2. If R.[[Value]] is not empty, set V to R.[[Value]].
      3. If R is an abrupt completion, return Completion(UpdateEmpty(R, V)).
  5. Return NormalCompletion(V).
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. Let V be undefined.
  2. If the first CaseClauses is present, then
    1. Let A be the List of CaseClause items in the first CaseClauses, in source text order.
  3. Else,
    1. Let A be « ».
  4. Let found be false.
  5. For each CaseClause C of A, do
    1. If found is false, then
      1. Set found to ? CaseClauseIsSelected(C, input).
    2. If found is true, then
      1. Let R be the result of evaluating C.
      2. If R.[[Value]] is not empty, set V to R.[[Value]].
      3. If R is an abrupt completion, return Completion(UpdateEmpty(R, V)).
  6. Let foundInB be false.
  7. If the second CaseClauses is present, then
    1. Let B be the List of CaseClause items in the second CaseClauses, in source text order.
  8. Else,
    1. Let B be « ».
  9. If found is false, then
    1. For each CaseClause C of B, do
      1. If foundInB is false, then
        1. Set foundInB to ? CaseClauseIsSelected(C, input).
      2. If foundInB is true, then
        1. Let R be the result of evaluating CaseClause C.
        2. If R.[[Value]] is not empty, set V to R.[[Value]].
        3. If R is an abrupt completion, return Completion(UpdateEmpty(R, V)).
  10. If foundInB is true, return NormalCompletion(V).
  11. Let R be the result of evaluating DefaultClause.
  12. If R.[[Value]] is not empty, set V to R.[[Value]].
  13. If R is an abrupt completion, return Completion(UpdateEmpty(R, V)).
  14. NOTE: The following is another complete iteration of the second CaseClauses.
  15. For each CaseClause C of B, do
    1. Let R be the result of evaluating CaseClause C.
    2. If R.[[Value]] is not empty, set V to R.[[Value]].
    3. If R is an abrupt completion, return Completion(UpdateEmpty(R, V)).
  16. Return NormalCompletion(V).

14.12.3 CaseClauseIsSelected ( C, input )

The abstract operation CaseClauseIsSelected takes arguments C (a CaseClause Parse Node) and input (an ECMAScript language value). It determines whether C matches input. It performs the following steps when called:

  1. Assert: C is an instance of the production CaseClause : case Expression : StatementListopt .
  2. Let exprRef be the result of evaluating the Expression of C.
  3. Let clauseSelector be ? GetValue(exprRef).
  4. Return IsStrictlyEqual(input, clauseSelector).
Note

This operation does not execute C's StatementList (if any). The CaseBlock algorithm uses its return value to determine which StatementList to start executing.

14.12.4 Runtime Semantics: Evaluation

SwitchStatement : switch ( Expression ) CaseBlock
  1. Let exprRef be the result of evaluating Expression.
  2. Let switchValue be ? GetValue(exprRef).
  3. Let oldEnv be the running execution context's LexicalEnvironment.
  4. Let blockEnv be NewDeclarativeEnvironment(oldEnv).
  5. Perform BlockDeclarationInstantiation(CaseBlock, blockEnv).
  6. Set the running execution context's LexicalEnvironment to blockEnv.
  7. Let R be CaseBlockEvaluation of CaseBlock with argument switchValue.
  8. Set the running execution context's LexicalEnvironment to oldEnv.
  9. Return R.
Note

No matter how control leaves the SwitchStatement the LexicalEnvironment is always restored to its former state.

CaseClause : case Expression :
  1. Return NormalCompletion(empty).
CaseClause : case Expression : StatementList
  1. Return the result of evaluating StatementList.
DefaultClause : default :
  1. Return NormalCompletion(empty).
DefaultClause : default : StatementList
  1. Return the result of evaluating StatementList.

14.13 Labelled Statements

Syntax

LabelledStatement[Yield, Await, Return] : LabelIdentifier[?Yield, ?Await] : LabelledItem[?Yield, ?Await, ?Return] LabelledItem[Yield, Await, Return] : Statement[?Yield, ?Await, ?Return] FunctionDeclaration[?Yield, ?Await, ~Default] Note

A Statement may be prefixed by a label. Labelled statements are only used in conjunction with labelled break and continue statements. ECMAScript has no goto statement. A Statement can be part of a LabelledStatement, which itself can be part of a LabelledStatement, and so on. The labels introduced this way are collectively referred to as the “current label set” when describing the semantics of individual statements.

14.13.1 Static Semantics: Early Errors

LabelledItem : FunctionDeclaration
  • It is a Syntax Error if any source text matches this rule.
Note

An alternative definition for this rule is provided in B.3.1.

14.13.2 Static Semantics: IsLabelledFunction ( stmt )

The abstract operation IsLabelledFunction takes argument stmt. It performs the following steps when called:

  1. If stmt is not a LabelledStatement, return false.
  2. Let item be the LabelledItem of stmt.
  3. If item is LabelledItem : FunctionDeclaration , return true.
  4. Let subStmt be the Statement of item.
  5. Return IsLabelledFunction(subStmt).

14.13.3 Runtime Semantics: Evaluation

LabelledStatement : LabelIdentifier : LabelledItem
  1. Let newLabelSet be a new empty List.
  2. Return LabelledEvaluation of this LabelledStatement with argument newLabelSet.

14.13.4 Runtime Semantics: LabelledEvaluation

The syntax-directed operation LabelledEvaluation takes argument labelSet. It is defined piecewise over the following productions:

BreakableStatement : IterationStatement
  1. Let stmtResult be LoopEvaluation of IterationStatement with argument labelSet.
  2. If stmtResult.[[Type]] is break, then
    1. If stmtResult.[[Target]] is empty, then
      1. If stmtResult.[[Value]] is empty, set stmtResult to NormalCompletion(undefined).
      2. Else, set stmtResult to NormalCompletion(stmtResult.[[Value]]).
  3. Return Completion(stmtResult).
BreakableStatement : SwitchStatement
  1. Let stmtResult be the result of evaluating SwitchStatement.
  2. If stmtResult.[[Type]] is break, then
    1. If stmtResult.[[Target]] is empty, then
      1. If stmtResult.[[Value]] is empty, set stmtResult to NormalCompletion(undefined).
      2. Else, set stmtResult to NormalCompletion(stmtResult.[[Value]]).
  3. Return Completion(stmtResult).
Note 1

A BreakableStatement is one that can be exited via an unlabelled BreakStatement.

LabelledStatement : LabelIdentifier : LabelledItem
  1. Let label be the StringValue of LabelIdentifier.
  2. Let newLabelSet be the list-concatenation of labelSet and « label ».
  3. Let stmtResult be LabelledEvaluation of LabelledItem with argument newLabelSet.
  4. If stmtResult.[[Type]] is break and SameValue(stmtResult.[[Target]], label) is true, then
    1. Set stmtResult to NormalCompletion(stmtResult.[[Value]]).
  5. Return Completion(stmtResult).
LabelledItem : FunctionDeclaration
  1. Return the result of evaluating FunctionDeclaration.
Statement : BlockStatement VariableStatement EmptyStatement ExpressionStatement IfStatement ContinueStatement BreakStatement ReturnStatement WithStatement ThrowStatement TryStatement DebuggerStatement
  1. Return the result of evaluating Statement.
Note 2

The only two productions of Statement which have special semantics for LabelledEvaluation are BreakableStatement and LabelledStatement.

14.14 The throw Statement

Syntax

ThrowStatement[Yield, Await] : throw [no LineTerminator here] Expression[+In, ?Yield, ?Await] ;

14.14.1 Runtime Semantics: Evaluation

ThrowStatement : throw Expression ;
  1. Let exprRef be the result of evaluating Expression.
  2. Let exprValue be ? GetValue(exprRef).
  3. Return ThrowCompletion(exprValue).

14.15 The try Statement

Syntax

TryStatement[Yield, Await, Return] : try Block[?Yield, ?Await, ?Return] Catch[?Yield, ?Await, ?Return] try Block[?Yield, ?Await, ?Return] Finally[?Yield, ?Await, ?Return] try Block[?Yield, ?Await, ?Return] Catch[?Yield, ?Await, ?Return] Finally[?Yield, ?Await, ?Return] Catch[Yield, Await, Return] : catch ( CatchParameter[?Yield, ?Await] ) Block[?Yield, ?Await, ?Return] catch Block[?Yield, ?Await, ?Return] Finally[Yield, Await, Return] : finally Block[?Yield, ?Await, ?Return] CatchParameter[Yield, Await] : BindingIdentifier[?Yield, ?Await] BindingPattern[?Yield, ?Await] Note

The try statement encloses a block of code in which an exceptional condition can occur, such as a runtime error or a throw statement. The catch clause provides the exception-handling code. When a catch clause catches an exception, its CatchParameter is bound to that exception.

14.15.1 Static Semantics: Early Errors

Catch : catch ( CatchParameter ) Block Note

An alternative static semantics for this production is given in B.3.4.

14.15.2 Runtime Semantics: CatchClauseEvaluation

The syntax-directed operation CatchClauseEvaluation takes argument thrownValue. It is defined piecewise over the following productions:

Catch : catch ( CatchParameter ) Block
  1. Let oldEnv be the running execution context's LexicalEnvironment.
  2. Let catchEnv be NewDeclarativeEnvironment(oldEnv).
  3. For each element argName of the BoundNames of CatchParameter, do
    1. Perform ! catchEnv.CreateMutableBinding(argName, false).
  4. Set the running execution context's LexicalEnvironment to catchEnv.
  5. Let status be BindingInitialization of CatchParameter with arguments thrownValue and catchEnv.
  6. If status is an abrupt completion, then
    1. Set the running execution context's LexicalEnvironment to oldEnv.
    2. Return Completion(status).
  7. Let B be the result of evaluating Block.
  8. Set the running execution context's LexicalEnvironment to oldEnv.
  9. Return Completion(B).
Catch : catch Block
  1. Return the result of evaluating Block.
Note

No matter how control leaves the Block the LexicalEnvironment is always restored to its former state.

14.15.3 Runtime Semantics: Evaluation

TryStatement : try Block Catch
  1. Let B be the result of evaluating Block.
  2. If B.[[Type]] is throw, let C be CatchClauseEvaluation of Catch with argument B.[[Value]].
  3. Else, let C be B.
  4. Return Completion(UpdateEmpty(C, undefined)).
TryStatement : try Block Finally
  1. Let B be the result of evaluating Block.
  2. Let F be the result of evaluating Finally.
  3. If F.[[Type]] is normal, set F to B.
  4. Return Completion(UpdateEmpty(F, undefined)).
TryStatement : try Block Catch Finally
  1. Let B be the result of evaluating Block.
  2. If B.[[Type]] is throw, let C be CatchClauseEvaluation of Catch with argument B.[[Value]].
  3. Else, let C be B.
  4. Let F be the result of evaluating Finally.
  5. If F.[[Type]] is normal, set F to C.
  6. Return Completion(UpdateEmpty(F, undefined)).

14.16 The debugger Statement

Syntax

DebuggerStatement : debugger ;

14.16.1 Runtime Semantics: Evaluation

Note

Evaluating a DebuggerStatement may allow an implementation to cause a breakpoint when run under a debugger. If a debugger is not present or active this statement has no observable effect.

DebuggerStatement : debugger ;
  1. If an implementation-defined debugging facility is available and enabled, then
    1. Perform an implementation-defined debugging action.
    2. Let result be an implementation-defined Completion value.
  2. Else,
    1. Let result be NormalCompletion(empty).
  3. Return result.