Stage 2 Draft / March 22, 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
Intrinsic Name Global Name ECMAScript Language Association
%AggregateError% AggregateError The AggregateError constructor (20.5.7.1)
%Array% Array The Array constructor (23.1.1)
%ArrayBuffer% ArrayBuffer The ArrayBuffer constructor (25.1.3)
%ArrayIteratorPrototype% The prototype of Array iterator objects (23.1.5)
%AsyncDisposableStack% AsyncDisposableStack The AsyncDisposableStack constructor (12.4.1)
%AsyncFromSyncIteratorPrototype% The prototype of async-from-sync iterator objects (27.1.4)
%AsyncFunction% The constructor of async function objects (27.7.1)
%AsyncGeneratorFunction% The constructor of async iterator objects (27.4.1)
%AsyncIteratorPrototype% An object that all standard built-in async iterator objects indirectly inherit from
%Atomics% Atomics The Atomics object (25.4)
%BigInt% BigInt The BigInt constructor (21.2.1)
%BigInt64Array% BigInt64Array The BigInt64Array constructor (23.2)
%BigUint64Array% BigUint64Array The BigUint64Array constructor (23.2)
%Boolean% Boolean The Boolean constructor (20.3.1)
%DataView% DataView The DataView constructor (25.3.2)
%Date% Date The Date constructor (21.4.2)
%decodeURI% decodeURI The decodeURI function (19.2.6.2)
%decodeURIComponent% decodeURIComponent The decodeURIComponent function (19.2.6.3)
%DisposableStack% DisposableStack The DisposableStack constructor (12.3.1)
%encodeURI% encodeURI The encodeURI function (19.2.6.4)
%encodeURIComponent% encodeURIComponent The encodeURIComponent function (19.2.6.5)
%Error% Error The Error constructor (20.5.1)
%eval% eval The eval function (10.1.1)
%EvalError% EvalError The EvalError constructor (20.5.5.1)
%FinalizationRegistry% FinalizationRegistry The FinalizationRegistry constructor (26.2.1)
%Float32Array% Float32Array The Float32Array constructor (23.2)
%Float64Array% Float64Array The Float64Array constructor (23.2)
%ForInIteratorPrototype% The prototype of For-In iterator objects (14.7.5.10)
%Function% Function The Function constructor (20.2.1)
%GeneratorFunction% The constructor of Generators (27.3.1)
%Int8Array% Int8Array The Int8Array constructor (23.2)
%Int16Array% Int16Array The Int16Array constructor (23.2)
%Int32Array% Int32Array The Int32Array constructor (23.2)
%isFinite% isFinite The isFinite function (19.2.2)
%isNaN% isNaN The isNaN function (19.2.3)
%IteratorPrototype% An object that all standard built-in iterator objects indirectly inherit from
%JSON% JSON The JSON object (25.5)
%Map% Map The Map constructor (24.1.1)
%MapIteratorPrototype% The prototype of Map iterator objects (24.1.5)
%Math% Math The Math object (21.3)
%Number% Number The Number constructor (21.1.1)
%Object% Object The Object constructor (20.1.1)
%parseFloat% parseFloat The parseFloat function (19.2.4)
%parseInt% parseInt The parseInt function (19.2.5)
%Promise% Promise The Promise constructor (27.2.3)
%Proxy% Proxy The Proxy constructor (28.2.1)
%RangeError% RangeError The RangeError constructor (20.5.5.2)
%ReferenceError% ReferenceError The ReferenceError constructor (20.5.5.3)
%Reflect% Reflect The Reflect object (28.1)
%RegExp% RegExp The RegExp constructor (22.2.3)
%RegExpStringIteratorPrototype% The prototype of RegExp String Iterator objects (22.2.7)
%Set% Set The Set constructor (24.2.1)
%SetIteratorPrototype% The prototype of Set iterator objects (24.2.5)
%SharedArrayBuffer% SharedArrayBuffer The SharedArrayBuffer constructor (25.2.2)
%String% String The String constructor (22.1.1)
%StringIteratorPrototype% The prototype of String iterator objects (22.1.5)
%SuppressedError% SuppressedError The SuppressedError constructor (11.1.4.1)
%Symbol% Symbol The Symbol constructor (20.4.1)
%SyntaxError% SyntaxError The SyntaxError constructor (20.5.5.4)
%ThrowTypeError% A function object that unconditionally throws a new instance of %TypeError%
%TypedArray% The super class of all typed Array constructors (23.2.1)
%TypeError% TypeError The TypeError constructor (20.5.5.5)
%Uint8Array% Uint8Array The Uint8Array constructor (23.2)
%Uint8ClampedArray% Uint8ClampedArray The Uint8ClampedArray constructor (23.2)
%Uint16Array% Uint16Array The Uint16Array constructor (23.2)
%Uint32Array% Uint32Array The Uint32Array constructor (23.2)
%URIError% URIError The URIError constructor (20.5.5.6)
%WeakMap% WeakMap The WeakMap constructor (24.3.1)
%WeakRef% WeakRef The WeakRef constructor (26.1.1)
%WeakSet% WeakSet The WeakSet constructor (24.4.1)

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:

  1. ReturnIfAbrupt(V).
  2. ReturnIfAbrupt(W).
  3. Assert: V is a Reference Record.
  4. Assert: IsUnresolvableReference(V) is false.
  5. Let base be V.[[Base]].
  6. Assert: base is an Environment Record.
  7. 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:

  1. Let stack be a new empty List.
  2. 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:

  1. If method is not present then,
    1. If V is either null or undefined and hint is sync-dispose, then
      1. Return unused.
    2. Let resource be ? CreateDisposableResource(V, hint).
  2. Else,
    1. If V is either null or undefined, then
      1. Let resource be ? CreateDisposableResource(undefined, hint, method).
    2. Else,
      1. If V is not an Object, throw a TypeError exception.
      2. Let resource be ? CreateDisposableResource(V, hint, method).
  3. Append resource to disposeCapability.[[DisposableResourceStack]].
  4. 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:

  1. If method is not present, then
    1. If V is either null or undefined, then
      1. Set V to undefined.
      2. Set method to undefined.
    2. Else,
      1. If V is not an Object, throw a TypeError exception.
      2. Set method to ? GetDisposeMethod(V, hint).
      3. If method is undefined, throw a TypeError exception.
  2. Else,
    1. If IsCallable(method) is false, throw a TypeError exception.
  3. 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:

  1. If hint is async-dispose, then
    1. Let method be ? GetMethod(V, @@asyncDispose).
    2. If method is undefined, then
      1. Set method to ? GetMethod(V, @@dispose).
  2. Else,
    1. Let method be ? GetMethod(V, @@dispose).
  3. 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:

  1. If method is undefined, let result be undefined.
  2. Else, let result be ? Call(method, V).
  3. If hint is async-dispose, then
    1. Perform ? Await(result).
  4. 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:

  1. For each resource of disposeCapability.[[DisposableResourceStack]], in reverse List order, do
    1. Let result be Dispose(resource.[[ResourceValue]], resource.[[Hint]], resource.[[DisposeMethod]]).
    2. If result.[[Type]] is throw, then
      1. If completion.[[Type]] is throw, then
        1. Set result to result.[[Value]].
        2. Let suppressed be completion.[[Value]].
        3. Let error be a newly created SuppressedError object.
        4. Perform ! CreateNonEnumerableDataPropertyOrThrow(error, "error", result).
        5. Perform ! CreateNonEnumerableDataPropertyOrThrow(error, "suppressed", suppressed).
        6. Set completion to ThrowCompletion(error).
      2. Else,
        1. Set completion to result.
  2. 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
  1. Return a List whose sole element is the StringValue of Identifier.
BindingIdentifier : yield
  1. Return « "yield" ».
BindingIdentifier : await
  1. Return « "await" ».
LexicalDeclaration : LetOrConst BindingList ;
  1. Return the BoundNames of BindingList.
UsingDeclaration : using BindingList ; AwaitUsingDeclaration : CoverAwaitExpressionAndAwaitUsingDeclarationHead BindingList ;
  1. Return the BoundNames of BindingList.
BindingList : BindingList , LexicalBinding
  1. Let names1 be the BoundNames of BindingList.
  2. Let names2 be the BoundNames of LexicalBinding.
  3. Return the list-concatenation of names1 and names2.
LexicalBinding : BindingIdentifier Initializeropt
  1. Return the BoundNames of BindingIdentifier.
LexicalBinding : BindingPattern Initializer
  1. Return the BoundNames of BindingPattern.
VariableDeclarationList : VariableDeclarationList , VariableDeclaration
  1. Let names1 be BoundNames of VariableDeclarationList.
  2. Let names2 be BoundNames of VariableDeclaration.
  3. Return the list-concatenation of names1 and names2.
VariableDeclaration : BindingIdentifier Initializeropt
  1. Return the BoundNames of BindingIdentifier.
VariableDeclaration : BindingPattern Initializer
  1. Return the BoundNames of BindingPattern.
ObjectBindingPattern : { }
  1. Return a new empty List.
ObjectBindingPattern : { BindingPropertyList , BindingRestProperty }
  1. Let names1 be BoundNames of BindingPropertyList.
  2. Let names2 be BoundNames of BindingRestProperty.
  3. Return the list-concatenation of names1 and names2.
ArrayBindingPattern : [ Elisionopt ]
  1. Return a new empty List.
ArrayBindingPattern : [ Elisionopt BindingRestElement ]
  1. Return the BoundNames of BindingRestElement.
ArrayBindingPattern : [ BindingElementList , Elisionopt ]
  1. Return the BoundNames of BindingElementList.
ArrayBindingPattern : [ BindingElementList , Elisionopt BindingRestElement ]
  1. Let names1 be BoundNames of BindingElementList.
  2. Let names2 be BoundNames of BindingRestElement.
  3. Return the list-concatenation of names1 and names2.
BindingPropertyList : BindingPropertyList , BindingProperty
  1. Let names1 be BoundNames of BindingPropertyList.
  2. Let names2 be BoundNames of BindingProperty.
  3. Return the list-concatenation of names1 and names2.
BindingElementList : BindingElementList , BindingElisionElement
  1. Let names1 be BoundNames of BindingElementList.
  2. Let names2 be BoundNames of BindingElisionElement.
  3. Return the list-concatenation of names1 and names2.
BindingElisionElement : Elisionopt BindingElement
  1. Return BoundNames of BindingElement.
BindingProperty : PropertyName : BindingElement
  1. Return the BoundNames of BindingElement.
SingleNameBinding : BindingIdentifier Initializeropt
  1. Return the BoundNames of BindingIdentifier.
BindingElement : BindingPattern Initializeropt
  1. Return the BoundNames of BindingPattern.
ForDeclaration : LetOrConst ForBinding
  1. Return the BoundNames of ForBinding.
FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody }
  1. Return the BoundNames of BindingIdentifier.
