Stage 1 Draft / April 4, 2024

Extractors

Introduction

See the proposal repository for background material and discussion.

Note

Draft Note: Portions of this proposal are intended to align with Pattern Matching. Where appropriate, functionality shared with Pattern Matching will be called out with a Draft Note.

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
@@customMatcher "Symbol.customMatcher" A method that performs custom pattern matching and destructuring semantics. Called by the semantics of the pattern-matching and destructuring features.
Editor's Note

Draft Note: @@customMatcher is also part of the Pattern Matching proposal.

2 Syntax-Directed Operations

2.1 Scope Analysis

2.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. This "*default*" string is never accessible to ECMAScript 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.
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 ] ExtractorBindingPattern : ExtractorMemberExpression ( Elisionopt )
  1. Return a new empty List.
ArrayBindingPattern : [ Elisionopt BindingRestElement ] ExtractorBindingPattern : ExtractorMemberExpression ( Elisionopt BindingRestElement )
  1. Return the BoundNames of BindingRestElement.
ArrayBindingPattern : [ BindingElementList , Elisionopt ] ExtractorBindingPattern : ExtractorMemberExpression ( BindingElementList , Elisionopt )
  1. Return the BoundNames of BindingElementList.
ArrayBindingPattern : [ BindingElementList , Elisionopt BindingRestElement ] ExtractorBindingPattern : ExtractorMemberExpression ( 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*" ».

2.2 Miscellaneous

2.2.1 Runtime Semantics: BindingInitialization

The syntax-directed operation BindingInitialization takes arguments value (an ECMAScript language value) and environment (an Environment Record or undefined) and returns either a normal completion containing unused or an abrupt completion.

Note

undefined is passed for environment to indicate that a PutValue operation should be used to assign the initialization value. This is the case for var statements and formal parameter lists of some non-strict functions (See 10.2.11). In those cases a lexical binding is hoisted and preinitialized prior to evaluation of its initializer.

It is defined piecewise over the following productions:

BindingIdentifier : Identifier
  1. Let name be StringValue of Identifier.
  2. Return ? InitializeBoundName(name, value, environment).
BindingIdentifier : yield
  1. Return ? InitializeBoundName("yield", value, environment).
BindingIdentifier : await
  1. Return ? InitializeBoundName("await", value, environment).
BindingPattern : ObjectBindingPattern
  1. Perform ? RequireObjectCoercible(value).
  2. Return ? BindingInitialization of ObjectBindingPattern with arguments value and environment.
BindingPattern : ArrayBindingPattern
  1. Let iteratorRecord be ? GetIterator(value, sync).
  2. Let result be Completion(IteratorBindingInitialization of ArrayBindingPattern with arguments iteratorRecord and environment).
  3. If iteratorRecord.[[Done]] is false, return ? IteratorClose(iteratorRecord, result).
  4. Return ? result.
ExtractorBindingPattern : ExtractorMemberExpression ( Elisionopt BindingRestElementopt ) ExtractorMemberExpression ( BindingElementList ) ExtractorMemberExpression ( BindingElementList , Elisionopt BindingRestElementopt )
  1. Let expr be the LeftHandSideExpression that is covered by ExtractorMemberExpression.
  2. Let ref be ? Evaluation of expr.
  3. Let extractor be ? GetValue(ref).
  4. If ref is a Reference Record and IsPropertyReference(ref) is true, let receiver be GetThisValue(ref).
  5. Else, let receiver be null.
  6. Let iteratorRecord be ? InvokeCustomMatcherOrThrow(extractor, value, receiver).
  7. Let result be ? IteratorBindingInitialization of this ExtractorBindingPattern with arguments iteratorRecord and environment.
  8. If iteratorRecord.[[Done]] is false, return ? IteratorClose(iteratorRecord, result).
  9. Return ? result.
Editor's Note

Draft Note: receiver is part of the Pattern Matching proposal but does not have consensus in the Pattern Matching champion group yet.

ObjectBindingPattern : { }
  1. Return unused.
ObjectBindingPattern : { BindingPropertyList } { BindingPropertyList , }
  1. Perform ? PropertyBindingInitialization of BindingPropertyList with arguments value and environment.
  2. Return unused.
ObjectBindingPattern : { BindingRestProperty }
  1. Let excludedNames be a new empty List.
  2. Return ? RestBindingInitialization of BindingRestProperty with arguments value, environment, and excludedNames.
ObjectBindingPattern : { BindingPropertyList , BindingRestProperty }
  1. Let excludedNames be ? PropertyBindingInitialization of BindingPropertyList with arguments value and environment.
  2. Return ? RestBindingInitialization of BindingRestProperty with arguments value, environment, and excludedNames.

2.2.1.1 InvokeCustomMatcherOrThrow ( matcher, subject, receiver )

The abstract operation InvokeCustomMatcherOrThrow takes arguments matcher (an ECMAScript language value), subject (an ECMAScript language value), and receiver (an ECMAScript language value) and returns either a normal completion containing an Object, or a throw completion. It performs the following steps when called:

  1. If matcher is not an Object, throw a TypeError exception.
  2. Let f be ? GetMethod(matcher, @@customMatcher).
  3. If f is undefined, throw a TypeError exception.
  4. Let result be ? Call(f, matcher, « subject, "list", receiver »).
  5. If result is not an Object, throw a TypeError exception.
  6. Let iteratorRecord be ? GetIterator(result, sync).
  7. Return iteratorRecord.
Editor's Note

Draft Note: The InvokeCustomMatcherOrThrow abstract operation is derived from InvokeCustomMatcher in the Pattern Matching proposal.

Editor's Note

Draft Note: The value "list" is related to two different modes ("boolean" and "list") supported by custom matchers in the Pattern Matching proposal and is provided here to satisfy cross-cutting concerns between the two proposals.

Editor's Note

Draft Note: The receiver parameter is not a consensus in the Pattern Matching champion group yet. This design is to keep the this value when calling the custom matchers. Not everyone in the champion group agrees we need to keep the this value.

Editor's Note

Draft Note: This proposal currently uses iterators for destructuring, but may choose to use Array objects explicitly in the future due to performance concerns related to iterators.

2.2.2 Runtime Semantics: IteratorBindingInitialization

The syntax-directed operation IteratorBindingInitialization takes arguments iteratorRecord (an Iterator Record) and environment (an Environment Record or undefined) 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 : [ ] ExtractorBindingPattern : ExtractorMemberExpression ( )
  1. Return unused.
ArrayBindingPattern : [ Elision ] ExtractorBindingPattern : ExtractorMemberExpression ( Elision )
  1. Return ? IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord.
ArrayBindingPattern : [ Elisionopt BindingRestElement ] ExtractorBindingPattern : ExtractorMemberExpression ( 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 ] ExtractorBindingPattern : ExtractorMemberExpression ( BindingElementList , Elision )
  1. Perform ? IteratorBindingInitialization of BindingElementList with arguments iteratorRecord and environment.
  2. Return ? IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord.
ArrayBindingPattern : [ BindingElementList , Elisionopt BindingRestElement ] ExtractorBindingPattern : ExtractorMemberExpression ( 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 ? IteratorStepValue(iteratorRecord).
    2. If next is not done, then
      1. Set v to next.
  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).
BindingElement : BindingPattern Initializeropt
  1. Let v be undefined.
  2. If iteratorRecord.[[Done]] is false, then
    1. Let next be ? IteratorStepValue(iteratorRecord).
    2. If next is not done, then
      1. Set v to next.
  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. Let next be done.
    2. If iteratorRecord.[[Done]] is false, then
      1. Set next to ? IteratorStepValue(iteratorRecord).
    3. If next is done, then
      1. If environment is undefined, return ? PutValue(lhs, A).
      2. Return ? InitializeReferencedBinding(lhs, A).
    4. Perform ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(n)), next).
    5. Set n to n + 1.
