Stage 2 Draft / July 15, 2024

Destructuring Private Fields

1 Scope

This is the spec text of the Destructuring Private Fields proposal in ECMAScript.

2 2

3 3

4 4

5 5

6 6

7 7

8 Syntax-Directed Operations

8.1 1

8.2 2

8.3 3

8.4 4

8.5 Miscellaneous

8.5.1 RS: InstantiateFunctionObject

8.5.2 RS: BindingInitialization

8.5.3 RS: IteratorBindingInitialization

8.5.4 SS: AssignmentTargetType

8.5.5 Static Semantics: PropName

PropertyDefinition : PrivateIdentifier : AssignmentExpression
  1. Return empty.

9 9

10 10

11 11

12 12

13 ECMAScript Language: Expressions

13.1 1

13.2 Primary Expression

13.2.1 The this Keyword

13.2.2 Identifier Reference

13.2.3 Literals

13.2.4 Array Initializer

13.2.5 Object Initializer

Note

An object initializer is an expression describing the initialization of an Object, written in a form resembling a literal. It is a list of zero or more pairs of property keys and associated values, enclosed in curly brackets. The values need not be literals; they are evaluated each time the object initializer is evaluated.

Syntax

ObjectLiteral[Yield, Await] : { } { PropertyDefinitionList[?Yield, ?Await] } { PropertyDefinitionList[?Yield, ?Await] , } PropertyDefinitionList[Yield, Await] : PropertyDefinition[?Yield, ?Await] PropertyDefinitionList[?Yield, ?Await] , PropertyDefinition[?Yield, ?Await] PropertyDefinition[Yield, Await] : IdentifierReference[?Yield, ?Await] CoverInitializedName[?Yield, ?Await] PropertyName[?Yield, ?Await] : AssignmentExpression[+In, ?Yield, ?Await] PrivateIdentifier[?Yield, ?Await] : AssignmentExpression[+In, ?Yield, ?Await] MethodDefinition[?Yield, ?Await] ... AssignmentExpression[+In, ?Yield, ?Await] PropertyName[Yield, Await] : LiteralPropertyName ComputedPropertyName[?Yield, ?Await] LiteralPropertyName : IdentifierName StringLiteral NumericLiteral ComputedPropertyName[Yield, Await] : [ AssignmentExpression[+In, ?Yield, ?Await] ] CoverInitializedName[Yield, Await] : IdentifierReference[?Yield, ?Await] Initializer[+In, ?Yield, ?Await] Initializer[In, Yield, Await] : = AssignmentExpression[?In, ?Yield, ?Await]

13.2.5.1 Static Semantics: Early Errors

In addition to describing an actual object initializer the ObjectLiteral productions are also used as a cover grammar for ObjectAssignmentPattern and may be recognized as part of a CoverParenthesizedExpressionAndArrowParameterList. When ObjectLiteral appears in a context where ObjectAssignmentPattern is required the following Early Error rules are not applied. In addition, they are not applied when initially parsing a CoverParenthesizedExpressionAndArrowParameterList or CoverCallExpressionAndAsyncArrowHead.

PropertyDefinition : PrivateIdentifier : AssignmentExpression
  • Always throw a Syntax Error if code matches this production.

13.3 3

13.4 4

13.5 5

13.6 6

13.7 7

13.8 8

13.9 9

13.10 10

13.11 11

13.12 12

13.13 13

13.14 14

13.15 Assignment Operators

13.15.1 Static Semantics: Early Errors

13.15.2 Runtime Semantics: Evaluation

13.15.3 ApplyStringOrNumericBinaryOperator

13.15.4 EvaluateStringOrNumericBinaryExpression

13.15.5 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] 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 ] 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] PrivateIdentifier : 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]

13.15.5.1 Static Semantics: Early Errors

13.15.5.2 Runtime Semantics: PropertyDestructuringAssignmentEvaluation ( value: unknown, )

Note 1
The following operations collect a list of all destructured property names.
AssignmentProperty : PrivateIdentifier : AssignmentElement
  1. Let privateIdentifier be the StringValue of PrivateIdentifier.
  2. Let privateEnv be the running execution context's PrivateEnvironment.
  3. Let privateName be ResolvePrivateIdentifier(privateEnv, privateIdentifier).
  4. Perform ? KeyedDestructuringAssignmentEvaluation of AssignmentElement with value and privateName as the arguments.
  5. Return a new empty List.
Note 2
PropertyDestructuringAssignmentEvaluation returns a list of property names which are kept so they can be excluded from a AssignmentRestProperty. Because AssignmentRestProperty already does not copy private fields to the new object, we do not need to add our privateName to the list.

13.15.5.3 Runtime Semantics: PropertyDestructuringAssignmentEvaluation

13.15.5.4 Runtime Semantics: RestDestructuringAssignmentEvaluation

13.15.5.5 Runtime Semantics: IteratorDestructuringAssignmentEvaluation

13.15.5.6 Runtime Semantics: KeyedDestructuringAssignmentEvaluation ( value: unknown, propertyName: unknown, )