FunctionDeclaration : function ( FormalParameters ) { FunctionBody }
  1. Return « "*default*" ».
FormalParameters : [empty]
  1. Return a new empty List.
FormalParameters : FormalParameterList , FunctionRestParameter
  1. Let names1 be BoundNames of FormalParameterList.
  2. Let names2 be BoundNames of FunctionRestParameter.
  3. Return the list-concatenation of names1 and names2.
FormalParameterList : FormalParameterList , FormalParameter
  1. Let names1 be BoundNames of FormalParameterList.
  2. Let names2 be BoundNames of FormalParameter.
  3. Return the list-concatenation of names1 and names2.
ArrowParameters : CoverParenthesizedExpressionAndArrowParameterList
  1. Let formals be the ArrowFormalParameters that is covered by CoverParenthesizedExpressionAndArrowParameterList.
  2. Return the BoundNames of formals.
GeneratorDeclaration : function * BindingIdentifier ( FormalParameters ) { GeneratorBody }
  1. Return the BoundNames of BindingIdentifier.
GeneratorDeclaration : function * ( FormalParameters ) { GeneratorBody }
  1. Return « "*default*" ».
AsyncGeneratorDeclaration : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody }
  1. Return the BoundNames of BindingIdentifier.
AsyncGeneratorDeclaration : async function * ( FormalParameters ) { AsyncGeneratorBody }
  1. Return « "*default*" ».
ClassDeclaration : class BindingIdentifier ClassTail
  1. Return the BoundNames of BindingIdentifier.
ClassDeclaration : class ClassTail
  1. Return « "*default*" ».
AsyncFunctionDeclaration : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody }
  1. Return the BoundNames of BindingIdentifier.
AsyncFunctionDeclaration : async function ( FormalParameters ) { AsyncFunctionBody }
  1. Return « "*default*" ».
CoverCallExpressionAndAsyncArrowHead : MemberExpression Arguments
  1. Let head be the AsyncArrowHead that is covered by CoverCallExpressionAndAsyncArrowHead.
  2. Return the BoundNames of head.
ImportDeclaration : import ImportClause FromClause ;
  1. Return the BoundNames of ImportClause.
ImportDeclaration : import ModuleSpecifier ;
  1. Return a new empty List.
ImportClause : ImportedDefaultBinding , NameSpaceImport
  1. Let names1 be the BoundNames of ImportedDefaultBinding.
  2. Let names2 be the BoundNames of NameSpaceImport.
  3. Return the list-concatenation of names1 and names2.
ImportClause : ImportedDefaultBinding , NamedImports
  1. Let names1 be the BoundNames of ImportedDefaultBinding.
  2. Let names2 be the BoundNames of NamedImports.
  3. Return the list-concatenation of names1 and names2.
NamedImports : { }
  1. Return a new empty List.
ImportsList : ImportsList , ImportSpecifier
  1. Let names1 be the BoundNames of ImportsList.
  2. Let names2 be the BoundNames of ImportSpecifier.
  3. Return the list-concatenation of names1 and names2.
ImportSpecifier : ModuleExportName as ImportedBinding
  1. Return the BoundNames of ImportedBinding.
ExportDeclaration : export ExportFromClause FromClause ; export NamedExports ;
  1. Return a new empty List.
ExportDeclaration : export VariableStatement
  1. Return the BoundNames of VariableStatement.
ExportDeclaration : export Declaration
  1. Return the BoundNames of Declaration.
ExportDeclaration : export default HoistableDeclaration
  1. Let declarationNames be the BoundNames of HoistableDeclaration.
  2. If declarationNames does not include the element "*default*", append "*default*" to declarationNames.
  3. Return declarationNames.
ExportDeclaration : export default ClassDeclaration
  1. Let declarationNames be the BoundNames of ClassDeclaration.
  2. If declarationNames does not include the element "*default*", append "*default*" to declarationNames.
  3. Return declarationNames.
ExportDeclaration : export default AssignmentExpression ;
  1. 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 ;
  1. Return IsConstantDeclaration of LetOrConst.
LetOrConst : let
  1. Return false.
LetOrConst : const
  1. Return true.
UsingDeclaration : using BindingList ; AwaitUsingDeclaration : CoverAwaitExpressionAndAwaitUsingDeclarationHead BindingList ;
  1. 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 }
  1. Return false.
ClassDeclaration : class BindingIdentifier ClassTail class ClassTail
  1. Return false.
ExportDeclaration : export ExportFromClause FromClause ; export NamedExports ; export default AssignmentExpression ;
  1. 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 ;
  1. Return false.
UsingDeclaration : using BindingList ; AwaitUsingDeclaration : CoverAwaitExpressionAndAwaitUsingDeclarationHead BindingList ;
  1. Return true.
ForDeclaration : LetOrConst ForBinding
  1. Return false.
ForDeclaration : using ForBinding await using ForBinding
  1. 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 }
  1. Return false.
ClassDeclaration : class BindingIdentifier ClassTail class ClassTail
  1. Return false.
ExportDeclaration : export ExportFromClause FromClause ; export NamedExports ; export default AssignmentExpression ;
  1. 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 ;
  1. Return false.
UsingDeclaration : using BindingList ;
  1. Return false.
AwaitUsingDeclaration : CoverAwaitExpressionAndAwaitUsingDeclarationHead BindingList ;
  1. Return true.
ForDeclaration : LetOrConst ForBinding
  1. Return false.
ForDeclaration : using ForBinding
  1. Return false.
ForDeclaration : await using ForBinding
  1. 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 }
  1. Return false.
ClassDeclaration : class BindingIdentifier ClassTail class ClassTail
  1. Return false.
ExportDeclaration : export ExportFromClause FromClause ; export NamedExports ; export default AssignmentExpression ;
  1. 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
  1. Let expr be the ParenthesizedExpression that is covered by CoverParenthesizedExpressionAndArrowParameterList.
  2. 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
  1. 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
  1. 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 : [ ]
  1. Return unused.
ArrayBindingPattern : [ Elision ]
  1. Return ? IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord.
ArrayBindingPattern : [ Elisionopt BindingRestElement ]
  1. If Elision is present, then
    1. Perform ? IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord.
  2. Return ? IteratorBindingInitialization of BindingRestElement with arguments iteratorRecord and environment.
ArrayBindingPattern : [ BindingElementList , Elision ]
  1. Perform ? IteratorBindingInitialization of BindingElementList with arguments iteratorRecord and environment.
  2. Return ? IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord.
ArrayBindingPattern : [ BindingElementList , Elisionopt BindingRestElement ]
  1. Perform ? IteratorBindingInitialization of BindingElementList with arguments iteratorRecord and environment.
  2. If Elision is present, then
    1. Perform ? IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord.
  3. Return ? IteratorBindingInitialization of BindingRestElement with arguments iteratorRecord and environment.
BindingElementList : BindingElementList , BindingElisionElement
  1. Perform ? IteratorBindingInitialization of BindingElementList with arguments iteratorRecord and environment.
  2. Return ? IteratorBindingInitialization of BindingElisionElement with arguments iteratorRecord and environment.
BindingElisionElement : Elision BindingElement
  1. Perform ? IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord.
  2. Return ? IteratorBindingInitialization of BindingElement with arguments iteratorRecord and environment.
SingleNameBinding : BindingIdentifier Initializeropt
  1. Let bindingId be StringValue of BindingIdentifier.
  2. Let lhs be ? ResolveBinding(bindingId, environment).
  3. Let v be undefined.
  4. If iteratorRecord.[[Done]] is false, then
    1. Let next be Completion(IteratorStep(iteratorRecord)).
    2. If next is an abrupt completion, set iteratorRecord.[[Done]] to true.
    3. ReturnIfAbrupt(next).
    4. If next is false, set iteratorRecord.[[Done]] to true.
    5. Else,
      1. Set v to Completion(IteratorValue(next)).
      2. If v is an abrupt completion, set iteratorRecord.[[Done]] to true.
      3. ReturnIfAbrupt(v).
  5. If Initializer is present and v is undefined, then
    1. If IsAnonymousFunctionDefinition(Initializer) is true, then
      1. Set v to ? NamedEvaluation of Initializer with argument bindingId.
    2. Else,
      1. Let defaultValue be ? Evaluation of Initializer.
      2. Set v to ? GetValue(defaultValue).
  6. If environment is undefined, return ? PutValue(lhs, v).
  7. Return ? InitializeReferencedBinding(lhs, v, normal).
BindingElement : BindingPattern Initializeropt
  1. Let v be undefined.
  2. If iteratorRecord.[[Done]] is false, then
    1. Let next be Completion(IteratorStep(iteratorRecord)).
    2. If next is an abrupt completion, set iteratorRecord.[[Done]] to true.
    3. ReturnIfAbrupt(next).
    4. If next is false, set iteratorRecord.[[Done]] to true.
    5. Else,
      1. Set v to Completion(IteratorValue(next)).
      2. If v is an abrupt completion, set iteratorRecord.[[Done]] to true.
      3. ReturnIfAbrupt(v).
  3. If Initializer is present and v is undefined, then
    1. Let defaultValue be ? Evaluation of Initializer.
    2. Set v to ? GetValue(defaultValue).
  4. Return ? BindingInitialization of BindingPattern with arguments v and environment.
BindingRestElement : ... BindingIdentifier
  1. Let lhs be ? ResolveBinding(StringValue of BindingIdentifier, environment).
  2. Let A be ! ArrayCreate(0).
  3. Let n be 0.
  4. Repeat,
    1. If iteratorRecord.[[Done]] is false, then
      1. Let next be Completion(IteratorStep(iteratorRecord)).
      2. If next is an abrupt completion, set iteratorRecord.[[Done]] to true.
      3. ReturnIfAbrupt(next).
      4. If next is false, set iteratorRecord.[[Done]] to true.
    2. If iteratorRecord.[[Done]] is true, then
      1. If environment is undefined, return ? PutValue(lhs, A).
      2. Return ? InitializeReferencedBinding(lhs, A, normal).
    3. Let nextValue be Completion(IteratorValue(next)).
    4. If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true.
    5. ReturnIfAbrupt(nextValue).
    6. Perform ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(n)), nextValue).
    7. Set n to n + 1.
BindingRestElement : ... BindingPattern
  1. Let A be ! ArrayCreate(0).
  2. Let n be 0.
  3. Repeat,
    1. If iteratorRecord.[[Done]] is false, then
      1. Let next be Completion(IteratorStep(iteratorRecord)).
      2. If next is an abrupt completion, set iteratorRecord.[[Done]] to true.
      3. ReturnIfAbrupt(next).
      4. If next is false, set iteratorRecord.[[Done]] to true.
    2. If iteratorRecord.[[Done]] is true, then
      1. Return ? BindingInitialization of BindingPattern with arguments A and environment.
    3. Let nextValue be Completion(IteratorValue(next)).
    4. If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true.
    5. ReturnIfAbrupt(nextValue).
    6. Perform ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(n)), nextValue).
    7. Set n to n + 1.