BindingRestElement : ... BindingPattern
  1. Let A be ! ArrayCreate(0).
  2. Let n be 0.
  3. Repeat,
    1. Let next be done.
    2. If iteratorRecord.[[Done]] is false, then
      1. Set next to ? IteratorStepValue(iteratorRecord).
    3. If next is done, then
      1. Return ? BindingInitialization of BindingPattern with arguments A and environment.
    4. Perform ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(n)), next).
    5. 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 ? IteratorStepValue(iteratorRecord).
  4. If next is not done, then
    1. Set v to next.
  5. 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 ? IteratorStepValue(iteratorRecord).
  4. If next is not done, then
    1. Set v to next.
  5. Return ? BindingInitialization of BindingIdentifier with arguments v and environment.

3 ECMAScript Language: Expressions

3.1 Left-Hand-Side Expressions

Syntax

MemberExpression[Yield, Await] : PrimaryExpression[?Yield, ?Await] MemberExpression[?Yield, ?Await] [ Expression[+In, ?Yield, ?Await] ] MemberExpression[?Yield, ?Await] . IdentifierName MemberExpression[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged] SuperProperty[?Yield, ?Await] MetaProperty new MemberExpression[?Yield, ?Await] Arguments[?Yield, ?Await] MemberExpression[?Yield, ?Await] . PrivateIdentifier SuperProperty[Yield, Await] : super [ Expression[+In, ?Yield, ?Await] ] super . IdentifierName MetaProperty : NewTarget ImportMeta NewTarget : new . target ImportMeta : import . meta NewExpression[Yield, Await] : MemberExpression[?Yield, ?Await] new NewExpression[?Yield, ?Await] CallExpression[Yield, Await] : CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await] SuperCall[?Yield, ?Await] ImportCall[?Yield, ?Await] CallExpression[?Yield, ?Await] Arguments[?Yield, ?Await] FunctionCall[?Yield, ?Await] CallExpression[?Yield, ?Await] [ Expression[+In, ?Yield, ?Await] ] CallExpression[?Yield, ?Await] . IdentifierName CallExpression[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged] CallExpression[?Yield, ?Await] . PrivateIdentifier FunctionCall[Yield, Await] : CallExpression[?Yield, ?Await] Arguments[?Yield, ?Await] SuperCall[Yield, Await] : super Arguments[?Yield, ?Await] ImportCall[Yield, Await] : import ( AssignmentExpression[+In, ?Yield, ?Await] ) Arguments[Yield, Await] : ( ) ( ArgumentList[?Yield, ?Await] ) ( ArgumentList[?Yield, ?Await] , ) ArgumentList[Yield, Await] : AssignmentExpression[+In, ?Yield, ?Await] ... AssignmentExpression[+In, ?Yield, ?Await] ArgumentList[?Yield, ?Await] , AssignmentExpression[+In, ?Yield, ?Await] ArgumentList[?Yield, ?Await] , ... AssignmentExpression[+In, ?Yield, ?Await] OptionalExpression[Yield, Await] : MemberExpression[?Yield, ?Await] OptionalChain[?Yield, ?Await] CallExpression[?Yield, ?Await] OptionalChain[?Yield, ?Await] OptionalExpression[?Yield, ?Await] OptionalChain[?Yield, ?Await] OptionalChain[Yield, Await] : ?. Arguments[?Yield, ?Await] ?. [ Expression[+In, ?Yield, ?Await] ] ?. IdentifierName ?. TemplateLiteral[?Yield, ?Await, +Tagged] ?. PrivateIdentifier OptionalChain[?Yield, ?Await] Arguments[?Yield, ?Await] OptionalChain[?Yield, ?Await] [ Expression[+In, ?Yield, ?Await] ] OptionalChain[?Yield, ?Await] . IdentifierName OptionalChain[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged] OptionalChain[?Yield, ?Await] . PrivateIdentifier LeftHandSideExpression[Yield, Await] : NewExpression[?Yield, ?Await] CallExpression[?Yield, ?Await] OptionalExpression[?Yield, ?Await]

Supplemental Syntax

When processing an instance of the production
CallExpression : CoverCallExpressionAndAsyncArrowHead
the interpretation of CoverCallExpressionAndAsyncArrowHead is refined using the following grammar:

CallMemberExpression[Yield, Await] : MemberExpression[?Yield, ?Await] Arguments[?Yield, ?Await]

3.1.1 Function Calls

3.1.1.1 Runtime Semantics: Evaluation

CallExpression : CoverCallExpressionAndAsyncArrowHead
  1. Let expr be the CallMemberExpression that is covered by CoverCallExpressionAndAsyncArrowHead.
  2. Let memberExpr be the MemberExpression of expr.
  3. Let arguments be the Arguments of expr.
  4. Let ref be ? Evaluation of memberExpr.
  5. Let func be ? GetValue(ref).
  6. If ref is a Reference Record, IsPropertyReference(ref) is false, and ref.[[ReferencedName]] is "eval", then
    1. If SameValue(func, %eval%) is true, then
      1. Let argList be ? ArgumentListEvaluation of arguments.
      2. If argList has no elements, return undefined.
      3. Let evalArg be the first element of argList.
      4. If IsStrict(this CallExpression) is true, let strictCaller be true. Otherwise let strictCaller be false.
      5. Return ? PerformEval(evalArg, strictCaller, true).
  7. Let thisCall be this CallExpression.
  8. Let tailCall be IsInTailPosition(thisCall).
  9. Return ? EvaluateCall(func, ref, arguments, tailCall).

