14.7 Iteration Statements
Syntax
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:
- If completion.[[Type]] is
normal , returntrue . - If completion.[[Type]] is not
continue , returnfalse . - If completion.[[Target]] is
empty , returntrue . - If completion.[[Target]] is an element of labelSet, return
true . - Return
false .
Within the
14.7.1.2 Runtime Semantics: LoopEvaluation
With parameter labelSet.
- Return ?
DoWhileLoopEvaluation ofDoWhileStatement with argument labelSet.
- Return ?
WhileLoopEvaluation ofWhileStatement with argument labelSet.
- Return ?
ForLoopEvaluation ofForStatement with argument labelSet.
- Return ?
ForInOfLoopEvaluation ofForInOfStatement with argument labelSet.
14.7.2 The do
-while
Statement
Syntax
14.7.2.1 Static Semantics: Early Errors
-
It is a Syntax Error if
IsLabelledFunction (Statement ) istrue .
It is only necessary to apply this rule if the extension specified in
14.7.2.2 Runtime Semantics: DoWhileLoopEvaluation
With parameter labelSet.
- Let V be
undefined . - Repeat,
- Let stmtResult be the result of evaluating
Statement . - If
LoopContinues (stmtResult, labelSet) isfalse , returnCompletion (UpdateEmpty (stmtResult, V)). - If stmtResult.[[Value]] is not
empty , set V to stmtResult.[[Value]]. - Let exprRef be the result of evaluating
Expression . - Let exprValue be ?
GetValue (exprRef). - If !
ToBoolean (exprValue) isfalse , returnNormalCompletion (V).
- Let stmtResult be the result of evaluating
14.7.3 The while
Statement
Syntax
14.7.3.1 Static Semantics: Early Errors
-
It is a Syntax Error if
IsLabelledFunction (Statement ) istrue .
It is only necessary to apply this rule if the extension specified in
14.7.3.2 Runtime Semantics: WhileLoopEvaluation
With parameter labelSet.
- Let V be
undefined . - Repeat,
- Let exprRef be the result of evaluating
Expression . - Let exprValue be ?
GetValue (exprRef). - If !
ToBoolean (exprValue) isfalse , returnNormalCompletion (V). - Let stmtResult be the result of evaluating
Statement . - If
LoopContinues (stmtResult, labelSet) isfalse , returnCompletion (UpdateEmpty (stmtResult, V)). - If stmtResult.[[Value]] is not
empty , set V to stmtResult.[[Value]].
- Let exprRef be the result of evaluating
14.7.4 The for
Statement
Syntax
14.7.4.1 Static Semantics: Early Errors
-
It is a Syntax Error if
IsLabelledFunction (Statement ) istrue .
It is only necessary to apply this rule if the extension specified in
-
It is a Syntax Error if any element of the
BoundNames ofLexicalDeclaration also occurs in theVarDeclaredNames ofStatement .
14.7.4.2 Runtime Semantics: ForLoopEvaluation
With parameter labelSet.
- If the first
Expression is present, then- Let exprRef be the result of evaluating the first
Expression . - Perform ?
GetValue (exprRef).
- Let exprRef be the result of evaluating the first
- Return ?
ForBodyEvaluation (the secondExpression , the thirdExpression ,Statement , « », labelSet).
- Let varDcl be the result of evaluating
VariableDeclarationList . ReturnIfAbrupt (varDcl).- Return ?
ForBodyEvaluation (the firstExpression , the secondExpression ,Statement , « », labelSet).
- Let oldEnv be the
running execution context 's LexicalEnvironment. - Let loopEnv be
NewDeclarativeEnvironment (oldEnv). - Let isConst be
IsConstantDeclaration ofLexicalDeclaration . - Let boundNames be the
BoundNames ofLexicalDeclaration . - For each element dn of boundNames, do
- If isConst is
true , then- Perform ! loopEnv.CreateImmutableBinding(dn,
true ).
- Perform ! loopEnv.CreateImmutableBinding(dn,
- Else,
- Perform ! loopEnv.CreateMutableBinding(dn,
false ).
- Perform ! loopEnv.CreateMutableBinding(dn,
- If isConst is
- Set the
running execution context 's LexicalEnvironment to loopEnv. - Let forDcl be the result of evaluating
LexicalDeclaration . - If forDcl is an
abrupt completion , then- Set the
running execution context 's LexicalEnvironment to oldEnv. - Return
Completion (forDcl).
- Set the
- If isConst is
false , let perIterationLets be boundNames; otherwise let perIterationLets be « ». - Let bodyResult be
ForBodyEvaluation (the firstExpression , the secondExpression ,Statement , perIterationLets, labelSet). - Set the
running execution context 's LexicalEnvironment to oldEnv. - 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:
- Let V be
undefined . - Perform ?
CreatePerIterationEnvironment (perIterationBindings). - Repeat,
- If test is not
[empty] , then- Let testRef be the result of evaluating test.
- Let testValue be ?
GetValue (testRef). - If !
ToBoolean (testValue) isfalse , returnNormalCompletion (V).
- Let result be the result of evaluating stmt.
- If
LoopContinues (result, labelSet) isfalse , returnCompletion (UpdateEmpty (result, V)). - If result.[[Value]] is not
empty , set V to result.[[Value]]. - Perform ?
CreatePerIterationEnvironment (perIterationBindings). - If increment is not
[empty] , then- Let incRef be the result of evaluating increment.
- Perform ?
GetValue (incRef).
- If test is not
14.7.4.4 CreatePerIterationEnvironment ( perIterationBindings )
The abstract operation CreatePerIterationEnvironment takes argument perIterationBindings. It performs the following steps when called:
- If perIterationBindings has any elements, then
- Let lastIterationEnv be the
running execution context 's LexicalEnvironment. - Let outer be lastIterationEnv.[[OuterEnv]].
Assert : outer is notnull .- Let thisIterationEnv be
NewDeclarativeEnvironment (outer). - For each element bn of perIterationBindings, do
- Perform ! thisIterationEnv.CreateMutableBinding(bn,
false ). - Let lastValue be ? lastIterationEnv.GetBindingValue(bn,
true ). - Perform thisIterationEnv.InitializeBinding(bn, lastValue).
- Perform ! thisIterationEnv.CreateMutableBinding(bn,
- Set the
running execution context 's LexicalEnvironment to thisIterationEnv.
- Let lastIterationEnv be the
- Return
undefined .
14.7.5 The for
-in
, for
-of
, and for
-await
-of
Statements
Syntax
This section is extended by Annex
14.7.5.1 Static Semantics: Early Errors
-
It is a Syntax Error if
IsLabelledFunction (Statement ) istrue .
It is only necessary to apply this rule if the extension specified in
If
-
It is a Syntax Error if
LeftHandSideExpression is notcovering anAssignmentPattern . -
All Early Error rules for
AssignmentPattern and its derived productions also apply to theAssignmentPattern that iscovered byLeftHandSideExpression .
If
-
It is a Syntax Error if
AssignmentTargetType ofLeftHandSideExpression is notsimple .
-
It is a Syntax Error if the
BoundNames ofForDeclaration contains"let" . -
It is a Syntax Error if any element of the
BoundNames ofForDeclaration also occurs in theVarDeclaredNames ofStatement . -
It is a Syntax Error if the
BoundNames ofForDeclaration contains any duplicate entries.
14.7.5.2 Static Semantics: IsDestructuring
- If
PrimaryExpression is either anObjectLiteral or anArrayLiteral , returntrue . - Return
false .
- Return
false .
- Return
IsDestructuring ofForBinding .
- Return
false .
- Return
true .
This section is extended by Annex
14.7.5.3 Runtime Semantics: ForDeclarationBindingInitialization
With parameters value and environment.
var
statements and the formal parameter lists of some non-strict functions (see
- Return the result of performing
BindingInitialization forForBinding passing value and environment as the arguments.
14.7.5.4 Runtime Semantics: ForDeclarationBindingInstantiation
With parameter environment.
Assert : environment is adeclarative Environment Record .- For each element name of the
BoundNames ofForBinding , do- If
IsConstantDeclaration ofLetOrConst istrue , then- Perform ! environment.CreateImmutableBinding(name,
true ).
- Perform ! environment.CreateImmutableBinding(name,
- Else,
- Perform ! environment.CreateMutableBinding(name,
false ).
- Perform ! environment.CreateMutableBinding(name,
- If
14.7.5.5 Runtime Semantics: ForInOfLoopEvaluation
With parameter labelSet.
- Let keyResult be ?
ForIn/OfHeadEvaluation (« »,Expression ,enumerate ). - Return ?
ForIn/OfBodyEvaluation (LeftHandSideExpression ,Statement , keyResult,enumerate ,assignment , labelSet).
- Let keyResult be ?
ForIn/OfHeadEvaluation (« »,Expression ,enumerate ). - Return ?
ForIn/OfBodyEvaluation (ForBinding ,Statement , keyResult,enumerate ,varBinding , labelSet).
- Let keyResult be ?
ForIn/OfHeadEvaluation (BoundNames ofForDeclaration ,Expression ,enumerate ). - Return ?
ForIn/OfBodyEvaluation (ForDeclaration ,Statement , keyResult,enumerate ,lexicalBinding , labelSet).
- Let keyResult be ?
ForIn/OfHeadEvaluation (« »,AssignmentExpression ,iterate ). - Return ?
ForIn/OfBodyEvaluation (LeftHandSideExpression ,Statement , keyResult,iterate ,assignment , labelSet).
- Let keyResult be ?
ForIn/OfHeadEvaluation (« »,AssignmentExpression ,iterate ). - Return ?
ForIn/OfBodyEvaluation (ForBinding ,Statement , keyResult,iterate ,varBinding , labelSet).
- Let keyResult be ?
ForIn/OfHeadEvaluation (BoundNames ofForDeclaration ,AssignmentExpression ,iterate ). - Return ?
ForIn/OfBodyEvaluation (ForDeclaration ,Statement , keyResult,iterate ,lexicalBinding , labelSet).
- Let keyResult be ?
ForIn/OfHeadEvaluation (« »,AssignmentExpression ,async-iterate ). - Return ?
ForIn/OfBodyEvaluation (LeftHandSideExpression ,Statement , keyResult,iterate ,assignment , labelSet,async ).
- Let keyResult be ?
ForIn/OfHeadEvaluation (« »,AssignmentExpression ,async-iterate ). - Return ?
ForIn/OfBodyEvaluation (ForBinding ,Statement , keyResult,iterate ,varBinding , labelSet,async ).
- Let keyResult be ?
ForIn/OfHeadEvaluation (BoundNames ofForDeclaration ,AssignmentExpression ,async-iterate ). - Return ?
ForIn/OfBodyEvaluation (ForDeclaration ,Statement , keyResult,iterate ,lexicalBinding , labelSet,async ).
This section is extended by Annex
14.7.5.6 ForIn/OfHeadEvaluation ( uninitializedBoundNames, expr, iterationKind )
The abstract operation ForIn/OfHeadEvaluation takes arguments uninitializedBoundNames, expr, and iterationKind (either
- Let oldEnv be the
running execution context 's LexicalEnvironment. - If uninitializedBoundNames is not an empty
List , thenAssert : uninitializedBoundNames has no duplicate entries.- Let newEnv be
NewDeclarativeEnvironment (oldEnv). - For each String name of uninitializedBoundNames, do
- Perform ! newEnv.CreateMutableBinding(name,
false ).
- Perform ! newEnv.CreateMutableBinding(name,
- Set the
running execution context 's LexicalEnvironment to newEnv.
- Let exprRef be the result of evaluating expr.
- Set the
running execution context 's LexicalEnvironment to oldEnv. - Let exprValue be ?
GetValue (exprRef). - If iterationKind is
enumerate , then- If exprValue is
undefined ornull , then- Return
Completion { [[Type]]:break , [[Value]]:empty , [[Target]]:empty }.
- Return
- Let obj be !
ToObject (exprValue). - Let iterator be ?
EnumerateObjectProperties (obj). - Let nextMethod be !
GetV (iterator,"next" ). - Return the
Record { [[Iterator]]: iterator, [[NextMethod]]: nextMethod, [[Done]]:false }.
- If exprValue is
- Else,
Assert : iterationKind isiterate orasync-iterate .- If iterationKind is
async-iterate , let iteratorHint beasync . - Else, let iteratorHint be
sync . - 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 (either
- If iteratorKind is not present, set iteratorKind to
sync . - Let oldEnv be the
running execution context 's LexicalEnvironment. - Let V be
undefined . - Let destructuring be
IsDestructuring of lhs. - If destructuring is
true and if lhsKind isassignment , thenAssert : lhs is aLeftHandSideExpression .- Let assignmentPattern be the
AssignmentPattern that iscovered by lhs.
- Repeat,
- Let nextResult be ?
Call (iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]]). - If iteratorKind is
async , set nextResult to ?Await (nextResult). - If
Type (nextResult) is not Object, throw aTypeError exception. - Let done be ?
IteratorComplete (nextResult). - If done is
true , returnNormalCompletion (V). - Let nextValue be ?
IteratorValue (nextResult). - If lhsKind is either
assignment orvarBinding , then- If destructuring is
false , then- Let lhsRef be the result of evaluating lhs. (It may be evaluated repeatedly.)
- If destructuring is
- Else,
Assert : lhsKind islexicalBinding .Assert : lhs is aForDeclaration .- Let iterationEnv be
NewDeclarativeEnvironment (oldEnv). - Perform
ForDeclarationBindingInstantiation for lhs passing iterationEnv as the argument. - Set the
running execution context 's LexicalEnvironment to iterationEnv. - If destructuring is
false , thenAssert : lhs binds a single name.- Let lhsName be the sole element of
BoundNames of lhs. - Let lhsRef be !
ResolveBinding (lhsName).
- If destructuring is
false , then- If lhsRef is an
abrupt completion , then- Let status be lhsRef.
- Else if lhsKind is
lexicalBinding , then- Let status be
InitializeReferencedBinding (lhsRef, nextValue).
- Let status be
- Else,
- Let status be
PutValue (lhsRef, nextValue).
- Let status be
- If lhsRef is an
- Else,
- If lhsKind is
assignment , then- Let status be
DestructuringAssignmentEvaluation of assignmentPattern with argument nextValue.
- Let status be
- Else if lhsKind is
varBinding , thenAssert : lhs is aForBinding .- Let status be
BindingInitialization of lhs with arguments nextValue andundefined .
- Else,
Assert : lhsKind islexicalBinding .Assert : lhs is aForDeclaration .- Let status be
ForDeclarationBindingInitialization of lhs with arguments nextValue and iterationEnv.
- If lhsKind is
- If status is an
abrupt completion , then- Set the
running execution context 's LexicalEnvironment to oldEnv. - If iteratorKind is
async , return ?AsyncIteratorClose (iteratorRecord, status). - If iterationKind is
enumerate , then- Return status.
- Else,
Assert : iterationKind isiterate .- Return ?
IteratorClose (iteratorRecord, status).
- Set the
- Let result be the result of evaluating stmt.
- Set the
running execution context 's LexicalEnvironment to oldEnv. - If
LoopContinues (result, labelSet) isfalse , then- If iterationKind is
enumerate , then- Return
Completion (UpdateEmpty (result, V)).
- Return
- Else,
Assert : iterationKind isiterate .- Set status to
UpdateEmpty (result, V). - If iteratorKind is
async , return ?AsyncIteratorClose (iteratorRecord, status). - Return ?
IteratorClose (iteratorRecord, status).
- If iterationKind is
- If result.[[Value]] is not
empty , set V to result.[[Value]].
- Let nextResult be ?
14.7.5.8 Runtime Semantics: Evaluation
- Let bindingId be
StringValue ofBindingIdentifier . - Return ?
ResolveBinding (bindingId).
14.7.5.9 EnumerateObjectProperties ( O )
The abstract operation EnumerateObjectProperties takes argument O. It performs the following steps when called:
Assert :Type (O) is Object.- Return an Iterator object (
27.1.1.2 ) whosenext
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 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 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
- 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.
ECMAScript implementations are not required to implement the algorithm in
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;
}
}
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
14.7.5.10.1 CreateForInIterator ( object )
The abstract operation CreateForInIterator takes argument 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:
Assert :Type (object) is Object.- Let iterator be !
OrdinaryObjectCreate (%ForInIteratorPrototype% , « [[Object]], [[ObjectWasVisited]], [[VisitedKeys]], [[RemainingKeys]] »). - Set iterator.[[Object]] to object.
- Set iterator.[[ObjectWasVisited]] to
false . - Set iterator.[[VisitedKeys]] to a new empty
List . - Set iterator.[[RemainingKeys]] to a new empty
List . - 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 ( )
- Let O be the
this value. Assert :Type (O) is Object.Assert : O has all of the internal slots of a For-In Iterator Instance (14.7.5.10.3 ).- Let object be O.[[Object]].
- Let visited be O.[[VisitedKeys]].
- Let remaining be O.[[RemainingKeys]].
- Repeat,
- If O.[[ObjectWasVisited]] is
false , then- Let keys be ? object.[[OwnPropertyKeys]]().
- For each element key of keys, do
- If
Type (key) is String, then- Append key to remaining.
- If
- Set O.[[ObjectWasVisited]] to
true .
- Repeat, while remaining is not empty,
- Let r be the first element of remaining.
- Remove the first element from remaining.
- If there does not exist an element v of visited such that
SameValue (r, v) istrue , then- Let desc be ? object.[[GetOwnProperty]](r).
- If desc is not
undefined , then- Append r to visited.
- If desc.[[Enumerable]] is
true , returnCreateIterResultObject (r,false ).
- Set object to ? object.[[GetPrototypeOf]]().
- Set O.[[Object]] to object.
- Set O.[[ObjectWasVisited]] to
false . - If object is
null , returnCreateIterResultObject (undefined ,true ).
- If O.[[ObjectWasVisited]] is
14.7.5.10.3 Properties of For-In Iterator Instances
For-In Iterator instances are ordinary objects that inherit properties from the
Internal Slot | Description |
---|---|
[[Object]] | The Object value whose properties are being iterated. |
[[ObjectWasVisited]] |
|
[[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 |