FormalParameters : [empty]
  1. Return unused.
FormalParameters : FormalParameterList , FunctionRestParameter
  1. Perform ? IteratorBindingInitialization of FormalParameterList with arguments iteratorRecord and environment.
  2. Return ? IteratorBindingInitialization of FunctionRestParameter with arguments iteratorRecord and environment.
FormalParameterList : FormalParameterList , FormalParameter
  1. Perform ? IteratorBindingInitialization of FormalParameterList with arguments iteratorRecord and environment.
  2. Return ? IteratorBindingInitialization of FormalParameter with arguments iteratorRecord and environment.
ArrowParameters : BindingIdentifier
  1. Let v be undefined.
  2. Assert: iteratorRecord.[[Done]] is false.
  3. Let next be Completion(IteratorStep(iteratorRecord)).
  4. If next is an abrupt completion, set iteratorRecord.[[Done]] to true.
  5. ReturnIfAbrupt(next).
  6. If next is false, set iteratorRecord.[[Done]] to true.
  7. Else,
    1. Set v to Completion(IteratorValue(next)).
    2. If v is an abrupt completion, set iteratorRecord.[[Done]] to true.
    3. ReturnIfAbrupt(v).
  8. Return ? BindingInitialization of BindingIdentifier with arguments v and environment.
ArrowParameters : CoverParenthesizedExpressionAndArrowParameterList
  1. Let formals be the ArrowFormalParameters that is covered by CoverParenthesizedExpressionAndArrowParameterList.
  2. Return ? IteratorBindingInitialization of formals with arguments iteratorRecord and environment.
AsyncArrowBindingIdentifier : BindingIdentifier
  1. Let v be undefined.
  2. Assert: iteratorRecord.[[Done]] is false.
  3. Let next be Completion(IteratorStep(iteratorRecord)).
  4. If next is an abrupt completion, set iteratorRecord.[[Done]] to true.
  5. ReturnIfAbrupt(next).
  6. If next is false, set iteratorRecord.[[Done]] to true.
  7. Else,
    1. Set v to Completion(IteratorValue(next)).
    2. If v is an abrupt completion, set iteratorRecord.[[Done]] to true.
    3. ReturnIfAbrupt(v).
  8. 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
  1. If this IdentifierReference is contained in strict mode code and StringValue of Identifier is "eval" or "arguments", return invalid.
  2. Return simple.
IdentifierReference : yield await CallExpression : CallExpression [ Expression ] CallExpression . IdentifierName CallExpression . PrivateIdentifier MemberExpression : MemberExpression [ Expression ] MemberExpression . IdentifierName SuperProperty MemberExpression . PrivateIdentifier
  1. Return simple.
PrimaryExpression : CoverParenthesizedExpressionAndArrowParameterList
  1. Let expr be the ParenthesizedExpression that is covered by CoverParenthesizedExpressionAndArrowParameterList.
  2. 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
  1. 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:

  1. Assert: envRec must have an uninitialized binding for N.
  2. If hint is not normal, perform ? AddDisposableResource(envRec, V, hint).
  3. Set the bound value for N in envRec to V.
  4. Record that the binding for N in envRec has been initialized.
  5. 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:

  1. Assert: hint is normal.
  2. Perform ? envRec.SetMutableBinding(N, V, false).
  3. 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:

  1. Let DclRec be envRec.[[DeclarativeRecord]].
  2. If ! DclRec.HasBinding(N) is true, then
    1. Return ! DclRec.InitializeBinding(N, V, hint).
  3. Assert: If the binding exists, it must be in the object Environment Record.
  4. Assert: hint is normal.
  5. Let ObjRec be envRec.[[ObjectRecord]].
  6. 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:

  1. Let calleeContext be the running execution context.
  2. Let code be func.[[ECMAScriptCode]].
  3. Let strict be func.[[Strict]].
  4. Let formals be func.[[FormalParameters]].
  5. Let parameterNames be the BoundNames of formals.
  6. If parameterNames has any duplicate entries, let hasDuplicates be true. Otherwise, let hasDuplicates be false.
  7. Let simpleParameterList be IsSimpleParameterList of formals.
  8. Let hasParameterExpressions be ContainsExpression of formals.
  9. Let varNames be the VarDeclaredNames of code.
  10. Let varDeclarations be the VarScopedDeclarations of code.
  11. Let lexicalNames be the LexicallyDeclaredNames of code.
  12. Let functionNames be a new empty List.
  13. Let functionsToInitialize be a new empty List.
  14. For each element d of varDeclarations, in reverse List order, do
    1. If d is neither a VariableDeclaration nor a ForBinding nor a BindingIdentifier, then
      1. Assert: d is either a FunctionDeclaration, a GeneratorDeclaration, an AsyncFunctionDeclaration, or an AsyncGeneratorDeclaration.
      2. Let fn be the sole element of the BoundNames of d.
      3. If fn is not an element of functionNames, then
        1. Insert fn as the first element of functionNames.
        2. NOTE: If there are multiple function declarations for the same name, the last declaration is used.
        3. Insert d as the first element of functionsToInitialize.
  15. Let argumentsObjectNeeded be true.
  16. If func.[[ThisMode]] is lexical, then
    1. NOTE: Arrow functions never have an arguments object.
    2. Set argumentsObjectNeeded to false.
  17. Else if "arguments" is an element of parameterNames, then
    1. Set argumentsObjectNeeded to false.
  18. Else if hasParameterExpressions is false, then
    1. If "arguments" is an element of functionNames or if "arguments" is an element of lexicalNames, then
      1. Set argumentsObjectNeeded to false.
  19. If strict is true or if hasParameterExpressions is false, then
    1. 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.
    2. Let env be the LexicalEnvironment of calleeContext.
  20. Else,
    1. 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.
    2. Let calleeEnv be the LexicalEnvironment of calleeContext.
    3. Let env be NewDeclarativeEnvironment(calleeEnv).
    4. Assert: The VariableEnvironment of calleeContext is calleeEnv.
    5. Set the LexicalEnvironment of calleeContext to env.
  21. For each String paramName of parameterNames, do
    1. Let alreadyDeclared be env.HasBinding(paramName).
    2. 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.
    3. If alreadyDeclared is false, then
      1. Perform ! env.CreateMutableBinding(paramName, false).
      2. If hasDuplicates is true, then
        1. Perform ! env.InitializeBinding(paramName, undefined, normal).
  22. If argumentsObjectNeeded is true, then
    1. If strict is true or if simpleParameterList is false, then
      1. Let ao be CreateUnmappedArgumentsObject(argumentsList).
    2. Else,
      1. 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.
      2. Let ao be CreateMappedArgumentsObject(func, formals, argumentsList, env).
    3. If strict is true, then
      1. Perform ! env.CreateImmutableBinding("arguments", false, false).
    4. Else,
      1. Perform ! env.CreateMutableBinding("arguments", false).
    5. Call env.InitializeBinding("arguments", ao, normal).
    6. Let parameterBindings be the list-concatenation of parameterNames and « "arguments" ».
  23. Else,
    1. Let parameterBindings be parameterNames.
  24. Let iteratorRecord be CreateListIteratorRecord(argumentsList).
  25. If hasDuplicates is true, then
    1. Perform ? IteratorBindingInitialization of formals with iteratorRecord and undefined as arguments.
  26. Else,
    1. Perform ? IteratorBindingInitialization of formals with iteratorRecord and env as arguments.
  27. If hasParameterExpressions is false, then
    1. NOTE: Only a single Environment Record is needed for the parameters and top-level vars.
    2. Let instantiatedVarNames be a copy of the List parameterBindings.
    3. For each element n of varNames, do
      1. If n is not an element of instantiatedVarNames, then
        1. Append n to instantiatedVarNames.
        2. Perform ! env.CreateMutableBinding(n, false).
        3. Call env.InitializeBinding(n, undefined, normal).
    4. Let varEnv be env.
  28. Else,
    1. 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.
    2. Let varEnv be NewDeclarativeEnvironment(env).
    3. Set the VariableEnvironment of calleeContext to varEnv.
    4. Let instantiatedVarNames be a new empty List.
    5. For each element n of varNames, do
      1. If n is not an element of instantiatedVarNames, then
        1. Append n to instantiatedVarNames.
        2. Perform ! varEnv.CreateMutableBinding(n, false).
        3. If n is not an element of parameterBindings or if n is an element of functionNames, let initialValue be undefined.
        4. Else,
          1. Let initialValue be ! env.GetBindingValue(n, false).
        5. Call varEnv.InitializeBinding(n, initialValue, normal).
        6. NOTE: A var with the same name as a formal parameter initially has the same value as the corresponding initialized parameter.
  29. NOTE: Annex B.3.2.1 adds additional steps at this point.
  30. If strict is false, then
    1. Let lexEnv be NewDeclarativeEnvironment(varEnv).
    2. 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.
  31. Else, let lexEnv be varEnv.
  32. Set the LexicalEnvironment of calleeContext to lexEnv.
  33. Let lexDeclarations be the LexicallyScopedDeclarations of code.
  34. For each element d of lexDeclarations, do
    1. 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.
    2. For each element dn of the BoundNames of d, do
      1. If IsConstantDeclaration of d is true, then
        1. Perform ! lexEnv.CreateImmutableBinding(dn, true).
      2. Else,
        1. Perform ! lexEnv.CreateMutableBinding(dn, false).
  35. Let privateEnv be the PrivateEnvironment of calleeContext.
  36. For each Parse Node f of functionsToInitialize, do
    1. Let fn be the sole element of the BoundNames of f.
    2. Let fo be InstantiateFunctionObject of f with arguments lexEnv and privateEnv.
    3. Perform ! varEnv.SetMutableBinding(fn, fo, false).
  37. 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 }
  1. Let oldEnv be the running execution context's LexicalEnvironment.
  2. Let blockEnv be NewDeclarativeEnvironment(oldEnv).
  3. Perform BlockDeclarationInstantiation(StatementList, blockEnv).
  4. Set the running execution context's LexicalEnvironment to blockEnv.
  5. Let blockValue be Completion(Evaluation of StatementList).
  6. Set blockValue to Completion(DisposeResources(blockEnv.[[DisposeCapability]], blockValue)).
  7. Set the running execution context's LexicalEnvironment to oldEnv.
  8. 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:

  1. Let declarations be the LexicallyScopedDeclarations of code.
  2. Let privateEnv be the running execution context's PrivateEnvironment.
  3. For each element d of declarations, do
    1. For each element dn of the BoundNames of d, do
      1. If IsConstantDeclaration of d is true, then
        1. Perform ! env.CreateImmutableBinding(dn, true).
      2. Else,
        1. Perform ! env.CreateMutableBinding(dn, false). NOTE: This step is replaced in section A.1.1.1.
    2. If d is a FunctionDeclaration, a GeneratorDeclaration, an AsyncFunctionDeclaration, or an AsyncGeneratorDeclaration, then
      1. Let fn be the sole element of the BoundNames of d.
      2. Let fo be InstantiateFunctionObject of d with arguments env and privateEnv.
      3. Perform env.InitializeBinding(fn, fo, 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] [lookahead ≠ await] BindingList[?In, ?Yield, ?Await, ~Pattern] ; AwaitUsingDeclaration[In, Yield] : CoverAwaitExpressionAndAwaitUsingDeclarationHead[?Yield] [no LineTerminator here] [lookahead ≠ await] 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 ; AwaitUsingDeclaration : CoverAwaitExpressionAndAwaitUsingDeclarationHead BindingList ; 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 ;
  1. Perform ? EvaluationBindingEvaluation of BindingList with parameter normal.
  2. Return empty.
