Skip to content

Commit

Permalink
fix(parser): minor tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
KFlash committed Aug 20, 2019
1 parent f1bc71f commit 6a14bab
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 14 deletions.
13 changes: 12 additions & 1 deletion src/estree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export type Node =
| BreakStatement
| CallExpression
| OptionalExpression
| OptionalChain
| ImportExpression
| CatchClause
| ClassBody
Expand Down Expand Up @@ -153,6 +154,7 @@ export type Expression =
| ConditionalExpression
| MetaProperty
| OptionalExpression
| OptionalChain
| JSXClosingElement
| JSXClosingFragment
| JSXExpressionContainer
Expand All @@ -179,6 +181,7 @@ export type JSXTagNameExpression = JSXIdentifier | JSXMemberExpression | JSXName
export type LeftHandSideExpression =
| CallExpression
| OptionalExpression
| OptionalChain
| ImportExpression
| ClassExpression
| ClassDeclaration
Expand Down Expand Up @@ -344,7 +347,15 @@ export interface ImportExpression extends _Node {

export interface OptionalExpression extends _Node {
type: 'OptionalExpression';
expression: any;
object: Expression;
chain: OptionalChain | MemberExpression;
}
export interface OptionalChain extends _Node {
type: 'OptionalChain';
base: Expression | null;
property?: Expression;
computed?: boolean;
arguments?: any;
}

export interface CallExpression extends _Node {
Expand Down
25 changes: 12 additions & 13 deletions src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3933,7 +3933,7 @@ export function parseMemberOrUpdateExpression(
type: 'OptionalExpression',
object: expr,
chain: parseOptionalChain(parser, context, start, line, column)
} as any);
});
break;
}

Expand Down Expand Up @@ -3975,7 +3975,7 @@ export function parseOptionalChain(
// MemberExpression
// CallExpression
// OptionalExpression[
let base: any = null;
let base: ESTree.OptionalChain | ESTree.MemberExpression | null = null;
if (parser.token === Token.LeftBracket) {
nextToken(parser, context | Context.AllowRegExp);
const { tokenPos, linePos, colPos } = parser;
Expand All @@ -3987,7 +3987,7 @@ export function parseOptionalChain(
base: null,
computed: true,
property
} as any);
});
} else if (parser.token === Token.LeftParen) {
const args = parseArguments(parser, context, 0);

Expand All @@ -3997,32 +3997,31 @@ export function parseOptionalChain(
type: 'OptionalChain',
base: null,
arguments: args
} as any);
});
} else {
const property = parsePropertyOrPrivatePropertyName(parser, context);
if ((parser.token & (Token.IsIdentifier | Token.Keyword)) < 1) report(parser, Errors.InvalidDotProperty);
const property = parseIdentifier(parser, context, 0);
parser.assignable = AssignmentKind.CannotAssign;
base = finishNode(parser, context, start, line, column, {
type: 'OptionalChain',
base: null,
computed: false,
property
} as any);
});
}

while ((parser.token & Token.IsMemberOrCallExpression) === Token.IsMemberOrCallExpression) {
if (parser.token === Token.Period) {
nextToken(parser, context);

parser.assignable = AssignmentKind.Assignable;

const property = parsePropertyOrPrivatePropertyName(parser, context);

if ((parser.token & (Token.IsIdentifier | Token.Keyword)) < 1) report(parser, Errors.InvalidDotProperty);
const property = parseIdentifier(parser, context, 0);
base = finishNode(parser, context, parser.tokenPos, parser.linePos, parser.colPos, {
type: 'OptionalChain',
base,
computed: false,
property
} as any);
});
} else if (parser.token === Token.LeftBracket) {
nextToken(parser, context | Context.AllowRegExp);
const { tokenPos, linePos, colPos } = parser;
Expand All @@ -4034,7 +4033,7 @@ export function parseOptionalChain(
base,
computed: true,
property
} as any);
});
} else if (parser.token === Token.LeftParen) {
const args = parseArguments(parser, context, 0);

Expand All @@ -4044,7 +4043,7 @@ export function parseOptionalChain(
type: 'OptionalChain',
base,
arguments: args
} as any);
});
} else if (parser.token === Token.TemplateContinuation || parser.token === Token.TemplateSpan) {
report(parser, Errors.OptionalChainingNoTemplate);
} else {
Expand Down
1 change: 1 addition & 0 deletions test/parser/miscellaneous/grammar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1915,6 +1915,7 @@ describe('Miscellaneous - Cover grammar', () => {

// Failures
for (const arg of [
'for(let()of t)x',
'([a.b]) => 0',
'function foo() {for (let {x} = {} of []) {}; }; foo();',
'({set a([a.b]){}})',
Expand Down
24 changes: 24 additions & 0 deletions test/parser/next/optional-chaining.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,23 @@ describe('Next - Optional chaining', () => {
'arr?.[i + 1]',
'arr[0]?.a',
'arr[1]?.a',
'false?.4:5',
'delete o2?.x',
'greet.call?.({ suffix: "!" }, "world")',
'({ undefined: 3 })?.[null?.a]',
'(() => 3)?.(null?.a)',
'({})?.["i"]?.()',
'() => ({})?.["i"]()',
'0?.()',
'1?.()',
'[]?.()',
'({})?.["constructor"]',
'[]?.length',
'1?.valueOf()',
'0?.valueOf()',
'o1.x?.["y"];',
'o1.x?.();',
'null?.(o1.x);',
'obj?.c(10)',
'obj?.d();',
'(a?.b).c',
Expand Down Expand Up @@ -292,6 +309,13 @@ describe('Next - Optional chaining', () => {
['a.?.2', Context.OptionsNext],
['a.?2.n', Context.OptionsNext],
['a.?2.3', Context.OptionsNext],
['class C {} class D extends C { foo() { return super?.["bar"]; } }', Context.OptionsNext],
['const o = { C: class {} }; new o?.C();', Context.OptionsNext],
['const o = { C: class {} }; new o?.["C"]();', Context.OptionsNext],
['class C {} new C?.();', Context.OptionsNext],
['function foo() { new?.target; }', Context.OptionsNext],
['function tag() {} tag?.``;', Context.OptionsNext],
['const o = { tag() {} }; o?.tag``;', Context.OptionsNext],
['a.?2.?n', Context.OptionsNext],
['obj?.a = 33;', Context.OptionsNext],
['a.? (?) [?]', Context.OptionsNext],
Expand Down

0 comments on commit 6a14bab

Please sign in to comment.