Implement class features in estree (#12370)

Co-authored-by: Kai Cataldo <kai@kaicataldo.com>
This commit is contained in:
Huáng Jùnliàng 2021-02-21 14:12:12 -05:00 committed by GitHub
parent 9c567baa9b
commit 03d7911be6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 656 additions and 20 deletions

View File

@ -166,6 +166,10 @@ class Referencer extends OriginalReferencer {
this._visitClassProperty(node); this._visitClassProperty(node);
} }
PropertyDefinition(node) {
this._visitClassProperty(node);
}
// TODO: Update to visit type annotations when TypeScript/Flow support this syntax. // TODO: Update to visit type annotations when TypeScript/Flow support this syntax.
ClassPrivateMethod(node) { ClassPrivateMethod(node) {
super.MethodDefinition(node); super.MethodDefinition(node);

View File

@ -8,11 +8,15 @@ export const newTypes = {
Literal: ESLINT_VISITOR_KEYS.Literal, Literal: ESLINT_VISITOR_KEYS.Literal,
MethodDefinition: ["decorators"].concat(ESLINT_VISITOR_KEYS.MethodDefinition), MethodDefinition: ["decorators"].concat(ESLINT_VISITOR_KEYS.MethodDefinition),
Property: ["decorators"].concat(ESLINT_VISITOR_KEYS.Property), Property: ["decorators"].concat(ESLINT_VISITOR_KEYS.Property),
// todo: remove this when Acorn supports class properties
PropertyDefinition: t.VISITOR_KEYS.ClassProperty,
// todo: remove this when Acorn supports class properties
PrivateIdentifier: [],
}; };
// AST Types that shares `"type"` property with Babel but have different shape // AST Types that shares `"type"` property with Babel but have different shape
export const conflictTypes = { export const conflictTypes = {
// todo: remove this when class features are supported // todo: remove this when we drop Babel 7 support
ClassPrivateMethod: ["decorators"].concat( ClassPrivateMethod: ["decorators"].concat(
ESLINT_VISITOR_KEYS.MethodDefinition, ESLINT_VISITOR_KEYS.MethodDefinition,
), ),

View File

@ -11,7 +11,10 @@ export default ruleComposer.filterReports(noInvalidThisRule, problem => {
if ( if (
node.type === "ClassPrivateMethod" || node.type === "ClassPrivateMethod" ||
node.type === "ClassPrivateProperty" || node.type === "ClassPrivateProperty" ||
node.type === "ClassProperty" node.type === "ClassProperty" ||
node.type === "PropertyDefinition" ||
(node.type === "MethodDefinition" &&
node.key.type === "PrivateIdentifier")
) { ) {
inClassMember = true; inClassMember = true;
return; return;

View File

@ -79,7 +79,7 @@ function report(context, node, missing) {
export default ruleComposer.joinReports([ export default ruleComposer.joinReports([
rule, rule,
context => ({ context => ({
"ClassProperty, ClassPrivateProperty"(node) { "ClassProperty, ClassPrivateProperty, PropertyDefinition"(node) {
const options = context.options[1]; const options = context.options[1];
const exceptOneLine = options && options.omitLastInOneLineBlock === true; const exceptOneLine = options && options.omitLastInOneLineBlock === true;
const sourceCode = context.getSourceCode(); const sourceCode = context.getSourceCode();

View File

@ -1734,6 +1734,15 @@ describe("verify", () => {
{ "no-unused-vars": 1 }, { "no-unused-vars": 1 },
); );
}); });
it("type annotations should work", () => {
verifyAndAssertMessages(
`class C {
#p: Array<number>
}`,
{ "no-undef": 1 },
);
});
}); });
describe("private methods", () => { describe("private methods", () => {
@ -1794,6 +1803,31 @@ describe("verify", () => {
{ "no-unreachable": 1 }, { "no-unreachable": 1 },
); );
}); });
it("should work with func-names", () => {
verifyAndAssertMessages(
`
export class C {
#d() {};
}
`,
{ "func-names": 1 },
);
});
it("should work with space-before-function-paren", () => {
verifyAndAssertMessages(
`
export class C {
#d() {};
}
`,
{ "space-before-function-paren": 1 },
[
"2:5 Missing space before function parentheses. space-before-function-paren",
],
);
});
}); });
}); });

View File

@ -1172,12 +1172,15 @@ export default class ExpressionParser extends LValParser {
node = (this.parseMaybePrivateName(true): N.PrivateName); node = (this.parseMaybePrivateName(true): N.PrivateName);
if (this.match(tt._in)) { if (this.match(tt._in)) {
this.expectPlugin("privateIn"); this.expectPlugin("privateIn");
this.classScope.usePrivateName(node.id.name, node.start); this.classScope.usePrivateName(
this.getPrivateNameSV(node),
node.start,
);
} else if (this.hasPlugin("privateIn")) { } else if (this.hasPlugin("privateIn")) {
this.raise( this.raise(
this.state.start, this.state.start,
Errors.PrivateInExpectedIn, Errors.PrivateInExpectedIn,
node.id.name, this.getPrivateNameSV(node),
); );
} else { } else {
throw this.unexpected(start); throw this.unexpected(start);

View File

@ -194,6 +194,33 @@ export default (superClass: Class<Parser>): Class<Parser> =>
} }
} }
parseMaybePrivateName(...args: [boolean]): any {
const node = super.parseMaybePrivateName(...args);
if (node.type === "PrivateName") {
return this.convertPrivateNameToPrivateIdentifier(node);
}
return node;
}
convertPrivateNameToPrivateIdentifier(
node: N.PrivateName,
): N.EstreePrivateIdentifier {
const name = super.getPrivateNameSV(node);
node = (node: any);
delete node.id;
node.name = name;
node.type = "PrivateIdentifier";
return node;
}
isPrivateName(node: N.Node): boolean {
return node.type === "PrivateIdentifier";
}
getPrivateNameSV(node: N.Node): string {
return node.name;
}
parseLiteral<T: N.Literal>( parseLiteral<T: N.Literal>(
value: any, value: any,
type: /*T["kind"]*/ string, type: /*T["kind"]*/ string,
@ -240,11 +267,27 @@ export default (superClass: Class<Parser>): Class<Parser> =>
delete funcNode.kind; delete funcNode.kind;
// $FlowIgnore // $FlowIgnore
node.value = funcNode; node.value = funcNode;
if (type === "ClassPrivateMethod") {
type = type === "ClassMethod" ? "MethodDefinition" : type; // $FlowIgnore
node.computed = false;
}
type = "MethodDefinition";
return this.finishNode(node, type); return this.finishNode(node, type);
} }
parseClassProperty(...args: [N.ClassProperty]): any {
const propertyNode = (super.parseClassProperty(...args): any);
propertyNode.type = "PropertyDefinition";
return (propertyNode: N.EstreePropertyDefinition);
}
parseClassPrivateProperty(...args: [N.ClassPrivateProperty]): any {
const propertyNode = (super.parseClassPrivateProperty(...args): any);
propertyNode.type = "PropertyDefinition";
propertyNode.computed = false;
return (propertyNode: N.EstreePropertyDefinition);
}
parseObjectMethod( parseObjectMethod(
prop: N.ObjectMethod, prop: N.ObjectMethod,
isGenerator: boolean, isGenerator: boolean,

View File

@ -2181,7 +2181,8 @@ export default (superClass: Class<Parser>): Class<Parser> =>
if (member.declare) { if (member.declare) {
if ( if (
member.type !== "ClassProperty" && member.type !== "ClassProperty" &&
member.type !== "ClassPrivateProperty" member.type !== "ClassPrivateProperty" &&
member.type !== "PropertyDefinition" // Used by estree plugin
) { ) {
this.raise(pos, FlowErrors.DeclareClassElement); this.raise(pos, FlowErrors.DeclareClassElement);
} else if (member.value) { } else if (member.value) {

View File

@ -1077,6 +1077,19 @@ export type EstreeImportExpression = NodeBase & {
source: Expression, source: Expression,
}; };
export type EstreePrivateIdentifier = NodeBase & {
type: "PrivateIdentifier",
name: string,
};
export type EstreePropertyDefinition = NodeBase & {
type: "PropertyDefinition",
static: boolean,
key: Expression | EstreePrivateIdentifier,
computed: boolean,
value: Expression,
};
// === === === === // === === === ===
// TypeScript // TypeScript
// === === === === // === === === ===

View File

@ -1,3 +1,4 @@
class A { class A {
#foo(arg, ...others) {} #foo(arg, ...others) {}
static #bar(arg, ...others) {}
} }

View File

@ -1,15 +1,15 @@
{ {
"type": "File", "type": "File",
"start":0,"end":37,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, "start":0,"end":70,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}},
"program": { "program": {
"type": "Program", "type": "Program",
"start":0,"end":37,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, "start":0,"end":70,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}},
"sourceType": "script", "sourceType": "script",
"interpreter": null, "interpreter": null,
"body": [ "body": [
{ {
"type": "ClassDeclaration", "type": "ClassDeclaration",
"start":0,"end":37,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}}, "start":0,"end":70,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}},
"id": { "id": {
"type": "Identifier", "type": "Identifier",
"start":6,"end":7,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":7},"identifierName":"A"}, "start":6,"end":7,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":7},"identifierName":"A"},
@ -18,20 +18,16 @@
"superClass": null, "superClass": null,
"body": { "body": {
"type": "ClassBody", "type": "ClassBody",
"start":8,"end":37,"loc":{"start":{"line":1,"column":8},"end":{"line":3,"column":1}}, "start":8,"end":70,"loc":{"start":{"line":1,"column":8},"end":{"line":4,"column":1}},
"body": [ "body": [
{ {
"type": "ClassPrivateMethod", "type": "MethodDefinition",
"start":12,"end":35,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":25}}, "start":12,"end":35,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":25}},
"static": false, "static": false,
"key": { "key": {
"type": "PrivateName", "type": "PrivateIdentifier",
"start":12,"end":16,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":6}}, "start":12,"end":16,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":6}},
"id": {
"type": "Identifier",
"start":13,"end":16,"loc":{"start":{"line":2,"column":3},"end":{"line":2,"column":6},"identifierName":"foo"},
"name": "foo" "name": "foo"
}
}, },
"kind": "method", "kind": "method",
"value": { "value": {
@ -62,8 +58,50 @@
"start":33,"end":35,"loc":{"start":{"line":2,"column":23},"end":{"line":2,"column":25}}, "start":33,"end":35,"loc":{"start":{"line":2,"column":23},"end":{"line":2,"column":25}},
"body": [] "body": []
} }
},
"computed": false
},
{
"type": "MethodDefinition",
"start":38,"end":68,"loc":{"start":{"line":3,"column":2},"end":{"line":3,"column":32}},
"static": true,
"key": {
"type": "PrivateIdentifier",
"start":45,"end":49,"loc":{"start":{"line":3,"column":9},"end":{"line":3,"column":13}},
"name": "bar"
},
"kind": "method",
"value": {
"type": "FunctionExpression",
"start":49,"end":68,"loc":{"start":{"line":3,"column":13},"end":{"line":3,"column":32}},
"id": null,
"generator": false,
"async": false,
"expression": false,
"params": [
{
"type": "Identifier",
"start":50,"end":53,"loc":{"start":{"line":3,"column":14},"end":{"line":3,"column":17},"identifierName":"arg"},
"name": "arg"
},
{
"type": "RestElement",
"start":55,"end":64,"loc":{"start":{"line":3,"column":19},"end":{"line":3,"column":28}},
"argument": {
"type": "Identifier",
"start":58,"end":64,"loc":{"start":{"line":3,"column":22},"end":{"line":3,"column":28},"identifierName":"others"},
"name": "others"
} }
} }
],
"body": {
"type": "BlockStatement",
"start":66,"end":68,"loc":{"start":{"line":3,"column":30},"end":{"line":3,"column":32}},
"body": []
}
},
"computed": false
}
] ]
} }
} }