UsingDeclaration : using BindingList ;
  1. Perform ? BindingEvaluation of BindingList with parameter sync-dispose.
  2. Return empty.
AwaitUsingDeclaration : CoverAwaitExpressionAndAwaitUsingDeclarationHead BindingList ;
  1. Perform ? BindingEvaluation of BindingList with parameter async-dispose.
  2. Return empty.
BindingList : BindingList , LexicalBinding
  1. Perform ? Evaluation of BindingList.
  2. Return ? Evaluation of LexicalBinding.
LexicalBinding : BindingIdentifier
  1. Let lhs be ! ResolveBinding(StringValue of BindingIdentifier).
  2. Perform ! InitializeReferencedBinding(lhs, undefined).
  3. Return empty.
Note

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

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

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
  1. Perform ? BindingEvaluation of BindingList with parameter hint.
  2. Return ? BindingEvaluation of LexicalBinding with parameter hint.
LexicalBinding : BindingIdentifier
  1. Assert: hint is normal.
  2. Let lhs be ! ResolveBinding(StringValue of BindingIdentifier).
  3. Perform ! InitializeReferencedBinding(lhs, undefined, normal).
  4. Return unused.
Note

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

LexicalBinding : BindingIdentifier Initializer
  1. Let bindingId be StringValue of BindingIdentifier.
  2. Let lhs be ? ResolveBinding(bindingId).
  3. If IsAnonymousFunctionDefinition(Initializer) is true, then
    1. Let value be ? NamedEvaluation of Initializer with argument bindingId.
  4. Else,
    1. Let rhs be ? Evaluation of Initializer.
    2. Let value be ? GetValue(rhs).
  5. Perform ? InitializeReferencedBinding(lhs, value, hint).
  6. Return unused.
LexicalBinding : BindingPattern Initializer
  1. Assert: hint is normal.
  2. Let rhs be ? Evaluation of Initializer.
  3. Let value be ? GetValue(rhs).
  4. Let env be the running execution context's LexicalEnvironment.
  5. 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
  1. Let lhs be ? ResolveBinding(StringValue of BindingIdentifier, environment).
  2. Let restObj be OrdinaryObjectCreate(%Object.prototype%).
  3. Perform ? CopyDataProperties(restObj, value, excludedNames).
  4. If environment is undefined, return PutValue(lhs, restObj).
  5. Return ? InitializeReferencedBinding(lhs, restObj, 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
  1. Let v be ? GetV(value, propertyName).
  2. If Initializer is present and v is undefined, then
    1. Let defaultValue be ? Evaluation of Initializer.
    2. Set v to ? GetValue(defaultValue).
  3. Return ? BindingInitialization of BindingPattern with arguments v and environment.
SingleNameBinding : BindingIdentifier Initializeropt
  1. Let bindingId be StringValue of BindingIdentifier.
  2. Let lhs be ? ResolveBinding(bindingId, environment).
  3. Let v be ? GetV(value, propertyName).
  4. If Initializer is present and v is undefined, then
    1. If IsAnonymousFunctionDefinition(Initializer) is true, then
      1. Set v to ? NamedEvaluation for Initializer with argument bindingId.
    2. Else,
      1. Let defaultValue be ? Evaluation of Initializer.
      2. Set v to ? GetValue(defaultValue).
  5. If environment is undefined, return ? PutValue(lhs, v).
  6. Return ? InitializeReferencedBinding(lhs, v, 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
  1. If the first Expression is present, then
    1. Let exprRef be ? Evaluation of the first Expression.
    2. Perform ? GetValue(exprRef).
  2. If the second Expression is present, let test be the second Expression; otherwise, let test be empty.
  3. If the third Expression is present, let increment be the third Expression; otherwise, let increment be empty.
  4. Return ? ForBodyEvaluation(test, increment, Statement, « », labelSet).
ForStatement : for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement
  1. Perform ? Evaluation of VariableDeclarationList.
  2. If the first Expression is present, let test be the first Expression; otherwise, let test be empty.
  3. If the second Expression is present, let increment be the second Expression; otherwise, let increment be empty.
  4. Return ? ForBodyEvaluation(test, increment, Statement, « », labelSet).
ForStatement : for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement
  1. Let oldEnv be the running execution context's LexicalEnvironment.
  2. Let loopEnv be NewDeclarativeEnvironment(oldEnv).
  3. Let isConst be IsConstantDeclaration of LexicalDeclaration.
  4. Let boundNames be the BoundNames of LexicalDeclaration.
  5. For each element dn of boundNames, do
    1. If isConst is true, then
      1. Perform ! loopEnv.CreateImmutableBinding(dn, true).
    2. Else,
      1. Perform ! loopEnv.CreateMutableBinding(dn, false).
  6. Set the running execution context's LexicalEnvironment to loopEnv.
  7. Let forDcl be Completion(Evaluation of LexicalDeclaration).
  8. If forDcl is an abrupt completion, then
    1. Set forDcl to Completion(DisposeResources(loopEnv.[[DisposeCapability]], forDcl)).
    2. Assert: forDcl is an abrupt completion.
    3. Set the running execution context's LexicalEnvironment to oldEnv.
    4. Return ? forDcl.
  9. If isConst is false, let perIterationLets be boundNames; otherwise let perIterationLets be a new empty List.
  10. If the first Expression is present, let test be the first Expression; otherwise, let test be empty.
  11. If the second Expression is present, let increment be the second Expression; otherwise, let increment be empty.
  12. Let bodyResult be Completion(ForBodyEvaluation(test, increment, Statement, perIterationLets, labelSet)).
  13. Set bodyResult to Completion(DisposeResources(loopEnv.[[DisposeCapability]], bodyResult)).
  14. Assert: If bodyResult.[[Type]] is normal, then bodyResult.[[Value]] is not empty.
  15. Set the running execution context's LexicalEnvironment to oldEnv.
  16. 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] [lookahead ≠ await] 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
  1. Assert: environment is a declarative Environment Record.
  2. For each element name of the BoundNames of ForBinding, do
    1. If IsConstantDeclaration of LetOrConst is true, then
      1. Perform ! environment.CreateImmutableBinding(name, true).
    2. Else,
      1. Perform ! environment.CreateMutableBinding(name, false).
ForDeclaration : using ForBinding await using ForBinding
  1. Assert: environment is a declarative Environment Record.
  2. For each element name of the BoundNames of ForBinding, do
    1. 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:

  1. If iteratorKind is not present, set iteratorKind to sync.
  2. Let oldEnv be the running execution context's LexicalEnvironment.
  3. Let V be undefined.
  4. If IsAwaitUsingDeclaration of lhs is true, then
    1. Let hint be async-dispose.
  5. Else, if IsUsingDeclaration of lhs is true, then
    1. Let hint be sync-dispose.
  6. Else,
    1. Let hint be normal.
  7. Let destructuring be IsDestructuring of lhs.
  8. If destructuring is true and if lhsKind is assignment, then
    1. Assert: lhs is a LeftHandSideExpression.
    2. Let assignmentPattern be the AssignmentPattern that is covered by lhs.
  9. Repeat,
    1. Let nextResult be ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]]).
    2. If iteratorKind is async, set nextResult to ? Await(nextResult).
    3. If nextResult is not an Object, throw a TypeError exception.
    4. Let done be ? IteratorComplete(nextResult).
    5. If done is true, return V.
    6. Let nextValue be ? IteratorValue(nextResult).
    7. If lhsKind is either assignment or varBinding, then
      1. If destructuring is true, then
        1. If lhsKind is assignment, then
          1. Let status be Completion(DestructuringAssignmentEvaluation of assignmentPattern with argument nextValue).
        2. Else,
          1. Assert: lhsKind is varBinding.
          2. Assert: lhs is a ForBinding.
          3. Let status be Completion(BindingInitialization of lhs with arguments nextValue and undefined).
      2. Else,
        1. Let lhsRef be Completion(Evaluation of lhs). (It may be evaluated repeatedly.)
        2. If lhsRef is an abrupt completion, then
          1. Let status be lhsRef.
        3. Else,
          1. Let status be Completion(PutValue(lhsRef.[[Value]], nextValue)).
      3. Let iterationEnv be undefined.
    8. Else,
      1. Assert: lhsKind is lexicalBinding.
      2. Assert: lhs is a ForDeclaration.
      3. Let iterationEnv be NewDeclarativeEnvironment(oldEnv).
      4. Perform ForDeclarationBindingInstantiation of lhs with argument iterationEnv.
      5. Set the running execution context's LexicalEnvironment to iterationEnv.
      6. If destructuring is true, then
        1. Let status be Completion(ForDeclarationBindingInitialization of lhs with arguments nextValue and iterationEnv).
      7. Else,
        1. Assert: lhs binds a single name.
        2. Let lhsName be the sole element of BoundNames of lhs.
        3. Let lhsRef be ! ResolveBinding(lhsName).
        4. Let status be Completion(InitializeReferencedBinding(lhsRef, nextValue)).
        5. If IsUsingDeclaration of lhs is true, then
          1. Let status be Completion(InitializeReferencedBinding(lhsRef, nextValue, sync-dispose)).
        6. Else,
          1. Let status be Completion(InitializeReferencedBinding(lhsRef, nextValue, normal)).
    9. If status is an abrupt completion, then
      1. If iterationEnv is not undefined, then
        1. Set status to Completion(DisposeResources(iterationEnv.[[DisposeCapability]], status)).
        2. Assert: status is an abrupt completion.
      2. Set the running execution context's LexicalEnvironment to oldEnv.
      3. If iteratorKind is async, return ? AsyncIteratorClose(iteratorRecord, status).
      4. If iterationKind is enumerate, then
        1. Return ? status.
      5. Else,
        1. Assert: iterationKind is iterate.
        2. Return ? IteratorClose(iteratorRecord, status).
    10. Let result be Completion(Evaluation of stmt).
    11. If iterationEnv is not undefined, then
      1. Set result to Completion(DisposeResources(iterationEnv.[[DisposeCapability]], result)).
    12. Set the running execution context's LexicalEnvironment to oldEnv.
    13. If LoopContinues(result, labelSet) is false, then
      1. If iterationKind is enumerate, then
        1. Return ? UpdateEmpty(result, V).
      2. Else,
        1. Assert: iterationKind is iterate.
        2. Set status to Completion(UpdateEmpty(result, V)).
        3. If iteratorKind is async, return ? AsyncIteratorClose(iteratorRecord, status).
        4. Return ? IteratorClose(iteratorRecord, status).
    14. 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
  1. Let exprRef be ? Evaluation of Expression.
  2. Let switchValue be ? GetValue(exprRef).
  3. Let oldEnv be the running execution context's LexicalEnvironment.
  4. Let blockEnv be NewDeclarativeEnvironment(oldEnv).
  5. Perform BlockDeclarationInstantiation(CaseBlock, blockEnv).
  6. Set the running execution context's LexicalEnvironment to blockEnv.
  7. Let R be Completion(CaseBlockEvaluation of CaseBlock with argument switchValue).
  8. Set R to Completion(DisposeResources(blockEnv.[[DisposeCapability]], R)).
  9. Assert: If R.[[Type]] is normal, then R.[[Value]] is not empty.
  10. Set the running execution context's LexicalEnvironment to oldEnv.
  11. 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
  1. Perform ? FunctionDeclarationInstantiation(functionObject, argumentsList).
  2. Return ? Evaluation of FunctionStatementList.
  3. Let result be Completion(Evaluation of FunctionStatementList).
  4. Let env be the running execution context's LexicalEnvironment.
  5. 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 }
  1. If name is not present, set name to "".
  2. Let scope be the LexicalEnvironment of the running execution context.
  3. Let privateScope be the running execution context's PrivateEnvironment.
  4. Let sourceText be the source text matched by FunctionExpression.
  5. Let closure be OrdinaryFunctionCreate(%Function.prototype%, sourceText, FormalParameters, FunctionBody, non-lexical-this, scope, privateScope).
  6. Perform SetFunctionName(closure, name).
  7. Perform MakeConstructor(closure).
  8. Return closure.
