diff --git a/README.md b/README.md index 873f034253..8b69868222 100644 --- a/README.md +++ b/README.md @@ -137,6 +137,7 @@ require("babylon").parse("code", { | `decorators` (Stage 1) and `decorators2` (Stage 2 [proposal](https://github.com/tc39/proposal-decorators)) | `@a class A {}` | | `classProperties` ([proposal](https://github.com/tc39/proposal-class-public-fields)) | `class A { b = 1; }` | | `classPrivateProperties` ([proposal](https://github.com/tc39/proposal-private-fields)) | `class A { #b = 1; }` | +| `classPrivateMethods` ([proposal](https://github.com/tc39/proposal-private-methods)) | `class A { #c() {} }` | | `exportExtensions` ([proposal 1](https://github.com/leebyron/ecmascript-export-default-from)), ([proposal 2](https://github.com/leebyron/ecmascript-export-ns-from)) | Proposal 1: `export v from "mod"` Proposal 2: `export * as ns from "mod"` | | `asyncGenerators` ([proposal](https://github.com/tc39/proposal-async-iteration)) | `async function*() {}`, `for await (let a of b) {}` | | `functionBind` ([proposal](https://github.com/zenparsing/es-function-bind)) | `a::b`, `::console.log` | diff --git a/ast/spec.md b/ast/spec.md index e3cbaab936..596acb462e 100644 --- a/ast/spec.md +++ b/ast/spec.md @@ -90,6 +90,7 @@ These are the core Babylon AST node types. - [Classes](#classes) - [ClassBody](#classbody) - [ClassMethod](#classmethod) + - [ClassPrivateMethod](#classprivatemethod) - [ClassProperty](#classproperty) - [ClassPrivateProperty](#classprivateproperty) - [ClassDeclaration](#classdeclaration) @@ -1032,7 +1033,7 @@ interface Class <: Node { ```js interface ClassBody <: Node { type: "ClassBody"; - body: [ ClassMethod | ClassProperty | ClassPrivateProperty ]; + body: [ ClassMethod | ClassPrivateMethod | ClassProperty | ClassPrivateProperty ]; } ``` @@ -1049,6 +1050,18 @@ interface ClassMethod <: Function { } ``` +## ClassPrivateMethod + +```js +interface ClassPrivateMethod <: Function { + type: "ClassPrivateMethod"; + key: PrivateName; + kind: "method" | "get" | "set"; + static: boolean; + decorators: [ Decorator ]; +} +``` + ## ClassProperty ```js @@ -1066,7 +1079,7 @@ interface ClassProperty <: Node { ```js interface ClassPrivateProperty <: Node { type: "ClassPrivateProperty"; - key: Identifier; + key: PrivateName; value: Expression; static: boolean; } diff --git a/scripts/test262_whitelist.txt b/scripts/test262_whitelist.txt index 5514f994a9..2ce1c445aa 100644 --- a/scripts/test262_whitelist.txt +++ b/scripts/test262_whitelist.txt @@ -256,8 +256,6 @@ language/statements/class/definition/early-errors-class-method-await-in-formals. language/statements/class/strict-mode/with.js(default) language/statements/class/syntax/early-errors/class-body-has-direct-super-missing-class-heritage.js(default) language/statements/class/syntax/early-errors/class-body-has-direct-super-missing-class-heritage.js(strict mode) -language/statements/class/syntax/early-errors/class-body-static-method-get-propname-prototype.js(default) -language/statements/class/syntax/early-errors/class-body-static-method-get-propname-prototype.js(strict mode) language/statements/class/syntax/early-errors/class-definition-evaluation-block-duplicate-binding.js(default) language/statements/class/syntax/early-errors/class-definition-evaluation-block-duplicate-binding.js(strict mode) language/statements/class/syntax/early-errors/class-definition-evaluation-scriptbody-duplicate-binding.js(default) @@ -1305,4 +1303,4 @@ language/statements/class/fields-wrapped-in-sc-string-literal-names.js(strict mo language/statements/labeled/let-identifier-with-newline.js(default) language/statements/labeled/value-yield-non-strict-escaped.js(default) -language/statements/let/syntax/escaped-let.js(default) \ No newline at end of file +language/statements/let/syntax/escaped-let.js(default) diff --git a/src/parser/expression.js b/src/parser/expression.js index 642bffa83c..870f91e0a5 100644 --- a/src/parser/expression.js +++ b/src/parser/expression.js @@ -1398,20 +1398,30 @@ export default class ExpressionParser extends LValParser { } parsePropertyName( - prop: N.ObjectOrClassMember | N.TsNamedTypeElementBase, - ): N.Expression { + prop: + | N.ObjectOrClassMember + | N.ClassPrivateProperty + | N.ClassPrivateMethod + | N.TsNamedTypeElementBase, + ): N.Expression | N.Identifier { if (this.eat(tt.bracketL)) { prop.computed = true; prop.key = this.parseMaybeAssign(); this.expect(tt.bracketR); } else { - prop.computed = false; const oldInPropertyName = this.state.inPropertyName; this.state.inPropertyName = true; + // We check if it's valid for it to be a private name when we push it. prop.key = this.match(tt.num) || this.match(tt.string) ? this.parseExprAtom() - : this.parseIdentifier(true); + : this.parseMaybePrivateName(); + + if (prop.key.type !== "PrivateName") { + // ClassPrivateProperty is never computed, so we don't assign in that case. + prop.computed = false; + } + this.state.inPropertyName = oldInPropertyName; } diff --git a/src/parser/statement.js b/src/parser/statement.js index 76b5ffcc57..fbbbe63c74 100644 --- a/src/parser/statement.js +++ b/src/parser/statement.js @@ -845,7 +845,7 @@ export default class StatementParser extends ExpressionParser { !method.computed && !method.static && (method.key.name === "constructor" || // Identifier - method.key.value === "constructor") // Literal + method.key.value === "constructor") // String literal ); } @@ -935,7 +935,7 @@ export default class StatementParser extends ExpressionParser { method.computed = false; method.key = key; method.static = false; - this.parseClassMethod( + this.pushClassMethod( classBody, method, false, @@ -955,17 +955,6 @@ export default class StatementParser extends ExpressionParser { isStatic = true; } - if (this.match(tt.hash)) { - // Private property - this.expectPlugin("classPrivateProperties"); - this.next(); - const privateProp: N.ClassPrivateProperty = memberAny; - privateProp.key = this.parseIdentifier(true); - privateProp.static = isStatic; - classBody.body.push(this.parsePrivateClassProperty(privateProp)); - return; - } - this.parseClassMemberWithIsStatic(classBody, member, state, isStatic); } @@ -976,54 +965,63 @@ export default class StatementParser extends ExpressionParser { isStatic: boolean, ) { const memberAny: any = member; - const methodOrProp: N.ClassMethod | N.ClassProperty = memberAny; - const method: N.ClassMethod = memberAny; - const prop: N.ClassProperty = memberAny; + const methodOrProp: + | N.ClassMethod + | N.ClassPrivateMethod + | N.ClassProperty + | N.ClassPrivateProperty = memberAny; + const method: N.ClassMethod | N.ClassPrivateMethod = memberAny; + const prop: N.ClassProperty | N.ClassPrivateProperty = memberAny; methodOrProp.static = isStatic; if (this.eat(tt.star)) { // a generator method.kind = "method"; - this.parsePropertyName(method); + this.parseClassPropertyName(method); + + if (method.key.type === "PrivateName") { + // Private generator method + this.pushClassPrivateMethod(classBody, method, true, false); + return; + } + if (this.isNonstaticConstructor(method)) { this.raise(method.key.start, "Constructor can't be a generator"); } - if ( - !method.computed && - method.static && - (method.key.name === "prototype" || method.key.value === "prototype") - ) { - this.raise( - method.key.start, - "Classes may not have static property named prototype", - ); - } - this.parseClassMethod( + + this.pushClassMethod( classBody, method, true, false, /* isConstructor */ false, ); + return; } - const isSimple = this.match(tt.name); const key = this.parseClassPropertyName(methodOrProp); + const isPrivate = key.type === "PrivateName"; + // Check the key is not a computed expression or string literal. + const isSimple = key.type === "Identifier"; this.parsePostMemberNameModifiers(methodOrProp); if (this.isClassMethod()) { + method.kind = "method"; + + if (isPrivate) { + this.pushClassPrivateMethod(classBody, method, false, false); + return; + } + // a normal method const isConstructor = this.isNonstaticConstructor(method); + if (isConstructor) { method.kind = "constructor"; - } else { - method.kind = "method"; - } - if (isConstructor) { if (method.decorators) { this.raise( method.start, @@ -1038,29 +1036,44 @@ export default class StatementParser extends ExpressionParser { state.hadConstructor = true; } - this.parseClassMethod(classBody, method, false, false, isConstructor); + this.pushClassMethod(classBody, method, false, false, isConstructor); } else if (this.isClassProperty()) { - this.pushClassProperty(classBody, prop); + if (isPrivate) { + this.pushClassPrivateProperty(classBody, prop); + } else { + this.pushClassProperty(classBody, prop); + } } else if (isSimple && key.name === "async" && !this.isLineTerminator()) { // an async method - let isGenerator = false; - if (this.match(tt.star)) { + const isGenerator = this.match(tt.star); + if (isGenerator) { this.expectPlugin("asyncGenerators"); this.next(); - isGenerator = true; } + method.kind = "method"; - this.parsePropertyName(method); - if (this.isNonstaticConstructor(method)) { - this.raise(method.key.start, "Constructor can't be an async function"); + // The so-called parsed name would have been "async": get the real name. + this.parseClassPropertyName(method); + + if (method.key.type === "PrivateName") { + // private async method + this.pushClassPrivateMethod(classBody, method, isGenerator, true); + } else { + if (this.isNonstaticConstructor(method)) { + this.raise( + method.key.start, + "Constructor can't be an async function", + ); + } + + this.pushClassMethod( + classBody, + method, + isGenerator, + true, + /* isConstructor */ false, + ); } - this.parseClassMethod( - classBody, - method, - isGenerator, - true, - /* isConstructor */ false, - ); } else if ( isSimple && (key.name === "get" || key.name === "set") && @@ -1069,51 +1082,73 @@ export default class StatementParser extends ExpressionParser { // `get\n*` is an uninitialized property named 'get' followed by a generator. // a getter or setter method.kind = key.name; - this.parsePropertyName(method); - if (this.isNonstaticConstructor(method)) { - this.raise(method.key.start, "Constructor can't have get/set modifier"); + // The so-called parsed name would have been "get/set": get the real name. + this.parseClassPropertyName(method); + + if (method.key.type === "PrivateName") { + // private getter/setter + this.pushClassPrivateMethod(classBody, method, false, false); + } else { + if (this.isNonstaticConstructor(method)) { + this.raise( + method.key.start, + "Constructor can't have get/set modifier", + ); + } + this.pushClassMethod( + classBody, + method, + false, + false, + /* isConstructor */ false, + ); } - this.parseClassMethod( - classBody, - method, - false, - false, - /* isConstructor */ false, - ); + this.checkGetterSetterParamCount(method); } else if (this.isLineTerminator()) { // an uninitialized class property (due to ASI, since we don't otherwise recognize the next token) - if (this.isNonstaticConstructor(prop)) { - this.raise( - prop.key.start, - "Classes may not have a non-static field named 'constructor'", - ); + if (isPrivate) { + this.pushClassPrivateProperty(classBody, prop); + } else { + this.pushClassProperty(classBody, prop); } - classBody.body.push(this.parseClassProperty(prop)); } else { this.unexpected(); } } parseClassPropertyName( - methodOrProp: N.ClassMethod | N.ClassProperty, - ): N.Expression { + methodOrProp: + | N.ClassMethod + | N.ClassProperty + | N.ClassPrivateProperty + | N.ClassPrivateMethod, + ): N.Expression | N.Identifier { const key = this.parsePropertyName(methodOrProp); + if ( !methodOrProp.computed && methodOrProp.static && - (methodOrProp.key.name === "prototype" || - methodOrProp.key.value === "prototype") + (key.name === "prototype" || key.value === "prototype") ) { this.raise( - methodOrProp.key.start, + key.start, "Classes may not have static property named prototype", ); } + + if (key.type === "PrivateName" && key.id.name === "constructor") { + this.raise( + key.start, + "Classes may not have a private field named '#constructor'", + ); + } + return key; } pushClassProperty(classBody: N.ClassBody, prop: N.ClassProperty) { + // This only affects properties, not methods. if (this.isNonstaticConstructor(prop)) { this.raise( prop.key.start, @@ -1123,6 +1158,47 @@ export default class StatementParser extends ExpressionParser { classBody.body.push(this.parseClassProperty(prop)); } + pushClassPrivateProperty(classBody: N.ClassBody, prop: N.ClassProperty) { + this.expectPlugin("classPrivateProperties", prop.key.start); + classBody.body.push(this.parseClassPrivateProperty(prop)); + } + + pushClassMethod( + classBody: N.ClassBody, + method: N.ClassMethod, + isGenerator: boolean, + isAsync: boolean, + isConstructor: boolean, + ): void { + classBody.body.push( + this.parseMethod( + method, + isGenerator, + isAsync, + isConstructor, + "ClassMethod", + ), + ); + } + + pushClassPrivateMethod( + classBody: N.ClassBody, + method: N.ClassMethod, + isGenerator: boolean, + isAsync: boolean, + ): void { + this.expectPlugin("classPrivateMethods", method.key.start); + classBody.body.push( + this.parseMethod( + method, + isGenerator, + isAsync, + /* isConstructor */ false, + "ClassPrivateMethod", + ), + ); + } + // Overridden in typescript.js parsePostMemberNameModifiers( // eslint-disable-next-line no-unused-vars @@ -1134,17 +1210,11 @@ export default class StatementParser extends ExpressionParser { return undefined; } - parsePrivateClassProperty( + parseClassPrivateProperty( node: N.ClassPrivateProperty, ): N.ClassPrivateProperty { this.state.inClassProperty = true; - - if (this.match(tt.eq)) { - this.next(); - node.value = this.parseMaybeAssign(); - } else { - node.value = null; - } + node.value = this.eat(tt.eq) ? this.parseMaybeAssign() : null; this.semicolon(); this.state.inClassProperty = false; return this.finishNode(node, "ClassPrivateProperty"); @@ -1170,24 +1240,6 @@ export default class StatementParser extends ExpressionParser { return this.finishNode(node, "ClassProperty"); } - parseClassMethod( - classBody: N.ClassBody, - method: N.ClassMethod, - isGenerator: boolean, - isAsync: boolean, - isConstructor: boolean, - ): void { - classBody.body.push( - this.parseMethod( - method, - isGenerator, - isAsync, - isConstructor, - "ClassMethod", - ), - ); - } - parseClassId( node: N.Class, isStatement: boolean, diff --git a/src/parser/util.js b/src/parser/util.js index 52587e3322..d17bad782b 100644 --- a/src/parser/util.js +++ b/src/parser/util.js @@ -110,20 +110,20 @@ export default class UtilParser extends Tokenizer { throw this.raise(pos != null ? pos : this.state.start, messageOrType); } - expectPlugin(name: string): void { + expectPlugin(name: string, pos?: ?number): void { if (!this.hasPlugin(name)) { throw this.raise( - this.state.start, + pos != null ? pos : this.state.start, `This experimental syntax requires enabling the parser plugin: '${name}'`, [name], ); } } - expectOnePlugin(names: Array): void { + expectOnePlugin(names: Array, pos?: ?number): void { if (!names.some(n => this.hasPlugin(n))) { throw this.raise( - this.state.start, + pos != null ? pos : this.state.start, `This experimental syntax requires enabling one of the following parser plugin(s): '${names.join( ", ", )}'`, diff --git a/src/plugins/estree.js b/src/plugins/estree.js index 7f227778df..8d1b151154 100644 --- a/src/plugins/estree.js +++ b/src/plugins/estree.js @@ -183,7 +183,7 @@ export default (superClass: Class): Class => delete node.directives; } - parseClassMethod( + pushClassMethod( classBody: N.ClassBody, method: N.ClassMethod, isGenerator: boolean, diff --git a/src/plugins/flow.js b/src/plugins/flow.js index 6e0bca571d..0e7b49917f 100644 --- a/src/plugins/flow.js +++ b/src/plugins/flow.js @@ -1526,7 +1526,7 @@ export default (superClass: Class): Class => } // parse type parameters for class methods - parseClassMethod( + pushClassMethod( classBody: N.ClassBody, method: N.ClassMethod, isGenerator: boolean, @@ -1541,7 +1541,7 @@ export default (superClass: Class): Class => method.typeParameters = this.flowParseTypeParameterDeclaration(); } - super.parseClassMethod( + super.pushClassMethod( classBody, method, isGenerator, @@ -1550,6 +1550,23 @@ export default (superClass: Class): Class => ); } + pushClassPrivateMethod( + classBody: N.ClassBody, + method: N.ClassPrivateMethod, + isGenerator: boolean, + isAsync: boolean, + ): void { + if (method.variance) { + this.unexpected(method.variance.start); + } + delete method.variance; + if (this.isRelational("<")) { + method.typeParameters = this.flowParseTypeParameterDeclaration(); + } + + super.pushClassPrivateMethod(classBody, method, isGenerator, isAsync); + } + // parse a the super class type parameters and implements parseClassSuper(node: N.Class): void { super.parseClassSuper(node); diff --git a/src/plugins/typescript.js b/src/plugins/typescript.js index 7d6971fa73..b4e60e5ed8 100644 --- a/src/plugins/typescript.js +++ b/src/plugins/typescript.js @@ -1639,7 +1639,7 @@ export default (superClass: Class): Class => return super.parseClassProperty(node); } - parseClassMethod( + pushClassMethod( classBody: N.ClassBody, method: N.ClassMethod, isGenerator: boolean, @@ -1648,7 +1648,7 @@ export default (superClass: Class): Class => ): void { const typeParameters = this.tsTryParseTypeParameters(); if (typeParameters) method.typeParameters = typeParameters; - super.parseClassMethod( + super.pushClassMethod( classBody, method, isGenerator, @@ -1657,6 +1657,17 @@ export default (superClass: Class): Class => ); } + pushClassPrivateMethod( + classBody: N.ClassBody, + method: N.ClassPrivateMethod, + isGenerator: boolean, + isAsync: boolean, + ): void { + const typeParameters = this.tsTryParseTypeParameters(); + if (typeParameters) method.typeParameters = typeParameters; + super.pushClassPrivateMethod(classBody, method, isGenerator, isAsync); + } + parseClassSuper(node: N.Class): void { super.parseClassSuper(node); if (node.superClass && this.isRelational("<")) { diff --git a/src/tokenizer/index.js b/src/tokenizer/index.js index f9ece03f80..aa0058e2f3 100644 --- a/src/tokenizer/index.js +++ b/src/tokenizer/index.js @@ -521,7 +521,8 @@ export default class Tokenizer extends LocationParser { switch (code) { case 35: // '#' if ( - this.hasPlugin("classPrivateProperties") && + (this.hasPlugin("classPrivateProperties") || + this.hasPlugin("classPrivateMethods")) && this.state.classLevel > 0 ) { ++this.state.pos; diff --git a/src/types.js b/src/types.js index cf6fec8c3c..dd9fe07563 100644 --- a/src/types.js +++ b/src/types.js @@ -635,6 +635,7 @@ export type ClassMemberBase = NodeBase & export type ClassMember = | ClassMethod + | ClassPrivateMethod | ClassProperty | ClassPrivateProperty | TsIndexSignature; @@ -643,6 +644,7 @@ export type MethodLike = | ObjectMethod | FunctionExpression | ClassMethod + | ClassPrivateMethod | TSDeclareMethod; export type MethodBase = FunctionBase & { @@ -664,6 +666,12 @@ export type ClassMethod = MethodBase & variance?: ?FlowVariance, // TODO: Not in spec }; +export type ClassPrivateMethod = NodeBase & + ClassMethodOrDeclareMethodCommon & { + type: "ClassPrivateMethod", + key: PrivateName, + }; + export type ClassProperty = ClassMemberBase & { type: "ClassProperty", key: Expression, @@ -678,7 +686,7 @@ export type ClassProperty = ClassMemberBase & { export type ClassPrivateProperty = NodeBase & { type: "ClassPrivateProperty", - key: Identifier, + key: PrivateName, value: ?Expression, // TODO: Not in spec that this is nullable. static: boolean, }; diff --git a/test/fixtures/es2015/class-methods/disallow-computed-async/actual.js b/test/fixtures/es2015/class-methods/disallow-computed-async/actual.js new file mode 100644 index 0000000000..32f69e4477 --- /dev/null +++ b/test/fixtures/es2015/class-methods/disallow-computed-async/actual.js @@ -0,0 +1,3 @@ +class A { + ["async"] a() {} +} diff --git a/test/fixtures/es2015/class-methods/disallow-computed-async/options.json b/test/fixtures/es2015/class-methods/disallow-computed-async/options.json new file mode 100644 index 0000000000..9f8cd12d30 --- /dev/null +++ b/test/fixtures/es2015/class-methods/disallow-computed-async/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Unexpected token (2:12)" +} diff --git a/test/fixtures/es2015/class-methods/disallow-computed-get/actual.js b/test/fixtures/es2015/class-methods/disallow-computed-get/actual.js new file mode 100644 index 0000000000..e6bc2fed10 --- /dev/null +++ b/test/fixtures/es2015/class-methods/disallow-computed-get/actual.js @@ -0,0 +1,3 @@ +class A { + ["get"] a() {} +} diff --git a/test/fixtures/es2015/class-methods/disallow-computed-get/options.json b/test/fixtures/es2015/class-methods/disallow-computed-get/options.json new file mode 100644 index 0000000000..7c05159f45 --- /dev/null +++ b/test/fixtures/es2015/class-methods/disallow-computed-get/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Unexpected token (2:10)" +} diff --git a/test/fixtures/es2015/class-methods/disallow-literal-async/actual.js b/test/fixtures/es2015/class-methods/disallow-literal-async/actual.js new file mode 100644 index 0000000000..1d67eb8875 --- /dev/null +++ b/test/fixtures/es2015/class-methods/disallow-literal-async/actual.js @@ -0,0 +1,3 @@ +class A { + "async" a() {} +} diff --git a/test/fixtures/es2015/class-methods/disallow-literal-async/options.json b/test/fixtures/es2015/class-methods/disallow-literal-async/options.json new file mode 100644 index 0000000000..7c05159f45 --- /dev/null +++ b/test/fixtures/es2015/class-methods/disallow-literal-async/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Unexpected token (2:10)" +} diff --git a/test/fixtures/es2015/class-methods/disallow-literal-get/actual.js b/test/fixtures/es2015/class-methods/disallow-literal-get/actual.js new file mode 100644 index 0000000000..d478ee909f --- /dev/null +++ b/test/fixtures/es2015/class-methods/disallow-literal-get/actual.js @@ -0,0 +1,3 @@ +class A { + "get" a() {} +} diff --git a/test/fixtures/es2015/class-methods/disallow-literal-get/options.json b/test/fixtures/es2015/class-methods/disallow-literal-get/options.json new file mode 100644 index 0000000000..ef2b7c682f --- /dev/null +++ b/test/fixtures/es2015/class-methods/disallow-literal-get/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Unexpected token (2:8)" +} diff --git a/test/fixtures/es2015/class-methods/tricky-names/actual.js b/test/fixtures/es2015/class-methods/tricky-names/actual.js index 35e8ddeefe..6aa4cc2979 100644 --- a/test/fixtures/es2015/class-methods/tricky-names/actual.js +++ b/test/fixtures/es2015/class-methods/tricky-names/actual.js @@ -12,6 +12,16 @@ class A { () {} + 'get' + () {} + + 'set' + () {} + + 'async' + () {} + + static get () {} @@ -42,4 +52,4 @@ class A { get static () {} -} \ No newline at end of file +} diff --git a/test/fixtures/es2015/class-methods/tricky-names/expected.json b/test/fixtures/es2015/class-methods/tricky-names/expected.json index 5a167e4d71..1e9e3bb027 100644 --- a/test/fixtures/es2015/class-methods/tricky-names/expected.json +++ b/test/fixtures/es2015/class-methods/tricky-names/expected.json @@ -1,28 +1,28 @@ { "type": "File", "start": 0, - "end": 257, + "end": 311, "loc": { "start": { "line": 1, "column": 0 }, "end": { - "line": 45, + "line": 55, "column": 1 } }, "program": { "type": "Program", "start": 0, - "end": 257, + "end": 311, "loc": { "start": { "line": 1, "column": 0 }, "end": { - "line": 45, + "line": 55, "column": 1 } }, @@ -31,14 +31,14 @@ { "type": "ClassDeclaration", "start": 0, - "end": 257, + "end": 311, "loc": { "start": { "line": 1, "column": 0 }, "end": { - "line": 45, + "line": 55, "column": 1 } }, @@ -63,14 +63,14 @@ "body": { "type": "ClassBody", "start": 8, - "end": 257, + "end": 311, "loc": { "start": { "line": 1, "column": 8 }, "end": { - "line": 45, + "line": 55, "column": 1 } }, @@ -90,7 +90,6 @@ } }, "static": false, - "computed": false, "key": { "type": "Identifier", "start": 12, @@ -108,6 +107,7 @@ }, "name": "get" }, + "computed": false, "kind": "method", "id": null, "generator": false, @@ -147,7 +147,6 @@ } }, "static": false, - "computed": false, "key": { "type": "Identifier", "start": 27, @@ -165,6 +164,7 @@ }, "name": "set" }, + "computed": false, "kind": "method", "id": null, "generator": false, @@ -203,7 +203,6 @@ "column": 7 } }, - "static": false, "kind": "method", "computed": false, "key": { @@ -223,6 +222,7 @@ }, "name": "static" }, + "static": false, "id": null, "generator": false, "expression": false, @@ -261,7 +261,6 @@ } }, "static": false, - "computed": false, "key": { "type": "Identifier", "start": 60, @@ -279,6 +278,7 @@ }, "name": "async" }, + "computed": false, "kind": "method", "id": null, "generator": false, @@ -306,36 +306,216 @@ { "type": "ClassMethod", "start": 78, - "end": 98, + "end": 91, "loc": { "start": { "line": 15, "column": 2 }, "end": { - "line": 17, + "line": 16, "column": 7 } }, - "static": true, + "static": false, + "key": { + "type": "StringLiteral", + "start": 78, + "end": 83, + "loc": { + "start": { + "line": 15, + "column": 2 + }, + "end": { + "line": 15, + "column": 7 + } + }, + "extra": { + "rawValue": "get", + "raw": "'get'" + }, + "value": "get" + }, + "computed": false, + "kind": "method", + "id": null, + "generator": false, + "expression": false, + "async": false, + "params": [], + "body": { + "type": "BlockStatement", + "start": 89, + "end": 91, + "loc": { + "start": { + "line": 16, + "column": 5 + }, + "end": { + "line": 16, + "column": 7 + } + }, + "body": [], + "directives": [] + } + }, + { + "type": "ClassMethod", + "start": 95, + "end": 108, + "loc": { + "start": { + "line": 18, + "column": 2 + }, + "end": { + "line": 19, + "column": 7 + } + }, + "static": false, + "key": { + "type": "StringLiteral", + "start": 95, + "end": 100, + "loc": { + "start": { + "line": 18, + "column": 2 + }, + "end": { + "line": 18, + "column": 7 + } + }, + "extra": { + "rawValue": "set", + "raw": "'set'" + }, + "value": "set" + }, + "computed": false, + "kind": "method", + "id": null, + "generator": false, + "expression": false, + "async": false, + "params": [], + "body": { + "type": "BlockStatement", + "start": 106, + "end": 108, + "loc": { + "start": { + "line": 19, + "column": 5 + }, + "end": { + "line": 19, + "column": 7 + } + }, + "body": [], + "directives": [] + } + }, + { + "type": "ClassMethod", + "start": 112, + "end": 127, + "loc": { + "start": { + "line": 21, + "column": 2 + }, + "end": { + "line": 22, + "column": 7 + } + }, + "static": false, + "key": { + "type": "StringLiteral", + "start": 112, + "end": 119, + "loc": { + "start": { + "line": 21, + "column": 2 + }, + "end": { + "line": 21, + "column": 9 + } + }, + "extra": { + "rawValue": "async", + "raw": "'async'" + }, + "value": "async" + }, "computed": false, + "kind": "method", + "id": null, + "generator": false, + "expression": false, + "async": false, + "params": [], + "body": { + "type": "BlockStatement", + "start": 125, + "end": 127, + "loc": { + "start": { + "line": 22, + "column": 5 + }, + "end": { + "line": 22, + "column": 7 + } + }, + "body": [], + "directives": [] + } + }, + { + "type": "ClassMethod", + "start": 132, + "end": 152, + "loc": { + "start": { + "line": 25, + "column": 2 + }, + "end": { + "line": 27, + "column": 7 + } + }, + "static": true, "key": { "type": "Identifier", - "start": 87, - "end": 90, + "start": 141, + "end": 144, "loc": { "start": { - "line": 16, + "line": 26, "column": 2 }, "end": { - "line": 16, + "line": 26, "column": 5 }, "identifierName": "get" }, "name": "get" }, + "computed": false, "kind": "method", "id": null, "generator": false, @@ -344,15 +524,15 @@ "params": [], "body": { "type": "BlockStatement", - "start": 96, - "end": 98, + "start": 150, + "end": 152, "loc": { "start": { - "line": 17, + "line": 27, "column": 5 }, "end": { - "line": 17, + "line": 27, "column": 7 } }, @@ -362,37 +542,37 @@ }, { "type": "ClassMethod", - "start": 102, - "end": 122, + "start": 156, + "end": 176, "loc": { "start": { - "line": 19, + "line": 29, "column": 2 }, "end": { - "line": 21, + "line": 31, "column": 7 } }, "static": true, - "computed": false, "key": { "type": "Identifier", - "start": 111, - "end": 114, + "start": 165, + "end": 168, "loc": { "start": { - "line": 20, + "line": 30, "column": 2 }, "end": { - "line": 20, + "line": 30, "column": 5 }, "identifierName": "set" }, "name": "set" }, + "computed": false, "kind": "method", "id": null, "generator": false, @@ -401,15 +581,15 @@ "params": [], "body": { "type": "BlockStatement", - "start": 120, - "end": 122, + "start": 174, + "end": 176, "loc": { "start": { - "line": 21, + "line": 31, "column": 5 }, "end": { - "line": 21, + "line": 31, "column": 7 } }, @@ -419,37 +599,37 @@ }, { "type": "ClassMethod", - "start": 126, - "end": 149, + "start": 180, + "end": 203, "loc": { "start": { - "line": 23, + "line": 33, "column": 2 }, "end": { - "line": 25, + "line": 35, "column": 7 } }, "static": true, - "computed": false, "key": { "type": "Identifier", - "start": 135, - "end": 141, + "start": 189, + "end": 195, "loc": { "start": { - "line": 24, + "line": 34, "column": 2 }, "end": { - "line": 24, + "line": 34, "column": 8 }, "identifierName": "static" }, "name": "static" }, + "computed": false, "kind": "method", "id": null, "generator": false, @@ -458,15 +638,15 @@ "params": [], "body": { "type": "BlockStatement", - "start": 147, - "end": 149, + "start": 201, + "end": 203, "loc": { "start": { - "line": 25, + "line": 35, "column": 5 }, "end": { - "line": 25, + "line": 35, "column": 7 } }, @@ -476,37 +656,37 @@ }, { "type": "ClassMethod", - "start": 153, - "end": 175, + "start": 207, + "end": 229, "loc": { "start": { - "line": 27, + "line": 37, "column": 2 }, "end": { - "line": 29, + "line": 39, "column": 7 } }, "static": true, - "computed": false, "key": { "type": "Identifier", - "start": 162, - "end": 167, + "start": 216, + "end": 221, "loc": { "start": { - "line": 28, + "line": 38, "column": 2 }, "end": { - "line": 28, + "line": 38, "column": 7 }, "identifierName": "async" }, "name": "async" }, + "computed": false, "kind": "method", "id": null, "generator": false, @@ -515,15 +695,15 @@ "params": [], "body": { "type": "BlockStatement", - "start": 173, - "end": 175, + "start": 227, + "end": 229, "loc": { "start": { - "line": 29, + "line": 39, "column": 5 }, "end": { - "line": 29, + "line": 39, "column": 7 } }, @@ -533,37 +713,37 @@ }, { "type": "ClassMethod", - "start": 179, - "end": 197, + "start": 233, + "end": 251, "loc": { "start": { - "line": 31, + "line": 41, "column": 2 }, "end": { - "line": 33, + "line": 43, "column": 7 } }, "static": true, - "computed": false, "key": { "type": "Identifier", - "start": 188, - "end": 189, + "start": 242, + "end": 243, "loc": { "start": { - "line": 32, + "line": 42, "column": 2 }, "end": { - "line": 32, + "line": 42, "column": 3 }, "identifierName": "a" }, "name": "a" }, + "computed": false, "kind": "method", "id": null, "generator": false, @@ -572,15 +752,15 @@ "params": [], "body": { "type": "BlockStatement", - "start": 195, - "end": 197, + "start": 249, + "end": 251, "loc": { "start": { - "line": 33, + "line": 43, "column": 5 }, "end": { - "line": 33, + "line": 43, "column": 7 } }, @@ -590,37 +770,37 @@ }, { "type": "ClassMethod", - "start": 202, - "end": 221, + "start": 256, + "end": 275, "loc": { "start": { - "line": 36, + "line": 46, "column": 2 }, "end": { - "line": 38, + "line": 48, "column": 7 } }, "static": false, - "computed": false, "key": { "type": "Identifier", - "start": 208, - "end": 213, + "start": 262, + "end": 267, "loc": { "start": { - "line": 37, + "line": 47, "column": 2 }, "end": { - "line": 37, + "line": 47, "column": 7 }, "identifierName": "async" }, "name": "async" }, + "computed": false, "kind": "get", "id": null, "generator": false, @@ -629,15 +809,15 @@ "params": [], "body": { "type": "BlockStatement", - "start": 219, - "end": 221, + "start": 273, + "end": 275, "loc": { "start": { - "line": 38, + "line": 48, "column": 5 }, "end": { - "line": 38, + "line": 48, "column": 7 } }, @@ -647,37 +827,37 @@ }, { "type": "ClassMethod", - "start": 226, - "end": 255, + "start": 280, + "end": 309, "loc": { "start": { - "line": 41, + "line": 51, "column": 2 }, "end": { - "line": 44, + "line": 54, "column": 7 } }, "static": true, - "computed": false, "key": { "type": "Identifier", - "start": 241, - "end": 247, + "start": 295, + "end": 301, "loc": { "start": { - "line": 43, + "line": 53, "column": 2 }, "end": { - "line": 43, + "line": 53, "column": 8 }, "identifierName": "static" }, "name": "static" }, + "computed": false, "kind": "get", "id": null, "generator": false, @@ -686,15 +866,15 @@ "params": [], "body": { "type": "BlockStatement", - "start": 253, - "end": 255, + "start": 307, + "end": 309, "loc": { "start": { - "line": 44, + "line": 54, "column": 5 }, "end": { - "line": 44, + "line": 54, "column": 7 } }, diff --git a/test/fixtures/experimental/class-private-methods/asi-failure-generator/actual.js b/test/fixtures/experimental/class-private-methods/asi-failure-generator/actual.js new file mode 100644 index 0000000000..4009ed9590 --- /dev/null +++ b/test/fixtures/experimental/class-private-methods/asi-failure-generator/actual.js @@ -0,0 +1,4 @@ +class Foo { + p = x + *#m () {} +} diff --git a/test/fixtures/experimental/class-private-methods/asi-failure-generator/options.json b/test/fixtures/experimental/class-private-methods/asi-failure-generator/options.json new file mode 100644 index 0000000000..6fa0f15832 --- /dev/null +++ b/test/fixtures/experimental/class-private-methods/asi-failure-generator/options.json @@ -0,0 +1,4 @@ +{ + "throws": "Unexpected token (3:3)", + "plugins": ["classProperties", "classPrivateMethods"] +} diff --git a/test/fixtures/experimental/class-private-methods/async-generator/actual.js b/test/fixtures/experimental/class-private-methods/async-generator/actual.js new file mode 100644 index 0000000000..c04e90e7a3 --- /dev/null +++ b/test/fixtures/experimental/class-private-methods/async-generator/actual.js @@ -0,0 +1,13 @@ +class Foo { + async* #readLines(path) { + let file = await fileOpen(path); + + try { + while (!file.EOF) { + yield await file.readLine(); + } + } finally { + await file.close(); + } + } +} diff --git a/test/fixtures/experimental/class-private-methods/async-generator/expected.json b/test/fixtures/experimental/class-private-methods/async-generator/expected.json new file mode 100644 index 0000000000..a222170f1b --- /dev/null +++ b/test/fixtures/experimental/class-private-methods/async-generator/expected.json @@ -0,0 +1,655 @@ +{ + "type": "File", + "start": 0, + "end": 212, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 13, + "column": 1 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 212, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 13, + "column": 1 + } + }, + "sourceType": "script", + "body": [ + { + "type": "ClassDeclaration", + "start": 0, + "end": 212, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 13, + "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": 212, + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 13, + "column": 1 + } + }, + "body": [ + { + "type": "ClassPrivateMethod", + "start": 14, + "end": 210, + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 12, + "column": 3 + } + }, + "static": false, + "key": { + "type": "PrivateName", + "start": 22, + "end": 31, + "loc": { + "start": { + "line": 2, + "column": 10 + }, + "end": { + "line": 2, + "column": 19 + } + }, + "id": { + "type": "Identifier", + "start": 22, + "end": 31, + "loc": { + "start": { + "line": 2, + "column": 10 + }, + "end": { + "line": 2, + "column": 19 + }, + "identifierName": "readLines" + }, + "name": "readLines" + } + }, + "computed": false, + "kind": "method", + "id": null, + "generator": true, + "expression": false, + "async": true, + "params": [ + { + "type": "Identifier", + "start": 32, + "end": 36, + "loc": { + "start": { + "line": 2, + "column": 20 + }, + "end": { + "line": 2, + "column": 24 + }, + "identifierName": "path" + }, + "name": "path" + } + ], + "body": { + "type": "BlockStatement", + "start": 38, + "end": 210, + "loc": { + "start": { + "line": 2, + "column": 26 + }, + "end": { + "line": 12, + "column": 3 + } + }, + "body": [ + { + "type": "VariableDeclaration", + "start": 44, + "end": 76, + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 3, + "column": 36 + } + }, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 48, + "end": 75, + "loc": { + "start": { + "line": 3, + "column": 8 + }, + "end": { + "line": 3, + "column": 35 + } + }, + "id": { + "type": "Identifier", + "start": 48, + "end": 52, + "loc": { + "start": { + "line": 3, + "column": 8 + }, + "end": { + "line": 3, + "column": 12 + }, + "identifierName": "file" + }, + "name": "file" + }, + "init": { + "type": "AwaitExpression", + "start": 55, + "end": 75, + "loc": { + "start": { + "line": 3, + "column": 15 + }, + "end": { + "line": 3, + "column": 35 + } + }, + "argument": { + "type": "CallExpression", + "start": 61, + "end": 75, + "loc": { + "start": { + "line": 3, + "column": 21 + }, + "end": { + "line": 3, + "column": 35 + } + }, + "callee": { + "type": "Identifier", + "start": 61, + "end": 69, + "loc": { + "start": { + "line": 3, + "column": 21 + }, + "end": { + "line": 3, + "column": 29 + }, + "identifierName": "fileOpen" + }, + "name": "fileOpen" + }, + "arguments": [ + { + "type": "Identifier", + "start": 70, + "end": 74, + "loc": { + "start": { + "line": 3, + "column": 30 + }, + "end": { + "line": 3, + "column": 34 + }, + "identifierName": "path" + }, + "name": "path" + } + ] + } + } + } + ], + "kind": "let" + }, + { + "type": "TryStatement", + "start": 82, + "end": 206, + "loc": { + "start": { + "line": 5, + "column": 4 + }, + "end": { + "line": 11, + "column": 5 + } + }, + "block": { + "type": "BlockStatement", + "start": 86, + "end": 164, + "loc": { + "start": { + "line": 5, + "column": 8 + }, + "end": { + "line": 9, + "column": 5 + } + }, + "body": [ + { + "type": "WhileStatement", + "start": 94, + "end": 158, + "loc": { + "start": { + "line": 6, + "column": 6 + }, + "end": { + "line": 8, + "column": 7 + } + }, + "test": { + "type": "UnaryExpression", + "start": 101, + "end": 110, + "loc": { + "start": { + "line": 6, + "column": 13 + }, + "end": { + "line": 6, + "column": 22 + } + }, + "operator": "!", + "prefix": true, + "argument": { + "type": "MemberExpression", + "start": 102, + "end": 110, + "loc": { + "start": { + "line": 6, + "column": 14 + }, + "end": { + "line": 6, + "column": 22 + } + }, + "object": { + "type": "Identifier", + "start": 102, + "end": 106, + "loc": { + "start": { + "line": 6, + "column": 14 + }, + "end": { + "line": 6, + "column": 18 + }, + "identifierName": "file" + }, + "name": "file" + }, + "property": { + "type": "Identifier", + "start": 107, + "end": 110, + "loc": { + "start": { + "line": 6, + "column": 19 + }, + "end": { + "line": 6, + "column": 22 + }, + "identifierName": "EOF" + }, + "name": "EOF" + }, + "computed": false + }, + "extra": { + "parenthesizedArgument": false + } + }, + "body": { + "type": "BlockStatement", + "start": 112, + "end": 158, + "loc": { + "start": { + "line": 6, + "column": 24 + }, + "end": { + "line": 8, + "column": 7 + } + }, + "body": [ + { + "type": "ExpressionStatement", + "start": 122, + "end": 150, + "loc": { + "start": { + "line": 7, + "column": 8 + }, + "end": { + "line": 7, + "column": 36 + } + }, + "expression": { + "type": "YieldExpression", + "start": 122, + "end": 149, + "loc": { + "start": { + "line": 7, + "column": 8 + }, + "end": { + "line": 7, + "column": 35 + } + }, + "delegate": false, + "argument": { + "type": "AwaitExpression", + "start": 128, + "end": 149, + "loc": { + "start": { + "line": 7, + "column": 14 + }, + "end": { + "line": 7, + "column": 35 + } + }, + "argument": { + "type": "CallExpression", + "start": 134, + "end": 149, + "loc": { + "start": { + "line": 7, + "column": 20 + }, + "end": { + "line": 7, + "column": 35 + } + }, + "callee": { + "type": "MemberExpression", + "start": 134, + "end": 147, + "loc": { + "start": { + "line": 7, + "column": 20 + }, + "end": { + "line": 7, + "column": 33 + } + }, + "object": { + "type": "Identifier", + "start": 134, + "end": 138, + "loc": { + "start": { + "line": 7, + "column": 20 + }, + "end": { + "line": 7, + "column": 24 + }, + "identifierName": "file" + }, + "name": "file" + }, + "property": { + "type": "Identifier", + "start": 139, + "end": 147, + "loc": { + "start": { + "line": 7, + "column": 25 + }, + "end": { + "line": 7, + "column": 33 + }, + "identifierName": "readLine" + }, + "name": "readLine" + }, + "computed": false + }, + "arguments": [] + } + } + } + } + ], + "directives": [] + } + } + ], + "directives": [] + }, + "handler": null, + "guardedHandlers": [], + "finalizer": { + "type": "BlockStatement", + "start": 173, + "end": 206, + "loc": { + "start": { + "line": 9, + "column": 14 + }, + "end": { + "line": 11, + "column": 5 + } + }, + "body": [ + { + "type": "ExpressionStatement", + "start": 181, + "end": 200, + "loc": { + "start": { + "line": 10, + "column": 6 + }, + "end": { + "line": 10, + "column": 25 + } + }, + "expression": { + "type": "AwaitExpression", + "start": 181, + "end": 199, + "loc": { + "start": { + "line": 10, + "column": 6 + }, + "end": { + "line": 10, + "column": 24 + } + }, + "argument": { + "type": "CallExpression", + "start": 187, + "end": 199, + "loc": { + "start": { + "line": 10, + "column": 12 + }, + "end": { + "line": 10, + "column": 24 + } + }, + "callee": { + "type": "MemberExpression", + "start": 187, + "end": 197, + "loc": { + "start": { + "line": 10, + "column": 12 + }, + "end": { + "line": 10, + "column": 22 + } + }, + "object": { + "type": "Identifier", + "start": 187, + "end": 191, + "loc": { + "start": { + "line": 10, + "column": 12 + }, + "end": { + "line": 10, + "column": 16 + }, + "identifierName": "file" + }, + "name": "file" + }, + "property": { + "type": "Identifier", + "start": 192, + "end": 197, + "loc": { + "start": { + "line": 10, + "column": 17 + }, + "end": { + "line": 10, + "column": 22 + }, + "identifierName": "close" + }, + "name": "close" + }, + "computed": false + }, + "arguments": [] + } + } + } + ], + "directives": [] + } + } + ], + "directives": [] + } + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/test/fixtures/experimental/class-private-methods/async-generator/options.json b/test/fixtures/experimental/class-private-methods/async-generator/options.json new file mode 100644 index 0000000000..14952c9423 --- /dev/null +++ b/test/fixtures/experimental/class-private-methods/async-generator/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["classProperties", "classPrivateMethods", "asyncGenerators"] +} diff --git a/test/fixtures/experimental/class-private-methods/async/actual.js b/test/fixtures/experimental/class-private-methods/async/actual.js new file mode 100644 index 0000000000..4d4bc0cb2a --- /dev/null +++ b/test/fixtures/experimental/class-private-methods/async/actual.js @@ -0,0 +1,5 @@ +class Hotel { + async #evil() { + await notReally(); + } +} diff --git a/test/fixtures/experimental/class-private-methods/async/expected.json b/test/fixtures/experimental/class-private-methods/async/expected.json new file mode 100644 index 0000000000..434f6f5b98 --- /dev/null +++ b/test/fixtures/experimental/class-private-methods/async/expected.json @@ -0,0 +1,220 @@ +{ + "type": "File", + "start": 0, + "end": 60, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 5, + "column": 1 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 60, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 5, + "column": 1 + } + }, + "sourceType": "script", + "body": [ + { + "type": "ClassDeclaration", + "start": 0, + "end": 60, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 5, + "column": 1 + } + }, + "id": { + "type": "Identifier", + "start": 6, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 6 + }, + "end": { + "line": 1, + "column": 11 + }, + "identifierName": "Hotel" + }, + "name": "Hotel" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start": 12, + "end": 60, + "loc": { + "start": { + "line": 1, + "column": 12 + }, + "end": { + "line": 5, + "column": 1 + } + }, + "body": [ + { + "type": "ClassPrivateMethod", + "start": 16, + "end": 58, + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 4, + "column": 3 + } + }, + "static": false, + "key": { + "type": "PrivateName", + "start": 23, + "end": 27, + "loc": { + "start": { + "line": 2, + "column": 9 + }, + "end": { + "line": 2, + "column": 13 + } + }, + "id": { + "type": "Identifier", + "start": 23, + "end": 27, + "loc": { + "start": { + "line": 2, + "column": 9 + }, + "end": { + "line": 2, + "column": 13 + }, + "identifierName": "evil" + }, + "name": "evil" + } + }, + "computed": false, + "kind": "method", + "id": null, + "generator": false, + "expression": false, + "async": true, + "params": [], + "body": { + "type": "BlockStatement", + "start": 30, + "end": 58, + "loc": { + "start": { + "line": 2, + "column": 16 + }, + "end": { + "line": 4, + "column": 3 + } + }, + "body": [ + { + "type": "ExpressionStatement", + "start": 36, + "end": 54, + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 3, + "column": 22 + } + }, + "expression": { + "type": "AwaitExpression", + "start": 36, + "end": 53, + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 3, + "column": 21 + } + }, + "argument": { + "type": "CallExpression", + "start": 42, + "end": 53, + "loc": { + "start": { + "line": 3, + "column": 10 + }, + "end": { + "line": 3, + "column": 21 + } + }, + "callee": { + "type": "Identifier", + "start": 42, + "end": 51, + "loc": { + "start": { + "line": 3, + "column": 10 + }, + "end": { + "line": 3, + "column": 19 + }, + "identifierName": "notReally" + }, + "name": "notReally" + }, + "arguments": [] + } + } + } + ], + "directives": [] + } + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/test/fixtures/experimental/class-private-methods/async/options.json b/test/fixtures/experimental/class-private-methods/async/options.json new file mode 100644 index 0000000000..aedb66f739 --- /dev/null +++ b/test/fixtures/experimental/class-private-methods/async/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["classProperties", "classPrivateMethods"] +} diff --git a/test/fixtures/experimental/class-private-methods/combined/actual.js b/test/fixtures/experimental/class-private-methods/combined/actual.js new file mode 100644 index 0000000000..41843455f5 --- /dev/null +++ b/test/fixtures/experimental/class-private-methods/combined/actual.js @@ -0,0 +1,16 @@ +class Foo { + a = 1; + + *#a() { + yield bar(); + } + + #b = 2; + + get b() { return 9999; } + set #c(x) { return x; } + + #d() { + return Math.random(); + } +} diff --git a/test/fixtures/experimental/class-private-methods/combined/expected.json b/test/fixtures/experimental/class-private-methods/combined/expected.json new file mode 100644 index 0000000000..c46bfafaf5 --- /dev/null +++ b/test/fixtures/experimental/class-private-methods/combined/expected.json @@ -0,0 +1,711 @@ +{ + "type": "File", + "start": 0, + "end": 159, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 16, + "column": 1 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 159, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 16, + "column": 1 + } + }, + "sourceType": "script", + "body": [ + { + "type": "ClassDeclaration", + "start": 0, + "end": 159, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 16, + "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": 159, + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 16, + "column": 1 + } + }, + "body": [ + { + "type": "ClassProperty", + "start": 14, + "end": 20, + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 2, + "column": 8 + } + }, + "static": false, + "key": { + "type": "Identifier", + "start": 14, + "end": 15, + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 2, + "column": 3 + }, + "identifierName": "a" + }, + "name": "a" + }, + "computed": false, + "value": { + "type": "NumericLiteral", + "start": 18, + "end": 19, + "loc": { + "start": { + "line": 2, + "column": 6 + }, + "end": { + "line": 2, + "column": 7 + } + }, + "extra": { + "rawValue": 1, + "raw": "1" + }, + "value": 1 + } + }, + { + "type": "ClassPrivateMethod", + "start": 24, + "end": 52, + "loc": { + "start": { + "line": 4, + "column": 2 + }, + "end": { + "line": 6, + "column": 3 + } + }, + "static": false, + "kind": "method", + "key": { + "type": "PrivateName", + "start": 26, + "end": 27, + "loc": { + "start": { + "line": 4, + "column": 4 + }, + "end": { + "line": 4, + "column": 5 + } + }, + "id": { + "type": "Identifier", + "start": 26, + "end": 27, + "loc": { + "start": { + "line": 4, + "column": 4 + }, + "end": { + "line": 4, + "column": 5 + }, + "identifierName": "a" + }, + "name": "a" + } + }, + "id": null, + "generator": true, + "expression": false, + "async": false, + "params": [], + "body": { + "type": "BlockStatement", + "start": 30, + "end": 52, + "loc": { + "start": { + "line": 4, + "column": 8 + }, + "end": { + "line": 6, + "column": 3 + } + }, + "body": [ + { + "type": "ExpressionStatement", + "start": 36, + "end": 48, + "loc": { + "start": { + "line": 5, + "column": 4 + }, + "end": { + "line": 5, + "column": 16 + } + }, + "expression": { + "type": "YieldExpression", + "start": 36, + "end": 47, + "loc": { + "start": { + "line": 5, + "column": 4 + }, + "end": { + "line": 5, + "column": 15 + } + }, + "delegate": false, + "argument": { + "type": "CallExpression", + "start": 42, + "end": 47, + "loc": { + "start": { + "line": 5, + "column": 10 + }, + "end": { + "line": 5, + "column": 15 + } + }, + "callee": { + "type": "Identifier", + "start": 42, + "end": 45, + "loc": { + "start": { + "line": 5, + "column": 10 + }, + "end": { + "line": 5, + "column": 13 + }, + "identifierName": "bar" + }, + "name": "bar" + }, + "arguments": [] + } + } + } + ], + "directives": [] + } + }, + { + "type": "ClassPrivateProperty", + "start": 56, + "end": 63, + "loc": { + "start": { + "line": 8, + "column": 2 + }, + "end": { + "line": 8, + "column": 9 + } + }, + "static": false, + "key": { + "type": "PrivateName", + "start": 57, + "end": 58, + "loc": { + "start": { + "line": 8, + "column": 3 + }, + "end": { + "line": 8, + "column": 4 + } + }, + "id": { + "type": "Identifier", + "start": 57, + "end": 58, + "loc": { + "start": { + "line": 8, + "column": 3 + }, + "end": { + "line": 8, + "column": 4 + }, + "identifierName": "b" + }, + "name": "b" + } + }, + "value": { + "type": "NumericLiteral", + "start": 61, + "end": 62, + "loc": { + "start": { + "line": 8, + "column": 7 + }, + "end": { + "line": 8, + "column": 8 + } + }, + "extra": { + "rawValue": 2, + "raw": "2" + }, + "value": 2 + } + }, + { + "type": "ClassMethod", + "start": 67, + "end": 91, + "loc": { + "start": { + "line": 10, + "column": 2 + }, + "end": { + "line": 10, + "column": 26 + } + }, + "static": false, + "key": { + "type": "Identifier", + "start": 71, + "end": 72, + "loc": { + "start": { + "line": 10, + "column": 6 + }, + "end": { + "line": 10, + "column": 7 + }, + "identifierName": "b" + }, + "name": "b" + }, + "computed": false, + "kind": "get", + "id": null, + "generator": false, + "expression": false, + "async": false, + "params": [], + "body": { + "type": "BlockStatement", + "start": 75, + "end": 91, + "loc": { + "start": { + "line": 10, + "column": 10 + }, + "end": { + "line": 10, + "column": 26 + } + }, + "body": [ + { + "type": "ReturnStatement", + "start": 77, + "end": 89, + "loc": { + "start": { + "line": 10, + "column": 12 + }, + "end": { + "line": 10, + "column": 24 + } + }, + "argument": { + "type": "NumericLiteral", + "start": 84, + "end": 88, + "loc": { + "start": { + "line": 10, + "column": 19 + }, + "end": { + "line": 10, + "column": 23 + } + }, + "extra": { + "rawValue": 9999, + "raw": "9999" + }, + "value": 9999 + } + } + ], + "directives": [] + } + }, + { + "type": "ClassPrivateMethod", + "start": 94, + "end": 117, + "loc": { + "start": { + "line": 11, + "column": 2 + }, + "end": { + "line": 11, + "column": 25 + } + }, + "static": false, + "key": { + "type": "PrivateName", + "start": 99, + "end": 100, + "loc": { + "start": { + "line": 11, + "column": 7 + }, + "end": { + "line": 11, + "column": 8 + } + }, + "id": { + "type": "Identifier", + "start": 99, + "end": 100, + "loc": { + "start": { + "line": 11, + "column": 7 + }, + "end": { + "line": 11, + "column": 8 + }, + "identifierName": "c" + }, + "name": "c" + } + }, + "computed": false, + "kind": "set", + "id": null, + "generator": false, + "expression": false, + "async": false, + "params": [ + { + "type": "Identifier", + "start": 101, + "end": 102, + "loc": { + "start": { + "line": 11, + "column": 9 + }, + "end": { + "line": 11, + "column": 10 + }, + "identifierName": "x" + }, + "name": "x" + } + ], + "body": { + "type": "BlockStatement", + "start": 104, + "end": 117, + "loc": { + "start": { + "line": 11, + "column": 12 + }, + "end": { + "line": 11, + "column": 25 + } + }, + "body": [ + { + "type": "ReturnStatement", + "start": 106, + "end": 115, + "loc": { + "start": { + "line": 11, + "column": 14 + }, + "end": { + "line": 11, + "column": 23 + } + }, + "argument": { + "type": "Identifier", + "start": 113, + "end": 114, + "loc": { + "start": { + "line": 11, + "column": 21 + }, + "end": { + "line": 11, + "column": 22 + }, + "identifierName": "x" + }, + "name": "x" + } + } + ], + "directives": [] + } + }, + { + "type": "ClassPrivateMethod", + "start": 121, + "end": 157, + "loc": { + "start": { + "line": 13, + "column": 2 + }, + "end": { + "line": 15, + "column": 3 + } + }, + "static": false, + "key": { + "type": "PrivateName", + "start": 122, + "end": 123, + "loc": { + "start": { + "line": 13, + "column": 3 + }, + "end": { + "line": 13, + "column": 4 + } + }, + "id": { + "type": "Identifier", + "start": 122, + "end": 123, + "loc": { + "start": { + "line": 13, + "column": 3 + }, + "end": { + "line": 13, + "column": 4 + }, + "identifierName": "d" + }, + "name": "d" + } + }, + "kind": "method", + "id": null, + "generator": false, + "expression": false, + "async": false, + "params": [], + "body": { + "type": "BlockStatement", + "start": 126, + "end": 157, + "loc": { + "start": { + "line": 13, + "column": 7 + }, + "end": { + "line": 15, + "column": 3 + } + }, + "body": [ + { + "type": "ReturnStatement", + "start": 132, + "end": 153, + "loc": { + "start": { + "line": 14, + "column": 4 + }, + "end": { + "line": 14, + "column": 25 + } + }, + "argument": { + "type": "CallExpression", + "start": 139, + "end": 152, + "loc": { + "start": { + "line": 14, + "column": 11 + }, + "end": { + "line": 14, + "column": 24 + } + }, + "callee": { + "type": "MemberExpression", + "start": 139, + "end": 150, + "loc": { + "start": { + "line": 14, + "column": 11 + }, + "end": { + "line": 14, + "column": 22 + } + }, + "object": { + "type": "Identifier", + "start": 139, + "end": 143, + "loc": { + "start": { + "line": 14, + "column": 11 + }, + "end": { + "line": 14, + "column": 15 + }, + "identifierName": "Math" + }, + "name": "Math" + }, + "property": { + "type": "Identifier", + "start": 144, + "end": 150, + "loc": { + "start": { + "line": 14, + "column": 16 + }, + "end": { + "line": 14, + "column": 22 + }, + "identifierName": "random" + }, + "name": "random" + }, + "computed": false + }, + "arguments": [] + } + } + ], + "directives": [] + } + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/test/fixtures/experimental/class-private-methods/combined/options.json b/test/fixtures/experimental/class-private-methods/combined/options.json new file mode 100644 index 0000000000..55a2c821d7 --- /dev/null +++ b/test/fixtures/experimental/class-private-methods/combined/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["classProperties", "classPrivateProperties", "classPrivateMethods"] +} diff --git a/test/fixtures/experimental/class-private-methods/failure-name-constructor/actual.js b/test/fixtures/experimental/class-private-methods/failure-name-constructor/actual.js new file mode 100644 index 0000000000..9b37f57c33 --- /dev/null +++ b/test/fixtures/experimental/class-private-methods/failure-name-constructor/actual.js @@ -0,0 +1,3 @@ +class Foo { + #constructor() {}; +} diff --git a/test/fixtures/experimental/class-private-methods/failure-name-constructor/options.json b/test/fixtures/experimental/class-private-methods/failure-name-constructor/options.json new file mode 100644 index 0000000000..14e0bd1888 --- /dev/null +++ b/test/fixtures/experimental/class-private-methods/failure-name-constructor/options.json @@ -0,0 +1,7 @@ +{ + "throws": "Classes may not have a private field named '#constructor' (2:3)", + "plugins": [ + "classProperties", + "classPrivateMethods" + ] +} diff --git a/test/fixtures/experimental/class-private-properties/failure-method/actual.js b/test/fixtures/experimental/class-private-methods/failure-no-plugin/actual.js similarity index 100% rename from test/fixtures/experimental/class-private-properties/failure-method/actual.js rename to test/fixtures/experimental/class-private-methods/failure-no-plugin/actual.js diff --git a/test/fixtures/experimental/class-private-methods/failure-no-plugin/options.json b/test/fixtures/experimental/class-private-methods/failure-no-plugin/options.json new file mode 100644 index 0000000000..284a3b1ef7 --- /dev/null +++ b/test/fixtures/experimental/class-private-methods/failure-no-plugin/options.json @@ -0,0 +1,4 @@ +{ + "throws": "This experimental syntax requires enabling the parser plugin: 'classPrivateMethods' (3:3)", + "plugins": ["classProperties", "classPrivateProperties"] +} diff --git a/test/fixtures/experimental/class-private-methods/generator/actual.js b/test/fixtures/experimental/class-private-methods/generator/actual.js new file mode 100644 index 0000000000..e0c6218884 --- /dev/null +++ b/test/fixtures/experimental/class-private-methods/generator/actual.js @@ -0,0 +1,5 @@ +class Hotel { + *#evil() { + yield notReally(); + } +} diff --git a/test/fixtures/experimental/class-private-methods/generator/expected.json b/test/fixtures/experimental/class-private-methods/generator/expected.json new file mode 100644 index 0000000000..13d9f1a2fa --- /dev/null +++ b/test/fixtures/experimental/class-private-methods/generator/expected.json @@ -0,0 +1,220 @@ +{ + "type": "File", + "start": 0, + "end": 55, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 5, + "column": 1 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 55, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 5, + "column": 1 + } + }, + "sourceType": "script", + "body": [ + { + "type": "ClassDeclaration", + "start": 0, + "end": 55, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 5, + "column": 1 + } + }, + "id": { + "type": "Identifier", + "start": 6, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 6 + }, + "end": { + "line": 1, + "column": 11 + }, + "identifierName": "Hotel" + }, + "name": "Hotel" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start": 12, + "end": 55, + "loc": { + "start": { + "line": 1, + "column": 12 + }, + "end": { + "line": 5, + "column": 1 + } + }, + "body": [ + { + "type": "ClassPrivateMethod", + "start": 16, + "end": 53, + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 4, + "column": 3 + } + }, + "static": false, + "kind": "method", + "key": { + "type": "PrivateName", + "start": 18, + "end": 22, + "loc": { + "start": { + "line": 2, + "column": 4 + }, + "end": { + "line": 2, + "column": 8 + } + }, + "id": { + "type": "Identifier", + "start": 18, + "end": 22, + "loc": { + "start": { + "line": 2, + "column": 4 + }, + "end": { + "line": 2, + "column": 8 + }, + "identifierName": "evil" + }, + "name": "evil" + } + }, + "id": null, + "generator": true, + "expression": false, + "async": false, + "params": [], + "body": { + "type": "BlockStatement", + "start": 25, + "end": 53, + "loc": { + "start": { + "line": 2, + "column": 11 + }, + "end": { + "line": 4, + "column": 3 + } + }, + "body": [ + { + "type": "ExpressionStatement", + "start": 31, + "end": 49, + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 3, + "column": 22 + } + }, + "expression": { + "type": "YieldExpression", + "start": 31, + "end": 48, + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 3, + "column": 21 + } + }, + "delegate": false, + "argument": { + "type": "CallExpression", + "start": 37, + "end": 48, + "loc": { + "start": { + "line": 3, + "column": 10 + }, + "end": { + "line": 3, + "column": 21 + } + }, + "callee": { + "type": "Identifier", + "start": 37, + "end": 46, + "loc": { + "start": { + "line": 3, + "column": 10 + }, + "end": { + "line": 3, + "column": 19 + }, + "identifierName": "notReally" + }, + "name": "notReally" + }, + "arguments": [] + } + } + } + ], + "directives": [] + } + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/test/fixtures/experimental/class-private-methods/generator/options.json b/test/fixtures/experimental/class-private-methods/generator/options.json new file mode 100644 index 0000000000..aedb66f739 --- /dev/null +++ b/test/fixtures/experimental/class-private-methods/generator/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["classProperties", "classPrivateMethods"] +} diff --git a/test/fixtures/experimental/class-private-methods/get-set/actual.js b/test/fixtures/experimental/class-private-methods/get-set/actual.js new file mode 100644 index 0000000000..be4be51d20 --- /dev/null +++ b/test/fixtures/experimental/class-private-methods/get-set/actual.js @@ -0,0 +1,8 @@ +class Hotel { + get #evil() { + return ohNo(); + } + set #evil(x) { + return makeEvil(x); + } +} diff --git a/test/fixtures/experimental/class-private-methods/get-set/expected.json b/test/fixtures/experimental/class-private-methods/get-set/expected.json new file mode 100644 index 0000000000..f8cbfe8346 --- /dev/null +++ b/test/fixtures/experimental/class-private-methods/get-set/expected.json @@ -0,0 +1,362 @@ +{ + "type": "File", + "start": 0, + "end": 99, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 8, + "column": 1 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 99, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 8, + "column": 1 + } + }, + "sourceType": "script", + "body": [ + { + "type": "ClassDeclaration", + "start": 0, + "end": 99, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 8, + "column": 1 + } + }, + "id": { + "type": "Identifier", + "start": 6, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 6 + }, + "end": { + "line": 1, + "column": 11 + }, + "identifierName": "Hotel" + }, + "name": "Hotel" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start": 12, + "end": 99, + "loc": { + "start": { + "line": 1, + "column": 12 + }, + "end": { + "line": 8, + "column": 1 + } + }, + "body": [ + { + "type": "ClassPrivateMethod", + "start": 16, + "end": 52, + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 4, + "column": 3 + } + }, + "static": false, + "key": { + "type": "PrivateName", + "start": 21, + "end": 25, + "loc": { + "start": { + "line": 2, + "column": 7 + }, + "end": { + "line": 2, + "column": 11 + } + }, + "id": { + "type": "Identifier", + "start": 21, + "end": 25, + "loc": { + "start": { + "line": 2, + "column": 7 + }, + "end": { + "line": 2, + "column": 11 + }, + "identifierName": "evil" + }, + "name": "evil" + } + }, + "computed": false, + "kind": "get", + "id": null, + "generator": false, + "expression": false, + "async": false, + "params": [], + "body": { + "type": "BlockStatement", + "start": 28, + "end": 52, + "loc": { + "start": { + "line": 2, + "column": 14 + }, + "end": { + "line": 4, + "column": 3 + } + }, + "body": [ + { + "type": "ReturnStatement", + "start": 34, + "end": 48, + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 3, + "column": 18 + } + }, + "argument": { + "type": "CallExpression", + "start": 41, + "end": 47, + "loc": { + "start": { + "line": 3, + "column": 11 + }, + "end": { + "line": 3, + "column": 17 + } + }, + "callee": { + "type": "Identifier", + "start": 41, + "end": 45, + "loc": { + "start": { + "line": 3, + "column": 11 + }, + "end": { + "line": 3, + "column": 15 + }, + "identifierName": "ohNo" + }, + "name": "ohNo" + }, + "arguments": [] + } + } + ], + "directives": [] + } + }, + { + "type": "ClassPrivateMethod", + "start": 55, + "end": 97, + "loc": { + "start": { + "line": 5, + "column": 2 + }, + "end": { + "line": 7, + "column": 3 + } + }, + "static": false, + "key": { + "type": "PrivateName", + "start": 60, + "end": 64, + "loc": { + "start": { + "line": 5, + "column": 7 + }, + "end": { + "line": 5, + "column": 11 + } + }, + "id": { + "type": "Identifier", + "start": 60, + "end": 64, + "loc": { + "start": { + "line": 5, + "column": 7 + }, + "end": { + "line": 5, + "column": 11 + }, + "identifierName": "evil" + }, + "name": "evil" + } + }, + "computed": false, + "kind": "set", + "id": null, + "generator": false, + "expression": false, + "async": false, + "params": [ + { + "type": "Identifier", + "start": 65, + "end": 66, + "loc": { + "start": { + "line": 5, + "column": 12 + }, + "end": { + "line": 5, + "column": 13 + }, + "identifierName": "x" + }, + "name": "x" + } + ], + "body": { + "type": "BlockStatement", + "start": 68, + "end": 97, + "loc": { + "start": { + "line": 5, + "column": 15 + }, + "end": { + "line": 7, + "column": 3 + } + }, + "body": [ + { + "type": "ReturnStatement", + "start": 74, + "end": 93, + "loc": { + "start": { + "line": 6, + "column": 4 + }, + "end": { + "line": 6, + "column": 23 + } + }, + "argument": { + "type": "CallExpression", + "start": 81, + "end": 92, + "loc": { + "start": { + "line": 6, + "column": 11 + }, + "end": { + "line": 6, + "column": 22 + } + }, + "callee": { + "type": "Identifier", + "start": 81, + "end": 89, + "loc": { + "start": { + "line": 6, + "column": 11 + }, + "end": { + "line": 6, + "column": 19 + }, + "identifierName": "makeEvil" + }, + "name": "makeEvil" + }, + "arguments": [ + { + "type": "Identifier", + "start": 90, + "end": 91, + "loc": { + "start": { + "line": 6, + "column": 20 + }, + "end": { + "line": 6, + "column": 21 + }, + "identifierName": "x" + }, + "name": "x" + } + ] + } + } + ], + "directives": [] + } + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/test/fixtures/experimental/class-private-methods/get-set/options.json b/test/fixtures/experimental/class-private-methods/get-set/options.json new file mode 100644 index 0000000000..aedb66f739 --- /dev/null +++ b/test/fixtures/experimental/class-private-methods/get-set/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["classProperties", "classPrivateMethods"] +} diff --git a/test/fixtures/experimental/class-private-methods/method/actual.js b/test/fixtures/experimental/class-private-methods/method/actual.js new file mode 100644 index 0000000000..cd42046085 --- /dev/null +++ b/test/fixtures/experimental/class-private-methods/method/actual.js @@ -0,0 +1,5 @@ +class Hotel { + #getBanned() { + return violentPeople(); + } +} diff --git a/test/fixtures/experimental/class-private-methods/method/expected.json b/test/fixtures/experimental/class-private-methods/method/expected.json new file mode 100644 index 0000000000..211e15b7ac --- /dev/null +++ b/test/fixtures/experimental/class-private-methods/method/expected.json @@ -0,0 +1,204 @@ +{ + "type": "File", + "start": 0, + "end": 64, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 5, + "column": 1 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 64, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 5, + "column": 1 + } + }, + "sourceType": "script", + "body": [ + { + "type": "ClassDeclaration", + "start": 0, + "end": 64, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 5, + "column": 1 + } + }, + "id": { + "type": "Identifier", + "start": 6, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 6 + }, + "end": { + "line": 1, + "column": 11 + }, + "identifierName": "Hotel" + }, + "name": "Hotel" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start": 12, + "end": 64, + "loc": { + "start": { + "line": 1, + "column": 12 + }, + "end": { + "line": 5, + "column": 1 + } + }, + "body": [ + { + "type": "ClassPrivateMethod", + "start": 16, + "end": 62, + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 4, + "column": 3 + } + }, + "static": false, + "key": { + "type": "PrivateName", + "start": 17, + "end": 26, + "loc": { + "start": { + "line": 2, + "column": 3 + }, + "end": { + "line": 2, + "column": 12 + } + }, + "id": { + "type": "Identifier", + "start": 17, + "end": 26, + "loc": { + "start": { + "line": 2, + "column": 3 + }, + "end": { + "line": 2, + "column": 12 + }, + "identifierName": "getBanned" + }, + "name": "getBanned" + } + }, + "kind": "method", + "id": null, + "generator": false, + "expression": false, + "async": false, + "params": [], + "body": { + "type": "BlockStatement", + "start": 29, + "end": 62, + "loc": { + "start": { + "line": 2, + "column": 15 + }, + "end": { + "line": 4, + "column": 3 + } + }, + "body": [ + { + "type": "ReturnStatement", + "start": 35, + "end": 58, + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 3, + "column": 27 + } + }, + "argument": { + "type": "CallExpression", + "start": 42, + "end": 57, + "loc": { + "start": { + "line": 3, + "column": 11 + }, + "end": { + "line": 3, + "column": 26 + } + }, + "callee": { + "type": "Identifier", + "start": 42, + "end": 55, + "loc": { + "start": { + "line": 3, + "column": 11 + }, + "end": { + "line": 3, + "column": 24 + }, + "identifierName": "violentPeople" + }, + "name": "violentPeople" + }, + "arguments": [] + } + } + ], + "directives": [] + } + } + ] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/test/fixtures/experimental/class-private-methods/method/options.json b/test/fixtures/experimental/class-private-methods/method/options.json new file mode 100644 index 0000000000..aedb66f739 --- /dev/null +++ b/test/fixtures/experimental/class-private-methods/method/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["classProperties", "classPrivateMethods"] +} diff --git a/test/fixtures/experimental/class-private-properties/asi-failure-inline/options.json b/test/fixtures/experimental/class-private-properties/asi-failure-inline/options.json index 123e8aa507..58f4f2f739 100644 --- a/test/fixtures/experimental/class-private-properties/asi-failure-inline/options.json +++ b/test/fixtures/experimental/class-private-properties/asi-failure-inline/options.json @@ -1,4 +1,4 @@ { - "throws": "Unexpected token, expected ; (2:5)", + "throws": "Unexpected token (2:5)", "plugins": ["classProperties", "classPrivateProperties"] } diff --git a/test/fixtures/experimental/class-private-properties/asi-success/expected.json b/test/fixtures/experimental/class-private-properties/asi-success/expected.json index 22a8ec7990..b3201d11ae 100644 --- a/test/fixtures/experimental/class-private-properties/asi-success/expected.json +++ b/test/fixtures/experimental/class-private-properties/asi-success/expected.json @@ -89,8 +89,9 @@ "column": 4 } }, + "static": false, "key": { - "type": "Identifier", + "type": "PrivateName", "start": 15, "end": 16, "loc": { @@ -101,12 +102,26 @@ "end": { "line": 2, "column": 4 - }, - "identifierName": "x" + } }, - "name": "x" + "id": { + "type": "Identifier", + "start": 15, + "end": 16, + "loc": { + "start": { + "line": 2, + "column": 3 + }, + "end": { + "line": 2, + "column": 4 + }, + "identifierName": "x" + }, + "name": "x" + } }, - "static": false, "value": null }, { @@ -123,8 +138,9 @@ "column": 4 } }, + "static": false, "key": { - "type": "Identifier", + "type": "PrivateName", "start": 20, "end": 21, "loc": { @@ -135,12 +151,26 @@ "end": { "line": 3, "column": 4 - }, - "identifierName": "y" + } }, - "name": "y" + "id": { + "type": "Identifier", + "start": 20, + "end": 21, + "loc": { + "start": { + "line": 3, + "column": 3 + }, + "end": { + "line": 3, + "column": 4 + }, + "identifierName": "y" + }, + "name": "y" + } }, - "static": false, "value": null } ] @@ -149,4 +179,4 @@ ], "directives": [] } -} +} \ No newline at end of file diff --git a/test/fixtures/experimental/class-private-properties/failure-method/options.json b/test/fixtures/experimental/class-private-properties/failure-method/options.json deleted file mode 100644 index 6110b91af1..0000000000 --- a/test/fixtures/experimental/class-private-properties/failure-method/options.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "throws": "Unexpected token, expected ; (3:5)", - "plugins": ["classProperties", "classPrivateProperties"] -} diff --git a/test/fixtures/experimental/class-private-properties/failure-name-constructor/actual.js b/test/fixtures/experimental/class-private-properties/failure-name-constructor/actual.js new file mode 100644 index 0000000000..d72b6a9a8d --- /dev/null +++ b/test/fixtures/experimental/class-private-properties/failure-name-constructor/actual.js @@ -0,0 +1,3 @@ +class Foo { + #constructor; +} diff --git a/test/fixtures/experimental/class-private-properties/failure-name-constructor/options.json b/test/fixtures/experimental/class-private-properties/failure-name-constructor/options.json new file mode 100644 index 0000000000..faa50232dd --- /dev/null +++ b/test/fixtures/experimental/class-private-properties/failure-name-constructor/options.json @@ -0,0 +1,7 @@ +{ + "throws": "Classes may not have a private field named '#constructor' (2:3)", + "plugins": [ + "classProperties", + "classPrivateProperties" + ] +} diff --git a/test/fixtures/experimental/class-private-properties/inline/expected.json b/test/fixtures/experimental/class-private-properties/inline/expected.json index 2ebb392b10..98c21df819 100644 --- a/test/fixtures/experimental/class-private-properties/inline/expected.json +++ b/test/fixtures/experimental/class-private-properties/inline/expected.json @@ -89,8 +89,9 @@ "column": 13 } }, + "static": false, "key": { - "type": "Identifier", + "type": "PrivateName", "start": 11, "end": 12, "loc": { @@ -101,12 +102,26 @@ "end": { "line": 1, "column": 12 - }, - "identifierName": "x" + } }, - "name": "x" + "id": { + "type": "Identifier", + "start": 11, + "end": 12, + "loc": { + "start": { + "line": 1, + "column": 11 + }, + "end": { + "line": 1, + "column": 12 + }, + "identifierName": "x" + }, + "name": "x" + } }, - "static": false, "value": null }, { @@ -123,8 +138,9 @@ "column": 17 } }, + "static": false, "key": { - "type": "Identifier", + "type": "PrivateName", "start": 15, "end": 16, "loc": { @@ -135,12 +151,26 @@ "end": { "line": 1, "column": 16 - }, - "identifierName": "y" + } }, - "name": "y" + "id": { + "type": "Identifier", + "start": 15, + "end": 16, + "loc": { + "start": { + "line": 1, + "column": 15 + }, + "end": { + "line": 1, + "column": 16 + }, + "identifierName": "y" + }, + "name": "y" + } }, - "static": false, "value": null } ] @@ -207,8 +237,9 @@ "column": 17 } }, + "static": false, "key": { - "type": "Identifier", + "type": "PrivateName", "start": 32, "end": 33, "loc": { @@ -219,12 +250,26 @@ "end": { "line": 3, "column": 12 - }, - "identifierName": "x" + } }, - "name": "x" + "id": { + "type": "Identifier", + "start": 32, + "end": 33, + "loc": { + "start": { + "line": 3, + "column": 11 + }, + "end": { + "line": 3, + "column": 12 + }, + "identifierName": "x" + }, + "name": "x" + } }, - "static": false, "value": { "type": "NumericLiteral", "start": 36, @@ -260,8 +305,9 @@ "column": 25 } }, + "static": false, "key": { - "type": "Identifier", + "type": "PrivateName", "start": 40, "end": 41, "loc": { @@ -272,12 +318,26 @@ "end": { "line": 3, "column": 20 - }, - "identifierName": "y" + } }, - "name": "y" + "id": { + "type": "Identifier", + "start": 40, + "end": 41, + "loc": { + "start": { + "line": 3, + "column": 19 + }, + "end": { + "line": 3, + "column": 20 + }, + "identifierName": "y" + }, + "name": "y" + } }, - "static": false, "value": { "type": "NumericLiteral", "start": 44, @@ -305,4 +365,4 @@ ], "directives": [] } -} +} \ No newline at end of file diff --git a/test/fixtures/experimental/class-private-properties/nested/expected.json b/test/fixtures/experimental/class-private-properties/nested/expected.json index c2cd3363c2..d5d64806a6 100644 --- a/test/fixtures/experimental/class-private-properties/nested/expected.json +++ b/test/fixtures/experimental/class-private-properties/nested/expected.json @@ -89,8 +89,9 @@ "column": 9 } }, + "static": false, "key": { - "type": "Identifier", + "type": "PrivateName", "start": 17, "end": 18, "loc": { @@ -101,12 +102,26 @@ "end": { "line": 2, "column": 4 - }, - "identifierName": "x" + } }, - "name": "x" + "id": { + "type": "Identifier", + "start": 17, + "end": 18, + "loc": { + "start": { + "line": 2, + "column": 3 + }, + "end": { + "line": 2, + "column": 4 + }, + "identifierName": "x" + }, + "name": "x" + } }, - "static": false, "value": { "type": "NumericLiteral", "start": 21, @@ -142,8 +157,9 @@ "column": 9 } }, + "static": false, "key": { - "type": "Identifier", + "type": "PrivateName", "start": 27, "end": 28, "loc": { @@ -154,12 +170,26 @@ "end": { "line": 3, "column": 4 - }, - "identifierName": "y" + } }, - "name": "y" + "id": { + "type": "Identifier", + "start": 27, + "end": 28, + "loc": { + "start": { + "line": 3, + "column": 3 + }, + "end": { + "line": 3, + "column": 4 + }, + "identifierName": "y" + }, + "name": "y" + } }, - "static": false, "value": { "type": "NumericLiteral", "start": 31, @@ -196,7 +226,6 @@ } }, "static": false, - "computed": false, "key": { "type": "Identifier", "start": 37, @@ -214,6 +243,7 @@ }, "name": "constructor" }, + "computed": false, "kind": "constructor", "id": null, "generator": false, @@ -724,8 +754,9 @@ "column": 13 } }, + "static": false, "key": { - "type": "Identifier", + "type": "PrivateName", "start": 132, "end": 133, "loc": { @@ -736,12 +767,26 @@ "end": { "line": 10, "column": 8 - }, - "identifierName": "x" + } }, - "name": "x" + "id": { + "type": "Identifier", + "start": 132, + "end": 133, + "loc": { + "start": { + "line": 10, + "column": 7 + }, + "end": { + "line": 10, + "column": 8 + }, + "identifierName": "x" + }, + "name": "x" + } }, - "static": false, "value": { "type": "NumericLiteral", "start": 136, @@ -777,8 +822,9 @@ "column": 13 } }, + "static": false, "key": { - "type": "Identifier", + "type": "PrivateName", "start": 146, "end": 147, "loc": { @@ -789,12 +835,26 @@ "end": { "line": 11, "column": 8 - }, - "identifierName": "y" + } }, - "name": "y" + "id": { + "type": "Identifier", + "start": 146, + "end": 147, + "loc": { + "start": { + "line": 11, + "column": 7 + }, + "end": { + "line": 11, + "column": 8 + }, + "identifierName": "y" + }, + "name": "y" + } }, - "static": false, "value": { "type": "NumericLiteral", "start": 150, @@ -831,7 +891,6 @@ } }, "static": false, - "computed": false, "key": { "type": "Identifier", "start": 160, @@ -849,6 +908,7 @@ }, "name": "constructor" }, + "computed": false, "kind": "constructor", "id": null, "generator": false, @@ -1256,7 +1316,6 @@ } }, "static": false, - "computed": false, "key": { "type": "Identifier", "start": 251, @@ -1274,6 +1333,7 @@ }, "name": "x" }, + "computed": false, "kind": "get", "id": null, "generator": false, @@ -1392,7 +1452,6 @@ } }, "static": false, - "computed": false, "key": { "type": "Identifier", "start": 284, @@ -1410,6 +1469,7 @@ }, "name": "x" }, + "computed": false, "kind": "set", "id": null, "generator": false, @@ -1599,7 +1659,6 @@ } }, "static": false, - "computed": false, "key": { "type": "Identifier", "start": 325, @@ -1617,6 +1676,7 @@ }, "name": "y" }, + "computed": false, "kind": "get", "id": null, "generator": false, @@ -1735,7 +1795,6 @@ } }, "static": false, - "computed": false, "key": { "type": "Identifier", "start": 358, @@ -1753,6 +1812,7 @@ }, "name": "y" }, + "computed": false, "kind": "set", "id": null, "generator": false, @@ -1942,7 +2002,6 @@ } }, "static": false, - "computed": false, "key": { "type": "Identifier", "start": 395, @@ -1960,6 +2019,7 @@ }, "name": "equals" }, + "computed": false, "kind": "method", "id": null, "generator": false, @@ -2337,7 +2397,6 @@ } }, "static": false, - "computed": false, "key": { "type": "Identifier", "start": 460, @@ -2355,6 +2414,7 @@ }, "name": "toString" }, + "computed": false, "kind": "method", "id": null, "generator": false, @@ -2624,7 +2684,6 @@ } }, "static": false, - "computed": false, "key": { "type": "Identifier", "start": 535, @@ -2642,6 +2701,7 @@ }, "name": "x" }, + "computed": false, "kind": "get", "id": null, "generator": false, @@ -2760,7 +2820,6 @@ } }, "static": false, - "computed": false, "key": { "type": "Identifier", "start": 564, @@ -2778,6 +2837,7 @@ }, "name": "x" }, + "computed": false, "kind": "set", "id": null, "generator": false, @@ -2967,7 +3027,6 @@ } }, "static": false, - "computed": false, "key": { "type": "Identifier", "start": 601, @@ -2985,6 +3044,7 @@ }, "name": "y" }, + "computed": false, "kind": "get", "id": null, "generator": false, @@ -3103,7 +3163,6 @@ } }, "static": false, - "computed": false, "key": { "type": "Identifier", "start": 630, @@ -3121,6 +3180,7 @@ }, "name": "y" }, + "computed": false, "kind": "set", "id": null, "generator": false, @@ -3310,7 +3370,6 @@ } }, "static": false, - "computed": false, "key": { "type": "Identifier", "start": 663, @@ -3328,6 +3387,7 @@ }, "name": "equals" }, + "computed": false, "kind": "method", "id": null, "generator": false, @@ -3705,7 +3765,6 @@ } }, "static": false, - "computed": false, "key": { "type": "Identifier", "start": 724, @@ -3723,6 +3782,7 @@ }, "name": "toString" }, + "computed": false, "kind": "method", "id": null, "generator": false, diff --git a/test/fixtures/experimental/class-private-properties/pbn-success/expected.json b/test/fixtures/experimental/class-private-properties/pbn-success/expected.json index 8e832903dc..420f3f9619 100644 --- a/test/fixtures/experimental/class-private-properties/pbn-success/expected.json +++ b/test/fixtures/experimental/class-private-properties/pbn-success/expected.json @@ -89,8 +89,9 @@ "column": 9 } }, + "static": false, "key": { - "type": "Identifier", + "type": "PrivateName", "start": 17, "end": 18, "loc": { @@ -101,12 +102,26 @@ "end": { "line": 2, "column": 4 - }, - "identifierName": "x" + } }, - "name": "x" + "id": { + "type": "Identifier", + "start": 17, + "end": 18, + "loc": { + "start": { + "line": 2, + "column": 3 + }, + "end": { + "line": 2, + "column": 4 + }, + "identifierName": "x" + }, + "name": "x" + } }, - "static": false, "value": { "type": "NumericLiteral", "start": 21, @@ -142,8 +157,9 @@ "column": 9 } }, + "static": false, "key": { - "type": "Identifier", + "type": "PrivateName", "start": 27, "end": 28, "loc": { @@ -154,12 +170,26 @@ "end": { "line": 3, "column": 4 - }, - "identifierName": "y" + } }, - "name": "y" + "id": { + "type": "Identifier", + "start": 27, + "end": 28, + "loc": { + "start": { + "line": 3, + "column": 3 + }, + "end": { + "line": 3, + "column": 4 + }, + "identifierName": "y" + }, + "name": "y" + } }, - "static": false, "value": { "type": "NumericLiteral", "start": 31, @@ -196,7 +226,6 @@ } }, "static": false, - "computed": false, "key": { "type": "Identifier", "start": 37, @@ -214,6 +243,7 @@ }, "name": "constructor" }, + "computed": false, "kind": "constructor", "id": null, "generator": false, @@ -621,7 +651,6 @@ } }, "static": false, - "computed": false, "key": { "type": "Identifier", "start": 112, @@ -639,6 +668,7 @@ }, "name": "x" }, + "computed": false, "kind": "get", "id": null, "generator": false, @@ -757,7 +787,6 @@ } }, "static": false, - "computed": false, "key": { "type": "Identifier", "start": 141, @@ -775,6 +804,7 @@ }, "name": "x" }, + "computed": false, "kind": "set", "id": null, "generator": false, @@ -964,7 +994,6 @@ } }, "static": false, - "computed": false, "key": { "type": "Identifier", "start": 178, @@ -982,6 +1011,7 @@ }, "name": "y" }, + "computed": false, "kind": "get", "id": null, "generator": false, @@ -1100,7 +1130,6 @@ } }, "static": false, - "computed": false, "key": { "type": "Identifier", "start": 207, @@ -1118,6 +1147,7 @@ }, "name": "y" }, + "computed": false, "kind": "set", "id": null, "generator": false, @@ -1307,7 +1337,6 @@ } }, "static": false, - "computed": false, "key": { "type": "Identifier", "start": 240, @@ -1325,6 +1354,7 @@ }, "name": "equals" }, + "computed": false, "kind": "method", "id": null, "generator": false, @@ -1702,7 +1732,6 @@ } }, "static": false, - "computed": false, "key": { "type": "Identifier", "start": 301, @@ -1720,6 +1749,7 @@ }, "name": "toString" }, + "computed": false, "kind": "method", "id": null, "generator": false, diff --git a/test/fixtures/experimental/class-private-properties/static/expected.json b/test/fixtures/experimental/class-private-properties/static/expected.json index 9d7c840f64..ac66240967 100644 --- a/test/fixtures/experimental/class-private-properties/static/expected.json +++ b/test/fixtures/experimental/class-private-properties/static/expected.json @@ -89,8 +89,9 @@ "column": 12 } }, + "static": true, "key": { - "type": "Identifier", + "type": "PrivateName", "start": 20, "end": 21, "loc": { @@ -101,12 +102,26 @@ "end": { "line": 2, "column": 11 - }, - "identifierName": "x" + } }, - "name": "x" + "id": { + "type": "Identifier", + "start": 20, + "end": 21, + "loc": { + "start": { + "line": 2, + "column": 10 + }, + "end": { + "line": 2, + "column": 11 + }, + "identifierName": "x" + }, + "name": "x" + } }, - "static": true, "value": null }, { @@ -123,8 +138,9 @@ "column": 16 } }, + "static": true, "key": { - "type": "Identifier", + "type": "PrivateName", "start": 33, "end": 34, "loc": { @@ -135,12 +151,26 @@ "end": { "line": 3, "column": 11 - }, - "identifierName": "y" + } }, - "name": "y" + "id": { + "type": "Identifier", + "start": 33, + "end": 34, + "loc": { + "start": { + "line": 3, + "column": 10 + }, + "end": { + "line": 3, + "column": 11 + }, + "identifierName": "y" + }, + "name": "y" + } }, - "static": true, "value": { "type": "NumericLiteral", "start": 37, @@ -168,4 +198,4 @@ ], "directives": [] } -} +} \ No newline at end of file