View File

@ -0,0 +1,4 @@
class A {
#foo = "bar";
static #bar = foo;
}

View File

@ -0,0 +1,3 @@
{
"plugins": ["estree", "classPrivateProperties"]
}

View File

@ -0,0 +1,61 @@
{
"type": "File",
"start":0,"end":48,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}},
"program": {
"type": "Program",
"start":0,"end":48,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ClassDeclaration",
"start":0,"end":48,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}},
"id": {
"type": "Identifier",
"start":6,"end":7,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":7},"identifierName":"A"},
"name": "A"
},
"superClass": null,
"body": {
"type": "ClassBody",
"start":8,"end":48,"loc":{"start":{"line":1,"column":8},"end":{"line":4,"column":1}},
"body": [
{
"type": "PropertyDefinition",
"start":12,"end":25,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":15}},
"static": false,
"key": {
"type": "PrivateIdentifier",
"start":12,"end":16,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":6}},
"name": "foo"
},
"value": {
"type": "Literal",
"start":19,"end":24,"loc":{"start":{"line":2,"column":9},"end":{"line":2,"column":14}},
"value": "bar",
"raw": "\"bar\""
},
"computed": false
},
{
"type": "PropertyDefinition",
"start":28,"end":46,"loc":{"start":{"line":3,"column":2},"end":{"line":3,"column":20}},
"static": true,
"key": {
"type": "PrivateIdentifier",
"start":35,"end":39,"loc":{"start":{"line":3,"column":9},"end":{"line":3,"column":13}},
"name": "bar"
},
"value": {
"type": "Identifier",
"start":42,"end":45,"loc":{"start":{"line":3,"column":16},"end":{"line":3,"column":19},"identifierName":"foo"},
"name": "foo"
},
"computed": false
}
]
}
}
]
}
}