FunctionExpression : function BindingIdentifier ( FormalParameters ) { FunctionBody }
  1. Assert: name is not present.
  2. Set name to StringValue of BindingIdentifier.
  3. Let scope be the running execution context's LexicalEnvironment.
  4. Let funcEnv be NewDeclarativeEnvironment(scope).
  5. Perform ! funcEnv.CreateImmutableBinding(name, false).
  6. Let privateScope be the running execution context's PrivateEnvironment.
  7. Let sourceText be the source text matched by FunctionExpression.
  8. Let closure be OrdinaryFunctionCreate(%Function.prototype%, sourceText, FormalParameters, FunctionBody, non-lexical-this, funcEnv, privateScope).
  9. Perform SetFunctionName(closure, name).
  10. Perform MakeConstructor(closure).
  11. Perform ! funcEnv.InitializeBinding(name, closure, normal).
  12. 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 }
  1. If name is not present, set name to "".
  2. Let scope be the LexicalEnvironment of the running execution context.
  3. Let privateScope be the running execution context's PrivateEnvironment.
  4. Let sourceText be the source text matched by GeneratorExpression.
  5. Let closure be OrdinaryFunctionCreate(%GeneratorFunction.prototype%, sourceText, FormalParameters, GeneratorBody, non-lexical-this, scope, privateScope).
  6. Perform SetFunctionName(closure, name).
  7. Let prototype be OrdinaryObjectCreate(%GeneratorFunction.prototype.prototype%).
  8. Perform ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }).
  9. Return closure.
GeneratorExpression : function * BindingIdentifier ( FormalParameters ) { GeneratorBody }
  1. Assert: name is not present.
  2. Set name to StringValue of BindingIdentifier.
  3. Let scope be the running execution context's LexicalEnvironment.
  4. Let funcEnv be NewDeclarativeEnvironment(scope).
  5. Perform ! funcEnv.CreateImmutableBinding(name, false).
  6. Let privateScope be the running execution context's PrivateEnvironment.
  7. Let sourceText be the source text matched by GeneratorExpression.
  8. Let closure be OrdinaryFunctionCreate(%GeneratorFunction.prototype%, sourceText, FormalParameters, GeneratorBody, non-lexical-this, funcEnv, privateScope).
  9. Perform SetFunctionName(closure, name).
  10. Let prototype be OrdinaryObjectCreate(%GeneratorFunction.prototype.prototype%).
  11. Perform ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }).
  12. Perform ! funcEnv.InitializeBinding(name, closure, normal).
  13. 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 }
  1. If name is not present, set name to "".
  2. Let scope be the LexicalEnvironment of the running execution context.
  3. Let privateScope be the running execution context's PrivateEnvironment.
  4. Let sourceText be the source text matched by AsyncGeneratorExpression.
  5. Let closure be OrdinaryFunctionCreate(%AsyncGeneratorFunction.prototype%, sourceText, FormalParameters, AsyncGeneratorBody, non-lexical-this, scope, privateScope).
  6. Perform SetFunctionName(closure, name).
  7. Let prototype be OrdinaryObjectCreate(%AsyncGeneratorFunction.prototype.prototype%).
  8. Perform ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }).
  9. Return closure.
AsyncGeneratorExpression : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody }
  1. Assert: name is not present.
  2. Set name to StringValue of BindingIdentifier.
  3. Let scope be the running execution context's LexicalEnvironment.
  4. Let funcEnv be NewDeclarativeEnvironment(scope).
  5. Perform ! funcEnv.CreateImmutableBinding(name, false).
  6. Let privateScope be the running execution context's PrivateEnvironment.
  7. Let sourceText be the source text matched by AsyncGeneratorExpression.
  8. Let closure be OrdinaryFunctionCreate(%AsyncGeneratorFunction.prototype%, sourceText, FormalParameters, AsyncGeneratorBody, non-lexical-this, funcEnv, privateScope).
  9. Perform SetFunctionName(closure, name).
  10. Let prototype be OrdinaryObjectCreate(%AsyncGeneratorFunction.prototype.prototype%).
  11. Perform ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }).
  12. Perform ! funcEnv.InitializeBinding(name, closure, normal).
  13. 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
  1. Perform ? FunctionDeclarationInstantiation(functionObject, « »).
  2. Return ? Evaluation of ClassStaticBlockStatementList.
  3. Let result be Completion(Evaluation of ClassStaticBlockStatementList).
  4. Let env be the running execution context's LexicalEnvironment.
  5. 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 }
  1. Let env be the LexicalEnvironment of the running execution context.
  2. Let classEnv be NewDeclarativeEnvironment(env).
  3. If classBinding is not undefined, then
    1. Perform ! classEnv.CreateImmutableBinding(classBinding, true).
  4. Let outerPrivateEnvironment be the running execution context's PrivateEnvironment.
  5. Let classPrivateEnvironment be NewPrivateEnvironment(outerPrivateEnvironment).
  6. If ClassBodyopt is present, then
    1. For each String dn of the PrivateBoundIdentifiers of ClassBodyopt, do
      1. If classPrivateEnvironment.[[Names]] contains a Private Name whose [[Description]] is dn, then
        1. Assert: This is only possible for getter/setter pairs.
      2. Else,
        1. Let name be a new Private Name whose [[Description]] value is dn.
        2. Append name to classPrivateEnvironment.[[Names]].
  7. If ClassHeritageopt is not present, then
    1. Let protoParent be %Object.prototype%.
    2. Let constructorParent be %Function.prototype%.
  8. Else,
    1. Set the running execution context's LexicalEnvironment to classEnv.
    2. NOTE: The running execution context's PrivateEnvironment is outerPrivateEnvironment when evaluating ClassHeritage.
    3. Let superclassRef be Completion(Evaluation of ClassHeritage).
    4. Set the running execution context's LexicalEnvironment to env.
    5. Let superclass be ? GetValue(? superclassRef).
    6. If superclass is null, then
      1. Let protoParent be null.
      2. Let constructorParent be %Function.prototype%.
    7. Else if IsConstructor(superclass) is false, throw a TypeError exception.
    8. Else,
      1. Let protoParent be ? Get(superclass, "prototype").
      2. If protoParent is not an Object and protoParent is not null, throw a TypeError exception.
      3. Let constructorParent be superclass.
  9. Let proto be OrdinaryObjectCreate(protoParent).
  10. If ClassBodyopt is not present, let constructor be empty.
  11. Else, let constructor be ConstructorMethod of ClassBody.
  12. Set the running execution context's LexicalEnvironment to classEnv.
  13. Set the running execution context's PrivateEnvironment to classPrivateEnvironment.
  14. If constructor is empty, then
    1. Let defaultConstructor be a new Abstract Closure with no parameters that captures nothing and performs the following steps when called:
      1. Let args be the List of arguments that was passed to this function by [[Call]] or [[Construct]].
      2. If NewTarget is undefined, throw a TypeError exception.
      3. Let F be the active function object.
      4. If F.[[ConstructorKind]] is derived, then
        1. 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.
        2. Let func be ! F.[[GetPrototypeOf]]().
        3. If IsConstructor(func) is false, throw a TypeError exception.
        4. Let result be ? Construct(func, args, NewTarget).
      5. Else,
        1. NOTE: This branch behaves similarly to constructor() {}.
        2. Let result be ? OrdinaryCreateFromConstructor(NewTarget, "%Object.prototype%").
      6. Perform ? InitializeInstanceElements(result, F).
      7. Return result.
    2. Let F be CreateBuiltinFunction(defaultConstructor, 0, className, « [[ConstructorKind]], [[SourceText]] », the current Realm Record, constructorParent).
  15. Else,
    1. Let constructorInfo be ! DefineMethod of constructor with arguments proto and constructorParent.
    2. Let F be constructorInfo.[[Closure]].
    3. Perform MakeClassConstructor(F).
    4. Perform SetFunctionName(F, className).
  16. Perform MakeConstructor(F, false, proto).
  17. If ClassHeritageopt is present, set F.[[ConstructorKind]] to derived.
  18. Perform CreateMethodProperty(proto, "constructor", F).
  19. If ClassBodyopt is not present, let elements be a new empty List.
  20. Else, let elements be NonConstructorElements of ClassBody.
  21. Let instancePrivateMethods be a new empty List.
  22. Let staticPrivateMethods be a new empty List.
  23. Let instanceFields be a new empty List.
  24. Let staticElements be a new empty List.
  25. For each ClassElement e of elements, do
    1. If IsStatic of e is false, then
      1. Let element be Completion(ClassElementEvaluation of e with argument proto).
    2. Else,
      1. Let element be Completion(ClassElementEvaluation of e with argument F).
    3. If element is an abrupt completion, then
      1. Set the running execution context's LexicalEnvironment to env.
      2. Set the running execution context's PrivateEnvironment to outerPrivateEnvironment.
      3. Return ? element.
    4. Set element to element.[[Value]].
    5. If element is a PrivateElement, then
      1. Assert: element.[[Kind]] is either method or accessor.
      2. If IsStatic of e is false, let container be instancePrivateMethods.
      3. Else, let container be staticPrivateMethods.
      4. If container contains a PrivateElement whose [[Key]] is element.[[Key]], then
        1. Let existing be that PrivateElement.
        2. Assert: element.[[Kind]] and existing.[[Kind]] are both accessor.
        3. If element.[[Get]] is undefined, then
          1. Let combined be PrivateElement { [[Key]]: element.[[Key]], [[Kind]]: accessor, [[Get]]: existing.[[Get]], [[Set]]: element.[[Set]] }.
        4. Else,
          1. Let combined be PrivateElement { [[Key]]: element.[[Key]], [[Kind]]: accessor, [[Get]]: element.[[Get]], [[Set]]: existing.[[Set]] }.
        5. Replace existing in container with combined.
      5. Else,
        1. Append element to container.
    6. Else if element is a ClassFieldDefinition Record, then
      1. If IsStatic of e is false, append element to instanceFields.
      2. Else, append element to staticElements.
    7. Else if element is a ClassStaticBlockDefinition Record, then
      1. Append element to staticElements.
  26. Set the running execution context's LexicalEnvironment to env.
  27. If classBinding is not undefined, then
    1. Perform ! classScope.InitializeBinding(classBinding, F, normal).
  28. Set F.[[PrivateMethods]] to instancePrivateMethods.
  29. Set F.[[Fields]] to instanceFields.
  30. For each PrivateElement method of staticPrivateMethods, do
    1. Perform ! PrivateMethodOrAccessorAdd(F, method).
  31. For each element elementRecord of staticElements, do
    1. If elementRecord is a ClassFieldDefinition Record, then
      1. Let result be Completion(DefineField(F, elementRecord)).
    2. Else,
      1. Assert: elementRecord is a ClassStaticBlockDefinition Record.
      2. Let result be Completion(Call(elementRecord.[[BodyFunction]], F)).
    3. If result is an abrupt completion, then
      1. Set the running execution context's PrivateEnvironment to outerPrivateEnvironment.
      2. Return ? result.
  32. Set the running execution context's PrivateEnvironment to outerPrivateEnvironment.
  33. 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 }
  1. If name is not present, set name to "".
  2. Let scope be the LexicalEnvironment of the running execution context.
  3. Let privateScope be the running execution context's PrivateEnvironment.
  4. Let sourceText be the source text matched by AsyncFunctionExpression.
  5. Let closure be OrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, FormalParameters, AsyncFunctionBody, non-lexical-this, scope, privateScope).
  6. Perform SetFunctionName(closure, name).
  7. Return closure.
