Skip to content

Commit

Permalink
fix(parser): tweaked ranges implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
KFlash committed May 30, 2019
1 parent 0d20e52 commit e443537
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 22 deletions.
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,22 @@ A 100% compliant, self-hosted javascript parser with high focus on both performa
* Conforms to the standard ECMAScript® 2020 (ECMA-262 10th Edition) language specification
* Support TC39 proposals via option
* Support for additional ECMAScript features for Web Browsers
* Optionally track syntactic node locations (*WIP*)
* Optionally track syntactic node locations
* Emits an ESTree-compatible abstract syntax tree.
* No backtracking
* Reduced memory usage
* Very well tested (~73 000 unit tests with full code coverage))
* Lightweight - ~71 KB minified
* Very well tested (~75 000 unit tests with full code coverage))
* Lightweight - ~74 KB minified

## ESNext features

* [BigInt](https://github.com/tc39/proposal-bigint)
* [Decorators](https://github.com/tc39/proposal-decorators)
* [Class Public Instance Fields & Private Instance Fields](https://github.com/tc39/proposal-class-fields)
* [Hashbang Grammar](https://github.com/tc39/proposal-hashbang)
* [Import()](https://github.com/tc39/proposal-dynamic-import)
* [Private methods](https://github.com/tc39/proposal-private-methods)
* [Static class features](https://github.com/tc39/proposal-static-class-features/)
* [Static class fields and private static methods](https://github.com/tc39/proposal-static-class-features/)

**Note:** These features need to be enabled with the `next` option.

Expand Down Expand Up @@ -115,4 +117,5 @@ The second argument allows you to specify various options:
| `module` | Allow parsing with module goal |
| `next` | Allow parsing with `ESNext` features |
| `raw` | Attach raw property to each literal node |
| `ranges` | Append start and end offsets to each node |
| `webcompat` | Enable [web compability](https://tc39.github.io/ecma262/#sec-additional-ecmascript-features-for-web-browsers) |
6 changes: 4 additions & 2 deletions src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,8 @@ export const enum Errors {
UnknownLabel,
InvalidImportTail,
ImportNotOneArg,
InvalidImportNew
InvalidImportNew,
InvalidSpreadInImport
}

/*@internal*/
Expand Down Expand Up @@ -328,7 +329,8 @@ export const errorMessages: {
[Errors.UnknownLabel]: "Undefined label '%0'",
[Errors.InvalidImportTail]: 'Trailing comma is disallowed inside import(...) arguments',
[Errors.ImportNotOneArg]: 'import() requires exactly one argument',
[Errors.InvalidImportNew]: 'Cannot use new with import(...)'
[Errors.InvalidImportNew]: 'Cannot use new with import(...)',
[Errors.InvalidSpreadInImport]: '... is not allowed in import() '
};

export class ParseError extends SyntaxError {
Expand Down
41 changes: 25 additions & 16 deletions src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2772,9 +2772,13 @@ export function parseMemberOrUpdateExpression(
if (parser.token === Token.Period) {
/* Property */
nextToken(parser, context);
if ((parser.token & (Token.IsIdentifier | Token.Keyword)) === 0 && parser.token !== Token.PrivateField)

if ((parser.token & (Token.IsIdentifier | Token.Keyword)) === 0 && parser.token !== Token.PrivateField) {
report(parser, Errors.UnexpectedToken, KeywordDescTable[parser.token & Token.Type]);
}

parser.assignable = AssignmentKind.IsAssignable;

const property =
context & Context.OptionsNext && parser.token === Token.PrivateField
? parsePrivateName(parser, context, parser.startIndex)
Expand Down Expand Up @@ -3235,25 +3239,30 @@ export function parseArguments(
let argCount = 0;

while (parser.token !== Token.RightParen) {
const { startIndex } = parser;
if (parser.token === Token.YieldKeyword) parser.destructible |= DestructuringKind.Yield;

if (parser.token === Token.Ellipsis) {
if (isImportCall) report(parser, Errors.Unexpected);
args.push(parseSpreadElement(parser, context, startIndex));
if (isImportCall) report(parser, Errors.InvalidSpreadInImport);
args.push(parseSpreadElement(parser, context, parser.startIndex));
} else {
args.push(parseExpression(parser, context, /* assignable */ 1, startIndex));
args.push(parseExpression(parser, context, /* assignable */ 1, parser.startIndex));
}

argCount++;

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

if (isImportCall) report(parser, Errors.InvalidImportTail);

nextToken(parser, context | Context.AllowRegExp);

if (parser.token === Token.RightParen) break;
}

if (isImportCall && argCount !== 1) report(parser, Errors.ImportNotOneArg);

consume(parser, context, Token.RightParen);

return args;
}

Expand Down Expand Up @@ -5218,7 +5227,7 @@ export function parseNewExpression(
// - `new (await foo);`
// - `new x(await foo);`
const id = parseIdentifier(parser, context | Context.AllowRegExp, start);
let t = parser.startIndex;
let startIdx = parser.startIndex;
if (consumeOpt(parser, context, Token.Period)) {
if (context & Context.AllowNewTarget && parser.token === Token.Target) {
parser.assignable = AssignmentKind.CannotAssign;
Expand All @@ -5227,8 +5236,8 @@ export function parseNewExpression(
report(parser, Errors.InvalidNewTarget);
}
parser.assignable = AssignmentKind.CannotAssign;
let callee = parsePrimaryExpressionExtended(parser, context, BindingType.None, /* inNewExpression*/ 1, 0, t);
callee = parseMemberOrUpdateExpression(parser, context, callee, /* inNewExpression*/ 1, 0, t);
let callee = parsePrimaryExpressionExtended(parser, context, BindingType.None, /* inNewExpression*/ 1, 0, startIdx);
callee = parseMemberOrUpdateExpression(parser, context, callee, /* inNewExpression*/ 1, 0, startIdx);
parser.assignable = AssignmentKind.CannotAssign;
return finishNode(parser, context, start, {
type: 'NewExpression',
Expand Down Expand Up @@ -5363,7 +5372,7 @@ export function parseAsyncArrowOrCallExpression(
let isComplex: 0 | 1 = 0;

while (parser.token !== Token.RightParen) {
const startt = parser.startIndex;
const idxAfterLeftParen = parser.startIndex;
if (parser.token & (Token.IsIdentifier | Token.Keyword)) {
if (
(parser.token & Token.IsEvalOrArguments) === Token.IsEvalOrArguments ||
Expand All @@ -5388,7 +5397,7 @@ export function parseAsyncArrowOrCallExpression(
: 0 | (parser.flags & Flags.Yield)
? DestructuringKind.Yield
: 0;
expr = finishNode(parser, context, startt, {
expr = finishNode(parser, context, idxAfterLeftParen, {
type: 'AssignmentExpression',
left: expr,
operator: '=',
Expand Down Expand Up @@ -5417,15 +5426,15 @@ export function parseAsyncArrowOrCallExpression(
/*skipInitializer */ 0,
/* inGroup */ 1,
BindingType.None,
startt
idxAfterLeftParen
)
: parseArrayExpressionOrPattern(
parser,
context,
/*skipInitializer */ 0,
/* inGroup */ 1,
BindingType.None,
startt
idxAfterLeftParen
);

destructible |= parser.destructible;
Expand All @@ -5437,7 +5446,7 @@ export function parseAsyncArrowOrCallExpression(
if ((parser.token & Token.IsCommaOrRightParen) !== Token.IsCommaOrRightParen) {
if (destructible & DestructuringKind.MustDestruct) report(parser, Errors.InvalidPatternTail);

expr = parseMemberOrUpdateExpression(parser, context, expr, /* assignable */ 0, 0, startt);
expr = parseMemberOrUpdateExpression(parser, context, expr, /* assignable */ 0, 0, idxAfterLeftParen);

destructible |= DestructuringKind.CannotDestruct;

Expand All @@ -5452,22 +5461,22 @@ export function parseAsyncArrowOrCallExpression(
BindingType.ArgumentList,
/* isAsync */ 1,
/* inGroup */ 1,
parser.startIndex
idxAfterLeftParen
);

destructible |= parser.destructible;

isComplex = 1;
if (parser.token !== Token.RightParen) parser.destructible |= DestructuringKind.CannotDestruct;
} else {
expr = parseExpression(parser, context, /* assignable */ 1, startt);
expr = parseExpression(parser, context, /* assignable */ 1, idxAfterLeftParen);

destructible = parser.assignable;

params.push(expr);

while (consumeOpt(parser, context | Context.AllowRegExp, Token.Comma)) {
params.push(parseExpression(parser, context, /* assignable */ 1, startt));
params.push(parseExpression(parser, context, /* assignable */ 1, idxAfterLeftParen));
parser.assignable = AssignmentKind.CannotAssign;
}

Expand Down

0 comments on commit e443537

Please sign in to comment.