View File

@ -0,0 +1,5 @@
class A {
#foo = "bar";
static #bar = foo;
declare #qux: Array<string>;
}

View File

@ -0,0 +1,3 @@
{
"plugins": ["flow", "estree", "classPrivateProperties"]
}

View File

@ -0,0 +1,100 @@
{
"type": "File",
"start":0,"end":79,"loc":{"start":{"line":1,"column":0},"end":{"line":5,"column":1}},
"program": {
"type": "Program",
"start":0,"end":79,"loc":{"start":{"line":1,"column":0},"end":{"line":5,"column":1}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ClassDeclaration",
"start":0,"end":79,"loc":{"start":{"line":1,"column":0},"end":{"line":5,"column":1}},
"id": {
"type": "Identifier",
"start":6,"end":7,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":7},"identifierName":"A"},
"name": "A"
},
"superClass": null,
"body": {
"type": "ClassBody",
"start":8,"end":79,"loc":{"start":{"line":1,"column":8},"end":{"line":5,"column":1}},
"body": [
{
"type": "PropertyDefinition",
"start":12,"end":25,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":15}},
"static": false,
"key": {
"type": "PrivateIdentifier",
"start":12,"end":16,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":6}},
"name": "foo"
},
"variance": null,
"value": {
"type": "Literal",
"start":19,"end":24,"loc":{"start":{"line":2,"column":9},"end":{"line":2,"column":14}},
"value": "bar",
"raw": "\"bar\""
},
"computed": false
},
{
"type": "PropertyDefinition",
"start":28,"end":46,"loc":{"start":{"line":3,"column":2},"end":{"line":3,"column":20}},
"static": true,
"key": {
"type": "PrivateIdentifier",
"start":35,"end":39,"loc":{"start":{"line":3,"column":9},"end":{"line":3,"column":13}},
"name": "bar"
},
"variance": null,
"value": {
"type": "Identifier",
"start":42,"end":45,"loc":{"start":{"line":3,"column":16},"end":{"line":3,"column":19},"identifierName":"foo"},
"name": "foo"
},
"computed": false
},
{
"type": "PropertyDefinition",
"start":49,"end":77,"loc":{"start":{"line":4,"column":2},"end":{"line":4,"column":30}},
"declare": true,
"static": false,
"key": {
"type": "PrivateIdentifier",
"start":57,"end":61,"loc":{"start":{"line":4,"column":10},"end":{"line":4,"column":14}},
"name": "qux"
},
"variance": null,
"typeAnnotation": {
"type": "TypeAnnotation",
"start":61,"end":76,"loc":{"start":{"line":4,"column":14},"end":{"line":4,"column":29}},
"typeAnnotation": {
"type": "GenericTypeAnnotation",
"start":63,"end":76,"loc":{"start":{"line":4,"column":16},"end":{"line":4,"column":29}},
"typeParameters": {
"type": "TypeParameterInstantiation",
"start":68,"end":76,"loc":{"start":{"line":4,"column":21},"end":{"line":4,"column":29}},
"params": [
{
"type": "StringTypeAnnotation",
"start":69,"end":75,"loc":{"start":{"line":4,"column":22},"end":{"line":4,"column":28}}
}
]
},
"id": {
"type": "Identifier",
"start":63,"end":68,"loc":{"start":{"line":4,"column":16},"end":{"line":4,"column":21},"identifierName":"Array"},
"name": "Array"
}
}
},
"value": null,
"computed": false
}
]
}
}
]
}
}