AssignmentElement : DestructuringAssignmentTarget Initializeropt
  1. If DestructuringAssignmentTarget is neither an ObjectLiteral nor an ArrayLiteral, then
    1. Let lref be the result of evaluating DestructuringAssignmentTarget.
    2. ReturnIfAbrupt(lref).
  2. Let v to ? GetV(value, propertyName).
  3. If propertyName is a Private Name, then
    1. Let v be ? PrivateGet(propertyName, value).
  4. Else,
    1. Let v be ? GetV(value, propertyName).
  5. If Initializer is present and v is undefined, then
    1. If IsAnonymousFunctionDefinition(Initializer) and IsIdentifierRef of DestructuringAssignmentTarget are both true, then
      1. Let rhsValue be ? NamedEvaluation of Initializer with argument lref.[[ReferencedName]].
    2. Else,
      1. Let defaultValue be the result of evaluating Initializer.
      2. Let rhsValue be ? GetValue(defaultValue).
  6. Else, let rhsValue be v.
  7. If DestructuringAssignmentTarget is an ObjectLiteral or an ArrayLiteral, then
    1. Let assignmentPattern be the AssignmentPattern that is covered by DestructuringAssignmentTarget.
    2. Return the result of performing DestructuringAssignmentEvaluation of assignmentPattern with rhsValue as the argument.
  8. Return ? PutValue(lref, rhsValue).

14 ECMAScript Language: Statements and Declarations

14.1 1

14.2 2

14.3 Declarations and the Variable Statement

14.3.1 Let and Const Declarations

14.3.2 Variable Statement

14.3.3 Destructuring Binding Patterns

Syntax

BindingPattern[Yield, Await] : ObjectBindingPattern[?Yield, ?Await] ArrayBindingPattern[?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 ] 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] PrivateIdentifier : 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]

14.3.3.1 Runtime Semantics: PropertyBindingInitialization

The syntax-directed operation PropertyBindingInitialization takes arguments value and environment. It collects a list of all bound property names rather than just empty completion.

BindingProperty : PrivateIdentifier : BindingElement
  1. Let privateIdentifier be the StringValue of PrivateIdentifier.
  2. Let privateEnv be the running execution context's PrivateEnvironment.
  3. Let privateName be ResolvePrivateIdentifier(privateEnv, privateIdentifier).
  4. Perform ? KeyedBindingInitialization of BindingElement with value, environment, and privateName as the arguments.
  5. Return a new empty List.

14.3.3.2 Runtime Semantics: RestBindingInitialization

14.3.3.3 Runtime Semantics: KeyedBindingInitialization ( value: unknown, environment: unknown, propertyName: unknown, )

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.

BindingElement : BindingPattern Initializeropt
  1. Let v to ? GetV(value, propertyName).
  2. If propertyName is a Private Name, then
    1. Let v be ? PrivateGet(propertyName, value).
  3. Else,
    1. Let v be ? GetV(value, propertyName).
  4. If Initializer is present and v is undefined, then
    1. Let defaultValue be the result of evaluating Initializer.
    2. Set v to ? GetValue(defaultValue).
  5. Return the result of performing BindingInitialization for BindingPattern passing v and environment as arguments.
SingleNameBinding : BindingIdentifier Initializeropt
  1. Let bindingId be StringValue of BindingIdentifier.
  2. Let lhs be ? ResolveBinding(bindingId, environment).
  3. Let v to ? GetV(value, propertyName).
  4. If propertyName is a Private Name, then
    1. Let v be ? PrivateGet(propertyName, value).
  5. Else,
    1. Let v be ? GetV(value, propertyName).
  6. If Initializer is present and v is undefined, then
    1. If IsAnonymousFunctionDefinition(Initializer) is true, then
      1. Set v to the result of performing NamedEvaluation for Initializer with argument bindingId.
    2. Else,
      1. Let defaultValue be the result of evaluating Initializer.
      2. Set v to ? GetValue(defaultValue).
  7. If environment is undefined, return ? PutValue(lhs, v).
  8. Return InitializeReferencedBinding(lhs, v).

15 ECMAScript Language: Functions and Classes

15.1 1

15.2 2

15.3 3

15.4 4

15.5 5

15.6 6

15.7 Class Definitions

15.7.1 Static Semantics: Early Errors

15.7.2 Static Semantics: ClassElementKind

15.7.3 Static Semantics: ConstructorMethod

15.7.4 Static Semantics: IsStatic

15.7.5 Static Semantics: NonConstructorElements

15.7.6 Static Semantics: PrototypePropertyNameList

15.7.7 Static Semantics: AllPrivateIdentifiersValid

With parameter names.

AssignmentProperty : PrivateIdentifier : AssignmentElement
  1. If names contains the StringValue of PrivateIdentifier, then
    1. Return AllPrivateIdentifiersValid of AssignmentElement with argument names.
  2. Return false.
BindingProperty : PrivateIdentifier : BindingElement
  1. If names contains the StringValue of PrivateIdentifier, then
    1. Return AllPrivateIdentifiersValid of BindingElement with argument names.
  2. Return false.

A Copyright & Software License

Copyright Notice

© 2024 Justin Ridgewell

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.