Skip to content

Commit

Permalink
fix(parser): fixed import call and added 'ImportExpression' AST node
Browse files Browse the repository at this point in the history
  • Loading branch information
KFlash committed Jun 12, 2019
1 parent 5265848 commit f735377
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 957 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "meriyah",
"version": "0.3.0",
"version": "0.3.1",
"description": "A 100% compliant, self-hosted javascript parser with high focus on both performance and stability",
"main": "dist/meriyah.umd.js",
"module": "dist/meriyah.esm.js",
Expand Down
10 changes: 6 additions & 4 deletions src/estree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ export type Expression =
| PrivateName
| ConditionalExpression
| CallExpression
| ImportExpression
| NewExpression
| SequenceExpression
| ArrowFunctionExpression
Expand Down Expand Up @@ -352,6 +353,7 @@ type Expression =
| LogicalExpression
| MemberExpression
| ConditionalExpression
| ImportExpression
| CallExpression
| NewExpression
| SequenceExpression
Expand Down Expand Up @@ -429,13 +431,13 @@ export interface ConditionalExpression extends _Expression<'ConditionalExpressio
}

export interface CallExpression extends _Expression<'CallExpression'> {
callee: Expression | Import | Super;
callee: Expression | Super;
arguments: (Expression | SpreadElement)[];
}

export interface Import extends _Node<'Import'> {}

export interface ImportExpression extends _Expression<'Import'> {}
export interface ImportExpression extends _Expression<'ImportExpression'> {
source: Expression;
}