AsyncFunctionExpression : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody }
  1. Assert: name is not present.
  2. Set name to StringValue of BindingIdentifier.
  3. Let scope be the LexicalEnvironment of the running execution context.
  4. Let funcEnv be NewDeclarativeEnvironment(scope).
  5. Perform ! funcEnv.CreateImmutableBinding(name, false).
  6. Let privateScope be the running execution context's PrivateEnvironment.
  7. Let sourceText be the source text matched by AsyncFunctionExpression.
  8. Let closure be OrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, FormalParameters, AsyncFunctionBody, non-lexical-this, funcEnv, privateScope).
  9. Perform SetFunctionName(closure, name).
  10. Perform ! funcEnv.InitializeBinding(name, closure, normal).
  11. 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
  1. Let expr be the AwaitExpression that is covered by CoverAwaitExpressionAndAwaitUsingDeclarationHead.
  2. 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
  1. Let has be HasCallInTailPosition of StatementList with argument call.
  2. If has is true, return true.
  3. If HasUnterminatedUsingDeclaration of StatementList is true, return false.
  4. 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 : { }
  1. Return false.
IfStatement : if ( Expression ) Statement else Statement
  1. Let has be HasCallInTailPosition of the first Statement with argument call.
  2. If has is true, return true.
  3. 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
  1. Return HasCallInTailPosition of Statement with argument call.
LabelledStatement : LabelIdentifier : LabelledItem
  1. Return HasCallInTailPosition of LabelledItem with argument call.
ReturnStatement : return Expression ;
  1. Return HasCallInTailPosition of Expression with argument call.
SwitchStatement : switch ( Expression ) CaseBlock
  1. Return HasCallInTailPosition of CaseBlock with argument call.
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. Let has be false.
  2. If the first CaseClauses is present, let has be HasCallInTailPosition of the first CaseClauses with argument call.
  3. If has is true, return true.
  4. If the first CaseClauses is present, then
    1. Let has be HasCallInTailPosition of the first CaseClauses with argument call.
    2. If has is true, return true.
    3. If HasUnterminatedUsingDeclaration of the first CaseClauses is true, return false.
  5. Let has be HasCallInTailPosition of DefaultClause with argument call.
  6. If has is true, return true.
  7. If HasUnterminatedUsingDeclaration of DefaultClause is true, return false.
  8. If the second CaseClauses is present, let has be HasCallInTailPosition of the second CaseClauses with argument call.
  9. Return has.
CaseClauses : CaseClauses CaseClause
  1. Let has be HasCallInTailPosition of CaseClauses with argument call.
  2. If has is true, return true.
  3. If HasUnterminatedUsingDeclaration of CaseClauses is true, return false.
  4. Return HasCallInTailPosition of CaseClause with argument call.
CaseClause : case Expression : StatementListopt DefaultClause : default : StatementListopt
  1. If StatementList is present, return HasCallInTailPosition of StatementList with argument call.
  2. Return false.
TryStatement : try Block Catch
  1. Return HasCallInTailPosition of Catch with argument call.
TryStatement : try Block Finally try Block Catch Finally
  1. Return HasCallInTailPosition of Finally with argument call.
Catch : catch ( CatchParameter ) Block
  1. 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
  1. Return false.
Expression : AssignmentExpression Expression , AssignmentExpression
  1. Return HasCallInTailPosition of AssignmentExpression with argument call.
ConditionalExpression : ShortCircuitExpression ? AssignmentExpression : AssignmentExpression
  1. Let has be HasCallInTailPosition of the first AssignmentExpression with argument call.
  2. If has is true, return true.
  3. Return HasCallInTailPosition of the second AssignmentExpression with argument call.
LogicalANDExpression : LogicalANDExpression && BitwiseORExpression
  1. Return HasCallInTailPosition of BitwiseORExpression with argument call.
LogicalORExpression : LogicalORExpression || LogicalANDExpression
  1. Return HasCallInTailPosition of LogicalANDExpression with argument call.
CoalesceExpression : CoalesceExpressionHead ?? BitwiseORExpression
  1. Return HasCallInTailPosition of BitwiseORExpression with argument call.
CallExpression : CoverCallExpressionAndAsyncArrowHead CallExpression Arguments CallExpression TemplateLiteral
  1. If this CallExpression is call, return true.
  2. Return false.
OptionalExpression : MemberExpression OptionalChain CallExpression OptionalChain OptionalExpression OptionalChain
  1. Return HasCallInTailPosition of OptionalChain with argument call.
OptionalChain : ?. [ Expression ] ?. IdentifierName ?. PrivateIdentifier OptionalChain [ Expression ] OptionalChain . IdentifierName OptionalChain . PrivateIdentifier
  1. Return false.
OptionalChain : ?. Arguments OptionalChain Arguments
  1. If this OptionalChain is call, return true.
  2. Return false.
MemberExpression : MemberExpression TemplateLiteral
  1. If this MemberExpression is call, return true.
  2. Return false.
PrimaryExpression : CoverParenthesizedExpressionAndArrowParameterList
  1. Let expr be the ParenthesizedExpression that is covered by CoverParenthesizedExpressionAndArrowParameterList.
  2. Return HasCallInTailPosition of expr with argument call.
ParenthesizedExpression : ( Expression )
  1. 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
  1. Let has be HasUnterminatedUsingDeclaration of StatementList.
  2. If has is true, return true.
  3. Return HasUnterminatedUsingDeclaration of StatementListItem.
StatementListItem : Statement CaseBlock : { } Declaration : HoistableDeclaration ClassDeclaration LexicalDeclaration : LetOrConst BindingList ;
  1. Return false.
UsingDeclaration : using BindingList ; AwaitUsingDeclaration : CoverAwaitExpressionAndAwaitUsingDeclarationHead BindingList ;
  1. Return true.
CaseClauses : CaseClauses CaseClause
  1. Let has be HasUnterminatedUsingDeclaration of CaseClauses.
  2. If has is true, return true.
  3. Return HasUnterminatedUsingDeclaration of CaseClause with argument call.
