Refactor bindingProperty parsing (#13929)
* refactor: inline parseMaybePrivateName * correct test case * perf: fast exit in checkExpressionErrors * refactor: add parseBindingProperty * fix: private property with variance * Update packages/babel-parser/src/parser/expression.js Co-authored-by: Nicolò Ribaudo <nicolo.ribaudo@gmail.com> * chore: update testcase * refactor: remove refExpressionErrors for record/tuple They are always non-ambiguous. Co-authored-by: Nicolò Ribaudo <nicolo.ribaudo@gmail.com>
This commit is contained in:
parent
135ab837bc
commit
54c539ecc1
@ -124,7 +124,7 @@ export default class ExpressionParser extends LValParser {
|
||||
|
||||
checkProto(
|
||||
prop: N.ObjectMember | N.SpreadElement,
|
||||
isRecord: boolean,
|
||||
isRecord: ?boolean,
|
||||
protoRef: { used: boolean },
|
||||
refExpressionErrors: ?ExpressionErrors,
|
||||
): void {
|
||||
@ -402,7 +402,7 @@ export default class ExpressionParser extends LValParser {
|
||||
minPrec: number,
|
||||
): N.Expression {
|
||||
if (this.isPrivateName(left)) {
|
||||
// https://tc39.es/proposal-private-fields-in-in
|
||||
// https://tc39.es/ecma262/#prod-RelationalExpression
|
||||
// RelationalExpression [In, Yield, Await]
|
||||
// [+In] PrivateIdentifier in ShiftExpression[?Yield, ?Await]
|
||||
|
||||
@ -1120,7 +1120,6 @@ export default class ExpressionParser extends LValParser {
|
||||
this.state.type === tt.bracketBarL ? tt.bracketBarR : tt.bracketR,
|
||||
/* canBePattern */ false,
|
||||
/* isTuple */ true,
|
||||
refExpressionErrors,
|
||||
);
|
||||
}
|
||||
case tt.bracketL: {
|
||||
@ -1137,7 +1136,6 @@ export default class ExpressionParser extends LValParser {
|
||||
this.state.type === tt.braceBarL ? tt.braceBarR : tt.braceR,
|
||||
/* isPattern */ false,
|
||||
/* isRecord */ true,
|
||||
refExpressionErrors,
|
||||
);
|
||||
}
|
||||
case tt.braceL: {
|
||||
@ -1513,21 +1511,6 @@ export default class ExpressionParser extends LValParser {
|
||||
return this.finishNode(node, "Super");
|
||||
}
|
||||
|
||||
parseMaybePrivateName(
|
||||
isPrivateNameAllowed: boolean,
|
||||
): N.PrivateName | N.Identifier {
|
||||
const isPrivate = this.match(tt.privateName);
|
||||
|
||||
if (isPrivate) {
|
||||
if (!isPrivateNameAllowed) {
|
||||
this.raise(this.state.start + 1, Errors.UnexpectedPrivateField);
|
||||
}
|
||||
return this.parsePrivateName();
|
||||
} else {
|
||||
return this.parseIdentifier(true);
|
||||
}
|
||||
}
|
||||
|
||||
parsePrivateName(): N.PrivateName {
|
||||
const node = this.startNode();
|
||||
const id = this.startNodeAt(
|
||||
@ -1925,9 +1908,11 @@ export default class ExpressionParser extends LValParser {
|
||||
}
|
||||
}
|
||||
|
||||
const prop = this.parsePropertyDefinition(isPattern, refExpressionErrors);
|
||||
if (!isPattern) {
|
||||
// $FlowIgnore RestElement will never be returned if !isPattern
|
||||
let prop;
|
||||
if (isPattern) {
|
||||
prop = this.parseBindingProperty();
|
||||
} else {
|
||||
prop = this.parsePropertyDefinition(refExpressionErrors);
|
||||
this.checkProto(prop, isRecord, propHash, refExpressionErrors);
|
||||
}
|
||||
|
||||
@ -1974,9 +1959,8 @@ export default class ExpressionParser extends LValParser {
|
||||
|
||||
// https://tc39.es/ecma262/#prod-PropertyDefinition
|
||||
parsePropertyDefinition(
|
||||
isPattern: boolean,
|
||||
refExpressionErrors?: ?ExpressionErrors,
|
||||
): N.ObjectMember | N.SpreadElement | N.RestElement {
|
||||
): N.ObjectMember | N.SpreadElement {
|
||||
let decorators = [];
|
||||
if (this.match(tt.at)) {
|
||||
if (this.hasPlugin("decorators")) {
|
||||
@ -1991,7 +1975,6 @@ export default class ExpressionParser extends LValParser {
|
||||
}
|
||||
|
||||
const prop = this.startNode();
|
||||
let isGenerator = false;
|
||||
let isAsync = false;
|
||||
let isAccessor = false;
|
||||
let startPos;
|
||||
@ -1999,14 +1982,6 @@ export default class ExpressionParser extends LValParser {
|
||||
|
||||
if (this.match(tt.ellipsis)) {
|
||||
if (decorators.length) this.unexpected();
|
||||
if (isPattern) {
|
||||
this.next();
|
||||
// Don't use parseRestBinding() as we only allow Identifier here.
|
||||
prop.argument = this.parseIdentifier();
|
||||
this.checkCommaAfterRest(charCodes.rightCurlyBrace);
|
||||
return this.finishNode(prop, "RestElement");
|
||||
}
|
||||
|
||||
return this.parseSpread();
|
||||
}
|
||||
|
||||
@ -2017,24 +1992,17 @@ export default class ExpressionParser extends LValParser {
|
||||
|
||||
prop.method = false;
|
||||
|
||||
if (isPattern || refExpressionErrors) {
|
||||
if (refExpressionErrors) {
|
||||
startPos = this.state.start;
|
||||
startLoc = this.state.startLoc;
|
||||
}
|
||||
|
||||
if (!isPattern) {
|
||||
isGenerator = this.eat(tt.star);
|
||||
}
|
||||
|
||||
let isGenerator = this.eat(tt.star);
|
||||
this.parsePropertyNamePrefixOperator(prop);
|
||||
const containsEsc = this.state.containsEsc;
|
||||
const key = this.parsePropertyName(prop, /* isPrivateNameAllowed */ false);
|
||||
const key = this.parsePropertyName(prop);
|
||||
|
||||
if (
|
||||
!isPattern &&
|
||||
!isGenerator &&
|
||||
!containsEsc &&
|
||||
this.maybeAsyncOrAccessorProp(prop)
|
||||
) {
|
||||
if (!isGenerator && !containsEsc && this.maybeAsyncOrAccessorProp(prop)) {
|
||||
const keyName = key.name;
|
||||
// https://tc39.es/ecma262/#prod-AsyncMethod
|
||||
// https://tc39.es/ecma262/#prod-AsyncGeneratorMethod
|
||||
@ -2042,7 +2010,7 @@ export default class ExpressionParser extends LValParser {
|
||||
isAsync = true;
|
||||
this.resetPreviousNodeTrailingComments(key);
|
||||
isGenerator = this.eat(tt.star);
|
||||
this.parsePropertyName(prop, /* isPrivateNameAllowed */ false);
|
||||
this.parsePropertyName(prop);
|
||||
}
|
||||
// get PropertyName[?Yield, ?Await] () { FunctionBody[~Yield, ~Await] }
|
||||
// set PropertyName[?Yield, ?Await] ( PropertySetParameterList ) { FunctionBody[~Yield, ~Await] }
|
||||
@ -2055,7 +2023,7 @@ export default class ExpressionParser extends LValParser {
|
||||
this.raise(this.state.pos, Errors.AccessorIsGenerator, keyName);
|
||||
this.next();
|
||||
}
|
||||
this.parsePropertyName(prop, /* isPrivateNameAllowed */ false);
|
||||
this.parsePropertyName(prop);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2065,7 +2033,7 @@ export default class ExpressionParser extends LValParser {
|
||||
startLoc,
|
||||
isGenerator,
|
||||
isAsync,
|
||||
isPattern,
|
||||
false /* isPattern */,
|
||||
isAccessor,
|
||||
refExpressionErrors,
|
||||
);
|
||||
@ -2231,7 +2199,6 @@ export default class ExpressionParser extends LValParser {
|
||||
|
||||
parsePropertyName(
|
||||
prop: N.ObjectOrClassMember | N.ClassMember | N.TsNamedTypeElementBase,
|
||||
isPrivateNameAllowed: boolean,
|
||||
): N.Expression | N.Identifier {
|
||||
if (this.eat(tt.bracketL)) {
|
||||
(prop: $FlowSubtype<N.ObjectOrClassMember>).computed = true;
|
||||
@ -2239,15 +2206,37 @@ export default class ExpressionParser extends LValParser {
|
||||
this.expect(tt.bracketR);
|
||||
} else {
|
||||
// We check if it's valid for it to be a private name when we push it.
|
||||
const type = this.state.type;
|
||||
(prop: $FlowFixMe).key =
|
||||
type === tt.num ||
|
||||
type === tt.string ||
|
||||
type === tt.bigint ||
|
||||
type === tt.decimal
|
||||
? this.parseExprAtom()
|
||||
: this.parseMaybePrivateName(isPrivateNameAllowed);
|
||||
|
||||
const { type, value } = this.state;
|
||||
let key;
|
||||
// most un-computed property names are identifiers
|
||||
if (tokenIsKeywordOrIdentifier(type)) {
|
||||
key = this.parseIdentifier(true);
|
||||
} else {
|
||||
switch (type) {
|
||||
case tt.num:
|
||||
key = this.parseNumericLiteral(value);
|
||||
break;
|
||||
case tt.string:
|
||||
key = this.parseStringLiteral(value);
|
||||
break;
|
||||
case tt.bigint:
|
||||
key = this.parseBigIntLiteral(value);
|
||||
break;
|
||||
case tt.decimal:
|
||||
key = this.parseDecimalLiteral(value);
|
||||
break;
|
||||
case tt.privateName: {
|
||||
// the class private key has been handled in parseClassElementName
|
||||
const privateKeyPos = this.state.start + 1;
|
||||
this.raise(privateKeyPos, Errors.UnexpectedPrivateField);
|
||||
key = this.parsePrivateName();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw this.unexpected();
|
||||
}
|
||||
}
|
||||
(prop: $FlowFixMe).key = key;
|
||||
if (type !== tt.privateName) {
|
||||
// ClassPrivateProperty is never computed, so we don't assign in that case.
|
||||
prop.computed = false;
|
||||
@ -2974,4 +2963,10 @@ export default class ExpressionParser extends LValParser {
|
||||
this.eat(tt.braceR);
|
||||
return this.finishNode<N.ModuleExpression>(node, "ModuleExpression");
|
||||
}
|
||||
|
||||
// Used in Flow plugin
|
||||
parsePropertyNamePrefixOperator(
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
prop: N.ObjectOrClassMember | N.ClassMember,
|
||||
): void {}
|
||||
}
|
||||
|
||||
@ -11,6 +11,10 @@ import type {
|
||||
Pattern,
|
||||
RestElement,
|
||||
SpreadElement,
|
||||
/*:: ObjectOrClassMember, */
|
||||
/*:: ClassMember, */
|
||||
/*:: ObjectMember, */
|
||||
/*:: TsNamedTypeElementBase, */
|
||||
/*:: Identifier, */
|
||||
/*:: ObjectExpression, */
|
||||
/*:: ObjectPattern, */
|
||||
@ -46,6 +50,19 @@ export default class LValParser extends NodeUtils {
|
||||
isRecord?: ?boolean,
|
||||
refExpressionErrors?: ?ExpressionErrors,
|
||||
) => T;
|
||||
+parseObjPropValue: (
|
||||
prop: any,
|
||||
startPos: ?number,
|
||||
startLoc: ?Position,
|
||||
isGenerator: boolean,
|
||||
isAsync: boolean,
|
||||
isPattern: boolean,
|
||||
isAccessor: boolean,
|
||||
refExpressionErrors?: ?ExpressionErrors,
|
||||
) => void;
|
||||
+parsePropertyName: (
|
||||
prop: ObjectOrClassMember | ClassMember | TsNamedTypeElementBase,
|
||||
) => Expression | Identifier;
|
||||
*/
|
||||
// Forward-declaration: defined in statement.js
|
||||
/*::
|
||||
@ -386,6 +403,38 @@ export default class LValParser extends NodeUtils {
|
||||
return elts;
|
||||
}
|
||||
|
||||
// https://tc39.es/ecma262/#prod-BindingRestProperty
|
||||
parseBindingRestProperty(prop: RestElement): RestElement {
|
||||
this.next(); // eat '...'
|
||||
// Don't use parseRestBinding() as we only allow Identifier here.
|
||||
prop.argument = this.parseIdentifier();
|
||||
this.checkCommaAfterRest(charCodes.rightCurlyBrace);
|
||||
return this.finishNode(prop, "RestElement");
|
||||
}
|
||||
|
||||
// https://tc39.es/ecma262/#prod-BindingProperty
|
||||
parseBindingProperty(): ObjectMember | RestElement {
|
||||
const prop = this.startNode();
|
||||
const { type, start: startPos, startLoc } = this.state;
|
||||
if (type === tt.ellipsis) {
|
||||
return this.parseBindingRestProperty(prop);
|
||||
} else {
|
||||
this.parsePropertyName(prop);
|
||||
}
|
||||
prop.method = false;
|
||||
this.parseObjPropValue(
|
||||
prop,
|
||||
startPos,
|
||||
startLoc,
|
||||
false /* isGenerator */,
|
||||
false /* isAsync */,
|
||||
true /* isPattern */,
|
||||
false /* isAccessor */,
|
||||
);
|
||||
|
||||
return prop;
|
||||
}
|
||||
|
||||
parseAssignableListItem(
|
||||
allowModifiers: ?boolean,
|
||||
decorators: Decorator[],
|
||||
|
||||
@ -1437,6 +1437,7 @@ export default class StatementParser extends ExpressionParser {
|
||||
const publicMember: typeof publicMethod | typeof publicProp = publicMethod;
|
||||
|
||||
member.static = isStatic;
|
||||
this.parsePropertyNamePrefixOperator(member);
|
||||
|
||||
if (this.eat(tt.star)) {
|
||||
// a generator
|
||||
@ -1597,7 +1598,7 @@ export default class StatementParser extends ExpressionParser {
|
||||
}
|
||||
}
|
||||
|
||||
// https://tc39.es/proposal-class-fields/#prod-ClassElementName
|
||||
// https://tc39.es/ecma262/#prod-ClassElementName
|
||||
parseClassElementName(member: N.ClassMember): N.Expression | N.Identifier {
|
||||
const { type, value, start } = this.state;
|
||||
if (
|
||||
@ -1608,11 +1609,16 @@ export default class StatementParser extends ExpressionParser {
|
||||
this.raise(start, Errors.StaticPrototype);
|
||||
}
|
||||
|
||||
if (type === tt.privateName && value === "constructor") {
|
||||
this.raise(start, Errors.ConstructorClassPrivateField);
|
||||
if (type === tt.privateName) {
|
||||
if (value === "constructor") {
|
||||
this.raise(start, Errors.ConstructorClassPrivateField);
|
||||
}
|
||||
const key = this.parsePrivateName();
|
||||
member.key = key;
|
||||
return key;
|
||||
}
|
||||
|
||||
return this.parsePropertyName(member, /* isPrivateNameAllowed */ true);
|
||||
return this.parsePropertyName(member);
|
||||
}
|
||||
|
||||
parseClassStaticBlock(
|
||||
@ -1733,7 +1739,7 @@ export default class StatementParser extends ExpressionParser {
|
||||
methodOrProp: N.ClassMethod | N.ClassProperty,
|
||||
): void {}
|
||||
|
||||
// https://tc39.es/proposal-class-fields/#prod-FieldDefinition
|
||||
// https://tc39.es/ecma262/#prod-FieldDefinition
|
||||
parseClassPrivateProperty(
|
||||
node: N.ClassPrivateProperty,
|
||||
): N.ClassPrivateProperty {
|
||||
@ -1742,14 +1748,14 @@ export default class StatementParser extends ExpressionParser {
|
||||
return this.finishNode(node, "ClassPrivateProperty");
|
||||
}
|
||||
|
||||
// https://tc39.es/proposal-class-fields/#prod-FieldDefinition
|
||||
// https://tc39.es/ecma262/#prod-FieldDefinition
|
||||
parseClassProperty(node: N.ClassProperty): N.ClassProperty {
|
||||
this.parseInitializer(node);
|
||||
this.semicolon();
|
||||
return this.finishNode(node, "ClassProperty");
|
||||
}
|
||||
|
||||
// https://tc39.es/proposal-class-fields/#prod-Initializer
|
||||
// https://tc39.es/ecma262/#prod-Initializer
|
||||
parseInitializer(node: N.ClassProperty | N.ClassPrivateProperty): void {
|
||||
this.scope.enter(SCOPE_CLASS | SCOPE_SUPER);
|
||||
this.expressionScope.enter(newExpressionScope());
|
||||
|
||||
@ -264,19 +264,20 @@ export default class UtilParser extends Tokenizer {
|
||||
if (!refExpressionErrors) return false;
|
||||
const { shorthandAssign, doubleProto, optionalParameters } =
|
||||
refExpressionErrors;
|
||||
// shorthandAssign >= 0 || doubleProto >= 0 || optionalParameters >= 0
|
||||
const hasErrors = shorthandAssign + doubleProto + optionalParameters > -3;
|
||||
if (!andThrow) {
|
||||
return (
|
||||
shorthandAssign >= 0 || doubleProto >= 0 || optionalParameters >= 0
|
||||
);
|
||||
}
|
||||
if (shorthandAssign >= 0) {
|
||||
this.unexpected(shorthandAssign);
|
||||
}
|
||||
if (doubleProto >= 0) {
|
||||
this.raise(doubleProto, Errors.DuplicateProto);
|
||||
}
|
||||
if (optionalParameters >= 0) {
|
||||
this.unexpected(optionalParameters);
|
||||
return hasErrors;
|
||||
} else if (hasErrors) {
|
||||
if (shorthandAssign >= 0) {
|
||||
this.unexpected(shorthandAssign);
|
||||
}
|
||||
if (doubleProto >= 0) {
|
||||
this.raise(doubleProto, Errors.DuplicateProto);
|
||||
}
|
||||
if (optionalParameters >= 0) {
|
||||
this.unexpected(optionalParameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -304,7 +305,7 @@ export default class UtilParser extends Tokenizer {
|
||||
/*
|
||||
* Return the string value of a given private name
|
||||
* WITHOUT `#`
|
||||
* @see {@link https://tc39.es/proposal-class-fields/#sec-private-names-static-semantics-stringvalue}
|
||||
* @see {@link https://tc39.es/ecma262/#sec-static-semantics-stringvalue}
|
||||
*/
|
||||
getPrivateNameSV(node: Node): string {
|
||||
return node.id.name;
|
||||
|
||||
@ -2475,15 +2475,10 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
}
|
||||
}
|
||||
|
||||
parsePropertyName(
|
||||
node: N.ObjectOrClassMember | N.ClassMember | N.TsNamedTypeElementBase,
|
||||
isPrivateNameAllowed: boolean,
|
||||
): N.Identifier {
|
||||
const variance = this.flowParseVariance();
|
||||
const key = super.parsePropertyName(node, isPrivateNameAllowed);
|
||||
// $FlowIgnore ("variance" not defined on TsNamedTypeElementBase)
|
||||
node.variance = variance;
|
||||
return key;
|
||||
parsePropertyNamePrefixOperator(
|
||||
node: N.ObjectOrClassMember | N.ClassMember,
|
||||
): void {
|
||||
node.variance = this.flowParseVariance();
|
||||
}
|
||||
|
||||
// parse type parameters for object method shorthand
|
||||
|
||||
@ -780,7 +780,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
return idx;
|
||||
}
|
||||
|
||||
this.parsePropertyName(node, /* isPrivateNameAllowed */ false);
|
||||
this.parsePropertyName(node);
|
||||
if (
|
||||
!node.computed &&
|
||||
node.key.type === "Identifier" &&
|
||||
@ -788,7 +788,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
this.tsTokenCanFollowModifier()
|
||||
) {
|
||||
node.kind = node.key.name;
|
||||
this.parsePropertyName(node, /* isPrivateNameAllowed */ false);
|
||||
this.parsePropertyName(node);
|
||||
}
|
||||
return this.tsParsePropertyOrMethodSignature(node, !!node.readonly);
|
||||
}
|
||||
|
||||
@ -816,6 +816,7 @@ export type ClassPrivateMethod = NodeBase &
|
||||
type: "ClassPrivateMethod",
|
||||
key: PrivateName,
|
||||
computed: false,
|
||||
variance?: ?FlowVariance, // TODO: Not in spec
|
||||
};
|
||||
|
||||
export type ClassProperty = ClassMemberBase &
|
||||
@ -825,6 +826,8 @@ export type ClassProperty = ClassMemberBase &
|
||||
value: ?Expression, // TODO: Not in spec that this is nullable.
|
||||
|
||||
typeAnnotation?: ?TypeAnnotationBase, // TODO: Not in spec
|
||||
|
||||
// Flow only:
|
||||
variance?: ?FlowVariance, // TODO: Not in spec
|
||||
|
||||
// TypeScript only: (TODO: Not in spec)
|
||||
@ -847,6 +850,9 @@ export type ClassPrivateProperty = NodeBase & {
|
||||
definite?: true,
|
||||
readonly?: true,
|
||||
override?: true,
|
||||
|
||||
// Flow only
|
||||
variance?: ?FlowVariance,
|
||||
};
|
||||
|
||||
export type OptClassDeclaration = ClassBase &
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
class C {
|
||||
#p = ({ #x: 42 });
|
||||
#p = ({ #x() {} });
|
||||
}
|
||||
|
||||
@ -1,18 +1,18 @@
|
||||
{
|
||||
"type": "File",
|
||||
"start":0,"end":32,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
|
||||
"start":0,"end":33,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
|
||||
"errors": [
|
||||
"SyntaxError: Private names can only be used as the name of a class element (i.e. class C { #p = 42; #m() {} } )\n or a property of member expression (i.e. this.#p). (2:11)"
|
||||
],
|
||||
"program": {
|
||||
"type": "Program",
|
||||
"start":0,"end":32,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
|
||||
"start":0,"end":33,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
|
||||
"sourceType": "script",
|
||||
"interpreter": null,
|
||||
"body": [
|
||||
{
|
||||
"type": "ClassDeclaration",
|
||||
"start":0,"end":32,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
|
||||
"start":0,"end":33,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"start":6,"end":7,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":7},"identifierName":"C"},
|
||||
@ -21,11 +21,11 @@
|
||||
"superClass": null,
|
||||
"body": {
|
||||
"type": "ClassBody",
|
||||
"start":8,"end":32,"loc":{"start":{"line":1,"column":8},"end":{"line":3,"column":1}},
|
||||
"start":8,"end":33,"loc":{"start":{"line":1,"column":8},"end":{"line":3,"column":1}},
|
||||
"body": [
|
||||
{
|
||||
"type": "ClassPrivateProperty",
|
||||
"start":12,"end":30,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":20}},
|
||||
"start":12,"end":31,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":21}},
|
||||
"static": false,
|
||||
"key": {
|
||||
"type": "PrivateName",
|
||||
@ -38,12 +38,12 @@
|
||||
},
|
||||
"value": {
|
||||
"type": "ObjectExpression",
|
||||
"start":18,"end":28,"loc":{"start":{"line":2,"column":8},"end":{"line":2,"column":18}},
|
||||
"start":18,"end":29,"loc":{"start":{"line":2,"column":8},"end":{"line":2,"column":19}},
|
||||
"properties": [
|
||||
{
|
||||
"type": "ObjectProperty",
|
||||
"start":20,"end":26,"loc":{"start":{"line":2,"column":10},"end":{"line":2,"column":16}},
|
||||
"method": false,
|
||||
"type": "ObjectMethod",
|
||||
"start":20,"end":27,"loc":{"start":{"line":2,"column":10},"end":{"line":2,"column":17}},
|
||||
"method": true,
|
||||
"key": {
|
||||
"type": "PrivateName",
|
||||
"start":20,"end":22,"loc":{"start":{"line":2,"column":10},"end":{"line":2,"column":12}},
|
||||
@ -53,15 +53,16 @@
|
||||
"name": "x"
|
||||
}
|
||||
},
|
||||
"shorthand": false,
|
||||
"value": {
|
||||
"type": "NumericLiteral",
|
||||
"start":24,"end":26,"loc":{"start":{"line":2,"column":14},"end":{"line":2,"column":16}},
|
||||
"extra": {
|
||||
"rawValue": 42,
|
||||
"raw": "42"
|
||||
},
|
||||
"value": 42
|
||||
"kind": "method",
|
||||
"id": null,
|
||||
"generator": false,
|
||||
"async": false,
|
||||
"params": [],
|
||||
"body": {
|
||||
"type": "BlockStatement",
|
||||
"start":25,"end":27,"loc":{"start":{"line":2,"column":15},"end":{"line":2,"column":17}},
|
||||
"body": [],
|
||||
"directives": []
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
class C {
|
||||
#p = ({ #x: 42 });
|
||||
}
|
||||
@ -0,0 +1,80 @@
|
||||
{
|
||||
"type": "File",
|
||||
"start":0,"end":32,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
|
||||
"errors": [
|
||||
"SyntaxError: Private names can only be used as the name of a class element (i.e. class C { #p = 42; #m() {} } )\n or a property of member expression (i.e. this.#p). (2:11)"
|
||||
],
|
||||
"program": {
|
||||
"type": "Program",
|
||||
"start":0,"end":32,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
|
||||
"sourceType": "script",
|
||||
"interpreter": null,
|
||||
"body": [
|
||||
{
|
||||
"type": "ClassDeclaration",
|
||||
"start":0,"end":32,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"start":6,"end":7,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":7},"identifierName":"C"},
|
||||
"name": "C"
|
||||
},
|
||||
"superClass": null,
|
||||
"body": {
|
||||
"type": "ClassBody",
|
||||
"start":8,"end":32,"loc":{"start":{"line":1,"column":8},"end":{"line":3,"column":1}},
|
||||
"body": [
|
||||
{
|
||||
"type": "ClassPrivateProperty",
|
||||
"start":12,"end":30,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":20}},
|
||||
"static": false,
|
||||
"key": {
|
||||
"type": "PrivateName",
|
||||
"start":12,"end":14,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":4}},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"start":13,"end":14,"loc":{"start":{"line":2,"column":3},"end":{"line":2,"column":4},"identifierName":"p"},
|
||||
"name": "p"
|
||||
}
|
||||
},
|
||||
"value": {
|
||||
"type": "ObjectExpression",
|
||||
"start":18,"end":28,"loc":{"start":{"line":2,"column":8},"end":{"line":2,"column":18}},
|
||||
"properties": [
|
||||
{
|
||||
"type": "ObjectProperty",
|
||||
"start":20,"end":26,"loc":{"start":{"line":2,"column":10},"end":{"line":2,"column":16}},
|
||||
"method": false,
|
||||
"key": {
|
||||
"type": "PrivateName",
|
||||
"start":20,"end":22,"loc":{"start":{"line":2,"column":10},"end":{"line":2,"column":12}},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"start":21,"end":22,"loc":{"start":{"line":2,"column":11},"end":{"line":2,"column":12},"identifierName":"x"},
|
||||
"name": "x"
|
||||
}
|
||||
},
|
||||
"shorthand": false,
|
||||
"value": {
|
||||
"type": "NumericLiteral",
|
||||
"start":24,"end":26,"loc":{"start":{"line":2,"column":14},"end":{"line":2,"column":16}},
|
||||
"extra": {
|
||||
"rawValue": 42,
|
||||
"raw": "42"
|
||||
},
|
||||
"value": 42
|
||||
}
|
||||
}
|
||||
],
|
||||
"extra": {
|
||||
"parenthesized": true,
|
||||
"parenStart": 17
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"directives": []
|
||||
}
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
var { @foo foo } = foo;
|
||||
@ -0,0 +1,4 @@
|
||||
{
|
||||
"plugins": [["decorators-legacy"]],
|
||||
"throws": "Unexpected token (1:6)"
|
||||
}
|
||||
4
packages/babel-parser/test/fixtures/flow/class-private-property/variance/input.js
vendored
Normal file
4
packages/babel-parser/test/fixtures/flow/class-private-property/variance/input.js
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
class A {
|
||||
+#foo;
|
||||
-#bar;
|
||||
}
|
||||
69
packages/babel-parser/test/fixtures/flow/class-private-property/variance/output.json
vendored
Normal file
69
packages/babel-parser/test/fixtures/flow/class-private-property/variance/output.json
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
{
|
||||
"type": "File",
|
||||
"start":0,"end":29,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}},
|
||||
"program": {
|
||||
"type": "Program",
|
||||
"start":0,"end":29,"loc":{"start":{"line":1,"column":0},"end":{"line":4,"column":1}},
|
||||
"sourceType": "module",
|
||||
"interpreter": null,
|
||||
"body": [
|
||||
{
|
||||
"type": "ClassDeclaration",
|
||||
"start":0,"end":29,"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":29,"loc":{"start":{"line":1,"column":8},"end":{"line":4,"column":1}},
|
||||
"body": [
|
||||
{
|
||||
"type": "ClassPrivateProperty",
|
||||
"start":12,"end":18,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":8}},
|
||||
"static": false,
|
||||
"variance": {
|
||||
"type": "Variance",
|
||||
"start":12,"end":13,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":3}},
|
||||
"kind": "plus"
|
||||
},
|
||||
"key": {
|
||||
"type": "PrivateName",
|
||||
"start":13,"end":17,"loc":{"start":{"line":2,"column":3},"end":{"line":2,"column":7}},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"start":14,"end":17,"loc":{"start":{"line":2,"column":4},"end":{"line":2,"column":7},"identifierName":"foo"},
|
||||
"name": "foo"
|
||||
}
|
||||
},
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"type": "ClassPrivateProperty",
|
||||
"start":21,"end":27,"loc":{"start":{"line":3,"column":2},"end":{"line":3,"column":8}},
|
||||
"static": false,
|
||||
"variance": {
|
||||
"type": "Variance",
|
||||
"start":21,"end":22,"loc":{"start":{"line":3,"column":2},"end":{"line":3,"column":3}},
|
||||
"kind": "minus"
|
||||
},
|
||||
"key": {
|
||||
"type": "PrivateName",
|
||||
"start":22,"end":26,"loc":{"start":{"line":3,"column":3},"end":{"line":3,"column":7}},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"start":23,"end":26,"loc":{"start":{"line":3,"column":4},"end":{"line":3,"column":7},"identifierName":"bar"},
|
||||
"name": "bar"
|
||||
}
|
||||
},
|
||||
"value": null
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"directives": []
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user