View File

@ -0,0 +1,5 @@
class A {
#foo = "bar";
static #bar = foo;
declare #qux: Array<string>;
}

View File

@ -0,0 +1,3 @@
{
"plugins": ["typescript", "estree", "classPrivateProperties"]
}

View File

@ -0,0 +1,97 @@
{
"type": "File",
"start":0,"end":79,"loc":{"start":{"line":1,"column":0},"end":{"line":5,"column":1}},
"program": {
"type": "Program",
"start":0,"end":79,"loc":{"start":{"line":1,"column":0},"end":{"line":5,"column":1}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ClassDeclaration",
"start":0,"end":79,"loc":{"start":{"line":1,"column":0},"end":{"line":5,"column":1}},
"id": {
"type": "Identifier",
"start":6,"end":7,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":7},"identifierName":"A"},
"name": "A"
},
"superClass": null,
"body": {
"type": "ClassBody",
"start":8,"end":79,"loc":{"start":{"line":1,"column":8},"end":{"line":5,"column":1}},
"body": [
{
"type": "PropertyDefinition",
"start":12,"end":25,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":15}},
"static": false,
"key": {
"type": "PrivateIdentifier",
"start":12,"end":16,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":6}},
"name": "foo"
},
"value": {
"type": "Literal",
"start":19,"end":24,"loc":{"start":{"line":2,"column":9},"end":{"line":2,"column":14}},
"value": "bar",
"raw": "\"bar\""
},
"computed": false
},
{
"type": "PropertyDefinition",
"start":28,"end":46,"loc":{"start":{"line":3,"column":2},"end":{"line":3,"column":20}},
"static": true,
"key": {
"type": "PrivateIdentifier",
"start":35,"end":39,"loc":{"start":{"line":3,"column":9},"end":{"line":3,"column":13}},
"name": "bar"
},
"value": {
"type": "Identifier",
"start":42,"end":45,"loc":{"start":{"line":3,"column":16},"end":{"line":3,"column":19},"identifierName":"foo"},
"name": "foo"
},
"computed": false
},
{
"type": "PropertyDefinition",
"start":49,"end":77,"loc":{"start":{"line":4,"column":2},"end":{"line":4,"column":30}},
"declare": true,
"static": false,
"key": {
"type": "PrivateIdentifier",
"start":57,"end":61,"loc":{"start":{"line":4,"column":10},"end":{"line":4,"column":14}},
"name": "qux"
},
"typeAnnotation": {
"type": "TSTypeAnnotation",
"start":61,"end":76,"loc":{"start":{"line":4,"column":14},"end":{"line":4,"column":29}},
"typeAnnotation": {
"type": "TSTypeReference",
"start":63,"end":76,"loc":{"start":{"line":4,"column":16},"end":{"line":4,"column":29}},
"typeName": {
"type": "Identifier",
"start":63,"end":68,"loc":{"start":{"line":4,"column":16},"end":{"line":4,"column":21},"identifierName":"Array"},
"name": "Array"
},
"typeParameters": {
"type": "TSTypeParameterInstantiation",
"start":68,"end":76,"loc":{"start":{"line":4,"column":21},"end":{"line":4,"column":29}},
"params": [
{
"type": "TSStringKeyword",
"start":69,"end":75,"loc":{"start":{"line":4,"column":22},"end":{"line":4,"column":28}}
}
]
}
}
},
"value": null,
"computed": false
}
]
}
}
]
}
}

