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 empty.
HoistableDeclaration : FunctionDeclaration
  1. Return ? Evaluation of FunctionDeclaration.
BreakableStatement : IterationStatement SwitchStatement
  1. Let newLabelSet be a new empty List.
  2. Return ? 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 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 Completion(Evaluation of 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 ? Evaluation of StatementList.
  2. Let s be Completion(Evaluation of StatementListItem).
  3. Return ? 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) and returns unused. 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 either 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.
  4. Return unused.

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. Perform ? Evaluation of BindingList.
  2. Return empty.
BindingList : BindingList , LexicalBinding
  1. Perform ? Evaluation of BindingList.
  2. Return ? Evaluation of LexicalBinding.
LexicalBinding : BindingIdentifier
  1. Let lhs be ! ResolveBinding(StringValue of BindingIdentifier).
  2. Perform ! InitializeReferencedBinding(lhs, undefined).
  3. Return empty.
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 ? Evaluation of Initializer.
    2. Let value be ? GetValue(rhs).
  5. Perform ! InitializeReferencedBinding(lhs, value).
  6. Return empty.
LexicalBinding : BindingPattern Initializer
  1. Let rhs be ? Evaluation of Initializer.
  2. Let value be ? GetValue(rhs).
  3. Let env be the running execution context's LexicalEnvironment.
  4. Return ? BindingInitialization of BindingPattern with arguments value and env.

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. Perform ? Evaluation of VariableDeclarationList.
  2. Return empty.
VariableDeclarationList : VariableDeclarationList , VariableDeclaration
  1. Perform ? Evaluation of VariableDeclarationList.
  2. Return ? Evaluation of VariableDeclaration.
VariableDeclaration : BindingIdentifier
  1. Return 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 ? Evaluation of Initializer.
    2. Let value be ? GetValue(rhs).
  5. Perform ? PutValue(lhs, value).
  6. Return empty.
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 ? Evaluation of Initializer.
  2. Let rval be ? GetValue(rhs).
  3. Return ? BindingInitialization of BindingPattern with arguments rval and undefined.

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 (an ECMAScript language value) and environment (an Environment Record or undefined) and returns either a normal completion containing a List of property keys or an abrupt completion. It collects a list of all bound property names. 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 sole element of the BoundNames of SingleNameBinding.
  2. Perform ? KeyedBindingInitialization of SingleNameBinding with arguments value, environment, and name.
  3. Return « name ».
BindingProperty : PropertyName : BindingElement
  1. Let P be ? Evaluation of PropertyName.
  2. Perform ? KeyedBindingInitialization of BindingElement with arguments value, environment, and P.
  3. Return « P ».

14.3.3.2 Runtime Semantics: RestBindingInitialization

The syntax-directed operation RestBindingInitialization takes arguments value (an ECMAScript language value), environment (an Environment Record or undefined), 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:

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 (an ECMAScript language value), environment (an Environment Record or undefined), and propertyName (a property key) and returns either a normal completion containing unused or an abrupt completion.

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 ? Evaluation of Initializer.
    2. Set v to ? GetValue(defaultValue).
  3. Return ? BindingInitialization of BindingPattern with arguments v and environment.
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 ? NamedEvaluation of Initializer with argument bindingId.
    2. Else,
      1. Let defaultValue be ? Evaluation of 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 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 ? Evaluation of 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 ? Evaluation of Expression.
  2. Let exprValue be ToBoolean(? GetValue(exprRef)).
  3. If exprValue is true, then
    1. Let stmtCompletion be Completion(Evaluation of the first Statement).
  4. Else,
    1. Let stmtCompletion be Completion(Evaluation of the second Statement).
  5. Return ? UpdateEmpty(stmtCompletion, undefined).
IfStatement : if ( Expression ) Statement
  1. Let exprRef be ? Evaluation of Expression.
  2. Let exprValue be ToBoolean(? GetValue(exprRef)).
  3. If exprValue is false, then
    1. Return undefined.
  4. Else,
    1. Let stmtCompletion be Completion(Evaluation of Statement).
    2. Return ? 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 (a Completion Record) and labelSet (a List of Strings) and returns a Boolean. It performs the following steps when called:

  1. If completion is a normal completion, return true.
  2. If completion is not a continue completion, return false.
  3. If completion.[[Target]] is empty, return true.
  4. If labelSet contains completion.[[Target]], 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 (a List of Strings) and returns either a normal completion containing an ECMAScript language value or an abrupt completion. 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 (a List of Strings) and returns either a normal completion containing an ECMAScript language value or an abrupt completion. It is defined piecewise over the following productions:

DoWhileStatement : do Statement while ( Expression ) ;
  1. Let V be undefined.
  2. Repeat,
    1. Let stmtResult be Completion(Evaluation of Statement).
    2. If LoopContinues(stmtResult, labelSet) is false, return ? UpdateEmpty(stmtResult, V).
    3. If stmtResult.[[Value]] is not empty, set V to stmtResult.[[Value]].
    4. Let exprRef be ? Evaluation of Expression.
    5. Let exprValue be ? GetValue(exprRef).
    6. If ToBoolean(exprValue) is false, return 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 (a List of Strings) and returns either a normal completion containing an ECMAScript language value or an abrupt completion. It is defined piecewise over the following productions:

WhileStatement : while ( Expression ) Statement
  1. Let V be undefined.
  2. Repeat,
    1. Let exprRef be ? Evaluation of Expression.
    2. Let exprValue be ? GetValue(exprRef).
    3. If ToBoolean(exprValue) is false, return V.
    4. Let stmtResult be Completion(Evaluation of Statement).
    5. If LoopContinues(stmtResult, labelSet) is false, return ? 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 (a List of Strings) and returns either a normal completion containing an ECMAScript language value or an abrupt completion. 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 ? Evaluation of the first Expression.
    2. Perform ? GetValue(exprRef).
  2. If the second Expression is present, let test be the second Expression; otherwise, let test be empty.
  3. If the third Expression is present, let increment be the third Expression; otherwise, let increment be empty.
  4. Return ? ForBodyEvaluation(test, increment, Statement, « », labelSet).
ForStatement : for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement
  1. Perform ? Evaluation of VariableDeclarationList.
  2. If the first Expression is present, let test be the first Expression; otherwise, let test be empty.
  3. If the second Expression is present, let increment be the second Expression; otherwise, let increment be empty.
  4. Return ? ForBodyEvaluation(test, increment, 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 Completion(Evaluation of LexicalDeclaration).
  8. If forDcl is an abrupt completion, then
    1. Set the running execution context's LexicalEnvironment to oldEnv.
    2. Return ? forDcl.
  9. If isConst is false, let perIterationLets be boundNames; otherwise let perIterationLets be a new empty List.
  10. If the first Expression is present, let test be the first Expression; otherwise, let test be empty.
  11. If the second Expression is present, let increment be the second Expression; otherwise, let increment be empty.
  12. Let bodyResult be Completion(ForBodyEvaluation(test, increment, Statement, perIterationLets, labelSet)).
  13. Set the running execution context's LexicalEnvironment to oldEnv.
  14. Return ? bodyResult.

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

The abstract operation ForBodyEvaluation takes arguments test (an Expression Parse Node or empty), increment (an Expression Parse Node or empty), stmt (a Statement Parse Node), perIterationBindings (a List of Strings), and labelSet (a List of Strings) and returns either a normal completion containing an ECMAScript language value or an abrupt completion. 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 ? Evaluation of test.
      2. Let testValue be ? GetValue(testRef).
      3. If ToBoolean(testValue) is false, return V.
    2. Let result be Completion(Evaluation of stmt).
    3. If LoopContinues(result, labelSet) is false, return ? 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 ? Evaluation of increment.
      2. Perform ? GetValue(incRef).

14.7.4.4 CreatePerIterationEnvironment ( perIterationBindings )

The abstract operation CreatePerIterationEnvironment takes argument perIterationBindings (a List of Strings) and returns either a normal completion containing unused or a throw completion. 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 unused.

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 and returns a Boolean. 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 (an ECMAScript language value) and environment (an Environment Record or undefined) and returns either a normal completion containing unused or an abrupt completion.

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 ? BindingInitialization of ForBinding with arguments value and environment.

14.7.5.4 Runtime Semantics: ForDeclarationBindingInstantiation

The syntax-directed operation ForDeclarationBindingInstantiation takes argument environment (a Declarative Environment Record) and returns unused. It is defined piecewise over the following productions:

ForDeclaration : LetOrConst ForBinding
  1. 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).
  2. Return unused.

14.7.5.5 Runtime Semantics: ForInOfLoopEvaluation

The syntax-directed operation ForInOfLoopEvaluation takes argument labelSet (a List of Strings) and returns either a normal completion containing an ECMAScript language value or an abrupt completion. 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, var-binding, 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, lexical-binding, 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, var-binding, 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, lexical-binding, 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, var-binding, 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, lexical-binding, 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 (a List of Strings), expr (an Expression Parse Node or an AssignmentExpression Parse Node), and iterationKind (enumerate, iterate, or async-iterate) and returns either a normal completion containing an Iterator Record or an abrupt completion. It performs the following steps when called:

  1. Let oldEnv be the running execution context's LexicalEnvironment.
  2. If uninitializedBoundNames is not empty, 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 Completion(Evaluation of 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 either undefined or null, then
      1. Return Completion Record { [[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 Iterator Record { [[Iterator]]: iterator, [[NextMethod]]: nextMethod, [[Done]]: false }.
  7. Else,
    1. Assert: iterationKind is either iterate or async-iterate.
    2. If iterationKind is async-iterate, let iteratorKind be async.
    3. Else, let iteratorKind be sync.
    4. Return ? GetIterator(exprValue, iteratorKind).

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

The abstract operation ForIn/OfBodyEvaluation takes arguments lhs (a Parse Node), stmt (a Statement Parse Node), iteratorRecord (an Iterator Record), iterationKind (enumerate or iterate), lhsKind (assignment, var-binding, or lexical-binding), and labelSet (a List of Strings) and optional argument iteratorKind (sync or async) and returns either a normal completion containing an ECMAScript language value or an abrupt completion. 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 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 nextResult is not an Object, throw a TypeError exception.
    4. Let done be ? IteratorComplete(nextResult).
    5. If done is true, return V.
    6. Let nextValue be ? IteratorValue(nextResult).
    7. If lhsKind is either assignment or var-binding, then
      1. If destructuring is true, then
        1. If lhsKind is assignment, then
          1. Let status be Completion(DestructuringAssignmentEvaluation of assignmentPattern with argument nextValue).
        2. Else,
          1. Assert: lhsKind is var-binding.
          2. Assert: lhs is a ForBinding.
          3. Let status be Completion(BindingInitialization of lhs with arguments nextValue and undefined).
      2. Else,
        1. Let lhsRef be Completion(Evaluation of lhs). (It may be evaluated repeatedly.)
        2. If lhsRef is an abrupt completion, then
          1. Let status be lhsRef.
        3. Else,
          1. Let status be Completion(PutValue(lhsRef.[[Value]], nextValue)).
    8. Else,
      1. Assert: lhsKind is lexical-binding.
      2. Assert: lhs is a ForDeclaration.
      3. Let iterationEnv be NewDeclarativeEnvironment(oldEnv).
      4. Perform ForDeclarationBindingInstantiation of lhs with argument iterationEnv.
      5. Set the running execution context's LexicalEnvironment to iterationEnv.
      6. If destructuring is true, then
        1. Let status be Completion(ForDeclarationBindingInitialization of lhs with arguments nextValue and iterationEnv).
      7. Else,
        1. Assert: lhs binds a single name.
        2. Let lhsName be the sole element of BoundNames of lhs.
        3. Let lhsRef be ! ResolveBinding(lhsName).
        4. Let status be Completion(InitializeReferencedBinding(lhsRef, nextValue)).
    9. 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).
    10. Let result be Completion(Evaluation of stmt).
    11. Set the running execution context's LexicalEnvironment to oldEnv.
    12. If LoopContinues(result, labelSet) is false, then
      1. If iterationKind is enumerate, then
        1. Return ? UpdateEmpty(result, V).
      2. Else,
        1. Assert: iterationKind is iterate.
        2. Set status to Completion(UpdateEmpty(result, V)).
        3. If iteratorKind is async, return ? AsyncIteratorClose(iteratorRecord, status).
        4. Return ? IteratorClose(iteratorRecord, status).
    13. 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) and returns an Iterator. 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, TypedArray, 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) and returns a For-In Iterator. 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: O is an 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. Repeat,
    1. If O.[[ObjectWasVisited]] is false, then
      1. Let keys be ? object.[[OwnPropertyKeys]]().
      2. For each element key of keys, do
        1. If key is a String, then
          1. Append key to O.[[RemainingKeys]].
      3. Set O.[[ObjectWasVisited]] to true.
    2. Repeat, while O.[[RemainingKeys]] is not empty,
      1. Let r be the first element of O.[[RemainingKeys]].
      2. Remove the first element from O.[[RemainingKeys]].
      3. If there does not exist an element v of O.[[VisitedKeys]] 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 O.[[VisitedKeys]].
          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 39.

Table 39: Internal Slots of For-In Iterator Instances
Internal Slot Type Description
[[Object]] an Object The Object value whose properties are being iterated.
[[ObjectWasVisited]] a Boolean true if the iterator has invoked [[OwnPropertyKeys]] on [[Object]], false otherwise.
[[VisitedKeys]] a List of Strings The values that have been emitted by this iterator thus far.
[[RemainingKeys]] a List of Strings The 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 Record { [[Type]]: continue, [[Value]]: empty, [[Target]]: empty }.
ContinueStatement : continue LabelIdentifier ;
  1. Let label be the StringValue of LabelIdentifier.
  2. Return Completion Record { [[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 Record { [[Type]]: break, [[Value]]: empty, [[Target]]: empty }.
BreakStatement : break LabelIdentifier ;
  1. Let label be the StringValue of LabelIdentifier.
  2. Return Completion Record { [[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 Record { [[Type]]: return, [[Value]]: undefined, [[Target]]: empty }.
ReturnStatement : return Expression ;
  1. Let exprRef be ? Evaluation of Expression.
  2. Let exprValue be ? GetValue(exprRef).
  3. If GetGeneratorKind() is async, set exprValue to ? Await(exprValue).
  4. Return Completion Record { [[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 ? Evaluation of 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 Completion(Evaluation of Statement).
  7. Set the running execution context's LexicalEnvironment to oldEnv.
  8. Return ? 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 (an ECMAScript language value) and returns either a normal completion containing an ECMAScript language value or an abrupt completion. It is defined piecewise over the following productions:

CaseBlock : { }
  1. Return 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 Completion(Evaluation of C).
      2. If R.[[Value]] is not empty, set V to R.[[Value]].
      3. If R is an abrupt completion, return ? UpdateEmpty(R, V).
  5. Return 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 a new empty List.
  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 Completion(Evaluation of C).
      2. If R.[[Value]] is not empty, set V to R.[[Value]].
      3. If R is an abrupt completion, return ? 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 a new empty List.
  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 Completion(Evaluation of CaseClause C).
        2. If R.[[Value]] is not empty, set V to R.[[Value]].
        3. If R is an abrupt completion, return ? UpdateEmpty(R, V).
  10. If foundInB is true, return V.
  11. Let defaultR be Completion(Evaluation of DefaultClause).
  12. If defaultR.[[Value]] is not empty, set V to defaultR.[[Value]].
  13. If defaultR is an abrupt completion, return ? UpdateEmpty(defaultR, 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 Completion(Evaluation of CaseClause C).
    2. If R.[[Value]] is not empty, set V to R.[[Value]].
    3. If R is an abrupt completion, return ? UpdateEmpty(R, V).
  16. Return V.

14.12.3 CaseClauseIsSelected ( C, input )

The abstract operation CaseClauseIsSelected takes arguments C (a CaseClause Parse Node) and input (an ECMAScript language value) and returns either a normal completion containing a Boolean or an abrupt completion. 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 ? Evaluation of 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 ? Evaluation of 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 Completion(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 empty.
CaseClause : case Expression : StatementList
  1. Return ? Evaluation of StatementList.
DefaultClause : default :
  1. Return empty.
DefaultClause : default : StatementList
  1. Return ? Evaluation of 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 is matched by this production.
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 (a Statement Parse Node) and returns a Boolean. 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. Return ? LabelledEvaluation of this LabelledStatement with argument « ».

14.13.4 Runtime Semantics: LabelledEvaluation

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

BreakableStatement : IterationStatement
  1. Let stmtResult be Completion(LoopEvaluation of IterationStatement with argument labelSet).
  2. If stmtResult is a break completion, 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 ? stmtResult.
BreakableStatement : SwitchStatement
  1. Let stmtResult be Completion(Evaluation of SwitchStatement).
  2. If stmtResult is a break completion, 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 ? 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 Completion(LabelledEvaluation of LabelledItem with argument newLabelSet).
  4. If stmtResult is a break completion and stmtResult.[[Target]] is label, then
    1. Set stmtResult to NormalCompletion(stmtResult.[[Value]]).
  5. Return ? stmtResult.
LabelledItem : FunctionDeclaration
  1. Return ? Evaluation of FunctionDeclaration.
Statement : BlockStatement VariableStatement EmptyStatement ExpressionStatement IfStatement ContinueStatement BreakStatement ReturnStatement WithStatement ThrowStatement TryStatement DebuggerStatement
  1. Return ? Evaluation of 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 ? Evaluation of 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 (an ECMAScript language value) and returns either a normal completion containing an ECMAScript language value or an abrupt completion. 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 Completion(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 ? status.
  7. Let B be Completion(Evaluation of Block).
  8. Set the running execution context's LexicalEnvironment to oldEnv.
  9. Return ? B.
Catch : catch Block
  1. Return ? Evaluation of 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 Completion(Evaluation of Block).
  2. If B is a throw completion, let C be Completion(CatchClauseEvaluation of Catch with argument B.[[Value]]).
  3. Else, let C be B.
  4. Return ? UpdateEmpty(C, undefined).
TryStatement : try Block Finally
  1. Let B be Completion(Evaluation of Block).
  2. Let F be Completion(Evaluation of Finally).
  3. If F is a normal completion, set F to B.
  4. Return ? UpdateEmpty(F, undefined).
TryStatement : try Block Catch Finally
  1. Let B be Completion(Evaluation of Block).
  2. If B is a throw completion, let C be Completion(CatchClauseEvaluation of Catch with argument B.[[Value]]).
  3. Else, let C be B.
  4. Let F be Completion(Evaluation of Finally).
  5. If F is a normal completion, set F to C.
  6. Return ? 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. Return a new implementation-defined Completion Record.
  2. Else,
    1. Return empty.