CaseClause : case Expression : StatementListopt DefaultClause : default : StatementListopt
  1. 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:

  1. For each ExportEntry Record e of module.[[IndirectExportEntries]], do
    1. Let resolution be module.ResolveExport(e.[[ExportName]]).
    2. If resolution is null or ambiguous, throw a SyntaxError exception.
    3. Assert: resolution is a ResolvedBinding Record.
  2. Assert: All named exports from module are resolvable.
  3. Let realm be module.[[Realm]].
  4. Assert: realm is not undefined.
  5. Let env be NewModuleEnvironment(realm.[[GlobalEnv]]).
  6. Set module.[[Environment]] to env.
  7. For each ImportEntry Record in of module.[[ImportEntries]], do
    1. Let importedModule be GetImportedModule(module, in.[[ModuleRequest]]).
    2. If in.[[ImportName]] is namespace-object, then
      1. Let namespace be GetModuleNamespace(importedModule).
      2. Perform ! env.CreateImmutableBinding(in.[[LocalName]], true).
      3. Perform ! env.InitializeBinding(in.[[LocalName]], namespace, normal).
    3. Else,
      1. Let resolution be importedModule.ResolveExport(in.[[ImportName]]).
      2. If resolution is null or ambiguous, throw a SyntaxError exception.
      3. If resolution.[[BindingName]] is namespace, then
        1. Let namespace be GetModuleNamespace(resolution.[[Module]]).
        2. Perform ! env.CreateImmutableBinding(in.[[LocalName]], true).
        3. Perform ! env.InitializeBinding(in.[[LocalName]], namespace, normal).
      4. Else,
        1. Perform env.CreateImportBinding(in.[[LocalName]], resolution.[[Module]], resolution.[[BindingName]]).
  8. Let moduleContext be a new ECMAScript code execution context.
  9. Set the Function of moduleContext to null.
  10. Assert: module.[[Realm]] is not undefined.
  11. Set the Realm of moduleContext to module.[[Realm]].
  12. Set the ScriptOrModule of moduleContext to module.
  13. Set the VariableEnvironment of moduleContext to module.[[Environment]].
  14. Set the LexicalEnvironment of moduleContext to module.[[Environment]].
  15. Set the PrivateEnvironment of moduleContext to null.
  16. Set module.[[Context]] to moduleContext.
  17. Push moduleContext onto the execution context stack; moduleContext is now the running execution context.
  18. Let code be module.[[ECMAScriptCode]].
  19. Let varDeclarations be the VarScopedDeclarations of code.
  20. Let declaredVarNames be a new empty List.
  21. For each element d of varDeclarations, do
    1. For each element dn of the BoundNames of d, do
      1. If dn is not an element of declaredVarNames, then
        1. Perform ! env.CreateMutableBinding(dn, false).
        2. Perform ! env.InitializeBinding(dn, undefined, normal).
        3. Append dn to declaredVarNames.
  22. Let lexDeclarations be the LexicallyScopedDeclarations of code.
  23. Let privateEnv be null.
  24. For each element d of lexDeclarations, do
    1. For each element dn of the BoundNames of d, do
      1. If IsConstantDeclaration of d is true, then
        1. Perform ! env.CreateImmutableBinding(dn, true).
      2. Else,
        1. Perform ! env.CreateMutableBinding(dn, false).
      3. If d is a FunctionDeclaration, a GeneratorDeclaration, an AsyncFunctionDeclaration, or an AsyncGeneratorDeclaration, then
        1. Let fo be InstantiateFunctionObject of d with arguments env and privateEnv.
        2. Perform ! env.InitializeBinding(dn, fo, normal).
  25. Remove moduleContext from the execution context stack.
  26. 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:

  1. Let moduleContext be a new ECMAScript code execution context.
  2. Set the Function of moduleContext to null.
  3. Set the Realm of moduleContext to module.[[Realm]].
  4. Set the ScriptOrModule of moduleContext to module.
  5. Assert: module has been linked and declarations in its module environment have been instantiated.
  6. Let env be module.[[Environment]].
  7. Set the VariableEnvironment of moduleContext to env.
  8. Set the LexicalEnvironment of moduleContext to env.
  9. Suspend the running execution context.
  10. If module.[[HasTLA]] is false, then
    1. Assert: capability is not present.
    2. Push moduleContext onto the execution context stack; moduleContext is now the running execution context.
    3. Let result be Completion(Evaluation of module.[[ECMAScriptCode]]).
    4. Set result to Completion(DisposeResources(env.[[DisposeCapability]], result)).
    5. Suspend moduleContext and remove it from the execution context stack.
    6. Resume the context that is now on the top of the execution context stack as the running execution context.
    7. If result is an abrupt completion, then
      1. Return ? result.
  11. Else,
    1. Assert: capability is a PromiseCapability Record.
    2. Perform AsyncBlockStart(capability, module.[[ECMAScriptCode]], moduleContext).
  12. 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:

  1. Let varNames be the VarDeclaredNames of body.
  2. Let varDeclarations be the VarScopedDeclarations of body.
  3. If strict is false, then
    1. If varEnv is a Global Environment Record, then
      1. For each element name of varNames, do
        1. If varEnv.HasLexicalDeclaration(name) is true, throw a SyntaxError exception.
        2. NOTE: eval will not create a global var declaration that would be shadowed by a global lexical declaration.
    2. Let thisEnv be lexEnv.
    3. Assert: The following loop will terminate.
    4. Repeat, while thisEnv is not the same as varEnv,
      1. If thisEnv is not an Object Environment Record, then
        1. NOTE: The environment of with statements cannot contain any lexical declaration so it doesn't need to be checked for var/let hoisting conflicts.
        2. For each element name of varNames, do
          1. If ! thisEnv.HasBinding(name) is true, then
            1. Throw a SyntaxError exception.
            2. NOTE: Annex B.3.4 defines alternate semantics for the above step.
          2. NOTE: A direct eval will not hoist var declaration over a like-named lexical declaration.
      2. Set thisEnv to thisEnv.[[OuterEnv]].
  4. Let privateIdentifiers be a new empty List.
  5. Let pointer be privateEnv.
  6. Repeat, while pointer is not null,
    1. For each Private Name binding of pointer.[[Names]], do
      1. If privateIdentifiers does not contain binding.[[Description]], append binding.[[Description]] to privateIdentifiers.
    2. Set pointer to pointer.[[OuterPrivateEnvironment]].
  7. If AllPrivateIdentifiersValid of body with argument privateIdentifiers is false, throw a SyntaxError exception.
  8. Let functionsToInitialize be a new empty List.
  9. Let declaredFunctionNames be a new empty List.
  10. For each element d of varDeclarations, in reverse List order, do
    1. If d is neither a VariableDeclaration nor a ForBinding nor a BindingIdentifier, then
      1. Assert: d is either a FunctionDeclaration, a GeneratorDeclaration, an AsyncFunctionDeclaration, or an AsyncGeneratorDeclaration.
      2. NOTE: If there are multiple function declarations for the same name, the last declaration is used.
      3. Let fn be the sole element of the BoundNames of d.
      4. If fn is not an element of declaredFunctionNames, then
        1. If varEnv is a Global Environment Record, then
          1. Let fnDefinable be ? varEnv.CanDeclareGlobalFunction(fn).
          2. If fnDefinable is false, throw a TypeError exception.
        2. Append fn to declaredFunctionNames.
        3. Insert d as the first element of functionsToInitialize.
  11. NOTE: Annex B.3.2.3 adds additional steps at this point.
  12. Let declaredVarNames be a new empty List.
  13. For each element d of varDeclarations, do
    1. If d is a VariableDeclaration, a ForBinding, or a BindingIdentifier, then
      1. For each String vn of the BoundNames of d, do
        1. If vn is not an element of declaredFunctionNames, then
          1. If varEnv is a Global Environment Record, then
            1. Let vnDefinable be ? varEnv.CanDeclareGlobalVar(vn).
            2. If vnDefinable is false, throw a TypeError exception.
          2. If vn is not an element of declaredVarNames, then
            1. Append vn to declaredVarNames.
  14. 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.
  15. Let lexDeclarations be the LexicallyScopedDeclarations of body.
  16. For each element d of lexDeclarations, do
    1. NOTE: Lexically declared names are only instantiated here but not initialized.
    2. For each element dn of the BoundNames of d, do
      1. If IsConstantDeclaration of d is true, then
        1. Perform ? lexEnv.CreateImmutableBinding(dn, true).
      2. Else,
        1. Perform ? lexEnv.CreateMutableBinding(dn, false).
  17. For each Parse Node f of functionsToInitialize, do
    1. Let fn be the sole element of the BoundNames of f.
    2. Let fo be InstantiateFunctionObject of f with arguments lexEnv and privateEnv.
    3. If varEnv is a Global Environment Record, then
      1. Perform ? varEnv.CreateGlobalFunctionBinding(fn, fo, true).
    4. Else,
      1. Let bindingExists be ! varEnv.HasBinding(fn).
      2. If bindingExists is false, then
        1. NOTE: The following invocation cannot return an abrupt completion because of the validation preceding step 14.
        2. Perform ! varEnv.CreateMutableBinding(fn, true).
        3. Perform ! varEnv.InitializeBinding(fn, fo, normal).
      3. Else,
        1. Perform ! varEnv.SetMutableBinding(fn, fo, false).
  18. For each String vn of declaredVarNames, do
    1. If varEnv is a Global Environment Record, then
      1. Perform ? varEnv.CreateGlobalVarBinding(vn, true).
    2. Else,
      1. Let bindingExists be ! varEnv.HasBinding(vn).
      2. If bindingExists is false, then
        1. NOTE: The following invocation cannot return an abrupt completion because of the validation preceding step 14.
        2. Perform ! varEnv.CreateMutableBinding(vn, true).
        3. Perform ! varEnv.InitializeBinding(vn, undefined, normal).
  19. 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:

  1. If NewTarget is undefined, let newTarget be the active function object; else let newTarget be NewTarget.
  2. Let O be ? OrdinaryCreateFromConstructor(newTarget, "%SuppressedError.prototype%", « [[ErrorData]] »).
  3. If message is not undefined, then
    1. Let messageString be ? ToString(message).
    2. Perform CreateNonEnumerableDataPropertyOrThrow(O, "message", messageString).
  4. Perform ? InstallErrorCause(O, options).
  5. Perform CreateNonEnumerableDataPropertyOrThrow(O, "error", error).
  6. Perform CreateNonEnumerableDataPropertyOrThrow(O, "suppressed", suppressed).
  7. 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:

  1. Let O be the this value.
  2. Let return be ? GetMethod(O, "return").
  3. If return is not undefined, then
    1. Perform ? Call(return, O, « »).
  4. 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:

  1. Let O be the this value.
  2. Let promiseCapability be ! NewPromiseCapability(%Promise%).
  3. Let return be GetMethod(O, "return").
  4. IfAbruptRejectPromise(return, promiseCapability).
  5. If return is undefined, then
    1. Perform ! Call(promiseCapability.[[Resolve]], undefined, « undefined »).
  6. Else,
    1. Let result be Call(return, O, « undefined »).
    2. IfAbruptRejectPromise(result, promiseCapability).
    3. Let resultWrapper be Completion(PromiseResolve(%Promise%, result)).
    4. IfAbruptRejectPromise(resultWrapper, promiseCapability).
    5. Let unwrap be a new Abstract Closure that performs the following steps when called:
      1. Return undefined.
    6. Let onFulfilled be CreateBuiltinFunction(unwrap, 1, "", « »).
    7. Perform PerformPromiseThen(resultWrapper, onFulfilled, undefined, promiseCapability).
  7. 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:

  1. If NewTarget is undefined, throw a TypeError exception.
  2. Let disposableStack be ? OrdinaryCreateFromConstructor(NewTarget, "%DisposableStack.prototype%", « [[DisposableState]], [[DisposeCapability]] »).
  3. Set disposableStack.[[DisposableState]] to pending.
  4. Set disposableStack.[[DisposeCapability]] to NewDisposeCapability().
  5. 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:

  1. Let disposableStack be the this value.
  2. Perform ? RequireInternalSlot(disposableStack, [[DisposableState]]).
  3. If disposableStack.[[DisposableState]] is disposed, return true.
  4. Otherwise, return false.

12.3.3.2 DisposableStack.prototype.dispose ()

When the dispose method is called, the following steps are taken:

  1. Let disposableStack be the this value.
  2. Perform ? RequireInternalSlot(disposableStack, [[DisposableState]]).
  3. If disposableStack.[[DisposableState]] is disposed, return undefined.
  4. Set disposableStack.[[DisposableState]] to disposed.
  5. 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:

  1. Let disposableStack be the this value.
  2. Perform ? RequireInternalSlot(disposableStack, [[DisposableState]]).
  3. If disposableStack.[[DisposableState]] is disposed, throw a ReferenceError exception.
  4. Perform ? AddDisposableResource(disposableStack.[[DisposeCapability]], value, sync-dispose).
  5. 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:

  1. Let disposableStack be the this value.
  2. Perform ? RequireInternalSlot(disposableStack, [[DisposableState]]).
  3. If disposableStack.[[DisposableState]] is disposed, throw a ReferenceError exception.
  4. If IsCallable(onDispose) is false, throw a TypeError exception.
  5. Let closure be a new Abstract Closure with no parameters that captures value and onDispose and performs the following steps when called:
    1. Return ? Call(onDispose, undefined, « value »).
  6. Let F be CreateBuiltinFunction(closure, 0, "", « »).
  7. Perform ? AddDisposableResource(disposableStack.[[DisposeCapability]], undefined, sync-dispose, F).
  8. Return value.