View File

@ -0,0 +1,6 @@
class A {
foo = "bar";
[bar] = foo;
static "qux" = "quux";
static [quux] = "qux";
}

View File

@ -0,0 +1,3 @@
{
"plugins": ["estree", "classProperties"]
}

View File

@ -0,0 +1,96 @@
{
"type": "File",
"start":0,"end":91,"loc":{"start":{"line":1,"column":0},"end":{"line":6,"column":1}},
"program": {
"type": "Program",
"start":0,"end":91,"loc":{"start":{"line":1,"column":0},"end":{"line":6,"column":1}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ClassDeclaration",
"start":0,"end":91,"loc":{"start":{"line":1,"column":0},"end":{"line":6,"column":1}},
"id": {
"type": "Identifier",
"start":6,"end":7,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":7},"identifierName":"A"},
"name": "A"
},
"superClass": null,
"body": {
"type": "ClassBody",
"start":8,"end":91,"loc":{"start":{"line":1,"column":8},"end":{"line":6,"column":1}},
"body": [
{
"type": "PropertyDefinition",
"start":12,"end":24,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":14}},
"static": false,
"key": {
"type": "Identifier",
"start":12,"end":15,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":5},"identifierName":"foo"},
"name": "foo"
},
"computed": false,
"value": {
"type": "Literal",
"start":18,"end":23,"loc":{"start":{"line":2,"column":8},"end":{"line":2,"column":13}},
"value": "bar",
"raw": "\"bar\""
}
},
{
"type": "PropertyDefinition",
"start":27,"end":39,"loc":{"start":{"line":3,"column":2},"end":{"line":3,"column":14}},
"static": false,
"computed": true,
"key": {
"type": "Identifier",
"start":28,"end":31,"loc":{"start":{"line":3,"column":3},"end":{"line":3,"column":6},"identifierName":"bar"},
"name": "bar"
},
"value": {
"type": "Identifier",
"start":35,"end":38,"loc":{"start":{"line":3,"column":10},"end":{"line":3,"column":13},"identifierName":"foo"},
"name": "foo"
}
},
{
"type": "PropertyDefinition",
"start":42,"end":64,"loc":{"start":{"line":4,"column":2},"end":{"line":4,"column":24}},
"static": true,
"key": {
"type": "Literal",
"start":49,"end":54,"loc":{"start":{"line":4,"column":9},"end":{"line":4,"column":14}},
"value": "qux",
"raw": "\"qux\""
},
"computed": false,
"value": {
"type": "Literal",
"start":57,"end":63,"loc":{"start":{"line":4,"column":17},"end":{"line":4,"column":23}},
"value": "quux",
"raw": "\"quux\""
}
},
{
"type": "PropertyDefinition",
"start":67,"end":89,"loc":{"start":{"line":5,"column":2},"end":{"line":5,"column":24}},
"static": true,
"computed": true,
"key": {
"type": "Identifier",
"start":75,"end":79,"loc":{"start":{"line":5,"column":10},"end":{"line":5,"column":14},"identifierName":"quux"},
"name": "quux"
},
"value": {
"type": "Literal",
"start":83,"end":88,"loc":{"start":{"line":5,"column":18},"end":{"line":5,"column":23}},
"value": "qux",
"raw": "\"qux\""
}
}
]
}
}
]
}
}

