Commit 9d27ec3a authored by Toon Verwaest's avatar Toon Verwaest Committed by Commit Bot

[parser] Introduce FailureExpression to return instead of nullptr

That allows us to keep on running further without explicit RETURN_IF

Bug: v8:8363, v8:7926
Change-Id: If1424a1dae656ac725a8443b09ea1b8cc25dfcb1
Reviewed-on: https://chromium-review.googlesource.com/c/1322953Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57319}
parent 50f52476
......@@ -109,6 +109,8 @@ namespace internal {
V(Yield) \
V(YieldStar)
#define FAILURE_NODE_LIST(V) V(FailureExpression)
#define AST_NODE_LIST(V) \
DECLARATION_NODE_LIST(V) \
STATEMENT_NODE_LIST(V) \
......@@ -128,12 +130,16 @@ class Statement;
#define DEF_FORWARD_DECLARATION(type) class type;
AST_NODE_LIST(DEF_FORWARD_DECLARATION)
FAILURE_NODE_LIST(DEF_FORWARD_DECLARATION)
#undef DEF_FORWARD_DECLARATION
class AstNode: public ZoneObject {
public:
#define DECLARE_TYPE_ENUM(type) k##type,
enum NodeType : uint8_t { AST_NODE_LIST(DECLARE_TYPE_ENUM) };
enum NodeType : uint8_t {
AST_NODE_LIST(DECLARE_TYPE_ENUM) /* , */
FAILURE_NODE_LIST(DECLARE_TYPE_ENUM)
};
#undef DECLARE_TYPE_ENUM
void* operator new(size_t size, Zone* zone) { return zone->New(size); }
......@@ -152,6 +158,7 @@ class AstNode: public ZoneObject {
V8_INLINE type* As##type(); \
V8_INLINE const type* As##type() const;
AST_NODE_LIST(DECLARE_NODE_FUNCTIONS)
FAILURE_NODE_LIST(DECLARE_NODE_FUNCTIONS)
#undef DECLARE_NODE_FUNCTIONS
BreakableStatement* AsBreakableStatement();
......@@ -249,6 +256,12 @@ class Expression : public AstNode {
static const uint8_t kNextBitFieldIndex = AstNode::kNextBitFieldIndex;
};
class FailureExpression : public Expression {
private:
friend class AstNodeFactory;
FailureExpression() : Expression(kNoSourcePosition, kFailureExpression) {}
};
// V8's notion of BreakableStatement does not correspond to the notion of
// BreakableStatement in ECMAScript. In V8, the idea is that a
// BreakableStatement is a statement that can be the target of a break
......@@ -2837,9 +2850,14 @@ class AstVisitor {
case AstNode::k##NodeType: \
return this->impl()->Visit##NodeType(static_cast<NodeType*>(node));
#define GENERATE_AST_VISITOR_SWITCH() \
switch (node->node_type()) { \
AST_NODE_LIST(GENERATE_VISIT_CASE) \
#define GENERATE_FAILURE_CASE(NodeType) \
case AstNode::k##NodeType: \
UNREACHABLE();
#define GENERATE_AST_VISITOR_SWITCH() \
switch (node->node_type()) { \
AST_NODE_LIST(GENERATE_VISIT_CASE) \
FAILURE_NODE_LIST(GENERATE_FAILURE_CASE) \
}
#define DEFINE_AST_VISITOR_SUBCLASS_MEMBERS() \
......@@ -2894,7 +2912,8 @@ class AstNodeFactory final {
AstNodeFactory(AstValueFactory* ast_value_factory, Zone* zone)
: zone_(zone),
ast_value_factory_(ast_value_factory),
empty_statement_(new (zone) class EmptyStatement()) {}
empty_statement_(new (zone) class EmptyStatement()),
failure_expression_(new (zone) class FailureExpression()) {}
AstValueFactory* ast_value_factory() const { return ast_value_factory_; }
......@@ -3051,6 +3070,10 @@ class AstNodeFactory final {
return empty_statement_;
}
class FailureExpression* FailureExpression() {
return failure_expression_;
}
SloppyBlockFunctionStatement* NewSloppyBlockFunctionStatement() {
return new (zone_) SloppyBlockFunctionStatement(EmptyStatement());
}
......@@ -3422,6 +3445,7 @@ class AstNodeFactory final {
Zone* zone_;
AstValueFactory* ast_value_factory_;
class EmptyStatement* empty_statement_;
class FailureExpression* failure_expression_;
};
......@@ -3463,6 +3487,7 @@ class AstNodeFactory final {
: nullptr; \
}
AST_NODE_LIST(DECLARE_NODE_FUNCTIONS)
FAILURE_NODE_LIST(DECLARE_NODE_FUNCTIONS)
#undef DECLARE_NODE_FUNCTIONS
} // namespace internal
......
......@@ -1446,6 +1446,7 @@ void DeclarationScope::ResetAfterPreparsing(AstValueFactory* ast_value_factory,
zone_ = ast_value_factory->zone();
variables_.Reset(ZoneAllocationPolicy(zone_));
if (!IsArrowFunction(function_kind_)) {
has_simple_parameters_ = true;
DeclareDefaultFunctionVariables(ast_value_factory);
}
} else {
......
......@@ -106,16 +106,8 @@ class SourceRangeScope final {
//
// SAFE_USE(foo);
#define RETURN_IF_PARSE_ERROR_CUSTOM(x, ...) \
if (has_error()) { \
return impl()->x(__VA_ARGS__); \
}
// Used in functions where the return type is ExpressionT.
#define RETURN_IF_PARSE_ERROR RETURN_IF_PARSE_ERROR_CUSTOM(NullExpression)
#define RETURN_IF_PARSE_ERROR_VOID \
if (has_error()) return;
#define RETURN_IF_PARSE_ERROR \
if (has_error()) return impl()->NullStatement();
// Common base class template shared between parser and pre-parser.
// The Impl parameter is the actual class of the parser/pre-parser,
......@@ -718,13 +710,6 @@ class ParserBase {
ReportUnexpectedToken(Next());
}
// Dummy functions, just useful as arguments to RETURN_IF_PARSE_ERROR_CUSTOM.
static void Void() {}
template <typename T>
static T Return(T result) {
return result;
}
bool peek_any_identifier() { return Token::IsAnyIdentifier(peek()); }
bool CheckContextualKeyword(Token::Value token) {
......@@ -1637,7 +1622,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseRegExpLiteral() {
if (!scanner()->ScanRegExpPattern()) {
Next();
ReportMessage(MessageTemplate::kUnterminatedRegExp);
return impl()->NullExpression();
return impl()->FailureExpression();
}
IdentifierT js_pattern = impl()->GetNextSymbol();
......@@ -1645,7 +1630,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseRegExpLiteral() {
if (flags.IsNothing()) {
Next();
ReportMessage(MessageTemplate::kMalformedRegExpFlags);
return impl()->NullExpression();
return impl()->FailureExpression();
}
int js_flags = flags.FromJust();
Next();
......@@ -1675,7 +1660,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseBindingPattern() {
result = ParseObjectLiteral();
} else {
ReportUnexpectedToken(Next());
return impl()->NullExpression();
return impl()->FailureExpression();
}
}
......@@ -1726,7 +1711,7 @@ ParserBase<Impl>::ParsePrimaryExpression() {
if (!classifier()->is_valid_async_arrow_formal_parameters()) {
ReportClassifierError(
classifier()->async_arrow_formal_parameters_error());
return impl()->NullExpression();
return impl()->FailureExpression();
}
infer = InferName::kNo;
}
......@@ -1833,7 +1818,7 @@ ParserBase<Impl>::ParsePrimaryExpression() {
}
ReportUnexpectedToken(Next());
return impl()->NullExpression();
return impl()->FailureExpression();
}
template <typename Impl>
......@@ -1867,7 +1852,7 @@ ParserBase<Impl>::ParseExpressionCoverGrammar(bool accept_IN) {
ExpressionT pattern = ParseBindingPattern();
if (peek() == Token::ASSIGN) {
ReportMessage(MessageTemplate::kRestDefaultInitializer);
return impl()->NullExpression();
return impl()->FailureExpression();
}
right = factory()->NewSpread(pattern, ellipsis_pos, pattern_pos);
} else {
......@@ -1876,8 +1861,6 @@ ParserBase<Impl>::ParseExpressionCoverGrammar(bool accept_IN) {
// No need to accumulate binding pattern-related errors, since
// an Expression can't be a binding pattern anyway.
AccumulateNonBindingPatternErrors();
// TODO(verwaest): Remove once we have FailureExpression.
RETURN_IF_PARSE_ERROR;
if (!impl()->IsIdentifier(right)) classifier()->RecordNonSimpleParameter();
list.Add(right);
......@@ -1932,8 +1915,6 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseArrayLiteral() {
first_spread_index = values.length();
}
// TODO(verwaest): Remove once we have FailureExpression.
RETURN_IF_PARSE_ERROR;
if (argument->IsAssignment()) {
classifier()->RecordPatternError(
Scanner::Location(start_pos, end_position()),
......@@ -1950,13 +1931,12 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseArrayLiteral() {
} else {
int beg_pos = peek_position();
elem = ParseAssignmentExpression(true);
// TODO(verwaest): Remove once we have FailureExpression.
RETURN_IF_PARSE_ERROR;
CheckDestructuringElement(elem, beg_pos, end_position());
}
values.Add(elem);
if (peek() != Token::RBRACK) {
Expect(Token::COMMA);
if (has_error()) return impl()->FailureExpression();
}
}
......@@ -2096,8 +2076,6 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePropertyName(
ExpressionT expression = ParseAssignmentExpression(true);
*kind = ParsePropertyKind::kSpread;
// TODO(verwaest): Remove once we have FailureExpression.
RETURN_IF_PARSE_ERROR;
if (!impl()->IsIdentifier(expression)) {
classifier()->RecordBindingPatternError(
scanner()->location(),
......@@ -2268,7 +2246,6 @@ ParserBase<Impl>::ParseClassPropertyDefinition(
if (!*is_computed_name) {
checker->CheckClassMethodName(name_token, kind,
ParseFunctionFlag::kIsNormal, *is_static);
RETURN_IF_PARSE_ERROR_CUSTOM(NullLiteralProperty)
// Make sure the name expression is a string since we need a Name for
// Runtime_DefineAccessorPropertyUnchecked and since we can determine
// this statically we can skip the extra runtime check.
......@@ -2296,7 +2273,6 @@ ParserBase<Impl>::ParseClassPropertyDefinition(
return result;
}
case ParsePropertyKind::kSpread:
RETURN_IF_PARSE_ERROR_CUSTOM(NullLiteralProperty);
ReportUnexpectedTokenAt(
Scanner::Location(name_token_position, name_expression->position()),
name_token);
......@@ -2393,7 +2369,6 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ObjectLiteralChecker* checker,
Consume(Token::COLON);
int beg_pos = peek_position();
ExpressionT value = ParseAssignmentExpression(true);
RETURN_IF_PARSE_ERROR_CUSTOM(NullLiteralProperty);
CheckDestructuringElement(value, beg_pos, end_position());
ObjectLiteralPropertyT result = factory()->NewObjectLiteralProperty(
......@@ -2498,7 +2473,6 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ObjectLiteralChecker* checker,
// Make sure the name expression is a string since we need a Name for
// Runtime_DefineAccessorPropertyUnchecked and since we can determine
// this statically we can skip the extra runtime check.
RETURN_IF_PARSE_ERROR_CUSTOM(NullLiteralProperty);
name_expression =
factory()->NewStringLiteral(name, name_expression->position());
}
......@@ -2553,7 +2527,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseObjectLiteral() {
bool is_rest_property = false;
ObjectLiteralPropertyT property = ParseObjectPropertyDefinition(
&checker, &is_computed_name, &is_rest_property);
RETURN_IF_PARSE_ERROR;
if (has_error()) return impl()->FailureExpression();
if (is_computed_name) {
has_computed_names = true;
......@@ -2609,8 +2583,6 @@ void ParserBase<Impl>::ParseArguments(
ExpressionT argument = ParseAssignmentExpression(true);
if (maybe_arrow) {
// TODO(verwaest): Remove once we have FailureExpression.
RETURN_IF_PARSE_ERROR_VOID;
if (!impl()->IsIdentifier(argument)) {
classifier()->previous()->RecordNonSimpleParameter();
}
......@@ -2724,8 +2696,6 @@ ParserBase<Impl>::ParseAssignmentExpression(bool accept_IN) {
// of a larger assignment pattern, even though parenthesized patterns
// themselves are not allowed, e.g., "[(x)] = []". Only accumulate
// assignment pattern errors if the parsed expression is more complex.
// TODO(verwaest): Remove once we have FailureExpression.
RETURN_IF_PARSE_ERROR;
if (IsValidReferenceExpression(expression)) {
productions &= ~ExpressionClassifier::AssignmentPatternProduction;
}
......@@ -2740,7 +2710,8 @@ ParserBase<Impl>::ParseAssignmentExpression(bool accept_IN) {
}
Accumulate(productions);
if (!Token::IsAssignmentOp(peek())) return expression;
Token::Value op = peek();
if (!Token::IsAssignmentOp(op)) return expression;
if (is_destructuring_assignment) {
impl()->MarkPatternAsAssigned(expression);
......@@ -2748,12 +2719,10 @@ ParserBase<Impl>::ParseAssignmentExpression(bool accept_IN) {
expression = CheckAndRewriteReferenceExpression(
expression, lhs_beg_pos, end_position(),
MessageTemplate::kInvalidLhsInAssignment);
// TODO(verwaest): Remove once we have FailureExpression.
RETURN_IF_PARSE_ERROR;
impl()->MarkExpressionAsAssigned(expression);
}
Token::Value op = Next(); // Get assignment operator.
Consume(op);
if (op != Token::ASSIGN) {
classifier()->RecordPatternError(scanner()->location(),
MessageTemplate::kUnexpectedToken,
......@@ -2775,8 +2744,6 @@ ParserBase<Impl>::ParseAssignmentExpression(bool accept_IN) {
function_state_->AddProperty();
}
// TODO(verwaest): Remove once we have FailureExpression.
RETURN_IF_PARSE_ERROR;
impl()->CheckAssigningFunctionLiteralToProperty(expression, right);
// Check if the right hand side is a call to avoid inferring a
......@@ -2936,8 +2903,6 @@ ParserBase<Impl>::ParseBinaryContinuation(ExpressionT x, int prec, int prec1,
const bool is_right_associative = op == Token::EXP;
const int next_prec = is_right_associative ? prec1 : prec1 + 1;
y = ParseBinaryExpression(next_prec, accept_IN);
// TODO(verwaest): Remove once we have FailureExpression.
RETURN_IF_PARSE_ERROR;
}
// For now we distinguish between comparisons and other binary
......@@ -3003,24 +2968,23 @@ ParserBase<Impl>::ParseUnaryOpExpression() {
CheckStackOverflow();
ExpressionT expression = ParseUnaryExpression();
RETURN_IF_PARSE_ERROR;
if (op == Token::DELETE) {
if (impl()->IsIdentifier(expression) && is_strict(language_mode())) {
// "delete identifier" is a syntax error in strict mode.
ReportMessage(MessageTemplate::kStrictDelete);
return impl()->NullExpression();
return impl()->FailureExpression();
}
if (impl()->IsPropertyWithPrivateFieldKey(expression)) {
ReportMessage(MessageTemplate::kDeletePrivateField);
return impl()->NullExpression();
return impl()->FailureExpression();
}
}
if (peek() == Token::EXP) {
ReportUnexpectedToken(Next());
return impl()->NullExpression();
return impl()->FailureExpression();
}
// Allow the parser's implementation to rewrite the expression.
......@@ -3038,13 +3002,9 @@ ParserBase<Impl>::ParsePrefixExpression() {
CheckStackOverflow();
ExpressionT expression = ParseUnaryExpression();
// TODO(verwaest): Remove once we have FailureExpression.
RETURN_IF_PARSE_ERROR;
expression = CheckAndRewriteReferenceExpression(
expression, beg_pos, end_position(),
MessageTemplate::kInvalidLhsInPrefixOp);
// TODO(verwaest): Remove once we have FailureExpression.
RETURN_IF_PARSE_ERROR;
impl()->MarkExpressionAsAssigned(expression);
return factory()->NewCountOperation(op, true /* prefix */, expression,
......@@ -3114,8 +3074,6 @@ ParserBase<Impl>::ParsePostfixExpression() {
expression = CheckAndRewriteReferenceExpression(
expression, lhs_beg_pos, end_position(),
MessageTemplate::kInvalidLhsInPostfixOp);
// TODO(verwaest): Remove once we have FailureExpression.
RETURN_IF_PARSE_ERROR;
impl()->MarkExpressionAsAssigned(expression);
Token::Value next = Next();
......@@ -3193,7 +3151,7 @@ ParserBase<Impl>::ParseLeftHandSideContinuation(ExpressionT result) {
if (!classifier()->is_valid_async_arrow_formal_parameters()) {
ReportClassifierError(
classifier()->async_arrow_formal_parameters_error());
return impl()->NullExpression();
return impl()->FailureExpression();
}
if (args.length()) {
// async ( Arguments ) => ...
......@@ -3289,7 +3247,7 @@ ParserBase<Impl>::ParseMemberWithPresentNewPrefixesExpression() {
(!allow_harmony_import_meta() || PeekAhead() == Token::LPAREN)) {
impl()->ReportMessageAt(scanner()->peek_location(),
MessageTemplate::kImportCallNotNewExpression);
return impl()->NullExpression();
return impl()->FailureExpression();
} else if (peek() == Token::PERIOD) {
result = ParseNewTargetExpression();
return ParseMemberExpressionContinuation(result);
......@@ -3354,12 +3312,15 @@ ParserBase<Impl>::ParseFunctionExpression() {
function_name_location = scanner()->location();
function_type = FunctionLiteral::kNamedExpression;
}
return impl()->ParseFunctionLiteral(name, function_name_location,
is_strict_reserved_name
? kFunctionNameIsStrictReserved
: kFunctionNameValidityUnknown,
function_kind, function_token_position,
function_type, language_mode(), nullptr);
FunctionLiteralT result = impl()->ParseFunctionLiteral(
name, function_name_location,
is_strict_reserved_name ? kFunctionNameIsStrictReserved
: kFunctionNameValidityUnknown,
function_kind, function_token_position, function_type, language_mode(),
nullptr);
// TODO(verwaest): FailureFunctionLiteral?
if (impl()->IsNull(result)) return impl()->FailureExpression();
return result;
}
template <typename Impl>
......@@ -3409,7 +3370,7 @@ ParserBase<Impl>::ParseImportExpressions() {
if (!parsing_module_) {
impl()->ReportMessageAt(scanner()->location(),
MessageTemplate::kImportMetaOutsideModule);
return impl()->NullExpression();
return impl()->FailureExpression();
}
return impl()->ImportMetaExpression(pos);
......@@ -3418,7 +3379,7 @@ ParserBase<Impl>::ParseImportExpressions() {
if (peek() == Token::RPAREN) {
impl()->ReportMessageAt(scanner()->location(),
MessageTemplate::kImportMissingSpecifier);
return impl()->NullExpression();
return impl()->FailureExpression();
}
ExpressionT arg = ParseAssignmentExpression(true);
Expect(Token::RPAREN);
......@@ -3450,7 +3411,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseSuperExpression(
impl()->ReportMessageAt(scanner()->location(),
MessageTemplate::kUnexpectedSuper);
return impl()->NullExpression();
return impl()->FailureExpression();
}
template <typename Impl>
......@@ -3478,7 +3439,7 @@ ParserBase<Impl>::ParseNewTargetExpression() {
if (!GetReceiverScope()->is_function_scope()) {
impl()->ReportMessageAt(scanner()->location(),
MessageTemplate::kUnexpectedNewTarget);
return impl()->NullExpression();
return impl()->FailureExpression();
}
return impl()->NewTargetExpression(pos);
......@@ -3499,8 +3460,6 @@ ParserBase<Impl>::DoParseMemberExpressionContinuation(ExpressionT expression) {
int pos = position();
ExpressionT index = ParseExpressionCoverGrammar(true);
expression = factory()->NewProperty(expression, index, pos);
// TODO(verwaest): Remove once we have FailureExpression.
RETURN_IF_PARSE_ERROR;
impl()->PushPropertyName(index);
Expect(Token::RBRACK);
break;
......@@ -3520,8 +3479,6 @@ ParserBase<Impl>::DoParseMemberExpressionContinuation(ExpressionT expression) {
pos = position();
} else {
pos = peek_position();
// TODO(verwaest): Remove once we have FailureExpression.
RETURN_IF_PARSE_ERROR;
if (expression->IsFunctionLiteral()) {
// If the tag function looks like an IIFE, set_parenthesized() to
// force eager compilation.
......@@ -3544,8 +3501,6 @@ void ParserBase<Impl>::ParseFormalParameter(FormalParametersT* parameters) {
FuncNameInferrerState fni_state(&fni_);
ExpressionT pattern = ParseBindingPattern();
// TODO(verwaest): Remove once we have FailureExpression.
RETURN_IF_PARSE_ERROR_VOID;
if (!impl()->IsIdentifier(pattern)) {
parameters->is_simple = false;
ValidateFormalParameterInitializer();
......@@ -3678,7 +3633,6 @@ typename ParserBase<Impl>::BlockT ParserBase<Impl>::ParseVariableDeclarations(
}
Scanner::Location variable_loc = scanner()->location();
// TODO(verwaest): Remove once we have FailureExpression.
bool single_name = impl()->IsIdentifier(pattern);
if (single_name) {
impl()->PushVariableName(impl()->AsIdentifier(pattern));
......@@ -3701,8 +3655,6 @@ typename ParserBase<Impl>::BlockT ParserBase<Impl>::ParseVariableDeclarations(
// Don't infer if it is "a = function(){...}();"-like expression.
if (single_name) {
// TODO(verwaest): Remove once we have FailureExpression.
RETURN_IF_PARSE_ERROR_CUSTOM(NullStatement);
if (!value->IsCall() && !value->IsCallNew()) {
fni_.Infer();
} else {
......@@ -3918,7 +3870,6 @@ ParserBase<Impl>::ParseNativeDeclaration() {
}
Expect(Token::RPAREN);
Expect(Token::SEMICOLON);
RETURN_IF_PARSE_ERROR_CUSTOM(NullStatement);
return impl()->DeclareNative(name, pos);
}
......@@ -3961,8 +3912,6 @@ void ParserBase<Impl>::ParseFunctionBody(
ExpressionT expression = ParseAssignmentExpression(accept_IN);
ValidateExpression();
// TODO(verwaest): Remove once we have FailureExpression.
RETURN_IF_PARSE_ERROR_VOID;
if (IsAsyncFunction(kind)) {
BlockT block = factory()->NewBlock(1, true);
impl()->RewriteAsyncFunctionBody(body, block, expression);
......@@ -4017,7 +3966,7 @@ void ParserBase<Impl>::ParseFunctionBody(
DCHECK_EQ(function_scope, inner_scope->outer_scope());
impl()->SetLanguageMode(function_scope, inner_scope->language_mode());
// TODO(verwaest): Disable DCHECKs in failure mode?
RETURN_IF_PARSE_ERROR_VOID;
if (has_error()) return;
BlockT init_block = impl()->BuildParameterInitializationBlock(parameters);
if (is_sloppy(inner_scope->language_mode())) {
......@@ -4051,7 +4000,6 @@ void ParserBase<Impl>::ParseFunctionBody(
function_scope->DeclareArguments(ast_value_factory());
}
RETURN_IF_PARSE_ERROR_VOID;
impl()->DeclareFunctionNameVar(function_name, function_type, function_scope);
}
......@@ -4128,7 +4076,7 @@ ParserBase<Impl>::ParseArrowFunctionLiteral(
// `=> ...` is never a valid expression, so report as syntax error.
// If next token is not `=>`, it's a syntax error anyways.
ReportUnexpectedTokenAt(scanner_->peek_location(), Token::ARROW);
return impl()->NullExpression();
return impl()->FailureExpression();
}
int expected_property_count = -1;
......@@ -4179,7 +4127,7 @@ ParserBase<Impl>::ParseArrowFunctionLiteral(
// Validate parameter names. We can do this only after preparsing the
// function, since the function can declare itself strict.
ValidateFormalParameters(language_mode(), false);
RETURN_IF_PARSE_ERROR;
if (has_error()) return impl()->FailureExpression();
DCHECK_NULL(produced_preparsed_scope_data);
......@@ -4197,7 +4145,7 @@ ParserBase<Impl>::ParseArrowFunctionLiteral(
FunctionLiteral::kAnonymousExpression,
FunctionBodyType::kBlock, true);
CHECK(has_error());
return impl()->NullExpression();
return impl()->FailureExpression();
}
} else {
Consume(Token::LBRACE);
......@@ -4269,12 +4217,12 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseClassLiteral(
if (name_is_strict_reserved) {
impl()->ReportMessageAt(class_name_location,
MessageTemplate::kUnexpectedStrictReserved);
return impl()->NullExpression();
return impl()->FailureExpression();
}
if (impl()->IsEvalOrArguments(name)) {
impl()->ReportMessageAt(class_name_location,
MessageTemplate::kStrictEvalArguments);
return impl()->NullExpression();
return impl()->FailureExpression();
}
}
......@@ -4328,7 +4276,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseClassLiteral(
ValidateExpression();
AccumulateFormalParameterContainmentErrors();
RETURN_IF_PARSE_ERROR;
if (has_error()) return impl()->FailureExpression();
impl()->DeclareClassProperty(name, property, property_name, property_kind,
is_static, is_constructor, is_computed_name,
is_private, &class_info);
......@@ -4394,11 +4342,13 @@ ParserBase<Impl>::ParseAsyncFunctionLiteral() {
// recognized the error.
DCHECK(!is_await);
}
return impl()->ParseFunctionLiteral(
FunctionLiteralT result = impl()->ParseFunctionLiteral(
name, scanner()->location(),
is_strict_reserved ? kFunctionNameIsStrictReserved
: kFunctionNameValidityUnknown,
kind, pos, type, language_mode(), nullptr);
if (impl()->IsNull(result)) return impl()->FailureExpression();
return result;
}
template <typename Impl>
......@@ -4457,7 +4407,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseTemplateLiteral(
if (peek() != Token::RBRACE) {
impl()->ReportMessageAt(Scanner::Location(expr_pos, peek_position()),
MessageTemplate::kUnterminatedTemplateExpr);
return impl()->NullExpression();
return impl()->FailureExpression();
}
// If we didn't die parsing that expression, our next token should be a
......@@ -4494,7 +4444,7 @@ ParserBase<Impl>::CheckAndRewriteReferenceExpression(ExpressionT expression,
impl()->IsEvalOrArguments(impl()->AsIdentifier(expression))) {
ReportMessageAt(Scanner::Location(beg_pos, end_pos),
MessageTemplate::kStrictEvalArguments, kSyntaxError);
return impl()->NullExpression();
return impl()->FailureExpression();
}
if (expression->IsValidReferenceExpression()) {
return expression;
......@@ -4511,7 +4461,7 @@ ParserBase<Impl>::CheckAndRewriteReferenceExpression(ExpressionT expression,
return factory()->NewProperty(expression, error, beg_pos);
}
ReportMessageAt(Scanner::Location(beg_pos, end_pos), message, type);
return impl()->NullExpression();
return impl()->FailureExpression();
}
template <typename Impl>
......@@ -4544,7 +4494,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseV8Intrinsic() {
ExpressionClassifier classifier(this);
if (peek() != Token::LPAREN) {
impl()->ReportUnexpectedToken(peek());
return impl()->NullExpression();
return impl()->FailureExpression();
}
bool has_spread;
ExpressionListT args(pointer_buffer());
......@@ -4553,7 +4503,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseV8Intrinsic() {
if (has_spread) {
ReportMessageAt(Scanner::Location(pos, position()),
MessageTemplate::kIntrinsicWithSpread, kSyntaxError);
return impl()->NullExpression();
return impl()->FailureExpression();
}
return impl()->NewV8Intrinsic(name, args, pos);
......@@ -4567,13 +4517,9 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseDoExpression() {
int pos = peek_position();
Consume(Token::DO);
BlockT block = ParseBlock(nullptr);
RETURN_IF_PARSE_ERROR;
return impl()->RewriteDoExpression(block, pos);
}
#undef RETURN_IF_PARSE_ERROR
#define RETURN_IF_PARSE_ERROR RETURN_IF_PARSE_ERROR_CUSTOM(NullStatement)
template <typename Impl>
typename ParserBase<Impl>::LazyParsingResult
ParserBase<Impl>::ParseStatementList(StatementListT* body,
......@@ -4598,7 +4544,7 @@ ParserBase<Impl>::ParseStatementList(StatementListT* body,
body->Add(stat);
may_abort = false;
RETURN_IF_PARSE_ERROR_CUSTOM(Return, kLazyParsingComplete);
if (has_error()) return kLazyParsingComplete;
if (!impl()->IsStringLiteral(stat)) break;
......@@ -4645,7 +4591,7 @@ ParserBase<Impl>::ParseStatementList(StatementListT* body,
while (peek() != end_token) {
StatementT stat = ParseStatementListItem();
RETURN_IF_PARSE_ERROR_CUSTOM(Return, kLazyParsingComplete);
if (has_error()) return kLazyParsingComplete;
if (stat->IsEmptyStatement()) continue;
body->Add(stat);
}
......@@ -4826,7 +4772,7 @@ typename ParserBase<Impl>::BlockT ParserBase<Impl>::ParseBlock(
while (peek() != Token::RBRACE) {
StatementT stat = ParseStatementListItem();
RETURN_IF_PARSE_ERROR_CUSTOM(NullStatement);
RETURN_IF_PARSE_ERROR;
if (stat->IsEmptyStatement()) continue;
statements.Add(stat);
}
......@@ -5484,8 +5430,6 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForStatement(
int lhs_end_pos = end_position();
bool is_for_each = CheckInOrOf(&for_info.mode);
// TODO(verwaest): Remove once we have FailureExpression.
RETURN_IF_PARSE_ERROR;
bool is_destructuring = is_for_each && (expression->IsArrayLiteral() ||
expression->IsObjectLiteral());
......@@ -5583,10 +5527,8 @@ ParserBase<Impl>::ParseForEachStatementWithDeclarations(
}
impl()->RecordIterationStatementSourceRange(loop, body_range);
RETURN_IF_PARSE_ERROR;
impl()->DesugarBindingInForEachStatement(for_info, &body_block,
&each_variable);
RETURN_IF_PARSE_ERROR;
body_block->statements()->Add(body, zone());
if (inner_block_scope != nullptr) {
......@@ -5595,7 +5537,6 @@ ParserBase<Impl>::ParseForEachStatementWithDeclarations(
}
}
RETURN_IF_PARSE_ERROR;
StatementT final_loop = impl()->InitializeForEachStatement(
loop, each_variable, enumerable, body_block);
......@@ -5730,8 +5671,6 @@ typename ParserBase<Impl>::ForStatementT ParserBase<Impl>::ParseStandardForLoop(
if (peek() != Token::RPAREN) {
ExpressionT exp = ParseExpression();
// TODO(verwaest): Remove once we have FailureExpression.
RETURN_IF_PARSE_ERROR;
*next = factory()->NewExpressionStatement(exp, exp->position());
}
Expect(Token::RPAREN);
......@@ -5824,7 +5763,6 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement(
BlockState inner_state(&scope_, inner_block_scope);
ExpressionClassifier classifier(this);
ExpressionT lhs = each_variable = ParseLeftHandSideExpression();
RETURN_IF_PARSE_ERROR;
int lhs_end_pos = end_position();
if (lhs->IsArrayLiteral() || lhs->IsObjectLiteral()) {
......@@ -5864,12 +5802,10 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement(
}
impl()->RecordIterationStatementSourceRange(loop, body_range);
RETURN_IF_PARSE_ERROR;
if (has_declarations) {
BlockT body_block = impl()->NullStatement();
impl()->DesugarBindingInForEachStatement(&for_info, &body_block,
&each_variable);
RETURN_IF_PARSE_ERROR;
body_block->statements()->Add(body, zone());
body_block->set_scope(scope()->FinalizeBlockScope());
body = body_block;
......@@ -5968,8 +5904,6 @@ void ParserBase<Impl>::ClassLiteralChecker::CheckClassFieldName(
}
#undef RETURN_IF_PARSE_ERROR
#undef RETURN_IF_PARSE_ERROR_CUSTOM
#undef RETURN_IF_PARSE_ERROR_VOID
} // namespace internal
} // namespace v8
......
......@@ -138,24 +138,6 @@ void Parser::GetUnexpectedTokenMessage(Token::Value token,
}
}
// ----------------------------------------------------------------------------
// The RETURN_IF_PARSE_ERROR macro is a convenient macro to enforce error
// handling for functions that may fail (by returning if there was an parser
// error).
//
// Usage:
// foo = ParseFoo(); // may fail
// RETURN_IF_PARSE_ERROR
//
// SAFE_USE(foo);
#define RETURN_IF_PARSE_ERROR_VALUE(x) \
if (has_error()) return x;
#define RETURN_IF_PARSE_ERROR RETURN_IF_PARSE_ERROR_VALUE(nullptr)
#define RETURN_IF_PARSE_ERROR_VOID \
if (has_error()) return;
// ----------------------------------------------------------------------------
// Implementation of Parser
......@@ -327,7 +309,7 @@ Expression* Parser::ImportMetaExpression(int pos) {
pos);
}
Literal* Parser::ExpressionFromLiteral(Token::Value token, int pos) {
Expression* Parser::ExpressionFromLiteral(Token::Value token, int pos) {
switch (token) {
case Token::NULL_LITERAL:
return factory()->NewNullLiteral(pos);
......@@ -354,7 +336,7 @@ Literal* Parser::ExpressionFromLiteral(Token::Value token, int pos) {
default:
DCHECK(false);
}
return nullptr;
return FailureExpression();
}
Expression* Parser::NewV8Intrinsic(const AstRawString* name,
......@@ -384,14 +366,14 @@ Expression* Parser::NewV8Intrinsic(const AstRawString* name,
return args.at(0);
} else {
ReportMessage(MessageTemplate::kNotIsvar);
return nullptr;
return FailureExpression();
}
}
// Check that the expected number of arguments are being passed.
if (function->nargs != -1 && function->nargs != args.length()) {
ReportMessage(MessageTemplate::kRuntimeWrongNumArgs);
return nullptr;
return FailureExpression();
}
return factory()->NewCallRuntime(function, args, pos);
......@@ -403,7 +385,7 @@ Expression* Parser::NewV8Intrinsic(const AstRawString* name,
// Check that the function is defined.
if (context_index == Context::kNotFound) {
ReportMessage(MessageTemplate::kNotDefined, name);
return nullptr;
return FailureExpression();
}
return factory()->NewCallRuntime(context_index, args, pos);
......@@ -614,7 +596,6 @@ FunctionLiteral* Parser::DoParseProgram(Isolate* isolate, ParseInfo* info) {
// unchanged if the property already exists.
InsertSloppyBlockFunctionVarBindings(scope);
}
RETURN_IF_PARSE_ERROR;
CheckConflictingVarDeclarations(scope);
if (info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) {
......@@ -639,7 +620,7 @@ FunctionLiteral* Parser::DoParseProgram(Isolate* isolate, ParseInfo* info) {
// Make sure the target stack is empty.
DCHECK_NULL(target_stack_);
RETURN_IF_PARSE_ERROR;
if (has_error()) return nullptr;
return result;
}
......@@ -867,7 +848,7 @@ FunctionLiteral* Parser::DoParseFunction(Isolate* isolate, ParseInfo* info,
arguments_for_wrapped_function);
}
RETURN_IF_PARSE_ERROR;
if (has_error()) return nullptr;
result->set_requires_instance_members_initializer(
info->requires_instance_members_initializer());
}
......@@ -918,7 +899,7 @@ void Parser::ParseModuleItemList(ScopedPtrList<Statement>* body) {
DCHECK(scope()->is_module_scope());
while (peek() != Token::EOS) {
Statement* stat = ParseModuleItem();
RETURN_IF_PARSE_ERROR_VOID;
if (has_error()) return;
if (stat->IsEmptyStatement()) continue;
body->Add(stat);
}
......@@ -975,7 +956,7 @@ ZoneChunkList<Parser::ExportClauseData>* Parser::ParseExportClause(
export_data->push_back({export_name, local_name, location});
if (peek() == Token::RBRACE) break;
Expect(Token::COMMA);
RETURN_IF_PARSE_ERROR;
if (has_error()) break;
}
Expect(Token::RBRACE);
......@@ -1018,7 +999,6 @@ ZonePtrList<const Parser::NamedImport>* Parser::ParseNamedImports(int pos) {
return nullptr;
}
RETURN_IF_PARSE_ERROR;
DeclareVariable(local_name, VariableMode::kConst, kNeedsInitialization,
position());
......@@ -1069,7 +1049,6 @@ void Parser::ParseImportDeclaration() {
if (tok != Token::MUL && tok != Token::LBRACE) {
import_default_binding = ParseIdentifier(kDontAllowRestrictedIdentifiers);
import_default_binding_loc = scanner()->location();
RETURN_IF_PARSE_ERROR_VOID;
DeclareVariable(import_default_binding, VariableMode::kConst,
kNeedsInitialization, pos);
}
......@@ -1086,7 +1065,6 @@ void Parser::ParseImportDeclaration() {
module_namespace_binding =
ParseIdentifier(kDontAllowRestrictedIdentifiers);
module_namespace_binding_loc = scanner()->location();
RETURN_IF_PARSE_ERROR_VOID;
DeclareVariable(module_namespace_binding, VariableMode::kConst,
kCreatedInitialized, pos);
break;
......@@ -1176,7 +1154,6 @@ Statement* Parser::ParseExportDefault() {
ExpressionClassifier classifier(this);
Expression* value = ParseAssignmentExpression(true);
ValidateExpression();
RETURN_IF_PARSE_ERROR;
SetFunctionName(value, ast_value_factory()->default_string());
const AstRawString* local_name =
......@@ -1199,7 +1176,7 @@ Statement* Parser::ParseExportDefault() {
}
}
RETURN_IF_PARSE_ERROR;
if (has_error()) return nullptr;
DCHECK_EQ(local_names.length(), 1);
module()->AddExport(local_names.first(),
ast_value_factory()->default_string(), default_loc,
......@@ -1244,7 +1221,6 @@ void Parser::ParseExportStar() {
Scanner::Location export_name_loc = scanner()->location();
const AstRawString* local_name = NextInternalNamespaceExportName();
Scanner::Location local_name_loc = Scanner::Location::invalid();
RETURN_IF_PARSE_ERROR_VOID;
DeclareVariable(local_name, VariableMode::kConst, kCreatedInitialized, pos);
ExpectContextualKeyword(Token::FROM);
......@@ -1304,7 +1280,6 @@ Statement* Parser::ParseExportDeclaration() {
return nullptr;
}
ExpectSemicolon();
RETURN_IF_PARSE_ERROR;
if (module_specifier == nullptr) {
for (const ExportClauseData& data : *export_data) {
module()->AddExport(data.local_name, data.export_name, data.location,
......@@ -1573,10 +1548,11 @@ Expression* Parser::RewriteReturn(Expression* return_value, int pos) {
}
Expression* Parser::RewriteDoExpression(Block* body, int pos) {
if (has_error()) return FailureExpression();
Variable* result = NewTemporary(ast_value_factory()->dot_result_string());
DoExpression* expr = factory()->NewDoExpression(body, result, pos);
if (!Rewriter::Rewrite(this, GetClosureScope(), expr, ast_value_factory())) {
return nullptr;
return FailureExpression();
}
return expr;
}
......@@ -1977,7 +1953,6 @@ void Parser::DesugarBindingInForEachStatement(ForInfo* for_info,
for_info->bound_names.Contains(name)) {
ReportMessageAt(for_info->parsing_result.bindings_loc,
MessageTemplate::kVarRedeclaration, name);
return;
}
}
catch_scope = catch_scope->outer_scope();
......@@ -2614,7 +2589,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
if (!is_wrapped) {
Expect(Token::LPAREN);
RETURN_IF_PARSE_ERROR;
if (has_error()) return nullptr;
}
scope->set_start_position(position());
......@@ -2658,8 +2633,6 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
}
}
RETURN_IF_PARSE_ERROR;
// Validate function name. We can do this only after parsing the function,
// since the function can declare itself strict.
language_mode = scope->language_mode();
......@@ -3219,6 +3192,7 @@ Expression* Parser::RewriteClassLiteral(Scope* block_scope,
}
void Parser::CheckConflictingVarDeclarations(Scope* scope) {
if (has_error()) return;
Declaration* decl = scope->CheckConflictingVarDeclarations();
if (decl != nullptr) {
// In ES6, conflicting variable bindings are early errors.
......@@ -3631,7 +3605,7 @@ void Parser::SetFunctionNameFromPropertyName(ObjectLiteralProperty* property,
void Parser::SetFunctionNameFromIdentifierRef(Expression* value,
Expression* identifier) {
if (has_error() || !identifier->IsVariableProxy()) return;
if (!identifier->IsVariableProxy()) return;
SetFunctionName(value, identifier->AsVariableProxy()->raw_name());
}
......@@ -4102,8 +4076,5 @@ Statement* Parser::FinalizeForOfStatement(ForOfStatement* loop,
return final_loop;
}
#undef RETURN_IF_PARSE_ERROR_VOID
#undef RETURN_IF_PARSE_ERROR
#undef RETURN_IF_PARSE_ERROR_VALUE
} // namespace internal
} // namespace v8
......@@ -812,6 +812,7 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
return nullptr;
}
V8_INLINE static std::nullptr_t NullStatement() { return nullptr; }
Expression* FailureExpression() { return factory()->FailureExpression(); }
template <typename T>
V8_INLINE static bool IsNull(T subject) {
......@@ -851,7 +852,7 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
Expression* NewTargetExpression(int pos);
Expression* ImportMetaExpression(int pos);
Literal* ExpressionFromLiteral(Token::Value token, int pos);
Expression* ExpressionFromLiteral(Token::Value token, int pos);
V8_INLINE VariableProxy* ExpressionFromIdentifier(
const AstRawString* name, int start_position,
......
......@@ -74,6 +74,7 @@ class PatternRewriter final : public AstVisitor<PatternRewriter> {
}
Expression* Rewrite(Assignment* assign) {
if (parser_->has_error()) return parser_->FailureExpression();
DCHECK_EQ(Token::ASSIGN, assign->op());
int pos = assign->position();
......
......@@ -95,6 +95,9 @@ class PreParserExpression {
: code_(TypeField::encode(kNull)), variables_(nullptr) {}
static PreParserExpression Null() { return PreParserExpression(); }
static PreParserExpression Failure() {
return PreParserExpression(TypeField::encode(kFailure));
}
static PreParserExpression Default(
VariableZoneThreadedListType* variables = nullptr) {
......@@ -320,6 +323,7 @@ class PreParserExpression {
private:
enum Type {
kNull,
kFailure,
kExpression,
kIdentifierExpression,
kStringLiteralExpression,
......@@ -1503,6 +1507,9 @@ class PreParser : public ParserBase<PreParser> {
V8_INLINE static PreParserExpression NullExpression() {
return PreParserExpression::Null();
}
V8_INLINE static PreParserExpression FailureExpression() {
return PreParserExpression::Failure();
}
V8_INLINE static PreParserExpression NullLiteralProperty() {
return PreParserExpression::Null();
}
......
......@@ -1838,6 +1838,7 @@ void RunParserSyncTest(
context_data[i][0],
statement_data[j],
context_data[i][1]);
PrintF("%s\n", program.start());
CHECK_EQ(length, kProgramSize);
TestParserSync(program.start(), flags, flags_len, result,
always_true_flags, always_true_len, always_false_flags,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment