@@ -1529,8 +1529,9 @@ export default class StatementParser extends ExpressionParser {
15291529 ) {
15301530 const publicMethod : $FlowSubtype < N . ClassMethod > = member;
15311531 const privateMethod: $FlowSubtype< N . ClassPrivateMethod > = member;
1532- const publicProp: $FlowSubtype< N . ClassMethod > = member;
1533- const privateProp: $FlowSubtype< N . ClassPrivateMethod > = member;
1532+ const publicProp: $FlowSubtype< N . ClassProperty > = member;
1533+ const privateProp: $FlowSubtype< N . ClassPrivateProperty > = member;
1534+ const accessorProp: $FlowSubtype< N . ClassAccessorProperty > = member;
15341535
15351536 const method: typeof publicMethod | typeof privateMethod = publicMethod;
15361537 const publicMember: typeof publicMethod | typeof publicProp = publicMethod;
@@ -1687,6 +1688,18 @@ export default class StatementParser extends ExpressionParser {
16871688 }
16881689
16891690 this . checkGetterSetterParams ( publicMethod ) ;
1691+ } else if (
1692+ isContextual &&
1693+ key . name === "accessor" &&
1694+ ! this . isLineTerminator ( )
1695+ ) {
1696+ this . expectPlugin ( "decoratorAutoAccessors" ) ;
1697+ this . resetPreviousNodeTrailingComments ( key ) ;
1698+
1699+ // The so-called parsed name would have been "accessor": get the real name.
1700+ const isPrivate = this . match ( tt . privateName ) ;
1701+ this . parseClassElementName ( publicProp ) ;
1702+ this . pushClassAccessorProperty ( classBody , accessorProp , isPrivate ) ;
16901703 } else if ( this . isLineTerminator ( ) ) {
16911704 // an uninitialized class property (due to ASI, since we don't otherwise recognize the next token)
16921705 if ( isPrivate ) {
@@ -1774,6 +1787,34 @@ export default class StatementParser extends ExpressionParser {
17741787 ) ;
17751788 }
17761789
1790+ pushClassAccessorProperty (
1791+ classBody : N . ClassBody ,
1792+ prop : N . ClassAccessorProperty ,
1793+ isPrivate : boolean ,
1794+ ) {
1795+ if ( ! isPrivate && ! prop . computed ) {
1796+ // Not private, so not node is not a PrivateName and we can safely cast
1797+ const key = ( prop . key : N . Expression ) ;
1798+
1799+ if ( key . name === "constructor" || key . value === "constructor" ) {
1800+ // Non-computed field, which is either an identifier named "constructor"
1801+ // or a string literal named "constructor"
1802+ this . raise ( Errors . ConstructorClassField , { node : key } ) ;
1803+ }
1804+ }
1805+
1806+ const node = this . parseClassAccessorProperty ( prop ) ;
1807+ classBody . body . push ( node ) ;
1808+
1809+ if ( isPrivate ) {
1810+ this . classScope . declarePrivateName (
1811+ this . getPrivateNameSV ( node . key ) ,
1812+ CLASS_ELEMENT_OTHER ,
1813+ node . key . loc . start ,
1814+ ) ;
1815+ }
1816+ }
1817+
17771818 pushClassMethod (
17781819 classBody : N . ClassBody ,
17791820 method : N . ClassMethod ,
@@ -1858,8 +1899,18 @@ export default class StatementParser extends ExpressionParser {
18581899 return this . finishNode ( node , "ClassProperty" ) ;
18591900 }
18601901
1902+ parseClassAccessorProperty (
1903+ node : N . ClassAccessorProperty ,
1904+ ) : N . ClassAccessorProperty {
1905+ this . parseInitializer ( node ) ;
1906+ this . semicolon ( ) ;
1907+ return this . finishNode ( node , "ClassAccessorProperty" ) ;
1908+ }
1909+
18611910 // https://tc39.es/ecma262/#prod-Initializer
1862- parseInitializer ( node : N . ClassProperty | N . ClassPrivateProperty ) : void {
1911+ parseInitializer (
1912+ node : N . ClassProperty | N . ClassPrivateProperty | N . ClassAccessorProperty ,
1913+ ) : void {
18631914 this . scope . enter ( SCOPE_CLASS | SCOPE_SUPER ) ;
18641915 this . expressionScope . enter ( newExpressionScope ( ) ) ;
18651916 this . prodParam . enter ( PARAM ) ;
0 commit comments