summaryrefslogtreecommitdiff
path: root/deps/v8/src/parsing/parser-base.h
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/parsing/parser-base.h')
-rw-r--r--deps/v8/src/parsing/parser-base.h1324
1 files changed, 665 insertions, 659 deletions
diff --git a/deps/v8/src/parsing/parser-base.h b/deps/v8/src/parsing/parser-base.h
index 9d13724f06..d1ad0e9d13 100644
--- a/deps/v8/src/parsing/parser-base.h
+++ b/deps/v8/src/parsing/parser-base.h
@@ -5,12 +5,14 @@
#ifndef V8_PARSING_PARSER_BASE_H_
#define V8_PARSING_PARSER_BASE_H_
+#include <stdint.h>
#include <vector>
#include "src/ast/ast-source-ranges.h"
#include "src/ast/ast.h"
#include "src/ast/scopes.h"
#include "src/bailout-reason.h"
+#include "src/base/flags.h"
#include "src/base/hashmap.h"
#include "src/base/v8-fallthrough.h"
#include "src/counters.h"
@@ -37,31 +39,13 @@ enum AllowLabelledFunctionStatement {
kDisallowLabelledFunctionStatement,
};
-enum class ParseFunctionFlags {
+enum class ParseFunctionFlag : uint8_t {
kIsNormal = 0,
- kIsGenerator = 1,
- kIsAsync = 2,
- kIsDefault = 4
+ kIsGenerator = 1 << 0,
+ kIsAsync = 1 << 1
};
-static inline ParseFunctionFlags operator|(ParseFunctionFlags lhs,
- ParseFunctionFlags rhs) {
- typedef unsigned char T;
- return static_cast<ParseFunctionFlags>(static_cast<T>(lhs) |
- static_cast<T>(rhs));
-}
-
-static inline ParseFunctionFlags& operator|=(ParseFunctionFlags& lhs,
- const ParseFunctionFlags& rhs) {
- lhs = lhs | rhs;
- return lhs;
-}
-
-static inline bool operator&(ParseFunctionFlags bitfield,
- ParseFunctionFlags mask) {
- typedef unsigned char T;
- return static_cast<T>(bitfield) & static_cast<T>(mask);
-}
+typedef base::Flags<ParseFunctionFlag> ParseFunctionFlags;
struct FormalParametersBase {
explicit FormalParametersBase(DeclarationScope* scope) : scope(scope) {}
@@ -228,6 +212,17 @@ class SourceRangeScope final {
template <typename Impl>
struct ParserTypes;
+enum class ParsePropertyKind : uint8_t {
+ kAccessorGetter,
+ kAccessorSetter,
+ kValue,
+ kShorthand,
+ kMethod,
+ kClassField,
+ kSpread,
+ kNotSet
+};
+
template <typename Impl>
class ParserBase {
public:
@@ -248,6 +243,10 @@ class ParserBase {
typedef typename Types::ForStatement ForStatementT;
typedef typename v8::internal::ExpressionClassifier<Types>
ExpressionClassifier;
+ typedef typename Types::FuncNameInferrer FuncNameInferrer;
+ typedef typename Types::FuncNameInferrer::State FuncNameInferrerState;
+ typedef typename Types::SourceRange SourceRange;
+ typedef typename Types::SourceRangeScope SourceRangeScope;
// All implementation-specific methods must be called through this.
Impl* impl() { return static_cast<Impl*>(this); }
@@ -262,7 +261,7 @@ class ParserBase {
original_scope_(nullptr),
function_state_(nullptr),
extension_(extension),
- fni_(nullptr),
+ fni_(ast_value_factory, zone),
ast_value_factory_(ast_value_factory),
ast_node_factory_(ast_value_factory, zone),
runtime_call_stats_(runtime_call_stats),
@@ -300,12 +299,6 @@ class ParserBase {
#undef ALLOW_ACCESSORS
- bool allow_harmony_bigint() const {
- return scanner()->allow_harmony_bigint();
- }
- void set_allow_harmony_bigint(bool allow) {
- scanner()->set_allow_harmony_bigint(allow);
- }
bool allow_harmony_numeric_separator() const {
return scanner()->allow_harmony_numeric_separator();
}
@@ -370,7 +363,7 @@ class ParserBase {
// The parser's current scope is in scope_. BlockState and FunctionState
// constructors push on the scope stack and the destructors pop. They are also
// used to hold the parser's per-funcion state.
- class BlockState BASE_EMBEDDED {
+ class BlockState {
public:
BlockState(Scope** scope_stack, Scope* scope)
: scope_stack_(scope_stack), outer_scope_(*scope_stack) {
@@ -433,7 +426,7 @@ class ParserBase {
return destructuring_assignments_to_rewrite_;
}
- ZoneVector<typename ExpressionClassifier::Error>* GetReportedErrorList() {
+ ZoneList<typename ExpressionClassifier::Error>* GetReportedErrorList() {
return &reported_errors_;
}
@@ -490,8 +483,7 @@ class ParserBase {
ZoneChunkList<RewritableExpressionT> destructuring_assignments_to_rewrite_;
- // We use a ZoneVector here because we need to do a lot of random access.
- ZoneVector<typename ExpressionClassifier::Error> reported_errors_;
+ ZoneList<typename ExpressionClassifier::Error> reported_errors_;
// A reason, if any, why this function should not be optimized.
BailoutReason dont_optimize_reason_;
@@ -652,11 +644,11 @@ class ParserBase {
// scope itself is either allocated in zone() or in target_zone if one is
// passed in.
DeclarationScope* NewFunctionScope(FunctionKind kind,
- Zone* target_zone = nullptr) const {
+ Zone* parse_zone = nullptr) const {
DCHECK(ast_value_factory());
- if (target_zone == nullptr) target_zone = zone();
- DeclarationScope* result = new (target_zone)
- DeclarationScope(zone(), scope(), FUNCTION_SCOPE, kind);
+ if (parse_zone == nullptr) parse_zone = zone();
+ DeclarationScope* result = new (zone())
+ DeclarationScope(parse_zone, scope(), FUNCTION_SCOPE, kind);
// Record presence of an inner function scope
function_state_->RecordFunctionOrEvalCall();
@@ -679,6 +671,8 @@ class ParserBase {
AstValueFactory* ast_value_factory() const { return ast_value_factory_; }
int position() const { return scanner_->location().beg_pos; }
int peek_position() const { return scanner_->peek_location().beg_pos; }
+ int end_position() const { return scanner_->location().end_pos; }
+ int peek_end_position() const { return scanner_->peek_location().end_pos; }
bool stack_overflow() const {
return pending_error_handler()->stack_overflow();
}
@@ -694,8 +688,7 @@ class ParserBase {
// Returns the position past the following semicolon (if it exists), and the
// position past the end of the current token otherwise.
int PositionAfterSemicolon() {
- return (peek() == Token::SEMICOLON) ? scanner_->peek_location().end_pos
- : scanner_->location().end_pos;
+ return (peek() == Token::SEMICOLON) ? peek_end_position() : end_position();
}
V8_INLINE Token::Value PeekAhead() {
@@ -720,7 +713,7 @@ class ParserBase {
Token::Value next = Next();
USE(next);
USE(token);
- DCHECK(next == token);
+ DCHECK_EQ(next, token);
}
bool Check(Token::Value token) {
@@ -753,22 +746,14 @@ class ParserBase {
return;
}
- Token::Value current = scanner()->current_token();
- Scanner::Location current_location = scanner()->location();
- Token::Value next = Next();
-
- if (next == Token::SEMICOLON) {
- return;
- }
-
*ok = false;
- if (current == Token::AWAIT && !is_async_function()) {
- ReportMessageAt(current_location,
+ if (scanner()->current_token() == Token::AWAIT && !is_async_function()) {
+ ReportMessageAt(scanner()->location(),
MessageTemplate::kAwaitNotInAsyncFunction, kSyntaxError);
return;
}
- ReportUnexpectedToken(next);
+ ReportUnexpectedToken(Next());
}
// Dummy functions, just useful as arguments to CHECK_OK_CUSTOM.
@@ -778,14 +763,7 @@ class ParserBase {
return result;
}
- bool is_any_identifier(Token::Value token) {
- return token == Token::IDENTIFIER || token == Token::ENUM ||
- token == Token::AWAIT || token == Token::ASYNC ||
- token == Token::ESCAPED_STRICT_RESERVED_WORD ||
- token == Token::FUTURE_STRICT_RESERVED_WORD || token == Token::LET ||
- token == Token::STATIC || token == Token::YIELD;
- }
- bool peek_any_identifier() { return is_any_identifier(peek()); }
+ bool peek_any_identifier() { return Token::IsAnyIdentifier(peek()); }
bool CheckContextualKeyword(Token::Value token) {
if (PeekContextualKeyword(token)) {
@@ -961,7 +939,11 @@ class ParserBase {
void ReportClassifierError(
const typename ExpressionClassifier::Error& error) {
- impl()->ReportMessageAt(error.location, error.message, error.arg);
+ if (classifier()->does_error_reporting()) {
+ impl()->ReportMessageAt(error.location, error.message, error.arg);
+ } else {
+ impl()->ReportUnidentifiableError();
+ }
}
void ValidateExpression(bool* ok) {
@@ -1006,7 +988,7 @@ class ParserBase {
}
bool IsValidArrowFormalParametersStart(Token::Value token) {
- return is_any_identifier(token) || token == Token::LPAREN;
+ return Token::IsAnyIdentifier(token) || token == Token::LPAREN;
}
void ValidateArrowFormalParameters(ExpressionT expr,
@@ -1096,15 +1078,12 @@ class ParserBase {
ExpressionT ParseRegExpLiteral(bool* ok);
+ ExpressionT ParseBindingPattern(bool* ok);
ExpressionT ParsePrimaryExpression(bool* is_async, bool* ok);
- ExpressionT ParsePrimaryExpression(bool* ok) {
- bool is_async;
- return ParsePrimaryExpression(&is_async, ok);
- }
// Use when parsing an expression that is known to not be a pattern or part
// of a pattern.
- V8_INLINE ExpressionT ParseExpression(bool accept_IN, bool* ok);
+ V8_INLINE ExpressionT ParseExpression(bool* ok);
// This method does not wrap the parsing of the expression inside a
// new expression classifier; it uses the top-level classifier instead.
@@ -1117,28 +1096,21 @@ class ParserBase {
ExpressionT ParseArrayLiteral(bool* ok);
- enum class PropertyKind {
- kAccessorProperty,
- kValueProperty,
- kShorthandProperty,
- kMethodProperty,
- kClassField,
- kSpreadProperty,
- kNotSet
- };
+ inline static bool IsAccessor(ParsePropertyKind kind) {
+ return IsInRange(kind, ParsePropertyKind::kAccessorGetter,
+ ParsePropertyKind::kAccessorSetter);
+ }
- bool SetPropertyKindFromToken(Token::Value token, PropertyKind* kind);
- ExpressionT ParsePropertyName(IdentifierT* name, PropertyKind* kind,
- bool* is_generator, bool* is_get, bool* is_set,
- bool* is_async, bool* is_computed_name,
- bool* ok);
+ ExpressionT ParsePropertyName(IdentifierT* name, ParsePropertyKind* kind,
+ ParseFunctionFlags* flags,
+ bool* is_computed_name, bool* ok);
ExpressionT ParseObjectLiteral(bool* ok);
ClassLiteralPropertyT ParseClassPropertyDefinition(
ClassLiteralChecker* checker, ClassInfo* class_info,
IdentifierT* property_name, bool has_extends, bool* is_computed_name,
ClassLiteralProperty::Kind* property_kind, bool* is_static, bool* ok);
- ExpressionT ParseClassFieldInitializer(ClassInfo* class_info, bool is_static,
- bool* ok);
+ ExpressionT ParseClassFieldInitializer(ClassInfo* class_info, int beg_pos,
+ bool is_static, bool* ok);
ObjectLiteralPropertyT ParseObjectPropertyDefinition(
ObjectLiteralChecker* checker, bool* is_computed_name,
bool* is_rest_property, bool* ok);
@@ -1147,17 +1119,26 @@ class ParserBase {
bool* is_simple_parameter_list, bool* ok);
ExpressionListT ParseArguments(Scanner::Location* first_spread_pos,
bool* ok) {
- return ParseArguments(first_spread_pos, false, nullptr, ok);
+ bool is_simple = true;
+ return ParseArguments(first_spread_pos, false, &is_simple, ok);
}
ExpressionT ParseAssignmentExpression(bool accept_IN, bool* ok);
ExpressionT ParseYieldExpression(bool accept_IN, bool* ok);
V8_INLINE ExpressionT ParseConditionalExpression(bool accept_IN, bool* ok);
+ ExpressionT ParseConditionalContinuation(ExpressionT expression,
+ bool accept_IN, int pos, bool* ok);
ExpressionT ParseBinaryExpression(int prec, bool accept_IN, bool* ok);
- ExpressionT ParseUnaryExpression(bool* ok);
+ ExpressionT ParseUnaryOpExpression(bool* ok);
+ ExpressionT ParseAwaitExpression(bool* ok);
+ ExpressionT ParsePrefixExpression(bool* ok);
+ V8_INLINE ExpressionT ParseUnaryExpression(bool* ok);
V8_INLINE ExpressionT ParsePostfixExpression(bool* ok);
V8_INLINE ExpressionT ParseLeftHandSideExpression(bool* ok);
- ExpressionT ParseMemberWithNewPrefixesExpression(bool* is_async, bool* ok);
+ ExpressionT ParseMemberWithPresentNewPrefixesExpression(bool* is_async,
+ bool* ok);
+ V8_INLINE ExpressionT ParseMemberWithNewPrefixesExpression(bool* is_async,
+ bool* ok);
V8_INLINE ExpressionT ParseMemberExpression(bool* is_async, bool* ok);
V8_INLINE ExpressionT ParseMemberExpressionContinuation(
ExpressionT expression, bool* is_async, bool* ok);
@@ -1169,8 +1150,6 @@ class ParserBase {
ExpressionT ParseArrowFunctionLiteral(bool accept_IN,
const FormalParametersT& parameters,
int rewritable_length, bool* ok);
- void ParseSingleExpressionFunctionBody(StatementListT body, bool is_async,
- bool accept_IN, bool* ok);
void ParseAsyncFunctionBody(Scope* scope, StatementListT body, bool* ok);
ExpressionT ParseAsyncFunctionLiteral(bool* ok);
ExpressionT ParseClassLiteral(IdentifierT name,
@@ -1205,11 +1184,14 @@ class ParserBase {
bool default_export, bool* ok);
StatementT ParseNativeDeclaration(bool* ok);
+ // Whether we're parsing a single-expression arrow function or something else.
+ enum class FunctionBodyType { kExpression, kBlock };
// Consumes the ending }.
void ParseFunctionBody(StatementListT result, IdentifierT function_name,
int pos, const FormalParametersT& parameters,
FunctionKind kind,
- FunctionLiteral::FunctionType function_type, bool* ok);
+ FunctionLiteral::FunctionType function_type,
+ FunctionBodyType body_type, bool accept_IN, bool* ok);
// Under some circumstances, we allow preparsing to abort if the preparsed
// function is "long and trivial", and fully parse instead. Our current
@@ -1363,8 +1345,7 @@ class ParserBase {
Scope* scope, Variable* var,
typename DeclarationDescriptor::Kind declaration_kind);
- FunctionKind FunctionKindForImpl(bool is_method, bool is_generator,
- bool is_async) {
+ FunctionKind FunctionKindForImpl(bool is_method, ParseFunctionFlags flags) {
static const FunctionKind kFunctionKinds[][2][2] = {
{
// is_method=false
@@ -1382,17 +1363,19 @@ class ParserBase {
FunctionKind::kConciseGeneratorMethod,
FunctionKind::kAsyncConciseGeneratorMethod},
}};
- return kFunctionKinds[is_method][is_generator][is_async];
+ return kFunctionKinds[is_method]
+ [(flags & ParseFunctionFlag::kIsGenerator) != 0]
+ [(flags & ParseFunctionFlag::kIsAsync) != 0];
}
- inline FunctionKind FunctionKindFor(bool is_generator, bool is_async) {
+ inline FunctionKind FunctionKindFor(ParseFunctionFlags flags) {
const bool kIsMethod = false;
- return FunctionKindForImpl(kIsMethod, is_generator, is_async);
+ return FunctionKindForImpl(kIsMethod, flags);
}
- inline FunctionKind MethodKindFor(bool is_generator, bool is_async) {
+ inline FunctionKind MethodKindFor(ParseFunctionFlags flags) {
const bool kIsMethod = true;
- return FunctionKindForImpl(kIsMethod, is_generator, is_async);
+ return FunctionKindForImpl(kIsMethod, flags);
}
// Keep track of eval() calls since they disable all local variable
@@ -1466,8 +1449,8 @@ class ParserBase {
explicit ClassLiteralChecker(ParserBase* parser)
: parser_(parser), has_seen_constructor_(false) {}
- void CheckClassMethodName(Token::Value property, PropertyKind type,
- bool is_generator, bool is_async, bool is_static,
+ void CheckClassMethodName(Token::Value property, ParsePropertyKind type,
+ ParseFunctionFlags flags, bool is_static,
bool* ok);
void CheckClassFieldName(bool is_static, bool* ok);
@@ -1546,7 +1529,7 @@ class ParserBase {
Scope* original_scope_; // The top scope for the current parsing item.
FunctionState* function_state_; // Function state stack.
v8::Extension* extension_;
- FuncNameInferrer* fni_;
+ FuncNameInferrer fni_;
AstValueFactory* ast_value_factory_; // Not owned.
typename Types::Factory ast_node_factory_;
RuntimeCallStats* runtime_call_stats_;
@@ -1577,8 +1560,6 @@ class ParserBase {
bool allow_harmony_import_meta_;
bool allow_harmony_private_fields_;
bool allow_eval_cache_;
-
- friend class DiscardableZoneScope;
};
template <typename Impl>
@@ -1592,13 +1573,12 @@ ParserBase<Impl>::FunctionState::FunctionState(
outer_function_state_(*function_state_stack),
scope_(scope),
destructuring_assignments_to_rewrite_(scope->zone()),
- reported_errors_(scope_->zone()),
+ reported_errors_(16, scope->zone()),
dont_optimize_reason_(BailoutReason::kNoReason),
next_function_is_likely_called_(false),
previous_function_was_likely_called_(false),
contains_function_or_eval_(false) {
*function_state_stack = this;
- reported_errors_.reserve(16);
if (outer_function_state_) {
outer_function_state_->previous_function_was_likely_called_ =
outer_function_state_->next_function_is_likely_called_;
@@ -1704,16 +1684,10 @@ template <typename Impl>
typename ParserBase<Impl>::IdentifierT
ParserBase<Impl>::ParseAndClassifyIdentifier(bool* ok) {
Token::Value next = Next();
- if (next == Token::IDENTIFIER || next == Token::ASYNC ||
- (next == Token::AWAIT && !parsing_module_ && !is_async_function())) {
+ STATIC_ASSERT(Token::IDENTIFIER + 1 == Token::ASYNC);
+ if (IsInRange(next, Token::IDENTIFIER, Token::ASYNC)) {
IdentifierT name = impl()->GetSymbol();
- if (impl()->IsArguments(name) && scope()->ShouldBanArguments()) {
- ReportMessage(MessageTemplate::kArgumentsDisallowedInInitializer);
- *ok = false;
- return impl()->NullIdentifier();
- }
-
// When this function is used to read a formal parameter, we don't always
// know whether the function is going to be strict or sloppy. Indeed for
// arrow functions we don't always know that the identifier we are reading
@@ -1721,15 +1695,18 @@ ParserBase<Impl>::ParseAndClassifyIdentifier(bool* ok) {
// must detect because we know we're in strict mode, we also record any
// error that we might make in the future once we know the language mode.
if (impl()->IsEvalOrArguments(name)) {
+ if (impl()->IsArguments(name) && scope()->ShouldBanArguments()) {
+ ReportMessage(MessageTemplate::kArgumentsDisallowedInInitializer);
+ *ok = false;
+ return impl()->NullIdentifier();
+ }
+
classifier()->RecordStrictModeFormalParameterError(
scanner()->location(), MessageTemplate::kStrictEvalArguments);
if (is_strict(language_mode())) {
classifier()->RecordBindingPatternError(
scanner()->location(), MessageTemplate::kStrictEvalArguments);
}
- } else if (next == Token::AWAIT) {
- classifier()->RecordAsyncArrowFormalParametersError(
- scanner()->location(), MessageTemplate::kAwaitBindingIdentifier);
}
if (classifier()->duplicate_finder() != nullptr &&
@@ -1737,20 +1714,17 @@ ParserBase<Impl>::ParseAndClassifyIdentifier(bool* ok) {
ast_value_factory())) {
classifier()->RecordDuplicateFormalParameterError(scanner()->location());
}
+
return name;
+ } else if (next == Token::AWAIT && !parsing_module_ && !is_async_function()) {
+ classifier()->RecordAsyncArrowFormalParametersError(
+ scanner()->location(), MessageTemplate::kAwaitBindingIdentifier);
+ return impl()->GetSymbol();
} else if (is_sloppy(language_mode()) &&
- (next == Token::FUTURE_STRICT_RESERVED_WORD ||
- next == Token::ESCAPED_STRICT_RESERVED_WORD ||
- next == Token::LET || next == Token::STATIC ||
+ (Token::IsStrictReservedWord(next) ||
(next == Token::YIELD && !is_generator()))) {
classifier()->RecordStrictModeFormalParameterError(
scanner()->location(), MessageTemplate::kUnexpectedStrictReserved);
- if (next == Token::ESCAPED_STRICT_RESERVED_WORD &&
- is_strict(language_mode())) {
- ReportUnexpectedToken(next);
- *ok = false;
- return impl()->NullIdentifier();
- }
if (scanner()->IsLet()) {
classifier()->RecordLetPatternError(
scanner()->location(), MessageTemplate::kLetInLexicalBinding);
@@ -1774,9 +1748,7 @@ ParserBase<Impl>::ParseIdentifierOrStrictReservedWord(
next == Token::ASYNC) {
*is_strict_reserved = false;
*is_await = next == Token::AWAIT;
- } else if (next == Token::ESCAPED_STRICT_RESERVED_WORD ||
- next == Token::FUTURE_STRICT_RESERVED_WORD || next == Token::LET ||
- next == Token::STATIC ||
+ } else if (Token::IsStrictReservedWord(next) ||
(next == Token::YIELD && !IsGeneratorFunction(function_kind))) {
*is_strict_reserved = true;
} else {
@@ -1792,12 +1764,8 @@ template <typename Impl>
typename ParserBase<Impl>::IdentifierT ParserBase<Impl>::ParseIdentifierName(
bool* ok) {
Token::Value next = Next();
- if (next != Token::IDENTIFIER && next != Token::ASYNC &&
- next != Token::ENUM && next != Token::AWAIT && next != Token::LET &&
- next != Token::STATIC && next != Token::YIELD &&
- next != Token::FUTURE_STRICT_RESERVED_WORD &&
- next != Token::ESCAPED_KEYWORD &&
- next != Token::ESCAPED_STRICT_RESERVED_WORD && !Token::IsKeyword(next)) {
+ if (!Token::IsAnyIdentifier(next) && next != Token::ESCAPED_KEYWORD &&
+ !Token::IsKeyword(next)) {
ReportUnexpectedToken(next);
*ok = false;
return impl()->NullIdentifier();
@@ -1852,6 +1820,39 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseRegExpLiteral(
}
template <typename Impl>
+typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseBindingPattern(
+ bool* ok) {
+ // Pattern ::
+ // Identifier
+ // ArrayLiteral
+ // ObjectLiteral
+
+ int beg_pos = peek_position();
+ Token::Value token = peek();
+ ExpressionT result;
+
+ if (Token::IsAnyIdentifier(token)) {
+ IdentifierT name = ParseAndClassifyIdentifier(CHECK_OK);
+ result = impl()->ExpressionFromIdentifier(name, beg_pos);
+ } else {
+ classifier()->RecordNonSimpleParameter();
+
+ if (token == Token::LBRACK) {
+ result = ParseArrayLiteral(CHECK_OK);
+ } else if (token == Token::LBRACE) {
+ result = ParseObjectLiteral(CHECK_OK);
+ } else {
+ ReportUnexpectedToken(Next());
+ *ok = false;
+ return impl()->NullExpression();
+ }
+ }
+
+ ValidateBindingPattern(CHECK_OK);
+ return result;
+}
+
+template <typename Impl>
typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePrimaryExpression(
bool* is_async, bool* ok) {
// PrimaryExpression ::
@@ -1872,7 +1873,8 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePrimaryExpression(
// AsyncFunctionLiteral
int beg_pos = peek_position();
- switch (peek()) {
+ Token::Value token = peek();
+ switch (token) {
case Token::THIS: {
BindingPatternUnexpectedToken();
Consume(Token::THIS);
@@ -1884,16 +1886,25 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePrimaryExpression(
case Token::FALSE_LITERAL:
case Token::SMI:
case Token::NUMBER:
- case Token::BIGINT:
+ case Token::BIGINT: {
+ // Ensure continuous enum range.
+ DCHECK(Token::IsLiteral(token));
BindingPatternUnexpectedToken();
return impl()->ExpressionFromLiteral(Next(), beg_pos);
+ }
+ case Token::STRING: {
+ DCHECK(Token::IsLiteral(token));
+ BindingPatternUnexpectedToken();
+ Consume(Token::STRING);
+ return impl()->ExpressionFromString(beg_pos);
+ }
case Token::ASYNC:
if (!scanner()->HasLineTerminatorAfterNext() &&
PeekAhead() == Token::FUNCTION) {
BindingPatternUnexpectedToken();
Consume(Token::ASYNC);
- return ParseAsyncFunctionLiteral(CHECK_OK);
+ return ParseAsyncFunctionLiteral(ok);
}
// CoverCallExpressionAndAsyncArrowHead
*is_async = true;
@@ -1903,19 +1914,16 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePrimaryExpression(
case Token::STATIC:
case Token::YIELD:
case Token::AWAIT:
- case Token::ESCAPED_STRICT_RESERVED_WORD:
- case Token::FUTURE_STRICT_RESERVED_WORD: {
+ case Token::FUTURE_STRICT_RESERVED_WORD:
+ case Token::ESCAPED_STRICT_RESERVED_WORD: {
+ // Ensure continuous enum range.
+ DCHECK(IsInRange(token, Token::IDENTIFIER,
+ Token::ESCAPED_STRICT_RESERVED_WORD));
// Using eval or arguments in this context is OK even in strict mode.
IdentifierT name = ParseAndClassifyIdentifier(CHECK_OK);
return impl()->ExpressionFromIdentifier(name, beg_pos);
}
- case Token::STRING: {
- BindingPatternUnexpectedToken();
- Consume(Token::STRING);
- return impl()->ExpressionFromString(beg_pos);
- }
-
case Token::ASSIGN_DIV:
case Token::DIV:
classifier()->RecordBindingPatternError(
@@ -1931,8 +1939,8 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePrimaryExpression(
case Token::LPAREN: {
// Arrow function formal parameters are either a single identifier or a
// list of BindingPattern productions enclosed in parentheses.
- // Parentheses are not valid on the LHS of a BindingPattern, so we use the
- // is_valid_binding_pattern() check to detect multiple levels of
+ // Parentheses are not valid on the LHS of a BindingPattern, so we use
+ // the is_valid_binding_pattern() check to detect multiple levels of
// parenthesization.
bool pattern_error = !classifier()->is_valid_binding_pattern();
classifier()->RecordPatternError(scanner()->peek_location(),
@@ -1955,7 +1963,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePrimaryExpression(
function_state_->set_next_function_is_likely_called();
}
ExpressionT expr = ParseExpressionCoverGrammar(true, CHECK_OK);
- Expect(Token::RPAREN, CHECK_OK);
+ Expect(Token::RPAREN, ok);
return expr;
}
@@ -2010,10 +2018,10 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePrimaryExpression(
template <typename Impl>
typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseExpression(
- bool accept_IN, bool* ok) {
+ bool* ok) {
ExpressionClassifier classifier(this);
- ExpressionT result = ParseExpressionCoverGrammar(accept_IN, CHECK_OK);
- ValidateExpression(CHECK_OK);
+ ExpressionT result = ParseExpressionCoverGrammar(true, CHECK_OK);
+ ValidateExpression(ok);
return result;
}
@@ -2038,13 +2046,12 @@ ParserBase<Impl>::ParseExpressionCoverGrammar(bool accept_IN, bool* ok) {
Token::String(Token::ELLIPSIS));
int ellipsis_pos = position();
int pattern_pos = peek_position();
- ExpressionT pattern = ParsePrimaryExpression(CHECK_OK);
+ ExpressionT pattern = ParseBindingPattern(CHECK_OK);
if (peek() == Token::ASSIGN) {
ReportMessage(MessageTemplate::kRestDefaultInitializer);
*ok = false;
return result;
}
- ValidateBindingPattern(CHECK_OK);
right = factory()->NewSpread(pattern, ellipsis_pos, pattern_pos);
} else {
right = ParseAssignmentExpression(accept_IN, CHECK_OK);
@@ -2097,14 +2104,13 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseArrayLiteral(
int pos = peek_position();
ExpressionListT values = impl()->NewExpressionList(4);
int first_spread_index = -1;
- Expect(Token::LBRACK, CHECK_OK);
- while (peek() != Token::RBRACK) {
+ Consume(Token::LBRACK);
+ while (!Check(Token::RBRACK)) {
ExpressionT elem;
if (peek() == Token::COMMA) {
elem = factory()->NewTheHoleLiteral();
- } else if (peek() == Token::ELLIPSIS) {
- int start_pos = peek_position();
- Consume(Token::ELLIPSIS);
+ } else if (Check(Token::ELLIPSIS)) {
+ int start_pos = position();
int expr_pos = peek_position();
ExpressionT argument = ParseAssignmentExpression(true, CHECK_OK);
elem = factory()->NewSpread(argument, start_pos, expr_pos);
@@ -2115,57 +2121,54 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseArrayLiteral(
if (argument->IsAssignment()) {
classifier()->RecordPatternError(
- Scanner::Location(start_pos, scanner()->location().end_pos),
+ Scanner::Location(start_pos, end_position()),
MessageTemplate::kInvalidDestructuringTarget);
} else {
- CheckDestructuringElement(argument, start_pos,
- scanner()->location().end_pos);
+ CheckDestructuringElement(argument, start_pos, end_position());
}
if (peek() == Token::COMMA) {
classifier()->RecordPatternError(
- Scanner::Location(start_pos, scanner()->location().end_pos),
+ Scanner::Location(start_pos, end_position()),
MessageTemplate::kElementAfterRest);
}
} else {
int beg_pos = peek_position();
elem = ParseAssignmentExpression(true, CHECK_OK);
- CheckDestructuringElement(elem, beg_pos, scanner()->location().end_pos);
+ CheckDestructuringElement(elem, beg_pos, end_position());
}
values->Add(elem, zone_);
if (peek() != Token::RBRACK) {
Expect(Token::COMMA, CHECK_OK);
}
}
- Expect(Token::RBRACK, CHECK_OK);
return factory()->NewArrayLiteral(values, first_spread_index, pos);
}
-template <class Impl>
-bool ParserBase<Impl>::SetPropertyKindFromToken(Token::Value token,
- PropertyKind* kind) {
+inline bool ParsePropertyKindFromToken(Token::Value token,
+ ParsePropertyKind* kind) {
// This returns true, setting the property kind, iff the given token is one
// which must occur after a property name, indicating that the previous token
// was in fact a name and not a modifier (like the "get" in "get x").
switch (token) {
case Token::COLON:
- *kind = PropertyKind::kValueProperty;
+ *kind = ParsePropertyKind::kValue;
return true;
case Token::COMMA:
case Token::RBRACE:
case Token::ASSIGN:
- *kind = PropertyKind::kShorthandProperty;
+ *kind = ParsePropertyKind::kShorthand;
return true;
case Token::LPAREN:
- *kind = PropertyKind::kMethodProperty;
+ *kind = ParsePropertyKind::kMethod;
return true;
case Token::MUL:
case Token::SEMICOLON:
- *kind = PropertyKind::kClassField;
+ *kind = ParsePropertyKind::kClassField;
return true;
case Token::PRIVATE_NAME:
- *kind = PropertyKind::kClassField;
+ *kind = ParsePropertyKind::kClassField;
return true;
default:
break;
@@ -2173,57 +2176,55 @@ bool ParserBase<Impl>::SetPropertyKindFromToken(Token::Value token,
return false;
}
-template <class Impl>
-typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePropertyName(
- IdentifierT* name, PropertyKind* kind, bool* is_generator, bool* is_get,
- bool* is_set, bool* is_async, bool* is_computed_name, bool* ok) {
- DCHECK_EQ(*kind, PropertyKind::kNotSet);
- DCHECK(!*is_generator);
- DCHECK(!*is_get);
- DCHECK(!*is_set);
- DCHECK(!*is_async);
- DCHECK(!*is_computed_name);
+inline bool ParseAsAccessor(Token::Value token, Token::Value contextual_token,
+ ParsePropertyKind* kind) {
+ if (ParsePropertyKindFromToken(token, kind)) return false;
- *is_generator = Check(Token::MUL);
- if (*is_generator) {
- *kind = PropertyKind::kMethodProperty;
+ if (contextual_token == Token::GET) {
+ *kind = ParsePropertyKind::kAccessorGetter;
+ } else if (contextual_token == Token::SET) {
+ *kind = ParsePropertyKind::kAccessorSetter;
+ } else {
+ return false;
}
- Token::Value token = peek();
- int pos = peek_position();
+ return true;
+}
- if (!*is_generator && token == Token::ASYNC &&
- !scanner()->HasLineTerminatorAfterNext()) {
- Consume(Token::ASYNC);
- token = peek();
- if (token == Token::MUL && !scanner()->HasLineTerminatorBeforeNext()) {
- Consume(Token::MUL);
- token = peek();
- *is_generator = true;
- } else if (SetPropertyKindFromToken(token, kind)) {
- *name = impl()->GetSymbol(); // TODO(bakkot) specialize on 'async'
- impl()->PushLiteralName(*name);
- return factory()->NewStringLiteral(*name, pos);
- }
- *kind = PropertyKind::kMethodProperty;
- *is_async = true;
- pos = peek_position();
- }
+template <class Impl>
+typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePropertyName(
+ IdentifierT* name, ParsePropertyKind* kind, ParseFunctionFlags* flags,
+ bool* is_computed_name, bool* ok) {
+ DCHECK_EQ(ParsePropertyKind::kNotSet, *kind);
+ DCHECK_EQ(*flags, ParseFunctionFlag::kIsNormal);
+ DCHECK(!*is_computed_name);
- if (token == Token::IDENTIFIER && !*is_generator && !*is_async) {
- // This is checking for 'get' and 'set' in particular.
- Consume(Token::IDENTIFIER);
- token = peek();
- if (SetPropertyKindFromToken(token, kind) ||
- !scanner()->IsGetOrSet(is_get, is_set)) {
+ if (Check(Token::ASYNC)) {
+ Token::Value token = peek();
+ if ((token != Token::MUL && ParsePropertyKindFromToken(token, kind)) ||
+ scanner()->HasLineTerminatorBeforeNext()) {
*name = impl()->GetSymbol();
impl()->PushLiteralName(*name);
- return factory()->NewStringLiteral(*name, pos);
+ return factory()->NewStringLiteral(*name, position());
}
- *kind = PropertyKind::kAccessorProperty;
- pos = peek_position();
+ *flags = ParseFunctionFlag::kIsAsync;
+ *kind = ParsePropertyKind::kMethod;
+ }
+
+ if (Check(Token::MUL)) {
+ *flags |= ParseFunctionFlag::kIsGenerator;
+ *kind = ParsePropertyKind::kMethod;
}
+ if (*kind == ParsePropertyKind::kNotSet && Check(Token::IDENTIFIER) &&
+ !ParseAsAccessor(peek(), scanner()->current_contextual_token(), kind)) {
+ *name = impl()->GetSymbol();
+ impl()->PushLiteralName(*name);
+ return factory()->NewStringLiteral(*name, position());
+ }
+
+ int pos = peek_position();
+
// For non computed property names we normalize the name a bit:
//
// "12" -> 12
@@ -2233,41 +2234,50 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePropertyName(
//
// This is important because we use the property name as a key in a hash
// table when we compute constant properties.
- ExpressionT expression = impl()->NullExpression();
- switch (token) {
+ bool is_array_index;
+ uint32_t index;
+ switch (peek()) {
case Token::STRING:
Consume(Token::STRING);
*name = impl()->GetSymbol();
+ is_array_index = impl()->IsArrayIndex(*name, &index);
break;
case Token::SMI:
Consume(Token::SMI);
- *name = impl()->GetNumberAsSymbol();
+ index = scanner()->smi_value();
+ is_array_index = true;
+ // Token::SMI were scanned from their canonical representation.
+ *name = impl()->GetSymbol();
break;
- case Token::NUMBER:
+ case Token::NUMBER: {
Consume(Token::NUMBER);
*name = impl()->GetNumberAsSymbol();
+ is_array_index = impl()->IsArrayIndex(*name, &index);
break;
-
+ }
case Token::LBRACK: {
*name = impl()->NullIdentifier();
*is_computed_name = true;
Consume(Token::LBRACK);
ExpressionClassifier computed_name_classifier(this);
- expression = ParseAssignmentExpression(true, CHECK_OK);
+ ExpressionT expression = ParseAssignmentExpression(true, CHECK_OK);
ValidateExpression(CHECK_OK);
AccumulateFormalParameterContainmentErrors();
Expect(Token::RBRACK, CHECK_OK);
- break;
+ if (*kind == ParsePropertyKind::kNotSet) {
+ ParsePropertyKindFromToken(peek(), kind);
+ }
+ return expression;
}
case Token::ELLIPSIS:
- if (!*is_generator && !*is_async && !*is_get && !*is_set) {
+ if (*kind == ParsePropertyKind::kNotSet) {
*name = impl()->NullIdentifier();
Consume(Token::ELLIPSIS);
- expression = ParseAssignmentExpression(true, CHECK_OK);
- *kind = PropertyKind::kSpreadProperty;
+ ExpressionT expression = ParseAssignmentExpression(true, CHECK_OK);
+ *kind = ParsePropertyKind::kSpread;
if (!impl()->IsIdentifier(expression)) {
classifier()->RecordBindingPatternError(
@@ -2291,23 +2301,16 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePropertyName(
default:
*name = ParseIdentifierName(CHECK_OK);
+ is_array_index = false;
break;
}
- if (*kind == PropertyKind::kNotSet) {
- SetPropertyKindFromToken(peek(), kind);
+ if (*kind == ParsePropertyKind::kNotSet) {
+ ParsePropertyKindFromToken(peek(), kind);
}
-
- if (*is_computed_name) {
- return expression;
- }
-
impl()->PushLiteralName(*name);
-
- uint32_t index;
- return impl()->IsArrayIndex(*name, &index)
- ? factory()->NewNumberLiteral(index, pos)
- : factory()->NewStringLiteral(*name, pos);
+ return is_array_index ? factory()->NewNumberLiteral(index, pos)
+ : factory()->NewStringLiteral(*name, pos);
}
template <typename Impl>
@@ -2317,26 +2320,24 @@ ParserBase<Impl>::ParseClassPropertyDefinition(
bool has_extends, bool* is_computed_name,
ClassLiteralProperty::Kind* property_kind, bool* is_static, bool* ok) {
DCHECK_NOT_NULL(class_info);
- bool is_get = false;
- bool is_set = false;
- bool is_generator = false;
- bool is_async = false;
+ ParseFunctionFlags function_flags = ParseFunctionFlag::kIsNormal;
*is_static = false;
*property_kind = ClassLiteralProperty::METHOD;
- PropertyKind kind = PropertyKind::kNotSet;
+ ParsePropertyKind kind = ParsePropertyKind::kNotSet;
Token::Value name_token = peek();
DCHECK_IMPLIES(name_token == Token::PRIVATE_NAME,
allow_harmony_private_fields());
- int name_token_position = scanner()->peek_location().beg_pos;
+ int property_beg_pos = scanner()->peek_location().beg_pos;
+ int name_token_position = property_beg_pos;
*name = impl()->NullIdentifier();
ExpressionT name_expression;
if (name_token == Token::STATIC) {
Consume(Token::STATIC);
name_token_position = scanner()->peek_location().beg_pos;
if (peek() == Token::LPAREN) {
- kind = PropertyKind::kMethodProperty;
+ kind = ParsePropertyKind::kMethod;
*name = impl()->GetSymbol(); // TODO(bakkot) specialize on 'static'
name_expression = factory()->NewStringLiteral(*name, position());
} else if (peek() == Token::ASSIGN || peek() == Token::SEMICOLON ||
@@ -2351,18 +2352,18 @@ ParserBase<Impl>::ParseClassPropertyDefinition(
return impl()->NullLiteralProperty();
} else {
*is_static = true;
- name_expression = ParsePropertyName(name, &kind, &is_generator, &is_get,
- &is_set, &is_async, is_computed_name,
- CHECK_OK_CUSTOM(NullLiteralProperty));
+ name_expression =
+ ParsePropertyName(name, &kind, &function_flags, is_computed_name,
+ CHECK_OK_CUSTOM(NullLiteralProperty));
}
} else if (name_token == Token::PRIVATE_NAME) {
Consume(Token::PRIVATE_NAME);
*name = impl()->GetSymbol();
name_expression = factory()->NewStringLiteral(*name, position());
} else {
- name_expression = ParsePropertyName(name, &kind, &is_generator, &is_get,
- &is_set, &is_async, is_computed_name,
- CHECK_OK_CUSTOM(NullLiteralProperty));
+ name_expression =
+ ParsePropertyName(name, &kind, &function_flags, is_computed_name,
+ CHECK_OK_CUSTOM(NullLiteralProperty));
}
if (!class_info->has_name_static_property && *is_static &&
@@ -2371,16 +2372,17 @@ ParserBase<Impl>::ParseClassPropertyDefinition(
}
switch (kind) {
- case PropertyKind::kClassField:
- case PropertyKind::kNotSet: // This case is a name followed by a name or
- // other property. Here we have to assume
- // that's an uninitialized field followed by a
- // linebreak followed by a property, with ASI
- // adding the semicolon. If not, there will be
- // a syntax error after parsing the first name
- // as an uninitialized field.
- case PropertyKind::kShorthandProperty:
- case PropertyKind::kValueProperty:
+ case ParsePropertyKind::kClassField:
+ case ParsePropertyKind::kNotSet: // This case is a name followed by a name
+ // or other property. Here we have to
+ // assume that's an uninitialized field
+ // followed by a linebreak followed by a
+ // property, with ASI adding the
+ // semicolon. If not, there will be a
+ // syntax error after parsing the first
+ // name as an uninitialized field.
+ case ParsePropertyKind::kShorthand:
+ case ParsePropertyKind::kValue:
if (allow_harmony_public_fields() || allow_harmony_private_fields()) {
*property_kind = name_token == Token::PRIVATE_NAME
? ClassLiteralProperty::PRIVATE_FIELD
@@ -2394,8 +2396,9 @@ ParserBase<Impl>::ParseClassPropertyDefinition(
checker->CheckClassFieldName(*is_static,
CHECK_OK_CUSTOM(NullLiteralProperty));
}
- ExpressionT initializer = ParseClassFieldInitializer(
- class_info, *is_static, CHECK_OK_CUSTOM(NullLiteralProperty));
+ ExpressionT initializer =
+ ParseClassFieldInitializer(class_info, property_beg_pos, *is_static,
+ CHECK_OK_CUSTOM(NullLiteralProperty));
ExpectSemicolon(CHECK_OK_CUSTOM(NullLiteralProperty));
ClassLiteralPropertyT result = factory()->NewClassLiteralProperty(
name_expression, initializer, *property_kind, *is_static,
@@ -2409,9 +2412,7 @@ ParserBase<Impl>::ParseClassPropertyDefinition(
return impl()->NullLiteralProperty();
}
- case PropertyKind::kMethodProperty: {
- DCHECK(!is_get && !is_set);
-
+ case ParsePropertyKind::kMethod: {
// MethodDefinition
// PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}'
// '*' PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}'
@@ -2421,12 +2422,12 @@ ParserBase<Impl>::ParseClassPropertyDefinition(
// '{' FunctionBody '}'
if (!*is_computed_name) {
- checker->CheckClassMethodName(name_token, PropertyKind::kMethodProperty,
- is_generator, is_async, *is_static,
+ checker->CheckClassMethodName(name_token, ParsePropertyKind::kMethod,
+ function_flags, *is_static,
CHECK_OK_CUSTOM(NullLiteralProperty));
}
- FunctionKind kind = MethodKindFor(is_generator, is_async);
+ FunctionKind kind = MethodKindFor(function_flags);
if (!*is_static && impl()->IsConstructor(*name)) {
class_info->has_seen_constructor = true;
@@ -2436,10 +2437,8 @@ ParserBase<Impl>::ParseClassPropertyDefinition(
ExpressionT value = impl()->ParseFunctionLiteral(
*name, scanner()->location(), kSkipFunctionNameCheck, kind,
- FLAG_harmony_function_tostring ? name_token_position
- : kNoSourcePosition,
- FunctionLiteral::kAccessorOrMethod, language_mode(), nullptr,
- CHECK_OK_CUSTOM(NullLiteralProperty));
+ name_token_position, FunctionLiteral::kAccessorOrMethod,
+ language_mode(), nullptr, CHECK_OK_CUSTOM(NullLiteralProperty));
*property_kind = ClassLiteralProperty::METHOD;
ClassLiteralPropertyT result = factory()->NewClassLiteralProperty(
@@ -2449,13 +2448,15 @@ ParserBase<Impl>::ParseClassPropertyDefinition(
return result;
}
- case PropertyKind::kAccessorProperty: {
- DCHECK((is_get || is_set) && !is_generator && !is_async);
+ case ParsePropertyKind::kAccessorGetter:
+ case ParsePropertyKind::kAccessorSetter: {
+ DCHECK_EQ(function_flags, ParseFunctionFlag::kIsNormal);
+ bool is_get = kind == ParsePropertyKind::kAccessorGetter;
if (!*is_computed_name) {
- checker->CheckClassMethodName(
- name_token, PropertyKind::kAccessorProperty, false, false,
- *is_static, CHECK_OK_CUSTOM(NullLiteralProperty));
+ checker->CheckClassMethodName(name_token, kind,
+ ParseFunctionFlag::kIsNormal, *is_static,
+ CHECK_OK_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.
@@ -2468,10 +2469,8 @@ ParserBase<Impl>::ParseClassPropertyDefinition(
FunctionLiteralT value = impl()->ParseFunctionLiteral(
*name, scanner()->location(), kSkipFunctionNameCheck, kind,
- FLAG_harmony_function_tostring ? name_token_position
- : kNoSourcePosition,
- FunctionLiteral::kAccessorOrMethod, language_mode(), nullptr,
- CHECK_OK_CUSTOM(NullLiteralProperty));
+ name_token_position, FunctionLiteral::kAccessorOrMethod,
+ language_mode(), nullptr, CHECK_OK_CUSTOM(NullLiteralProperty));
*property_kind =
is_get ? ClassLiteralProperty::GETTER : ClassLiteralProperty::SETTER;
@@ -2484,7 +2483,7 @@ ParserBase<Impl>::ParseClassPropertyDefinition(
impl()->SetFunctionNameFromPropertyName(result, *name, prefix);
return result;
}
- case PropertyKind::kSpreadProperty:
+ case ParsePropertyKind::kSpread:
ReportUnexpectedTokenAt(
Scanner::Location(name_token_position, name_expression->position()),
name_token);
@@ -2496,7 +2495,7 @@ ParserBase<Impl>::ParseClassPropertyDefinition(
template <typename Impl>
typename ParserBase<Impl>::ExpressionT
-ParserBase<Impl>::ParseClassFieldInitializer(ClassInfo* class_info,
+ParserBase<Impl>::ParseClassFieldInitializer(ClassInfo* class_info, int beg_pos,
bool is_static, bool* ok) {
DeclarationScope* initializer_scope = is_static
? class_info->static_fields_scope
@@ -2506,7 +2505,7 @@ ParserBase<Impl>::ParseClassFieldInitializer(ClassInfo* class_info,
initializer_scope =
NewFunctionScope(FunctionKind::kClassFieldsInitializerFunction);
// TODO(gsathya): Make scopes be non contiguous.
- initializer_scope->set_start_position(scanner()->location().end_pos);
+ initializer_scope->set_start_position(beg_pos);
initializer_scope->SetLanguageMode(LanguageMode::kStrict);
}
@@ -2523,7 +2522,7 @@ ParserBase<Impl>::ParseClassFieldInitializer(ClassInfo* class_info,
initializer = factory()->NewUndefinedLiteral(kNoSourcePosition);
}
- initializer_scope->set_end_position(scanner()->location().end_pos);
+ initializer_scope->set_end_position(end_position());
if (is_static) {
class_info->static_fields_scope = initializer_scope;
class_info->has_static_class_fields = true;
@@ -2541,26 +2540,23 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ObjectLiteralChecker* checker,
bool* is_computed_name,
bool* is_rest_property,
bool* ok) {
- bool is_get = false;
- bool is_set = false;
- bool is_generator = false;
- bool is_async = false;
- PropertyKind kind = PropertyKind::kNotSet;
+ ParseFunctionFlags function_flags = ParseFunctionFlag::kIsNormal;
+ ParsePropertyKind kind = ParsePropertyKind::kNotSet;
IdentifierT name = impl()->NullIdentifier();
Token::Value name_token = peek();
- int next_beg_pos = scanner()->peek_location().beg_pos;
- int next_end_pos = scanner()->peek_location().end_pos;
+ int next_beg_pos = peek_position();
+ int next_end_pos = peek_end_position();
- ExpressionT name_expression = ParsePropertyName(
- &name, &kind, &is_generator, &is_get, &is_set, &is_async,
- is_computed_name, CHECK_OK_CUSTOM(NullLiteralProperty));
+ ExpressionT name_expression =
+ ParsePropertyName(&name, &kind, &function_flags, is_computed_name,
+ CHECK_OK_CUSTOM(NullLiteralProperty));
switch (kind) {
- case PropertyKind::kSpreadProperty:
- DCHECK(!is_get && !is_set && !is_generator && !is_async &&
- !*is_computed_name);
- DCHECK(name_token == Token::ELLIPSIS);
+ case ParsePropertyKind::kSpread:
+ DCHECK_EQ(function_flags, ParseFunctionFlag::kIsNormal);
+ DCHECK(!*is_computed_name);
+ DCHECK_EQ(Token::ELLIPSIS, name_token);
*is_computed_name = true;
*is_rest_property = true;
@@ -2569,8 +2565,8 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ObjectLiteralChecker* checker,
factory()->NewTheHoleLiteral(), name_expression,
ObjectLiteralProperty::SPREAD, true);
- case PropertyKind::kValueProperty: {
- DCHECK(!is_get && !is_set && !is_generator && !is_async);
+ case ParsePropertyKind::kValue: {
+ DCHECK_EQ(function_flags, ParseFunctionFlag::kIsNormal);
if (!*is_computed_name) {
checker->CheckDuplicateProto(name_token);
@@ -2579,7 +2575,7 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ObjectLiteralChecker* checker,
int beg_pos = peek_position();
ExpressionT value =
ParseAssignmentExpression(true, CHECK_OK_CUSTOM(NullLiteralProperty));
- CheckDestructuringElement(value, beg_pos, scanner()->location().end_pos);
+ CheckDestructuringElement(value, beg_pos, end_position());
ObjectLiteralPropertyT result = factory()->NewObjectLiteralProperty(
name_expression, value, *is_computed_name);
@@ -2587,14 +2583,14 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ObjectLiteralChecker* checker,
return result;
}
- case PropertyKind::kShorthandProperty: {
+ case ParsePropertyKind::kShorthand: {
// PropertyDefinition
// IdentifierReference
// CoverInitializedName
//
// CoverInitializedName
// IdentifierReference Initializer?
- DCHECK(!is_get && !is_set && !is_generator && !is_async);
+ DCHECK_EQ(function_flags, ParseFunctionFlag::kIsNormal);
if (!Token::IsIdentifier(name_token, language_mode(),
this->is_generator(),
@@ -2642,7 +2638,7 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ObjectLiteralChecker* checker,
value = factory()->NewAssignment(Token::ASSIGN, lhs, rhs,
kNoSourcePosition);
classifier()->RecordExpressionError(
- Scanner::Location(next_beg_pos, scanner()->location().end_pos),
+ Scanner::Location(next_beg_pos, end_position()),
MessageTemplate::kInvalidCoverInitializedName);
impl()->SetFunctionNameFromIdentifierRef(rhs, lhs);
@@ -2656,24 +2652,21 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ObjectLiteralChecker* checker,
return result;
}
- case PropertyKind::kMethodProperty: {
- DCHECK(!is_get && !is_set);
-
+ case ParsePropertyKind::kMethod: {
// MethodDefinition
// PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}'
// '*' PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}'
classifier()->RecordPatternError(
- Scanner::Location(next_beg_pos, scanner()->location().end_pos),
+ Scanner::Location(next_beg_pos, end_position()),
MessageTemplate::kInvalidDestructuringTarget);
- FunctionKind kind = MethodKindFor(is_generator, is_async);
+ FunctionKind kind = MethodKindFor(function_flags);
ExpressionT value = impl()->ParseFunctionLiteral(
name, scanner()->location(), kSkipFunctionNameCheck, kind,
- FLAG_harmony_function_tostring ? next_beg_pos : kNoSourcePosition,
- FunctionLiteral::kAccessorOrMethod, language_mode(), nullptr,
- CHECK_OK_CUSTOM(NullLiteralProperty));
+ next_beg_pos, FunctionLiteral::kAccessorOrMethod, language_mode(),
+ nullptr, CHECK_OK_CUSTOM(NullLiteralProperty));
ObjectLiteralPropertyT result = factory()->NewObjectLiteralProperty(
name_expression, value, ObjectLiteralProperty::COMPUTED,
@@ -2682,12 +2675,13 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ObjectLiteralChecker* checker,
return result;
}
- case PropertyKind::kAccessorProperty: {
- DCHECK((is_get || is_set) && !(is_set && is_get) && !is_generator &&
- !is_async);
+ case ParsePropertyKind::kAccessorGetter:
+ case ParsePropertyKind::kAccessorSetter: {
+ DCHECK_EQ(function_flags, ParseFunctionFlag::kIsNormal);
+ bool is_get = kind == ParsePropertyKind::kAccessorGetter;
classifier()->RecordPatternError(
- Scanner::Location(next_beg_pos, scanner()->location().end_pos),
+ Scanner::Location(next_beg_pos, end_position()),
MessageTemplate::kInvalidDestructuringTarget);
if (!*is_computed_name) {
@@ -2703,9 +2697,8 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ObjectLiteralChecker* checker,
FunctionLiteralT value = impl()->ParseFunctionLiteral(
name, scanner()->location(), kSkipFunctionNameCheck, kind,
- FLAG_harmony_function_tostring ? next_beg_pos : kNoSourcePosition,
- FunctionLiteral::kAccessorOrMethod, language_mode(), nullptr,
- CHECK_OK_CUSTOM(NullLiteralProperty));
+ next_beg_pos, FunctionLiteral::kAccessorOrMethod, language_mode(),
+ nullptr, CHECK_OK_CUSTOM(NullLiteralProperty));
ObjectLiteralPropertyT result = factory()->NewObjectLiteralProperty(
name_expression, value,
@@ -2719,8 +2712,8 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ObjectLiteralChecker* checker,
return result;
}
- case PropertyKind::kClassField:
- case PropertyKind::kNotSet:
+ case ParsePropertyKind::kClassField:
+ case ParsePropertyKind::kNotSet:
ReportUnexpectedToken(Next());
*ok = false;
return impl()->NullLiteralProperty();
@@ -2743,10 +2736,10 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseObjectLiteral(
bool has_rest_property = false;
ObjectLiteralChecker checker(this);
- Expect(Token::LBRACE, CHECK_OK);
+ Consume(Token::LBRACE);
- while (peek() != Token::RBRACE) {
- FuncNameInferrer::State fni_state(fni_);
+ while (!Check(Token::RBRACE)) {
+ FuncNameInferrerState fni_state(&fni_);
bool is_computed_name = false;
bool is_rest_property = false;
@@ -2774,9 +2767,8 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseObjectLiteral(
Expect(Token::COMMA, CHECK_OK);
}
- if (fni_ != nullptr) fni_->Infer();
+ fni_.Infer();
}
- Expect(Token::RBRACE, CHECK_OK);
// In pattern rewriter, we rewrite rest property to call out to a
// runtime function passing all the other properties as arguments to
@@ -2802,25 +2794,20 @@ typename ParserBase<Impl>::ExpressionListT ParserBase<Impl>::ParseArguments(
Scanner::Location spread_arg = Scanner::Location::invalid();
ExpressionListT result = impl()->NewExpressionList(4);
Expect(Token::LPAREN, CHECK_OK_CUSTOM(NullExpressionList));
- bool done = (peek() == Token::RPAREN);
- while (!done) {
+ while (peek() != Token::RPAREN) {
int start_pos = peek_position();
bool is_spread = Check(Token::ELLIPSIS);
int expr_pos = peek_position();
ExpressionT argument =
ParseAssignmentExpression(true, CHECK_OK_CUSTOM(NullExpressionList));
- if (!impl()->IsIdentifier(argument) &&
- is_simple_parameter_list != nullptr) {
- *is_simple_parameter_list = false;
- }
+ if (!impl()->IsIdentifier(argument)) *is_simple_parameter_list = false;
+
if (!maybe_arrow) {
ValidateExpression(CHECK_OK_CUSTOM(NullExpressionList));
}
if (is_spread) {
- if (is_simple_parameter_list != nullptr) {
- *is_simple_parameter_list = false;
- }
+ *is_simple_parameter_list = false;
if (!spread_arg.IsValid()) {
spread_arg.beg_pos = start_pos;
spread_arg.end_pos = peek_position();
@@ -2833,24 +2820,22 @@ typename ParserBase<Impl>::ExpressionListT ParserBase<Impl>::ParseArguments(
}
result->Add(argument, zone_);
- if (result->length() > Code::kMaxArguments) {
- ReportMessage(MessageTemplate::kTooManyArguments);
- *ok = false;
- return impl()->NullExpressionList();
- }
- done = (peek() != Token::COMMA);
- if (!done) {
- Next();
- if (argument->IsSpread()) {
- classifier()->RecordAsyncArrowFormalParametersError(
- scanner()->location(), MessageTemplate::kParamAfterRest);
- }
- if (peek() == Token::RPAREN) {
- // allow trailing comma
- done = true;
- }
+ if (peek() != Token::COMMA) break;
+
+ Next();
+
+ if (argument->IsSpread()) {
+ classifier()->RecordAsyncArrowFormalParametersError(
+ scanner()->location(), MessageTemplate::kParamAfterRest);
}
}
+
+ if (result->length() > Code::kMaxArguments) {
+ ReportMessage(MessageTemplate::kTooManyArguments);
+ *ok = false;
+ return impl()->NullExpressionList();
+ }
+
Scanner::Location location = scanner_->location();
if (Token::RPAREN != Next()) {
impl()->ReportMessageAt(location, MessageTemplate::kUnterminatedArgList);
@@ -2883,7 +2868,7 @@ ParserBase<Impl>::ParseAssignmentExpression(bool accept_IN, bool* ok) {
return ParseYieldExpression(accept_IN, ok);
}
- FuncNameInferrer::State fni_state(fni_);
+ FuncNameInferrerState fni_state(&fni_);
ExpressionClassifier arrow_formals_classifier(
this, classifier()->duplicate_finder());
@@ -2915,10 +2900,8 @@ ParserBase<Impl>::ParseAssignmentExpression(bool accept_IN, bool* ok) {
IdentifierT name = ParseAndClassifyIdentifier(CHECK_OK);
expression =
impl()->ExpressionFromIdentifier(name, position(), InferName::kNo);
- if (fni_) {
- // Remove `async` keyword from inferred name stack.
- fni_->RemoveAsyncKeywordFromEnd();
- }
+ // Remove `async` keyword from inferred name stack.
+ fni_.RemoveAsyncKeywordFromEnd();
}
if (peek() == Token::ARROW) {
@@ -2931,9 +2914,9 @@ ParserBase<Impl>::ParseAssignmentExpression(bool accept_IN, bool* ok) {
// in an arrow parameter list, this is correct.
// TODO(adamk): Rename "FormalParameterInitializerError" to refer to
// "YieldExpression", which is its only use.
- ValidateFormalParameterInitializer(ok);
+ ValidateFormalParameterInitializer(CHECK_OK);
- Scanner::Location loc(lhs_beg_pos, scanner()->location().end_pos);
+ Scanner::Location loc(lhs_beg_pos, end_position());
DeclarationScope* scope =
NewFunctionScope(is_async ? FunctionKind::kAsyncArrowFunction
: FunctionKind::kArrowFunction);
@@ -2962,7 +2945,7 @@ ParserBase<Impl>::ParseAssignmentExpression(bool accept_IN, bool* ok) {
MessageTemplate::kUnexpectedToken,
Token::String(Token::ARROW));
- if (fni_ != nullptr) fni_->Infer();
+ fni_.Infer();
return expression;
}
@@ -2997,7 +2980,7 @@ ParserBase<Impl>::ParseAssignmentExpression(bool accept_IN, bool* ok) {
ValidateAssignmentPattern(CHECK_OK);
} else {
expression = CheckAndRewriteReferenceExpression(
- expression, lhs_beg_pos, scanner()->location().end_pos,
+ expression, lhs_beg_pos, end_position(),
MessageTemplate::kInvalidLhsInAssignment, CHECK_OK);
}
@@ -3027,15 +3010,13 @@ ParserBase<Impl>::ParseAssignmentExpression(bool accept_IN, bool* ok) {
impl()->CheckAssigningFunctionLiteralToProperty(expression, right);
- if (fni_ != nullptr) {
- // Check if the right hand side is a call to avoid inferring a
- // name if we're dealing with "a = function(){...}();"-like
- // expression.
- if (op == Token::ASSIGN && !right->IsCall() && !right->IsCallNew()) {
- fni_->Infer();
- } else {
- fni_->RemoveLastFunction();
- }
+ // Check if the right hand side is a call to avoid inferring a
+ // name if we're dealing with "a = function(){...}();"-like
+ // expression.
+ if (op == Token::ASSIGN && !right->IsCall() && !right->IsCallNew()) {
+ fni_.Infer();
+ } else {
+ fni_.RemoveLastFunction();
}
if (op == Token::ASSIGN) {
@@ -3124,11 +3105,20 @@ ParserBase<Impl>::ParseConditionalExpression(bool accept_IN,
// LogicalOrExpression
// LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
- SourceRange then_range, else_range;
int pos = peek_position();
// We start using the binary expression parser for prec >= 4 only!
ExpressionT expression = ParseBinaryExpression(4, accept_IN, CHECK_OK);
- if (peek() != Token::CONDITIONAL) return expression;
+ return peek() == Token::CONDITIONAL
+ ? ParseConditionalContinuation(expression, accept_IN, pos, ok)
+ : expression;
+}
+
+template <typename Impl>
+typename ParserBase<Impl>::ExpressionT
+ParserBase<Impl>::ParseConditionalContinuation(ExpressionT expression,
+ bool accept_IN, int pos,
+ bool* ok) {
+ SourceRange then_range, else_range;
ValidateExpression(CHECK_OK);
BindingPatternUnexpectedToken();
ArrowFormalParametersUnexpectedToken();
@@ -3184,10 +3174,6 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseBinaryExpression(
right_range_scope.Finalize();
ValidateExpression(CHECK_OK);
- if (impl()->ShortcutNumericLiteralBinaryExpression(&x, y, op, pos)) {
- continue;
- }
-
// For now we distinguish between comparisons and other binary
// operations. (We could combine the two and get rid of this
// code and AST node eventually.)
@@ -3204,9 +3190,9 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseBinaryExpression(
// The comparison was negated - add a NOT.
x = factory()->NewUnaryOperation(Token::NOT, x, pos);
}
- } else if (impl()->CollapseNaryExpression(&x, y, op, pos, right_range)) {
- continue;
- } else {
+ } else if (!impl()->ShortcutNumericLiteralBinaryExpression(&x, y, op,
+ pos) &&
+ !impl()->CollapseNaryExpression(&x, y, op, pos, right_range)) {
// We have a "normal" binary operation.
x = factory()->NewBinaryOperation(op, x, y, pos);
if (op == Token::OR || op == Token::AND) {
@@ -3219,97 +3205,109 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseBinaryExpression(
}
template <typename Impl>
-typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseUnaryExpression(
+typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseUnaryOpExpression(
bool* ok) {
- // UnaryExpression ::
- // PostfixExpression
- // 'delete' UnaryExpression
- // 'void' UnaryExpression
- // 'typeof' UnaryExpression
- // '++' UnaryExpression
- // '--' UnaryExpression
- // '+' UnaryExpression
- // '-' UnaryExpression
- // '~' UnaryExpression
- // '!' UnaryExpression
- // [+Await] AwaitExpression[?Yield]
-
- Token::Value op = peek();
- if (Token::IsUnaryOp(op)) {
- BindingPatternUnexpectedToken();
- ArrowFormalParametersUnexpectedToken();
-
- op = Next();
- int pos = position();
+ BindingPatternUnexpectedToken();
+ ArrowFormalParametersUnexpectedToken();
- // Assume "! function ..." indicates the function is likely to be called.
- if (op == Token::NOT && peek() == Token::FUNCTION) {
- function_state_->set_next_function_is_likely_called();
- }
+ Token::Value op = Next();
+ int pos = position();
- ExpressionT expression = ParseUnaryExpression(CHECK_OK);
- ValidateExpression(CHECK_OK);
+ // Assume "! function ..." indicates the function is likely to be called.
+ if (op == Token::NOT && peek() == Token::FUNCTION) {
+ function_state_->set_next_function_is_likely_called();
+ }
- if (op == Token::DELETE) {
- if (impl()->IsIdentifier(expression) && is_strict(language_mode())) {
- // "delete identifier" is a syntax error in strict mode.
- ReportMessage(MessageTemplate::kStrictDelete);
- *ok = false;
- return impl()->NullExpression();
- }
+ ExpressionT expression = ParseUnaryExpression(CHECK_OK);
+ ValidateExpression(CHECK_OK);
- if (impl()->IsPropertyWithPrivateFieldKey(expression)) {
- ReportMessage(MessageTemplate::kDeletePrivateField);
- *ok = false;
- return impl()->NullExpression();
- }
+ if (op == Token::DELETE) {
+ if (impl()->IsIdentifier(expression) && is_strict(language_mode())) {
+ // "delete identifier" is a syntax error in strict mode.
+ ReportMessage(MessageTemplate::kStrictDelete);
+ *ok = false;
+ return impl()->NullExpression();
}
- if (peek() == Token::EXP) {
- ReportUnexpectedToken(Next());
+ if (impl()->IsPropertyWithPrivateFieldKey(expression)) {
+ ReportMessage(MessageTemplate::kDeletePrivateField);
*ok = false;
return impl()->NullExpression();
}
+ }
- // Allow the parser's implementation to rewrite the expression.
- return impl()->BuildUnaryExpression(expression, op, pos);
- } else if (Token::IsCountOp(op)) {
- BindingPatternUnexpectedToken();
- ArrowFormalParametersUnexpectedToken();
- op = Next();
- int beg_pos = peek_position();
- ExpressionT expression = ParseUnaryExpression(CHECK_OK);
- expression = CheckAndRewriteReferenceExpression(
- expression, beg_pos, scanner()->location().end_pos,
- MessageTemplate::kInvalidLhsInPrefixOp, CHECK_OK);
- impl()->MarkExpressionAsAssigned(expression);
- ValidateExpression(CHECK_OK);
+ if (peek() == Token::EXP) {
+ ReportUnexpectedToken(Next());
+ *ok = false;
+ return impl()->NullExpression();
+ }
- return factory()->NewCountOperation(op,
- true /* prefix */,
- expression,
- position());
+ // Allow the parser's implementation to rewrite the expression.
+ return impl()->BuildUnaryExpression(expression, op, pos);
+}
- } else if (is_async_function() && peek() == Token::AWAIT) {
- classifier()->RecordFormalParameterInitializerError(
- scanner()->peek_location(),
- MessageTemplate::kAwaitExpressionFormalParameter);
- int await_pos = peek_position();
- Consume(Token::AWAIT);
+template <typename Impl>
+typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePrefixExpression(
+ bool* ok) {
+ BindingPatternUnexpectedToken();
+ ArrowFormalParametersUnexpectedToken();
+ Token::Value op = Next();
+ int beg_pos = peek_position();
+ ExpressionT expression = ParseUnaryExpression(CHECK_OK);
+ expression = CheckAndRewriteReferenceExpression(
+ expression, beg_pos, end_position(),
+ MessageTemplate::kInvalidLhsInPrefixOp, CHECK_OK);
+ impl()->MarkExpressionAsAssigned(expression);
+ ValidateExpression(CHECK_OK);
- ExpressionT value = ParseUnaryExpression(CHECK_OK);
+ return factory()->NewCountOperation(op, true /* prefix */, expression,
+ position());
+}
- classifier()->RecordBindingPatternError(
- Scanner::Location(await_pos, scanner()->location().end_pos),
- MessageTemplate::kInvalidDestructuringTarget);
+template <typename Impl>
+typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseAwaitExpression(
+ bool* ok) {
+ classifier()->RecordFormalParameterInitializerError(
+ scanner()->peek_location(),
+ MessageTemplate::kAwaitExpressionFormalParameter);
+ int await_pos = peek_position();
+ Consume(Token::AWAIT);
- ExpressionT expr = factory()->NewAwait(value, await_pos);
- function_state_->AddSuspend();
- impl()->RecordSuspendSourceRange(expr, PositionAfterSemicolon());
- return expr;
- } else {
- return ParsePostfixExpression(ok);
+ ExpressionT value = ParseUnaryExpression(CHECK_OK);
+
+ classifier()->RecordBindingPatternError(
+ Scanner::Location(await_pos, end_position()),
+ MessageTemplate::kInvalidDestructuringTarget);
+
+ ExpressionT expr = factory()->NewAwait(value, await_pos);
+ function_state_->AddSuspend();
+ impl()->RecordSuspendSourceRange(expr, PositionAfterSemicolon());
+ return expr;
+}
+
+template <typename Impl>
+typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseUnaryExpression(
+ bool* ok) {
+ // UnaryExpression ::
+ // PostfixExpression
+ // 'delete' UnaryExpression
+ // 'void' UnaryExpression
+ // 'typeof' UnaryExpression
+ // '++' UnaryExpression
+ // '--' UnaryExpression
+ // '+' UnaryExpression
+ // '-' UnaryExpression
+ // '~' UnaryExpression
+ // '!' UnaryExpression
+ // [+Await] AwaitExpression[?Yield]
+
+ Token::Value op = peek();
+ if (Token::IsUnaryOp(op)) return ParseUnaryOpExpression(ok);
+ if (Token::IsCountOp(op)) return ParsePrefixExpression(ok);
+ if (is_async_function() && op == Token::AWAIT) {
+ return ParseAwaitExpression(ok);
}
+ return ParsePostfixExpression(ok);
}
template <typename Impl>
@@ -3325,7 +3323,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePostfixExpression(
ArrowFormalParametersUnexpectedToken();
expression = CheckAndRewriteReferenceExpression(
- expression, lhs_beg_pos, scanner()->location().end_pos,
+ expression, lhs_beg_pos, end_position(),
MessageTemplate::kInvalidLhsInPostfixOp, CHECK_OK);
impl()->MarkExpressionAsAssigned(expression);
ValidateExpression(CHECK_OK);
@@ -3398,9 +3396,7 @@ ParserBase<Impl>::ParseLeftHandSideExpression(bool* ok) {
args = ParseArguments(&spread_pos, true, &is_simple_parameter_list,
CHECK_OK);
if (peek() == Token::ARROW) {
- if (fni_) {
- fni_->RemoveAsyncKeywordFromEnd();
- }
+ fni_.RemoveAsyncKeywordFromEnd();
ValidateBindingPattern(CHECK_OK);
ValidateFormalParameterInitializer(CHECK_OK);
if (!classifier()->is_valid_async_arrow_formal_parameters()) {
@@ -3443,7 +3439,7 @@ ParserBase<Impl>::ParseLeftHandSideExpression(bool* ok) {
result = factory()->NewCall(result, args, pos, is_possibly_eval);
}
- if (fni_ != nullptr) fni_->RemoveLastFunction();
+ fni_.RemoveLastFunction();
break;
}
@@ -3475,8 +3471,8 @@ ParserBase<Impl>::ParseLeftHandSideExpression(bool* ok) {
template <typename Impl>
typename ParserBase<Impl>::ExpressionT
-ParserBase<Impl>::ParseMemberWithNewPrefixesExpression(bool* is_async,
- bool* ok) {
+ParserBase<Impl>::ParseMemberWithPresentNewPrefixesExpression(bool* is_async,
+ bool* ok) {
// NewExpression ::
// ('new')+ MemberExpression
//
@@ -3496,49 +3492,52 @@ ParserBase<Impl>::ParseMemberWithNewPrefixesExpression(bool* is_async,
// new new foo means new (new foo)
// new new foo() means new (new foo())
// new new foo().bar().baz means (new (new foo()).bar()).baz
+ BindingPatternUnexpectedToken();
+ ArrowFormalParametersUnexpectedToken();
+ Consume(Token::NEW);
+ int new_pos = position();
+ ExpressionT result;
+ if (peek() == Token::SUPER) {
+ const bool is_new = true;
+ result = ParseSuperExpression(is_new, CHECK_OK);
+ } else if (allow_harmony_dynamic_import() && peek() == Token::IMPORT &&
+ (!allow_harmony_import_meta() || PeekAhead() == Token::LPAREN)) {
+ impl()->ReportMessageAt(scanner()->peek_location(),
+ MessageTemplate::kImportCallNotNewExpression);
+ *ok = false;
+ return impl()->NullExpression();
+ } else if (peek() == Token::PERIOD) {
+ *is_async = false;
+ result = ParseNewTargetExpression(CHECK_OK);
+ return ParseMemberExpressionContinuation(result, is_async, ok);
+ } else {
+ result = ParseMemberWithNewPrefixesExpression(is_async, CHECK_OK);
+ }
+ ValidateExpression(CHECK_OK);
+ if (peek() == Token::LPAREN) {
+ // NewExpression with arguments.
+ Scanner::Location spread_pos;
+ ExpressionListT args = ParseArguments(&spread_pos, CHECK_OK);
- if (peek() == Token::NEW) {
- BindingPatternUnexpectedToken();
- ArrowFormalParametersUnexpectedToken();
- Consume(Token::NEW);
- int new_pos = position();
- ExpressionT result;
- if (peek() == Token::SUPER) {
- const bool is_new = true;
- result = ParseSuperExpression(is_new, CHECK_OK);
- } else if (allow_harmony_dynamic_import() && peek() == Token::IMPORT &&
- (!allow_harmony_import_meta() || PeekAhead() == Token::LPAREN)) {
- impl()->ReportMessageAt(scanner()->peek_location(),
- MessageTemplate::kImportCallNotNewExpression);
- *ok = false;
- return impl()->NullExpression();
- } else if (peek() == Token::PERIOD) {
- *is_async = false;
- result = ParseNewTargetExpression(CHECK_OK);
- return ParseMemberExpressionContinuation(result, is_async, CHECK_OK);
+ if (spread_pos.IsValid()) {
+ result = impl()->SpreadCallNew(result, args, new_pos);
} else {
- result = ParseMemberWithNewPrefixesExpression(is_async, CHECK_OK);
+ result = factory()->NewCallNew(result, args, new_pos);
}
- ValidateExpression(CHECK_OK);
- if (peek() == Token::LPAREN) {
- // NewExpression with arguments.
- Scanner::Location spread_pos;
- ExpressionListT args = ParseArguments(&spread_pos, CHECK_OK);
-
- if (spread_pos.IsValid()) {
- result = impl()->SpreadCallNew(result, args, new_pos);
- } else {
- result = factory()->NewCallNew(result, args, new_pos);
- }
- // The expression can still continue with . or [ after the arguments.
- result = ParseMemberExpressionContinuation(result, is_async, CHECK_OK);
- return result;
- }
- // NewExpression without arguments.
- return factory()->NewCallNew(result, impl()->NewExpressionList(0), new_pos);
+ // The expression can still continue with . or [ after the arguments.
+ return ParseMemberExpressionContinuation(result, is_async, ok);
}
- // No 'new' or 'super' keyword.
- return ParseMemberExpression(is_async, ok);
+ // NewExpression without arguments.
+ return factory()->NewCallNew(result, impl()->NewExpressionList(0), new_pos);
+}
+
+template <typename Impl>
+typename ParserBase<Impl>::ExpressionT
+ParserBase<Impl>::ParseMemberWithNewPrefixesExpression(bool* is_async,
+ bool* ok) {
+ return peek() == Token::NEW
+ ? ParseMemberWithPresentNewPrefixesExpression(is_async, ok)
+ : ParseMemberExpression(is_async, ok);
}
template <typename Impl>
@@ -3604,8 +3603,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseMemberExpression(
result = ParsePrimaryExpression(is_async, CHECK_OK);
}
- result = ParseMemberExpressionContinuation(result, is_async, CHECK_OK);
- return result;
+ return ParseMemberExpressionContinuation(result, is_async, ok);
}
template <typename Impl>
@@ -3678,9 +3676,9 @@ void ParserBase<Impl>::ExpectMetaProperty(Token::Value property_name,
Consume(Token::PERIOD);
ExpectContextualKeyword(property_name, CHECK_OK_CUSTOM(Void));
if (scanner()->literal_contains_escapes()) {
- impl()->ReportMessageAt(
- Scanner::Location(pos, scanner()->location().end_pos),
- MessageTemplate::kInvalidEscapedMetaProperty, full_name);
+ impl()->ReportMessageAt(Scanner::Location(pos, end_position()),
+ MessageTemplate::kInvalidEscapedMetaProperty,
+ full_name);
*ok = false;
}
}
@@ -3692,7 +3690,7 @@ ParserBase<Impl>::ParseNewTargetExpression(bool* ok) {
ExpectMetaProperty(Token::TARGET, "new.target", pos, CHECK_OK);
classifier()->RecordAssignmentPatternError(
- Scanner::Location(pos, scanner()->location().end_pos),
+ Scanner::Location(pos, end_position()),
MessageTemplate::kInvalidDestructuringTarget);
if (!GetReceiverScope()->is_function_scope()) {
@@ -3780,14 +3778,11 @@ void ParserBase<Impl>::ParseFormalParameter(FormalParametersT* parameters,
// BindingElement[?Yield, ?GeneratorParameter]
bool is_rest = parameters->has_rest;
- FuncNameInferrer::State fni_state(fni_);
- ExpressionT pattern = ParsePrimaryExpression(CHECK_OK_CUSTOM(Void));
- ValidateBindingPattern(CHECK_OK_CUSTOM(Void));
-
+ FuncNameInferrerState fni_state(&fni_);
+ ExpressionT pattern = ParseBindingPattern(CHECK_OK_CUSTOM(Void));
if (!impl()->IsIdentifier(pattern)) {
parameters->is_simple = false;
ValidateFormalParameterInitializer(CHECK_OK_CUSTOM(Void));
- classifier()->RecordNonSimpleParameter();
}
ExpressionT initializer = impl()->NullExpression();
@@ -3808,8 +3803,8 @@ void ParserBase<Impl>::ParseFormalParameter(FormalParametersT* parameters,
impl()->SetFunctionNameFromIdentifierRef(initializer, pattern);
}
- impl()->AddFormalParameter(parameters, pattern, initializer,
- scanner()->location().end_pos, is_rest);
+ impl()->AddFormalParameter(parameters, pattern, initializer, end_position(),
+ is_rest);
}
template <typename Impl>
@@ -3908,23 +3903,21 @@ typename ParserBase<Impl>::BlockT ParserBase<Impl>::ParseVariableDeclarations(
int bindings_start = peek_position();
do {
// Parse binding pattern.
- FuncNameInferrer::State fni_state(fni_);
+ FuncNameInferrerState fni_state(&fni_);
ExpressionT pattern = impl()->NullExpression();
int decl_pos = peek_position();
{
ExpressionClassifier pattern_classifier(this);
- pattern = ParsePrimaryExpression(CHECK_OK_CUSTOM(NullStatement));
+ pattern = ParseBindingPattern(CHECK_OK_CUSTOM(NullStatement));
- ValidateBindingPattern(CHECK_OK_CUSTOM(NullStatement));
if (IsLexicalVariableMode(parsing_result->descriptor.mode)) {
ValidateLetPattern(CHECK_OK_CUSTOM(NullStatement));
}
}
-
Scanner::Location variable_loc = scanner()->location();
- bool single_name = impl()->IsIdentifier(pattern);
+ bool single_name = impl()->IsIdentifier(pattern);
if (single_name) {
impl()->PushVariableName(impl()->AsIdentifier(pattern));
}
@@ -3939,32 +3932,32 @@ typename ParserBase<Impl>::BlockT ParserBase<Impl>::ParseVariableDeclarations(
value = ParseAssignmentExpression(var_context != kForStatement,
CHECK_OK_CUSTOM(NullStatement));
ValidateExpression(CHECK_OK_CUSTOM(NullStatement));
- variable_loc.end_pos = scanner()->location().end_pos;
+ variable_loc.end_pos = end_position();
if (!parsing_result->first_initializer_loc.IsValid()) {
parsing_result->first_initializer_loc = variable_loc;
}
// Don't infer if it is "a = function(){...}();"-like expression.
- if (single_name && fni_ != nullptr) {
+ if (single_name) {
if (!value->IsCall() && !value->IsCallNew()) {
- fni_->Infer();
+ fni_.Infer();
} else {
- fni_->RemoveLastFunction();
+ fni_.RemoveLastFunction();
}
}
impl()->SetFunctionNameFromIdentifierRef(value, pattern);
// End position of the initializer is after the assignment expression.
- initializer_position = scanner()->location().end_pos;
+ initializer_position = end_position();
} else {
if (var_context != kForStatement || !PeekInOrOf()) {
// ES6 'const' and binding patterns require initializers.
if (parsing_result->descriptor.mode == VariableMode::kConst ||
!impl()->IsIdentifier(pattern)) {
impl()->ReportMessageAt(
- Scanner::Location(decl_pos, scanner()->location().end_pos),
+ Scanner::Location(decl_pos, end_position()),
MessageTemplate::kDeclarationMissingInitializer,
!impl()->IsIdentifier(pattern) ? "destructuring" : "const");
*ok = false;
@@ -3998,7 +3991,7 @@ typename ParserBase<Impl>::BlockT ParserBase<Impl>::ParseVariableDeclarations(
} while (Check(Token::COMMA));
parsing_result->bindings_loc =
- Scanner::Location(bindings_start, scanner()->location().end_pos);
+ Scanner::Location(bindings_start, end_position());
DCHECK(*ok);
return init_block;
@@ -4009,7 +4002,7 @@ typename ParserBase<Impl>::StatementT
ParserBase<Impl>::ParseFunctionDeclaration(bool* ok) {
Consume(Token::FUNCTION);
int pos = position();
- ParseFunctionFlags flags = ParseFunctionFlags::kIsNormal;
+ ParseFunctionFlags flags = ParseFunctionFlag::kIsNormal;
if (Check(Token::MUL)) {
impl()->ReportMessageAt(
scanner()->location(),
@@ -4026,9 +4019,9 @@ ParserBase<Impl>::ParseHoistableDeclaration(
ZonePtrList<const AstRawString>* names, bool default_export, bool* ok) {
Expect(Token::FUNCTION, CHECK_OK_CUSTOM(NullStatement));
int pos = position();
- ParseFunctionFlags flags = ParseFunctionFlags::kIsNormal;
+ ParseFunctionFlags flags = ParseFunctionFlag::kIsNormal;
if (Check(Token::MUL)) {
- flags |= ParseFunctionFlags::kIsGenerator;
+ flags |= ParseFunctionFlag::kIsGenerator;
}
return ParseHoistableDeclaration(pos, flags, names, default_export, ok);
}
@@ -4049,13 +4042,12 @@ ParserBase<Impl>::ParseHoistableDeclaration(
//
// 'function' and '*' (if present) have been consumed by the caller.
- bool is_generator = flags & ParseFunctionFlags::kIsGenerator;
- const bool is_async = flags & ParseFunctionFlags::kIsAsync;
- DCHECK(!is_generator || !is_async);
+ DCHECK_IMPLIES((flags & ParseFunctionFlag::kIsAsync) != 0,
+ (flags & ParseFunctionFlag::kIsGenerator) == 0);
- if (is_async && Check(Token::MUL)) {
+ if ((flags & ParseFunctionFlag::kIsAsync) != 0 && Check(Token::MUL)) {
// Async generator
- is_generator = true;
+ flags |= ParseFunctionFlag::kIsGenerator;
}
IdentifierT name;
@@ -4074,10 +4066,10 @@ ParserBase<Impl>::ParseHoistableDeclaration(
variable_name = name;
}
- FuncNameInferrer::State fni_state(fni_);
+ FuncNameInferrerState fni_state(&fni_);
impl()->PushEnclosingName(name);
- FunctionKind kind = FunctionKindFor(is_generator, is_async);
+ FunctionKind kind = FunctionKindFor(flags);
FunctionLiteralT function = impl()->ParseFunctionLiteral(
name, scanner()->location(), name_validity, kind, pos,
@@ -4097,7 +4089,7 @@ ParserBase<Impl>::ParseHoistableDeclaration(
// a flag and UseCounting violations to assess web compatibility.
bool is_sloppy_block_function = is_sloppy(language_mode()) &&
!scope()->is_declaration_scope() &&
- !is_async && !is_generator;
+ flags == ParseFunctionFlag::kIsNormal;
return impl()->DeclareFunction(variable_name, function, mode, pos,
is_sloppy_block_function, names, ok);
@@ -4187,7 +4179,7 @@ ParserBase<Impl>::ParseAsyncFunctionDeclaration(
return impl()->NullStatement();
}
Expect(Token::FUNCTION, CHECK_OK_CUSTOM(NullStatement));
- ParseFunctionFlags flags = ParseFunctionFlags::kIsAsync;
+ ParseFunctionFlags flags = ParseFunctionFlag::kIsAsync;
return ParseHoistableDeclaration(pos, flags, names, default_export, ok);
}
@@ -4195,7 +4187,8 @@ template <typename Impl>
void ParserBase<Impl>::ParseFunctionBody(
typename ParserBase<Impl>::StatementListT result, IdentifierT function_name,
int pos, const FormalParametersT& parameters, FunctionKind kind,
- FunctionLiteral::FunctionType function_type, bool* ok) {
+ FunctionLiteral::FunctionType function_type, FunctionBodyType body_type,
+ bool accept_IN, bool* ok) {
DeclarationScope* function_scope = scope()->AsDeclarationScope();
DeclarationScope* inner_scope = function_scope;
BlockT inner_block = impl()->NullStatement();
@@ -4209,35 +4202,56 @@ void ParserBase<Impl>::ParseFunctionBody(
body = inner_block->statements();
}
- // If we are parsing the source as if it is wrapped in a function, the source
- // ends without a closing brace.
- Token::Value closing_token =
- function_type == FunctionLiteral::kWrapped ? Token::EOS : Token::RBRACE;
-
{
BlockState block_state(&scope_, inner_scope);
if (IsResumableFunction(kind)) impl()->PrepareGeneratorVariables();
- if (IsAsyncGeneratorFunction(kind)) {
- impl()->ParseAndRewriteAsyncGeneratorFunctionBody(pos, kind, body, ok);
- } else if (IsGeneratorFunction(kind)) {
- impl()->ParseAndRewriteGeneratorFunctionBody(pos, kind, body, ok);
- } else if (IsAsyncFunction(kind)) {
- ParseAsyncFunctionBody(inner_scope, body, CHECK_OK_VOID);
+ if (body_type == FunctionBodyType::kExpression) {
+ ExpressionClassifier classifier(this);
+ ExpressionT expression =
+ ParseAssignmentExpression(accept_IN, CHECK_OK_VOID);
+ ValidateExpression(CHECK_OK_VOID);
+
+ if (IsAsyncFunction(kind)) {
+ BlockT block = factory()->NewBlock(1, true);
+ impl()->RewriteAsyncFunctionBody(body, block, expression,
+ CHECK_OK_VOID);
+ } else {
+ body->Add(BuildReturnStatement(expression, expression->position()),
+ zone());
+ }
} else {
- ParseStatementList(body, closing_token, CHECK_OK_VOID);
- }
+ DCHECK(accept_IN);
+ DCHECK_EQ(FunctionBodyType::kBlock, body_type);
+ // If we are parsing the source as if it is wrapped in a function, the
+ // source ends without a closing brace.
+ Token::Value closing_token = function_type == FunctionLiteral::kWrapped
+ ? Token::EOS
+ : Token::RBRACE;
+
+ if (IsAsyncGeneratorFunction(kind)) {
+ impl()->ParseAndRewriteAsyncGeneratorFunctionBody(pos, kind, body,
+ CHECK_OK_VOID);
+ } else if (IsGeneratorFunction(kind)) {
+ impl()->ParseAndRewriteGeneratorFunctionBody(pos, kind, body,
+ CHECK_OK_VOID);
+ } else if (IsAsyncFunction(kind)) {
+ ParseAsyncFunctionBody(inner_scope, body, CHECK_OK_VOID);
+ } else {
+ ParseStatementList(body, closing_token, CHECK_OK_VOID);
+ }
- if (IsDerivedConstructor(kind)) {
- body->Add(factory()->NewReturnStatement(impl()->ThisExpression(),
- kNoSourcePosition),
- zone());
+ if (IsDerivedConstructor(kind)) {
+ body->Add(factory()->NewReturnStatement(impl()->ThisExpression(),
+ kNoSourcePosition),
+ zone());
+ }
+ Expect(closing_token, CHECK_OK_VOID);
}
}
- Expect(closing_token, CHECK_OK_VOID);
- scope()->set_end_position(scanner()->location().end_pos);
+ scope()->set_end_position(end_position());
if (!parameters.is_simple) {
DCHECK_NOT_NULL(inner_scope);
@@ -4256,7 +4270,7 @@ void ParserBase<Impl>::ParseFunctionBody(
init_block = impl()->BuildRejectPromiseOnException(init_block);
}
- inner_scope->set_end_position(scanner()->location().end_pos);
+ inner_scope->set_end_position(end_position());
if (inner_scope->FinalizeBlockScope() != nullptr) {
impl()->CheckConflictingVarDeclarations(inner_scope, CHECK_OK_VOID);
impl()->InsertShadowingVarBindingInitializers(inner_block);
@@ -4315,7 +4329,7 @@ void ParserBase<Impl>::CheckArityRestrictions(int param_count,
template <typename Impl>
bool ParserBase<Impl>::IsNextLetKeyword() {
- DCHECK(peek() == Token::LET);
+ DCHECK_EQ(Token::LET, peek());
Token::Value next_next = PeekAhead();
switch (next_next) {
case Token::LBRACE:
@@ -4340,17 +4354,13 @@ bool ParserBase<Impl>::IsNextLetKeyword() {
template <typename Impl>
bool ParserBase<Impl>::IsTrivialExpression() {
- Token::Value peek_token = peek();
- if (peek_token == Token::SMI || peek_token == Token::NUMBER ||
- peek_token == Token::BIGINT || peek_token == Token::NULL_LITERAL ||
- peek_token == Token::TRUE_LITERAL || peek_token == Token::FALSE_LITERAL ||
- peek_token == Token::STRING || peek_token == Token::IDENTIFIER ||
- peek_token == Token::THIS) {
- // PeekAhead() is expensive & may not always be called, so we only call it
- // after checking peek().
+ if (Token::IsTrivialExpressionToken(peek())) {
+ // PeekAhead() may not always be called, so we only call it after checking
+ // peek().
Token::Value peek_ahead = PeekAhead();
if (peek_ahead == Token::COMMA || peek_ahead == Token::RPAREN ||
- peek_ahead == Token::SEMICOLON || peek_ahead == Token::RBRACK) {
+ peek_ahead == Token::SEMICOLON || peek_ahead == Token::RBRACK ||
+ Token::IsAssignmentOp(peek_ahead)) {
return true;
}
}
@@ -4421,39 +4431,52 @@ ParserBase<Impl>::ParseArrowFunctionLiteral(
// parameters.
int dummy_num_parameters = -1;
DCHECK_NE(kind & FunctionKind::kArrowFunction, 0);
- LazyParsingResult result = impl()->SkipFunction(
+ FunctionLiteral::EagerCompileHint hint;
+ bool did_preparse_successfully = impl()->SkipFunction(
nullptr, kind, FunctionLiteral::kAnonymousExpression,
formal_parameters.scope, &dummy_num_parameters,
- &produced_preparsed_scope_data, false, false, CHECK_OK);
- DCHECK_NE(result, kLazyParsingAborted);
+ &produced_preparsed_scope_data, false, false, &hint, CHECK_OK);
+
DCHECK_NULL(produced_preparsed_scope_data);
- USE(result);
- formal_parameters.scope->ResetAfterPreparsing(ast_value_factory_,
- false);
- // Discard any queued destructuring assignments which appeared
- // in this function's parameter list, and which were adopted
- // into this function state, above.
- function_state.RewindDestructuringAssignments(0);
+
+ if (did_preparse_successfully) {
+ // Discard any queued destructuring assignments which appeared
+ // in this function's parameter list, and which were adopted
+ // into this function state, above.
+ function_state.RewindDestructuringAssignments(0);
+ } else {
+ // In case we did not sucessfully preparse the function because of an
+ // unidentified error we do a full reparse to return the error.
+ Consume(Token::LBRACE);
+ body = impl()->NewStatementList(8);
+ ParseFunctionBody(body, impl()->NullIdentifier(), kNoSourcePosition,
+ formal_parameters, kind,
+ FunctionLiteral::kAnonymousExpression,
+ FunctionBodyType::kBlock, true, ok);
+ CHECK(!*ok);
+ return impl()->NullExpression();
+ }
} else {
Consume(Token::LBRACE);
body = impl()->NewStatementList(8);
ParseFunctionBody(body, impl()->NullIdentifier(), kNoSourcePosition,
formal_parameters, kind,
- FunctionLiteral::kAnonymousExpression, CHECK_OK);
+ FunctionLiteral::kAnonymousExpression,
+ FunctionBodyType::kBlock, true, CHECK_OK);
expected_property_count = function_state.expected_property_count();
}
} else {
// Single-expression body
has_braces = false;
- const bool is_async = IsAsyncFunction(kind);
body = impl()->NewStatementList(1);
- impl()->AddParameterInitializationBlock(formal_parameters, body, is_async,
- CHECK_OK);
- ParseSingleExpressionFunctionBody(body, is_async, accept_IN, CHECK_OK);
+ ParseFunctionBody(body, impl()->NullIdentifier(), kNoSourcePosition,
+ formal_parameters, kind,
+ FunctionLiteral::kAnonymousExpression,
+ FunctionBodyType::kExpression, accept_IN, CHECK_OK);
expected_property_count = function_state.expected_property_count();
}
- formal_parameters.scope->set_end_position(scanner()->location().end_pos);
+ formal_parameters.scope->set_end_position(end_position());
// Arrow function formal parameters are parsed as StrictFormalParameterList,
// which is not the same as "parameters of a strict function"; it only means
@@ -4466,7 +4489,7 @@ ParserBase<Impl>::ParseArrowFunctionLiteral(
// Validate strict mode.
if (is_strict(language_mode())) {
CheckStrictOctalLiteral(formal_parameters.scope->start_position(),
- scanner()->location().end_pos, CHECK_OK);
+ end_position(), CHECK_OK);
}
impl()->CheckConflictingVarDeclarations(formal_parameters.scope, CHECK_OK);
@@ -4532,9 +4555,9 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseClassLiteral(
class_info.is_anonymous = is_anonymous;
impl()->DeclareClassVariable(name, &class_info, class_token_pos, CHECK_OK);
- scope()->set_start_position(scanner()->location().end_pos);
+ scope()->set_start_position(end_position());
if (Check(Token::EXTENDS)) {
- FuncNameInferrer::State fni_state(fni_);
+ FuncNameInferrerState fni_state(&fni_);
ExpressionClassifier extends_classifier(this);
class_info.extends = ParseLeftHandSideExpression(CHECK_OK);
ValidateExpression(CHECK_OK);
@@ -4548,7 +4571,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseClassLiteral(
const bool has_extends = !impl()->IsNull(class_info.extends);
while (peek() != Token::RBRACE) {
if (Check(Token::SEMICOLON)) continue;
- FuncNameInferrer::State fni_state(fni_);
+ FuncNameInferrerState fni_state(&fni_);
bool is_computed_name = false; // Classes do not care about computed
// property names here.
bool is_static;
@@ -4580,32 +4603,13 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseClassLiteral(
}
Expect(Token::RBRACE, CHECK_OK);
- int end_pos = scanner()->location().end_pos;
+ int end_pos = end_position();
block_scope->set_end_position(end_pos);
return impl()->RewriteClassLiteral(block_scope, name, &class_info,
class_token_pos, end_pos, ok);
}
template <typename Impl>
-void ParserBase<Impl>::ParseSingleExpressionFunctionBody(StatementListT body,
- bool is_async,
- bool accept_IN,
- bool* ok) {
- if (is_async) impl()->PrepareGeneratorVariables();
-
- ExpressionClassifier classifier(this);
- ExpressionT expression = ParseAssignmentExpression(accept_IN, CHECK_OK_VOID);
- ValidateExpression(CHECK_OK_VOID);
-
- if (is_async) {
- BlockT block = factory()->NewBlock(1, true);
- impl()->RewriteAsyncFunctionBody(body, block, expression, CHECK_OK_VOID);
- } else {
- body->Add(BuildReturnStatement(expression, expression->position()), zone());
- }
-}
-
-template <typename Impl>
void ParserBase<Impl>::ParseAsyncFunctionBody(Scope* scope, StatementListT body,
bool* ok) {
BlockT block = factory()->NewBlock(8, true);
@@ -4614,7 +4618,7 @@ void ParserBase<Impl>::ParseAsyncFunctionBody(Scope* scope, StatementListT body,
impl()->RewriteAsyncFunctionBody(
body, block, factory()->NewUndefinedLiteral(kNoSourcePosition),
CHECK_OK_VOID);
- scope->set_end_position(scanner()->location().end_pos);
+ scope->set_end_position(end_position());
}
template <typename Impl>
@@ -4633,9 +4637,9 @@ ParserBase<Impl>::ParseAsyncFunctionLiteral(bool* ok) {
IdentifierT name = impl()->NullIdentifier();
FunctionLiteral::FunctionType type = FunctionLiteral::kAnonymousExpression;
- bool is_generator = Check(Token::MUL);
- const bool kIsAsync = true;
- const FunctionKind kind = FunctionKindFor(is_generator, kIsAsync);
+ ParseFunctionFlags flags = ParseFunctionFlag::kIsAsync;
+ if (Check(Token::MUL)) flags |= ParseFunctionFlag::kIsGenerator;
+ const FunctionKind kind = FunctionKindFor(flags);
if (impl()->ParsingDynamicFunctionDeclaration()) {
// We don't want dynamic functions to actually declare their name
@@ -4659,7 +4663,7 @@ ParserBase<Impl>::ParseAsyncFunctionLiteral(bool* ok) {
name, scanner()->location(),
is_strict_reserved ? kFunctionNameIsStrictReserved
: kFunctionNameValidityUnknown,
- kind, pos, type, language_mode(), nullptr, CHECK_OK);
+ kind, pos, type, language_mode(), nullptr, ok);
}
template <typename Impl>
@@ -5112,6 +5116,7 @@ typename ParserBase<Impl>::BlockT ParserBase<Impl>::ParseBlock(
Expect(Token::LBRACE, CHECK_OK_CUSTOM(NullStatement));
{
BlockState block_state(zone(), &scope_);
+ // Scope starts before opening brace.
scope()->set_start_position(scanner()->location().beg_pos);
typename Types::Target target(this, body);
@@ -5123,9 +5128,10 @@ typename ParserBase<Impl>::BlockT ParserBase<Impl>::ParseBlock(
}
Expect(Token::RBRACE, CHECK_OK_CUSTOM(NullStatement));
- int end_pos = scanner()->location().end_pos;
- scope()->set_end_position(end_pos);
- impl()->RecordBlockSourceRange(body, end_pos);
+ // Scope ends after closing brace.
+ scope()->set_end_position(scanner()->location().end_pos);
+ // Coverage range uses position before closing brace.
+ impl()->RecordBlockSourceRange(body, scanner()->location().beg_pos);
body->set_scope(scope()->FinalizeBlockScope());
}
return body;
@@ -5144,7 +5150,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseScopedStatement(
BlockT block = factory()->NewBlock(1, false);
StatementT body = ParseFunctionDeclaration(CHECK_OK);
block->statements()->Add(body, zone());
- scope()->set_end_position(scanner()->location().end_pos);
+ scope()->set_end_position(end_position());
block->set_scope(scope()->FinalizeBlockScope());
return block;
}
@@ -5172,7 +5178,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseVariableStatement(
DeclarationParsingResult parsing_result;
StatementT result =
ParseVariableDeclarations(var_context, &parsing_result, names, CHECK_OK);
- ExpectSemicolon(CHECK_OK);
+ ExpectSemicolon(ok);
return result;
}
@@ -5234,7 +5240,7 @@ ParserBase<Impl>::ParseExpressionOrLabelledStatement(
}
bool starts_with_identifier = peek_any_identifier();
- ExpressionT expr = ParseExpression(true, CHECK_OK);
+ ExpressionT expr = ParseExpression(CHECK_OK);
if (peek() == Token::COLON && starts_with_identifier &&
impl()->IsIdentifier(expr)) {
// The whole expression was a single identifier, and not, e.g.,
@@ -5273,7 +5279,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseIfStatement(
int pos = peek_position();
Expect(Token::IF, CHECK_OK);
Expect(Token::LPAREN, CHECK_OK);
- ExpressionT condition = ParseExpression(true, CHECK_OK);
+ ExpressionT condition = ParseExpression(CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
SourceRange then_range, else_range;
@@ -5285,9 +5291,8 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseIfStatement(
StatementT else_statement = impl()->NullStatement();
if (Check(Token::ELSE)) {
- else_range = SourceRange::ContinuationOf(then_range);
else_statement = ParseScopedStatement(labels, CHECK_OK);
- else_range.end = scanner_->location().end_pos;
+ else_range = SourceRange::ContinuationOf(then_range, end_position());
} else {
else_statement = factory()->NewEmptyStatement(kNoSourcePosition);
}
@@ -5330,7 +5335,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseContinueStatement(
}
ExpectSemicolon(CHECK_OK);
StatementT stmt = factory()->NewContinueStatement(target, pos);
- impl()->RecordJumpStatementSourceRange(stmt, scanner_->location().end_pos);
+ impl()->RecordJumpStatementSourceRange(stmt, end_position());
return stmt;
}
@@ -5369,7 +5374,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseBreakStatement(
}
ExpectSemicolon(CHECK_OK);
StatementT stmt = factory()->NewBreakStatement(target, pos);
- impl()->RecordJumpStatementSourceRange(stmt, scanner_->location().end_pos);
+ impl()->RecordJumpStatementSourceRange(stmt, end_position());
return stmt;
}
@@ -5404,14 +5409,14 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseReturnStatement(
return_value = impl()->ThisExpression(loc.beg_pos);
}
} else {
- return_value = ParseExpression(true, CHECK_OK);
+ return_value = ParseExpression(CHECK_OK);
}
ExpectSemicolon(CHECK_OK);
return_value = impl()->RewriteReturn(return_value, loc.beg_pos);
- int continuation_pos = scanner_->location().end_pos;
+ int continuation_pos = end_position();
StatementT stmt =
BuildReturnStatement(return_value, loc.beg_pos, continuation_pos);
- impl()->RecordJumpStatementSourceRange(stmt, scanner_->location().end_pos);
+ impl()->RecordJumpStatementSourceRange(stmt, end_position());
return stmt;
}
@@ -5431,7 +5436,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseWithStatement(
}
Expect(Token::LPAREN, CHECK_OK);
- ExpressionT expr = ParseExpression(true, CHECK_OK);
+ ExpressionT expr = ParseExpression(CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
Scope* with_scope = NewScope(WITH_SCOPE);
@@ -5440,7 +5445,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseWithStatement(
BlockState block_state(&scope_, with_scope);
with_scope->set_start_position(scanner()->peek_location().beg_pos);
body = ParseStatement(labels, nullptr, CHECK_OK);
- with_scope->set_end_position(scanner()->location().end_pos);
+ with_scope->set_end_position(end_position());
}
return factory()->NewWithStatement(with_scope, expr, body, pos);
}
@@ -5467,7 +5472,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseDoWhileStatement(
Expect(Token::WHILE, CHECK_OK);
Expect(Token::LPAREN, CHECK_OK);
- ExpressionT cond = ParseExpression(true, CHECK_OK);
+ ExpressionT cond = ParseExpression(CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
// Allow do-statements to be terminated with and without
@@ -5497,7 +5502,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseWhileStatement(
Expect(Token::WHILE, CHECK_OK);
Expect(Token::LPAREN, CHECK_OK);
- ExpressionT cond = ParseExpression(true, CHECK_OK);
+ ExpressionT cond = ParseExpression(CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
{
SourceRangeScope range_scope(scanner(), &body_range);
@@ -5523,11 +5528,11 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseThrowStatement(
*ok = false;
return impl()->NullStatement();
}
- ExpressionT exception = ParseExpression(true, CHECK_OK);
+ ExpressionT exception = ParseExpression(CHECK_OK);
ExpectSemicolon(CHECK_OK);
StatementT stmt = impl()->NewThrowStatement(exception, pos);
- impl()->RecordThrowSourceRange(stmt, scanner_->location().end_pos);
+ impl()->RecordThrowSourceRange(stmt, end_position());
return stmt;
}
@@ -5545,7 +5550,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseSwitchStatement(
Expect(Token::SWITCH, CHECK_OK);
Expect(Token::LPAREN, CHECK_OK);
- ExpressionT tag = ParseExpression(true, CHECK_OK);
+ ExpressionT tag = ParseExpression(CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
auto switch_statement =
@@ -5565,7 +5570,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseSwitchStatement(
SourceRange clause_range;
SourceRangeScope range_scope(scanner(), &clause_range);
if (Check(Token::CASE)) {
- label = ParseExpression(true, CHECK_OK);
+ label = ParseExpression(CHECK_OK);
} else {
Expect(Token::DEFAULT, CHECK_OK);
if (default_seen) {
@@ -5588,9 +5593,9 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseSwitchStatement(
}
Expect(Token::RBRACE, CHECK_OK);
- int end_position = scanner()->location().end_pos;
- scope()->set_end_position(end_position);
- impl()->RecordSwitchStatementSourceRange(switch_statement, end_position);
+ int end_pos = end_position();
+ scope()->set_end_position(end_pos);
+ impl()->RecordSwitchStatementSourceRange(switch_statement, end_pos);
Scope* switch_scope = scope()->FinalizeBlockScope();
if (switch_scope != nullptr) {
return impl()->RewriteSwitchStatement(switch_statement, switch_scope);
@@ -5659,8 +5664,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseTryStatement(
ParseIdentifier(kDontAllowRestrictedIdentifiers, CHECK_OK);
} else {
ExpressionClassifier pattern_classifier(this);
- catch_info.pattern = ParsePrimaryExpression(CHECK_OK);
- ValidateBindingPattern(CHECK_OK);
+ catch_info.pattern = ParseBindingPattern(CHECK_OK);
}
Expect(Token::RPAREN, CHECK_OK);
@@ -5672,12 +5676,12 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseTryStatement(
catch_info.inner_block = ParseBlock(nullptr, CHECK_OK);
catch_block->statements()->Add(catch_info.inner_block, zone());
impl()->ValidateCatchBlock(catch_info, CHECK_OK);
- scope()->set_end_position(scanner()->location().end_pos);
+ scope()->set_end_position(end_position());
catch_block->set_scope(scope()->FinalizeBlockScope());
}
}
- catch_info.scope->set_end_position(scanner()->location().end_pos);
+ catch_info.scope->set_end_position(end_position());
} else {
catch_block = ParseBlock(nullptr, CHECK_OK);
}
@@ -5777,7 +5781,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForStatement(
int lhs_beg_pos = peek_position();
ExpressionClassifier classifier(this);
ExpressionT expression = ParseExpressionCoverGrammar(false, CHECK_OK);
- int lhs_end_pos = scanner()->location().end_pos;
+ int lhs_end_pos = end_position();
bool is_for_each = CheckInOrOf(&for_info.mode);
bool is_destructuring = is_for_each && (expression->IsArrayLiteral() ||
@@ -5853,7 +5857,7 @@ ParserBase<Impl>::ParseForEachStatementWithDeclarations(
enumerable = ParseAssignmentExpression(true, CHECK_OK);
ValidateExpression(CHECK_OK);
} else {
- enumerable = ParseExpression(true, CHECK_OK);
+ enumerable = ParseExpression(CHECK_OK);
}
Expect(Token::RPAREN, CHECK_OK);
@@ -5861,7 +5865,7 @@ ParserBase<Impl>::ParseForEachStatementWithDeclarations(
Scope* for_scope = nullptr;
if (inner_block_scope != nullptr) {
for_scope = inner_block_scope->outer_scope();
- DCHECK(for_scope == scope());
+ DCHECK_EQ(for_scope, scope());
inner_block_scope->set_start_position(scanner()->location().beg_pos);
}
@@ -5882,7 +5886,7 @@ ParserBase<Impl>::ParseForEachStatementWithDeclarations(
body_block->statements()->Add(body, zone());
if (inner_block_scope != nullptr) {
- inner_block_scope->set_end_position(scanner()->location().end_pos);
+ inner_block_scope->set_end_position(end_position());
body_block->set_scope(inner_block_scope->FinalizeBlockScope());
}
}
@@ -5890,10 +5894,11 @@ ParserBase<Impl>::ParseForEachStatementWithDeclarations(
StatementT final_loop = impl()->InitializeForEachStatement(
loop, each_variable, enumerable, body_block);
- init_block = impl()->CreateForEachStatementTDZ(init_block, *for_info, ok);
+ init_block =
+ impl()->CreateForEachStatementTDZ(init_block, *for_info, CHECK_OK);
if (for_scope != nullptr) {
- for_scope->set_end_position(scanner()->location().end_pos);
+ for_scope->set_end_position(end_position());
for_scope = for_scope->FinalizeBlockScope();
}
@@ -5931,7 +5936,7 @@ ParserBase<Impl>::ParseForEachStatementWithoutDeclarations(
enumerable = ParseAssignmentExpression(true, CHECK_OK);
ValidateExpression(CHECK_OK);
} else {
- enumerable = ParseExpression(true, CHECK_OK);
+ enumerable = ParseExpression(CHECK_OK);
}
Expect(Token::RPAREN, CHECK_OK);
@@ -5965,10 +5970,10 @@ ParserBase<Impl>::ParseStandardForLoopWithLexicalDeclarations(
scope()->set_start_position(scanner()->location().beg_pos);
loop = ParseStandardForLoop(stmt_pos, labels, own_labels, &cond, &next,
&body, CHECK_OK);
- scope()->set_end_position(scanner()->location().end_pos);
+ scope()->set_end_position(end_position());
}
- scope()->set_end_position(scanner()->location().end_pos);
+ scope()->set_end_position(end_position());
if (for_info->bound_names.length() > 0 &&
function_state_->contains_function_or_eval()) {
scope()->set_is_hidden();
@@ -6014,12 +6019,12 @@ typename ParserBase<Impl>::ForStatementT ParserBase<Impl>::ParseStandardForLoop(
typename Types::Target target(this, loop);
if (peek() != Token::SEMICOLON) {
- *cond = ParseExpression(true, CHECK_OK);
+ *cond = ParseExpression(CHECK_OK);
}
Expect(Token::SEMICOLON, CHECK_OK);
if (peek() != Token::RPAREN) {
- ExpressionT exp = ParseExpression(true, CHECK_OK);
+ ExpressionT exp = ParseExpression(CHECK_OK);
*next = factory()->NewExpressionStatement(exp, exp->position());
}
Expect(Token::RPAREN, CHECK_OK);
@@ -6114,7 +6119,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement(
BlockState inner_state(&scope_, inner_block_scope);
ExpressionClassifier classifier(this);
ExpressionT lhs = each_variable = ParseLeftHandSideExpression(CHECK_OK);
- int lhs_end_pos = scanner()->location().end_pos;
+ int lhs_end_pos = end_position();
if (lhs->IsArrayLiteral() || lhs->IsObjectLiteral()) {
ValidateAssignmentPattern(CHECK_OK);
@@ -6149,7 +6154,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement(
SourceRangeScope range_scope(scanner(), &body_range);
body = ParseStatement(nullptr, nullptr, CHECK_OK);
- scope()->set_end_position(scanner()->location().end_pos);
+ scope()->set_end_position(end_position());
impl()->RecordIterationStatementSourceRange(loop, range_scope.Finalize());
if (has_declarations) {
@@ -6177,10 +6182,10 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement(
return final_loop;
}
- BlockT init_block =
- impl()->CreateForEachStatementTDZ(impl()->NullStatement(), for_info, ok);
+ BlockT init_block = impl()->CreateForEachStatementTDZ(impl()->NullStatement(),
+ for_info, CHECK_OK);
- scope()->set_end_position(scanner()->location().end_pos);
+ scope()->set_end_position(end_position());
Scope* for_scope = scope()->FinalizeBlockScope();
// Parsed for-in loop w/ variable declarations.
if (!impl()->IsNull(init_block)) {
@@ -6209,10 +6214,9 @@ void ParserBase<Impl>::ObjectLiteralChecker::CheckDuplicateProto(
template <typename Impl>
void ParserBase<Impl>::ClassLiteralChecker::CheckClassMethodName(
- Token::Value property, PropertyKind type, bool is_generator, bool is_async,
+ Token::Value property, ParsePropertyKind type, ParseFunctionFlags flags,
bool is_static, bool* ok) {
- DCHECK(type == PropertyKind::kMethodProperty ||
- type == PropertyKind::kAccessorProperty);
+ DCHECK(type == ParsePropertyKind::kMethod || IsAccessor(type));
if (property == Token::SMI || property == Token::NUMBER) return;
@@ -6223,11 +6227,13 @@ void ParserBase<Impl>::ClassLiteralChecker::CheckClassMethodName(
return;
}
} else if (IsConstructor()) {
- if (is_generator || is_async || type == PropertyKind::kAccessorProperty) {
+ if (flags != ParseFunctionFlag::kIsNormal || IsAccessor(type)) {
MessageTemplate::Template msg =
- is_generator ? MessageTemplate::kConstructorIsGenerator
- : is_async ? MessageTemplate::kConstructorIsAsync
- : MessageTemplate::kConstructorIsAccessor;
+ (flags & ParseFunctionFlag::kIsGenerator) != 0
+ ? MessageTemplate::kConstructorIsGenerator
+ : (flags & ParseFunctionFlag::kIsAsync) != 0
+ ? MessageTemplate::kConstructorIsAsync
+ : MessageTemplate::kConstructorIsAccessor;
this->parser()->ReportMessage(msg);
*ok = false;
return;