Multipage preference

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 blockValue to Completion(DisposeResources(blockEnv.[[DisposableResourceStack]], blockValue)).
  7. Set the running execution context's LexicalEnvironment to oldEnv.
  8. 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, envRecord )

The abstract operation BlockDeclarationInstantiation takes arguments code (a Parse Node) and envRecord (a Declarative Environment Record) and returns unused. code is the Parse Node corresponding to the body of the block. envRecord 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 decls be the LexicallyScopedDeclarations of code.
  2. Let privateEnv be the running execution context's PrivateEnvironment.
  3. For each element decl of decls, do
    1. For each element name of the BoundNames of decl, do
      1. If IsConstantDeclaration of decl is true, then
        1. Perform ! envRecord.CreateImmutableBinding(name, true).
      2. Else,
        1. If the host is a web browser or otherwise supports Block-Level Function Declarations Web Legacy Compatibility Semantics, then
          1. If ! envRecord.HasBinding(name) is false, then
            1. Perform ! envRecord.CreateMutableBinding(name, false).
        2. Else,
          1. Perform ! envRecord.CreateMutableBinding(name, false).
    2. If decl is either a FunctionDeclaration, a GeneratorDeclaration, an AsyncFunctionDeclaration, or an AsyncGeneratorDeclaration, then
      1. Let funcName be the sole element of the BoundNames of decl.
      2. Let funcObj be InstantiateFunctionObject of decl with arguments envRecord and privateEnv.
      3. If the host is a web browser or otherwise supports Block-Level Function Declarations Web Legacy Compatibility Semantics, then
        1. If the binding for funcName in envRecord is an uninitialized binding, then
          1. Perform ! envRecord.InitializeBinding(funcName, funcObj).
        2. Else,
          1. Assert: decl is a FunctionDeclaration.
          2. Perform ! envRecord.SetMutableBinding(funcName, funcObj, false).
      4. Else,
        1. Perform ! envRecord.InitializeBinding(funcName, funcObj).
  4. Return unused.

14.3 Declarations and the Variable Statement

14.3.1 Let, Const, Using, and Await Using Declarations

Note

let, const, using, and await using 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, +Pattern] ; UsingDeclaration[?In, ?Yield, ?Await] [+Await] AwaitUsingDeclaration[?In, ?Yield] LetOrConst : let const UsingDeclaration[In, Yield, Await] : using [no LineTerminator here] BindingList[?In, ?Yield, ?Await, ~Pattern] ; AwaitUsingDeclaration[In, Yield] : CoverAwaitExpressionAndAwaitUsingDeclarationHead[?Yield] [no LineTerminator here] BindingList[?In, ?Yield, +Await, ~Pattern] ; BindingList[In, Yield, Await, Pattern] : LexicalBinding[?In, ?Yield, ?Await, ?Pattern] BindingList[?In, ?Yield, ?Await, ?Pattern] , LexicalBinding[?In, ?Yield, ?Await, ?Pattern] LexicalBinding[In, Yield, Await, Pattern] : BindingIdentifier[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]opt [+Pattern] BindingPattern[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]

Supplemental Syntax

When processing an instance of the production
AwaitUsingDeclaration : CoverAwaitExpressionAndAwaitUsingDeclarationHead BindingList ;
the interpretation of CoverAwaitExpressionAndAwaitUsingDeclarationHead is refined using the following grammar:

AwaitUsingDeclarationHead : await [no LineTerminator here] using

14.3.1.1 Static Semantics: Early Errors

LexicalDeclaration : LetOrConst BindingList ; UsingDeclaration : using BindingList ; AwaitUsingDeclaration : CoverAwaitExpressionAndAwaitUsingDeclarationHead BindingList ; LexicalBinding : BindingIdentifier Initializeropt

14.3.1.2 Runtime Semantics: Evaluation

LexicalDeclaration : LetOrConst BindingList ;
  1. Perform ? BindingEvaluation of BindingList with argument normal.
  2. Return empty.
UsingDeclaration : using BindingList ;
  1. Perform ? BindingEvaluation of BindingList with argument sync-dispose.
  2. Return empty.
AwaitUsingDeclaration : CoverAwaitExpressionAndAwaitUsingDeclarationHead BindingList ;
  1. Perform ? BindingEvaluation of BindingList with argument async-dispose.
  2. Return empty.

14.3.1.3 Runtime Semantics: BindingEvaluation

The syntax-directed operation BindingEvaluation takes argument kind (normal, sync-dispose, or async-dispose) and returns either a normal completion containing unused or an abrupt completion. It is defined piecewise over the following productions:

BindingList : BindingList , LexicalBinding
  1. Perform ? BindingEvaluation of the derived BindingList with argument kind.
  2. Return ? BindingEvaluation of LexicalBinding with argument kind.
LexicalBinding : BindingIdentifier
  1. Assert: kind is normal.
  2. Let lhs be ! ResolveBinding(StringValue of BindingIdentifier).
  3. Perform ! InitializeReferencedBinding(lhs, undefined).
  4. Return unused.
Note

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

LexicalBinding : BindingIdentifier Initializer
  1. Let name be the StringValue of BindingIdentifier.
  2. Let lhs be ! ResolveBinding(name).
  3. If IsAnonymousFunctionDefinition(Initializer) is true, then
    1. Let value be ? NamedEvaluation of Initializer with argument name.
  4. Else,
    1. Let rhs be ? Evaluation of Initializer.
    2. Let value be ? GetValue(rhs).
  5. If kind is not normal, then
    1. Assert: IsUnresolvableReference(lhs) is false.
    2. Let base be lhs.[[Base]].
    3. Assert: base is a Declarative Environment Record.
    4. Perform ? AddDisposableResource(base.[[DisposableResourceStack]], value, kind).
  6. Perform ? InitializeReferencedBinding(lhs, value).
  7. Return unused.
LexicalBinding : BindingPattern Initializer
  1. Assert: kind is normal.
  2. Let rhs be ? Evaluation of Initializer.
  3. Let value be ? GetValue(rhs).
  4. Let envRecord be the running execution context's LexicalEnvironment.
  5. Return ? BindingInitialization of BindingPattern with arguments value and envRecord.

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 name be the StringValue of BindingIdentifier.
  2. Let lhs be ? ResolveBinding(name).
  3. If IsAnonymousFunctionDefinition(Initializer) is true, then
    1. Let value be ?