A CallExpression evaluation that executes step 6.a.v is a direct eval.

CallExpression : CallExpression Arguments FunctionCall : CallExpression Arguments
  1. Let ref be ? Evaluation of CallExpression.
  2. Let func be ? GetValue(ref).
  3. Let thisCall be this CallExpression.
  4. Let tailCall be IsInTailPosition(thisCall).
  5. Return ? EvaluateCall(func, ref, Arguments, tailCall).

3.2 Assignment Operators

3.2.1 Runtime Semantics: Evaluation

AssignmentExpression : LeftHandSideExpression = AssignmentExpression
  1. If LeftHandSideExpression is neither an ObjectLiteral nor, an ArrayLiteral, a FunctionCall, nor a CallMemberExpression, then
    1. Let lref be ? Evaluation of LeftHandSideExpression.
    2. If IsAnonymousFunctionDefinition(AssignmentExpression) and IsIdentifierRef of LeftHandSideExpression are both true, then
      1. Let rval be ? NamedEvaluation of AssignmentExpression with argument lref.[[ReferencedName]].
    3. Else,
      1. Let rref be ? Evaluation of AssignmentExpression.
      2. Let rval be ? GetValue(rref).
    4. Perform ? PutValue(lref, rval).
    5. Return rval.
  2. Let assignmentPattern be the AssignmentPattern that is covered by LeftHandSideExpression.
  3. Let rref be ? Evaluation of AssignmentExpression.
  4. Let rval be ? GetValue(rref).
  5. Perform ? DestructuringAssignmentEvaluation of assignmentPattern with argument rval.
  6. Return rval.
AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression
  1. Let lref be ? Evaluation of LeftHandSideExpression.
  2. Let lval be ? GetValue(lref).
  3. Let rref be ? Evaluation of AssignmentExpression.
  4. Let rval be ? GetValue(rref).
  5. Let assignmentOpText be the source text matched by AssignmentOperator.
  6. Let opText be the sequence of Unicode code points associated with assignmentOpText in the following table:
    assignmentOpText opText
    **= **
    *= *
    /= /
    %= %
    += +
    -= -
    <<= <<
    >>= >>
    >>>= >>>
    &= &
    ^= ^
    |= |
  7. Let r be ? ApplyStringOrNumericBinaryOperator(lval, opText, rval).
  8. Perform ? PutValue(lref, r).
  9. Return r.
AssignmentExpression : LeftHandSideExpression &&= AssignmentExpression
  1. Let lref be ? Evaluation of LeftHandSideExpression.
  2. Let lval be ? GetValue(lref).
  3. Let lbool be ToBoolean(lval).
  4. If lbool is false, return lval.
  5. If IsAnonymousFunctionDefinition(AssignmentExpression) is true and IsIdentifierRef of LeftHandSideExpression is true, then
    1. Let rval be ? NamedEvaluation of AssignmentExpression with argument lref.[[ReferencedName]].
  6. Else,
    1. Let rref be ? Evaluation of AssignmentExpression.
    2. Let rval be ? GetValue(rref).
  7. Perform ? PutValue(lref, rval).
  8. Return rval.