View File

@ -0,0 +1,6 @@
class A {
#foo = "bar";
static isA(obj) {
return #foo in obj;
}
}

View File

@ -0,0 +1,3 @@
{
"plugins": ["estree", "classPrivateProperties", "privateIn"]
}

View File

@ -0,0 +1,97 @@
{
"type": "File",
"start":0,"end":75,"loc":{"start":{"line":1,"column":0},"end":{"line":6,"column":1}},
"program": {
"type": "Program",
"start":0,"end":75,"loc":{"start":{"line":1,"column":0},"end":{"line":6,"column":1}},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ClassDeclaration",
"start":0,"end":75,"loc":{"start":{"line":1,"column":0},"end":{"line":6,"column":1}},
"id": {
"type": "Identifier",
"start":6,"end":7,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":7},"identifierName":"A"},
"name": "A"
},
"superClass": null,
"body": {
"type": "ClassBody",
"start":8,"end":75,"loc":{"start":{"line":1,"column":8},"end":{"line":6,"column":1}},
"body": [
{
"type": "PropertyDefinition",
"start":12,"end":25,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":15}},
"static": false,
"key": {
"type": "PrivateIdentifier",
"start":12,"end":16,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":6}},
"name": "foo"
},
"value": {
"type": "Literal",
"start":19,"end":24,"loc":{"start":{"line":2,"column":9},"end":{"line":2,"column":14}},
"value": "bar",
"raw": "\"bar\""
},
"computed": false
},
{
"type": "MethodDefinition",
"start":28,"end":73,"loc":{"start":{"line":3,"column":2},"end":{"line":5,"column":3}},
"static": true,
"key": {
"type": "Identifier",
"start":35,"end":38,"loc":{"start":{"line":3,"column":9},"end":{"line":3,"column":12},"identifierName":"isA"},
"name": "isA"
},
"computed": false,
"kind": "method",
"value": {
"type": "FunctionExpression",
"start":38,"end":73,"loc":{"start":{"line":3,"column":12},"end":{"line":5,"column":3}},
"id": null,
"generator": false,
"async": false,
"expression": false,
"params": [
{
"type": "Identifier",
"start":39,"end":42,"loc":{"start":{"line":3,"column":13},"end":{"line":3,"column":16},"identifierName":"obj"},
"name": "obj"
}
],
"body": {
"type": "BlockStatement",
"start":44,"end":73,"loc":{"start":{"line":3,"column":18},"end":{"line":5,"column":3}},
"body": [
{
"type": "ReturnStatement",
"start":50,"end":69,"loc":{"start":{"line":4,"column":4},"end":{"line":4,"column":23}},
"argument": {
"type": "BinaryExpression",
"start":57,"end":68,"loc":{"start":{"line":4,"column":11},"end":{"line":4,"column":22}},
"left": {
"type": "PrivateIdentifier",
"start":57,"end":61,"loc":{"start":{"line":4,"column":11},"end":{"line":4,"column":15}},
"name": "foo"
},
"operator": "in",
"right": {
"type": "Identifier",
"start":65,"end":68,"loc":{"start":{"line":4,"column":19},"end":{"line":4,"column":22},"identifierName":"obj"},
"name": "obj"
}
}
}
]
}
}
}
]
}
}
]
}
}