From 09dfd6a2a5048f66f9a56b886f6423adaae0179d Mon Sep 17 00:00:00 2001 From: Chris Hewell Garrett Date: Mon, 16 Aug 2021 11:23:50 -0400 Subject: [PATCH] Adds the `simpleAutoAccessors` parser plugin This is the first part of the implementation of the latest version of the decorators proposal: https://github.com/tc39/proposal-decorators The keyword is outlined here in the README: https://github.com/tc39/proposal-decorators#class-auto-accessors It adds a `simpleAutoAccessors` plugin which can be used to parse the `accessor` keyword into ClassAccessorProperty and ClassPrivateAccessorProperty node types. --- packages/babel-compat-data/data/plugins.json | 2 +- .../babel-generator/src/generators/classes.ts | 65 +++++++++++++ packages/babel-parser/ast/spec.md | 23 +++++ packages/babel-parser/src/parser/statement.js | 79 +++++++++++++++- packages/babel-parser/src/types.js | 35 ++++++- .../accessor-named-constructor/input.js | 3 + .../accessor-named-constructor/output.json | 44 +++++++++ .../basic-accessor-with-newline/input.js | 4 + .../basic-accessor-with-newline/output.json | 53 +++++++++++ .../basic-accessor/input.js | 3 + .../basic-accessor/output.json | 41 +++++++++ .../input.js | 3 + .../output.json | 45 +++++++++ .../computed-accessor-with-newline/input.js | 4 + .../output.json | 57 ++++++++++++ .../computed-accessor/input.js | 3 + .../computed-accessor/output.json | 45 +++++++++ .../computed-static-accesor/input.js | 3 + .../computed-static-accesor/output.json | 45 +++++++++ .../field-named-accessor/input.js | 3 + .../field-named-accessor/output.json | 49 ++++++++++ .../input.js | 3 + .../output.json | 56 +++++++++++ .../invalid-static-keyword-order/input.js | 3 + .../invalid-static-keyword-order/output.json | 56 +++++++++++ .../method-named-accessor/input.js | 3 + .../method-named-accessor/output.json | 51 ++++++++++ .../not-allowed-on-methods/input.js | 5 + .../not-allowed-on-methods/options.json | 3 + .../simple-auto-accessors/options.json | 5 + .../private-accessor/input.js | 3 + .../private-accessor/output.json | 45 +++++++++ .../private-static-accessor/input.js | 3 + .../private-static-accessor/output.json | 45 +++++++++ .../static-accessor-with-newline/input.js | 4 + .../static-accessor-with-newline/output.json | 53 +++++++++++ .../static-accessor/input.js | 3 + .../static-accessor/output.json | 41 +++++++++ .../src/path/generated/asserts.ts | 6 ++ .../src/path/generated/validators.ts | 6 ++ .../src/asserts/generated/index.ts | 12 +++ .../src/ast-types/generated/index.ts | 46 +++++++++- .../src/builders/generated/index.ts | 18 ++++ .../src/builders/generated/uppercase.js | 2 + .../src/converters/toComputedKey.ts | 1 + packages/babel-types/src/definitions/core.ts | 92 +++++++++++++++++++ .../src/validators/generated/index.ts | 39 +++++++- .../src/validators/isReferenced.ts | 2 + 48 files changed, 1207 insertions(+), 8 deletions(-) create mode 100644 packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/accessor-named-constructor/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/accessor-named-constructor/output.json create mode 100644 packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/basic-accessor-with-newline/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/basic-accessor-with-newline/output.json create mode 100644 packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/basic-accessor/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/basic-accessor/output.json create mode 100644 packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/computed-accessor-named-constructor/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/computed-accessor-named-constructor/output.json create mode 100644 packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/computed-accessor-with-newline/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/computed-accessor-with-newline/output.json create mode 100644 packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/computed-accessor/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/computed-accessor/output.json create mode 100644 packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/computed-static-accesor/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/computed-static-accesor/output.json create mode 100644 packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/field-named-accessor/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/field-named-accessor/output.json create mode 100644 packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/invalid-static-keyword-order-newline/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/invalid-static-keyword-order-newline/output.json create mode 100644 packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/invalid-static-keyword-order/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/invalid-static-keyword-order/output.json create mode 100644 packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/method-named-accessor/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/method-named-accessor/output.json create mode 100644 packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/not-allowed-on-methods/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/not-allowed-on-methods/options.json create mode 100644 packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/options.json create mode 100644 packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/private-accessor/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/private-accessor/output.json create mode 100644 packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/private-static-accessor/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/private-static-accessor/output.json create mode 100644 packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/static-accessor-with-newline/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/static-accessor-with-newline/output.json create mode 100644 packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/static-accessor/input.js create mode 100644 packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/static-accessor/output.json diff --git a/packages/babel-compat-data/data/plugins.json b/packages/babel-compat-data/data/plugins.json index 13b40a3abf67..e2cbef0129d9 100644 --- a/packages/babel-compat-data/data/plugins.json +++ b/packages/babel-compat-data/data/plugins.json @@ -379,7 +379,7 @@ "chrome": "46", "opera": "33", "edge": "14", - "firefox": "45", + "firefox": "41", "safari": "10", "node": "5", "ios": "10", diff --git a/packages/babel-generator/src/generators/classes.ts b/packages/babel-generator/src/generators/classes.ts index d909d5afb941..e1f34dbc3544 100644 --- a/packages/babel-generator/src/generators/classes.ts +++ b/packages/babel-generator/src/generators/classes.ts @@ -114,6 +114,48 @@ export function ClassProperty(this: Printer, node: t.ClassProperty) { this.semicolon(); } +export function ClassAccessorProperty( + this: Printer, + node: t.ClassAccessorProperty, +) { + this.printJoin(node.decorators, node); + + // catch up to property key, avoid line break + // between member modifiers and the property key. + this.source("end", node.key.loc); + + this.tsPrintClassMemberModifiers(node, /* isField */ true); + + this.word("accessor"); + this.space(); + + if (node.computed) { + this.token("["); + this.print(node.key, node); + this.token("]"); + } else { + this._variance(node); + this.print(node.key, node); + } + + // TS + if (node.optional) { + this.token("?"); + } + if (node.definite) { + this.token("!"); + } + + this.print(node.typeAnnotation, node); + if (node.value) { + this.space(); + this.token("="); + this.space(); + this.print(node.value, node); + } + this.semicolon(); +} + export function ClassPrivateProperty( this: Printer, node: t.ClassPrivateProperty, @@ -134,6 +176,29 @@ export function ClassPrivateProperty( this.semicolon(); } +export function ClassPrivateAccessorProperty( + this: Printer, + node: t.ClassPrivateAccessorProperty, +) { + this.printJoin(node.decorators, node); + if (node.static) { + this.word("static"); + this.space(); + } + this.word("accessor"); + this.space(); + + this.print(node.key, node); + this.print(node.typeAnnotation, node); + if (node.value) { + this.space(); + this.token("="); + this.space(); + this.print(node.value, node); + } + this.semicolon(); +} + export function ClassMethod(this: Printer, node: t.ClassMethod) { this._classMethodHead(node); this.space(); diff --git a/packages/babel-parser/ast/spec.md b/packages/babel-parser/ast/spec.md index 8205526f5ec6..92d974d7faf1 100644 --- a/packages/babel-parser/ast/spec.md +++ b/packages/babel-parser/ast/spec.md @@ -1213,6 +1213,29 @@ interface ClassPrivateProperty <: Node { } ``` +## ClassAccessorProperty + +```js +interface ClassAccessorProperty <: Node { + type: "ClassAccessorProperty"; + key: Expression; + value: Expression; + static: boolean; + computed: boolean; +} +``` + +## ClassPrivateAccessorProperty + +```js +interface ClassPrivateAccessorProperty <: Node { + type: "ClassPrivateAccessorProperty"; + key: PrivateName; + value: Expression; + static: boolean; +} +``` + ## StaticBlock ```js diff --git a/packages/babel-parser/src/parser/statement.js b/packages/babel-parser/src/parser/statement.js index 2b529897d05c..69da5c9eb78b 100644 --- a/packages/babel-parser/src/parser/statement.js +++ b/packages/babel-parser/src/parser/statement.js @@ -1393,6 +1393,7 @@ export default class StatementParser extends ExpressionParser { prop.computed = false; prop.key = key; prop.static = false; + classBody.body.push(this.parseClassProperty(prop)); return true; } @@ -1429,8 +1430,11 @@ export default class StatementParser extends ExpressionParser { ) { const publicMethod: $FlowSubtype = member; const privateMethod: $FlowSubtype = member; - const publicProp: $FlowSubtype = member; - const privateProp: $FlowSubtype = member; + const publicProp: $FlowSubtype = member; + const privateProp: $FlowSubtype = member; + const publicAccessorProp: $FlowSubtype = member; + const privateAccessorProp: $FlowSubtype = + member; const method: typeof publicMethod | typeof privateMethod = publicMethod; const publicMember: typeof publicMethod | typeof publicProp = publicMethod; @@ -1583,6 +1587,23 @@ export default class StatementParser extends ExpressionParser { } this.checkGetterSetterParams(publicMethod); + } else if ( + isContextual && + key.name === "accessor" && + this.hasPlugin("simpleAutoAccessors") && + !this.isLineTerminator() + ) { + this.resetPreviousNodeTrailingComments(key); + + // The so-called parsed name would have been "accessor": get the real name. + const isPrivate = this.match(tt.privateName); + this.parseClassElementName(publicProp); + + if (isPrivate) { + this.pushClassPrivateAccessorProperty(classBody, privateAccessorProp); + } else { + this.pushClassAccessorProperty(classBody, publicAccessorProp); + } } else if (this.isLineTerminator()) { // an uninitialized class property (due to ASI, since we don't otherwise recognize the next token) if (isPrivate) { @@ -1664,6 +1685,36 @@ export default class StatementParser extends ExpressionParser { ); } + pushClassAccessorProperty( + classBody: N.ClassBody, + prop: N.ClassAccessorProperty, + ) { + if ( + !prop.computed && + (prop.key.name === "constructor" || prop.key.value === "constructor") + ) { + // Non-computed field, which is either an identifier named "constructor" + // or a string literal named "constructor" + this.raise(prop.key.start, Errors.ConstructorClassField); + } + + classBody.body.push(this.parseClassAccessorProperty(prop)); + } + + pushClassPrivateAccessorProperty( + classBody: N.ClassBody, + prop: N.ClassPrivateAccessorProperty, + ) { + const node = this.parseClassPrivateAccessorProperty(prop); + classBody.body.push(node); + + this.classScope.declarePrivateName( + this.getPrivateNameSV(node.key), + CLASS_ELEMENT_OTHER, + node.key.start, + ); + } + pushClassMethod( classBody: N.ClassBody, method: N.ClassMethod, @@ -1741,8 +1792,30 @@ export default class StatementParser extends ExpressionParser { return this.finishNode(node, "ClassProperty"); } + parseClassPrivateAccessorProperty( + node: N.ClassPrivateAccessorProperty, + ): N.ClassPrivateAccessorProperty { + this.parseInitializer(node); + this.semicolon(); + return this.finishNode(node, "ClassPrivateAccessorProperty"); + } + + parseClassAccessorProperty( + node: N.ClassAccessorProperty, + ): N.ClassAccessorProperty { + this.parseInitializer(node); + this.semicolon(); + return this.finishNode(node, "ClassAccessorProperty"); + } + // https://tc39.es/proposal-class-fields/#prod-Initializer - parseInitializer(node: N.ClassProperty | N.ClassPrivateProperty): void { + parseInitializer( + node: + | N.ClassProperty + | N.ClassPrivateProperty + | N.ClassAccessorProperty + | N.ClassPrivateAccessorProperty, + ): void { this.scope.enter(SCOPE_CLASS | SCOPE_SUPER); this.expressionScope.enter(newExpressionScope()); this.prodParam.enter(PARAM); diff --git a/packages/babel-parser/src/types.js b/packages/babel-parser/src/types.js index e747abc6b5f5..7059b7232885 100644 --- a/packages/babel-parser/src/types.js +++ b/packages/babel-parser/src/types.js @@ -782,7 +782,9 @@ export type ClassMember = | ClassMethod | ClassPrivateMethod | ClassProperty - | ClassPrivateProperty; + | ClassPrivateProperty + | ClassAccessorProperty + | ClassPrivateAccessorProperty; export type MethodLike = | ObjectMethod @@ -849,6 +851,37 @@ export type ClassPrivateProperty = NodeBase & { override?: true, }; +export type ClassAccessorProperty = ClassMemberBase & + DeclarationBase & { + type: "ClassAccessorProperty", + key: Expression, + value: ?Expression, // TODO: Not in spec that this is nullable. + + typeAnnotation?: ?TypeAnnotationBase, // TODO: Not in spec + variance?: ?FlowVariance, // TODO: Not in spec + + // TypeScript only: (TODO: Not in spec) + readonly?: true, + definite?: true, + }; + +export type ClassPrivateAccessorProperty = NodeBase & { + type: "ClassPrivateAccessorProperty", + key: PrivateName, + value: ?Expression, // TODO: Not in spec that this is nullable. + static: boolean, + computed: false, + + // Flow and Typescript + typeAnnotation?: ?TypeAnnotationBase, + + // TypeScript only + optional?: true, + definite?: true, + readonly?: true, + override?: true, +}; + export type OptClassDeclaration = ClassBase & DeclarationBase & HasDecorators & { diff --git a/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/accessor-named-constructor/input.js b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/accessor-named-constructor/input.js new file mode 100644 index 000000000000..fa4a4b67422e --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/accessor-named-constructor/input.js @@ -0,0 +1,3 @@ +class Foo { + accessor constructor; +} diff --git a/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/accessor-named-constructor/output.json b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/accessor-named-constructor/output.json new file mode 100644 index 000000000000..6860810b0dda --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/accessor-named-constructor/output.json @@ -0,0 +1,44 @@ +{ + "type": "File", + "start":0,"end":37,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "errors": [ + "SyntaxError: Classes may not have a field named 'constructor'. (2:11)" + ], + "program": { + "type": "Program", + "start":0,"end":37,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":37,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":9,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":9},"identifierName":"Foo"}, + "name": "Foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":10,"end":37,"loc":{"start":{"line":1,"column":10},"end":{"line":3,"column":1}}, + "body": [ + { + "type": "ClassAccessorProperty", + "start":14,"end":35,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":23}}, + "static": false, + "key": { + "type": "Identifier", + "start":23,"end":34,"loc":{"start":{"line":2,"column":11},"end":{"line":2,"column":22},"identifierName":"constructor"}, + "name": "constructor" + }, + "computed": false, + "value": null + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/basic-accessor-with-newline/input.js b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/basic-accessor-with-newline/input.js new file mode 100644 index 000000000000..30bf86a73fd0 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/basic-accessor-with-newline/input.js @@ -0,0 +1,4 @@ +class Foo { + accessor + bar; +} diff --git a/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/basic-accessor-with-newline/output.json b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/basic-accessor-with-newline/output.json new file mode 100644 index 000000000000..4c9daf45e5b4 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/basic-accessor-with-newline/output.json @@ -0,0 +1,53 @@ +{ + "type": "File", + "start":0,"end":31,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}}, + "program": { + "type": "Program", + "start":0,"end":31,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":31,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":9,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":9},"identifierName":"Foo"}, + "name": "Foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":10,"end":31,"loc":{"start":{"line":1,"column":10},"end":{"line":4,"column":1}}, + "body": [ + { + "type": "ClassProperty", + "start":14,"end":22,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":10}}, + "static": false, + "key": { + "type": "Identifier", + "start":14,"end":22,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":10},"identifierName":"accessor"}, + "name": "accessor" + }, + "computed": false, + "value": null + }, + { + "type": "ClassProperty", + "start":25,"end":29,"loc":{"start":{"line":3,"column":2},"end":{"line":3,"column":6}}, + "static": false, + "key": { + "type": "Identifier", + "start":25,"end":28,"loc":{"start":{"line":3,"column":2},"end":{"line":3,"column":5},"identifierName":"bar"}, + "name": "bar" + }, + "computed": false, + "value": null + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/basic-accessor/input.js b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/basic-accessor/input.js new file mode 100644 index 000000000000..735a7a78e304 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/basic-accessor/input.js @@ -0,0 +1,3 @@ +class Foo { + accessor bar; +} diff --git a/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/basic-accessor/output.json b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/basic-accessor/output.json new file mode 100644 index 000000000000..378b00ee57ee --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/basic-accessor/output.json @@ -0,0 +1,41 @@ +{ + "type": "File", + "start":0,"end":29,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "program": { + "type": "Program", + "start":0,"end":29,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":29,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":9,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":9},"identifierName":"Foo"}, + "name": "Foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":10,"end":29,"loc":{"start":{"line":1,"column":10},"end":{"line":3,"column":1}}, + "body": [ + { + "type": "ClassAccessorProperty", + "start":14,"end":27,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":15}}, + "static": false, + "key": { + "type": "Identifier", + "start":23,"end":26,"loc":{"start":{"line":2,"column":11},"end":{"line":2,"column":14},"identifierName":"bar"}, + "name": "bar" + }, + "computed": false, + "value": null + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/computed-accessor-named-constructor/input.js b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/computed-accessor-named-constructor/input.js new file mode 100644 index 000000000000..27dd24f5bb98 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/computed-accessor-named-constructor/input.js @@ -0,0 +1,3 @@ +class Foo { + accessor ["constructor"]; +} diff --git a/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/computed-accessor-named-constructor/output.json b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/computed-accessor-named-constructor/output.json new file mode 100644 index 000000000000..2705e4929c5d --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/computed-accessor-named-constructor/output.json @@ -0,0 +1,45 @@ +{ + "type": "File", + "start":0,"end":41,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "program": { + "type": "Program", + "start":0,"end":41,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":41,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":9,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":9},"identifierName":"Foo"}, + "name": "Foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":10,"end":41,"loc":{"start":{"line":1,"column":10},"end":{"line":3,"column":1}}, + "body": [ + { + "type": "ClassAccessorProperty", + "start":14,"end":39,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":27}}, + "static": false, + "key": { + "type": "StringLiteral", + "start":24,"end":37,"loc":{"start":{"line":2,"column":12},"end":{"line":2,"column":25}}, + "extra": { + "rawValue": "constructor", + "raw": "\"constructor\"" + }, + "value": "constructor" + }, + "computed": true, + "value": null + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/computed-accessor-with-newline/input.js b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/computed-accessor-with-newline/input.js new file mode 100644 index 000000000000..a067c2ad5c2d --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/computed-accessor-with-newline/input.js @@ -0,0 +1,4 @@ +class Foo { + accessor + ["bar"]; +} diff --git a/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/computed-accessor-with-newline/output.json b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/computed-accessor-with-newline/output.json new file mode 100644 index 000000000000..8b7e59c2ee0a --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/computed-accessor-with-newline/output.json @@ -0,0 +1,57 @@ +{ + "type": "File", + "start":0,"end":35,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}}, + "program": { + "type": "Program", + "start":0,"end":35,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":35,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":9,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":9},"identifierName":"Foo"}, + "name": "Foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":10,"end":35,"loc":{"start":{"line":1,"column":10},"end":{"line":4,"column":1}}, + "body": [ + { + "type": "ClassProperty", + "start":14,"end":22,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":10}}, + "static": false, + "key": { + "type": "Identifier", + "start":14,"end":22,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":10},"identifierName":"accessor"}, + "name": "accessor" + }, + "computed": false, + "value": null + }, + { + "type": "ClassProperty", + "start":25,"end":33,"loc":{"start":{"line":3,"column":2},"end":{"line":3,"column":10}}, + "static": false, + "computed": true, + "key": { + "type": "StringLiteral", + "start":26,"end":31,"loc":{"start":{"line":3,"column":3},"end":{"line":3,"column":8}}, + "extra": { + "rawValue": "bar", + "raw": "\"bar\"" + }, + "value": "bar" + }, + "value": null + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/computed-accessor/input.js b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/computed-accessor/input.js new file mode 100644 index 000000000000..f77d3f867281 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/computed-accessor/input.js @@ -0,0 +1,3 @@ +class Foo { + accessor ["bar"]; +} diff --git a/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/computed-accessor/output.json b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/computed-accessor/output.json new file mode 100644 index 000000000000..d15e333f0317 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/computed-accessor/output.json @@ -0,0 +1,45 @@ +{ + "type": "File", + "start":0,"end":33,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "program": { + "type": "Program", + "start":0,"end":33,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":33,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":9,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":9},"identifierName":"Foo"}, + "name": "Foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":10,"end":33,"loc":{"start":{"line":1,"column":10},"end":{"line":3,"column":1}}, + "body": [ + { + "type": "ClassAccessorProperty", + "start":14,"end":31,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":19}}, + "static": false, + "key": { + "type": "StringLiteral", + "start":24,"end":29,"loc":{"start":{"line":2,"column":12},"end":{"line":2,"column":17}}, + "extra": { + "rawValue": "bar", + "raw": "\"bar\"" + }, + "value": "bar" + }, + "computed": true, + "value": null + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/computed-static-accesor/input.js b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/computed-static-accesor/input.js new file mode 100644 index 000000000000..03a1bfe9b8d2 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/computed-static-accesor/input.js @@ -0,0 +1,3 @@ +class Foo { + static accessor ["bar"]; +} diff --git a/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/computed-static-accesor/output.json b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/computed-static-accesor/output.json new file mode 100644 index 000000000000..709fa0b48133 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/computed-static-accesor/output.json @@ -0,0 +1,45 @@ +{ + "type": "File", + "start":0,"end":40,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "program": { + "type": "Program", + "start":0,"end":40,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":40,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":9,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":9},"identifierName":"Foo"}, + "name": "Foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":10,"end":40,"loc":{"start":{"line":1,"column":10},"end":{"line":3,"column":1}}, + "body": [ + { + "type": "ClassAccessorProperty", + "start":14,"end":38,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":26}}, + "static": true, + "key": { + "type": "StringLiteral", + "start":31,"end":36,"loc":{"start":{"line":2,"column":19},"end":{"line":2,"column":24}}, + "extra": { + "rawValue": "bar", + "raw": "\"bar\"" + }, + "value": "bar" + }, + "computed": true, + "value": null + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/field-named-accessor/input.js b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/field-named-accessor/input.js new file mode 100644 index 000000000000..fba4a91f8875 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/field-named-accessor/input.js @@ -0,0 +1,3 @@ +class Foo { + accessor = 123; +} diff --git a/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/field-named-accessor/output.json b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/field-named-accessor/output.json new file mode 100644 index 000000000000..6f6c5d059cc5 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/field-named-accessor/output.json @@ -0,0 +1,49 @@ +{ + "type": "File", + "start":0,"end":31,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "program": { + "type": "Program", + "start":0,"end":31,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":31,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":9,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":9},"identifierName":"Foo"}, + "name": "Foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":10,"end":31,"loc":{"start":{"line":1,"column":10},"end":{"line":3,"column":1}}, + "body": [ + { + "type": "ClassProperty", + "start":14,"end":29,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":17}}, + "static": false, + "key": { + "type": "Identifier", + "start":14,"end":22,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":10},"identifierName":"accessor"}, + "name": "accessor" + }, + "computed": false, + "value": { + "type": "NumericLiteral", + "start":25,"end":28,"loc":{"start":{"line":2,"column":13},"end":{"line":2,"column":16}}, + "extra": { + "rawValue": 123, + "raw": "123" + }, + "value": 123 + } + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/invalid-static-keyword-order-newline/input.js b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/invalid-static-keyword-order-newline/input.js new file mode 100644 index 000000000000..7443f54725f1 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/invalid-static-keyword-order-newline/input.js @@ -0,0 +1,3 @@ +class Foo { + accessor static bar; +} diff --git a/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/invalid-static-keyword-order-newline/output.json b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/invalid-static-keyword-order-newline/output.json new file mode 100644 index 000000000000..fcca9f53576d --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/invalid-static-keyword-order-newline/output.json @@ -0,0 +1,56 @@ +{ + "type": "File", + "start":0,"end":36,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "errors": [ + "SyntaxError: Missing semicolon. (2:17)" + ], + "program": { + "type": "Program", + "start":0,"end":36,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":36,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":9,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":9},"identifierName":"Foo"}, + "name": "Foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":10,"end":36,"loc":{"start":{"line":1,"column":10},"end":{"line":3,"column":1}}, + "body": [ + { + "type": "ClassAccessorProperty", + "start":14,"end":29,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":17}}, + "static": false, + "key": { + "type": "Identifier", + "start":23,"end":29,"loc":{"start":{"line":2,"column":11},"end":{"line":2,"column":17},"identifierName":"static"}, + "name": "static" + }, + "computed": false, + "value": null + }, + { + "type": "ClassProperty", + "start":30,"end":34,"loc":{"start":{"line":2,"column":18},"end":{"line":2,"column":22}}, + "static": false, + "key": { + "type": "Identifier", + "start":30,"end":33,"loc":{"start":{"line":2,"column":18},"end":{"line":2,"column":21},"identifierName":"bar"}, + "name": "bar" + }, + "computed": false, + "value": null + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/invalid-static-keyword-order/input.js b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/invalid-static-keyword-order/input.js new file mode 100644 index 000000000000..7443f54725f1 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/invalid-static-keyword-order/input.js @@ -0,0 +1,3 @@ +class Foo { + accessor static bar; +} diff --git a/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/invalid-static-keyword-order/output.json b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/invalid-static-keyword-order/output.json new file mode 100644 index 000000000000..fcca9f53576d --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/invalid-static-keyword-order/output.json @@ -0,0 +1,56 @@ +{ + "type": "File", + "start":0,"end":36,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "errors": [ + "SyntaxError: Missing semicolon. (2:17)" + ], + "program": { + "type": "Program", + "start":0,"end":36,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":36,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":9,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":9},"identifierName":"Foo"}, + "name": "Foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":10,"end":36,"loc":{"start":{"line":1,"column":10},"end":{"line":3,"column":1}}, + "body": [ + { + "type": "ClassAccessorProperty", + "start":14,"end":29,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":17}}, + "static": false, + "key": { + "type": "Identifier", + "start":23,"end":29,"loc":{"start":{"line":2,"column":11},"end":{"line":2,"column":17},"identifierName":"static"}, + "name": "static" + }, + "computed": false, + "value": null + }, + { + "type": "ClassProperty", + "start":30,"end":34,"loc":{"start":{"line":2,"column":18},"end":{"line":2,"column":22}}, + "static": false, + "key": { + "type": "Identifier", + "start":30,"end":33,"loc":{"start":{"line":2,"column":18},"end":{"line":2,"column":21},"identifierName":"bar"}, + "name": "bar" + }, + "computed": false, + "value": null + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/method-named-accessor/input.js b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/method-named-accessor/input.js new file mode 100644 index 000000000000..d4092463f89a --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/method-named-accessor/input.js @@ -0,0 +1,3 @@ +class Foo { + accessor() {} +} diff --git a/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/method-named-accessor/output.json b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/method-named-accessor/output.json new file mode 100644 index 000000000000..b55c19130b12 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/method-named-accessor/output.json @@ -0,0 +1,51 @@ +{ + "type": "File", + "start":0,"end":29,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "program": { + "type": "Program", + "start":0,"end":29,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":29,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":9,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":9},"identifierName":"Foo"}, + "name": "Foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":10,"end":29,"loc":{"start":{"line":1,"column":10},"end":{"line":3,"column":1}}, + "body": [ + { + "type": "ClassMethod", + "start":14,"end":27,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":15}}, + "static": false, + "key": { + "type": "Identifier", + "start":14,"end":22,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":10},"identifierName":"accessor"}, + "name": "accessor" + }, + "computed": false, + "kind": "method", + "id": null, + "generator": false, + "async": false, + "params": [], + "body": { + "type": "BlockStatement", + "start":25,"end":27,"loc":{"start":{"line":2,"column":13},"end":{"line":2,"column":15}}, + "body": [], + "directives": [] + } + } + ] + } + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/not-allowed-on-methods/input.js b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/not-allowed-on-methods/input.js new file mode 100644 index 000000000000..4e41f3511da0 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/not-allowed-on-methods/input.js @@ -0,0 +1,5 @@ +class Foo { + accessor bar() { + + } +} diff --git a/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/not-allowed-on-methods/options.json b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/not-allowed-on-methods/options.json new file mode 100644 index 000000000000..a1c98245e1ed --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/not-allowed-on-methods/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Unexpected token (2:14)" +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/options.json b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/options.json new file mode 100644 index 000000000000..a8f08fad2f89 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/options.json @@ -0,0 +1,5 @@ +{ + "plugins": [ + "simpleAutoAccessors" + ] +} diff --git a/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/private-accessor/input.js b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/private-accessor/input.js new file mode 100644 index 000000000000..9127772fc36b --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/private-accessor/input.js @@ -0,0 +1,3 @@ +class Foo { + accessor #bar; +} diff --git a/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/private-accessor/output.json b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/private-accessor/output.json new file mode 100644 index 000000000000..14d271d0366b --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/private-accessor/output.json @@ -0,0 +1,45 @@ +{ + "type": "File", + "start":0,"end":30,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "program": { + "type": "Program", + "start":0,"end":30,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":30,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":9,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":9},"identifierName":"Foo"}, + "name": "Foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":10,"end":30,"loc":{"start":{"line":1,"column":10},"end":{"line":3,"column":1}}, + "body": [ + { + "type": "ClassPrivateAccessorProperty", + "start":14,"end":28,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":16}}, + "static": false, + "key": { + "type": "PrivateName", + "start":23,"end":27,"loc":{"start":{"line":2,"column":11},"end":{"line":2,"column":15}}, + "id": { + "type": "Identifier", + "start":24,"end":27,"loc":{"start":{"line":2,"column":12},"end":{"line":2,"column":15},"identifierName":"bar"}, + "name": "bar" + } + }, + "computed": false, + "value": null + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/private-static-accessor/input.js b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/private-static-accessor/input.js new file mode 100644 index 000000000000..eda1665ae885 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/private-static-accessor/input.js @@ -0,0 +1,3 @@ +class Foo { + static accessor #bar; +} diff --git a/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/private-static-accessor/output.json b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/private-static-accessor/output.json new file mode 100644 index 000000000000..a0d3a0ed0a01 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/private-static-accessor/output.json @@ -0,0 +1,45 @@ +{ + "type": "File", + "start":0,"end":37,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "program": { + "type": "Program", + "start":0,"end":37,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":37,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":9,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":9},"identifierName":"Foo"}, + "name": "Foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":10,"end":37,"loc":{"start":{"line":1,"column":10},"end":{"line":3,"column":1}}, + "body": [ + { + "type": "ClassPrivateAccessorProperty", + "start":14,"end":35,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":23}}, + "static": true, + "key": { + "type": "PrivateName", + "start":30,"end":34,"loc":{"start":{"line":2,"column":18},"end":{"line":2,"column":22}}, + "id": { + "type": "Identifier", + "start":31,"end":34,"loc":{"start":{"line":2,"column":19},"end":{"line":2,"column":22},"identifierName":"bar"}, + "name": "bar" + } + }, + "computed": false, + "value": null + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/static-accessor-with-newline/input.js b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/static-accessor-with-newline/input.js new file mode 100644 index 000000000000..e297f3f665b3 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/static-accessor-with-newline/input.js @@ -0,0 +1,4 @@ +class Foo { + static accessor + bar; +} diff --git a/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/static-accessor-with-newline/output.json b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/static-accessor-with-newline/output.json new file mode 100644 index 000000000000..b4301f09e1a4 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/static-accessor-with-newline/output.json @@ -0,0 +1,53 @@ +{ + "type": "File", + "start":0,"end":38,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}}, + "program": { + "type": "Program", + "start":0,"end":38,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":38,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":9,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":9},"identifierName":"Foo"}, + "name": "Foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":10,"end":38,"loc":{"start":{"line":1,"column":10},"end":{"line":4,"column":1}}, + "body": [ + { + "type": "ClassProperty", + "start":14,"end":29,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":17}}, + "static": true, + "key": { + "type": "Identifier", + "start":21,"end":29,"loc":{"start":{"line":2,"column":9},"end":{"line":2,"column":17},"identifierName":"accessor"}, + "name": "accessor" + }, + "computed": false, + "value": null + }, + { + "type": "ClassProperty", + "start":32,"end":36,"loc":{"start":{"line":3,"column":2},"end":{"line":3,"column":6}}, + "static": false, + "key": { + "type": "Identifier", + "start":32,"end":35,"loc":{"start":{"line":3,"column":2},"end":{"line":3,"column":5},"identifierName":"bar"}, + "name": "bar" + }, + "computed": false, + "value": null + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/static-accessor/input.js b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/static-accessor/input.js new file mode 100644 index 000000000000..10777835cd1c --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/static-accessor/input.js @@ -0,0 +1,3 @@ +class Foo { + static accessor bar; +} diff --git a/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/static-accessor/output.json b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/static-accessor/output.json new file mode 100644 index 000000000000..ca4c9c4e761e --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/simple-auto-accessors/static-accessor/output.json @@ -0,0 +1,41 @@ +{ + "type": "File", + "start":0,"end":36,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "program": { + "type": "Program", + "start":0,"end":36,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":36,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, + "id": { + "type": "Identifier", + "start":6,"end":9,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":9},"identifierName":"Foo"}, + "name": "Foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":10,"end":36,"loc":{"start":{"line":1,"column":10},"end":{"line":3,"column":1}}, + "body": [ + { + "type": "ClassAccessorProperty", + "start":14,"end":34,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":22}}, + "static": true, + "key": { + "type": "Identifier", + "start":30,"end":33,"loc":{"start":{"line":2,"column":18},"end":{"line":2,"column":21},"identifierName":"bar"}, + "name": "bar" + }, + "computed": false, + "value": null + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-traverse/src/path/generated/asserts.ts b/packages/babel-traverse/src/path/generated/asserts.ts index 3acc28f3fbb8..b1c09d7013fd 100755 --- a/packages/babel-traverse/src/path/generated/asserts.ts +++ b/packages/babel-traverse/src/path/generated/asserts.ts @@ -61,6 +61,9 @@ export interface NodePathAssetions { ): asserts this is NodePath; assertCatchClause(opts?: object): asserts this is NodePath; assertClass(opts?: object): asserts this is NodePath; + assertClassAccessorProperty( + opts?: object, + ): asserts this is NodePath; assertClassBody(opts?: object): asserts this is NodePath; assertClassDeclaration( opts?: object, @@ -72,6 +75,9 @@ export interface NodePathAssetions { opts?: object, ): asserts this is NodePath; assertClassMethod(opts?: object): asserts this is NodePath; + assertClassPrivateAccessorProperty( + opts?: object, + ): asserts this is NodePath; assertClassPrivateMethod( opts?: object, ): asserts this is NodePath; diff --git a/packages/babel-traverse/src/path/generated/validators.ts b/packages/babel-traverse/src/path/generated/validators.ts index 6f6c457e37e5..ad05d229fa4e 100755 --- a/packages/babel-traverse/src/path/generated/validators.ts +++ b/packages/babel-traverse/src/path/generated/validators.ts @@ -38,11 +38,17 @@ export interface NodePathValidators { isCallExpression(opts?: object): this is NodePath; isCatchClause(opts?: object): this is NodePath; isClass(opts?: object): this is NodePath; + isClassAccessorProperty( + opts?: object, + ): this is NodePath; isClassBody(opts?: object): this is NodePath; isClassDeclaration(opts?: object): this is NodePath; isClassExpression(opts?: object): this is NodePath; isClassImplements(opts?: object): this is NodePath; isClassMethod(opts?: object): this is NodePath; + isClassPrivateAccessorProperty( + opts?: object, + ): this is NodePath; isClassPrivateMethod(opts?: object): this is NodePath; isClassPrivateProperty( opts?: object, diff --git a/packages/babel-types/src/asserts/generated/index.ts b/packages/babel-types/src/asserts/generated/index.ts index c171b27816cf..b0f697c29cf3 100755 --- a/packages/babel-types/src/asserts/generated/index.ts +++ b/packages/babel-types/src/asserts/generated/index.ts @@ -506,12 +506,24 @@ export function assertClassProperty( ): asserts node is t.ClassProperty { assert("ClassProperty", node, opts); } +export function assertClassAccessorProperty( + node: object | null | undefined, + opts?: object | null, +): asserts node is t.ClassAccessorProperty { + assert("ClassAccessorProperty", node, opts); +} export function assertClassPrivateProperty( node: object | null | undefined, opts?: object | null, ): asserts node is t.ClassPrivateProperty { assert("ClassPrivateProperty", node, opts); } +export function assertClassPrivateAccessorProperty( + node: object | null | undefined, + opts?: object | null, +): asserts node is t.ClassPrivateAccessorProperty { + assert("ClassPrivateAccessorProperty", node, opts); +} export function assertClassPrivateMethod( node: object | null | undefined, opts?: object | null, diff --git a/packages/babel-types/src/ast-types/generated/index.ts b/packages/babel-types/src/ast-types/generated/index.ts index f4def136c3c2..091efb7f83ca 100755 --- a/packages/babel-types/src/ast-types/generated/index.ts +++ b/packages/babel-types/src/ast-types/generated/index.ts @@ -69,11 +69,13 @@ export type Node = | CallExpression | CatchClause | Class + | ClassAccessorProperty | ClassBody | ClassDeclaration | ClassExpression | ClassImplements | ClassMethod + | ClassPrivateAccessorProperty | ClassPrivateMethod | ClassPrivateProperty | ClassProperty @@ -1032,6 +1034,24 @@ export interface ClassProperty extends BaseNode { variance?: Variance | null; } +export interface ClassAccessorProperty extends BaseNode { + type: "ClassAccessorProperty"; + key: Identifier | StringLiteral | NumericLiteral | Expression; + value?: Expression | null; + typeAnnotation?: TypeAnnotation | TSTypeAnnotation | Noop | null; + decorators?: Array | null; + computed?: boolean; + static?: boolean; + abstract?: boolean | null; + accessibility?: "public" | "private" | "protected" | null; + declare?: boolean | null; + definite?: boolean | null; + optional?: boolean | null; + override?: boolean; + readonly?: boolean | null; + variance?: Variance | null; +} + export interface ClassPrivateProperty extends BaseNode { type: "ClassPrivateProperty"; key: PrivateName; @@ -1044,6 +1064,19 @@ export interface ClassPrivateProperty extends BaseNode { variance?: Variance | null; } +export interface ClassPrivateAccessorProperty extends BaseNode { + type: "ClassPrivateAccessorProperty"; + key: PrivateName; + value?: Expression | null; + decorators?: Array | null; + static: any; + computed?: boolean; + definite?: boolean | null; + readonly?: boolean | null; + typeAnnotation?: TypeAnnotation | TSTypeAnnotation | Noop | null; + variance?: Variance | null; +} + export interface ClassPrivateMethod extends BaseNode { type: "ClassPrivateMethod"; kind?: "get" | "set" | "method" | "constructor"; @@ -2322,7 +2355,12 @@ export type UserWhitespacable = | ObjectTypeSpreadProperty; export type Method = ObjectMethod | ClassMethod | ClassPrivateMethod; export type ObjectMember = ObjectMethod | ObjectProperty; -export type Property = ObjectProperty | ClassProperty | ClassPrivateProperty; +export type Property = + | ObjectProperty + | ClassProperty + | ClassAccessorProperty + | ClassPrivateProperty + | ClassPrivateAccessorProperty; export type UnaryLike = UnaryExpression | SpreadElement; export type Pattern = AssignmentPattern | ArrayPattern | ObjectPattern; export type Class = ClassExpression | ClassDeclaration; @@ -2342,7 +2380,11 @@ export type ModuleSpecifier = | ImportSpecifier | ExportNamespaceSpecifier | ExportDefaultSpecifier; -export type Private = ClassPrivateProperty | ClassPrivateMethod | PrivateName; +export type Private = + | ClassPrivateProperty + | ClassPrivateAccessorProperty + | ClassPrivateMethod + | PrivateName; export type Flow = | AnyTypeAnnotation | ArrayTypeAnnotation diff --git a/packages/babel-types/src/builders/generated/index.ts b/packages/babel-types/src/builders/generated/index.ts index aa5591c88bbd..8e8e5b7add7b 100755 --- a/packages/babel-types/src/builders/generated/index.ts +++ b/packages/babel-types/src/builders/generated/index.ts @@ -525,6 +525,16 @@ export function classProperty( ): t.ClassProperty { return builder("ClassProperty", ...arguments); } +export function classAccessorProperty( + key: t.Identifier | t.StringLiteral | t.NumericLiteral | t.Expression, + value?: t.Expression | null, + typeAnnotation?: t.TypeAnnotation | t.TSTypeAnnotation | t.Noop | null, + decorators?: Array | null, + computed?: boolean, + _static?: boolean, +): t.ClassAccessorProperty { + return builder("ClassAccessorProperty", ...arguments); +} export function classPrivateProperty( key: t.PrivateName, value: t.Expression | null | undefined, @@ -533,6 +543,14 @@ export function classPrivateProperty( ): t.ClassPrivateProperty { return builder("ClassPrivateProperty", ...arguments); } +export function classPrivateAccessorProperty( + key: t.PrivateName, + value: t.Expression | null | undefined, + decorators: Array | null | undefined, + _static: any, +): t.ClassPrivateAccessorProperty { + return builder("ClassPrivateAccessorProperty", ...arguments); +} export function classPrivateMethod( kind: "get" | "set" | "method" | "constructor" | undefined, key: t.PrivateName, diff --git a/packages/babel-types/src/builders/generated/uppercase.js b/packages/babel-types/src/builders/generated/uppercase.js index 73d60dbb6ff8..bf6c4f3fac53 100755 --- a/packages/babel-types/src/builders/generated/uppercase.js +++ b/packages/babel-types/src/builders/generated/uppercase.js @@ -91,7 +91,9 @@ export { optionalMemberExpression as OptionalMemberExpression, optionalCallExpression as OptionalCallExpression, classProperty as ClassProperty, + classAccessorProperty as ClassAccessorProperty, classPrivateProperty as ClassPrivateProperty, + classPrivateAccessorProperty as ClassPrivateAccessorProperty, classPrivateMethod as ClassPrivateMethod, privateName as PrivateName, anyTypeAnnotation as AnyTypeAnnotation, diff --git a/packages/babel-types/src/converters/toComputedKey.ts b/packages/babel-types/src/converters/toComputedKey.ts index d82d266af12d..4db773ddb56d 100644 --- a/packages/babel-types/src/converters/toComputedKey.ts +++ b/packages/babel-types/src/converters/toComputedKey.ts @@ -8,6 +8,7 @@ export default function toComputedKey( | t.ObjectProperty | t.ClassMethod | t.ClassProperty + | t.ClassAccessorProperty | t.MemberExpression | t.OptionalMemberExpression, // @ts-expect-error todo(flow->ts): maybe check the type of node before accessing .key and .property diff --git a/packages/babel-types/src/definitions/core.ts b/packages/babel-types/src/definitions/core.ts index fbf7e1859342..c11463ffe73f 100644 --- a/packages/babel-types/src/definitions/core.ts +++ b/packages/babel-types/src/definitions/core.ts @@ -2117,6 +2117,55 @@ defineType("ClassProperty", { }, }); +defineType("ClassAccessorProperty", { + visitor: ["key", "value", "typeAnnotation", "decorators"], + builder: [ + "key", + "value", + "typeAnnotation", + "decorators", + "computed", + "static", + ], + aliases: ["Property"], + fields: { + ...classMethodOrPropertyCommon, + value: { + validate: assertNodeType("Expression"), + optional: true, + }, + definite: { + validate: assertValueType("boolean"), + optional: true, + }, + typeAnnotation: { + validate: process.env.BABEL_8_BREAKING + ? assertNodeType("TypeAnnotation", "TSTypeAnnotation") + : assertNodeType("TypeAnnotation", "TSTypeAnnotation", "Noop"), + optional: true, + }, + decorators: { + validate: chain( + assertValueType("array"), + assertEach(assertNodeType("Decorator")), + ), + optional: true, + }, + readonly: { + validate: assertValueType("boolean"), + optional: true, + }, + declare: { + validate: assertValueType("boolean"), + optional: true, + }, + variance: { + validate: assertNodeType("Variance"), + optional: true, + }, + }, +}); + defineType("ClassPrivateProperty", { visitor: ["key", "value", "decorators", "typeAnnotation"], builder: ["key", "value", "decorators", "static"], @@ -2157,6 +2206,49 @@ defineType("ClassPrivateProperty", { }, }); +defineType("ClassPrivateAccessorProperty", { + visitor: ["key", "value", "decorators", "typeAnnotation"], + builder: ["key", "value", "decorators", "static"], + aliases: ["Property", "Private"], + fields: { + key: { + validate: assertNodeType("PrivateName"), + }, + value: { + validate: assertNodeType("Expression"), + optional: true, + }, + typeAnnotation: { + validate: process.env.BABEL_8_BREAKING + ? assertNodeType("TypeAnnotation", "TSTypeAnnotation") + : assertNodeType("TypeAnnotation", "TSTypeAnnotation", "Noop"), + optional: true, + }, + decorators: { + validate: chain( + assertValueType("array"), + assertEach(assertNodeType("Decorator")), + ), + optional: true, + }, + readonly: { + validate: assertValueType("boolean"), + optional: true, + }, + definite: { + validate: assertValueType("boolean"), + optional: true, + }, + variance: { + validate: assertNodeType("Variance"), + optional: true, + }, + computed: { + default: false, + }, + }, +}); + defineType("ClassPrivateMethod", { builder: ["kind", "key", "params", "body", "static"], visitor: [ diff --git a/packages/babel-types/src/validators/generated/index.ts b/packages/babel-types/src/validators/generated/index.ts index 7a2509842d27..e0c80ebc2f16 100755 --- a/packages/babel-types/src/validators/generated/index.ts +++ b/packages/babel-types/src/validators/generated/index.ts @@ -1399,6 +1399,23 @@ export function isClassProperty( return false; } +export function isClassAccessorProperty( + node: object | null | undefined, + opts?: object | null, +): node is t.ClassAccessorProperty { + if (!node) return false; + + const nodeType = (node as t.Node).type; + if (nodeType === "ClassAccessorProperty") { + if (typeof opts === "undefined") { + return true; + } else { + return shallowEqual(node, opts); + } + } + + return false; +} export function isClassPrivateProperty( node: object | null | undefined, opts?: object | null, @@ -1416,6 +1433,23 @@ export function isClassPrivateProperty( return false; } +export function isClassPrivateAccessorProperty( + node: object | null | undefined, + opts?: object | null, +): node is t.ClassPrivateAccessorProperty { + if (!node) return false; + + const nodeType = (node as t.Node).type; + if (nodeType === "ClassPrivateAccessorProperty") { + if (typeof opts === "undefined") { + return true; + } else { + return shallowEqual(node, opts); + } + } + + return false; +} export function isClassPrivateMethod( node: object | null | undefined, opts?: object | null, @@ -4942,7 +4976,9 @@ export function isProperty( if ( "ObjectProperty" === nodeType || "ClassProperty" === nodeType || - "ClassPrivateProperty" === nodeType + "ClassAccessorProperty" === nodeType || + "ClassPrivateProperty" === nodeType || + "ClassPrivateAccessorProperty" === nodeType ) { if (typeof opts === "undefined") { return true; @@ -5086,6 +5122,7 @@ export function isPrivate( const nodeType = (node as t.Node).type; if ( "ClassPrivateProperty" === nodeType || + "ClassPrivateAccessorProperty" === nodeType || "ClassPrivateMethod" === nodeType || "PrivateName" === nodeType ) { diff --git a/packages/babel-types/src/validators/isReferenced.ts b/packages/babel-types/src/validators/isReferenced.ts index 46c9cce7f6c3..278733858cb2 100644 --- a/packages/babel-types/src/validators/isReferenced.ts +++ b/packages/babel-types/src/validators/isReferenced.ts @@ -63,11 +63,13 @@ export default function isReferenced( // yes: class { [NODE] = value; } // yes: class { key = NODE; } case "ClassProperty": + case "ClassAccessorProperty": if (parent.key === node) { return !!parent.computed; } return true; case "ClassPrivateProperty": + case "ClassPrivateAccessorProperty": return parent.key !== node; // no: class NODE {}