AssignmentExpression : LeftHandSideExpression ||= AssignmentExpression
  1. Let lref be ? Evaluation of LeftHandSideExpression.
  2. Let lval be ? GetValue(lref).
  3. Let lbool be ToBoolean(lval).
  4. If lbool is true, return lval.
  5. If IsAnonymousFunctionDefinition(AssignmentExpression) is true and IsIdentifierRef of LeftHandSideExpression is true, then
    1. Let rval be ? NamedEvaluation of AssignmentExpression with argument lref.[[ReferencedName]].
  6. Else,
    1. Let rref be ? Evaluation of AssignmentExpression.
    2. Let rval be ? GetValue(rref).
  7. Perform ? PutValue(lref, rval).
  8. Return rval.
AssignmentExpression : LeftHandSideExpression ??= AssignmentExpression
  1. Let lref be ? Evaluation of LeftHandSideExpression.
  2. Let lval be ? GetValue(lref).
  3. If lval is neither undefined nor null, return lval.
  4. If IsAnonymousFunctionDefinition(AssignmentExpression) is true and IsIdentifierRef of LeftHandSideExpression is true, then
    1. Let rval be ? NamedEvaluation of AssignmentExpression with argument lref.[[ReferencedName]].
  5. Else,
    1. Let rref be ? Evaluation of AssignmentExpression.
    2. Let rval be ? GetValue(rref).
  6. Perform ? PutValue(lref, rval).
  7. Return rval.
Note

When this expression occurs within strict mode code, it is a runtime error if lref in step 1.d, 2, 2, 2, 2 is an unresolvable reference. If it is, a ReferenceError exception is thrown. Additionally, it is a runtime error if the lref in step 8, 7, 7, 6 is a reference to a data property with the attribute value { [[Writable]]: false }, to an accessor property with the attribute value { [[Set]]: undefined }, or to a non-existent property of an object for which the IsExtensible predicate returns the value false. In these cases a TypeError exception is thrown.

3.2.2 Destructuring Assignment

Supplemental Syntax

In certain circumstances when processing an instance of the production
AssignmentExpression : LeftHandSideExpression = AssignmentExpression
the interpretation of LeftHandSideExpression is refined using the following grammar:

AssignmentPattern[Yield, Await] : ObjectAssignmentPattern[?Yield, ?Await] ArrayAssignmentPattern[?Yield, ?Await] ExtractorAssignmentPattern[?Yield, ?Await] ObjectAssignmentPattern[Yield, Await] : { } { AssignmentRestProperty[?Yield, ?Await] } { AssignmentPropertyList[?Yield, ?Await] } { AssignmentPropertyList[?Yield, ?Await] , AssignmentRestProperty[?Yield, ?Await]opt } ArrayAssignmentPattern[Yield, Await] : [ Elisionopt AssignmentRestElement[?Yield, ?Await]opt ] [ AssignmentElementList[?Yield, ?Await] ] [ AssignmentElementList[?Yield, ?Await] , Elisionopt AssignmentRestElement[?Yield, ?Await]opt ] ExtractorAssignmentPattern[Yield, Await] : ExtractorMemberExpression[?Yield, ?Await] ( Elisionopt AssignmentRestElement[?Yield, ?Await]opt ) ExtractorMemberExpression[?Yield, ?Await] ( AssignmentElementList[?Yield, ?Await] ) ExtractorMemberExpression[?Yield, ?Await] ( AssignmentElementList[?Yield, ?Await] , Elisionopt AssignmentRestElement[?Yield, ?Await]opt ) AssignmentRestProperty[Yield, Await] : ... DestructuringAssignmentTarget[?Yield, ?Await] AssignmentPropertyList[Yield, Await] : AssignmentProperty[?Yield, ?Await] AssignmentPropertyList[?Yield, ?Await] , AssignmentProperty[?Yield, ?Await] AssignmentElementList[Yield, Await] : AssignmentElisionElement[?Yield, ?Await] AssignmentElementList[?Yield, ?Await] , AssignmentElisionElement[?Yield, ?Await] AssignmentElisionElement[Yield, Await] : Elisionopt AssignmentElement[?Yield, ?Await] AssignmentProperty[Yield, Await] : IdentifierReference[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt PropertyName[?Yield, ?Await] : AssignmentElement[?Yield, ?Await] AssignmentElement[Yield, Await] : DestructuringAssignmentTarget[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt AssignmentRestElement[Yield, Await] : ... DestructuringAssignmentTarget[?Yield, ?Await] DestructuringAssignmentTarget[Yield, Await] : LeftHandSideExpression[?Yield, ?Await]

3.2.2.1 Static Semantics: Early Errors

AssignmentProperty : IdentifierReference Initializeropt AssignmentRestProperty : ... DestructuringAssignmentTarget DestructuringAssignmentTarget : LeftHandSideExpression

3.2.2.2 Runtime Semantics: DestructuringAssignmentEvaluation

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

ObjectAssignmentPattern : { }
  1. Perform ? RequireObjectCoercible(value).
  2. Return unused.
ObjectAssignmentPattern : { AssignmentPropertyList } { AssignmentPropertyList , }
  1. Perform ? RequireObjectCoercible(value).
  2. Perform ? PropertyDestructuringAssignmentEvaluation of AssignmentPropertyList with argument value.
  3. Return unused.
ObjectAssignmentPattern : { AssignmentRestProperty }
  1. Perform ? RequireObjectCoercible(value).
  2. Let excludedNames be a new empty List.
  3. Return ? RestDestructuringAssignmentEvaluation of AssignmentRestProperty with arguments value and excludedNames.
ObjectAssignmentPattern : { AssignmentPropertyList , AssignmentRestProperty }
  1. Perform ? RequireObjectCoercible(value).
  2. Let excludedNames be ? PropertyDestructuringAssignmentEvaluation of AssignmentPropertyList with argument value.
  3. Return ? RestDestructuringAssignmentEvaluation of AssignmentRestProperty with arguments value and excludedNames.
ArrayAssignmentPattern : [ ]
  1. Let iteratorRecord be ? GetIterator(value, sync).
  2. Return ? IteratorClose(iteratorRecord, NormalCompletion(unused)).
ArrayAssignmentPattern : [ Elision ]
  1. Let iteratorRecord be ? GetIterator(value, sync).
  2. Let result be Completion(IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord).
  3. If iteratorRecord.[[Done]] is false, return ? IteratorClose(iteratorRecord, result).
  4. Return result.
ArrayAssignmentPattern : [ Elisionopt AssignmentRestElement ]
  1. Let iteratorRecord be ? GetIterator(value, sync).
  2. If Elision is present, then
    1. Let status be Completion(IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord).
    2. If status is an abrupt completion, then
      1. Assert: iteratorRecord.[[Done]] is true.
      2. Return ? status.
  3. Let result be Completion(IteratorDestructuringAssignmentEvaluation of AssignmentRestElement with argument iteratorRecord).
  4. If iteratorRecord.[[Done]] is false, return ? IteratorClose(iteratorRecord, result).
  5. Return result.
ArrayAssignmentPattern : [ AssignmentElementList ]
  1. Let iteratorRecord be ? GetIterator(value, sync).
  2. Let result be Completion(IteratorDestructuringAssignmentEvaluation of AssignmentElementList with argument iteratorRecord).
  3. If iteratorRecord.[[Done]] is false, return ? IteratorClose(iteratorRecord, result).
  4. Return result.
ArrayAssignmentPattern : [ AssignmentElementList , Elisionopt AssignmentRestElementopt ]
  1. Let iteratorRecord be ? GetIterator(value, sync).
  2. Let status be Completion(IteratorDestructuringAssignmentEvaluation of AssignmentElementList with argument iteratorRecord).
  3. If status is an abrupt completion, then
    1. If iteratorRecord.[[Done]] is false, return ? IteratorClose(iteratorRecord, status).
    2. Return ? status.
  4. If Elision is present, then
    1. Set status to Completion(IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord).
    2. If status is an abrupt completion, then
      1. Assert: iteratorRecord.[[Done]] is true.
      2. Return ? status.
  5. If AssignmentRestElement is present, then
    1. Set status to Completion(IteratorDestructuringAssignmentEvaluation of AssignmentRestElement with argument iteratorRecord).
  6. If iteratorRecord.[[Done]] is false, return ? IteratorClose(iteratorRecord, status).
  7. Return ? status.
ExtractorAssignmentPattern : ExtractorMemberExpression ( )
  1. Let expr be the LeftHandSideExpression that is covered by ExtractorMemberExpression.
  2. Let ref be ? Evaluation of expr.
  3. Let extractor be ? GetValue(ref).
  4. If ref is a Reference Record and IsPropertyReference(ref) is true, let receiver be GetThisValue(ref).
  5. Else, Let receiver be null.
  6. Let obj be ? InvokeCustomMatcherOrThrow(extractor, value, receiver).
  7. Let iteratorRecord be ? GetIterator(obj, sync).
  8. Return ? IteratorClose(iteratorRecord, NormalCompletion(unused)).
ExtractorAssignmentPattern : ExtractorMemberExpression ( Elision )
  1. Let expr be the LeftHandSideExpression that is covered by ExtractorMemberExpression.
  2. Let ref be ? Evaluation of expr.
  3. Let extractor be ? GetValue(ref).
  4. If ref is a Reference Record and IsPropertyReference(ref) is true, let receiver be GetThisValue(ref).
  5. Else, Let receiver be null.
  6. Let obj be ? InvokeCustomMatcherOrThrow(extractor, value, receiver).
  7. Let iteratorRecord be ? GetIterator(obj, sync).
  8. Let result be Completion(IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord).
  9. If iteratorRecord.[[Done]] is false, return ? IteratorClose(iteratorRecord, result).
  10. Return result.
ExtractorAssignmentPattern : ExtractorMemberExpression ( Elisionopt AssignmentRestElement )
  1. Let expr be the LeftHandSideExpression that is covered by ExtractorMemberExpression.
  2. Let ref be ? Evaluation of expr.
  3. Let extractor be ? GetValue(ref).
  4. If ref is a Reference Record and IsPropertyReference(ref) is true, let receiver be GetThisValue(ref).
  5. Else, Let receiver be null.
  6. Let obj be ? InvokeCustomMatcherOrThrow(extractor, value, receiver).
  7. Let iteratorRecord be ? GetIterator(obj, sync).
  8. If Elision is present, then
    1. Let status be Completion(IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord).
    2. If status is an abrupt completion, then
      1. Assert: iteratorRecord.[[Done]] is true.
      2. Return ? status.
  9. Let result be Completion(IteratorDestructuringAssignmentEvaluation of AssignmentRestElement with argument iteratorRecord).
  10. If iteratorRecord.[[Done]] is false, return ? IteratorClose(iteratorRecord, result).
  11. Return result.
ExtractorAssignmentPattern : ExtractorMemberExpression ( AssignmentElementList )
  1. Let expr be the LeftHandSideExpression that is covered by ExtractorMemberExpression.
  2. Let ref be ? Evaluation of expr.
  3. Let extractor be ? GetValue(ref).
  4. If ref is a Reference Record and IsPropertyReference(ref) is true, let receiver be GetThisValue(ref).
  5. Else, Let receiver be null.
  6. Let obj be ? InvokeCustomMatcherOrThrow(extractor, value, receiver).
  7. Let iteratorRecord be ? GetIterator(obj, sync).
  8. Let result be Completion(IteratorDestructuringAssignmentEvaluation of AssignmentElementList with argument iteratorRecord).
  9. If iteratorRecord.[[Done]] is false, return ? IteratorClose(iteratorRecord, result).
  10. Return result.
ExtractorAssignmentPattern : ExtractorMemberExpression ( AssignmentElementList , Elisionopt AssignmentRestElementopt )
  1. Let expr be the LeftHandSideExpression that is covered by ExtractorMemberExpression.
  2. Let ref be ? Evaluation of expr.
  3. Let extractor be ? GetValue(ref).
  4. If ref is a Reference Record and IsPropertyReference(ref) is true, let receiver be GetThisValue(ref).
  5. Else, Let receiver be null.
  6. Let obj be ? InvokeCustomMatcherOrThrow(extractor, value, receiver).
  7. Let iteratorRecord be ? GetIterator(obj, sync).
  8. Let status be Completion(IteratorDestructuringAssignmentEvaluation of AssignmentElementList with argument iteratorRecord).
  9. If status is an abrupt completion, then
    1. If iteratorRecord.[[Done]] is false, return ? IteratorClose(iteratorRecord, status).
    2. Return ? status.
  10. If Elision is present, then
    1. Set status to Completion(IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord).
    2. If status is an abrupt completion, then
      1. Assert: iteratorRecord.[[Done]] is true.
      2. Return ? status.
  11. If AssignmentRestElement is present, then
    1. Set status to Completion(IteratorDestructuringAssignmentEvaluation of AssignmentRestElement with argument iteratorRecord).
  12. If iteratorRecord.[[Done]] is false, return ? IteratorClose(iteratorRecord, status).
  13. Return ? status.
Editor's Note

Draft Note: receiver is part of the Pattern Matching proposal but does not have consensus in the Pattern Matching champion group yet.

4 ECMAScript Language: Statements and Declarations

4.1 Declarations and the Variable Statement

4.1.1 Destructuring Binding Patterns

Syntax

BindingPattern[Yield, Await] : ObjectBindingPattern[?Yield, ?Await] ArrayBindingPattern[?Yield, ?Await] ExtractorBindingPattern[?Yield, ?Await] ObjectBindingPattern[Yield, Await] : { } { BindingRestProperty[?Yield, ?Await] } { BindingPropertyList[?Yield, ?Await] } { BindingPropertyList[?Yield, ?Await] , BindingRestProperty[?Yield, ?Await]opt } ArrayBindingPattern[Yield, Await] : [ Elisionopt BindingRestElement[?Yield, ?Await]opt ] [ BindingElementList[?Yield, ?Await] ] [ BindingElementList[?Yield, ?Await] , Elisionopt BindingRestElement[?Yield, ?Await]opt ] ExtractorBindingPattern[Yield, Await] : ExtractorMemberExpression[?Yield, ?Await] ( Elisionopt BindingRestElement[?Yield, ?Await]opt ) ExtractorMemberExpression[?Yield, ?Await] ( BindingElementList[?Yield, ?Await] ) ExtractorMemberExpression[?Yield, ?Await] ( BindingElementList[?Yield, ?Await] , Elisionopt BindingRestElement[?Yield, ?Await]opt ) ExtractorMemberExpression[Yield, Await] : this MetaProperty IdentifierReference[?Yield, ?Await] super . IdentifierName ExtractorMemberExpression[?Yield, ?Await] . IdentifierName ExtractorMemberExpression[?Yield, ?Await] . PrivateIdentifier ExtractorMemberExpression[?Yield, ?Await] [ Expression[+In, ?Yield, ?Await] ] Editor's Note

Draft Note: The ExtractorMemberExpression production is equivalent to PatternMatchingMemberExpression in the Pattern Matching proposal.

BindingRestProperty[Yield, Await] : ... BindingIdentifier[?Yield, ?Await] BindingPropertyList[Yield, Await] : BindingProperty[?Yield, ?Await] BindingPropertyList[?Yield, ?Await] , BindingProperty[?Yield, ?Await] BindingElementList[Yield, Await] : BindingElisionElement[?Yield, ?Await] BindingElementList[?Yield, ?Await] , BindingElisionElement[?Yield, ?Await] BindingElisionElement[Yield, Await] : Elisionopt BindingElement[?Yield, ?Await] BindingProperty[Yield, Await] : SingleNameBinding[?Yield, ?Await] PropertyName[?Yield, ?Await] : BindingElement[?Yield, ?Await] BindingElement[Yield, Await] : SingleNameBinding[?Yield, ?Await] BindingPattern[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt SingleNameBinding[Yield, Await] : BindingIdentifier[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt BindingRestElement[Yield, Await] : ... BindingIdentifier[?Yield, ?Await] ... BindingPattern[?Yield, ?Await]

A Copyright & Software License

Copyright Notice

© 2024 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.