Stage 3 Draft / April 12, 2023
ECMAScript Async Explicit Resource Management
Introduction
This proposal introduces syntax and semantics around explicit resource management.
See the proposal repository for background material and discussion.
This document includes specification text also proposed in Explicit Resource Management to provide a comprehensive, holistic specification.
1 ECMAScript Data Types and Values
1.1 ECMAScript Language Types
1.1.1 The Symbol Type
1.1.1.1 Well-Known Symbols
Table 1: Well-known Symbols
Specification Name
[[Description]]
Value and Purpose
|
@@asyncDispose
|
"Symbol.asyncDispose"
|
A method that performs explicit resource cleanup on an object. Called by the semantics of the await using declaration and AsyncDisposableStack objects.
|
|
@@dispose
|
"Symbol.dispose"
|
A method that performs explicit resource cleanup on an object. Called by the semantics of the using declaration and DisposableStack objects.
|
1.1.2 The Object Type
1.1.2.1 Well-Known Intrinsic Objects
Table 2: Well-Known Intrinsic Objects
1.2 ECMAScript Specification Types
1.2.1 The Reference Record Specification Type
1.2.1.1 InitializeReferencedBinding ( V, W, hint )
The abstract operation InitializeReferencedBinding takes arguments V, W, and hint (one of normal, sync-dispose, or async-dispose) and returns either a normal completion containing unused or an abrupt completion. It performs the following steps when called:
- ReturnIfAbrupt(V).
- ReturnIfAbrupt(W).
- Assert: V is a Reference Record.
- Assert: IsUnresolvableReference(V) is false.
- Let base be V.[[Base]].
- Assert: base is an Environment Record.
- Return ? base.InitializeBinding(V.[[ReferencedName]], W, hint).
2 Abstract Operations
2.1 DisposeCapability Records
A DisposeCapability Record is a Record value used to contain a List of DisposableResource Records that are disposed together. DisposeCapability Records are produced by the NewDisposeCapability abstract operation.
DisposeCapability Records have the fields listed in Table 3:
Table 3:
DisposeCapability Record Fields
Field Name
Value
Meaning
|
[[DisposableResourceStack]]
|
a List of DisposableResource Records
|
The resources to be disposed. Resources are added in the order they are initialized, and are disposed in reverse order.
|
2.2 Operations on Disposable Objects
See Common Resource Management Interfaces (12.2.1).
2.2.1 DisposableResource Records
A DisposableResource Record is a Record value used to encapsulate a disposable object along with the method used to dispose the object. DisposableResource Records are produced by the CreateDisposableResource abstract operation.
DisposableResource Records have the fields listed in Table 4:
Table 4:
DisposableResource Record Fields
Field Name
Value
Meaning
|
[[ResourceValue]]
|
An Object or undefined.
|
The value to be disposed.
|
|
[[Hint]]
|
sync-dispose or async-dispose.
|
Indicates whether the resource was added by a using declaration or DisposableStack object (sync-dispose) or a await using declaration or AsyncDisposableStack object (async-dispose).
|
|
[[DisposeMethod]]
|
A function object or undefined.
|
A function object that will be called with [[ResourceValue]] as its this value when the resource disposed.
|
2.2.2 NewDisposeCapability ( )
The abstract operation NewDisposeCapability takes no arguments and returns a DisposeCapability Record. It performs the following steps when called:
- Let stack be a new empty List.
- Return the DisposeCapability Record { [[DisposableResourceStack]]: stack }.
2.2.3 AddDisposableResource ( disposeCapability, V, hint [ , method ] )
The abstract operation AddDisposableResource takes arguments disposeCapability (a DisposeCapability Record), V (an ECMAScript language value), and hint (either sync-dispose or async-dispose) and optional argument method (a function object) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:
- If method is not present then,
- If V is either null or undefined and hint is sync-dispose, then
- Return unused.
- Let resource be ? CreateDisposableResource(V, hint).
- Else,
- If V is either null or undefined, then
- Let resource be ? CreateDisposableResource(undefined, hint, method).
- Else,
- If V is not an Object, throw a TypeError exception.
- Let resource be ? CreateDisposableResource(V, hint, method).
- Append resource to disposeCapability.[[DisposableResourceStack]].
- Return unused.
2.2.4 CreateDisposableResource ( V, hint [ , method ] )
The abstract operation CreateDisposableResource takes arguments V (an ECMAScript language value) and hint (either sync-dispose or async-dispose) and optional argument method (a function object) and returns either a normal completion containing a DisposableResource Record or a throw completion. It performs the following steps when called:
- If method is not present, then
- If V is either null or undefined, then
- Set V to undefined.
- Set method to undefined.
- Else,
- If V is not an Object, throw a TypeError exception.
- Set method to ? GetDisposeMethod(V, hint).
- If method is undefined, throw a TypeError exception.
- Else,
- If IsCallable(method) is false, throw a TypeError exception.
- Return the DisposableResource Record { [[ResourceValue]]: V, [[Hint]]: hint, [[DisposeMethod]]: method }.
2.2.5 GetDisposeMethod ( V, hint )
The abstract operation GetDisposeMethod takes arguments V (an Object) and hint (either sync-dispose or async-dispose) and returns either a normal completion containing either a function object or undefined, or a throw completion. It performs the following steps when called:
- If hint is async-dispose, then
- Let method be ? GetMethod(V, @@asyncDispose).
- If method is undefined, then
- Set method to ? GetMethod(V, @@dispose).
- Else,
- Let method be ? GetMethod(V, @@dispose).
- Return method.
2.2.6 Dispose ( V, hint, method )
The abstract operation Dispose takes arguments V (an Object or undefined), hint (either sync-dispose or async-dispose), and method (a function object or undefined) and returns either a normal completion containing undefined or a throw completion. It performs the following steps when called:
- If method is undefined, let result be undefined.
- Else, let result be ? Call(method, V).
- If hint is async-dispose, then
- Perform ? Await(result).
- Return undefined.
2.2.7 DisposeResources ( disposeCapability, completion )
The abstract operation DisposeResources takes arguments disposeCapability (a DisposeCapability Record) and completion (either a normal completion containing either an ECMAScript language value or empty, or an abrupt completion) and returns either a normal completion containing either an ECMAScript language value or empty, or an abrupt completion. It performs the following steps when called:
- For each resource of disposeCapability.[[DisposableResourceStack]], in reverse List order, do
- Let result be Dispose(resource.[[ResourceValue]], resource.[[Hint]], resource.[[DisposeMethod]]).
- If result.[[Type]] is throw, then
- If completion.[[Type]] is throw, then
- Set result to result.[[Value]].
- Let suppressed be completion.[[Value]].
- Let error be a newly created SuppressedError object.
- Perform ! CreateNonEnumerableDataPropertyOrThrow(error, "error", result).
- Perform ! CreateNonEnumerableDataPropertyOrThrow(error, "suppressed", suppressed).
- Set completion to ThrowCompletion(error).
- Else,
- Set completion to result.
- Return completion.
3 Syntax-Directed Operations
3.1 Scope Analysis
3.1.1 Static Semantics: BoundNames
The syntax-directed operation BoundNames takes no arguments and returns a List of Strings.
Note
"*default*" is used within this specification as a synthetic name for a module's default export when it does not have another name. An entry in the module's [[Environment]] is created with that name and holds the corresponding value, and resolving the export named "default" by calling ResolveExport ( exportName [ , resolveSet ] ) for the module will return a ResolvedBinding Record whose [[BindingName]] is "*default*", which will then resolve in the module's [[Environment]] to the above-mentioned value. This is done only for ease of specification, so that anonymous default exports can be resolved like any other export. The string "*default*" is never accessible to user code or to the module linking algorithm.
It is defined piecewise over the following productions:
BindingIdentifier :
Identifier
- Return a List whose sole element is the StringValue of Identifier.
BindingIdentifier : yield
- Return « "yield" ».
BindingIdentifier : await
- Return « "await" ».
LexicalDeclaration :
LetOrConst
BindingList
;
- Return the BoundNames of BindingList.
UsingDeclaration :
using
BindingList
;
AwaitUsingDeclaration :
CoverAwaitExpressionAndAwaitUsingDeclarationHead
BindingList
;
- Return the BoundNames of BindingList.
BindingList :
BindingList
,
LexicalBinding
- Let names1 be the BoundNames of BindingList.
- Let names2 be the BoundNames of LexicalBinding.
- Return the list-concatenation of names1 and names2.
LexicalBinding :
BindingIdentifier
Initializeropt
- Return the BoundNames of BindingIdentifier.
LexicalBinding :
BindingPattern
Initializer
- Return the BoundNames of BindingPattern.
VariableDeclarationList :
VariableDeclarationList
,
VariableDeclaration
- Let names1 be BoundNames of VariableDeclarationList.
- Let names2 be BoundNames of VariableDeclaration.
- Return the list-concatenation of names1 and names2.
VariableDeclaration :
BindingIdentifier
Initializeropt
- Return the BoundNames of BindingIdentifier.
VariableDeclaration :
BindingPattern
Initializer
- Return the BoundNames of BindingPattern.
ObjectBindingPattern :
{
}
- Return a new empty List.
ObjectBindingPattern :
{
BindingPropertyList
,
BindingRestProperty
}
- Let names1 be BoundNames of BindingPropertyList.
- Let names2 be BoundNames of BindingRestProperty.
- Return the list-concatenation of names1 and names2.
ArrayBindingPattern :
[
Elisionopt
]
- Return a new empty List.
ArrayBindingPattern :
[
Elisionopt
BindingRestElement
]
- Return the BoundNames of BindingRestElement.
ArrayBindingPattern :
[
BindingElementList
,
Elisionopt
]
- Return the BoundNames of BindingElementList.
ArrayBindingPattern :
[
BindingElementList
,
Elisionopt
BindingRestElement
]
- Let names1 be BoundNames of BindingElementList.
- Let names2 be BoundNames of BindingRestElement.
- Return the list-concatenation of names1 and names2.
BindingPropertyList :
BindingPropertyList
,
BindingProperty
- Let names1 be BoundNames of BindingPropertyList.
- Let names2 be BoundNames of BindingProperty.
- Return the list-concatenation of names1 and names2.
BindingElementList :
BindingElementList
,
BindingElisionElement
- Let names1 be BoundNames of BindingElementList.
- Let names2 be BoundNames of BindingElisionElement.
- Return the list-concatenation of names1 and names2.
BindingElisionElement :
Elisionopt
BindingElement
- Return BoundNames of BindingElement.
BindingProperty :
PropertyName
:
BindingElement
- Return the BoundNames of BindingElement.
SingleNameBinding :
BindingIdentifier
Initializeropt
- Return the BoundNames of BindingIdentifier.
BindingElement :
BindingPattern
Initializeropt
- Return the BoundNames of BindingPattern.
ForDeclaration :
LetOrConst
ForBinding
- Return the BoundNames of ForBinding.
FunctionDeclaration :
function
BindingIdentifier
(
FormalParameters
)
{
FunctionBody
}
- Return the BoundNames of BindingIdentifier.
FunctionDeclaration :
function
(
FormalParameters
)
{
FunctionBody
}
- Return « "*default*" ».
FormalParameters : [empty]
- Return a new empty List.
FormalParameters :
FormalParameterList
,
FunctionRestParameter
- Let names1 be BoundNames of FormalParameterList.
- Let names2 be BoundNames of FunctionRestParameter.
- Return the list-concatenation of names1 and names2.
FormalParameterList :
FormalParameterList
,
FormalParameter
- Let names1 be BoundNames of FormalParameterList.
- Let names2 be BoundNames of FormalParameter.
- Return the list-concatenation of names1 and names2.
ArrowParameters :
CoverParenthesizedExpressionAndArrowParameterList
- Let formals be the ArrowFormalParameters that is covered by CoverParenthesizedExpressionAndArrowParameterList.
- Return the BoundNames of formals.
GeneratorDeclaration :
function
*
BindingIdentifier
(
FormalParameters
)
{
GeneratorBody
}
- Return the BoundNames of BindingIdentifier.
GeneratorDeclaration :
function
*
(
FormalParameters
)
{
GeneratorBody
}
- Return « "*default*" ».
AsyncGeneratorDeclaration :
async
function
*
BindingIdentifier
(
FormalParameters
)
{
AsyncGeneratorBody
}
- Return the BoundNames of BindingIdentifier.
AsyncGeneratorDeclaration :
async
function
*
(
FormalParameters
)
{
AsyncGeneratorBody
}
- Return « "*default*" ».
ClassDeclaration :
class
BindingIdentifier
ClassTail
- Return the BoundNames of BindingIdentifier.
ClassDeclaration :
class
ClassTail
- Return « "*default*" ».
AsyncFunctionDeclaration :
async
function
BindingIdentifier
(
FormalParameters
)
{
AsyncFunctionBody
}
- Return the BoundNames of BindingIdentifier.
AsyncFunctionDeclaration :
async
function
(
FormalParameters
)
{
AsyncFunctionBody
}
- Return « "*default*" ».
CoverCallExpressionAndAsyncArrowHead :
MemberExpression
Arguments
- Let head be the AsyncArrowHead that is covered by CoverCallExpressionAndAsyncArrowHead.
- Return the BoundNames of head.
ImportDeclaration :
import
ImportClause
FromClause
;
- Return the BoundNames of ImportClause.
ImportDeclaration :
import
ModuleSpecifier
;
- Return a new empty List.
ImportClause :
ImportedDefaultBinding
,
NameSpaceImport
- Let names1 be the BoundNames of ImportedDefaultBinding.
- Let names2 be the BoundNames of NameSpaceImport.
- Return the list-concatenation of names1 and names2.
ImportClause :
ImportedDefaultBinding
,
NamedImports
- Let names1 be the BoundNames of ImportedDefaultBinding.
- Let names2 be the BoundNames of NamedImports.
- Return the list-concatenation of names1 and names2.
NamedImports :
{
}
- Return a new empty List.
ImportsList :
ImportsList
,
ImportSpecifier
- Let names1 be the BoundNames of ImportsList.
- Let names2 be the BoundNames of ImportSpecifier.
- Return the list-concatenation of names1 and names2.
ImportSpecifier :
ModuleExportName
as
ImportedBinding
- Return the BoundNames of ImportedBinding.
ExportDeclaration :
export
ExportFromClause
FromClause
;
export
NamedExports
;
- Return a new empty List.
ExportDeclaration :
export
VariableStatement
- Return the BoundNames of VariableStatement.
ExportDeclaration :
export
Declaration
- Return the BoundNames of Declaration.
ExportDeclaration :
export
default
HoistableDeclaration
- Let declarationNames be the BoundNames of HoistableDeclaration.
- If declarationNames does not include the element "*default*", append "*default*" to declarationNames.
- Return declarationNames.
ExportDeclaration :
export
default
ClassDeclaration
- Let declarationNames be the BoundNames of ClassDeclaration.
- If declarationNames does not include the element "*default*", append "*default*" to declarationNames.
- Return declarationNames.
ExportDeclaration :
export
default
AssignmentExpression
;
- Return « "*default*" ».
3.1.2 Static Semantics: IsConstantDeclaration
The syntax-directed operation IsConstantDeclaration takes no arguments and returns a Boolean. It is defined piecewise over the following productions:
LexicalDeclaration :
LetOrConst
BindingList
;
- Return IsConstantDeclaration of LetOrConst.
LetOrConst : let
- Return false.
LetOrConst : const
- Return true.
UsingDeclaration :
using
BindingList
;
AwaitUsingDeclaration :
CoverAwaitExpressionAndAwaitUsingDeclarationHead
BindingList
;
- Return true.
FunctionDeclaration :
function
BindingIdentifier
(
FormalParameters
)
{
FunctionBody
}
function
(
FormalParameters
)
{
FunctionBody
}
GeneratorDeclaration :
function
*
BindingIdentifier
(
FormalParameters
)
{
GeneratorBody
}
function
*
(
FormalParameters
)
{
GeneratorBody
}
AsyncGeneratorDeclaration :
async
function
*
BindingIdentifier
(
FormalParameters
)
{
AsyncGeneratorBody
}
async
function
*
(
FormalParameters
)
{
AsyncGeneratorBody
}
AsyncFunctionDeclaration :
async
function
BindingIdentifier
(
FormalParameters
)
{
AsyncFunctionBody
}
async
function
(
FormalParameters
)
{
AsyncFunctionBody
}
- Return false.
ClassDeclaration :
class
BindingIdentifier
ClassTail
class
ClassTail
- Return false.
ExportDeclaration :
export
ExportFromClause
FromClause
;
export
NamedExports
;
export
default
AssignmentExpression
;
- Return false.
Note
It is not necessary to treat export default AssignmentExpression as a constant declaration because there is no syntax that permits assignment to the internal bound name used to reference a module's default object.
3.1.3 Static Semantics: IsUsingDeclaration
The syntax-directed operation IsUsingDeclaration takes no arguments and returns a Boolean. It is defined piecewise over the following productions:
LexicalDeclaration :
LetOrConst
BindingList
;
- Return false.
UsingDeclaration :
using
BindingList
;
AwaitUsingDeclaration :
CoverAwaitExpressionAndAwaitUsingDeclarationHead
BindingList
;
- Return true.
ForDeclaration :
LetOrConst
ForBinding
- Return false.
ForDeclaration :
using
ForBinding
await
using
ForBinding
- Return true.
FunctionDeclaration :
function
BindingIdentifier
(
FormalParameters
)
{
FunctionBody
}
function
(
FormalParameters
)
{
FunctionBody
}
GeneratorDeclaration :
function
*
BindingIdentifier
(
FormalParameters
)
{
GeneratorBody
}
function
*
(
FormalParameters
)
{
GeneratorBody
}
AsyncGeneratorDeclaration :
async
function
*
BindingIdentifier
(
FormalParameters
)
{
AsyncGeneratorBody
}
async
function
*
(
FormalParameters
)
{
AsyncGeneratorBody
}
AsyncFunctionDeclaration :
async
function
BindingIdentifier
(
FormalParameters
)
{
AsyncFunctionBody
}
async
function
(
FormalParameters
)
{
AsyncFunctionBody
}
- Return false.
ClassDeclaration :
class
BindingIdentifier
ClassTail
class
ClassTail
- Return false.
ExportDeclaration :
export
ExportFromClause
FromClause
;
export
NamedExports
;
export
default
AssignmentExpression
;
- Return false.
3.1.4 Static Semantics: IsAwaitUsingDeclaration
The syntax-directed operation IsAwaitUsingDeclaration takes no arguments and returns a Boolean. It is defined piecewise over the following productions:
LexicalDeclaration :
LetOrConst
BindingList
;
- Return false.
UsingDeclaration :
using
BindingList
;
- Return false.
AwaitUsingDeclaration :
CoverAwaitExpressionAndAwaitUsingDeclarationHead
BindingList
;
- Return true.
ForDeclaration :
LetOrConst
ForBinding
- Return false.
ForDeclaration :
using
ForBinding
- Return false.
ForDeclaration :
await
using
ForBinding
- Return true.
FunctionDeclaration :
function
BindingIdentifier
(
FormalParameters
)
{
FunctionBody
}
function
(
FormalParameters
)
{
FunctionBody
}
GeneratorDeclaration :
function
*
BindingIdentifier
(
FormalParameters
)
{
GeneratorBody
}
function
*
(
FormalParameters
)
{
GeneratorBody
}
AsyncGeneratorDeclaration :
async
function
*
BindingIdentifier
(
FormalParameters
)
{
AsyncGeneratorBody
}
async
function
*
(
FormalParameters
)
{
AsyncGeneratorBody
}
AsyncFunctionDeclaration :
async
function
BindingIdentifier
(
FormalParameters
)
{
AsyncFunctionBody
}
async
function
(
FormalParameters
)
{
AsyncFunctionBody
}
- Return false.
ClassDeclaration :
class
BindingIdentifier
ClassTail
class
ClassTail
- Return false.
ExportDeclaration :
export
ExportFromClause
FromClause
;
export
NamedExports
;
export
default
AssignmentExpression
;
- Return false.
3.2 Function Name Inference
3.2.1 Static Semantics: IsFunctionDefinition
The syntax-directed operation IsFunctionDefinition takes no arguments and returns a Boolean. It is defined piecewise over the following productions:
PrimaryExpression :
CoverParenthesizedExpressionAndArrowParameterList
- Let expr be the ParenthesizedExpression that is covered by CoverParenthesizedExpressionAndArrowParameterList.
- Return IsFunctionDefinition of expr.
PrimaryExpression :
this
IdentifierReference
Literal
ArrayLiteral
ObjectLiteral
RegularExpressionLiteral
TemplateLiteral
MemberExpression :
MemberExpression
[
Expression
]
MemberExpression
.
IdentifierName
MemberExpression
TemplateLiteral
SuperProperty
MetaProperty
new
MemberExpression
Arguments
MemberExpression
.
PrivateIdentifier
NewExpression :
new
NewExpression
LeftHandSideExpression :
CallExpression
OptionalExpression
UpdateExpression :
LeftHandSideExpression
++
LeftHandSideExpression
--
++
UnaryExpression
--
UnaryExpression
UnaryExpression :
delete
UnaryExpression
void
UnaryExpression
typeof
UnaryExpression
+
UnaryExpression
-
UnaryExpression
~
UnaryExpression
!
UnaryExpression
AwaitExpression
CoverAwaitExpressionAndAwaitUsingDeclarationHead
AwaitExpression :
await
UnaryExpression
ExponentiationExpression :
UpdateExpression
**
ExponentiationExpression
MultiplicativeExpression :
MultiplicativeExpression
MultiplicativeOperator
ExponentiationExpression
AdditiveExpression :
AdditiveExpression
+
MultiplicativeExpression
AdditiveExpression
-
MultiplicativeExpression
ShiftExpression :
ShiftExpression
<<
AdditiveExpression
ShiftExpression
>>
AdditiveExpression
ShiftExpression
>>>
AdditiveExpression
RelationalExpression :
RelationalExpression
<
ShiftExpression
RelationalExpression
>
ShiftExpression
RelationalExpression
<=
ShiftExpression
RelationalExpression
>=
ShiftExpression
RelationalExpression
instanceof
ShiftExpression
RelationalExpression
in
ShiftExpression
PrivateIdentifier
in
ShiftExpression
EqualityExpression :
EqualityExpression
==
RelationalExpression
EqualityExpression
!=
RelationalExpression
EqualityExpression
===
RelationalExpression
EqualityExpression
!==
RelationalExpression
BitwiseANDExpression :
BitwiseANDExpression
&
EqualityExpression
BitwiseXORExpression :
BitwiseXORExpression
^
BitwiseANDExpression
BitwiseORExpression :
BitwiseORExpression
|
BitwiseXORExpression
LogicalANDExpression :
LogicalANDExpression
&&
BitwiseORExpression
LogicalORExpression :
LogicalORExpression
||
LogicalANDExpression
CoalesceExpression :
CoalesceExpressionHead
??
BitwiseORExpression
ConditionalExpression :
ShortCircuitExpression
?
AssignmentExpression
:
AssignmentExpression
AssignmentExpression :
YieldExpression
LeftHandSideExpression
=
AssignmentExpression
LeftHandSideExpression
AssignmentOperator
AssignmentExpression
LeftHandSideExpression
&&=
AssignmentExpression
LeftHandSideExpression
||=
AssignmentExpression
LeftHandSideExpression
??=
AssignmentExpression
Expression :
Expression
,
AssignmentExpression
- Return false.
AssignmentExpression :
ArrowFunction
AsyncArrowFunction
FunctionExpression :
function
BindingIdentifieropt
(
FormalParameters
)
{
FunctionBody
}
GeneratorExpression :
function
*
BindingIdentifieropt
(
FormalParameters
)
{
GeneratorBody
}
AsyncGeneratorExpression :
async
function
*
BindingIdentifieropt
(
FormalParameters
)
{
AsyncGeneratorBody
}
AsyncFunctionExpression :
async
function
BindingIdentifieropt
(
FormalParameters
)
{
AsyncFunctionBody
}
ClassExpression :
class
BindingIdentifieropt
ClassTail
- Return true.
3.3 Miscellaneous
3.3.1 Runtime Semantics: IteratorBindingInitialization
The syntax-directed operation IteratorBindingInitialization takes arguments iteratorRecord and environment 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:
ArrayBindingPattern :
[
]
- Return unused.
ArrayBindingPattern :
[
Elision
]
- Return ? IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord.
ArrayBindingPattern :
[
Elisionopt
BindingRestElement
]
- If Elision is present, then
- Perform ? IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord.
- Return ? IteratorBindingInitialization of BindingRestElement with arguments iteratorRecord and environment.
ArrayBindingPattern :
[
BindingElementList
,
Elision
]
- Perform ? IteratorBindingInitialization of BindingElementList with arguments iteratorRecord and environment.
- Return ? IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord.
ArrayBindingPattern :
[
BindingElementList
,
Elisionopt
BindingRestElement
]
- Perform ? IteratorBindingInitialization of BindingElementList with arguments iteratorRecord and environment.
- If Elision is present, then
- Perform ? IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord.
- Return ? IteratorBindingInitialization of BindingRestElement with arguments iteratorRecord and environment.
BindingElementList :
BindingElementList
,
BindingElisionElement
- Perform ? IteratorBindingInitialization of BindingElementList with arguments iteratorRecord and environment.
- Return ? IteratorBindingInitialization of BindingElisionElement with arguments iteratorRecord and environment.
BindingElisionElement :
Elision
BindingElement
- Perform ? IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord.
- Return ? IteratorBindingInitialization of BindingElement with arguments iteratorRecord and environment.
SingleNameBinding :
BindingIdentifier
Initializeropt
- Let bindingId be StringValue of BindingIdentifier.
- Let lhs be ? ResolveBinding(bindingId, environment).
- Let v be undefined.
- If iteratorRecord.[[Done]] is false, then
- Let next be Completion(IteratorStep(iteratorRecord)).
- If next is an abrupt completion, set iteratorRecord.[[Done]] to true.
- ReturnIfAbrupt(next).
- If next is false, set iteratorRecord.[[Done]] to true.
- Else,
- Set v to Completion(IteratorValue(next)).
- If v is an abrupt completion, set iteratorRecord.[[Done]] to true.
- ReturnIfAbrupt(v).
- If Initializer is present and v is undefined, then
- If IsAnonymousFunctionDefinition(Initializer) is true, then
- Set v to ? NamedEvaluation of Initializer with argument bindingId.
- Else,
- Let defaultValue be ? Evaluation of Initializer.
- Set v to ? GetValue(defaultValue).
- If environment is undefined, return ? PutValue(lhs, v).
- Return ? InitializeReferencedBinding(lhs, v, normal).
BindingElement :
BindingPattern
Initializeropt
- Let v be undefined.
- If iteratorRecord.[[Done]] is false, then
- Let next be Completion(IteratorStep(iteratorRecord)).
- If next is an abrupt completion, set iteratorRecord.[[Done]] to true.
- ReturnIfAbrupt(next).
- If next is false, set iteratorRecord.[[Done]] to true.
- Else,
- Set v to Completion(IteratorValue(next)).
- If v is an abrupt completion, set iteratorRecord.[[Done]] to true.
- ReturnIfAbrupt(v).
- If Initializer is present and v is undefined, then
- Let defaultValue be ? Evaluation of Initializer.
- Set v to ? GetValue(defaultValue).
- Return ? BindingInitialization of BindingPattern with arguments v and environment.
BindingRestElement :
...
BindingIdentifier
- Let lhs be ? ResolveBinding(StringValue of BindingIdentifier, environment).
- Let A be ! ArrayCreate(0).
- Let n be 0.
- Repeat,
- If iteratorRecord.[[Done]] is false, then
- Let next be Completion(IteratorStep(iteratorRecord)).
- If next is an abrupt completion, set iteratorRecord.[[Done]] to true.
- ReturnIfAbrupt(next).
- If next is false, set iteratorRecord.[[Done]] to true.
- If iteratorRecord.[[Done]] is true, then
- If environment is undefined, return ? PutValue(lhs, A).
- Return ? InitializeReferencedBinding(lhs, A, normal).
- Let nextValue be Completion(IteratorValue(next)).
- If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true.
- ReturnIfAbrupt(nextValue).
- Perform ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(n)), nextValue).
- Set n to n + 1.
BindingRestElement :
...
BindingPattern
- Let A be ! ArrayCreate(0).
- Let n be 0.
- Repeat,
- If iteratorRecord.[[Done]] is false, then
- Let next be Completion(IteratorStep(iteratorRecord)).
- If next is an abrupt completion, set iteratorRecord.[[Done]] to true.
- ReturnIfAbrupt(next).
- If next is false, set iteratorRecord.[[Done]] to true.
- If iteratorRecord.[[Done]] is true, then
- Return ? BindingInitialization of BindingPattern with arguments A and environment.
- Let nextValue be Completion(IteratorValue(next)).
- If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true.
- ReturnIfAbrupt(nextValue).
- Perform ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(n)), nextValue).
- Set n to n + 1.
FormalParameters : [empty]
- Return unused.
FormalParameters :
FormalParameterList
,
FunctionRestParameter
- Perform ? IteratorBindingInitialization of FormalParameterList with arguments iteratorRecord and environment.
- Return ? IteratorBindingInitialization of FunctionRestParameter with arguments iteratorRecord and environment.
FormalParameterList :
FormalParameterList
,
FormalParameter
- Perform ? IteratorBindingInitialization of FormalParameterList with arguments iteratorRecord and environment.
- Return ? IteratorBindingInitialization of FormalParameter with arguments iteratorRecord and environment.
ArrowParameters :
BindingIdentifier
- Let v be undefined.
- Assert: iteratorRecord.[[Done]] is false.
- Let next be Completion(IteratorStep(iteratorRecord)).
- If next is an abrupt completion, set iteratorRecord.[[Done]] to true.
- ReturnIfAbrupt(next).
- If next is false, set iteratorRecord.[[Done]] to true.
- Else,
- Set v to Completion(IteratorValue(next)).
- If v is an abrupt completion, set iteratorRecord.[[Done]] to true.
- ReturnIfAbrupt(v).
- Return ? BindingInitialization of BindingIdentifier with arguments v and environment.
ArrowParameters :
CoverParenthesizedExpressionAndArrowParameterList
- Let formals be the ArrowFormalParameters that is covered by CoverParenthesizedExpressionAndArrowParameterList.
- Return ? IteratorBindingInitialization of formals with arguments iteratorRecord and environment.
AsyncArrowBindingIdentifier :
BindingIdentifier
- Let v be undefined.
- Assert: iteratorRecord.[[Done]] is false.
- Let next be Completion(IteratorStep(iteratorRecord)).
- If next is an abrupt completion, set iteratorRecord.[[Done]] to true.
- ReturnIfAbrupt(next).
- If next is false, set iteratorRecord.[[Done]] to true.
- Else,
- Set v to Completion(IteratorValue(next)).
- If v is an abrupt completion, set iteratorRecord.[[Done]] to true.
- ReturnIfAbrupt(v).
- Return ? BindingInitialization of BindingIdentifier with arguments v and environment.
3.3.2 Static Semantics: AssignmentTargetType
The syntax-directed operation AssignmentTargetType takes no arguments and returns simple or invalid. It is defined piecewise over the following productions:
IdentifierReference :
Identifier
- If this IdentifierReference is contained in strict mode code and StringValue of Identifier is "eval" or "arguments", return invalid.
- Return simple.
IdentifierReference :
yield
await
CallExpression :
CallExpression
[
Expression
]
CallExpression
.
IdentifierName
CallExpression
.
PrivateIdentifier
MemberExpression :
MemberExpression
[
Expression
]
MemberExpression
.
IdentifierName
SuperProperty
MemberExpression
.
PrivateIdentifier
- Return simple.
PrimaryExpression :
CoverParenthesizedExpressionAndArrowParameterList
- Let expr be the ParenthesizedExpression that is covered by CoverParenthesizedExpressionAndArrowParameterList.
- Return AssignmentTargetType of expr.
PrimaryExpression :
this
Literal
ArrayLiteral
ObjectLiteral
FunctionExpression
ClassExpression
GeneratorExpression
AsyncFunctionExpression
AsyncGeneratorExpression
RegularExpressionLiteral
TemplateLiteral
CallExpression :
CoverCallExpressionAndAsyncArrowHead
SuperCall
ImportCall
CallExpression
Arguments
CallExpression
TemplateLiteral
NewExpression :
new
NewExpression
MemberExpression :
MemberExpression
TemplateLiteral
new
MemberExpression
Arguments
NewTarget :
new
.
target
ImportMeta :
import
.
meta
LeftHandSideExpression :
OptionalExpression
UpdateExpression :
LeftHandSideExpression
++
LeftHandSideExpression
--
++
UnaryExpression
--
UnaryExpression
UnaryExpression :
delete
UnaryExpression
void
UnaryExpression
typeof
UnaryExpression
+
UnaryExpression
-
UnaryExpression
~
UnaryExpression
!
UnaryExpression
AwaitExpression
CoverAwaitExpressionAndAwaitUsingDeclarationHead
AwaitExpression :
await
UnaryExpression
ExponentiationExpression :
UpdateExpression
**
ExponentiationExpression
MultiplicativeExpression :
MultiplicativeExpression
MultiplicativeOperator
ExponentiationExpression
AdditiveExpression :
AdditiveExpression
+
MultiplicativeExpression
AdditiveExpression
-
MultiplicativeExpression
ShiftExpression :
ShiftExpression
<<
AdditiveExpression
ShiftExpression
>>
AdditiveExpression
ShiftExpression
>>>
AdditiveExpression
RelationalExpression :
RelationalExpression
<
ShiftExpression
RelationalExpression
>
ShiftExpression
RelationalExpression
<=
ShiftExpression
RelationalExpression
>=
ShiftExpression
RelationalExpression
instanceof
ShiftExpression
RelationalExpression
in
ShiftExpression
PrivateIdentifier
in
ShiftExpression
EqualityExpression :
EqualityExpression
==
RelationalExpression
EqualityExpression
!=
RelationalExpression
EqualityExpression
===
RelationalExpression
EqualityExpression
!==
RelationalExpression
BitwiseANDExpression :
BitwiseANDExpression
&
EqualityExpression
BitwiseXORExpression :
BitwiseXORExpression
^
BitwiseANDExpression
BitwiseORExpression :
BitwiseORExpression
|
BitwiseXORExpression
LogicalANDExpression :
LogicalANDExpression
&&
BitwiseORExpression
LogicalORExpression :
LogicalORExpression
||
LogicalANDExpression
CoalesceExpression :
CoalesceExpressionHead
??
BitwiseORExpression
ConditionalExpression :
ShortCircuitExpression
?
AssignmentExpression
:
AssignmentExpression
AssignmentExpression :
YieldExpression
ArrowFunction
AsyncArrowFunction
LeftHandSideExpression
=
AssignmentExpression
LeftHandSideExpression
AssignmentOperator
AssignmentExpression
LeftHandSideExpression
&&=
AssignmentExpression
LeftHandSideExpression
||=
AssignmentExpression
LeftHandSideExpression
??=
AssignmentExpression
Expression :
Expression
,
AssignmentExpression
- Return invalid.
4 Executable Code and Execution Contexts
4.1 Environment Records
Environment Record is a specification type used to define the association of Identifiers to specific variables and functions, based upon the lexical nesting structure of ECMAScript code. Usually an Environment Record is associated with some specific syntactic structure of ECMAScript code such as a FunctionDeclaration, a BlockStatement, or a Catch clause of a TryStatement. Each time such code is evaluated, a new Environment Record is created to record the identifier bindings that are created by that code.
Every Environment Record has an [[OuterEnv]] field, which is either null or a reference to an outer Environment Record. This is used to model the logical nesting of Environment Record values. The outer reference of an (inner) Environment Record is a reference to the Environment Record that logically surrounds the inner Environment Record. An outer Environment Record may, of course, have its own outer Environment Record. An Environment Record may serve as the outer environment for multiple inner Environment Records. For example, if a FunctionDeclaration contains two nested FunctionDeclarations then the Environment Records of each of the nested functions will have as their outer Environment Record the Environment Record of the current evaluation of the surrounding function.
Environment Records are purely specification mechanisms and need not correspond to any specific artefact of an ECMAScript implementation. It is impossible for an ECMAScript program to directly access or manipulate such values.
4.1.1 The Environment Record Type Hierarchy
The Environment Record abstract class includes the abstract specification methods defined in Table 5. These abstract methods have distinct concrete algorithms for each of the concrete subclasses.
Table 5: Abstract Methods of
Environment Records
Method
Purpose
|
HasBinding(N)
|
Determine if an Environment Record has a binding for the String value N. Return true if it does and false if it does not.
|
|
CreateMutableBinding(N, D)
|
Create a new but uninitialized mutable binding in an Environment Record. The String value N is the text of the bound name. If the Boolean argument D is true the binding may be subsequently deleted.
|
|
CreateImmutableBinding(N, S)
|
Create a new but uninitialized immutable binding in an Environment Record. The String value N is the text of the bound name. If S is true then attempts to set it after it has been initialized will always throw an exception, regardless of the strict mode setting of operations that reference that binding.
|
|
InitializeBinding(N, V, hint)
|
Set the value of an already existing but uninitialized binding in an Environment Record. The String value N is the text of the bound name. V is the value for the binding and is a value of any ECMAScript language type. hint indicates whether the binding came from either a using declaration (sync-dispose), a await using declaration (async-dispose), or a regular variable declaration (normal).
|
|
SetMutableBinding(N, V, S)
|
Set the value of an already existing mutable binding in an Environment Record. The String value N is the text of the bound name. V is the value for the binding and may be a value of any ECMAScript language type. S is a Boolean flag. If S is true and the binding cannot be set throw a TypeError exception.
|
|
GetBindingValue(N, S)
|
Returns the value of an already existing binding from an Environment Record. The String value N is the text of the bound name. S is used to identify references originating in strict mode code or that otherwise require strict mode reference semantics. If S is true and the binding does not exist throw a ReferenceError exception. If the binding exists but is uninitialized a ReferenceError is thrown, regardless of the value of S.
|
|
DeleteBinding(N)
|
Delete a binding from an Environment Record. The String value N is the text of the bound name. If a binding for N exists, remove the binding and return true. If the binding exists but cannot be removed return false. If the binding does not exist return true.
|
|
HasThisBinding()
|
Determine if an Environment Record establishes a this binding. Return true if it does and false if it does not.
|
|
HasSuperBinding()
|
Determine if an Environment Record establishes a super method binding. Return true if it does and false if it does not.
|
|
WithBaseObject()
|
If this Environment Record is associated with a with statement, return the with object. Otherwise, return undefined.
|
4.1.1.1 Declarative Environment Records
Each Declarative Environment Record is associated with an ECMAScript program scope containing variable, constant, let, class, module, import, and/or function declarations. A declarative Environment Record binds the set of identifiers defined by the declarations contained within its scope.
Every Declarative Environment Record also has a [[DisposeCapability]] field, which contains a DisposeCapability Record. This field holds a stack of resources tracked by the using declarations and await using declarations that must be disposed when the Evaluation step that constructed the Environment Record has completed.
The behaviour of the concrete specification methods for Declarative Environment Records is defined by the following algorithms.
4.1.1.1.1 InitializeBinding ( N, V, hint )
The InitializeBinding concrete method of a declarative Environment Record envRec takes arguments N (a String), V (an ECMAScript language value), and hint (one of normal, sync-dispose, or async-dispose) and returns a normal completion containing unused. It is used to set the bound value of the current binding of the identifier whose name is the value of the argument N to the value of argument V. An uninitialized binding for N must already exist. It performs the following steps when called:
- Assert: envRec must have an uninitialized binding for N.
- If hint is not normal, perform ? AddDisposableResource(envRec, V, hint).
- Set the bound value for N in envRec to V.
- Record that the binding for N in envRec has been initialized.
- Return unused.
4.1.1.2 Object Environment Records
4.1.1.2.1 InitializeBinding ( N, V, hint )
The InitializeBinding concrete method of an object Environment Record envRec takes arguments N (a String), V (an ECMAScript language value), and hint (one of normal, sync-dispose, or async-dispose) and returns either a normal completion containing unused or a throw completion. It is used to set the bound value of the current binding of the identifier whose name is the value of the argument N to the value of argument V. It performs the following steps when called:
- Assert: hint is normal.
- Perform ? envRec.SetMutableBinding(N, V, false).
- Return unused.
Note
In this specification, all uses of CreateMutableBinding for object Environment Records are immediately followed by a call to InitializeBinding for the same name. Hence, this specification does not explicitly track the initialization state of bindings in object Environment Records.
4.1.1.3 Global Environment Records
4.1.1.3.1 InitializeBinding ( N, V, hint )
The InitializeBinding concrete method of a global Environment Record envRec takes arguments N (a String), V (an ECMAScript language value), and hint (one of normal, sync-dispose, or async-dispose) and returns either a normal completion containing unused or a throw completion. It is used to set the bound value of the current binding of the identifier whose name is the value of the argument N to the value of argument V. An uninitialized binding for N must already exist. It performs the following steps when called:
- Let DclRec be envRec.[[DeclarativeRecord]].
- If ! DclRec.HasBinding(N) is true, then
- Return ! DclRec.InitializeBinding(N, V, hint).
- Assert: If the binding exists, it must be in the object Environment Record.
- Assert: hint is normal.
- Let ObjRec be envRec.[[ObjectRecord]].
- Return ? ObjRec.InitializeBinding(N, V, normal).
5 Ordinary and Exotic Objects Behaviours
5.1 ECMAScript Function Objects
5.1.1 FunctionDeclarationInstantiation ( func, argumentsList )
The abstract operation FunctionDeclarationInstantiation takes arguments func (a function object) and argumentsList. func is the function object for which the execution context is being established.
Note 1
When an execution context is established for evaluating an ECMAScript function a new function Environment Record is created and bindings for each formal parameter are instantiated in that Environment Record. Each declaration in the function body is also instantiated. If the function's formal parameters do not include any default value initializers then the body declarations are instantiated in the same Environment Record as the parameters. If default value parameter initializers exist, a second Environment Record is created for the body declarations. Formal parameters and functions are initialized as part of FunctionDeclarationInstantiation. All other bindings are initialized during evaluation of the function body.
It performs the following steps when called:
- Let calleeContext be the running execution context.
- Let code be func.[[ECMAScriptCode]].
- Let strict be func.[[Strict]].
- Let formals be func.[[FormalParameters]].
- Let parameterNames be the BoundNames of formals.
- If parameterNames has any duplicate entries, let hasDuplicates be true. Otherwise, let hasDuplicates be false.
- Let simpleParameterList be IsSimpleParameterList of formals.
- Let hasParameterExpressions be ContainsExpression of formals.
- Let varNames be the VarDeclaredNames of code.
- Let varDeclarations be the VarScopedDeclarations of code.
- Let lexicalNames be the LexicallyDeclaredNames of code.
- Let functionNames be a new empty List.
- Let functionsToInitialize be a new empty List.
- For each element d of varDeclarations, in reverse List order, do
- If d is neither a VariableDeclaration nor a ForBinding nor a BindingIdentifier, then
- Assert: d is either a FunctionDeclaration, a GeneratorDeclaration, an AsyncFunctionDeclaration, or an AsyncGeneratorDeclaration.
- Let fn be the sole element of the BoundNames of d.
- If fn is not an element of functionNames, then
- Insert fn as the first element of functionNames.
- NOTE: If there are multiple function declarations for the same name, the last declaration is used.
- Insert d as the first element of functionsToInitialize.
- Let argumentsObjectNeeded be true.
- If func.[[ThisMode]] is lexical, then
- NOTE: Arrow functions never have an arguments object.
- Set argumentsObjectNeeded to false.
- Else if "arguments" is an element of parameterNames, then
- Set argumentsObjectNeeded to false.
- Else if hasParameterExpressions is false, then
- If "arguments" is an element of functionNames or if "arguments" is an element of lexicalNames, then
- Set argumentsObjectNeeded to false.
- If strict is true or if hasParameterExpressions is false, then
- NOTE: Only a single Environment Record is needed for the parameters, since calls to eval in strict mode code cannot create new bindings which are visible outside of the eval.
- Let env be the LexicalEnvironment of calleeContext.
- Else,
- NOTE: A separate Environment Record is needed to ensure that bindings created by direct eval calls in the formal parameter list are outside the environment where parameters are declared.
- Let calleeEnv be the LexicalEnvironment of calleeContext.
- Let env be NewDeclarativeEnvironment(calleeEnv).
- Assert: The VariableEnvironment of calleeContext is calleeEnv.
- Set the LexicalEnvironment of calleeContext to env.
- For each String paramName of parameterNames, do
- Let alreadyDeclared be env.HasBinding(paramName).
- NOTE: Early errors ensure that duplicate parameter names can only occur in non-strict functions that do not have parameter default values or rest parameters.
- If alreadyDeclared is false, then
- Perform ! env.CreateMutableBinding(paramName, false).
- If hasDuplicates is true, then
- Perform ! env.InitializeBinding(paramName, undefined, normal).
- If argumentsObjectNeeded is true, then
- If strict is true or if simpleParameterList is false, then
- Let ao be CreateUnmappedArgumentsObject(argumentsList).
- Else,
- NOTE: A mapped argument object is only provided for non-strict functions that don't have a rest parameter, any parameter default value initializers, or any destructured parameters.
- Let ao be CreateMappedArgumentsObject(func, formals, argumentsList, env).
- If strict is true, then
- Perform ! env.CreateImmutableBinding("arguments", false, false).
- Else,
- Perform ! env.CreateMutableBinding("arguments", false).
- Call env.InitializeBinding("arguments", ao, normal).
- Let parameterBindings be the list-concatenation of parameterNames and « "arguments" ».
- Else,
- Let parameterBindings be parameterNames.
- Let iteratorRecord be CreateListIteratorRecord(argumentsList).
- If hasDuplicates is true, then
- Perform ? IteratorBindingInitialization of formals with iteratorRecord and undefined as arguments.
- Else,
- Perform ? IteratorBindingInitialization of formals with iteratorRecord and env as arguments.
- If hasParameterExpressions is false, then
- NOTE: Only a single Environment Record is needed for the parameters and top-level vars.
- Let instantiatedVarNames be a copy of the List parameterBindings.
- For each element n of varNames, do
- If n is not an element of instantiatedVarNames, then
- Append n to instantiatedVarNames.
- Perform ! env.CreateMutableBinding(n, false).
- Call env.InitializeBinding(n, undefined, normal).
- Let varEnv be env.
- Else,
- NOTE: A separate Environment Record is needed to ensure that closures created by expressions in the formal parameter list do not have visibility of declarations in the function body.
- Let varEnv be NewDeclarativeEnvironment(env).
- Set the VariableEnvironment of calleeContext to varEnv.
- Let instantiatedVarNames be a new empty List.
- For each element n of varNames, do
- If n is not an element of instantiatedVarNames, then
- Append n to instantiatedVarNames.
- Perform ! varEnv.CreateMutableBinding(n, false).
- If n is not an element of parameterBindings or if n is an element of functionNames, let initialValue be undefined.
- Else,
- Let initialValue be ! env.GetBindingValue(n, false).
- Call varEnv.InitializeBinding(n, initialValue, normal).
- NOTE: A var with the same name as a formal parameter initially has the same value as the corresponding initialized parameter.
- NOTE: Annex B.3.2.1 adds additional steps at this point.
- If strict is false, then
- Let lexEnv be NewDeclarativeEnvironment(varEnv).
- NOTE: Non-strict functions use a separate Environment Record for top-level lexical declarations so that a direct eval can determine whether any var scoped declarations introduced by the eval code conflict with pre-existing top-level lexically scoped declarations. This is not needed for strict functions because a strict direct eval always places all declarations into a new Environment Record.
- Else, let lexEnv be varEnv.
- Set the LexicalEnvironment of calleeContext to lexEnv.
- Let lexDeclarations be the LexicallyScopedDeclarations of code.
- For each element d of lexDeclarations, do
- NOTE: A lexically declared name cannot be the same as a function/generator declaration, formal parameter, or a var name. Lexically declared names are only instantiated here but not initialized.
- For each element dn of the BoundNames of d, do
- If IsConstantDeclaration of d is true, then
- Perform ! lexEnv.CreateImmutableBinding(dn, true).
- Else,
- Perform ! lexEnv.CreateMutableBinding(dn, false).
- Let privateEnv be the PrivateEnvironment of calleeContext.
- For each Parse Node f of functionsToInitialize, do
- Let fn be the sole element of the BoundNames of f.
- Let fo be InstantiateFunctionObject of f with arguments lexEnv and privateEnv.
- Perform ! varEnv.SetMutableBinding(fn, fo, false).
- Return NormalCompletion(empty).
Note 2
A.1.1 provides an extension to the above algorithm that is necessary for backwards compatibility with web browser implementations of ECMAScript that predate ECMAScript 2015.
6 ECMAScript Language: Expressions
6.1 Unary Operators
Syntax
UnaryExpression[Yield, Await] :
UpdateExpression[?Yield, ?Await]
delete
UnaryExpression[?Yield, ?Await]
void
UnaryExpression[?Yield, ?Await]
typeof
UnaryExpression[?Yield, ?Await]
+
UnaryExpression[?Yield, ?Await]
-
UnaryExpression[?Yield, ?Await]
~
UnaryExpression[?Yield, ?Await]
!
UnaryExpression[?Yield, ?Await]
[+Await]
AwaitExpression[?Yield]
[+Await]
CoverAwaitExpressionAndAwaitUsingDeclarationHead[?Yield]
CoverAwaitExpressionAndAwaitUsingDeclarationHead[Yield] :
await
UnaryExpression[?Yield, +Await]
Supplemental Syntax
When processing an instance of the production
UnaryExpression : CoverAwaitExpressionAndAwaitUsingDeclarationHead
the interpretation of CoverAwaitExpressionAndAwaitUsingDeclarationHead is refined using the following grammar:
AwaitExpression[Yield] :
await
UnaryExpression[?Yield, +Await]
7 ECMAScript Language: Statements and Declarations
7.1 Block
7.1.1 Runtime Semantics: Evaluation
Block :
{
StatementList
}
- Let oldEnv be the running execution context's LexicalEnvironment.
- Let blockEnv be NewDeclarativeEnvironment(oldEnv).
- Perform BlockDeclarationInstantiation(StatementList, blockEnv).
- Set the running execution context's LexicalEnvironment to blockEnv.
- Let blockValue be Completion(Evaluation of StatementList).
- Set blockValue to Completion(DisposeResources(blockEnv.[[DisposeCapability]], blockValue)).
- Set the running execution context's LexicalEnvironment to oldEnv.
- Return blockValue.
Note
No matter how control leaves the Block the LexicalEnvironment is always restored to its former state.
7.1.2 BlockDeclarationInstantiation ( code, env )
The abstract operation BlockDeclarationInstantiation takes arguments code (a Parse Node) and env (a declarative Environment Record). code is the Parse Node corresponding to the body of the block. env is the Environment Record in which bindings are to be created.
Note
When a Block or CaseBlock is evaluated a new declarative Environment Record is created and bindings for each block scoped variable, constant, function, or class declared in the block are instantiated in the Environment Record.
It performs the following steps when called:
- Let declarations be the LexicallyScopedDeclarations of code.
- Let privateEnv be the running execution context's PrivateEnvironment.
- For each element d of declarations, do
- For each element dn of the BoundNames of d, do
- If IsConstantDeclaration of d is true, then
- Perform ! env.CreateImmutableBinding(dn, true).
- Else,
- Perform ! env.CreateMutableBinding(dn, false). NOTE: This step is replaced in section A.1.1.1.
- If d is a FunctionDeclaration, a GeneratorDeclaration, an AsyncFunctionDeclaration, or an AsyncGeneratorDeclaration, then
- Let fn be the sole element of the BoundNames of d.
- Let fo be InstantiateFunctionObject of d with arguments env and privateEnv.
- Perform env.InitializeBinding(fn, fo, normal). NOTE: This step is replaced in section A.1.1.1.
7.2 Declarations and the Variable Statement
7.2.1 Let and Const, Const, and Using Declarations
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
BindingPattern[?Yield, ?Await]
Initializer[?In, ?Yield, ?Await]
[+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
7.2.1.1 Static Semantics: Early Errors
UsingDeclaration :
using
BindingList
;
-
It is a Syntax Error if the BoundNames of BindingList contains "let".
-
It is a Syntax Error if the BoundNames of BindingList contains "await".
-
It is a Syntax Error if the BoundNames of BindingList contains any duplicate entries.
-
It is a Syntax Error if the goal symbol is Script and UsingDeclaration is not contained, either directly or indirectly, within a Block, CaseBlock, ForStatement, ForInOfStatement, FunctionBody, GeneratorBody, AsyncGeneratorBody, AsyncFunctionBody, ClassStaticBlockBody, or ClassBody.
AwaitUsingDeclaration :
CoverAwaitExpressionAndAwaitUsingDeclarationHead
BindingList
;
- CoverAwaitExpressionAndAwaitUsingDeclarationHead must cover an AwaitUsingDeclarationHead.
-
It is a Syntax Error if the BoundNames of BindingList contains "let".
-
It is a Syntax Error if the BoundNames of BindingList contains any duplicate entries.
-
It is a Syntax Error if the goal symbol is Script and AwaitUsingDeclaration is not contained, either directly or indirectly, within a Block, CaseBlock, ForStatement, ForInOfStatement, FunctionBody, GeneratorBody, AsyncGeneratorBody, AsyncFunctionBody, ClassStaticBlockBody, or ClassBody.
Note
Draft Note: This behavior is currently under discussion in
#66. The above boundaries have been chosen for the following reasons:
7.2.1.2 Runtime Semantics: Evaluation
LexicalDeclaration :
LetOrConst
BindingList
;
- Perform ? EvaluationBindingEvaluation of BindingList with parameter normal.
- Return empty.
UsingDeclaration :
using
BindingList
;
- Perform ? BindingEvaluation of BindingList with parameter sync-dispose.
- Return empty.
AwaitUsingDeclaration :
CoverAwaitExpressionAndAwaitUsingDeclarationHead
BindingList
;
- Perform ? BindingEvaluation of BindingList with parameter async-dispose.
- Return empty.
BindingList :
BindingList
,
LexicalBinding
- Perform ? Evaluation of BindingList.
- Return ? Evaluation of LexicalBinding.
LexicalBinding :
BindingIdentifier
- Let lhs be ! ResolveBinding(StringValue of BindingIdentifier).
- Perform ! InitializeReferencedBinding(lhs, undefined).
- Return empty.
Note
A static semantics rule ensures that this form of LexicalBinding never occurs in a const declaration.
LexicalBinding :
BindingIdentifier
Initializer
- Let bindingId be StringValue of BindingIdentifier.
- Let lhs be ! ResolveBinding(bindingId).
- If IsAnonymousFunctionDefinition(Initializer) is true, then
- Let value be ? NamedEvaluation of Initializer with argument bindingId.
- Else,
- Let rhs be ? Evaluation of Initializer.
- Let value be ? GetValue(rhs).
- Perform ! InitializeReferencedBinding(lhs, value).
- Return empty.
LexicalBinding :
BindingPattern
Initializer
- Let rhs be ? Evaluation of Initializer.
- Let value be ? GetValue(rhs).
- Let env be the running execution context's LexicalEnvironment.
- Return ? BindingInitialization of BindingPattern with arguments value and env.
7.2.1.3 Runtime Semantics: BindingEvaluation
The syntax-directed operation BindingEvaluation takes argument hint (one of 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
- Perform ? BindingEvaluation of BindingList with parameter hint.
- Return ? BindingEvaluation of LexicalBinding with parameter hint.
LexicalBinding :
BindingIdentifier
- Assert: hint is normal.
- Let lhs be ! ResolveBinding(StringValue of BindingIdentifier).
- Perform ! InitializeReferencedBinding(lhs, undefined, normal).
- Return unused.
Note
A static semantics rule ensures that this form of LexicalBinding never occurs in a const declaration.
LexicalBinding :
BindingIdentifier
Initializer
- Let bindingId be StringValue of BindingIdentifier.
- Let lhs be ? ResolveBinding(bindingId).
- If IsAnonymousFunctionDefinition(Initializer) is true, then
- Let value be ? NamedEvaluation of Initializer with argument bindingId.
- Else,
- Let rhs be ? Evaluation of Initializer.
- Let value be ? GetValue(rhs).
- Perform ? InitializeReferencedBinding(lhs, value, hint).
- Return unused.
LexicalBinding :
BindingPattern
Initializer
- Assert: hint is normal.
- Let rhs be ? Evaluation of Initializer.
- Let value be ? GetValue(rhs).
- Let env be the running execution context's LexicalEnvironment.
- Return ? BindingInitialization of BindingPattern with arguments value and env.
7.2.2 Destructuring Binding Patterns
7.2.2.1 Runtime Semantics: RestBindingInitialization
The syntax-directed operation RestBindingInitialization takes arguments value, environment, and excludedNames and returns either a normal completion containing unused or an abrupt completion. It is defined piecewise over the following productions:
BindingRestProperty :
...
BindingIdentifier
- Let lhs be ? ResolveBinding(StringValue of BindingIdentifier, environment).
- Let restObj be OrdinaryObjectCreate(%Object.prototype%).
- Perform ? CopyDataProperties(restObj, value, excludedNames).
- If environment is undefined, return PutValue(lhs, restObj).
- Return ? InitializeReferencedBinding(lhs, restObj, normal).
7.2.2.2 Runtime Semantics: KeyedBindingInitialization
The syntax-directed operation KeyedBindingInitialization takes arguments value, environment, and propertyName 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
- Let v be ? GetV(value, propertyName).
- If Initializer is present and v is undefined, then
- Let defaultValue be ? Evaluation of Initializer.
- Set v to ? GetValue(defaultValue).
- Return ? BindingInitialization of BindingPattern with arguments v and environment.
SingleNameBinding :
BindingIdentifier
Initializeropt
- Let bindingId be StringValue of BindingIdentifier.
- Let lhs be ? ResolveBinding(bindingId, environment).
- Let v be ? GetV(value, propertyName).
- If Initializer is present and v is undefined, then
- If IsAnonymousFunctionDefinition(Initializer) is true, then
- Set v to ? NamedEvaluation for Initializer with argument bindingId.
- Else,
- Let defaultValue be ? Evaluation of Initializer.
- Set v to ? GetValue(defaultValue).
- If environment is undefined, return ? PutValue(lhs, v).
- Return ? InitializeReferencedBinding(lhs, v, normal).
7.3 Iteration Statements
7.3.1 The for Statement
7.3.1.1 Runtime Semantics: ForLoopEvaluation
The syntax-directed operation ForLoopEvaluation takes argument labelSet 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
- If the first Expression is present, then
- Let exprRef be ? Evaluation of the first Expression.
- Perform ? GetValue(exprRef).
- If the second Expression is present, let test be the second Expression; otherwise, let test be empty.
- If the third Expression is present, let increment be the third Expression; otherwise, let increment be empty.
- Return ? ForBodyEvaluation(test, increment, Statement, « », labelSet).
ForStatement :
for
(
var
VariableDeclarationList
;
Expressionopt
;
Expressionopt
)
Statement
- Perform ? Evaluation of VariableDeclarationList.
- If the first Expression is present, let test be the first Expression; otherwise, let test be empty.
- If the second Expression is present, let increment be the second Expression; otherwise, let increment be empty.
- Return ? ForBodyEvaluation(test, increment, Statement, « », labelSet).
ForStatement :
for
(
LexicalDeclaration
Expressionopt
;
Expressionopt
)
Statement
- Let oldEnv be the running execution context's LexicalEnvironment.
- Let loopEnv be NewDeclarativeEnvironment(oldEnv).
- Let isConst be IsConstantDeclaration of LexicalDeclaration.
- Let boundNames be the BoundNames of LexicalDeclaration.
- For each element dn of boundNames, do
- If isConst is true, then
- Perform ! loopEnv.CreateImmutableBinding(dn, true).
- Else,
- Perform ! loopEnv.CreateMutableBinding(dn, false).
- Set the running execution context's LexicalEnvironment to loopEnv.
- Let forDcl be Completion(Evaluation of LexicalDeclaration).
- If forDcl is an abrupt completion, then
- Set forDcl to Completion(DisposeResources(loopEnv.[[DisposeCapability]], forDcl)).
- Assert: forDcl is an abrupt completion.
- Set the running execution context's LexicalEnvironment to oldEnv.
- Return ? forDcl.
- If isConst is false, let perIterationLets be boundNames; otherwise let perIterationLets be a new empty List.
- If the first Expression is present, let test be the first Expression; otherwise, let test be empty.
- If the second Expression is present, let increment be the second Expression; otherwise, let increment be empty.
- Let bodyResult be Completion(ForBodyEvaluation(test, increment, Statement, perIterationLets, labelSet)).
- Set bodyResult to Completion(DisposeResources(loopEnv.[[DisposeCapability]], bodyResult)).
- Assert: If bodyResult.[[Type]] is normal, then bodyResult.[[Value]] is not empty.
- Set the running execution context's LexicalEnvironment to oldEnv.
- Return ? bodyResult.
7.3.2 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, +Pattern]
in
Expression[+In, ?Yield, ?Await]
)
Statement[?Yield, ?Await, ?Return]
for
(
ForDeclaration[?Yield, ?Await, ~Using]
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, +Pattern]
of
AssignmentExpression[+In, ?Yield, ?Await]
)
Statement[?Yield, ?Await, ?Return]
for
(
[lookahead ≠ using
of]
ForDeclaration[?Yield, ?Await, +Using]
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, +Pattern]
of
AssignmentExpression[+In, ?Yield, ?Await]
)
Statement[?Yield, ?Await, ?Return]
[+Await]
for
await
(
[lookahead ≠ using
of]
ForDeclaration[?Yield, ?Await, +Using]
of
AssignmentExpression[+In, ?Yield, ?Await]
)
Statement[?Yield, ?Await, ?Return]
ForDeclaration[Yield, Await, Using] :
LetOrConst
ForBinding[?Yield, ?Await, +Pattern]
[+Using]
using
[no
LineTerminator here]
ForBinding[?Yield, ?Await, ~Pattern]
[+Using, +Await]
await
[no
LineTerminator here]
using
[no
LineTerminator here]
ForBinding[?Yield, +Await, ~Pattern]
ForBinding[Yield, Await, Pattern] :
BindingIdentifier[?Yield, ?Await]
BindingPattern[?Yield, ?Await]
[+Pattern]
BindingPattern[?Yield, ?Await]
7.3.2.1 Runtime Semantics: ForDeclarationBindingInstantiation
The syntax-directed operation ForDeclarationBindingInstantiation takes argument environment. It is defined piecewise over the following productions:
ForDeclaration :
LetOrConst
ForBinding
- Assert: environment is a declarative Environment Record.
- For each element name of the BoundNames of ForBinding, do
- If IsConstantDeclaration of LetOrConst is true, then
- Perform ! environment.CreateImmutableBinding(name, true).
- Else,
- Perform ! environment.CreateMutableBinding(name, false).
ForDeclaration :
using
ForBinding
await
using
ForBinding
- Assert: environment is a declarative Environment Record.
- For each element name of the BoundNames of ForBinding, do
- Perform ! environment.CreateImmutableBinding(name, true).
7.3.2.2 ForIn/OfBodyEvaluation ( lhs, stmt, iteratorRecord, iterationKind, lhsKind, labelSet [ , iteratorKind ] )
The abstract operation ForIn/OfBodyEvaluation takes arguments lhs, stmt, iteratorRecord, iterationKind, lhsKind (assignment, varBinding, or lexicalBinding), and labelSet and optional argument iteratorKind (sync or async) and returns either a normal completion containing an ECMAScript language value or an abrupt completion. It performs the following steps when called:
- If iteratorKind is not present, set iteratorKind to sync.
- Let oldEnv be the running execution context's LexicalEnvironment.
- Let V be undefined.
- If IsAwaitUsingDeclaration of lhs is true, then
- Let hint be async-dispose.
- Else, if IsUsingDeclaration of lhs is true, then
- Let hint be sync-dispose.
- Else,
- Let hint be normal.
- Let destructuring be IsDestructuring of lhs.
- If destructuring is true and if lhsKind is assignment, then
- Assert: lhs is a LeftHandSideExpression.
- Let assignmentPattern be the AssignmentPattern that is covered by lhs.
- Repeat,
- Let nextResult be ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]]).
- If iteratorKind is async, set nextResult to ? Await(nextResult).
- If nextResult is not an Object, throw a TypeError exception.
- Let done be ? IteratorComplete(nextResult).
- If done is true, return V.
- Let nextValue be ? IteratorValue(nextResult).
- If lhsKind is either assignment or varBinding, then
- If destructuring is true, then
- If lhsKind is assignment, then
- Let status be Completion(DestructuringAssignmentEvaluation of assignmentPattern with argument nextValue).
- Else,
- Assert: lhsKind is varBinding.
- Assert: lhs is a ForBinding.
- Let status be Completion(BindingInitialization of lhs with arguments nextValue and undefined).
- Else,
- Let lhsRef be Completion(Evaluation of lhs). (It may be evaluated repeatedly.)
- If lhsRef is an abrupt completion, then
- Let status be lhsRef.
- Else,
- Let status be Completion(PutValue(lhsRef.[[Value]], nextValue)).
- Let iterationEnv be undefined.
- Else,
- Assert: lhsKind is lexicalBinding.
- Assert: lhs is a ForDeclaration.
- Let iterationEnv be NewDeclarativeEnvironment(oldEnv).
- Perform ForDeclarationBindingInstantiation of lhs with argument iterationEnv.
- Set the running execution context's LexicalEnvironment to iterationEnv.
- If destructuring is true, then
- Let status be Completion(ForDeclarationBindingInitialization of lhs with arguments nextValue and iterationEnv).
- Else,
- Assert: lhs binds a single name.
- Let lhsName be the sole element of BoundNames of lhs.
- Let lhsRef be ! ResolveBinding(lhsName).
- Let status be Completion(InitializeReferencedBinding(lhsRef, nextValue)).
- If IsUsingDeclaration of lhs is true, then
- Let status be Completion(InitializeReferencedBinding(lhsRef, nextValue, sync-dispose)).
- Else,
- Let status be Completion(InitializeReferencedBinding(lhsRef, nextValue, normal)).
- If status is an abrupt completion, then
- If iterationEnv is not undefined, then
- Set status to Completion(DisposeResources(iterationEnv.[[DisposeCapability]], status)).
- Assert: status is an abrupt completion.
- 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 is iterate.
- Return ? IteratorClose(iteratorRecord, status).
- Let result be Completion(Evaluation of stmt).
- If iterationEnv is not undefined, then
- Set result to Completion(DisposeResources(iterationEnv.[[DisposeCapability]], result)).
- Set the running execution context's LexicalEnvironment to oldEnv.
- If LoopContinues(result, labelSet) is false, then
- If iterationKind is enumerate, then
- Return ? UpdateEmpty(result, V).
- Else,
- Assert: iterationKind is iterate.
- Set status to Completion(UpdateEmpty(result, V)).
- If iteratorKind is async, return ? AsyncIteratorClose(iteratorRecord, status).
- Return ? IteratorClose(iteratorRecord, status).
- If result.[[Value]] is not empty, set V to result.[[Value]].
7.4 The switch Statement
7.4.1 Runtime Semantics: Evaluation
SwitchStatement :
switch
(
Expression
)
CaseBlock
- Let exprRef be ? Evaluation of Expression.
- Let switchValue be ? GetValue(exprRef).
- Let oldEnv be the running execution context's LexicalEnvironment.
- Let blockEnv be NewDeclarativeEnvironment(oldEnv).
- Perform BlockDeclarationInstantiation(CaseBlock, blockEnv).
- Set the running execution context's LexicalEnvironment to blockEnv.
- Let R be Completion(CaseBlockEvaluation of CaseBlock with argument switchValue).
- Set R to Completion(DisposeResources(blockEnv.[[DisposeCapability]], R)).
- Assert: If R.[[Type]] is normal, then R.[[Value]] is not empty.
- Set the running execution context's LexicalEnvironment to oldEnv.
- Return R.
Note
No matter how control leaves the SwitchStatement the LexicalEnvironment is always restored to its former state.
8 ECMAScript Language: Functions and Classes
8.1 Function Definitions
8.1.1 Runtime Semantics: EvaluateFunctionBody
The syntax-directed operation EvaluateFunctionBody takes arguments functionObject and argumentsList (a List) and returns either a normal completion containing an ECMAScript language value or an abrupt completion. It is defined piecewise over the following productions:
FunctionBody :
FunctionStatementList
- Perform ? FunctionDeclarationInstantiation(functionObject, argumentsList).
- Return ? Evaluation of FunctionStatementList.
- Let result be Completion(Evaluation of FunctionStatementList).
- Let env be the running execution context's LexicalEnvironment.
- Return ? DisposeResources(env.[[DisposeCapability]], result).
8.1.2 Runtime Semantics: InstantiateOrdinaryFunctionExpression
The syntax-directed operation InstantiateOrdinaryFunctionExpression takes optional argument name. It is defined piecewise over the following productions:
FunctionExpression :
function
(
FormalParameters
)
{
FunctionBody
}
- If name is not present, set name to "".
- Let scope be the LexicalEnvironment of the running execution context.
- Let privateScope be the running execution context's PrivateEnvironment.
- Let sourceText be the source text matched by FunctionExpression.
- Let closure be OrdinaryFunctionCreate(%Function.prototype%, sourceText, FormalParameters, FunctionBody, non-lexical-this, scope, privateScope).
- Perform SetFunctionName(closure, name).
- Perform MakeConstructor(closure).
- Return closure.
FunctionExpression :
function
BindingIdentifier
(
FormalParameters
)
{
FunctionBody
}
- Assert: name is not present.
- Set name to StringValue of BindingIdentifier.
- Let scope be the running execution context's LexicalEnvironment.
- Let funcEnv be NewDeclarativeEnvironment(scope).
- Perform ! funcEnv.CreateImmutableBinding(name, false).
- Let privateScope be the running execution context's PrivateEnvironment.
- Let sourceText be the source text matched by FunctionExpression.
- Let closure be OrdinaryFunctionCreate(%Function.prototype%, sourceText, FormalParameters, FunctionBody, non-lexical-this, funcEnv, privateScope).
- Perform SetFunctionName(closure, name).
- Perform MakeConstructor(closure).
- Perform ! funcEnv.InitializeBinding(name, closure, normal).
- Return closure.
Note
The BindingIdentifier in a FunctionExpression can be referenced from inside the FunctionExpression's FunctionBody to allow the function to call itself recursively. However, unlike in a FunctionDeclaration, the BindingIdentifier in a FunctionExpression cannot be referenced from and does not affect the scope enclosing the FunctionExpression.
8.2 Generator Function Definitions
8.2.1 Runtime Semantics: InstantiateGeneratorFunctionExpression
The syntax-directed operation InstantiateGeneratorFunctionExpression takes optional argument name. It is defined piecewise over the following productions:
GeneratorExpression :
function
*
(
FormalParameters
)
{
GeneratorBody
}
- If name is not present, set name to "".
- Let scope be the LexicalEnvironment of the running execution context.
- Let privateScope be the running execution context's PrivateEnvironment.
- Let sourceText be the source text matched by GeneratorExpression.
- Let closure be OrdinaryFunctionCreate(%GeneratorFunction.prototype%, sourceText, FormalParameters, GeneratorBody, non-lexical-this, scope, privateScope).
- Perform SetFunctionName(closure, name).
- Let prototype be OrdinaryObjectCreate(%GeneratorFunction.prototype.prototype%).
- Perform ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }).
- Return closure.
GeneratorExpression :
function
*
BindingIdentifier
(
FormalParameters
)
{
GeneratorBody
}
- Assert: name is not present.
- Set name to StringValue of BindingIdentifier.
- Let scope be the running execution context's LexicalEnvironment.
- Let funcEnv be NewDeclarativeEnvironment(scope).
- Perform ! funcEnv.CreateImmutableBinding(name, false).
- Let privateScope be the running execution context's PrivateEnvironment.
- Let sourceText be the source text matched by GeneratorExpression.
- Let closure be OrdinaryFunctionCreate(%GeneratorFunction.prototype%, sourceText, FormalParameters, GeneratorBody, non-lexical-this, funcEnv, privateScope).
- Perform SetFunctionName(closure, name).
- Let prototype be OrdinaryObjectCreate(%GeneratorFunction.prototype.prototype%).
- Perform ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }).
- Perform ! funcEnv.InitializeBinding(name, closure, normal).
- Return closure.
Note
The BindingIdentifier in a GeneratorExpression can be referenced from inside the GeneratorExpression's FunctionBody to allow the generator code to call itself recursively. However, unlike in a GeneratorDeclaration, the BindingIdentifier in a GeneratorExpression cannot be referenced from and does not affect the scope enclosing the GeneratorExpression.
8.3 Async Generator Function Definitions
8.3.1 Runtime Semantics: InstantiateAsyncGeneratorFunctionExpression
The syntax-directed operation InstantiateAsyncGeneratorFunctionExpression takes optional argument name. It is defined piecewise over the following productions:
AsyncGeneratorExpression :
async
function
*
(
FormalParameters
)
{
AsyncGeneratorBody
}
- If name is not present, set name to "".
- Let scope be the LexicalEnvironment of the running execution context.
- Let privateScope be the running execution context's PrivateEnvironment.
- Let sourceText be the source text matched by AsyncGeneratorExpression.
- Let closure be OrdinaryFunctionCreate(%AsyncGeneratorFunction.prototype%, sourceText, FormalParameters, AsyncGeneratorBody, non-lexical-this, scope, privateScope).
- Perform SetFunctionName(closure, name).
- Let prototype be OrdinaryObjectCreate(%AsyncGeneratorFunction.prototype.prototype%).
- Perform ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }).
- Return closure.
AsyncGeneratorExpression :
async
function
*
BindingIdentifier
(
FormalParameters
)
{
AsyncGeneratorBody
}
- Assert: name is not present.
- Set name to StringValue of BindingIdentifier.
- Let scope be the running execution context's LexicalEnvironment.
- Let funcEnv be NewDeclarativeEnvironment(scope).
- Perform ! funcEnv.CreateImmutableBinding(name, false).
- Let privateScope be the running execution context's PrivateEnvironment.
- Let sourceText be the source text matched by AsyncGeneratorExpression.
- Let closure be OrdinaryFunctionCreate(%AsyncGeneratorFunction.prototype%, sourceText, FormalParameters, AsyncGeneratorBody, non-lexical-this, funcEnv, privateScope).
- Perform SetFunctionName(closure, name).
- Let prototype be OrdinaryObjectCreate(%AsyncGeneratorFunction.prototype.prototype%).
- Perform ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }).
- Perform ! funcEnv.InitializeBinding(name, closure, normal).
- Return closure.
Note
The BindingIdentifier in an AsyncGeneratorExpression can be referenced from inside the AsyncGeneratorExpression's AsyncGeneratorBody to allow the generator code to call itself recursively. However, unlike in an AsyncGeneratorDeclaration, the BindingIdentifier in an AsyncGeneratorExpression cannot be referenced from and does not affect the scope enclosing the AsyncGeneratorExpression.
8.4 Class Definitions
8.4.1 Runtime Semantics: EvaluateClassStaticBlockBody
The syntax-directed operation EvaluateClassStaticBlockBody takes argument functionObject and returns either a normal completion containing an ECMAScript language value or an abrupt completion. It is defined piecewise over the following productions:
ClassStaticBlockBody :
ClassStaticBlockStatementList
- Perform ? FunctionDeclarationInstantiation(functionObject, « »).
- Return ? Evaluation of ClassStaticBlockStatementList.
- Let result be Completion(Evaluation of ClassStaticBlockStatementList).
- Let env be the running execution context's LexicalEnvironment.
- Return ? DisposeResources(env.[[DisposeCapability]], result).
8.4.2 Runtime Semantics: ClassDefinitionEvaluation
The syntax-directed operation ClassDefinitionEvaluation takes arguments classBinding and className.
Note
For ease of specification, private methods and accessors are included alongside private fields in the [[PrivateElements]] slot of class instances. However, any given object has either all or none of the private methods and accessors defined by a given class. This feature has been designed so that implementations may choose to implement private methods and accessors using a strategy which does not require tracking each method or accessor individually.
For example, an implementation could directly associate instance private methods with their corresponding Private Name and track, for each object, which class constructors have run with that object as their this value. Looking up an instance private method on an object then consists of checking that the class constructor which defines the method has been used to initialize the object, then returning the method associated with the Private Name.
This differs from private fields: because field initializers can throw during class instantiation, an individual object may have some proper subset of the private fields of a given class, and so private fields must in general be tracked individually.
It is defined piecewise over the following productions:
ClassTail :
ClassHeritageopt
{
ClassBodyopt
}
- Let env be the LexicalEnvironment of the running execution context.
- Let classEnv be NewDeclarativeEnvironment(env).
- If classBinding is not undefined, then
- Perform ! classEnv.CreateImmutableBinding(classBinding, true).
- Let outerPrivateEnvironment be the running execution context's PrivateEnvironment.
- Let classPrivateEnvironment be NewPrivateEnvironment(outerPrivateEnvironment).
- If ClassBodyopt is present, then
- For each String dn of the PrivateBoundIdentifiers of ClassBodyopt, do
- If classPrivateEnvironment.[[Names]] contains a Private Name whose [[Description]] is dn, then
- Assert: This is only possible for getter/setter pairs.
- Else,
- Let name be a new Private Name whose [[Description]] value is dn.
- Append name to classPrivateEnvironment.[[Names]].
- If ClassHeritageopt is not present, then
- Let protoParent be %Object.prototype%.
- Let constructorParent be %Function.prototype%.
- Else,
- Set the running execution context's LexicalEnvironment to classEnv.
- NOTE: The running execution context's PrivateEnvironment is outerPrivateEnvironment when evaluating ClassHeritage.
- Let superclassRef be Completion(Evaluation of ClassHeritage).
- Set the running execution context's LexicalEnvironment to env.
- Let superclass be ? GetValue(? superclassRef).
- If superclass is null, then
- Let protoParent be null.
- Let constructorParent be %Function.prototype%.
- Else if IsConstructor(superclass) is false, throw a TypeError exception.
- Else,
- Let protoParent be ? Get(superclass, "prototype").
- If protoParent is not an Object and protoParent is not null, throw a TypeError exception.
- Let constructorParent be superclass.
- Let proto be OrdinaryObjectCreate(protoParent).
- If ClassBodyopt is not present, let constructor be empty.
- Else, let constructor be ConstructorMethod of ClassBody.
- Set the running execution context's LexicalEnvironment to classEnv.
- Set the running execution context's PrivateEnvironment to classPrivateEnvironment.
- If constructor is empty, then
- Let defaultConstructor be a new Abstract Closure with no parameters that captures nothing and performs the following steps when called:
- Let args be the List of arguments that was passed to this function by [[Call]] or [[Construct]].
- If NewTarget is undefined, throw a TypeError exception.
- Let F be the active function object.
- If F.[[ConstructorKind]] is derived, then
- NOTE: This branch behaves similarly to constructor(...args) { super(...args); }. The most notable distinction is that while the aforementioned ECMAScript source text observably calls the @@iterator method on %Array.prototype%, this function does not.
- Let func be ! F.[[GetPrototypeOf]]().
- If IsConstructor(func) is false, throw a TypeError exception.
- Let result be ? Construct(func, args, NewTarget).
- Else,
- NOTE: This branch behaves similarly to constructor() {}.
- Let result be ? OrdinaryCreateFromConstructor(NewTarget, "%Object.prototype%").
- Perform ? InitializeInstanceElements(result, F).
- Return result.
- Let F be CreateBuiltinFunction(defaultConstructor, 0, className, « [[ConstructorKind]], [[SourceText]] », the current Realm Record, constructorParent).
- Else,
- Let constructorInfo be ! DefineMethod of constructor with arguments proto and constructorParent.
- Let F be constructorInfo.[[Closure]].
- Perform MakeClassConstructor(F).
- Perform SetFunctionName(F, className).
- Perform MakeConstructor(F, false, proto).
- If ClassHeritageopt is present, set F.[[ConstructorKind]] to derived.
- Perform CreateMethodProperty(proto, "constructor", F).
- If ClassBodyopt is not present, let elements be a new empty List.
- Else, let elements be NonConstructorElements of ClassBody.
- Let instancePrivateMethods be a new empty List.
- Let staticPrivateMethods be a new empty List.
- Let instanceFields be a new empty List.
- Let staticElements be a new empty List.
- For each ClassElement e of elements, do
- If IsStatic of e is false, then
- Let element be Completion(ClassElementEvaluation of e with argument proto).
- Else,
- Let element be Completion(ClassElementEvaluation of e with argument F).
- If element is an abrupt completion, then
- Set the running execution context's LexicalEnvironment to env.
- Set the running execution context's PrivateEnvironment to outerPrivateEnvironment.
- Return ? element.
- Set element to element.[[Value]].
- If element is a PrivateElement, then
- Assert: element.[[Kind]] is either method or accessor.
- If IsStatic of e is false, let container be instancePrivateMethods.
- Else, let container be staticPrivateMethods.
- If container contains a PrivateElement whose [[Key]] is element.[[Key]], then
- Let existing be that PrivateElement.
- Assert: element.[[Kind]] and existing.[[Kind]] are both accessor.
- If element.[[Get]] is undefined, then
- Let combined be PrivateElement { [[Key]]: element.[[Key]], [[Kind]]: accessor, [[Get]]: existing.[[Get]], [[Set]]: element.[[Set]] }.
- Else,
- Let combined be PrivateElement { [[Key]]: element.[[Key]], [[Kind]]: accessor, [[Get]]: element.[[Get]], [[Set]]: existing.[[Set]] }.
- Replace existing in container with combined.
- Else,
- Append element to container.
- Else if element is a ClassFieldDefinition Record, then
- If IsStatic of e is false, append element to instanceFields.
- Else, append element to staticElements.
- Else if element is a ClassStaticBlockDefinition Record, then
- Append element to staticElements.
- Set the running execution context's LexicalEnvironment to env.
- If classBinding is not undefined, then
- Perform ! classScope.InitializeBinding(classBinding, F, normal).
- Set F.[[PrivateMethods]] to instancePrivateMethods.
- Set F.[[Fields]] to instanceFields.
- For each PrivateElement method of staticPrivateMethods, do
- Perform ! PrivateMethodOrAccessorAdd(F, method).
- For each element elementRecord of staticElements, do
- If elementRecord is a ClassFieldDefinition Record, then
- Let result be Completion(DefineField(F, elementRecord)).
- Else,
- Assert: elementRecord is a ClassStaticBlockDefinition Record.
- Let result be Completion(Call(elementRecord.[[BodyFunction]], F)).
- If result is an abrupt completion, then
- Set the running execution context's PrivateEnvironment to outerPrivateEnvironment.
- Return ? result.
- Set the running execution context's PrivateEnvironment to outerPrivateEnvironment.
- Return F.
8.5 Async Function Definitions
Syntax
AsyncFunctionDeclaration[Yield, Await, Default] :
async
[no
LineTerminator here]
function
BindingIdentifier[?Yield, ?Await]
(
FormalParameters[~Yield, +Await]
)
{
AsyncFunctionBody
}
[+Default]
async
[no
LineTerminator here]
function
(
FormalParameters[~Yield, +Await]
)
{
AsyncFunctionBody
}
AsyncFunctionExpression :
async
[no
LineTerminator here]
function
BindingIdentifier[~Yield, +Await]opt
(
FormalParameters[~Yield, +Await]
)
{
AsyncFunctionBody
}
AsyncMethod[Yield, Await] :
async
[no
LineTerminator here]
ClassElementName[?Yield, ?Await]
(
UniqueFormalParameters[~Yield, +Await]
)
{
AsyncFunctionBody
}
AsyncFunctionBody :
FunctionBody[~Yield, +Await]
AwaitExpression[Yield] :
await
UnaryExpression[?Yield, +Await]
8.5.1 Static Semantics: Early Errors
UnaryExpression :
CoverAwaitExpressionAndAwaitUsingDeclarationHead
8.5.2 Runtime Semantics: InstantiateAsyncFunctionExpression
The syntax-directed operation InstantiateAsyncFunctionExpression takes optional argument name. It is defined piecewise over the following productions:
AsyncFunctionExpression :
async
function
(
FormalParameters
)
{
AsyncFunctionBody
}
- If name is not present, set name to "".
- Let scope be the LexicalEnvironment of the running execution context.
- Let privateScope be the running execution context's PrivateEnvironment.
- Let sourceText be the source text matched by AsyncFunctionExpression.
- Let closure be OrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, FormalParameters, AsyncFunctionBody, non-lexical-this, scope, privateScope).
- Perform SetFunctionName(closure, name).
- Return closure.
AsyncFunctionExpression :
async
function
BindingIdentifier
(
FormalParameters
)
{
AsyncFunctionBody
}
- Assert: name is not present.
- Set name to StringValue of BindingIdentifier.
- Let scope be the LexicalEnvironment of the running execution context.
- Let funcEnv be NewDeclarativeEnvironment(scope).
- Perform ! funcEnv.CreateImmutableBinding(name, false).
- Let privateScope be the running execution context's PrivateEnvironment.
- Let sourceText be the source text matched by AsyncFunctionExpression.
- Let closure be OrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, FormalParameters, AsyncFunctionBody, non-lexical-this, funcEnv, privateScope).
- Perform SetFunctionName(closure, name).
- Perform ! funcEnv.InitializeBinding(name, closure, normal).
- Return closure.
Note
The BindingIdentifier in an AsyncFunctionExpression can be referenced from inside the AsyncFunctionExpression's AsyncFunctionBody to allow the function to call itself recursively. However, unlike in a FunctionDeclaration, the BindingIdentifier in a AsyncFunctionExpression cannot be referenced from and does not affect the scope enclosing the AsyncFunctionExpression.
8.5.3 Runtime Semantics: Evaluation
UnaryExpression :
CoverAwaitExpressionAndAwaitUsingDeclarationHead
- Let expr be the AwaitExpression that is covered by CoverAwaitExpressionAndAwaitUsingDeclarationHead.
- Return ? Evaluation of expr.
8.6 Tail Position Calls
8.6.1 Static Semantics: HasCallInTailPosition
The syntax-directed operation HasCallInTailPosition takes argument call (a CallExpression Parse Node, a MemberExpression Parse Node, or an OptionalChain Parse Node) and returns a Boolean.
Note 1
call is a Parse Node that represents a specific range of source text. When the following algorithms compare call to another Parse Node, it is a test of whether they represent the same source text.
Note 2
A potential tail position call that is immediately followed by return GetValue of the call result is also a possible tail position call. A function call cannot return a Reference Record, so such a GetValue operation will always return the same value as the actual function call result.
It is defined piecewise over the following productions:
StatementList :
StatementList
StatementListItem
- Let has be HasCallInTailPosition of StatementList with argument call.
- If has is true, return true.
- If HasUnterminatedUsingDeclaration of StatementList is true, return false.
- Return HasCallInTailPosition of StatementListItem with argument call.
FunctionStatementList :
[empty]
StatementListItem :
Declaration
Statement :
VariableStatement
EmptyStatement
ExpressionStatement
ContinueStatement
BreakStatement
ThrowStatement
DebuggerStatement
Block :
{
}
ReturnStatement :
return
;
LabelledItem :
FunctionDeclaration
ForInOfStatement :
for
(
LeftHandSideExpression
of
AssignmentExpression
)
Statement
for
(
var
ForBinding
of
AssignmentExpression
)
Statement
for
(
ForDeclaration
of
AssignmentExpression
)
Statement
CaseBlock :
{
}
- Return false.
IfStatement :
if
(
Expression
)
Statement
else
Statement
- Let has be HasCallInTailPosition of the first Statement with argument call.
- If has is true, return true.
- Return HasCallInTailPosition of the second Statement with argument call.
IfStatement :
if
(
Expression
)
Statement
DoWhileStatement :
do
Statement
while
(
Expression
)
;
WhileStatement :
while
(
Expression
)
Statement
ForStatement :
for
(
Expressionopt
;
Expressionopt
;
Expressionopt
)
Statement
for
(
var
VariableDeclarationList
;
Expressionopt
;
Expressionopt
)
Statement
for
(
LexicalDeclaration
Expressionopt
;
Expressionopt
)
Statement
ForInOfStatement :
for
(
LeftHandSideExpression
in
Expression
)
Statement
for
(
var
ForBinding
in
Expression
)
Statement
for
(
ForDeclaration
in
Expression
)
Statement
WithStatement :
with
(
Expression
)
Statement
- Return HasCallInTailPosition of Statement with argument call.
LabelledStatement :
LabelIdentifier
:
LabelledItem
- Return HasCallInTailPosition of LabelledItem with argument call.
ReturnStatement :
return
Expression
;
- Return HasCallInTailPosition of Expression with argument call.
SwitchStatement :
switch
(
Expression
)
CaseBlock
- Return HasCallInTailPosition of CaseBlock with argument call.
CaseBlock :
{
CaseClausesopt
DefaultClause
CaseClausesopt
}
- Let has be false.
- If the first CaseClauses is present, let has be HasCallInTailPosition of the first CaseClauses with argument call.
- If has is true, return true.
- If the first CaseClauses is present, then
- Let has be HasCallInTailPosition of the first CaseClauses with argument call.
- If has is true, return true.
- If HasUnterminatedUsingDeclaration of the first CaseClauses is true, return false.
- Let has be HasCallInTailPosition of DefaultClause with argument call.
- If has is true, return true.
- If HasUnterminatedUsingDeclaration of DefaultClause is true, return false.
- If the second CaseClauses is present, let has be HasCallInTailPosition of the second CaseClauses with argument call.
- Return has.
CaseClauses :
CaseClauses
CaseClause
- Let has be HasCallInTailPosition of CaseClauses with argument call.
- If has is true, return true.
- If HasUnterminatedUsingDeclaration of CaseClauses is true, return false.
- Return HasCallInTailPosition of CaseClause with argument call.
CaseClause :
case
Expression
:
StatementListopt
DefaultClause :
default
:
StatementListopt
- If StatementList is present, return HasCallInTailPosition of StatementList with argument call.
- Return false.
TryStatement :
try
Block
Catch
- Return HasCallInTailPosition of Catch with argument call.
TryStatement :
try
Block
Finally
try
Block
Catch
Finally
- Return HasCallInTailPosition of Finally with argument call.
Catch :
catch
(
CatchParameter
)
Block
- Return HasCallInTailPosition of Block with argument call.
AssignmentExpression :
YieldExpression
ArrowFunction
AsyncArrowFunction
LeftHandSideExpression
=
AssignmentExpression
LeftHandSideExpression
AssignmentOperator
AssignmentExpression
LeftHandSideExpression
&&=
AssignmentExpression
LeftHandSideExpression
||=
AssignmentExpression
LeftHandSideExpression
??=
AssignmentExpression
BitwiseANDExpression :
BitwiseANDExpression
&
EqualityExpression
BitwiseXORExpression :
BitwiseXORExpression
^
BitwiseANDExpression
BitwiseORExpression :
BitwiseORExpression
|
BitwiseXORExpression
EqualityExpression :
EqualityExpression
==
RelationalExpression
EqualityExpression
!=
RelationalExpression
EqualityExpression
===
RelationalExpression
EqualityExpression
!==
RelationalExpression
RelationalExpression :
RelationalExpression
<
ShiftExpression
RelationalExpression
>
ShiftExpression
RelationalExpression
<=
ShiftExpression
RelationalExpression
>=
ShiftExpression
RelationalExpression
instanceof
ShiftExpression
RelationalExpression
in
ShiftExpression
PrivateIdentifier
in
ShiftExpression
ShiftExpression :
ShiftExpression
<<
AdditiveExpression
ShiftExpression
>>
AdditiveExpression
ShiftExpression
>>>
AdditiveExpression
AdditiveExpression :
AdditiveExpression
+
MultiplicativeExpression
AdditiveExpression
-
MultiplicativeExpression
MultiplicativeExpression :
MultiplicativeExpression
MultiplicativeOperator
ExponentiationExpression
ExponentiationExpression :
UpdateExpression
**
ExponentiationExpression
UpdateExpression :
LeftHandSideExpression
++
LeftHandSideExpression
--
++
UnaryExpression
--
UnaryExpression
UnaryExpression :
delete
UnaryExpression
void
UnaryExpression
typeof
UnaryExpression
+
UnaryExpression
-
UnaryExpression
~
UnaryExpression
!
UnaryExpression
AwaitExpression
CoverAwaitExpressionAndAwaitUsingDeclarationHead
AwaitExpression :
await
UnaryExpression
CallExpression :
SuperCall
CallExpression
[
Expression
]
CallExpression
.
IdentifierName
CallExpression
.
PrivateIdentifier
NewExpression :
new
NewExpression
MemberExpression :
MemberExpression
[
Expression
]
MemberExpression
.
IdentifierName
SuperProperty
MetaProperty
new
MemberExpression
Arguments
MemberExpression
.
PrivateIdentifier
PrimaryExpression :
this
IdentifierReference
Literal
ArrayLiteral
ObjectLiteral
FunctionExpression
ClassExpression
GeneratorExpression
AsyncFunctionExpression
AsyncGeneratorExpression
RegularExpressionLiteral
TemplateLiteral
- Return false.
Expression :
AssignmentExpression
Expression
,
AssignmentExpression
- Return HasCallInTailPosition of AssignmentExpression with argument call.
ConditionalExpression :
ShortCircuitExpression
?
AssignmentExpression
:
AssignmentExpression
- Let has be HasCallInTailPosition of the first AssignmentExpression with argument call.
- If has is true, return true.
- Return HasCallInTailPosition of the second AssignmentExpression with argument call.
LogicalANDExpression :
LogicalANDExpression
&&
BitwiseORExpression
- Return HasCallInTailPosition of BitwiseORExpression with argument call.
LogicalORExpression :
LogicalORExpression
||
LogicalANDExpression
- Return HasCallInTailPosition of LogicalANDExpression with argument call.
CoalesceExpression :
CoalesceExpressionHead
??
BitwiseORExpression
- Return HasCallInTailPosition of BitwiseORExpression with argument call.
CallExpression :
CoverCallExpressionAndAsyncArrowHead
CallExpression
Arguments
CallExpression
TemplateLiteral
- If this CallExpression is call, return true.
- Return false.
OptionalExpression :
MemberExpression
OptionalChain
CallExpression
OptionalChain
OptionalExpression
OptionalChain
- Return HasCallInTailPosition of OptionalChain with argument call.
OptionalChain :
?.
[
Expression
]
?.
IdentifierName
?.
PrivateIdentifier
OptionalChain
[
Expression
]
OptionalChain
.
IdentifierName
OptionalChain
.
PrivateIdentifier
- Return false.
OptionalChain :
?.
Arguments
OptionalChain
Arguments
- If this OptionalChain is call, return true.
- Return false.
MemberExpression :
MemberExpression
TemplateLiteral
- If this MemberExpression is call, return true.
- Return false.
PrimaryExpression :
CoverParenthesizedExpressionAndArrowParameterList
- Let expr be the ParenthesizedExpression that is covered by CoverParenthesizedExpressionAndArrowParameterList.
- Return HasCallInTailPosition of expr with argument call.
ParenthesizedExpression :
(
Expression
)
- Return HasCallInTailPosition of Expression with argument call.
8.6.2 Static Semantics: HasUnterminatedUsingDeclaration
The syntax-directed operation HasUnterminatedUsingDeclaration takes no arguments and returns a Boolean. It is defined piecewise over the following productions:
StatementList :
StatementList
StatementListItem
- Let has be HasUnterminatedUsingDeclaration of StatementList.
- If has is true, return true.
- Return HasUnterminatedUsingDeclaration of StatementListItem.
StatementListItem :
Statement
CaseBlock :
{
}
Declaration :
HoistableDeclaration
ClassDeclaration
LexicalDeclaration :
LetOrConst
BindingList
;
- Return false.
UsingDeclaration :
using
BindingList
;
AwaitUsingDeclaration :
CoverAwaitExpressionAndAwaitUsingDeclarationHead
BindingList
;
- Return true.
CaseClauses :
CaseClauses
CaseClause
- Let has be HasUnterminatedUsingDeclaration of CaseClauses.
- If has is true, return true.
- Return HasUnterminatedUsingDeclaration of CaseClause with argument call.
CaseClause :
case
Expression
:
StatementListopt
DefaultClause :
default
:
StatementListopt
- If StatementList is present, return HasUnterminatedUsingDeclaration of StatementList.
9 ECMAScript Language: Scripts and Modules
9.1 Modules
9.1.1 Module Semantics
9.1.1.1 Source Text Module Records
9.1.1.1.1 InitializeEnvironment ( )
The InitializeEnvironment concrete method of a Source Text Module Record module takes no arguments and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:
- For each ExportEntry Record e of module.[[IndirectExportEntries]], do
- Let resolution be module.ResolveExport(e.[[ExportName]]).
- If resolution is null or ambiguous, throw a SyntaxError exception.
- Assert: resolution is a ResolvedBinding Record.
- Assert: All named exports from module are resolvable.
- Let realm be module.[[Realm]].
- Assert: realm is not undefined.
- Let env be NewModuleEnvironment(realm.[[GlobalEnv]]).
- Set module.[[Environment]] to env.
- For each ImportEntry Record in of module.[[ImportEntries]], do
- Let importedModule be GetImportedModule(module, in.[[ModuleRequest]]).
- If in.[[ImportName]] is namespace-object, then
- Let namespace be GetModuleNamespace(importedModule).
- Perform ! env.CreateImmutableBinding(in.[[LocalName]], true).
- Perform ! env.InitializeBinding(in.[[LocalName]], namespace, normal).
- Else,
- Let resolution be importedModule.ResolveExport(in.[[ImportName]]).
- If resolution is null or ambiguous, throw a SyntaxError exception.
- If resolution.[[BindingName]] is namespace, then
- Let namespace be GetModuleNamespace(resolution.[[Module]]).
- Perform ! env.CreateImmutableBinding(in.[[LocalName]], true).
- Perform ! env.InitializeBinding(in.[[LocalName]], namespace, normal).
- Else,
- Perform env.CreateImportBinding(in.[[LocalName]], resolution.[[Module]], resolution.[[BindingName]]).
- Let moduleContext be a new ECMAScript code execution context.
- Set the Function of moduleContext to null.
- Assert: module.[[Realm]] is not undefined.
- Set the Realm of moduleContext to module.[[Realm]].
- Set the ScriptOrModule of moduleContext to module.
- Set the VariableEnvironment of moduleContext to module.[[Environment]].
- Set the LexicalEnvironment of moduleContext to module.[[Environment]].
- Set the PrivateEnvironment of moduleContext to null.
- Set module.[[Context]] to moduleContext.
- Push moduleContext onto the execution context stack; moduleContext is now the running execution context.
- Let code be module.[[ECMAScriptCode]].
- Let varDeclarations be the VarScopedDeclarations of code.
- Let declaredVarNames be a new empty List.
- For each element d of varDeclarations, do
- For each element dn of the BoundNames of d, do
- If dn is not an element of declaredVarNames, then
- Perform ! env.CreateMutableBinding(dn, false).
- Perform ! env.InitializeBinding(dn, undefined, normal).
- Append dn to declaredVarNames.
- Let lexDeclarations be the LexicallyScopedDeclarations of code.
- Let privateEnv be null.
- For each element d of lexDeclarations, do
- For each element dn of the BoundNames of d, do
- If IsConstantDeclaration of d is true, then
- Perform ! env.CreateImmutableBinding(dn, true).
- Else,
- Perform ! env.CreateMutableBinding(dn, false).
- If d is a FunctionDeclaration, a GeneratorDeclaration, an AsyncFunctionDeclaration, or an AsyncGeneratorDeclaration, then
- Let fo be InstantiateFunctionObject of d with arguments env and privateEnv.
- Perform ! env.InitializeBinding(dn, fo, normal).
- Remove moduleContext from the execution context stack.
- Return unused.
9.1.1.1.2 ExecuteModule ( [ capability ] )
The ExecuteModule concrete method of a Source Text Module Record module takes optional argument capability and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:
- Let moduleContext be a new ECMAScript code execution context.
- Set the Function of moduleContext to null.
- Set the Realm of moduleContext to module.[[Realm]].
- Set the ScriptOrModule of moduleContext to module.
- Assert: module has been linked and declarations in its module environment have been instantiated.
- Let env be module.[[Environment]].
- Set the VariableEnvironment of moduleContext to env.
- Set the LexicalEnvironment of moduleContext to env.
- Suspend the running execution context.
- If module.[[HasTLA]] is false, then
- Assert: capability is not present.
- Push moduleContext onto the execution context stack; moduleContext is now the running execution context.
- Let result be Completion(Evaluation of module.[[ECMAScriptCode]]).
- Set result to Completion(DisposeResources(env.[[DisposeCapability]], result)).
- Suspend moduleContext and remove it from the execution context stack.
- Resume the context that is now on the top of the execution context stack as the running execution context.
- If result is an abrupt completion, then
- Return ? result.
- Else,
- Assert: capability is a PromiseCapability Record.
- Perform AsyncBlockStart(capability, module.[[ECMAScriptCode]], moduleContext).
- Return unused.
9.1.1.2 Exports
Syntax
ExportDeclaration :
export
ExportFromClause
FromClause
;
export
NamedExports
;
export
VariableStatement[~Yield, +Await]
export
[lookahead ≠ using]
Declaration[~Yield, +Await]
export
default
HoistableDeclaration[~Yield, +Await, +Default]
export
default
ClassDeclaration[~Yield, +Await, +Default]
export
default
[lookahead ∉ { function, async
[no
LineTerminator here]
function, class }]
AssignmentExpression[+In, ~Yield, +Await]
;
ExportFromClause :
*
*
as
IdentifierName
NamedExports
NamedExports :
{
}
{
ExportsList
}
{
ExportsList
,
}
ExportsList :
ExportSpecifier
ExportsList
,
ExportSpecifier
ExportSpecifier :
IdentifierName
IdentifierName
as
IdentifierName
10 The Global Object
10.1 Function Properties of the Global Object
10.1.1 eval ( x )
10.1.1.1 EvalDeclarationInstantiation ( body, varEnv, lexEnv, privateEnv, strict )
The abstract operation EvalDeclarationInstantiation takes arguments body, varEnv, lexEnv, privateEnv, and strict. It performs the following steps when called:
- Let varNames be the VarDeclaredNames of body.
- Let varDeclarations be the VarScopedDeclarations of body.
- If strict is false, then
- If varEnv is a Global Environment Record, then
- For each element name of varNames, do
- If varEnv.HasLexicalDeclaration(name) is true, throw a SyntaxError exception.
- NOTE: eval will not create a global var declaration that would be shadowed by a global lexical declaration.
- Let thisEnv be lexEnv.
- Assert: The following loop will terminate.
- Repeat, while thisEnv is not the same as varEnv,
- If thisEnv is not an Object Environment Record, then
- NOTE: The environment of with statements cannot contain any lexical declaration so it doesn't need to be checked for var/let hoisting conflicts.
- For each element name of varNames, do
- If ! thisEnv.HasBinding(name) is true, then
- Throw a SyntaxError exception.
- NOTE: Annex B.3.4 defines alternate semantics for the above step.
- NOTE: A direct eval will not hoist var declaration over a like-named lexical declaration.
- Set thisEnv to thisEnv.[[OuterEnv]].
- Let privateIdentifiers be a new empty List.
- Let pointer be privateEnv.
- Repeat, while pointer is not null,
- For each Private Name binding of pointer.[[Names]], do
- If privateIdentifiers does not contain binding.[[Description]], append binding.[[Description]] to privateIdentifiers.
- Set pointer to pointer.[[OuterPrivateEnvironment]].
- If AllPrivateIdentifiersValid of body with argument privateIdentifiers is false, throw a SyntaxError exception.
- Let functionsToInitialize be a new empty List.
- Let declaredFunctionNames be a new empty List.
- For each element d of varDeclarations, in reverse List order, do
- If d is neither a VariableDeclaration nor a ForBinding nor a BindingIdentifier, then
- Assert: d is either a FunctionDeclaration, a GeneratorDeclaration, an AsyncFunctionDeclaration, or an AsyncGeneratorDeclaration.
- NOTE: If there are multiple function declarations for the same name, the last declaration is used.
- Let fn be the sole element of the BoundNames of d.
- If fn is not an element of declaredFunctionNames, then
- If varEnv is a Global Environment Record, then
- Let fnDefinable be ? varEnv.CanDeclareGlobalFunction(fn).
- If fnDefinable is false, throw a TypeError exception.
- Append fn to declaredFunctionNames.
- Insert d as the first element of functionsToInitialize.
- NOTE: Annex B.3.2.3 adds additional steps at this point.
- Let declaredVarNames be a new empty List.
- For each element d of varDeclarations, do
- If d is a VariableDeclaration, a ForBinding, or a BindingIdentifier, then
- For each String vn of the BoundNames of d, do
- If vn is not an element of declaredFunctionNames, then
- If varEnv is a Global Environment Record, then
- Let vnDefinable be ? varEnv.CanDeclareGlobalVar(vn).
- If vnDefinable is false, throw a TypeError exception.
- If vn is not an element of declaredVarNames, then
- Append vn to declaredVarNames.
- NOTE: No abnormal terminations occur after this algorithm step unless varEnv is a Global Environment Record and the global object is a Proxy exotic object.
- Let lexDeclarations be the LexicallyScopedDeclarations of body.
- For each element d of lexDeclarations, do
- NOTE: Lexically declared names are only instantiated here but not initialized.
- For each element dn of the BoundNames of d, do
- If IsConstantDeclaration of d is true, then
- Perform ? lexEnv.CreateImmutableBinding(dn, true).
- Else,
- Perform ? lexEnv.CreateMutableBinding(dn, false).
- For each Parse Node f of functionsToInitialize, do
- Let fn be the sole element of the BoundNames of f.
- Let fo be InstantiateFunctionObject of f with arguments lexEnv and privateEnv.
- If varEnv is a Global Environment Record, then
- Perform ? varEnv.CreateGlobalFunctionBinding(fn, fo, true).
- Else,
- Let bindingExists be ! varEnv.HasBinding(fn).
- If bindingExists is false, then
- NOTE: The following invocation cannot return an abrupt completion because of the validation preceding step 14.
- Perform ! varEnv.CreateMutableBinding(fn, true).
- Perform ! varEnv.InitializeBinding(fn, fo, normal).
- Else,
- Perform ! varEnv.SetMutableBinding(fn, fo, false).
- For each String vn of declaredVarNames, do
- If varEnv is a Global Environment Record, then
- Perform ? varEnv.CreateGlobalVarBinding(vn, true).
- Else,
- Let bindingExists be ! varEnv.HasBinding(vn).
- If bindingExists is false, then
- NOTE: The following invocation cannot return an abrupt completion because of the validation preceding step 14.
- Perform ! varEnv.CreateMutableBinding(vn, true).
- Perform ! varEnv.InitializeBinding(vn, undefined, normal).
- Return unused.
Note
An alternative version of this algorithm is described in B.3.4.
11 Fundamental Objects
11.1 Error Objects
Instances of Error objects are thrown as exceptions when runtime errors occur. The Error objects may also serve as base objects for user-defined exception classes.
When an ECMAScript implementation detects a runtime error, it throws a new instance of one of the NativeError objects defined in 20.5.5 or a new instance of either the AggregateError object defined in 11.1.3, or the SuppressedError object defined in 11.1.4. Each of these objects has the structure described below, differing only in the name used as the constructor name instead of NativeError, in the "name" property of the prototype object, in the implementation-defined "message" property of the prototype object, and in the presence of the %AggregateError%-specific "errors" property or the %SuppressedError%-specific "error" and "suppressed" properties.
11.1.1 Properties of Error Instances
Error instances are ordinary objects that inherit properties from the Error prototype object and have an [[ErrorData]] internal slot whose value is undefined. The only specified uses of [[ErrorData]] is to identify Error, AggregateError, SuppressedError, and NativeError instances as Error objects within Object.prototype.toString.
11.1.2 NativeError Object Structure
When an ECMAScript implementation detects a runtime error, it throws a new instance of one of the NativeError objects defined in 20.5.5. Each of these objects has the structure described below, differing only in the name used as the constructor name instead of NativeError, in the "name" property of the prototype object, and in the implementation-defined "message" property of the prototype object.
For each error object, references to NativeError in the definition should be replaced with the appropriate error object name from 20.5.5.
11.1.2.1 Properties of NativeError Instances
NativeError instances are ordinary objects that inherit properties from their NativeError prototype object and have an [[ErrorData]] internal slot whose value is undefined. The only specified use of [[ErrorData]] is by Object.prototype.toString (20.1.3.6) to identify Error, AggregateError, SuppressedError, or NativeError instances.
11.1.3 AggregateError Objects
11.1.3.1 Properties of AggregateError Instances
AggregateError instances are ordinary objects that inherit properties from their AggregateError prototype object and have an [[ErrorData]] internal slot whose value is undefined. The only specified use of [[ErrorData]] is by Object.prototype.toString (20.1.3.6) to identify Error, AggregateError, SuppressedError, or NativeError instances.
11.1.4 SuppressedError Objects
11.1.4.1 The SuppressedError Constructor
The SuppressedError constructor:
- is %SuppressedError%.
- is the initial value of the "SuppressedError" property of the global object.
- creates and initializes a new SuppressedError object when called as a function rather than as a constructor. Thus the function call SuppressedError(…) is equivalent to the object creation expression new SuppressedError(…) with the same arguments.
- may be used as the value of an extends clause of a class definition. Subclass constructors that intend to inherit the specified SuppressedError behaviour must include a super call to the SuppressedError constructor to create and initialize subclass instances with an [[ErrorData]] internal slot.
11.1.4.1.1 SuppressedError ( error, suppressed, message [ , options ] )
This function performs the following steps when called:
- If NewTarget is undefined, let newTarget be the active function object; else let newTarget be NewTarget.
- Let O be ? OrdinaryCreateFromConstructor(newTarget, "%SuppressedError.prototype%", « [[ErrorData]] »).
- If message is not undefined, then
- Let messageString be ? ToString(message).
- Perform CreateNonEnumerableDataPropertyOrThrow(O, "message", messageString).
- Perform ? InstallErrorCause(O, options).
- Perform CreateNonEnumerableDataPropertyOrThrow(O, "error", error).
- Perform CreateNonEnumerableDataPropertyOrThrow(O, "suppressed", suppressed).
- Return O.
11.1.4.2 Properties of the SuppressedError Constructor
The SuppressedError constructor:
- has a [[Prototype]] internal slot whose value is %Error%.
- has the following properties:
11.1.4.2.1 SuppressedError.prototype
The initial value of SuppressedError.prototype is %SuppressedError.prototype%.
This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.
11.1.4.3 Properties of the SuppressedError Prototype Object
The SuppressedError prototype object:
- is %SuppressedError.prototype%.
- is an ordinary object.
- is not an Error instance or an SuppressedError instance and does not have an [[ErrorData]] internal slot.
- has a [[Prototype]] internal slot whose value is %Error.prototype%.
11.1.4.3.1 SuppressedError.prototype.constructor
The initial value of SuppressedError.prototype.constructor is %SuppressedError%.
11.1.4.3.2 SuppressedError.prototype.message
The initial value of SuppressedError.prototype.message is the empty String.
11.1.4.3.3 SuppressedError.prototype.name
The initial value of SuppressedError.prototype.name is "SuppressedError".
11.1.4.4 Properties of SuppressedError Instances
SuppressedError instances are ordinary objects that inherit properties from their SuppressedError prototype object and have an [[ErrorData]] internal slot whose value is undefined. The only specified use of [[ErrorData]] is by Object.prototype.toString (20.1.3.6) to identify Error, AggregateError, SuppressedError, or NativeError instances.
12 Control Abstraction Objects
12.1 Iteration
12.1.1 The %IteratorPrototype% Object
12.1.1.1 %IteratorPrototype% [ @@dispose ] ( )
The following steps are taken:
- Let O be the this value.
- Let return be ? GetMethod(O, "return").
- If return is not undefined, then
- Perform ? Call(return, O, « »).
- Return NormalCompletion(empty).
The value of the "name" property of this function is "[Symbol.dispose]".
12.1.2 The %AsyncIteratorPrototype% Object
12.1.2.1 %AsyncIteratorPrototype% [ @@asyncDispose ] ( )
The following steps are taken:
- Let O be the this value.
- Let promiseCapability be ! NewPromiseCapability(%Promise%).
- Let return be GetMethod(O, "return").
- IfAbruptRejectPromise(return, promiseCapability).
- If return is undefined, then
- Perform ! Call(promiseCapability.[[Resolve]], undefined, « undefined »).
- Else,
- Let result be Call(return, O, « undefined »).
- IfAbruptRejectPromise(result, promiseCapability).
- Let resultWrapper be Completion(PromiseResolve(%Promise%, result)).
- IfAbruptRejectPromise(resultWrapper, promiseCapability).
- Let unwrap be a new Abstract Closure that performs the following steps when called:
- Return undefined.
- Let onFulfilled be CreateBuiltinFunction(unwrap, 1, "", « »).
- Perform PerformPromiseThen(resultWrapper, onFulfilled, undefined, promiseCapability).
- Return promiseCapability.[[Promise]].
The value of the "name" property of this function is "[Symbol.asyncDispose]".
12.2 Resource Management
12.2.1 Common Resource Management Interfaces
An interface is a set of property keys whose associated values match a specific specification. Any object that provides all the properties as described by an interface's specification conforms to that interface. An interface is not represented by a distinct object. There may be many separately implemented objects that conform to any interface. An individual object may conform to multiple interfaces.
12.2.1.1 The Disposable Interface
The Disposable interface includes the property described in Table 6:
Table 6:
Disposable Interface Required Properties
Property
Value
Requirements
|
@@dispose
|
A function.
|
Invoking this method notifies the Disposable object that the caller does not intend to continue to use this object. This method should perform any necessary logic to perform explicit clean-up of the resource including, but not limited to, file system handles, streams, host objects, etc. When an exception is thrown from this method, it typically means that the resource could not be explicitly freed.
If called more than once on the same object, the function should not throw an exception. However, this requirement is not enforced.
When using a Disposable object, it is good practice to create the instance with a using declaration, as the resource will be automatically disposed when the Block or Module immediately containing the declaration has been evaluated.
|
12.2.1.2 The AsyncDisposable Interface
The AsyncDisposable interface includes the property described in Table 7:
Table 7:
AsyncDisposable Interface Required Properties
Property
Value
Requirements
|
@@asyncDispose
|
A function that returns a promise.
|
Invoking this method notifies the AsyncDisposable object that the caller does not intend to continue to use this object. This method should perform any necessary logic to perform explicit clean-up of the resource including, but not limited to, file system handles, streams, host objects, etc. When an exception is thrown from this method, it typically means that the resource could not be explicitly freed. An AsyncDisposable object is not considered "disposed" until the resulting Promise has been fulfilled.
If called more than once on the same object, the function should not throw an exception. However, this requirement is not enforced.
When using an AsyncDisposable object, it is good practice to create the instance with a await using declaration, as the resource will be automatically disposed when the Block or Module immediately containing the declaration has been evaluated.
|
12.3 DisposableStack Objects
A DisposableStack is an object that can be used to contain one or more resources that should be disposed together.
Any DisposableStack object is in one of two mutually exclusive states: disposed or pending:
- A disposable stack d is pending if d[Symbol.dispose]() has yet to be invoked for d.
- A disposable stack d is disposed if d[Symbol.dispose]() has already been invoked once for d.
12.3.1 The DisposableStack Constructor
The DisposableStack constructor:
- is %DisposableStack%.
- is the initial value of the "DisposableStack" property of the global object.
- creates and initializes a new DisposableStack when called as a constructor.
- is not intended to be called as a function and will throw an exception when called in that manner.
- may be used as the value in an extends clause of a class definition. Subclass constructors that intend to inherit the specified DisposableStack behaviour must include a super call to the DisposableStack constructor to create and initialize the subclass instance with the internal state necessary to support the DisposableStack and DisposableStack.prototype built-in methods.
12.3.1.1 DisposableStack ( )
When the DisposableStack function is called, the following steps are taken:
- If NewTarget is undefined, throw a TypeError exception.
- Let disposableStack be ? OrdinaryCreateFromConstructor(NewTarget, "%DisposableStack.prototype%", « [[DisposableState]], [[DisposeCapability]] »).
- Set disposableStack.[[DisposableState]] to pending.
- Set disposableStack.[[DisposeCapability]] to NewDisposeCapability().
- Return disposableStack.
12.3.2 Properties of the DisposableStack Constructor
The DisposableStack constructor:
12.3.3 Properties of the DisposableStack Prototype Object
The DisposableStack prototype object:
- is %DisposableStack.prototype%.
- has a [[Prototype]] internal slot whose value is %Object.prototype%.
- is an ordinary object.
- does not have a [[DisposableState]] internal slot or any of the other internal slots of DisposableStack instances.
12.3.3.1 get DisposableStack.prototype.disposed
DisposableStack.prototype.disposed is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:
- Let disposableStack be the this value.
- Perform ? RequireInternalSlot(disposableStack, [[DisposableState]]).
- If disposableStack.[[DisposableState]] is disposed, return true.
- Otherwise, return false.
12.3.3.2 DisposableStack.prototype.dispose ()
When the dispose method is called, the following steps are taken:
- Let disposableStack be the this value.
- Perform ? RequireInternalSlot(disposableStack, [[DisposableState]]).
- If disposableStack.[[DisposableState]] is disposed, return undefined.
- Set disposableStack.[[DisposableState]] to disposed.
- Return DisposeResources(disposableStack.[[DisposeCapability]], NormalCompletion(undefined)).
12.3.3.3 DisposableStack.prototype.use( value )
When the use function is called with one argument, the following steps are taken:
- Let disposableStack be the this value.
- Perform ? RequireInternalSlot(disposableStack, [[DisposableState]]).
- If disposableStack.[[DisposableState]] is disposed, throw a ReferenceError exception.
- Perform ? AddDisposableResource(disposableStack.[[DisposeCapability]], value, sync-dispose).
- Return value.
12.3.3.4 DisposableStack.prototype.adopt( value, onDispose )
When the adopt function is called with two arguments, the following steps are taken:
- Let disposableStack be the this value.
- Perform ? RequireInternalSlot(disposableStack, [[DisposableState]]).
- If disposableStack.[[DisposableState]] is disposed, throw a ReferenceError exception.
- If IsCallable(onDispose) is false, throw a TypeError exception.
- Let closure be a new Abstract Closure with no parameters that captures value and onDispose and performs the following steps when called:
- Return ? Call(onDispose, undefined, « value »).
- Let F be CreateBuiltinFunction(closure, 0, "", « »).
- Perform ? AddDisposableResource(disposableStack.[[DisposeCapability]], undefined, sync-dispose, F).
- Return value.
12.3.3.5 DisposableStack.prototype.defer( onDispose )
When the defer function is called with one argument, the following steps are taken:
- Let disposableStack be the this value.
- Perform ? RequireInternalSlot(disposableStack, [[DisposableState]]).
- If disposableStack.[[DisposableState]] is disposed, throw a ReferenceError exception.
- If IsCallable(onDispose) is false, throw a TypeError exception.
- Perform ? AddDisposableResource(disposableStack.[[DisposeCapability]], undefined, sync-dispose, onDispose).
- Return undefined.
12.3.3.6 DisposableStack.prototype.move()
When the move function is called, the following steps are taken:
- Let disposableStack be the this value.
- Perform ? RequireInternalSlot(disposableStack, [[DisposableState]]).
- If disposableStack.[[DisposableState]] is disposed, throw a ReferenceError exception.
- Let newDisposableStack be ? OrdinaryCreateFromConstructor(%DisposableStack%, "%DisposableStack.prototype%", « [[DisposableState]], [[DisposeCapability]] »).
- Set newDisposableStack.[[DisposableState]] to pending.
- Set newDisposableStack.[[DisposeCapability]] to disposableStack.[[DisposeCapability]].
- Set disposableStack.[[DisposeCapability]] to NewDisposeCapability().
- Set disposableStack.[[DisposableState]] to disposed.
- Return newDisposableStack.
12.3.3.7 DisposableStack.prototype [ @@dispose ] ()
The initial value of the @@dispose property is %DisposableStack.prototype.dispose%, defined in 12.3.3.2.
12.3.3.8 DisposableStack.prototype [ @@toStringTag ]
The initial value of the @@toStringTag property is the String value "DisposableStack".
This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.
12.3.4 Properties of DisposableStack Instances
DisposableStack instances are ordinary objects that inherit properties from the DisposableStack prototype object (the intrinsic %DisposableStack.prototype%). DisposableStack instances are initially created with internal slots described in Table 8.
Table 8: Internal Slots of DisposableStack Instances
Internal Slot
Type
Description
|
[[DisposableState]]
|
pending or disposed
|
Governs how a disposable stack will react to incoming calls to its @@dispose method.
|
|
[[DisposeCapability]]
|
a DisposeCapability Record
|
Resources to be disposed when the disposable stack is disposed.
|
12.4 AsyncDisposableStack Objects
An AsyncDisposableStack is an object that can be used to contain one or more resources that should be asynchronously disposed together.
Any AsyncDisposableStack object is in one of two mutually exclusive states: disposed or pending:
- An async-disposable stack d is pending if d[Symbol.asyncDispose]() has yet to be invoked for d.
- An async-disposable stack d is disposed if d[Symbol.asyncDispose]() has already been invoked once for d.
12.4.1 The AsyncDisposableStack Constructor
The AsyncDisposableStack constructor:
- is %AsyncDisposableStack%.
- is the initial value of the "AsyncDisposableStack" property of the global object.
- creates and initializes a new AsyncDisposableStack when called as a constructor.
- is not intended to be called as a function and will throw an exception when called in that manner.
- may be used as the value in an extends clause of a class definition. Subclass constructors that intend to inherit the specified AsyncDisposableStack behaviour must include a super call to the AsyncDisposableStack constructor to create and initialize the subclass instance with the internal state necessary to support the AsyncDisposableStack and AsyncDisposableStack.prototype built-in methods.
12.4.1.1 AsyncDisposableStack ( )
When the AsyncDisposableStack function is called, the following steps are taken:
- If NewTarget is undefined, throw a TypeError exception.
- Let asyncDisposableStack be ? OrdinaryCreateFromConstructor(NewTarget, "%AsyncDisposableStack.prototype%", « [[AsyncDisposableState]], [[DisposeCapability]] »).
- Set asyncDisposableStack.[[AsyncDisposableState]] to pending.
- Set asyncDisposableStack.[[DisposeCapability]] to NewDisposeCapability().
- Return asyncDisposableStack.
12.4.2 Properties of the AsyncDisposableStack Constructor
The AsyncDisposableStack constructor:
12.4.3 Properties of the AsyncDisposableStack Prototype Object
The AsyncDisposableStack prototype object:
- is %AsyncDisposableStack.prototype%.
- has a [[Prototype]] internal slot whose value is %Object.prototype%.
- is an ordinary object.
- does not have an [[AsyncDisposableState]] internal slot or any of the other internal slots of AsyncDisposableStack instances.
12.4.3.1 get AsyncDisposableStack.prototype.disposed
AsyncDisposableStack.prototype.disposed is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:
- Let asyncDisposableStack be the this value.
- Perform ? RequireInternalSlot(asyncDisposableStack, [[AsyncDisposableState]]).
- If asyncDisposableStack.[[AsyncDisposableState]] is disposed, return true.
- Otherwise, return false.
12.4.3.2 AsyncDisposableStack.prototype.disposeAsync()
When the disposeAsync method is called, the following steps are taken:
- Let asyncDisposableStack be the this value.
- Let promiseCapability be ! NewPromiseCapability(%Promise%).
- If asyncDisposableStack does not have an [[AsyncDisposableState]] internal slot, then
- Perform ! Call(promiseCapability.[[Reject]], undefined, « a newly created TypeError object »).
- Return promiseCapability.[[Promise]].
- If asyncDisposableStack.[[AsyncDisposableState]] is disposed, then
- Perform ! Call(promiseCapability.[[Resolve]], undefined, « undefined »).
- Return promiseCapability.[[Promise]].
- Set asyncDisposableStack.[[AsyncDisposableState]] to disposed.
- Let result be DisposeResources(asyncDisposableStack.[[DisposeCapability]], NormalCompletion(undefined)).
- IfAbruptRejectPromise(result, promiseCapability).
- Perform ! Call(promiseCapability.[[Resolve]], undefined, « result »).
- Return promiseCapability.[[Promise]].
12.4.3.3 AsyncDisposableStack.prototype.use( value )
When the use function is called with one argument, the following steps are taken:
- Let asyncDisposableStack be the this value.
- Perform ? RequireInternalSlot(asyncDisposableStack, [[AsyncDisposableState]]).
- If asyncDisposableStack.[[AsyncDisposableState]] is disposed, throw a ReferenceError exception.
- Perform ? AddDisposableResource(asyncDisposableStack.[[DisposeCapability]], value, async-dispose).
- Return value.
12.4.3.4 AsyncDisposableStack.prototype.adopt( value, onDisposeAsync )
When the adopt function is called with two arguments, the following steps are taken:
- Let asyncDisposableStack be the this value.
- Perform ? RequireInternalSlot(asyncDisposableStack, [[AsyncDisposableState]]).
- If asyncDisposableStack.[[AsyncDisposableState]] is disposed, throw a ReferenceError exception.
- If IsCallable(onDisposeAsync) is false, throw a TypeError exception.
- Let closure be a new Abstract Closure with no parameters that captures value and onDisposeAsync and performs the following steps when called:
- Return ? Call(onDisposeAsync, undefined, « value »).
- Let F be CreateBuiltinFunction(closure, 0, "", « »).
- Perform ? AddDisposableResource(asyncDisposableStack.[[DisposeCapability]], undefined, async-dispose, F).
- Return value.
12.4.3.5 AsyncDisposableStack.prototype.defer( onDisposeAsync )
When the defer function is called with one argument, the following steps are taken:
- Let asyncDisposableStack be the this value.
- Perform ? RequireInternalSlot(asyncDisposableStack, [[AsyncDisposableState]]).
- If asyncDisposableStack.[[AsyncDisposableState]] is disposed, throw a ReferenceError exception.
- If IsCallable(onDisposeAsync) is false, throw a TypeError exception.
- Perform ? AddDisposableResource(asyncDisposableStack.[[DisposeCapability]], undefined, async-dispose, onDisposeAsync).
- Return undefined.
12.4.3.6 AsyncDisposableStack.prototype.move()
When the move function is called, the following steps are taken:
- Let asyncDisposableStack be the this value.
- Perform ? RequireInternalSlot(asyncDisposableStack, [[AsyncDisposableState]]).
- If asyncDisposableStack.[[AsyncDisposableState]] is disposed, throw a ReferenceError exception.
- Let newAsyncDisposableStack be ? OrdinaryCreateFromConstructor(%AsyncDisposableStack%, "%AsyncDisposableStack.prototype%", « [[AsyncDisposableState]], [[DisposeCapability]] »).
- Set newAsyncDisposableStack.[[AsyncDisposableState]] to pending.
- Set newAsyncDisposableStack.[[DisposeCapability]] to asyncDisposableStack.[[DisposeCapability]].
- Set asyncDisposableStack.[[DisposeCapability]] to NewDisposeCapability().
- Set asyncDisposableStack.[[AsyncDisposableState]] to disposed.
- Return newAsyncDisposableStack.
12.4.3.7 AsyncDisposableStack.prototype [ @@asyncDispose ] ()
The initial value of the @@asyncDispose property is %AsyncDisposableStack.prototype.disposeAsync%, defined in 12.4.3.2.
12.4.3.8 AsyncDisposableStack.prototype [ @@toStringTag ]
The initial value of the @@toStringTag property is the String value "AsyncDisposableStack".
This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.
12.4.4 Properties of AsyncDisposableStack Instances
AsyncDisposableStack instances are ordinary objects that inherit properties from the AsyncDisposableStack prototype object (the intrinsic %AsyncDisposableStack.prototype%). AsyncDisposableStack instances are initially created with internal slots described in Table 9.
Table 9: Internal Slots of AsyncDisposableStack Instances
Internal Slot
Type
Description
|
[[AsyncDisposableState]]
|
pending or disposed
|
Governs how a disposable stack will react to incoming calls to its @@asyncDispose method.
|
|
[[DisposeCapability]]
|
a DisposeCapability Record
|
Resources to be disposed when the disposable stack is disposed.
|
12.5 Generator Objects
12.5.1 Generator Abstract Operations
12.5.1.1 GeneratorStart ( generator, generatorBody )
The abstract operation GeneratorStart takes arguments generator and generatorBody (a FunctionBody Parse Node or an Abstract Closure with no parameters) and returns unused. It performs the following steps when called:
- Assert: The value of generator.[[GeneratorState]] is undefined.
- Let genContext be the running execution context.
- Set the Generator component of genContext to generator.
- Set the code evaluation state of genContext such that when evaluation is resumed for that execution context the following steps will be performed:
- If generatorBody is a Parse Node, then
- Let result be the result of evaluating generatorBody.
- Else,
- Assert: generatorBody is an Abstract Closure with no parameters.
- Let result be generatorBody().
- Assert: If we return here, the generator either threw an exception or performed either an implicit or explicit return.
- Remove genContext from the execution context stack and restore the execution context that is at the top of the execution context stack as the running execution context.
- Set generator.[[GeneratorState]] to completed.
- Once a generator enters the completed state it never leaves it and its associated execution context is never resumed. Any execution state associated with generator can be discarded at this point.
- Let env be genContext's LexicalEnvironment.
- Set result to DisposeResources(env.[[DisposeCapability]], result).
- If result.[[Type]] is normal, let resultValue be undefined.
- Else if result.[[Type]] is return, let resultValue be result.[[Value]].
- Else,
- Assert: result.[[Type]] is throw.
- Return ? result.
- Return CreateIterResultObject(resultValue, true).
- Set generator.[[GeneratorContext]] to genContext.
- Set generator.[[GeneratorState]] to suspendedStart.
- Return unused.
12.6 AsyncGenerator Objects
12.6.1 AsyncGenerator Abstract Operations
12.6.1.1 AsyncGeneratorStart ( generator, generatorBody )
The abstract operation AsyncGeneratorStart takes arguments generator (an AsyncGenerator) and generatorBody (a FunctionBody Parse Node or an Abstract Closure with no parameters) and returns unused. It performs the following steps when called:
- Assert: generator.[[AsyncGeneratorState]] is undefined.
- Let genContext be the running execution context.
- Set the Generator component of genContext to generator.
- Set the code evaluation state of genContext such that when evaluation is resumed for that execution context the following steps will be performed:
- If generatorBody is a Parse Node, then
- Let result be the result of evaluating generatorBody.
- Else,
- Assert: generatorBody is an Abstract Closure with no parameters.
- Let result be Completion(generatorBody()).
- Assert: If we return here, the async generator either threw an exception or performed either an implicit or explicit return.
- Remove genContext from the execution context stack and restore the execution context that is at the top of the execution context stack as the running execution context.
- Set generator.[[AsyncGeneratorState]] to completed.
- Let env be genContext's LexicalEnvironment.
- Set result to DisposeResources(env.[[DisposeCapability]], result).
- If result.[[Type]] is normal, set result to NormalCompletion(undefined).
- If result.[[Type]] is return, set result to NormalCompletion(result.[[Value]]).
- Perform AsyncGeneratorCompleteStep(generator, result, true).
- Perform AsyncGeneratorDrainQueue(generator).
- Return undefined.
- Set generator.[[AsyncGeneratorContext]] to genContext.
- Set generator.[[AsyncGeneratorState]] to suspendedStart.
- Set generator.[[AsyncGeneratorQueue]] to a new empty List.
- Return unused.
12.7 AsyncFunction Objects
12.7.1 Async Functions Abstract Operations
12.7.1.1 AsyncBlockStart ( promiseCapability, asyncBody, asyncContext )
The abstract operation AsyncBlockStart takes arguments promiseCapability (a PromiseCapability Record), asyncBody (a Parse Node), and asyncContext (an execution context) and returns unused. It performs the following steps when called:
- Assert: promiseCapability is a PromiseCapability Record.
- Let runningContext be the running execution context.
- Set the code evaluation state of asyncContext such that when evaluation is resumed for that execution context the following steps will be performed:
- Let result be the result of evaluating asyncBody.
- Assert: If we return here, the async function either threw an exception or performed an implicit or explicit return; all awaiting is done.
- Remove asyncContext from the execution context stack and restore the execution context that is at the top of the execution context stack as the running execution context.
- Let env be asyncContext's LexicalEnvironment.
- Set result to DisposeResources(env.[[DisposeCapability]], result).
- If result.[[Type]] is normal, then
- Perform ! Call(promiseCapability.[[Resolve]], undefined, « undefined »).
- Else if result.[[Type]] is return, then
- Perform ! Call(promiseCapability.[[Resolve]], undefined, « result.[[Value]] »).
- Else,
- Assert: result.[[Type]] is throw.
- Perform ! Call(promiseCapability.[[Reject]], undefined, « result.[[Value]] »).
- Return unused.
- Push asyncContext onto the execution context stack; asyncContext is now the running execution context.
- Resume the suspended evaluation of asyncContext. Let result be the value returned by the resumed computation.
- Assert: When we return here, asyncContext has already been removed from the execution context stack and runningContext is the currently running execution context.
- Assert: result is a normal completion with a value of unused. The possible sources of this value are Await or, if the async function doesn't await anything, step 3.i above.
- Return unused.
A Additional ECMAScript Features for Web Browsers
A.1 Other Additional Features
A.1.1 Block-Level Function Declarations Web Legacy Compatibility Semantics
A.1.1.1 Changes to BlockDeclarationInstantiation
During BlockDeclarationInstantiation the following steps are performed in place of step 3.a.ii.1:
- If env.HasBinding(dn) is false, then
- Perform ! env.CreateMutableBinding(dn, false).
During BlockDeclarationInstantiation the following steps are performed in place of step 3.b.iii:
- If the binding for fn in env is an uninitialized binding, then
- Perform env.InitializeBinding(fn, fo, normal).
- Else,
- Assert: d is a FunctionDeclaration.
- Perform env.SetMutableBinding(fn, fo, false).
B Copyright & Software License
Copyright Notice
© 2023 Ron Buckton, Ecma International
Software License
All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
- Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.