Stage 1 Draft / May 25, 2022

Grouped Accessors and Auto Accessors

Introduction

This proposal defines additional syntax for accessor properties in classes and object literals.

See the proposal repository for background material and discussion.

1 ECMAScript Data Types and Values

1.1 ECMAScript Specification Types

1.1.1 The ClassElementDefinition Record Specification Type

The ClassElementDefinition type is a Record used in the specification of private and public, static and non-static class fields, methods, and accessors.

Values of the ClassElementDefinition type are Record values whose fields are defined by Table 1. Such values are referred to as ClassElementDefinition Records.

Table 1: ClassElementDefinition Record Fields
Field Name Values of the [[Kind]] field for which it is present Value Meaning
[[Key]] field, method, accessor, getter, setter a Private Name, a String, or a Symbol The name of the field.
[[Kind]] field, method, accessor, getter, or setter field, method, accessor, getter, or setter The kind of the element.
[[Value]] method a function object The function for a method definition.
[[Get]] accessor and getter a function object or undefined The getter for an accessor definition.
[[Set]] accessor and setter a function object or undefined The setter for an accessor definition.
[[BackingStorageKey]] accessor a Private Name or empty A private name for the backing state behind accessors defined with the accessor keyword
[[PrivateSetKey]] accessor a Private Name or empty A private name for the private setter in an accessor group
[[Decorators]] field, method, accessor, getter, setter a List of function objects or empty The decorators applied to the class element, if any.
[[GetDecorators]] accessor a List of function objects or empty The decorators applied only to the getter of a grouped accessor, if any.
[[SetDecorators]] accessor a List of function objects or empty The decorators applied only to the setter of a grouped accessor, if any.
[[Initializers]] field and accessor a List of function objects The initializers of the field or accessor, if any.

2 ECMAScript Language: Expressions

2.1 Primary Expression

2.1.1 Object Initializer

Note 1

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] MethodDefinition[?Yield, ?Await] AccessorGroupDefinition[?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] AccessorGroupDefinition[Yield, Await] : accessor PropertyName[?Yield, ?Await] AccessorGroup[?Yield, ?Await, ~Class] Note 2

MethodDefinition is defined in 15.4.

Note 3

In certain contexts, ObjectLiteral is used as a cover grammar for a more restricted secondary grammar. The CoverInitializedName production is necessary to fully cover these secondary grammars. However, use of this production results in an early Syntax Error in normal contexts where an actual ObjectLiteral is expected.

2.1.1.1 Runtime Semantics: PropertyDefinitionEvaluation

The syntax-directed operation PropertyDefinitionEvaluation takes argument object and returns either a normal completion containing unused or an abrupt completion. It is defined piecewise over the following productions:

PropertyDefinitionList : PropertyDefinitionList , PropertyDefinition
  1. Perform ? PropertyDefinitionEvaluation of PropertyDefinitionList with argument object.
  2. Perform ? PropertyDefinitionEvaluation of PropertyDefinition with argument object.
  3. Return unused.
PropertyDefinition : ... AssignmentExpression
  1. Let exprValue be the result of evaluating AssignmentExpression.
  2. Let fromValue be ? GetValue(exprValue).
  3. Let excludedNames be a new empty List.
  4. Perform ? CopyDataProperties(object, fromValue, excludedNames).
  5. Return unused.
PropertyDefinition : IdentifierReference
  1. Let propName be StringValue of IdentifierReference.
  2. Let exprValue be the result of evaluating IdentifierReference.
  3. Let propValue be ? GetValue(exprValue).
  4. Assert: object is an ordinary, extensible object with no non-configurable properties.
  5. Perform ! CreateDataPropertyOrThrow(object, propName, propValue).
  6. Return unused.
PropertyDefinition : PropertyName : AssignmentExpression
  1. Let propKey be the result of evaluating PropertyName.
  2. ReturnIfAbrupt(propKey).
  3. If this PropertyDefinition is contained within a Script that is being evaluated for JSON.parse (see step 7 of JSON.parse), then
    1. Let isProtoSetter be false.
  4. Else if propKey is the String value "__proto__" and if IsComputedPropertyKey of PropertyName is false, then
    1. Let isProtoSetter be true.
  5. Else,
    1. Let isProtoSetter be false.
  6. If IsAnonymousFunctionDefinition(AssignmentExpression) is true and isProtoSetter is false, then
    1. Let propValue be ? NamedEvaluation of AssignmentExpression with argument propKey.
  7. Else,
    1. Let exprValueRef be the result of evaluating AssignmentExpression.
    2. Let propValue be ? GetValue(exprValueRef).
  8. If isProtoSetter is true, then
    1. If Type(propValue) is either Object or Null, then
      1. Return ! object.[[SetPrototypeOf]](propValue).
    2. Return NormalCompletion(empty).
  9. Assert: object is an ordinary, extensible object with no non-configurable properties.
  10. Perform ! CreateDataPropertyOrThrow(object, propKey, propValue).
  11. Return unused.
PropertyDefinition : MethodDefinition
  1. Let methodDefinition be ? MethodDefinitionEvaluation of MethodDefinition with argument object.
  2. Perform ? DefineMethodProperty(object, methodDefinition, true).
  3. Return unused.
AccessorGroupDefinition : accessor PropertyName AccessorGroup
  1. Let propKey be the result of evaluating PropertyName.
  2. ReturnIfAbrupt(propKey).
  3. Let accessorGroup be the ClassElementDefinition Record { [[Key]]: popKey, [[Kind]]: accessor, [[Get]]: undefined, [[Set]]: undefined, [[BackingStorageKey]]: empty, [[PrivateSetKey]]: setterPrivateName, [[Initializers]]: a new empty List, [[Decorators]] empty, [[GetDecorators]]: empty, [[SetDecorators]]: empty }.
  4. Set accessorGroup to ? AccessorGroupEvaluation of AccessorGroup with arguments object and accessorGroup.
  5. Perform ? DefineMethodProperty(object, accessorGroup, true).
  6. Return unused.

3 ECMAScript Language: Functions and Classes

3.1 Static Semantics: Method Decorators

3.1.1 ApplyDecoratorsAndDefineMethod ( homeObject, methodDefinition, extraInitializers, isStatic )

The abstract operation ApplyDecoratorsAndDefineMethod takes arguments homeObject (an Object), methodDefinition (a ClassElementDefinition Record), extraInitializers (a List of function objects), and isStatic (a Boolean) and returns either a normal completion containing unused, or an abrupt completion. It performs the following steps when called:

  1. If methodDefinition.[[Kind]] is accessor, then
    1. If methodDefinition.[[GetDecorators]] is a List, then
      1. Let getterName be methodDefinition.[[Key]].
      2. Let getter be methodDefinition.[[Get]].
      3. Let getDecorators be methodDefinition.[[GetDecorators]].
      4. Let getterDefinition be the ClassElementDefinition Record { [[Key]]: getterName, [[Kind]]: getter, [[Get]]: getter, [[Decorators]]: getDecorators }.
      5. Perform ? ApplyDecoratorsToElementDefinition(homeObject, getterDefinition, extraInitializers, isStatic).
      6. Set methodDefinition.[[Get]] to getterDefinition.[[Get]].
      7. Set methodDefinition.[[GetDecorators]] to empty.
    2. If methodDefinition.[[SetDecorators]] is a List, then
      1. If methodDefinition.[[PrivateSetKey]] is a Private Name, then
        1. Let setterName be methodDefinition.[[PrivateSetKey]].
      2. Else,
        1. Let setterName be methodDefinition.[[Key]].
      3. Let setter be methodDefinition.[[Set]].
      4. Let setterDefinition be the ClassElementDefinition Record { [[Key]]: setterName, [[Kind]]: setter, [[Set]]: setter, [[Decorators]]: setDecorators }.
      5. Perform ? ApplyDecoratorsToElementDefinition(homeObject, setterDefinition, extraInitializers, isStatic).
      6. Set methodDefinition.[[Set]] to setterDefinition.[[Set]].
      7. Set methodDefinition.[[SetDecorators]] to empty.
  2. Perform ? ApplyDecoratorsToElementDefinition(homeObject, methodDefinition, extraInitializers, isStatic).
  3. Perform ? DefineMethodProperty(homeObject, methodDefinition, isStatic).
  4. Return unused.

3.2 Class Definitions

Syntax