export interface NewExpression extends _Expression<'NewExpression'> {
callee: Expression;
Expand Down
67 changes: 48 additions & 19 deletions src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1945,9 +1945,10 @@ function parseImportSpecifierOrNamedImports(
*
* @param parser Parser object
* @param context Context masks
* @param number
*/
function parseImportCallDeclaration(parser: ParserState, context: Context, start: number) {
let expr: ESTree.ImportExpression = finishNode(parser, context, start, { type: 'Import' } as any);
function parseImportCallDeclaration(parser: ParserState, context: Context, start: number): ESTree.ExpressionStatement {
let expr = parseImportExpression(parser, context, /* inGroup */ 0, start);

/** MemberExpression :
* 1. PrimaryExpression
Expand All @@ -1967,7 +1968,6 @@ function parseImportCallDeclaration(parser: ParserState, context: Context, start
* ('++' | '--')? LeftHandSideExpression
*
*/

expr = parseMemberOrUpdateExpression(parser, context, expr as any, 0, 1, 0, start);

/**
Expand Down Expand Up @@ -2544,7 +2544,7 @@ export function parseYieldExpressionOrIdentifier(parser: ParserState, context: C
}

if (context & Context.Strict) report(parser, Errors.AwaitOrYieldIdentInModule, 'Yield');
return parseIdentifierOrArrow(parser, context, start);
return parseIdentifierOrArrow(parser, context, parseIdentifier(parser, context, start), start);
}

/**
Expand Down Expand Up @@ -2581,7 +2581,7 @@ export function parseAwaitExpressionOrIdentifier(

if (context & Context.Module) report(parser, Errors.AwaitOrYieldIdentInModule, 'Await');

const expr = parseIdentifierOrArrow(parser, context, start);
const expr = parseIdentifierOrArrow(parser, context, parseIdentifier(parser, context, start), start);

parser.assignable = AssignmentKind.IsAssignable;

Expand Down Expand Up @@ -3030,39 +3030,72 @@ export function parsePrimaryExpressionExtended(
(token & Token.FutureReserved) === Token.FutureReserved
) {
parser.assignable = AssignmentKind.IsAssignable;
return parseIdentifierOrArrow(parser, context, start);
return parseIdentifierOrArrow(parser, context, parseIdentifier(parser, context, start), start);
}

report(parser, Errors.UnexpectedToken, KeywordDescTable[parser.token & Token.Type]);
}
}

/**
* Parses Import call expression
*
* @param parser Parser object
* @param context Context masks
* @param inGroup
* @param start
*/
function parseImportCallExpression(
parser: ParserState,
context: Context,
inNewExpression: 0 | 1,
inGroup: 0 | 1,
start: number
): ESTree.ImportExpression | ESTree.MetaProperty {
): ESTree.ImportExpression {
// ImportCall[Yield, Await]:
// import(AssignmentExpression[+In, ?Yield, ?Await])

nextToken(parser, context);

if (parser.token !== Token.LeftParen)
report(parser, Errors.UnexpectedToken, KeywordDescTable[parser.token & Token.Type]);

if (inNewExpression) report(parser, Errors.InvalidImportNew);

let expr = finishNode(parser, context, start, { type: 'Import' } as any);
nextToken(parser, context);

let expr = parseImportExpression(parser, context, inGroup, start);

expr = parseMemberOrUpdateExpression(parser, context, expr, inNewExpression, 1, inGroup, start);
expr = parseMemberOrUpdateExpression(parser, context, expr as any, 0, 1, inGroup, start);

parser.assignable = AssignmentKind.CannotAssign;

return expr;
}

/**
* Parses Import expression
*
* @param parser Parser object
* @param context Context masks
* @param inGroup
* @param start
*/
export function parseImportExpression(
parser: ParserState,
context: Context,
inGroup: 0 | 1,
start: number
): ESTree.ImportExpression {
consume(parser, context, Token.LeftParen);

if (parser.token === Token.Ellipsis) report(parser, Errors.InvalidSpreadInImport);

const source = parseExpression(parser, context, /* assignable */ 1, inGroup, parser.tokenIndex);

consume(parser, context, Token.RightParen);

return finishNode(parser, context, start, {
type: 'ImportExpression',
source
} as any);
}

/**
* Parses BigInt literal
*
Expand Down Expand Up @@ -3250,8 +3283,6 @@ export function parseArguments(
return args;
}

let argCount = 0;

while (parser.token !== Token.RightParen) {
if (parser.token === Token.Ellipsis) {
if (isImportCall) report(parser, Errors.InvalidSpreadInImport);
Expand All @@ -3260,8 +3291,6 @@ export function parseArguments(
args.push(parseExpression(parser, context, /* assignable */ 1, inGroup, parser.tokenIndex));
}

argCount++;

if (parser.token !== Token.Comma) break;

if (isImportCall) report(parser, Errors.InvalidImportTail);
Expand Down Expand Up @@ -4945,9 +4974,9 @@ export function parseParenthesizedExpression(
export function parseIdentifierOrArrow(
parser: ParserState,
context: Context,
expr: ESTree.Identifier,
start: number
): ESTree.Identifier | ESTree.ArrowFunctionExpression {
const expr = parseIdentifier(parser, context, start);
if (parser.token === Token.Arrow) {
parser.flags &= ~Flags.SimpleParameterList;
return parseArrowFunctionExpression(parser, context, [expr], /* isAsync */ 0, start);
Expand Down
6 changes: 3 additions & 3 deletions test/parser/declarations/let.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,8 @@ describe('Declarations - Let', () => {
'let { x, y, } = obj;',
'let { w: { x, y, z } = { x: 4, y: 5, z: 6 } } = { w: null };',
'let {a, b, ...rest} = {x: 1, y: 2, a: 5, b: 3};',
`let x = "x";
let y = "y";
`let a = "a";
let b = "b";
let { x, y, } = obj;
for (let x = "x", i = 0; i < 1; i++) { let y = "y"; }`,
'[1 <= 0]',
Expand Down Expand Up @@ -207,7 +207,7 @@ describe('Declarations - Let', () => {
'let foo, bar;',
'let foo;',
'let {foo} = x, b = y;',
'let {foo} = x, {foo} = y;',
'let {foo} = x, {bar} = y;',
'let [foo,bar=b] = x;',
'let x = y, [foo] = z;',
'let [foo,bar] = x;',
Expand Down
2 changes: 1 addition & 1 deletion test/parser/expressions/arrow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1044,7 +1044,7 @@ describe('Expressions - Arrow', () => {
`async () => {}`,
`async () => {async () => {async () => {async () => {async () => {}}}}}`,
`async => {}`,
'({ async foo(b, c, b){} });',
'({ async foo(a, c, b){} });',
`async => {}
async => {}`,
`() => () => () => {}`,
Expand Down
2 changes: 1 addition & 1 deletion test/parser/expressions/async-function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ describe('Expressions - Async function', () => {
"var O = { async ['meth' + 'od'](arguments) {} }",
"var O = { async 'method'(arguments) {} }",
'var O = { async 0(arguments) {} }',
'var O = { async method(dupe, dupe) {} }',
'var O = { async method(foo, bar) {} }',
'async function await() {}',
'class X { static async await(){} }',
`(async function ref(a, b = 39,) {});`,
Expand Down
Loading

0 comments on commit f735377

Please sign in to comment.