@babel/parser error recovery (#10363)

* Add error recovery support to @babel/parser

* Update @babel/parser tests to always recover from errors

* Update this.raise usage in @babel/parser:

- expression.js
- lval.js
- statement.js
- estree.js
- flow.js
- jsx/index.js
- tokenizer/index.js

* Update @babel/parser fixtures with recovered errors

* Fix tests out of @babel/parser

* Do not use try/catch for control flow

* Update invalid fixtures

* Do not report invalid lhs in toAssignable

* Do not validate function id multiple times

* Dedupe reserved await errors

* Remove duplicate errors about strict reserved bindings

* Remove duplicated error about yield/await inside params

* Don't error twice for methods in object patterns

* Don't report invalid super() twice

* Remove dup error about reserved param for expr arrows

* Remove double escapes in migrated tests

* Dedupe errors about invalid escapes in identifiers

* Remove duplicated error about decorated constructor

* Remove duplicated error about spread in flow class

* Don't throw for invalid super usage

* Don't fail for object decorators with stage 2

* Fix flow inexact type errors

* Fix flow

* Fix errors about escapes in keywords (ref: #10455)

* Update after rebase

* Fix todo

* Remove duplicated error when using += for defaults

* Remove unnecessary throw

* Nit: use ??
This commit is contained in:
Nicolò Ribaudo
2019-11-05 10:15:00 +01:00
committed by GitHub
parent d25262ec4b
commit 87feda7c2a
2224 changed files with 155996 additions and 3353 deletions

View File

@@ -2,6 +2,7 @@
import { types as tt, type TokenType } from "../tokenizer/types";
import Tokenizer from "../tokenizer";
import State from "../tokenizer/state";
import type { Node } from "../types";
import { lineBreak, skipWhiteSpace } from "../util/whitespace";
import { isIdentifierChar } from "../util/identifier";
@@ -9,6 +10,14 @@ import * as charCodes from "charcodes";
const literal = /^('|")((?:\\?.)*?)\1/;
type TryParse<Node, Error, Thrown, Aborted, FailState> = {
node: Node,
error: Error,
thrown: Thrown,
aborted: Aborted,
failState: FailState,
};
// ## Parser utilities
export default class UtilParser extends Tokenizer {
@@ -215,4 +224,58 @@ export default class UtilParser extends Tokenizer {
return false;
}
// tryParse will clone parser state.
// It is expensive and should be used with cautions
tryParse<T: Node | $ReadOnlyArray<Node>>(
fn: (abort: (node?: T) => empty) => T,
oldState: State = this.state.clone(),
):
| TryParse<T, null, false, false, null>
| TryParse<T | null, SyntaxError, boolean, false, State>
| TryParse<T | null, null, false, true, State> {
const abortSignal: { node: T | null } = { node: null };
try {
const node = fn((node = null) => {
abortSignal.node = node;
throw abortSignal;
});
if (this.state.errors.length > oldState.errors.length) {
const failState = this.state;
this.state = oldState;
return {
node,
error: (failState.errors[oldState.errors.length]: SyntaxError),
thrown: false,
aborted: false,
failState,
};
}
return {
node,
error: null,
thrown: false,
aborted: false,
failState: null,
};
} catch (error) {
const failState = this.state;
this.state = oldState;
if (error instanceof SyntaxError) {
return { node: null, error, thrown: true, aborted: false, failState };
}
if (error === abortSignal) {
return {
node: abortSignal.node,
error: null,
thrown: false,
aborted: true,
failState,
};
}
throw error;
}
}
}