ClassDeclaration[Yield, Await, Default] : DecoratorList[?Yield, ?Await]opt class BindingIdentifier[?Yield, ?Await] ClassTail[?Yield, ?Await] [+Default] DecoratorList[?Yield, ?Await]opt class ClassTail[?Yield, ?Await] ClassExpression[Yield, Await] : DecoratorList[?Yield, ?Await]opt class BindingIdentifier[?Yield, ?Await]opt ClassTail[?Yield, ?Await] ClassTail[Yield, Await] : ClassHeritage[?Yield, ?Await]opt { ClassBody[?Yield, ?Await]opt } ClassHeritage[Yield, Await] : extends LeftHandSideExpression[?Yield, ?Await] ClassBody[Yield, Await] : ClassElementList[?Yield, ?Await] ClassElementList[Yield, Await] : ClassElement[?Yield, ?Await] ClassElementList[?Yield, ?Await] ClassElement[?Yield, ?Await] ClassElement[Yield, Await] : DecoratorList[?Yield, ?Await]opt MethodDefinition[?Yield, ?Await] DecoratorList[?Yield, ?Await]opt static MethodDefinition[?Yield, ?Await] DecoratorList[?Yield, ?Await]opt FieldDefinition[?Yield, ?Await] ; DecoratorList[?Yield, ?Await]opt static FieldDefinition[?Yield, ?Await] ; DecoratorList[?Yield, ?Await]opt FieldDefinition[?Yield, ?Await] DecoratorList[?Yield, ?Await]opt static FieldDefinition[?Yield, ?Await] ClassStaticBlock ; FieldDefinition[Yield, Await] : ClassElementName[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt accessor [no LineTerminator here] ClassElementName[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt ClassElementName[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt ; accessor [no LineTerminator here] ClassElementName[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt ; accessor [no LineTerminator here] ClassElementName[?Yield, ?Await] AccessorGroup[?Yield, ?Await] Initializer[+In, ?Yield, ?Await] ; accessor [no LineTerminator here] ClassElementName[?Yield, ?Await] AccessorGroup[?Yield, ?Await] ClassElementName[Yield, Await] : PropertyName[?Yield, ?Await] PrivateIdentifier AccessorGroup[Yield, Await, Class] : [+Class] { } { AccessorGroupElement[?Yield, ?Await, ?Class] AccessorGroupElement[?Yield, ?Await, ?Class]opt } AccessorGroupElement[Yield, Await, Class] : [+Class] DecoratorList[?Yield, ?Await] AccessorGroupGetMethodDefinition [+Class] DecoratorList[?Yield, ?Await] AccessorGroupSetMethodDefinition [+Class] DecoratorList[?Yield, ?Await]opt AccessorGroupPrivateSetMethodDefinition [+Class] DecoratorList[?Yield, ?Await]opt AccessorGroupGetMethodStub [+Class] DecoratorList[?Yield, ?Await]opt AccessorGroupSetMethodStub [+Class] DecoratorList[?Yield, ?Await]opt AccessorGroupPrivateSetMethodStub AccessorGroupGetMethodDefinition AccessorGroupSetMethodDefinition AccessorGroupGetMethodDefinition : get ( ) { FunctionBody[~Yield, ~Await] } AccessorGroupSetMethodDefinition : set ( PropertySetParameterList ) { FunctionBody[~Yield, ~Await] } AccessorGroupPrivateSetMethodDefinition : #set ( PropertySetParameterList ) { FunctionBody[~Yield, ~Await] } AccessorGroupGetMethodStub : get ; AccessorGroupSetMethodStub : set ; AccessorGroupPrivateSetMethodStub : #set ; ClassStaticBlock : static { ClassStaticBlockBody } ClassStaticBlockBody : ClassStaticBlockStatementList ClassStaticBlockStatementList : StatementList[~Yield, +Await, ~Return]opt Note

A class definition is always strict mode code.

3.2.1 Static Semantics: Early Errors

FieldDefinition : accessor ClassElementName AccessorGroup Initializer ; FieldDefinition : accessor ClassElementName AccessorGroup AccessorGroup : { AccessorGroupElement AccessorGroupElement }

3.2.2 Static Semantics: PrivateBoundIdentifiers

The syntax-directed operation PrivateBoundIdentifiers takes no arguments and returns a List of Strings. It is defined piecewise over the following productions:

FieldDefinition : ClassElementName Initializeropt
  1. Return PrivateBoundIdentifiers of ClassElementName.
FieldDefinition : ClassElementName AccessorGroup Initializer ; ClassElementName AccessorGroup
  1. If ContainsAccessorGroupPrivateMethod of AccessorGroup is true, then
    1. Let name be PropName of ClassElementName.
    2. Assert: Type(name) is String.
    3. Let privateIdentifier to be the string-concatenation of 0x0023 (NUMBER SIGN) and name.
    4. Return a List whose sole element is privateIdentifier.
  2. Else,
    1. Return PrivateBoundIdentifiers of ClassElementName.
ClassElement : DecoratorListopt MethodDefinition DecoratorListopt static MethodDefinition
  1. Return PrivateBoundIdentifiers of MethodDefinition.
ClassElement : DecoratorListopt FieldDefinition DecoratorListopt static FieldDefinition
  1. Return PrivateBoundIdentifiers of FieldDefinition.
ClassElementName : PrivateIdentifier
  1. Return a List whose sole element is the StringValue of PrivateIdentifier.
ClassElementName : PropertyName ClassElement : ClassStaticBlock ;
  1. Return a new empty List.
ClassElementList : ClassElementList ClassElement
  1. Let names1 be PrivateBoundIdentifiers of ClassElementList.
  2. Let names2 be PrivateBoundIdentifiers of ClassElement.
  3. Return the list-concatenation of names1 and names2.
MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody } get ClassElementName ( ) { FunctionBody } set ClassElementName ( PropertySetParameterList ) { FunctionBody } GeneratorMethod : * ClassElementName ( UniqueFormalParameters ) { GeneratorBody } AsyncMethod : async ClassElementName ( UniqueFormalParameters ) { AsyncFunctionBody } AsyncGeneratorMethod : async * ClassElementName ( UniqueFormalParameters ) { AsyncGeneratorBody }
  1. Return PrivateBoundIdentifiers of ClassElementName.

3.2.3 Static Semantics: ContainsNonIdentifierName

The syntax-directed operation ContainsNonIdentifierName takes no arguments and returns a Boolean. It is defined piecewise over the following productions:

ClassElementName : PrivateIdentifier PropertyName : ComputedPropertyName LiteralPropertyName : StringLiteral LiteralPropertyName : NumericLiteral
  1. Return true.
LiteralPropertyName : IdentifierName
  1. Return false.
Note
DRAFT NOTE: Used to verify an AccessorGroup containing #set is only used with a ClassElementName that is an IdentifierName.

3.2.4 Static Semantics: ContainsAccessorGroupMethodDefinition

The syntax-directed operation ContainsAccessorGroupMethodDefinition takes no arguments and returns a Boolean. It is defined piecewise over the following productions:

AccessorGroup : { }
  1. Return false.
AccessorGroup : { AccessorGroupElement }
  1. Return ContainsAccessorGroupMethodDefinition of AccessorGroupElement.
AccessorGroup : { AccessorGroupElement AccessorGroupElement }
  1. Let result be ContainsAccessorGroupMethodDefinition of the first AccessorGroupElement.
  2. If result is true, return true.
  3. Return ContainsAccessorGroupMethodDefinition of the second AccessorGroupElement.
AccessorGroupElement : DecoratorList AccessorGroupGetMethodDefinition DecoratorList AccessorGroupSetMethodDefinition DecoratorListopt AccessorGroupPrivateSetMethodDefinition AccessorGroupGetMethodDefinition AccessorGroupSetMethodDefinition
  1. Return true.
AccessorGroupElement : DecoratorListopt AccessorGroupGetMethodStub DecoratorListopt AccessorGroupSetMethodStub DecoratorListopt AccessorGroupPrivateSetMethodStub
  1. Return false.
Note
DRAFT NOTE: Used to determine whether an AccessorGroup contains any method definitions (i.e., AccessorGroupGetMethodDefinition, AccessorGroupSetMethodDefinition, AccessorGroupPrivateSetMethodDefinition).

3.2.5 Static Semantics: ContainsAccessorGroupGetMethod

The syntax-directed operation ContainsAccessorGroupGetMethod takes no arguments and returns a Boolean. It is defined piecewise over the following productions:

AccessorGroupElement : DecoratorList AccessorGroupGetMethodDefinition DecoratorListopt AccessorGroupGetMethodStub AccessorGroupGetMethodDefinition
  1. Return true.
AccessorGroupElement : DecoratorList AccessorGroupSetMethodDefinition DecoratorListopt AccessorGroupSetMethodStub DecoratorListopt AccessorGroupPrivateSetMethodDefinition DecoratorListopt AccessorGroupPrivateSetMethodStub AccessorGroupSetMethodDefinition
  1. Return false.
Note
DRAFT NOTE: Used to determine whether an AccessorGroup contains a getter (i.e., AccessorGroupGetMethodDefinition or AccessorGroupGetMethodStub).

3.2.6 Static Semantics: ContainsAccessorGroupSetMethod

The syntax-directed operation ContainsAccessorGroupSetMethod takes no arguments and returns a Boolean. It is defined piecewise over the following productions:

AccessorGroupElement : DecoratorList AccessorGroupGetMethodDefinition DecoratorListopt AccessorGroupGetMethodStub AccessorGroupGetMethodDefinition
  1. Return false.
AccessorGroupElement : DecoratorList AccessorGroupSetMethodDefinition DecoratorListopt AccessorGroupSetMethodStub DecoratorListopt AccessorGroupPrivateSetMethodDefinition DecoratorListopt AccessorGroupPrivateSetMethodStub AccessorGroupSetMethodDefinition
  1. Return true.
Note

3.2.7 Static Semantics: ContainsAccessorGroupPrivateMethod

The syntax-directed operation ContainsAccessorGroupPrivateMethod takes no arguments and returns a Boolean. It is defined piecewise over the following productions:

AccessorGroup : { }
  1. Return false.
AccessorGroup : { AccessorGroupElement }
  1. Return ContainsAccessorGroupPrivateMethod of AccessorGroupElement.
AccessorGroup : { AccessorGroupElement AccessorGroupElement }
  1. Let result be ContainsAccessorGroupPrivateMethod of the first AccessorGroupElement.
  2. If result is true, return true.
  3. Return ContainsAccessorGroupPrivateMethod of the second AccessorGroupElement.
AccessorGroupElement : DecoratorList AccessorGroupGetMethodDefinition DecoratorList AccessorGroupSetMethodDefinition DecoratorListopt AccessorGroupGetMethodStub DecoratorListopt AccessorGroupSetMethodStub AccessorGroupGetMethodDefinition AccessorGroupSetMethodDefinition
  1. Return false.
AccessorGroupElement : DecoratorListopt AccessorGroupPrivateSetMethodDefinition DecoratorListopt AccessorGroupPrivateSetMethodStub
  1. Return true.
Note
DRAFT NOTE: Used to determine whether an AccessorGroup contains a private method (i.e., AccessorGroupPrivateSetMethodDefinition or AccessorGroupPrivateSetMethodStub).

3.2.8 Static Semantics: ContainsAccessorGroupMethodStub

The syntax-directed operation ContainsAccessorGroupMethodStub takes no arguments and returns a Boolean. It is defined piecewise over the following productions:

AccessorGroupElement : DecoratorList AccessorGroupGetMethodDefinition DecoratorList AccessorGroupSetMethodDefinition DecoratorListopt AccessorGroupPrivateSetMethodDefinition AccessorGroupGetMethodDefinition AccessorGroupSetMethodDefinition
  1. Return false.
AccessorGroupElement : DecoratorListopt AccessorGroupGetMethodStub DecoratorListopt AccessorGroupSetMethodStub DecoratorListopt AccessorGroupPrivateSetMethodStub
  1. Return true.
Note
DRAFT NOTE: Used to determine whether an AccessorGroup contains any method stubs (i.e., AccessorGroupGetMethodStub, AccessorGroupSetMethodStub, or AccessorGroupPrivateSetMethodStub).

3.2.9 Static Semantics: IsAutoAccessor

The syntax-directed operation IsAutoAccessor takes no arguments and returns a Boolean. It is defined piecewise over the following productions:

AccessorGroup : { }
  1. Return true.
AccessorGroup : { AccessorGroupElement }
  1. Return ContainsAccessorGroupMethodStub of AccessorGroupElement.
AccessorGroup : { AccessorGroupElement AccessorGroupElement }
  1. Let result be ContainsAccessorGroupMethodStub of the first AccessorGroupElement.
  2. If result is true, return true.
  3. Return ContainsAccessorGroupMethodStub of the second AccessorGroupElement.

3.2.10 Runtime Semantics: ClassFieldDefinitionEvaluation

The syntax-directed operation ClassFieldDefinitionEvaluation takes argument homeObject and returns either a normal completion containing a ClassElementDefinition Record or an abrupt completion. It is defined piecewise over the following productions:

FieldDefinition : accessor ClassElementName Initializeropt FieldDefinition : accessor ClassElementName Initializeropt ;
  1. Let name be the result of evaluating ClassElementName.
  2. ReturnIfAbrupt(name).
  3. Let privateStateDesc be the string-concatenation of name and " accessor storage".
  4. Let privateStateName be a new Private Name whose [[Description]] value is privateStateDesc.
  5. Let getter be MakeAutoAccessorGetter(homeObject, name, privateStateName).
  6. Let setter be MakeAutoAccessorSetter(homeObject, name, privateStateName).
  7. Let initializer be a new empty List.
  8. If Initializeropt is present, then
    1. Let initializer be CreateFieldInitializerFunction(homeObject, name, Initializer).
    2. Append initializer to initializers.
  9. If name is not a Private Name, then
    1. Let desc be the PropertyDescriptor { [[Get]]: getter, [[Set]]: setter, [[Enumerable]]: true, [[Configurable]]: true }.
    2. Perform ? DefinePropertyOrThrow(homeObject, name, desc).
  10. Return ClassElementDefinition Record { [[Key]]: name, [[Kind]]: accessor, [[Get]]: getter, [[Set]]: setter, [[BackingStorageKey]]: privateStateName, [[PrivateSetKey]]: empty, [[Initializers]]: initializers, [[Decorators]]: empty, [[GetDecorators]]: empty, [[SetDecorators]]: empty }.
FieldDefinition : accessor ClassElementName AccessorGroup Initializer ;
  1. Let name be the result of evaluating ClassElementName.
  2. ReturnIfAbrupt(name).
  3. Let privateStateDesc be the string-concatenation of name and " accessor storage".
  4. Let privateStateName be a new Private Name whose [[Description]] value is privateStateDesc.
  5. If ContainsAccessorGroupPrivateMethod of AccessorGroup is true, then
    1. Assert: Type(name) is String.
    2. Let setterPrivateIdentifier be the string-concatenation of 0x0023 (NUMBER SIGN) and name.
    3. Let privateEnvRec be the running execution context's PrivateEnvironment.
    4. Let names be privateEnvRec.[[Names]].
    5. Assert: Exactly one element of names is a Private Name whose [[Description]] is setterPrivateIdentifier.
    6. Let setterPrivateName be the Private Name in names whose [[Description]] is setterPrivateIdentifier.
  6. Else,
    1. Let setterPrivateName be empty.
  7. Let accessorGroup be the ClassElementDefinition Record { [[Key]]: name, [[Kind]]: accessor, [[Get]]: undefined, [[Set]]: undefined, [[BackingStorageKey]]: privateStateName, [[PrivateSetKey]]: setterPrivateName, [[Initializers]]: a new empty List, [[Decorators]] empty, [[GetDecorators]]: empty, [[SetDecorators]]: empty }.
  8. Set accessorGroup to ? AccessorGroupEvaluation of AccessorGroup with arguments homeObject and accessorGroup.
  9. Let initializer be CreateFieldInitializerFunction(homeObject, name, Initializer).
  10. Append initializer to accessorGroup.[[Initializers]].
  11. Return accessorGroup.
FieldDefinition : accessor ClassElementName AccessorGroup
  1. Let name be the result of evaluating ClassElementName.
  2. ReturnIfAbrupt(name).
  3. If IsAutoAccessor of AccessorGroup is true, then
    1. Let privateStateDesc be the string-concatenation of name and " accessor storage".
    2. Let privateStateName be a new Private Name whose [[Description]] value is privateStateDesc.
  4. Else,
    1. Let privateStateName be empty.
  5. If ContainsAccessorGroupPrivateMethod of AccessorGroup is true, then
    1. Assert: Type(name) is String.
    2. Let setterPrivateIdentifier be the string-concatenation of 0x0023 (NUMBER SIGN) and name.
    3. Let privateEnvRec be the running execution context's PrivateEnvironment.
    4. Let names be privateEnvRec.[[Names]].
    5. Assert: Exactly one element of names is a Private Name whose [[Description]] is setterPrivateIdentifier.
    6. Let setterPrivateName be the Private Name in names whose [[Description]] is setterPrivateIdentifier.
  6. Else,
    1. Let setterPrivateName be empty.
  7. Let accessorGroup be the ClassElementDefinition Record { [[Key]]: name, [[Kind]]: accessor, [[Get]]: undefined, [[Set]]: undefined, [[BackingStorageKey]]: privateStateName, [[PrivateSetKey]]: setterPrivateName, [[Initializers]]: a new empty List, [[Decorators]] empty, [[GetDecorators]]: empty, [[SetDecorators]]: empty }.
  8. Set accessorGroup to ? AccessorGroupEvaluation of AccessorGroup with arguments homeObject and accessorGroup.
  9. Return accessorGroup.

3.2.11 Runtime Semantics: AccessorGroupEvaluation

The syntax-directed operation AccessorGroupEvaluation takes arguments homeObject and accessorGroup (a ClassElementDefinition Record) and returns either a normal completion containing a ClassElementDefinition Record or an abrupt completion. It is defined piecewise over the following productions:

AccessorGroup : { }
  1. Assert: accessorGroup.[[BackingStorageKey]] is a Private Name.
  2. Assert: accessorGroup.[[PrivateSetKey]] is empty.
  3. Assert: accessorGroup.[[Get]] is undefined.
  4. Assert: accessorGroup.[[Set]] is undefined.
  5. Let name be accessorGroup.[[Key]].
  6. Let privateStateName be accessorGroup.[[BackingStorageKey]].
  7. Let getter be MakeAutoAccessorGetter(homeObject, name, privateStateName).
  8. Let setter be MakeAutoAccessorSetter(homeObject, name, privateStateName).
  9. Set accessorGroup.[[Get]] to getter.
  10. Set accessorGroup.[[Set]] to setter.
  11. Return accessorGroup.
AccessorGroup : { AccessorGroupElement }
  1. Return ? AccessorGroupEvaluation of AccessorGroupElement with arguments homeObject and accessorGroup.
AccessorGroup : { AccessorGroupElement AccessorGroupElement }
  1. Set accessorGroup to ? AccessorGroupEvaluation of the first AccessorGroupElement with arguments homeObject and accessorGroup.
  2. Return ? AccessorGroupEvaluation of the second AccessorGroupElement with arguments homeObject and accessorGroup.
AccessorGroupElement : DecoratorList AccessorGroupGetMethodDefinition
  1. If DecoratorListopt is present, let decorators be ? DecoratorListEvaluation of DecoratorList.
  2. Else, let decorators be a new empty List.
  3. Set accessorGroup to ? AccessorGroupEvaluation of AccessorGroupGetMethodDefinition with arguments homeObject and accessorGroup.
  4. Set accessorGroup.[[GetDecorators]] to decorators.
  5. Return accessorGroup.
AccessorGroupElement : AccessorGroupGetMethodDefinition
  1. Return ? AccessorGroupEvaluation of AccessorGroupGetMethodDefinition with arguments homeObject and accessorGroup.
AccessorGroupElement : DecoratorListopt AccessorGroupGetMethodStub
  1. If DecoratorListopt is present, let decorators be ? DecoratorListEvaluation of DecoratorList.
  2. Else, let decorators be a new empty List.
  3. Set accessorGroup to ? AccessorGroupEvaluation of AccessorGroupGetMethodStub with arguments homeObject and accessorGroup.
  4. Set accessorGroup.[[GetDecorators]] to decorators.
  5. Return accessorGroup.
AccessorGroupElement : DecoratorList AccessorGroupSetMethodDefinition
  1. If DecoratorListopt is present, let decorators be ? DecoratorListEvaluation of DecoratorList.
  2. Else, let decorators be a new empty List.
  3. Set accessorGroup to ? AccessorGroupEvaluation of AccessorGroupSetMethodDefinition with arguments homeObject and accessorGroup.
  4. Set accessorGroup.[[SetDecorators]] to decorators.
  5. Return accessorGroup.
AccessorGroupElement : AccessorGroupSetMethodDefinition
  1. Return AccessorGroupEvaluation of AccessorGroupSetMethodDefinition with arguments homeObject and accessorGroup.
AccessorGroupElement : DecoratorListopt AccessorGroupSetMethodStub
  1. If DecoratorListopt is present, let decorators be ? DecoratorListEvaluation of DecoratorList.
  2. Else, let decorators be a new empty List.
  3. Set accessorGroup to ? AccessorGroupEvaluation of AccessorGroupSetMethodStub with arguments homeObject and accessorGroup.
  4. Set accessorGroup.[[SetDecorators]] to decorators.
  5. Return accessorGroup.
AccessorGroupElement : DecoratorListopt AccessorGroupPrivateSetMethodDefinition
  1. If DecoratorListopt is present, let decorators be ? DecoratorListEvaluation of DecoratorList.
  2. Else, let decorators be a new empty List.
  3. Set accessorGroup to ? AccessorGroupEvaluation of AccessorGroupPrivateSetMethodDefinition with arguments homeObject and accessorGroup.
  4. Set accessorGroup.[[SetDecorators]] to decorators.
  5. Return accessorGroup.
AccessorGroupElement : DecoratorListopt AccessorGroupPrivateSetMethodStub
  1. If DecoratorListopt is present, let decorators be ? DecoratorListEvaluation of DecoratorList.
  2. Else, let decorators be a new empty List.
  3. Set accessorGroup to ? AccessorGroupEvaluation of AccessorGroupPrivateSetMethodStub with arguments homeObject and accessorGroup.
  4. Set accessorGroup.[[SetDecorators]] to decorators.
  5. Return accessorGroup.
AccessorGroupGetMethodDefinition : get ( ) { FunctionBody }
  1. Assert: accessorGroup.[[BackingStorageKey]] is empty.
  2. Assert: accessorGroup.[[Get]] is undefined.
  3. Let name be accessorGroup.[[Key]].
  4. Let env be the running execution context's LexicalEnvironment.
  5. Let privateEnv be the running execution context's PrivateEnvironment.
  6. Let sourceText be the source text matched by GetAccessorMethodDefinition.
  7. Let formalParameterList be an instance of the production FormalParameters : [empty]
  8. Let closure be OrdinaryFunctionCreate(%Function.prototype%, sourceText, formalParameterList, FunctionBody, non-lexical-this, env, privateEnv).
  9. Perform MakeMethod(closure, homeObject).
  10. Perform SetFunctionName(closure, privateName, "get").
  11. Set accessorGroup.[[Get]] to closure.
  12. Return accessorGroup.
AccessorGroupSetMethodDefinition : set ( PropertySetParameterList ) { FunctionBody }
  1. Assert: accessorGroup.[[BackingStorageKey]] is empty.
  2. Assert: accessorGroup.[[PrivateSetKey]] is empty.
  3. Assert: accessorGroup.[[Set]] is undefined.
  4. Let name be accessorGroup.[[Key]].
  5. Let env be the running execution context's LexicalEnvironment.
  6. Let privateEnv be the running execution context's PrivateEnvironment.
  7. Let sourceText be the source text matched by SetAccessorMethodDefinition.
  8. Let closure be OrdinaryFunctionCreate(%Function.prototype%, sourceText, PropertySetParameterList, FunctionBody, non-lexical-this, env, privateEnv).
  9. Perform MakeMethod(closure, homeObject).
  10. Perform SetFunctionName(closure, privateName, "set").
  11. Set accessorGroup.[[Set]] to closure.
  12. Return accessorGroup.
AccessorGroupPrivateSetMethodDefinition : #set ( PropertySetParameterList ) { FunctionBody }
  1. Assert: accessorGroup.[[BackingStorageKey]] is empty.
  2. Assert: accessorGroup.[[PrivateSetKey]] is a Private Name.
  3. Assert: accessorGroup.[[Set]] is undefined.
  4. Let name be accessorGroup.[[PrivateSetKey]].
  5. Let env be the running execution context's LexicalEnvironment.
  6. Let privateEnv be the running execution context's PrivateEnvironment.
  7. Let sourceText be the source text matched by PrivateSetAccessorMethodDefinition.
  8. Let closure be OrdinaryFunctionCreate(%Function.prototype%, sourceText, PropertySetParameterList, FunctionBody, non-lexical-this, env, privateEnv).
  9. Perform MakeMethod(closure, homeObject).
  10. Perform SetFunctionName(closure, name, "set").
  11. Set accessorGroup.[[Set]] to closure.
  12. Return accessorGroup.
AccessorGroupGetMethodStub : get ;
  1. Assert: accessorGroup.[[BackingStorageKey]] is a Private Name.
  2. Assert: accessorGroup.[[Get]] is undefined.
  3. Let name be accessorGroup.[[Key]].
  4. Let privateStateName be accessorGroup.[[BackingStorageKey]].
  5. Let closure be MakeAutoAccessorGetter(homeObject, name, privateStateName).
  6. Set accessorGroup.[[Get]] to closure.
  7. Return accessorGroup.
AccessorGroupSetMethodStub : set ;
  1. Assert: accessorGroup.[[BackingStorageKey]] is a Private Name.
  2. Assert: accessorGroup.[[PrivateSetKey]] is empty.
  3. Assert: accessorGroup.[[Set]] is undefined.
  4. Let name be accessorGroup.[[Key]].
  5. Let privateStateName be accessorGroup.[[BackingStorageKey]].
  6. Let closure be MakeAutoAccessorSetter(homeObject, name, privateStateName).
  7. Set accessorGroup.[[Set]] to closure.
  8. Return accessorGroup.
AccessorGroupPrivateSetMethodStub : #set ;
  1. Assert: accessorGroup.[[BackingStorageKey]] is a Private Name.
  2. Assert: accessorGroup.[[PrivateSetKey]] is a Private Name.
  3. Assert: accessorGroup.[[Set]] is undefined.
  4. Let name be accessorGroup.[[PrivateSetKey]].
  5. Let closure be MakeAutoAccessorSetter(homeObject, name, privateStateName).
  6. Set accessorGroup.[[Set]] to closure.
  7. Return accessorGroup.

A Copyright & Software License

Copyright Notice

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