12.3.3.5 DisposableStack.prototype.defer( onDispose )

When the defer function is called with one argument, the following steps are taken:

  1. Let disposableStack be the this value.
  2. Perform ? RequireInternalSlot(disposableStack, [[DisposableState]]).
  3. If disposableStack.[[DisposableState]] is disposed, throw a ReferenceError exception.
  4. If IsCallable(onDispose) is false, throw a TypeError exception.
  5. Perform ? AddDisposableResource(disposableStack.[[DisposeCapability]], undefined, sync-dispose, onDispose).
  6. Return undefined.

12.3.3.6 DisposableStack.prototype.move()

When the move function is called, the following steps are taken:

  1. Let disposableStack be the this value.
  2. Perform ? RequireInternalSlot(disposableStack, [[DisposableState]]).
  3. If disposableStack.[[DisposableState]] is disposed, throw a ReferenceError exception.
  4. Let newDisposableStack be ? OrdinaryCreateFromConstructor(%DisposableStack%, "%DisposableStack.prototype%", « [[DisposableState]], [[DisposeCapability]] »).
  5. Set newDisposableStack.[[DisposableState]] to pending.
  6. Set newDisposableStack.[[DisposeCapability]] to disposableStack.[[DisposeCapability]].
  7. Set disposableStack.[[DisposeCapability]] to NewDisposeCapability().
  8. Set disposableStack.[[DisposableState]] to disposed.
  9. 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:

  1. If NewTarget is undefined, throw a TypeError exception.
  2. Let asyncDisposableStack be ? OrdinaryCreateFromConstructor(NewTarget, "%AsyncDisposableStack.prototype%", « [[AsyncDisposableState]], [[DisposeCapability]] »).
  3. Set asyncDisposableStack.[[AsyncDisposableState]] to pending.
  4. Set asyncDisposableStack.[[DisposeCapability]] to NewDisposeCapability().
  5. 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:

  1. Let asyncDisposableStack be the this value.
  2. Perform ? RequireInternalSlot(asyncDisposableStack, [[AsyncDisposableState]]).
  3. If asyncDisposableStack.[[AsyncDisposableState]] is disposed, return true.
  4. Otherwise, return false.

12.4.3.2 AsyncDisposableStack.prototype.disposeAsync()

When the disposeAsync method is called, the following steps are taken:

  1. Let asyncDisposableStack be the this value.
  2. Let promiseCapability be ! NewPromiseCapability(%Promise%).
  3. If asyncDisposableStack does not have an [[AsyncDisposableState]] internal slot, then
    1. Perform ! Call(promiseCapability.[[Reject]], undefined, « a newly created TypeError object »).
    2. Return promiseCapability.[[Promise]].
  4. If asyncDisposableStack.[[AsyncDisposableState]] is disposed, then
    1. Perform ! Call(promiseCapability.[[Resolve]], undefined, « undefined »).
    2. Return promiseCapability.[[Promise]].
  5. Set asyncDisposableStack.[[AsyncDisposableState]] to disposed.
  6. Let result be DisposeResources(asyncDisposableStack.[[DisposeCapability]], NormalCompletion(undefined)).
  7. IfAbruptRejectPromise(result, promiseCapability).
  8. Perform ! Call(promiseCapability.[[Resolve]], undefined, « result »).
  9. 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:

  1. Let asyncDisposableStack be the this value.
  2. Perform ? RequireInternalSlot(asyncDisposableStack, [[AsyncDisposableState]]).
  3. If asyncDisposableStack.[[AsyncDisposableState]] is disposed, throw a ReferenceError exception.
  4. Perform ? AddDisposableResource(asyncDisposableStack.[[DisposeCapability]], value, async-dispose).
  5. 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:

  1. Let asyncDisposableStack be the this value.
  2. Perform ? RequireInternalSlot(asyncDisposableStack, [[AsyncDisposableState]]).
  3. If asyncDisposableStack.[[AsyncDisposableState]] is disposed, throw a ReferenceError exception.
  4. If IsCallable(onDisposeAsync) is false, throw a TypeError exception.
  5. Let closure be a new Abstract Closure with no parameters that captures value and onDisposeAsync and performs the following steps when called:
    1. Return ? Call(onDisposeAsync, undefined, « value »).
  6. Let F be CreateBuiltinFunction(closure, 0, "", « »).
  7. Perform ? AddDisposableResource(asyncDisposableStack.[[DisposeCapability]], undefined, async-dispose, F).
  8. Return value.

12.4.3.5 AsyncDisposableStack.prototype.defer( onDisposeAsync )

When the defer function is called with one argument, the following steps are taken:

  1. Let asyncDisposableStack be the this value.
  2. Perform ? RequireInternalSlot(asyncDisposableStack, [[AsyncDisposableState]]).
  3. If asyncDisposableStack.[[AsyncDisposableState]] is disposed, throw a ReferenceError exception.
  4. If IsCallable(onDisposeAsync) is false, throw a TypeError exception.
  5. Perform ? AddDisposableResource(asyncDisposableStack.[[DisposeCapability]], undefined, async-dispose, onDisposeAsync).
  6. Return undefined.

12.4.3.6 AsyncDisposableStack.prototype.move()

When the move function is called, the following steps are taken:

  1. Let asyncDisposableStack be the this value.
  2. Perform ? RequireInternalSlot(asyncDisposableStack, [[AsyncDisposableState]]).
  3. If asyncDisposableStack.[[AsyncDisposableState]] is disposed, throw a ReferenceError exception.
  4. Let newAsyncDisposableStack be ? OrdinaryCreateFromConstructor(%AsyncDisposableStack%, "%AsyncDisposableStack.prototype%", « [[AsyncDisposableState]], [[DisposeCapability]] »).
  5. Set newAsyncDisposableStack.[[AsyncDisposableState]] to pending.
  6. Set newAsyncDisposableStack.[[DisposeCapability]] to asyncDisposableStack.[[DisposeCapability]].
  7. Set asyncDisposableStack.[[DisposeCapability]] to NewDisposeCapability().
  8. Set asyncDisposableStack.[[AsyncDisposableState]] to disposed.
  9. 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:

  1. Assert: The value of generator.[[GeneratorState]] is undefined.
  2. Let genContext be the running execution context.
  3. Set the Generator component of genContext to generator.
  4. Set the code evaluation state of genContext such that when evaluation is resumed for that execution context the following steps will be performed:
    1. If generatorBody is a Parse Node, then
      1. Let result be the result of evaluating generatorBody.
    2. Else,
      1. Assert: generatorBody is an Abstract Closure with no parameters.
      2. Let result be generatorBody().
    3. Assert: If we return here, the generator either threw an exception or performed either an implicit or explicit return.
    4. 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.
    5. Set generator.[[GeneratorState]] to completed.
    6. 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.
    7. Let env be genContext's LexicalEnvironment.
    8. Set result to DisposeResources(env.[[DisposeCapability]], result).
    9. If result.[[Type]] is normal, let resultValue be undefined.
    10. Else if result.[[Type]] is return, let resultValue be result.[[Value]].
    11. Else,
      1. Assert: result.[[Type]] is throw.
      2. Return ? result.
    12. Return CreateIterResultObject(resultValue, true).
  5. Set generator.[[GeneratorContext]] to genContext.
  6. Set generator.[[GeneratorState]] to suspendedStart.
  7. 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:

  1. Assert: generator.[[AsyncGeneratorState]] is undefined.
  2. Let genContext be the running execution context.
  3. Set the Generator component of genContext to generator.
  4. Set the code evaluation state of genContext such that when evaluation is resumed for that execution context the following steps will be performed:
    1. If generatorBody is a Parse Node, then
      1. Let result be the result of evaluating generatorBody.
    2. Else,
      1. Assert: generatorBody is an Abstract Closure with no parameters.
      2. Let result be Completion(generatorBody()).
    3. Assert: If we return here, the async generator either threw an exception or performed either an implicit or explicit return.
    4. 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.
    5. Set generator.[[AsyncGeneratorState]] to completed.
    6. Let env be genContext's LexicalEnvironment.
    7. Set result to DisposeResources(env.[[DisposeCapability]], result).
    8. If result.[[Type]] is normal, set result to NormalCompletion(undefined).
    9. If result.[[Type]] is return, set result to NormalCompletion(result.[[Value]]).
    10. Perform AsyncGeneratorCompleteStep(generator, result, true).
    11. Perform AsyncGeneratorDrainQueue(generator).
    12. Return undefined.
  5. Set generator.[[AsyncGeneratorContext]] to genContext.
  6. Set generator.[[AsyncGeneratorState]] to suspendedStart.
  7. Set generator.[[AsyncGeneratorQueue]] to a new empty List.
  8. 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:

  1. Assert: promiseCapability is a PromiseCapability Record.
  2. Let runningContext be the running execution context.
  3. Set the code evaluation state of asyncContext such that when evaluation is resumed for that execution context the following steps will be performed:
    1. Let result be the result of evaluating asyncBody.
    2. Assert: If we return here, the async function either threw an exception or performed an implicit or explicit return; all awaiting is done.
    3. 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.
    4. Let env be asyncContext's LexicalEnvironment.
    5. Set result to DisposeResources(env.[[DisposeCapability]], result).
    6. If result.[[Type]] is normal, then
      1. Perform ! Call(promiseCapability.[[Resolve]], undefined, « undefined »).
    7. Else if result.[[Type]] is return, then
      1. Perform ! Call(promiseCapability.[[Resolve]], undefined, « result.[[Value]] »).
    8. Else,
      1. Assert: result.[[Type]] is throw.
      2. Perform ! Call(promiseCapability.[[Reject]], undefined, « result.[[Value]] »).
    9. Return unused.
  4. Push asyncContext onto the execution context stack; asyncContext is now the running execution context.
  5. Resume the suspended evaluation of asyncContext. Let result be the value returned by the resumed computation.
  6. Assert: When we return here, asyncContext has already been removed from the execution context stack and runningContext is the currently running execution context.
  7. 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.
  8. 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:

  1. If env.HasBinding(dn) is false, then
    1. Perform ! env.CreateMutableBinding(dn, false).

During BlockDeclarationInstantiation the following steps are performed in place of step 3.b.iii:

  1. If the binding for fn in env is an uninitialized binding, then
    1. Perform env.InitializeBinding(fn, fo, normal).
  2. Else,
    1. Assert: d is a FunctionDeclaration.
    2. 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:

  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. 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.
  3. 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.