Skip to content

Commit

Permalink
fix(parser): improved optional chaining implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
KFlash committed Aug 3, 2019
1 parent 6bcfda0 commit 2766dd9
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 19 deletions.
10 changes: 6 additions & 4 deletions src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,9 @@ export const enum Errors {
FinallyWithoutTry,
UnCorrespondingFragmentTag,
InvalidCoalescing,
InvalidChaining,
OptionalChainingNoTemplate
OptionalChainingNoTemplate,
OptionalChainingNoSuper,
OptionalChainingNoNew
}

/*@internal*/
Expand Down Expand Up @@ -355,8 +356,9 @@ export const errorMessages: {
[Errors.UnCorrespondingFragmentTag]: 'Expected corresponding closing tag for JSX fragment',
[Errors.InvalidCoalescing]:
'Coalescing and logical operators used together in the same expression must be disambiguated with parentheses',
[Errors.InvalidChaining]: 'Constructors in/after an Optional Chain are not allowed',
[Errors.OptionalChainingNoTemplate]: 'Tagged Template Literals are not allowed in optionalChain'
[Errors.OptionalChainingNoTemplate]: 'Invalid tagged template on optional chain',
[Errors.OptionalChainingNoSuper]: 'Invalid optional chain from super property',
[Errors.OptionalChainingNoNew]: 'Invalid optional chain from new expression'
};

export class ParseError extends SyntaxError {
Expand Down
32 changes: 17 additions & 15 deletions src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3548,6 +3548,8 @@ export function parseSuperExpression(
nextToken(parser, context);

switch (parser.token) {
case Token.QuestionMarkPeriod:
report(parser, Errors.OptionalChainingNoSuper);
case Token.LeftParen: {
// The super property has to be within a class constructor
if ((context & Context.SuperCall) < 1) report(parser, Errors.SuperNoConstructor);
Expand Down Expand Up @@ -3643,7 +3645,7 @@ export function parseMemberOrUpdateExpression(
});
}

if (parser.token & Token.IsMemberOrCallExpression) {
if ((parser.token & Token.IsMemberOrCallExpression) === Token.IsMemberOrCallExpression || isOptional) {
context = context & ~Context.DisallowIn;

switch (parser.token) {
Expand Down Expand Up @@ -3739,6 +3741,19 @@ export function parseMemberOrUpdateExpression(

/* Template */
default: {
if (context & Context.OptionsNext && isOptional && parser.token & Token.IsIdentifier) {
parser.assignable = AssignmentKind.CannotAssign;
const property = parsePropertyOrPrivatePropertyName(parser, context);
expr = finishNode(parser, context, start, line, column, {
type: 'MemberExpression',
optional: true,
object: expr,
computed: false,
property
});
isOptional = 0;
break;
}
if (optionalChaining) report(parser, Errors.OptionalChainingNoTemplate);

parser.assignable = AssignmentKind.CannotAssign;
Expand All @@ -3754,19 +3769,6 @@ export function parseMemberOrUpdateExpression(
}
}

if (context & Context.OptionsNext && isOptional && parser.token & Token.IsIdentifier) {
parser.assignable = AssignmentKind.CannotAssign;
const property = parsePropertyOrPrivatePropertyName(parser, context);
expr = finishNode(parser, context, start, line, column, {
type: 'MemberExpression',
optional: true,
object: expr,
computed: false,
property
});
isOptional = 0;
}

return parseMemberOrUpdateExpression(parser, context, expr, 0, start, line, column, isOptional, optionalChaining);
}

Expand Down Expand Up @@ -7222,7 +7224,7 @@ export function parseNewExpression(
colPos
);

if (parser.token === Token.QuestionMarkPeriod) report(parser, Errors.InvalidChaining);
if (parser.token === Token.QuestionMarkPeriod) report(parser, Errors.OptionalChainingNoNew);

// NewExpression without arguments.
const callee = parseMembeExpressionNoCall(parser, context, expr, inGroup, tokenPos, linePos, colPos);
Expand Down

0 comments on commit 2766dd9

Please sign in to comment.