aboutsummaryrefslogtreecommitdiff
path: root/deps/v8/src/parsing/parser-base.h
diff options
context:
space:
mode:
authorMichaël Zasso <targos@protonmail.com>2019-03-12 09:01:49 +0100
committerMichaël Zasso <targos@protonmail.com>2019-03-14 18:49:21 +0100
commit7b48713334469818661fe276cf571de9c7899f2d (patch)
tree4dbda49ac88db76ce09dc330a0cb587e68e139ba /deps/v8/src/parsing/parser-base.h
parent8549ac09b256666cf5275224ec58fab9939ff32e (diff)
downloadandroid-node-v8-7b48713334469818661fe276cf571de9c7899f2d.tar.gz
android-node-v8-7b48713334469818661fe276cf571de9c7899f2d.tar.bz2
android-node-v8-7b48713334469818661fe276cf571de9c7899f2d.zip
deps: update V8 to 7.3.492.25
PR-URL: https://github.com/nodejs/node/pull/25852 Reviewed-By: Ujjwal Sharma <usharma1998@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Ali Ijaz Sheikh <ofrobots@google.com>
Diffstat (limited to 'deps/v8/src/parsing/parser-base.h')
-rw-r--r--deps/v8/src/parsing/parser-base.h4704
1 files changed, 2104 insertions, 2600 deletions
diff --git a/deps/v8/src/parsing/parser-base.h b/deps/v8/src/parsing/parser-base.h
index bfb056e0c8..33c165cd92 100644
--- a/deps/v8/src/parsing/parser-base.h
+++ b/deps/v8/src/parsing/parser-base.h
@@ -18,11 +18,12 @@
#include "src/counters.h"
#include "src/globals.h"
#include "src/log.h"
-#include "src/messages.h"
-#include "src/parsing/expression-classifier.h"
+#include "src/message-template.h"
+#include "src/parsing/expression-scope.h"
#include "src/parsing/func-name-inferrer.h"
#include "src/parsing/scanner.h"
#include "src/parsing/token.h"
+#include "src/pointer-with-payload.h"
#include "src/zone/zone-chunk-list.h"
namespace v8 {
@@ -39,6 +40,8 @@ enum AllowLabelledFunctionStatement {
kDisallowLabelledFunctionStatement,
};
+enum ParsingArrowHeadFlag { kCertainlyNotArrowHead, kMaybeArrowHead };
+
enum class ParseFunctionFlag : uint8_t {
kIsNormal = 0,
kIsGenerator = 1 << 0,
@@ -74,77 +77,39 @@ struct FormalParametersBase {
// Stack-allocated scope to collect source ranges from the parser.
class SourceRangeScope final {
public:
- enum PositionKind {
- POSITION_BEG,
- POSITION_END,
- PEEK_POSITION_BEG,
- PEEK_POSITION_END,
- };
-
- SourceRangeScope(Scanner* scanner, SourceRange* range,
- PositionKind pre_kind = PEEK_POSITION_BEG,
- PositionKind post_kind = POSITION_END)
- : scanner_(scanner), range_(range), post_kind_(post_kind) {
- range_->start = GetPosition(pre_kind);
+ SourceRangeScope(const Scanner* scanner, SourceRange* range)
+ : scanner_(scanner), range_(range) {
+ range_->start = scanner->peek_location().beg_pos;
DCHECK_NE(range_->start, kNoSourcePosition);
+ DCHECK_EQ(range_->end, kNoSourcePosition);
}
- ~SourceRangeScope() { Finalize(); }
-
- const SourceRange& Finalize() {
- if (is_finalized_) return *range_;
- is_finalized_ = true;
- range_->end = GetPosition(post_kind_);
+ ~SourceRangeScope() {
+ DCHECK_EQ(kNoSourcePosition, range_->end);
+ range_->end = scanner_->location().end_pos;
DCHECK_NE(range_->end, kNoSourcePosition);
- return *range_;
}
private:
- int32_t GetPosition(PositionKind kind) {
- switch (kind) {
- case POSITION_BEG:
- return scanner_->location().beg_pos;
- case POSITION_END:
- return scanner_->location().end_pos;
- case PEEK_POSITION_BEG:
- return scanner_->peek_location().beg_pos;
- case PEEK_POSITION_END:
- return scanner_->peek_location().end_pos;
- default:
- UNREACHABLE();
- }
- }
-
- Scanner* scanner_;
+ const Scanner* scanner_;
SourceRange* range_;
- PositionKind post_kind_;
- bool is_finalized_ = false;
DISALLOW_IMPLICIT_CONSTRUCTORS(SourceRangeScope);
};
// ----------------------------------------------------------------------------
-// The CHECK_OK macro is a convenient macro to enforce error
-// handling for functions that may fail (by returning !*ok).
+// The RETURN_IF_PARSE_ERROR macro is a convenient macro to enforce error
+// handling for functions that may fail (by returning if there was an parser
+// error).
//
-// CAUTION: This macro appends extra statements after a call,
-// thus it must never be used where only a single statement
-// is correct (e.g. an if statement branch w/o braces)!
-
-#define CHECK_OK_CUSTOM(x, ...) ok); \
- if (!*ok) return impl()->x(__VA_ARGS__); \
- ((void)0
-#define DUMMY ) // to make indentation work
-#undef DUMMY
-
-// Used in functions where the return type is ExpressionT.
-#define CHECK_OK CHECK_OK_CUSTOM(NullExpression)
+// Usage:
+// foo = ParseFoo(); // may fail
+// RETURN_IF_PARSE_ERROR
+//
+// SAFE_USE(foo);
-#define CHECK_OK_VOID ok); \
- if (!*ok) return; \
- ((void)0
-#define DUMMY ) // to make indentation work
-#undef DUMMY
+#define RETURN_IF_PARSE_ERROR \
+ if (has_error()) return impl()->NullStatement();
// Common base class template shared between parser and pre-parser.
// The Impl parameter is the actual class of the parser/pre-parser,
@@ -217,8 +182,10 @@ enum class ParsePropertyKind : uint8_t {
kAccessorSetter,
kValue,
kShorthand,
+ kAssign,
kMethod,
kClassField,
+ kShorthandOrClassField,
kSpread,
kNotSet
};
@@ -228,25 +195,43 @@ class ParserBase {
public:
// Shorten type names defined by ParserTypes<Impl>.
typedef ParserTypes<Impl> Types;
- typedef typename Types::Identifier IdentifierT;
- typedef typename Types::Expression ExpressionT;
- typedef typename Types::FunctionLiteral FunctionLiteralT;
- typedef typename Types::ObjectLiteralProperty ObjectLiteralPropertyT;
+ typedef typename v8::internal::ExpressionScope<Types> ExpressionScope;
+ typedef typename v8::internal::ExpressionParsingScope<Types>
+ ExpressionParsingScope;
+ typedef typename v8::internal::AccumulationScope<Types> AccumulationScope;
+ typedef typename v8::internal::ArrowHeadParsingScope<Types>
+ ArrowHeadParsingScope;
+ typedef typename v8::internal::VariableDeclarationParsingScope<Types>
+ VariableDeclarationParsingScope;
+ typedef typename v8::internal::ParameterDeclarationParsingScope<Types>
+ ParameterDeclarationParsingScope;
+
+ // Return types for traversing functions.
+ typedef typename Types::Block BlockT;
+ typedef typename Types::BreakableStatement BreakableStatementT;
typedef typename Types::ClassLiteralProperty ClassLiteralPropertyT;
- typedef typename Types::Suspend SuspendExpressionT;
- typedef typename Types::RewritableExpression RewritableExpressionT;
+ typedef typename Types::ClassPropertyList ClassPropertyListT;
+ typedef typename Types::Expression ExpressionT;
typedef typename Types::ExpressionList ExpressionListT;
typedef typename Types::FormalParameters FormalParametersT;
+ typedef typename Types::ForStatement ForStatementT;
+ typedef typename Types::FunctionLiteral FunctionLiteralT;
+ typedef typename Types::Identifier IdentifierT;
+ typedef typename Types::IterationStatement IterationStatementT;
+ typedef typename Types::ObjectLiteralProperty ObjectLiteralPropertyT;
+ typedef typename Types::ObjectPropertyList ObjectPropertyListT;
typedef typename Types::Statement StatementT;
typedef typename Types::StatementList StatementListT;
- typedef typename Types::Block BlockT;
- typedef typename Types::ForStatement ForStatementT;
- typedef typename v8::internal::ExpressionClassifier<Types>
- ExpressionClassifier;
+ typedef typename Types::Suspend SuspendExpressionT;
+ // For constructing objects returned by the traversing functions.
+ typedef typename Types::Factory FactoryT;
+ // Other implementation-specific tasks.
typedef typename Types::FuncNameInferrer FuncNameInferrer;
typedef typename Types::FuncNameInferrer::State FuncNameInferrerState;
typedef typename Types::SourceRange SourceRange;
typedef typename Types::SourceRangeScope SourceRangeScope;
+ typedef typename Types::Target TargetT;
+ typedef typename Types::TargetScope TargetScopeT;
// All implementation-specific methods must be called through this.
Impl* impl() { return static_cast<Impl*>(this); }
@@ -261,7 +246,7 @@ class ParserBase {
original_scope_(nullptr),
function_state_(nullptr),
extension_(extension),
- fni_(ast_value_factory, zone),
+ fni_(ast_value_factory),
ast_value_factory_(ast_value_factory),
ast_node_factory_(ast_value_factory, zone),
runtime_call_stats_(runtime_call_stats),
@@ -271,34 +256,38 @@ class ParserBase {
stack_limit_(stack_limit),
pending_error_handler_(pending_error_handler),
zone_(zone),
- classifier_(nullptr),
+ expression_scope_(nullptr),
scanner_(scanner),
- default_eager_compile_hint_(FunctionLiteral::kShouldLazyCompile),
function_literal_id_(0),
script_id_(script_id),
+ default_eager_compile_hint_(FunctionLiteral::kShouldLazyCompile),
allow_natives_(false),
- allow_harmony_do_expressions_(false),
allow_harmony_public_fields_(false),
allow_harmony_static_fields_(false),
allow_harmony_dynamic_import_(false),
allow_harmony_import_meta_(false),
allow_harmony_private_fields_(false),
- allow_eval_cache_(true) {}
+ allow_harmony_private_methods_(false),
+ allow_eval_cache_(true) {
+ pointer_buffer_.reserve(32);
+ variable_buffer_.reserve(32);
+ }
#define ALLOW_ACCESSORS(name) \
bool allow_##name() const { return allow_##name##_; } \
void set_allow_##name(bool allow) { allow_##name##_ = allow; }
ALLOW_ACCESSORS(natives);
- ALLOW_ACCESSORS(harmony_do_expressions);
ALLOW_ACCESSORS(harmony_public_fields);
ALLOW_ACCESSORS(harmony_static_fields);
ALLOW_ACCESSORS(harmony_dynamic_import);
ALLOW_ACCESSORS(harmony_import_meta);
+ ALLOW_ACCESSORS(harmony_private_methods);
ALLOW_ACCESSORS(eval_cache);
#undef ALLOW_ACCESSORS
+ V8_INLINE bool has_error() const { return scanner()->has_parser_error(); }
bool allow_harmony_numeric_separator() const {
return scanner()->allow_harmony_numeric_separator();
}
@@ -326,6 +315,10 @@ class ParserBase {
return default_eager_compile_hint_;
}
+ int loop_nesting_depth() const {
+ return function_state_->loop_nesting_depth();
+ }
+
int GetNextFunctionLiteralId() { return ++function_literal_id_; }
int GetLastFunctionLiteralId() const { return function_literal_id_; }
@@ -340,14 +333,9 @@ class ParserBase {
Zone* zone() const { return zone_; }
protected:
- friend class v8::internal::ExpressionClassifier<ParserTypes<Impl>>;
-
- enum AllowRestrictedIdentifiers {
- kAllowRestrictedIdentifiers,
- kDontAllowRestrictedIdentifiers
- };
-
- enum LazyParsingResult { kLazyParsingComplete, kLazyParsingAborted };
+ friend class v8::internal::ExpressionScope<ParserTypes<Impl>>;
+ friend class v8::internal::ExpressionParsingScope<ParserTypes<Impl>>;
+ friend class v8::internal::ArrowHeadParsingScope<ParserTypes<Impl>>;
enum VariableDeclarationContext {
kStatementListItem,
@@ -356,7 +344,6 @@ class ParserBase {
};
class ClassLiteralChecker;
- class ObjectLiteralChecker;
// ---------------------------------------------------------------------------
// BlockState and FunctionState implement the parser's scope stack.
@@ -403,33 +390,6 @@ class ParserBase {
FunctionKind kind() const { return scope()->function_kind(); }
- void RewindDestructuringAssignments(int pos) {
- destructuring_assignments_to_rewrite_.Rewind(pos);
- }
-
- void AdoptDestructuringAssignmentsFromParentState(int pos) {
- const auto& outer_assignments =
- outer_function_state_->destructuring_assignments_to_rewrite_;
- DCHECK_GE(outer_assignments.size(), pos);
- auto it = outer_assignments.begin();
- it.Advance(pos);
- for (; it != outer_assignments.end(); ++it) {
- auto expr = *it;
- expr->set_scope(scope_);
- destructuring_assignments_to_rewrite_.push_back(expr);
- }
- outer_function_state_->RewindDestructuringAssignments(pos);
- }
-
- const ZoneChunkList<RewritableExpressionT>&
- destructuring_assignments_to_rewrite() const {
- return destructuring_assignments_to_rewrite_;
- }
-
- ZoneList<typename ExpressionClassifier::Error>* GetReportedErrorList() {
- return &reported_errors_;
- }
-
bool next_function_is_likely_called() const {
return next_function_is_likely_called_;
}
@@ -450,41 +410,50 @@ class ParserBase {
class FunctionOrEvalRecordingScope {
public:
explicit FunctionOrEvalRecordingScope(FunctionState* state)
- : state_(state) {
- prev_value_ = state->contains_function_or_eval_;
+ : state_and_prev_value_(state, state->contains_function_or_eval_) {
state->contains_function_or_eval_ = false;
}
~FunctionOrEvalRecordingScope() {
- bool found = state_->contains_function_or_eval_;
+ bool found = state_and_prev_value_->contains_function_or_eval_;
if (!found) {
- state_->contains_function_or_eval_ = prev_value_;
+ state_and_prev_value_->contains_function_or_eval_ =
+ state_and_prev_value_.GetPayload();
}
}
private:
- FunctionState* state_;
- bool prev_value_;
+ PointerWithPayload<FunctionState, bool, 1> state_and_prev_value_;
};
- private:
- void AddDestructuringAssignment(RewritableExpressionT expr) {
- destructuring_assignments_to_rewrite_.push_back(expr);
- }
+ class LoopScope {
+ public:
+ explicit LoopScope(FunctionState* function_state)
+ : function_state_(function_state) {
+ function_state_->loop_nesting_depth_++;
+ }
+ ~LoopScope() { function_state_->loop_nesting_depth_--; }
+
+ private:
+ FunctionState* function_state_;
+ };
+
+ int loop_nesting_depth() const { return loop_nesting_depth_; }
+
+ private:
// Properties count estimation.
int expected_property_count_;
// How many suspends are needed for this function.
int suspend_count_;
+ // How deeply nested we currently are in this function.
+ int loop_nesting_depth_ = 0;
+
FunctionState** function_state_stack_;
FunctionState* outer_function_state_;
DeclarationScope* scope_;
- ZoneChunkList<RewritableExpressionT> destructuring_assignments_to_rewrite_;
-
- ZoneList<typename ExpressionClassifier::Error> reported_errors_;
-
// A reason, if any, why this function should not be optimized.
BailoutReason dont_optimize_reason_;
@@ -503,12 +472,10 @@ class ParserBase {
};
struct DeclarationDescriptor {
- enum Kind { NORMAL, PARAMETER, FOR_EACH };
- Scope* scope;
VariableMode mode;
+ VariableKind kind;
int declaration_pos;
int initialization_pos;
- Kind declaration_kind;
};
struct DeclarationParsingResult {
@@ -538,18 +505,12 @@ class ParserBase {
struct CatchInfo {
public:
explicit CatchInfo(ParserBase* parser)
- : name(parser->impl()->NullIdentifier()),
- pattern(parser->impl()->NullExpression()),
- scope(nullptr),
- init_block(parser->impl()->NullStatement()),
- inner_block(parser->impl()->NullStatement()),
- bound_names(1, parser->zone()) {}
- IdentifierT name;
+ : pattern(parser->impl()->NullExpression()),
+ variable(nullptr),
+ scope(nullptr) {}
ExpressionT pattern;
+ Variable* variable;
Scope* scope;
- BlockT init_block;
- BlockT inner_block;
- ZonePtrList<const AstRawString> bound_names;
};
struct ForInfo {
@@ -578,29 +539,102 @@ class ParserBase {
has_name_static_property(false),
has_static_computed_names(false),
has_static_class_fields(false),
- has_instance_class_fields(false),
+ has_instance_members(false),
is_anonymous(false),
static_fields_scope(nullptr),
- instance_fields_scope(nullptr),
+ instance_members_scope(nullptr),
computed_field_count(0) {}
Variable* variable;
ExpressionT extends;
- typename Types::ClassPropertyList properties;
- typename Types::ClassPropertyList static_fields;
- typename Types::ClassPropertyList instance_fields;
+ ClassPropertyListT properties;
+ ClassPropertyListT static_fields;
+ ClassPropertyListT instance_fields;
FunctionLiteralT constructor;
bool has_seen_constructor;
bool has_name_static_property;
bool has_static_computed_names;
bool has_static_class_fields;
- bool has_instance_class_fields;
+ bool has_instance_members;
bool is_anonymous;
DeclarationScope* static_fields_scope;
- DeclarationScope* instance_fields_scope;
+ DeclarationScope* instance_members_scope;
int computed_field_count;
};
+ enum class PropertyPosition { kObjectLiteral, kClassLiteral };
+ struct ParsePropertyInfo {
+ public:
+ explicit ParsePropertyInfo(ParserBase* parser,
+ AccumulationScope* accumulation_scope = nullptr)
+ : accumulation_scope(accumulation_scope),
+ name(parser->impl()->NullIdentifier()),
+ position(PropertyPosition::kClassLiteral),
+ function_flags(ParseFunctionFlag::kIsNormal),
+ kind(ParsePropertyKind::kNotSet),
+ is_computed_name(false),
+ is_private(false),
+ is_static(false),
+ is_rest(false) {}
+
+ bool ParsePropertyKindFromToken(Token::Value token) {
+ // 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 = ParsePropertyKind::kValue;
+ return true;
+ case Token::COMMA:
+ kind = ParsePropertyKind::kShorthand;
+ return true;
+ case Token::RBRACE:
+ kind = ParsePropertyKind::kShorthandOrClassField;
+ return true;
+ case Token::ASSIGN:
+ kind = ParsePropertyKind::kAssign;
+ return true;
+ case Token::LPAREN:
+ kind = ParsePropertyKind::kMethod;
+ return true;
+ case Token::MUL:
+ case Token::SEMICOLON:
+ kind = ParsePropertyKind::kClassField;
+ return true;
+ default:
+ break;
+ }
+ return false;
+ }
+
+ AccumulationScope* accumulation_scope;
+ IdentifierT name;
+ PropertyPosition position;
+ ParseFunctionFlags function_flags;
+ ParsePropertyKind kind;
+ bool is_computed_name;
+ bool is_private;
+ bool is_static;
+ bool is_rest;
+ };
+
+ ClassLiteralProperty::Kind ClassPropertyKindFor(ParsePropertyKind kind) {
+ switch (kind) {
+ case ParsePropertyKind::kAccessorGetter:
+ return ClassLiteralProperty::GETTER;
+ case ParsePropertyKind::kAccessorSetter:
+ return ClassLiteralProperty::SETTER;
+ case ParsePropertyKind::kMethod:
+ return ClassLiteralProperty::METHOD;
+ case ParsePropertyKind::kClassField:
+ return ClassLiteralProperty::FIELD;
+ default:
+ // Only returns for deterministic kinds
+ UNREACHABLE();
+ }
+ }
+
const AstRawString* ClassFieldVariableName(AstValueFactory* ast_value_factory,
int index) {
std::string name = ".class-field-" + std::to_string(index);
@@ -667,6 +701,22 @@ class ParserBase {
return scope()->GetClosureScope();
}
+ VariableProxy* NewRawVariable(const AstRawString* name, int pos) {
+ return factory()->ast_node_factory()->NewVariableProxy(
+ name, NORMAL_VARIABLE, pos);
+ }
+
+ VariableProxy* NewUnresolved(const AstRawString* name) {
+ return scope()->NewUnresolved(factory()->ast_node_factory(), name,
+ scanner()->location().beg_pos);
+ }
+
+ VariableProxy* NewUnresolved(const AstRawString* name, int begin_pos,
+ VariableKind kind = NORMAL_VARIABLE) {
+ return scope()->NewUnresolved(factory()->ast_node_factory(), name,
+ begin_pos, kind);
+ }
+
Scanner* scanner() const { return scanner_; }
AstValueFactory* ast_value_factory() const { return ast_value_factory_; }
int position() const { return scanner_->location().beg_pos; }
@@ -676,14 +726,18 @@ class ParserBase {
bool stack_overflow() const {
return pending_error_handler()->stack_overflow();
}
- void set_stack_overflow() { pending_error_handler()->set_stack_overflow(); }
+ void set_stack_overflow() {
+ scanner_->set_parser_error();
+ pending_error_handler()->set_stack_overflow();
+ }
+ void CheckStackOverflow() {
+ // Any further calls to Next or peek will return the illegal token.
+ if (GetCurrentStackPosition() < stack_limit_) set_stack_overflow();
+ }
int script_id() { return script_id_; }
void set_script_id(int id) { script_id_ = id; }
- V8_INLINE Token::Value peek() {
- if (stack_overflow()) return Token::ILLEGAL;
- return scanner()->peek();
- }
+ V8_INLINE Token::Value peek() { return scanner()->peek(); }
// Returns the position past the following semicolon (if it exists), and the
// position past the end of the current token otherwise.
@@ -691,33 +745,19 @@ class ParserBase {
return (peek() == Token::SEMICOLON) ? peek_end_position() : end_position();
}
- V8_INLINE Token::Value PeekAhead() {
- if (stack_overflow()) return Token::ILLEGAL;
- return scanner()->PeekAhead();
- }
+ V8_INLINE Token::Value PeekAhead() { return scanner()->PeekAhead(); }
- V8_INLINE Token::Value Next() {
- if (stack_overflow()) return Token::ILLEGAL;
- {
- if (GetCurrentStackPosition() < stack_limit_) {
- // Any further calls to Next or peek will return the illegal token.
- // The current call must return the next token, which might already
- // have been peek'ed.
- set_stack_overflow();
- }
- }
- return scanner()->Next();
- }
+ V8_INLINE Token::Value Next() { return scanner()->Next(); }
- void Consume(Token::Value token) {
- Token::Value next = Next();
+ V8_INLINE void Consume(Token::Value token) {
+ Token::Value next = scanner()->Next();
USE(next);
USE(token);
- DCHECK_EQ(next, token);
+ DCHECK_IMPLIES(!has_error(), next == token);
}
- bool Check(Token::Value token) {
- Token::Value next = peek();
+ V8_INLINE bool Check(Token::Value token) {
+ Token::Value next = scanner()->peek();
if (next == token) {
Consume(next);
return true;
@@ -725,28 +765,26 @@ class ParserBase {
return false;
}
- void Expect(Token::Value token, bool* ok) {
+ void Expect(Token::Value token) {
Token::Value next = Next();
- if (next != token) {
+ if (V8_UNLIKELY(next != token)) {
ReportUnexpectedToken(next);
- *ok = false;
}
}
- void ExpectSemicolon(bool* ok) {
+ void ExpectSemicolon() {
// Check for automatic semicolon insertion according to
// the rules given in ECMA-262, section 7.9, page 21.
Token::Value tok = peek();
- if (tok == Token::SEMICOLON) {
+ if (V8_LIKELY(tok == Token::SEMICOLON)) {
Next();
return;
}
- if (scanner()->HasLineTerminatorBeforeNext() || tok == Token::RBRACE ||
- tok == Token::EOS) {
+ if (V8_LIKELY(scanner()->HasLineTerminatorBeforeNext() ||
+ Token::IsAutoSemicolon(tok))) {
return;
}
- *ok = false;
if (scanner()->current_token() == Token::AWAIT && !is_async_function()) {
ReportMessageAt(scanner()->location(),
MessageTemplate::kAwaitNotInAsyncFunction, kSyntaxError);
@@ -756,38 +794,28 @@ class ParserBase {
ReportUnexpectedToken(Next());
}
- // Dummy functions, just useful as arguments to CHECK_OK_CUSTOM.
- static void Void() {}
- template <typename T>
- static T Return(T result) {
- return result;
- }
-
bool peek_any_identifier() { return Token::IsAnyIdentifier(peek()); }
- bool CheckContextualKeyword(Token::Value token) {
- if (PeekContextualKeyword(token)) {
+ bool PeekContextualKeyword(const AstRawString* name) {
+ return peek() == Token::IDENTIFIER &&
+ scanner()->NextSymbol(ast_value_factory()) == name;
+ }
+
+ bool CheckContextualKeyword(const AstRawString* name) {
+ if (PeekContextualKeyword(name)) {
Consume(Token::IDENTIFIER);
return true;
}
return false;
}
- bool PeekContextualKeyword(Token::Value token) {
- DCHECK(Token::IsContextualKeyword(token));
- return peek() == Token::IDENTIFIER &&
- scanner()->next_contextual_token() == token;
- }
-
- void ExpectMetaProperty(Token::Value property_name, const char* full_name,
- int pos, bool* ok);
+ void ExpectMetaProperty(const AstRawString* property_name,
+ const char* full_name, int pos);
- void ExpectContextualKeyword(Token::Value token, bool* ok) {
- DCHECK(Token::IsContextualKeyword(token));
- Expect(Token::IDENTIFIER, CHECK_OK_CUSTOM(Void));
- if (scanner()->current_contextual_token() != token) {
+ void ExpectContextualKeyword(const AstRawString* name) {
+ Expect(Token::IDENTIFIER);
+ if (V8_UNLIKELY(scanner()->CurrentSymbol(ast_value_factory()) != name)) {
ReportUnexpectedToken(scanner()->current_token());
- *ok = false;
}
}
@@ -795,7 +823,7 @@ class ParserBase {
if (Check(Token::IN)) {
*visit_mode = ForEachStatement::ENUMERATE;
return true;
- } else if (CheckContextualKeyword(Token::OF)) {
+ } else if (CheckContextualKeyword(ast_value_factory()->of_string())) {
*visit_mode = ForEachStatement::ITERATE;
return true;
}
@@ -803,23 +831,23 @@ class ParserBase {
}
bool PeekInOrOf() {
- return peek() == Token::IN || PeekContextualKeyword(Token::OF);
+ return peek() == Token::IN ||
+ PeekContextualKeyword(ast_value_factory()->of_string());
}
// Checks whether an octal literal was last seen between beg_pos and end_pos.
// Only called for strict mode strings.
- void CheckStrictOctalLiteral(int beg_pos, int end_pos, bool* ok) {
+ void CheckStrictOctalLiteral(int beg_pos, int end_pos) {
Scanner::Location octal = scanner()->octal_position();
if (octal.IsValid() && beg_pos <= octal.beg_pos &&
octal.end_pos <= end_pos) {
- MessageTemplate::Template message = scanner()->octal_message();
+ MessageTemplate message = scanner()->octal_message();
DCHECK_NE(message, MessageTemplate::kNone);
impl()->ReportMessageAt(octal, message);
scanner()->clear_octal_position();
if (message == MessageTemplate::kStrictDecimalWithLeadingZero) {
impl()->CountUsage(v8::Isolate::kDecimalWithLeadingZeroInStrictMode);
}
- *ok = false;
}
}
@@ -827,29 +855,29 @@ class ParserBase {
// appears in the current template literal token. In the presence of such,
// either returns false or reports an error, depending on should_throw.
// Otherwise returns true.
- inline bool CheckTemplateEscapes(bool should_throw, bool* ok) {
- DCHECK(scanner()->current_token() == Token::TEMPLATE_SPAN ||
- scanner()->current_token() == Token::TEMPLATE_TAIL);
- if (!scanner()->has_invalid_template_escape()) {
- return true;
- }
+ inline bool CheckTemplateEscapes(bool should_throw) {
+ DCHECK(Token::IsTemplate(scanner()->current_token()));
+ if (!scanner()->has_invalid_template_escape()) return true;
// Handle error case(s)
if (should_throw) {
impl()->ReportMessageAt(scanner()->invalid_template_escape_location(),
scanner()->invalid_template_escape_message());
- *ok = false;
}
- return false;
+ scanner()->clear_invalid_template_escape_message();
+ return should_throw;
}
- void CheckDestructuringElement(ExpressionT element, int beg_pos, int end_pos);
+ ExpressionT ParsePossibleDestructuringSubPattern(AccumulationScope* scope);
+ void ClassifyParameter(IdentifierT parameter, int beg_pos, int end_pos);
+ void ClassifyArrowParameter(AccumulationScope* accumulation_scope,
+ int position, ExpressionT parameter);
// Checking the name of a function literal. This has to be done after parsing
// the function, since the function can declare itself strict.
void CheckFunctionName(LanguageMode language_mode, IdentifierT function_name,
FunctionNameValidity function_name_validity,
- const Scanner::Location& function_name_loc, bool* ok) {
+ const Scanner::Location& function_name_loc) {
if (impl()->IsNull(function_name)) return;
if (function_name_validity == kSkipFunctionNameCheck) return;
// The function name needs to be checked in strict mode.
@@ -858,24 +886,15 @@ class ParserBase {
if (impl()->IsEvalOrArguments(function_name)) {
impl()->ReportMessageAt(function_name_loc,
MessageTemplate::kStrictEvalArguments);
- *ok = false;
return;
}
if (function_name_validity == kFunctionNameIsStrictReserved) {
impl()->ReportMessageAt(function_name_loc,
MessageTemplate::kUnexpectedStrictReserved);
- *ok = false;
return;
}
}
- // Determine precedence of given token.
- static int Precedence(Token::Value token, bool accept_IN) {
- if (token == Token::IN && !accept_IN)
- return 0; // 0 precedence will terminate binary expression parsing
- return Token::Precedence(token);
- }
-
typename Types::Factory* factory() { return &ast_node_factory_; }
DeclarationScope* GetReceiverScope() const {
@@ -907,405 +926,280 @@ class ParserBase {
}
// Report syntax errors.
- void ReportMessage(MessageTemplate::Template message) {
+ V8_NOINLINE void ReportMessage(MessageTemplate message) {
Scanner::Location source_location = scanner()->location();
impl()->ReportMessageAt(source_location, message,
static_cast<const char*>(nullptr), kSyntaxError);
}
template <typename T>
- void ReportMessage(MessageTemplate::Template message, T arg,
- ParseErrorType error_type = kSyntaxError) {
+ V8_NOINLINE void ReportMessage(MessageTemplate message, T arg,
+ ParseErrorType error_type = kSyntaxError) {
Scanner::Location source_location = scanner()->location();
impl()->ReportMessageAt(source_location, message, arg, error_type);
}
- void ReportMessageAt(Scanner::Location location,
- MessageTemplate::Template message,
- ParseErrorType error_type) {
+ V8_NOINLINE void ReportMessageAt(Scanner::Location location,
+ MessageTemplate message,
+ ParseErrorType error_type) {
impl()->ReportMessageAt(location, message,
static_cast<const char*>(nullptr), error_type);
}
- void GetUnexpectedTokenMessage(
- Token::Value token, MessageTemplate::Template* message,
- Scanner::Location* location, const char** arg,
- MessageTemplate::Template default_ = MessageTemplate::kUnexpectedToken);
+ V8_NOINLINE void ReportUnexpectedToken(Token::Value token);
- void ReportUnexpectedToken(Token::Value token);
- void ReportUnexpectedTokenAt(
- Scanner::Location location, Token::Value token,
- MessageTemplate::Template message = MessageTemplate::kUnexpectedToken);
-
- void ReportClassifierError(
- const typename ExpressionClassifier::Error& error) {
- if (classifier()->does_error_reporting()) {
- impl()->ReportMessageAt(error.location, error.message, error.arg);
- } else {
- impl()->ReportUnidentifiableError();
- }
+ void ValidateFormalParameters(LanguageMode language_mode,
+ const FormalParametersT& parameters,
+ bool allow_duplicates) {
+ if (!allow_duplicates) parameters.ValidateDuplicate(impl());
+ if (is_strict(language_mode)) parameters.ValidateStrictMode(impl());
}
- void ValidateExpression(bool* ok) {
- if (!classifier()->is_valid_expression()) {
- ReportClassifierError(classifier()->expression_error());
- *ok = false;
- }
+ V8_INLINE IdentifierT ParseAndClassifyIdentifier(Token::Value token);
+ // Parses an identifier or a strict mode future reserved word. Allows passing
+ // in function_kind for the case of parsing the identifier in a function
+ // expression, where the relevant "function_kind" bit is of the function being
+ // parsed, not the containing function.
+ V8_INLINE IdentifierT ParseIdentifier(FunctionKind function_kind);
+ V8_INLINE IdentifierT ParseIdentifier() {
+ return ParseIdentifier(function_state_->kind());
}
+ // Same as above but additionally disallows 'eval' and 'arguments' in strict
+ // mode.
+ IdentifierT ParseNonRestrictedIdentifier();
- void ValidateFormalParameterInitializer(bool* ok) {
- if (!classifier()->is_valid_formal_parameter_initializer()) {
- ReportClassifierError(classifier()->formal_parameter_initializer_error());
- *ok = false;
- }
- }
+ V8_INLINE IdentifierT ParsePropertyName();
- void ValidateBindingPattern(bool* ok) {
- if (!classifier()->is_valid_binding_pattern()) {
- ReportClassifierError(classifier()->binding_pattern_error());
- *ok = false;
- }
- }
+ ExpressionT ParsePropertyOrPrivatePropertyName();
- void ValidateAssignmentPattern(bool* ok) {
- if (!classifier()->is_valid_assignment_pattern()) {
- ReportClassifierError(classifier()->assignment_pattern_error());
- *ok = false;
- }
- }
+ ExpressionT ParseRegExpLiteral();
- void ValidateFormalParameters(LanguageMode language_mode,
- bool allow_duplicates, bool* ok) {
- if (!allow_duplicates &&
- !classifier()->is_valid_formal_parameter_list_without_duplicates()) {
- ReportClassifierError(classifier()->duplicate_formal_parameter_error());
- *ok = false;
- } else if (is_strict(language_mode) &&
- !classifier()->is_valid_strict_mode_formal_parameters()) {
- ReportClassifierError(classifier()->strict_mode_formal_parameter_error());
- *ok = false;
- }
- }
-
- bool IsValidArrowFormalParametersStart(Token::Value token) {
- return Token::IsAnyIdentifier(token) || token == Token::LPAREN;
- }
-
- void ValidateArrowFormalParameters(ExpressionT expr,
- bool parenthesized_formals, bool is_async,
- bool* ok) {
- if (classifier()->is_valid_binding_pattern()) {
- // A simple arrow formal parameter: IDENTIFIER => BODY.
- if (!impl()->IsIdentifier(expr)) {
- impl()->ReportMessageAt(scanner()->location(),
- MessageTemplate::kUnexpectedToken,
- Token::String(scanner()->current_token()));
- *ok = false;
- }
- } else if (!classifier()->is_valid_arrow_formal_parameters()) {
- // If after parsing the expr, we see an error but the expression is
- // neither a valid binding pattern nor a valid parenthesized formal
- // parameter list, show the "arrow formal parameters" error if the formals
- // started with a parenthesis, and the binding pattern error otherwise.
- const typename ExpressionClassifier::Error& error =
- parenthesized_formals ? classifier()->arrow_formal_parameters_error()
- : classifier()->binding_pattern_error();
- ReportClassifierError(error);
- *ok = false;
- }
- if (is_async && !classifier()->is_valid_async_arrow_formal_parameters()) {
- const typename ExpressionClassifier::Error& error =
- classifier()->async_arrow_formal_parameters_error();
- ReportClassifierError(error);
- *ok = false;
- }
- }
-
- void ValidateLetPattern(bool* ok) {
- if (!classifier()->is_valid_let_pattern()) {
- ReportClassifierError(classifier()->let_pattern_error());
- *ok = false;
- }
- }
-
- void BindingPatternUnexpectedToken() {
- MessageTemplate::Template message = MessageTemplate::kUnexpectedToken;
- const char* arg;
- Scanner::Location location = scanner()->peek_location();
- GetUnexpectedTokenMessage(peek(), &message, &location, &arg);
- classifier()->RecordBindingPatternError(location, message, arg);
- }
-
- void ArrowFormalParametersUnexpectedToken() {
- MessageTemplate::Template message = MessageTemplate::kUnexpectedToken;
- const char* arg;
- Scanner::Location location = scanner()->peek_location();
- GetUnexpectedTokenMessage(peek(), &message, &location, &arg);
- classifier()->RecordArrowFormalParametersError(location, message, arg);
- }
-
- // Recursive descent functions.
- // All ParseXXX functions take as the last argument an *ok parameter
- // which is set to false if parsing failed; it is unchanged otherwise.
- // By making the 'exception handling' explicit, we are forced to check
- // for failure at the call sites. The family of CHECK_OK* macros can
- // be useful for this.
-
- // Parses an identifier that is valid for the current scope, in particular it
- // fails on strict mode future reserved keywords in a strict scope. If
- // allow_eval_or_arguments is kAllowEvalOrArguments, we allow "eval" or
- // "arguments" as identifier even in strict mode (this is needed in cases like
- // "var foo = eval;").
- IdentifierT ParseIdentifier(AllowRestrictedIdentifiers, bool* ok);
- IdentifierT ParseAndClassifyIdentifier(bool* ok);
- // Parses an identifier or a strict mode future reserved word, and indicate
- // whether it is strict mode future reserved. Allows passing in function_kind
- // for the case of parsing the identifier in a function expression, where the
- // relevant "function_kind" bit is of the function being parsed, not the
- // containing function.
- IdentifierT ParseIdentifierOrStrictReservedWord(FunctionKind function_kind,
- bool* is_strict_reserved,
- bool* is_await, bool* ok);
- IdentifierT ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved,
- bool* is_await, bool* ok) {
- return ParseIdentifierOrStrictReservedWord(
- function_state_->kind(), is_strict_reserved, is_await, ok);
- }
-
- V8_INLINE IdentifierT ParseIdentifierName(bool* ok);
-
- ExpressionT ParseIdentifierNameOrPrivateName(bool* ok);
-
- ExpressionT ParseRegExpLiteral(bool* ok);
-
- ExpressionT ParseBindingPattern(bool* ok);
- ExpressionT ParsePrimaryExpression(bool* is_async, bool* ok);
-
- // Use when parsing an expression that is known to not be a pattern or part
- // of a pattern.
- 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.
- // It should be used whenever we're parsing something with the "cover"
- // grammar that recognizes both patterns and non-patterns (which roughly
- // corresponds to what's inside the parentheses generated by the symbol
+ ExpressionT ParseBindingPattern();
+ ExpressionT ParsePrimaryExpression();
+
+ // Use when parsing an expression that is known to not be a pattern or part of
+ // a pattern.
+ V8_INLINE ExpressionT ParseExpression();
+ V8_INLINE ExpressionT ParseAssignmentExpression();
+
+ // These methods do not wrap the parsing of the expression inside a new
+ // expression_scope; they use the outer expression_scope instead. They should
+ // be used whenever we're parsing something with the "cover" grammar that
+ // recognizes both patterns and non-patterns (which roughly corresponds to
+ // what's inside the parentheses generated by the symbol
// "CoverParenthesizedExpressionAndArrowParameterList" in the ES 2017
// specification).
- ExpressionT ParseExpressionCoverGrammar(bool accept_IN, bool* ok);
+ ExpressionT ParseExpressionCoverGrammar();
+ ExpressionT ParseAssignmentExpressionCoverGrammar();
+
+ ExpressionT ParseArrowParametersWithRest(ExpressionListT* list,
+ AccumulationScope* scope);
- ExpressionT ParseArrayLiteral(bool* ok);
+ ExpressionT ParseArrayLiteral();
inline static bool IsAccessor(ParsePropertyKind kind) {
return IsInRange(kind, ParsePropertyKind::kAccessorGetter,
ParsePropertyKind::kAccessorSetter);
}
- ExpressionT ParsePropertyName(IdentifierT* name, ParsePropertyKind* kind,
- ParseFunctionFlags* flags,
- bool* is_computed_name, bool* ok);
- ExpressionT ParseObjectLiteral(bool* ok);
+ ExpressionT ParseProperty(ParsePropertyInfo* prop_info);
+ ExpressionT ParseObjectLiteral();
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, int beg_pos,
- bool is_static, bool* ok);
+ ClassInfo* class_info, ParsePropertyInfo* prop_info, bool has_extends);
+ void CheckClassFieldName(IdentifierT name, bool is_static);
+ void CheckClassMethodName(IdentifierT name, ParsePropertyKind type,
+ ParseFunctionFlags flags, bool is_static,
+ bool* has_seen_constructor);
+ ExpressionT ParseMemberInitializer(ClassInfo* class_info, int beg_pos,
+ bool is_static);
ObjectLiteralPropertyT ParseObjectPropertyDefinition(
- ObjectLiteralChecker* checker, bool* is_computed_name,
- bool* is_rest_property, bool* ok);
- ExpressionListT ParseArguments(Scanner::Location* first_spread_pos,
- bool maybe_arrow,
- bool* is_simple_parameter_list, bool* ok);
- ExpressionListT ParseArguments(Scanner::Location* first_spread_pos,
- bool* 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 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 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);
-
- // `rewritable_length`: length of the destructuring_assignments_to_rewrite()
- // queue in the parent function state, prior to parsing of formal parameters.
- // If the arrow function is lazy, any items added during formal parameter
- // parsing are removed from the queue.
- ExpressionT ParseArrowFunctionLiteral(bool accept_IN,
- const FormalParametersT& parameters,
- int rewritable_length, bool* ok);
- void ParseAsyncFunctionBody(Scope* scope, StatementListT body, bool* ok);
- ExpressionT ParseAsyncFunctionLiteral(bool* ok);
+ ParsePropertyInfo* prop_info, bool* has_seen_proto);
+ void ParseArguments(
+ ExpressionListT* args, bool* has_spread,
+ ParsingArrowHeadFlag maybe_arrow = kCertainlyNotArrowHead);
+
+ ExpressionT ParseYieldExpression();
+ V8_INLINE ExpressionT ParseConditionalExpression();
+ ExpressionT ParseConditionalContinuation(ExpressionT expression, int pos);
+ ExpressionT ParseBinaryContinuation(ExpressionT x, int prec, int prec1);
+ V8_INLINE ExpressionT ParseBinaryExpression(int prec);
+ ExpressionT ParseUnaryOrPrefixExpression();
+ ExpressionT ParseAwaitExpression();
+ V8_INLINE ExpressionT ParseUnaryExpression();
+ V8_INLINE ExpressionT ParsePostfixExpression();
+ V8_INLINE ExpressionT ParseLeftHandSideExpression();
+ ExpressionT ParseLeftHandSideContinuation(ExpressionT expression);
+ ExpressionT ParseMemberWithPresentNewPrefixesExpression();
+ V8_INLINE ExpressionT ParseMemberWithNewPrefixesExpression();
+ ExpressionT ParseFunctionExpression();
+ V8_INLINE ExpressionT ParseMemberExpression();
+ V8_INLINE ExpressionT
+ ParseMemberExpressionContinuation(ExpressionT expression) {
+ if (!Token::IsMember(peek())) return expression;
+ return DoParseMemberExpressionContinuation(expression);
+ }
+ ExpressionT DoParseMemberExpressionContinuation(ExpressionT expression);
+
+ ExpressionT ParseArrowFunctionLiteral(const FormalParametersT& parameters);
+ void ParseAsyncFunctionBody(Scope* scope, StatementListT* body);
+ ExpressionT ParseAsyncFunctionLiteral();
ExpressionT ParseClassLiteral(IdentifierT name,
Scanner::Location class_name_location,
bool name_is_strict_reserved,
- int class_token_pos, bool* ok);
- ExpressionT ParseTemplateLiteral(ExpressionT tag, int start, bool tagged,
- bool* ok);
- ExpressionT ParseSuperExpression(bool is_new, bool* ok);
- ExpressionT ParseImportExpressions(bool* ok);
- ExpressionT ParseNewTargetExpression(bool* ok);
-
- V8_INLINE void ParseFormalParameter(FormalParametersT* parameters, bool* ok);
- void ParseFormalParameterList(FormalParametersT* parameters, bool* ok);
+ int class_token_pos);
+ ExpressionT ParseTemplateLiteral(ExpressionT tag, int start, bool tagged);
+ ExpressionT ParseSuperExpression(bool is_new);
+ ExpressionT ParseImportExpressions();
+ ExpressionT ParseNewTargetExpression();
+
+ V8_INLINE void ParseFormalParameter(FormalParametersT* parameters);
+ void ParseFormalParameterList(FormalParametersT* parameters);
void CheckArityRestrictions(int param_count, FunctionKind function_type,
bool has_rest, int formals_start_pos,
- int formals_end_pos, bool* ok);
+ int formals_end_pos);
- BlockT ParseVariableDeclarations(VariableDeclarationContext var_context,
- DeclarationParsingResult* parsing_result,
- ZonePtrList<const AstRawString>* names,
- bool* ok);
+ void ParseVariableDeclarations(VariableDeclarationContext var_context,
+ DeclarationParsingResult* parsing_result,
+ ZonePtrList<const AstRawString>* names);
StatementT ParseAsyncFunctionDeclaration(
- ZonePtrList<const AstRawString>* names, bool default_export, bool* ok);
- StatementT ParseFunctionDeclaration(bool* ok);
+ ZonePtrList<const AstRawString>* names, bool default_export);
+ StatementT ParseFunctionDeclaration();
StatementT ParseHoistableDeclaration(ZonePtrList<const AstRawString>* names,
- bool default_export, bool* ok);
+ bool default_export);
StatementT ParseHoistableDeclaration(int pos, ParseFunctionFlags flags,
ZonePtrList<const AstRawString>* names,
- bool default_export, bool* ok);
+ bool default_export);
StatementT ParseClassDeclaration(ZonePtrList<const AstRawString>* names,
- bool default_export, bool* ok);
- StatementT ParseNativeDeclaration(bool* ok);
+ bool default_export);
+ StatementT ParseNativeDeclaration();
// 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,
+ void ParseFunctionBody(StatementListT* body, IdentifierT function_name,
int pos, const FormalParametersT& parameters,
FunctionKind kind,
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
- // definition of "long and trivial" is:
- // - over kLazyParseTrialLimit statements
- // - all starting with an identifier (i.e., no if, for, while, etc.)
- static const int kLazyParseTrialLimit = 200;
+ FunctionBodyType body_type);
// TODO(nikolaos, marja): The first argument should not really be passed
// by value. The method is expected to add the parsed statements to the
// list. This works because in the case of the parser, StatementListT is
// a pointer whereas the preparser does not really modify the body.
- V8_INLINE void ParseStatementList(StatementListT body, Token::Value end_token,
- bool* ok) {
- LazyParsingResult result = ParseStatementList(body, end_token, false, ok);
- USE(result);
- DCHECK_EQ(result, kLazyParsingComplete);
- }
- V8_INLINE LazyParsingResult ParseStatementList(StatementListT body,
- Token::Value end_token,
- bool may_abort, bool* ok);
- StatementT ParseStatementListItem(bool* ok);
+ V8_INLINE void ParseStatementList(StatementListT* body,
+ Token::Value end_token);
+ StatementT ParseStatementListItem();
StatementT ParseStatement(ZonePtrList<const AstRawString>* labels,
- ZonePtrList<const AstRawString>* own_labels,
- bool* ok) {
+ ZonePtrList<const AstRawString>* own_labels) {
return ParseStatement(labels, own_labels,
- kDisallowLabelledFunctionStatement, ok);
+ kDisallowLabelledFunctionStatement);
}
StatementT ParseStatement(ZonePtrList<const AstRawString>* labels,
ZonePtrList<const AstRawString>* own_labels,
- AllowLabelledFunctionStatement allow_function,
- bool* ok);
- BlockT ParseBlock(ZonePtrList<const AstRawString>* labels, bool* ok);
+ AllowLabelledFunctionStatement allow_function);
+ BlockT ParseBlock(ZonePtrList<const AstRawString>* labels);
// Parse a SubStatement in strict mode, or with an extra block scope in
// sloppy mode to handle
// ES#sec-functiondeclarations-in-ifstatement-statement-clauses
- StatementT ParseScopedStatement(ZonePtrList<const AstRawString>* labels,
- bool* ok);
+ StatementT ParseScopedStatement(ZonePtrList<const AstRawString>* labels);
StatementT ParseVariableStatement(VariableDeclarationContext var_context,
- ZonePtrList<const AstRawString>* names,
- bool* ok);
+ ZonePtrList<const AstRawString>* names);
// Magical syntax support.
- ExpressionT ParseV8Intrinsic(bool* ok);
+ ExpressionT ParseV8Intrinsic();
- ExpressionT ParseDoExpression(bool* ok);
-
- StatementT ParseDebuggerStatement(bool* ok);
+ StatementT ParseDebuggerStatement();
StatementT ParseExpressionOrLabelledStatement(
ZonePtrList<const AstRawString>* labels,
ZonePtrList<const AstRawString>* own_labels,
- AllowLabelledFunctionStatement allow_function, bool* ok);
- StatementT ParseIfStatement(ZonePtrList<const AstRawString>* labels,
- bool* ok);
- StatementT ParseContinueStatement(bool* ok);
- StatementT ParseBreakStatement(ZonePtrList<const AstRawString>* labels,
- bool* ok);
- StatementT ParseReturnStatement(bool* ok);
- StatementT ParseWithStatement(ZonePtrList<const AstRawString>* labels,
- bool* ok);
+ AllowLabelledFunctionStatement allow_function);
+ StatementT ParseIfStatement(ZonePtrList<const AstRawString>* labels);
+ StatementT ParseContinueStatement();
+ StatementT ParseBreakStatement(ZonePtrList<const AstRawString>* labels);
+ StatementT ParseReturnStatement();
+ StatementT ParseWithStatement(ZonePtrList<const AstRawString>* labels);
StatementT ParseDoWhileStatement(ZonePtrList<const AstRawString>* labels,
- ZonePtrList<const AstRawString>* own_labels,
- bool* ok);
+ ZonePtrList<const AstRawString>* own_labels);
StatementT ParseWhileStatement(ZonePtrList<const AstRawString>* labels,
- ZonePtrList<const AstRawString>* own_labels,
- bool* ok);
- StatementT ParseThrowStatement(bool* ok);
- StatementT ParseSwitchStatement(ZonePtrList<const AstRawString>* labels,
- bool* ok);
- V8_INLINE StatementT ParseTryStatement(bool* ok);
+ ZonePtrList<const AstRawString>* own_labels);
+ StatementT ParseThrowStatement();
+ StatementT ParseSwitchStatement(ZonePtrList<const AstRawString>* labels);
+ V8_INLINE StatementT ParseTryStatement();
StatementT ParseForStatement(ZonePtrList<const AstRawString>* labels,
- ZonePtrList<const AstRawString>* own_labels,
- bool* ok);
+ ZonePtrList<const AstRawString>* own_labels);
StatementT ParseForEachStatementWithDeclarations(
int stmt_pos, ForInfo* for_info, ZonePtrList<const AstRawString>* labels,
- ZonePtrList<const AstRawString>* own_labels, Scope* inner_block_scope,
- bool* ok);
+ ZonePtrList<const AstRawString>* own_labels, Scope* inner_block_scope);
StatementT ParseForEachStatementWithoutDeclarations(
int stmt_pos, ExpressionT expression, int lhs_beg_pos, int lhs_end_pos,
ForInfo* for_info, ZonePtrList<const AstRawString>* labels,
- ZonePtrList<const AstRawString>* own_labels, bool* ok);
+ ZonePtrList<const AstRawString>* own_labels);
// Parse a C-style for loop: 'for (<init>; <cond>; <next>) { ... }'
// "for (<init>;" is assumed to have been parser already.
ForStatementT ParseStandardForLoop(
int stmt_pos, ZonePtrList<const AstRawString>* labels,
ZonePtrList<const AstRawString>* own_labels, ExpressionT* cond,
- StatementT* next, StatementT* body, bool* ok);
+ StatementT* next, StatementT* body);
// Same as the above, but handles those cases where <init> is a
// lexical variable declaration.
StatementT ParseStandardForLoopWithLexicalDeclarations(
int stmt_pos, StatementT init, ForInfo* for_info,
ZonePtrList<const AstRawString>* labels,
- ZonePtrList<const AstRawString>* own_labels, bool* ok);
- StatementT ParseForAwaitStatement(ZonePtrList<const AstRawString>* labels,
- ZonePtrList<const AstRawString>* own_labels,
- bool* ok);
+ ZonePtrList<const AstRawString>* own_labels);
+ StatementT ParseForAwaitStatement(
+ ZonePtrList<const AstRawString>* labels,
+ ZonePtrList<const AstRawString>* own_labels);
+
+ V8_INLINE bool IsLet(const AstRawString* identifier) const {
+ return identifier == ast_value_factory()->let_string();
+ }
+
+ void DesugarBindingInForEachStatement(ForInfo* for_info, BlockT* body_block,
+ ExpressionT* each_variable) {
+ // Annex B.3.5 prohibits the form
+ // `try {} catch(e) { for (var e of {}); }`
+ // So if we are parsing a statement like `for (var ... of ...)`
+ // we need to walk up the scope chain and look for catch scopes
+ // which have a simple binding, then compare their binding against
+ // all of the names declared in the init of the for-of we're
+ // parsing.
+ bool is_for_var_of =
+ for_info->mode == ForEachStatement::ITERATE &&
+ for_info->parsing_result.descriptor.mode == VariableMode::kVar;
+
+ if (is_for_var_of) {
+ Scope* scope = this->scope();
+ while (scope != nullptr && !scope->is_declaration_scope()) {
+ if (scope->is_catch_scope()) {
+ auto name = scope->catch_variable()->raw_name();
+ // If it's a simple binding and the name is declared in the for loop.
+ if (name != ast_value_factory()->dot_catch_string() &&
+ for_info->bound_names.Contains(name)) {
+ impl()->ReportMessageAt(for_info->parsing_result.bindings_loc,
+ MessageTemplate::kVarRedeclaration, name);
+ }
+ }
+ scope = scope->outer_scope();
+ }
+ }
+
+ impl()->DesugarBindingInForEachStatement(for_info, body_block,
+ each_variable);
+ }
bool IsNextLetKeyword();
- bool IsTrivialExpression();
// Checks if the expression is a valid reference expression (e.g., on the
// left-hand side of assignments). Although ruled out by ECMA as early errors,
// we allow calls for web compatibility and rewrite them to a runtime throw.
- ExpressionT CheckAndRewriteReferenceExpression(
- ExpressionT expression, int beg_pos, int end_pos,
- MessageTemplate::Template message, bool* ok);
- ExpressionT CheckAndRewriteReferenceExpression(
- ExpressionT expression, int beg_pos, int end_pos,
- MessageTemplate::Template message, ParseErrorType type, bool* ok);
+ ExpressionT RewriteInvalidReferenceExpression(
+ ExpressionT expression, int beg_pos, int end_pos, MessageTemplate message,
+ ParseErrorType type = kReferenceError);
bool IsValidReferenceExpression(ExpressionT expression);
@@ -1318,33 +1212,6 @@ class ParserBase {
return true;
}
- bool IsValidPattern(ExpressionT expression) {
- return expression->IsObjectLiteral() || expression->IsArrayLiteral();
- }
-
- // Due to hoisting, the value of a 'var'-declared variable may actually change
- // even if the code contains only the "initial" assignment, namely when that
- // assignment occurs inside a loop. For example:
- //
- // let i = 10;
- // do { var x = i } while (i--):
- //
- // As a simple and very conservative approximation of this, we explicitly mark
- // as maybe-assigned any non-lexical variable whose initializing "declaration"
- // does not syntactically occur in the function scope. (In the example above,
- // it occurs in a block scope.)
- //
- // Note that non-lexical variables include temporaries, which may also get
- // assigned inside a loop due to the various rewritings that the parser
- // performs.
- //
- // This also handles marking of loop variables in for-in and for-of loops,
- // as determined by declaration_kind.
- //
- static void MarkLoopVariableAsAssigned(
- Scope* scope, Variable* var,
- typename DeclarationDescriptor::Kind declaration_kind);
-
FunctionKind FunctionKindForImpl(bool is_method, ParseFunctionFlags flags) {
static const FunctionKind kFunctionKinds[][2][2] = {
{
@@ -1422,106 +1289,64 @@ class ParserBase {
return factory()->NewReturnStatement(expr, pos, end_pos);
}
- // Validation per ES6 object literals.
- class ObjectLiteralChecker {
- public:
- explicit ObjectLiteralChecker(ParserBase* parser)
- : parser_(parser), has_seen_proto_(false) {}
+ ModuleDescriptor* module() const {
+ return scope()->AsModuleScope()->module();
+ }
+ Scope* scope() const { return scope_; }
- void CheckDuplicateProto(Token::Value property);
+ // Stack of expression expression_scopes.
+ // The top of the stack is always pointed to by expression_scope().
+ V8_INLINE ExpressionScope* expression_scope() const {
+ DCHECK_NOT_NULL(expression_scope_);
+ return expression_scope_;
+ }
- private:
- bool IsProto() const {
- return this->scanner()->CurrentMatchesContextualEscaped(
- Token::PROTO_UNDERSCORED);
+ class AcceptINScope final {
+ public:
+ AcceptINScope(ParserBase* parser, bool accept_IN)
+ : parser_(parser), previous_accept_IN_(parser->accept_IN_) {
+ parser_->accept_IN_ = accept_IN;
}
- ParserBase* parser() const { return parser_; }
- Scanner* scanner() const { return parser_->scanner(); }
+ ~AcceptINScope() { parser_->accept_IN_ = previous_accept_IN_; }
+ private:
ParserBase* parser_;
- bool has_seen_proto_;
+ bool previous_accept_IN_;
};
- // Validation per ES6 class literals.
- class ClassLiteralChecker {
+ class ParameterParsingScope {
public:
- explicit ClassLiteralChecker(ParserBase* parser)
- : parser_(parser), has_seen_constructor_(false) {}
-
- void CheckClassMethodName(Token::Value property, ParsePropertyKind type,
- ParseFunctionFlags flags, bool is_static,
- bool* ok);
- void CheckClassFieldName(bool is_static, bool* ok);
-
- private:
- bool IsConstructor() {
- return this->scanner()->CurrentMatchesContextualEscaped(
- Token::CONSTRUCTOR);
- }
- bool IsPrivateConstructor() {
- return this->scanner()->CurrentMatchesContextualEscaped(
- Token::PRIVATE_CONSTRUCTOR);
- }
- bool IsPrototype() {
- return this->scanner()->CurrentMatchesContextualEscaped(Token::PROTOTYPE);
+ ParameterParsingScope(Impl* parser, FormalParametersT* parameters)
+ : parser_(parser), parent_parameters_(parser_->parameters_) {
+ parser_->parameters_ = parameters;
}
- ParserBase* parser() const { return parser_; }
- Scanner* scanner() const { return parser_->scanner(); }
+ ~ParameterParsingScope() { parser_->parameters_ = parent_parameters_; }
- ParserBase* parser_;
- bool has_seen_constructor_;
+ private:
+ Impl* parser_;
+ FormalParametersT* parent_parameters_;
};
- ModuleDescriptor* module() const {
- return scope()->AsModuleScope()->module();
- }
- Scope* scope() const { return scope_; }
-
- // Stack of expression classifiers.
- // The top of the stack is always pointed to by classifier().
- V8_INLINE ExpressionClassifier* classifier() const {
- DCHECK_NOT_NULL(classifier_);
- return classifier_;
- }
-
- // Accumulates the classifier that is on top of the stack (inner) to
- // the one that is right below (outer) and pops the inner.
- V8_INLINE void Accumulate(unsigned productions) {
- DCHECK_NOT_NULL(classifier_);
- ExpressionClassifier* previous = classifier_->previous();
- DCHECK_NOT_NULL(previous);
- previous->Accumulate(classifier_, productions);
- classifier_ = previous;
- }
+ class FunctionBodyParsingScope {
+ public:
+ explicit FunctionBodyParsingScope(Impl* parser)
+ : parser_(parser), expression_scope_(parser_->expression_scope_) {
+ parser_->expression_scope_ = nullptr;
+ }
- V8_INLINE void AccumulateNonBindingPatternErrors() {
- this->Accumulate(ExpressionClassifier::AllProductions &
- ~(ExpressionClassifier::BindingPatternProduction |
- ExpressionClassifier::LetPatternProduction));
- }
+ ~FunctionBodyParsingScope() {
+ parser_->expression_scope_ = expression_scope_;
+ }
- // Pops and discards the classifier that is on top of the stack
- // without accumulating.
- V8_INLINE void DiscardExpressionClassifier() {
- DCHECK_NOT_NULL(classifier_);
- classifier_->Discard();
- classifier_ = classifier_->previous();
- }
+ private:
+ Impl* parser_;
+ ExpressionScope* expression_scope_;
+ };
- // Accumulate errors that can be arbitrarily deep in an expression.
- // These correspond to the ECMAScript spec's 'Contains' operation
- // on productions. This includes:
- //
- // - YieldExpression is disallowed in arrow parameters in a generator.
- // - AwaitExpression is disallowed in arrow parameters in an async function.
- // - AwaitExpression is disallowed in async arrow parameters.
- //
- V8_INLINE void AccumulateFormalParameterContainmentErrors() {
- Accumulate(ExpressionClassifier::FormalParameterInitializerProduction |
- ExpressionClassifier::AsyncArrowFormalParametersProduction);
- }
+ std::vector<void*>* pointer_buffer() { return &pointer_buffer_; }
+ std::vector<void*>* variable_buffer() { return &variable_buffer_; }
// Parser base's protected field members.
@@ -1543,22 +1368,60 @@ class ParserBase {
private:
Zone* zone_;
- ExpressionClassifier* classifier_;
+ ExpressionScope* expression_scope_;
- Scanner* scanner_;
+ std::vector<void*> pointer_buffer_;
+ std::vector<void*> variable_buffer_;
- FunctionLiteral::EagerCompileHint default_eager_compile_hint_;
+ Scanner* scanner_;
int function_literal_id_;
int script_id_;
+ FunctionLiteral::EagerCompileHint default_eager_compile_hint_;
+
+ // This struct is used to move information about the next arrow function from
+ // the place where the arrow head was parsed to where the body will be parsed.
+ // Nothing can be parsed between the head and the body, so it will be consumed
+ // immediately after it's produced.
+ // Preallocating the struct as part of the parser minimizes the cost of
+ // supporting arrow functions on non-arrow expressions.
+ struct NextArrowFunctionInfo {
+ Scanner::Location strict_parameter_error_location =
+ Scanner::Location::invalid();
+ MessageTemplate strict_parameter_error_message = MessageTemplate::kNone;
+ DeclarationScope* scope = nullptr;
+
+ bool HasInitialState() const { return scope == nullptr; }
+
+ void Reset() {
+ scope = nullptr;
+ ClearStrictParameterError();
+ DCHECK(HasInitialState());
+ }
+
+ // Tracks strict-mode parameter violations of sloppy-mode arrow heads in
+ // case the function ends up becoming strict mode. Only one global place to
+ // track this is necessary since arrow functions with none-simple parameters
+ // cannot become strict-mode later on.
+ void ClearStrictParameterError() {
+ strict_parameter_error_location = Scanner::Location::invalid();
+ strict_parameter_error_message = MessageTemplate::kNone;
+ }
+ };
+
+ FormalParametersT* parameters_;
+ NextArrowFunctionInfo next_arrow_function_info_;
+
+ bool accept_IN_ = true;
+
bool allow_natives_;
- bool allow_harmony_do_expressions_;
bool allow_harmony_public_fields_;
bool allow_harmony_static_fields_;
bool allow_harmony_dynamic_import_;
bool allow_harmony_import_meta_;
bool allow_harmony_private_fields_;
+ bool allow_harmony_private_methods_;
bool allow_eval_cache_;
};
@@ -1572,8 +1435,6 @@ ParserBase<Impl>::FunctionState::FunctionState(
function_state_stack_(function_state_stack),
outer_function_state_(*function_state_stack),
scope_(scope),
- destructuring_assignments_to_rewrite_(scope->zone()),
- reported_errors_(16, scope->zone()),
dont_optimize_reason_(BailoutReason::kNoReason),
next_function_is_likely_called_(false),
previous_function_was_likely_called_(false),
@@ -1592,218 +1453,109 @@ ParserBase<Impl>::FunctionState::~FunctionState() {
}
template <typename Impl>
-void ParserBase<Impl>::GetUnexpectedTokenMessage(
- Token::Value token, MessageTemplate::Template* message,
- Scanner::Location* location, const char** arg,
- MessageTemplate::Template default_) {
- *arg = nullptr;
- switch (token) {
- case Token::EOS:
- *message = MessageTemplate::kUnexpectedEOS;
- break;
- case Token::SMI:
- case Token::NUMBER:
- case Token::BIGINT:
- *message = MessageTemplate::kUnexpectedTokenNumber;
- break;
- case Token::STRING:
- *message = MessageTemplate::kUnexpectedTokenString;
- break;
- case Token::PRIVATE_NAME:
- case Token::IDENTIFIER:
- *message = MessageTemplate::kUnexpectedTokenIdentifier;
- break;
- case Token::AWAIT:
- case Token::ENUM:
- *message = MessageTemplate::kUnexpectedReserved;
- break;
- case Token::LET:
- case Token::STATIC:
- case Token::YIELD:
- case Token::FUTURE_STRICT_RESERVED_WORD:
- *message = is_strict(language_mode())
- ? MessageTemplate::kUnexpectedStrictReserved
- : MessageTemplate::kUnexpectedTokenIdentifier;
- break;
- case Token::TEMPLATE_SPAN:
- case Token::TEMPLATE_TAIL:
- *message = MessageTemplate::kUnexpectedTemplateString;
- break;
- case Token::ESCAPED_STRICT_RESERVED_WORD:
- case Token::ESCAPED_KEYWORD:
- *message = MessageTemplate::kInvalidEscapedReservedWord;
- break;
- case Token::ILLEGAL:
- if (scanner()->has_error()) {
- *message = scanner()->error();
- *location = scanner()->error_location();
- } else {
- *message = MessageTemplate::kInvalidOrUnexpectedToken;
- }
- break;
- case Token::REGEXP_LITERAL:
- *message = MessageTemplate::kUnexpectedTokenRegExp;
- break;
- default:
- const char* name = Token::String(token);
- DCHECK_NOT_NULL(name);
- *arg = name;
- break;
- }
-}
-
-template <typename Impl>
void ParserBase<Impl>::ReportUnexpectedToken(Token::Value token) {
- return ReportUnexpectedTokenAt(scanner_->location(), token);
-}
-
-template <typename Impl>
-void ParserBase<Impl>::ReportUnexpectedTokenAt(
- Scanner::Location source_location, Token::Value token,
- MessageTemplate::Template message) {
- const char* arg;
- GetUnexpectedTokenMessage(token, &message, &source_location, &arg);
- impl()->ReportMessageAt(source_location, message, arg);
-}
-
-template <typename Impl>
-typename ParserBase<Impl>::IdentifierT ParserBase<Impl>::ParseIdentifier(
- AllowRestrictedIdentifiers allow_restricted_identifiers, bool* ok) {
- ExpressionClassifier classifier(this);
- auto result = ParseAndClassifyIdentifier(CHECK_OK_CUSTOM(NullIdentifier));
-
- if (allow_restricted_identifiers == kDontAllowRestrictedIdentifiers) {
- ValidateAssignmentPattern(CHECK_OK_CUSTOM(NullIdentifier));
- ValidateBindingPattern(CHECK_OK_CUSTOM(NullIdentifier));
- }
-
- return result;
+ return impl()->ReportUnexpectedTokenAt(scanner_->location(), token);
}
template <typename Impl>
typename ParserBase<Impl>::IdentifierT
-ParserBase<Impl>::ParseAndClassifyIdentifier(bool* ok) {
- Token::Value next = Next();
+ParserBase<Impl>::ParseAndClassifyIdentifier(Token::Value next) {
+ DCHECK_EQ(scanner()->current_token(), next);
STATIC_ASSERT(Token::IDENTIFIER + 1 == Token::ASYNC);
- if (IsInRange(next, Token::IDENTIFIER, Token::ASYNC)) {
+ if (V8_LIKELY(IsInRange(next, Token::IDENTIFIER, Token::ASYNC))) {
IdentifierT name = impl()->GetSymbol();
-
- // 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
- // is actually a formal parameter. Therefore besides the errors that we
- // 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);
- }
+ if (V8_UNLIKELY(impl()->IsArguments(name) &&
+ scope()->ShouldBanArguments())) {
+ ReportMessage(MessageTemplate::kArgumentsDisallowedInInitializer);
+ return impl()->EmptyIdentifierString();
}
+ return name;
+ }
- if (classifier()->duplicate_finder() != nullptr &&
- scanner()->IsDuplicateSymbol(classifier()->duplicate_finder(),
- ast_value_factory())) {
- classifier()->RecordDuplicateFormalParameterError(scanner()->location());
- }
+ if (!Token::IsValidIdentifier(next, language_mode(), is_generator(),
+ parsing_module_ || is_async_function())) {
+ ReportUnexpectedToken(next);
+ return impl()->EmptyIdentifierString();
+ }
- return name;
- } else if (next == Token::AWAIT && !parsing_module_ && !is_async_function()) {
- classifier()->RecordAsyncArrowFormalParametersError(
+ if (next == Token::AWAIT) {
+ expression_scope()->RecordAsyncArrowParametersError(
scanner()->location(), MessageTemplate::kAwaitBindingIdentifier);
return impl()->GetSymbol();
- } else if (is_sloppy(language_mode()) &&
- (Token::IsStrictReservedWord(next) ||
- (next == Token::YIELD && !is_generator()))) {
- classifier()->RecordStrictModeFormalParameterError(
- scanner()->location(), MessageTemplate::kUnexpectedStrictReserved);
- if (scanner()->IsLet()) {
- classifier()->RecordLetPatternError(
- scanner()->location(), MessageTemplate::kLetInLexicalBinding);
- }
- return impl()->GetSymbol();
- } else {
- ReportUnexpectedToken(next);
- *ok = false;
- return impl()->NullIdentifier();
}
+
+ DCHECK(Token::IsStrictReservedWord(next));
+ expression_scope()->RecordStrictModeParameterError(
+ scanner()->location(), MessageTemplate::kUnexpectedStrictReserved);
+ return impl()->GetSymbol();
}
template <class Impl>
-typename ParserBase<Impl>::IdentifierT
-ParserBase<Impl>::ParseIdentifierOrStrictReservedWord(
- FunctionKind function_kind, bool* is_strict_reserved, bool* is_await,
- bool* ok) {
+typename ParserBase<Impl>::IdentifierT ParserBase<Impl>::ParseIdentifier(
+ FunctionKind function_kind) {
Token::Value next = Next();
- if (next == Token::IDENTIFIER || (next == Token::AWAIT && !parsing_module_ &&
- !IsAsyncFunction(function_kind)) ||
- next == Token::ASYNC) {
- *is_strict_reserved = false;
- *is_await = next == Token::AWAIT;
- } else if (Token::IsStrictReservedWord(next) ||
- (next == Token::YIELD && !IsGeneratorFunction(function_kind))) {
- *is_strict_reserved = true;
- } else {
+
+ if (!Token::IsValidIdentifier(
+ next, language_mode(), IsGeneratorFunction(function_kind),
+ parsing_module_ || IsAsyncFunction(function_kind))) {
ReportUnexpectedToken(next);
- *ok = false;
- return impl()->NullIdentifier();
+ return impl()->EmptyIdentifierString();
}
return impl()->GetSymbol();
}
template <typename Impl>
-typename ParserBase<Impl>::IdentifierT ParserBase<Impl>::ParseIdentifierName(
- bool* ok) {
- Token::Value next = Next();
- if (!Token::IsAnyIdentifier(next) && next != Token::ESCAPED_KEYWORD &&
- !Token::IsKeyword(next)) {
- ReportUnexpectedToken(next);
- *ok = false;
- return impl()->NullIdentifier();
+typename ParserBase<Impl>::IdentifierT
+ParserBase<Impl>::ParseNonRestrictedIdentifier() {
+ IdentifierT result = ParseIdentifier();
+
+ if (is_strict(language_mode()) &&
+ V8_UNLIKELY(impl()->IsEvalOrArguments(result))) {
+ impl()->ReportMessageAt(scanner()->location(),
+ MessageTemplate::kStrictEvalArguments);
}
- return impl()->GetSymbol();
+ return result;
+}
+
+template <typename Impl>
+typename ParserBase<Impl>::IdentifierT ParserBase<Impl>::ParsePropertyName() {
+ Token::Value next = Next();
+ if (V8_LIKELY(Token::IsPropertyName(next))) return impl()->GetSymbol();
+
+ ReportUnexpectedToken(next);
+ return impl()->EmptyIdentifierString();
}
template <typename Impl>
typename ParserBase<Impl>::ExpressionT
-ParserBase<Impl>::ParseIdentifierNameOrPrivateName(bool* ok) {
+ParserBase<Impl>::ParsePropertyOrPrivatePropertyName() {
int pos = position();
IdentifierT name;
ExpressionT key;
- if (allow_harmony_private_fields() && peek() == Token::PRIVATE_NAME) {
- Consume(Token::PRIVATE_NAME);
+ Token::Value next = Next();
+ if (V8_LIKELY(Token::IsPropertyName(next))) {
name = impl()->GetSymbol();
- auto key_proxy =
- impl()->ExpressionFromIdentifier(name, pos, InferName::kNo);
- key_proxy->set_is_private_field();
- key = key_proxy;
- } else {
- name = ParseIdentifierName(CHECK_OK);
key = factory()->NewStringLiteral(name, pos);
+ } else if (allow_harmony_private_fields() && next == Token::PRIVATE_NAME) {
+ name = impl()->GetSymbol();
+ key = impl()->ExpressionFromIdentifier(name, pos, InferName::kNo);
+ } else {
+ ReportUnexpectedToken(next);
+ return impl()->FailureExpression();
}
impl()->PushLiteralName(name);
return key;
}
template <typename Impl>
-typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseRegExpLiteral(
- bool* ok) {
+typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseRegExpLiteral() {
int pos = peek_position();
if (!scanner()->ScanRegExpPattern()) {
Next();
ReportMessage(MessageTemplate::kUnterminatedRegExp);
- *ok = false;
- return impl()->NullExpression();
+ return impl()->FailureExpression();
}
IdentifierT js_pattern = impl()->GetNextSymbol();
@@ -1811,8 +1563,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseRegExpLiteral(
if (flags.IsNothing()) {
Next();
ReportMessage(MessageTemplate::kMalformedRegExpFlags);
- *ok = false;
- return impl()->NullExpression();
+ return impl()->FailureExpression();
}
int js_flags = flags.FromJust();
Next();
@@ -1820,8 +1571,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseRegExpLiteral(
}
template <typename Impl>
-typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseBindingPattern(
- bool* ok) {
+typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseBindingPattern() {
// Pattern ::
// Identifier
// ArrayLiteral
@@ -1832,29 +1582,35 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseBindingPattern(
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();
+ IdentifierT name = ParseAndClassifyIdentifier(Next());
+ if (V8_UNLIKELY(is_strict(language_mode()) &&
+ impl()->IsEvalOrArguments(name))) {
+ impl()->ReportMessageAt(scanner()->location(),
+ MessageTemplate::kStrictEvalArguments);
+ return impl()->FailureExpression();
}
+ return impl()->ExpressionFromIdentifier(name, beg_pos);
+ }
+
+ CheckStackOverflow();
+
+ if (token == Token::LBRACK) {
+ result = ParseArrayLiteral();
+ } else if (token == Token::LBRACE) {
+ result = ParseObjectLiteral();
+ } else {
+ ReportUnexpectedToken(Next());
+ return impl()->FailureExpression();
}
- ValidateBindingPattern(CHECK_OK);
return result;
}
template <typename Impl>
-typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePrimaryExpression(
- bool* is_async, bool* ok) {
+typename ParserBase<Impl>::ExpressionT
+ParserBase<Impl>::ParsePrimaryExpression() {
+ CheckStackOverflow();
+
// PrimaryExpression ::
// 'this'
// 'null'
@@ -1874,136 +1630,115 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePrimaryExpression(
int beg_pos = peek_position();
Token::Value token = peek();
- switch (token) {
- case Token::THIS: {
- BindingPatternUnexpectedToken();
- Consume(Token::THIS);
- return impl()->ThisExpression(beg_pos);
+
+ if (Token::IsAnyIdentifier(token)) {
+ Consume(token);
+
+ FunctionKind kind = FunctionKind::kArrowFunction;
+
+ if (V8_UNLIKELY(token == Token::ASYNC &&
+ !scanner()->HasLineTerminatorBeforeNext())) {
+ // async function ...
+ if (peek() == Token::FUNCTION) return ParseAsyncFunctionLiteral();
+
+ // async Identifier => ...
+ if (peek_any_identifier() && PeekAhead() == Token::ARROW) {
+ token = Next();
+ beg_pos = position();
+ kind = FunctionKind::kAsyncArrowFunction;
+ }
}
- case Token::NULL_LITERAL:
- case Token::TRUE_LITERAL:
- case Token::FALSE_LITERAL:
- case Token::SMI:
- case Token::NUMBER:
- 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);
+ if (V8_UNLIKELY(peek() == Token::ARROW)) {
+ ArrowHeadParsingScope parsing_scope(impl(), kind);
+ IdentifierT name = ParseAndClassifyIdentifier(token);
+ ClassifyParameter(name, beg_pos, end_position());
+ ExpressionT result =
+ impl()->ExpressionFromIdentifier(name, beg_pos, InferName::kNo);
+ next_arrow_function_info_.scope = parsing_scope.ValidateAndCreateScope();
+ return result;
}
- case Token::ASYNC:
- if (!scanner()->HasLineTerminatorAfterNext() &&
- PeekAhead() == Token::FUNCTION) {
- BindingPatternUnexpectedToken();
- Consume(Token::ASYNC);
- return ParseAsyncFunctionLiteral(ok);
- }
- // CoverCallExpressionAndAsyncArrowHead
- *is_async = true;
- V8_FALLTHROUGH;
- case Token::IDENTIFIER:
- case Token::LET:
- case Token::STATIC:
- case Token::YIELD:
- case Token::AWAIT:
- 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);
+ IdentifierT name = ParseAndClassifyIdentifier(token);
+ return impl()->ExpressionFromIdentifier(name, beg_pos);
+ }
+
+ if (Token::IsLiteral(token)) {
+ return impl()->ExpressionFromLiteral(Next(), beg_pos);
+ }
+
+ switch (token) {
+ case Token::THIS: {
+ Consume(Token::THIS);
+ return impl()->ThisExpression(beg_pos);
}
case Token::ASSIGN_DIV:
case Token::DIV:
- classifier()->RecordBindingPatternError(
- scanner()->peek_location(), MessageTemplate::kUnexpectedTokenRegExp);
- return ParseRegExpLiteral(ok);
+ return ParseRegExpLiteral();
case Token::LBRACK:
- return ParseArrayLiteral(ok);
+ return ParseArrayLiteral();
case Token::LBRACE:
- return ParseObjectLiteral(ok);
+ return ParseObjectLiteral();
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
- // parenthesization.
- bool pattern_error = !classifier()->is_valid_binding_pattern();
- classifier()->RecordPatternError(scanner()->peek_location(),
- MessageTemplate::kUnexpectedToken,
- Token::String(Token::LPAREN));
- if (pattern_error) ArrowFormalParametersUnexpectedToken();
Consume(Token::LPAREN);
if (Check(Token::RPAREN)) {
- // ()=>x. The continuation that looks for the => is in
- // ParseAssignmentExpression.
- classifier()->RecordExpressionError(scanner()->location(),
- MessageTemplate::kUnexpectedToken,
- Token::String(Token::RPAREN));
+ // ()=>x. The continuation that consumes the => is in
+ // ParseAssignmentExpressionCoverGrammar.
+ if (peek() != Token::ARROW) ReportUnexpectedToken(Token::RPAREN);
+ next_arrow_function_info_.scope =
+ NewFunctionScope(FunctionKind::kArrowFunction);
return factory()->NewEmptyParentheses(beg_pos);
}
+ Scope::Snapshot scope_snapshot(scope());
+ ArrowHeadParsingScope maybe_arrow(impl(), FunctionKind::kArrowFunction);
// Heuristically try to detect immediately called functions before
// seeing the call parentheses.
if (peek() == Token::FUNCTION ||
(peek() == Token::ASYNC && PeekAhead() == Token::FUNCTION)) {
function_state_->set_next_function_is_likely_called();
}
- ExpressionT expr = ParseExpressionCoverGrammar(true, CHECK_OK);
- Expect(Token::RPAREN, ok);
+ AcceptINScope scope(this, true);
+ ExpressionT expr = ParseExpressionCoverGrammar();
+ expr->mark_parenthesized();
+ Expect(Token::RPAREN);
+
+ if (peek() == Token::ARROW) {
+ next_arrow_function_info_.scope = maybe_arrow.ValidateAndCreateScope();
+ scope_snapshot.Reparent(next_arrow_function_info_.scope);
+ } else {
+ maybe_arrow.ValidateExpression();
+ }
+
return expr;
}
case Token::CLASS: {
- BindingPatternUnexpectedToken();
Consume(Token::CLASS);
int class_token_pos = position();
IdentifierT name = impl()->NullIdentifier();
bool is_strict_reserved_name = false;
Scanner::Location class_name_location = Scanner::Location::invalid();
if (peek_any_identifier()) {
- bool is_await = false;
- name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name,
- &is_await, CHECK_OK);
+ name = ParseAndClassifyIdentifier(Next());
class_name_location = scanner()->location();
- if (is_await) {
- classifier()->RecordAsyncArrowFormalParametersError(
- scanner()->location(), MessageTemplate::kAwaitBindingIdentifier);
- }
+ is_strict_reserved_name =
+ Token::IsStrictReservedWord(scanner()->current_token());
}
return ParseClassLiteral(name, class_name_location,
- is_strict_reserved_name, class_token_pos, ok);
+ is_strict_reserved_name, class_token_pos);
}
case Token::TEMPLATE_SPAN:
case Token::TEMPLATE_TAIL:
- BindingPatternUnexpectedToken();
- return ParseTemplateLiteral(impl()->NullExpression(), beg_pos, false, ok);
+ return ParseTemplateLiteral(impl()->NullExpression(), beg_pos, false);
case Token::MOD:
if (allow_natives() || extension_ != nullptr) {
- BindingPatternUnexpectedToken();
- return ParseV8Intrinsic(ok);
- }
- break;
-
- case Token::DO:
- if (allow_harmony_do_expressions()) {
- BindingPatternUnexpectedToken();
- return ParseDoExpression(ok);
+ return ParseV8Intrinsic();
}
break;
@@ -2012,72 +1747,49 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePrimaryExpression(
}
ReportUnexpectedToken(Next());
- *ok = false;
- return impl()->NullExpression();
+ return impl()->FailureExpression();
}
template <typename Impl>
-typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseExpression(
- bool* ok) {
- ExpressionClassifier classifier(this);
- ExpressionT result = ParseExpressionCoverGrammar(true, CHECK_OK);
- ValidateExpression(ok);
+typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseExpression() {
+ ExpressionParsingScope expression_scope(impl());
+ AcceptINScope scope(this, true);
+ ExpressionT result = ParseExpressionCoverGrammar();
+ expression_scope.ValidateExpression();
return result;
}
template <typename Impl>
typename ParserBase<Impl>::ExpressionT
-ParserBase<Impl>::ParseExpressionCoverGrammar(bool accept_IN, bool* ok) {
+ParserBase<Impl>::ParseAssignmentExpression() {
+ ExpressionParsingScope expression_scope(impl());
+ ExpressionT result = ParseAssignmentExpressionCoverGrammar();
+ expression_scope.ValidateExpression();
+ return result;
+}
+
+template <typename Impl>
+typename ParserBase<Impl>::ExpressionT
+ParserBase<Impl>::ParseExpressionCoverGrammar() {
// Expression ::
// AssignmentExpression
// Expression ',' AssignmentExpression
- ExpressionT result = impl()->NullExpression();
+ ExpressionListT list(pointer_buffer());
+ ExpressionT expression;
+ AccumulationScope accumulation_scope(expression_scope());
while (true) {
- int comma_pos = position();
- ExpressionClassifier binding_classifier(this);
- ExpressionT right;
- if (Check(Token::ELLIPSIS)) {
- // 'x, y, ...z' in CoverParenthesizedExpressionAndArrowParameterList only
- // as the formal parameters of'(x, y, ...z) => foo', and is not itself a
- // valid expression.
- classifier()->RecordExpressionError(scanner()->location(),
- MessageTemplate::kUnexpectedToken,
- Token::String(Token::ELLIPSIS));
- int ellipsis_pos = position();
- int pattern_pos = peek_position();
- ExpressionT pattern = ParseBindingPattern(CHECK_OK);
- if (peek() == Token::ASSIGN) {
- ReportMessage(MessageTemplate::kRestDefaultInitializer);
- *ok = false;
- return result;
- }
- right = factory()->NewSpread(pattern, ellipsis_pos, pattern_pos);
- } else {
- right = ParseAssignmentExpression(accept_IN, CHECK_OK);
- }
- // No need to accumulate binding pattern-related errors, since
- // an Expression can't be a binding pattern anyway.
- AccumulateNonBindingPatternErrors();
- if (!impl()->IsIdentifier(right)) classifier()->RecordNonSimpleParameter();
- if (impl()->IsNull(result)) {
- // First time through the loop.
- result = right;
- } else if (impl()->CollapseNaryExpression(&result, right, Token::COMMA,
- comma_pos,
- SourceRange::Empty())) {
- // Do nothing, "result" is already updated.
- } else {
- result =
- factory()->NewBinaryOperation(Token::COMMA, result, right, comma_pos);
+ if (V8_UNLIKELY(peek() == Token::ELLIPSIS)) {
+ return ParseArrowParametersWithRest(&list, &accumulation_scope);
}
- if (!Check(Token::COMMA)) break;
+ int expr_pos = peek_position();
+ expression = ParseAssignmentExpressionCoverGrammar();
- if (right->IsSpread()) {
- classifier()->RecordArrowFormalParametersError(
- scanner()->location(), MessageTemplate::kParamAfterRest);
- }
+ ClassifyArrowParameter(&accumulation_scope, expr_pos, expression);
+ list.Add(expression);
+
+ if (!Check(Token::COMMA)) break;
if (peek() == Token::RPAREN && PeekAhead() == Token::ARROW) {
// a trailing comma is allowed at the end of an arrow parameter list
@@ -2092,19 +1804,64 @@ ParserBase<Impl>::ParseExpressionCoverGrammar(bool accept_IN, bool* ok) {
}
}
- return result;
+ // Return the single element if the list is empty. We need to do this because
+ // callers of this function care about the type of the result if there was
+ // only a single assignment expression. The preparser would lose this
+ // information otherwise.
+ if (list.length() == 1) return expression;
+ return impl()->ExpressionListToExpression(list);
}
template <typename Impl>
-typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseArrayLiteral(
- bool* ok) {
+typename ParserBase<Impl>::ExpressionT
+ParserBase<Impl>::ParseArrowParametersWithRest(
+ typename ParserBase<Impl>::ExpressionListT* list,
+ AccumulationScope* accumulation_scope) {
+ Consume(Token::ELLIPSIS);
+
+ Scanner::Location ellipsis = scanner()->location();
+ int pattern_pos = peek_position();
+ ExpressionT pattern = ParseBindingPattern();
+ ClassifyArrowParameter(accumulation_scope, pattern_pos, pattern);
+
+ expression_scope()->RecordNonSimpleParameter();
+
+ if (V8_UNLIKELY(peek() == Token::ASSIGN)) {
+ ReportMessage(MessageTemplate::kRestDefaultInitializer);
+ return impl()->FailureExpression();
+ }
+
+ ExpressionT spread =
+ factory()->NewSpread(pattern, ellipsis.beg_pos, pattern_pos);
+ if (V8_UNLIKELY(peek() == Token::COMMA)) {
+ ReportMessage(MessageTemplate::kParamAfterRest);
+ return impl()->FailureExpression();
+ }
+
+ // 'x, y, ...z' in CoverParenthesizedExpressionAndArrowParameterList only
+ // as the formal parameters of'(x, y, ...z) => foo', and is not itself a
+ // valid expression.
+ if (peek() != Token::RPAREN || PeekAhead() != Token::ARROW) {
+ impl()->ReportUnexpectedTokenAt(ellipsis, Token::ELLIPSIS);
+ return impl()->FailureExpression();
+ }
+
+ list->Add(spread);
+ return impl()->ExpressionListToExpression(*list);
+}
+
+template <typename Impl>
+typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseArrayLiteral() {
// ArrayLiteral ::
// '[' Expression? (',' Expression?)* ']'
int pos = peek_position();
- ExpressionListT values = impl()->NewExpressionList(4);
+ ExpressionListT values(pointer_buffer());
int first_spread_index = -1;
Consume(Token::LBRACK);
+
+ AccumulationScope accumulation_scope(expression_scope());
+
while (!Check(Token::RBRACK)) {
ExpressionT elem;
if (peek() == Token::COMMA) {
@@ -2112,115 +1869,80 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseArrayLiteral(
} else if (Check(Token::ELLIPSIS)) {
int start_pos = position();
int expr_pos = peek_position();
- ExpressionT argument = ParseAssignmentExpression(true, CHECK_OK);
+ AcceptINScope scope(this, true);
+ ExpressionT argument =
+ ParsePossibleDestructuringSubPattern(&accumulation_scope);
elem = factory()->NewSpread(argument, start_pos, expr_pos);
if (first_spread_index < 0) {
- first_spread_index = values->length();
+ first_spread_index = values.length();
}
if (argument->IsAssignment()) {
- classifier()->RecordPatternError(
+ expression_scope()->RecordPatternError(
Scanner::Location(start_pos, end_position()),
MessageTemplate::kInvalidDestructuringTarget);
- } else {
- CheckDestructuringElement(argument, start_pos, end_position());
}
if (peek() == Token::COMMA) {
- classifier()->RecordPatternError(
+ expression_scope()->RecordPatternError(
Scanner::Location(start_pos, end_position()),
MessageTemplate::kElementAfterRest);
}
} else {
- int beg_pos = peek_position();
- elem = ParseAssignmentExpression(true, CHECK_OK);
- CheckDestructuringElement(elem, beg_pos, end_position());
+ AcceptINScope scope(this, true);
+ elem = ParsePossibleDestructuringSubPattern(&accumulation_scope);
}
- values->Add(elem, zone_);
+ values.Add(elem);
if (peek() != Token::RBRACK) {
- Expect(Token::COMMA, CHECK_OK);
+ Expect(Token::COMMA);
+ if (elem->IsFailureExpression()) return elem;
}
}
return factory()->NewArrayLiteral(values, first_spread_index, pos);
}
-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 = ParsePropertyKind::kValue;
- return true;
- case Token::COMMA:
- case Token::RBRACE:
- case Token::ASSIGN:
- *kind = ParsePropertyKind::kShorthand;
- return true;
- case Token::LPAREN:
- *kind = ParsePropertyKind::kMethod;
- return true;
- case Token::MUL:
- case Token::SEMICOLON:
- *kind = ParsePropertyKind::kClassField;
- return true;
- case Token::PRIVATE_NAME:
- *kind = ParsePropertyKind::kClassField;
- return true;
- default:
- break;
- }
- return false;
-}
-
-inline bool ParseAsAccessor(Token::Value token, Token::Value contextual_token,
- ParsePropertyKind* kind) {
- if (ParsePropertyKindFromToken(token, kind)) return false;
-
- if (contextual_token == Token::GET) {
- *kind = ParsePropertyKind::kAccessorGetter;
- } else if (contextual_token == Token::SET) {
- *kind = ParsePropertyKind::kAccessorSetter;
- } else {
- return false;
- }
-
- return true;
-}
-
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);
+typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseProperty(
+ ParsePropertyInfo* prop_info) {
+ DCHECK_EQ(prop_info->kind, ParsePropertyKind::kNotSet);
+ DCHECK_EQ(prop_info->function_flags, ParseFunctionFlag::kIsNormal);
+ DCHECK(!prop_info->is_computed_name);
if (Check(Token::ASYNC)) {
Token::Value token = peek();
- if ((token != Token::MUL && ParsePropertyKindFromToken(token, kind)) ||
+ if ((token != Token::MUL && prop_info->ParsePropertyKindFromToken(token)) ||
scanner()->HasLineTerminatorBeforeNext()) {
- *name = impl()->GetSymbol();
- impl()->PushLiteralName(*name);
- return factory()->NewStringLiteral(*name, position());
+ prop_info->name = impl()->GetSymbol();
+ impl()->PushLiteralName(prop_info->name);
+ return factory()->NewStringLiteral(prop_info->name, position());
}
- *flags = ParseFunctionFlag::kIsAsync;
- *kind = ParsePropertyKind::kMethod;
+ prop_info->function_flags = ParseFunctionFlag::kIsAsync;
+ prop_info->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());
+ prop_info->function_flags |= ParseFunctionFlag::kIsGenerator;
+ prop_info->kind = ParsePropertyKind::kMethod;
+ }
+
+ if (prop_info->kind == ParsePropertyKind::kNotSet &&
+ Check(Token::IDENTIFIER)) {
+ IdentifierT symbol = impl()->GetSymbol();
+ if (!prop_info->ParsePropertyKindFromToken(peek())) {
+ if (impl()->IdentifierEquals(symbol, ast_value_factory()->get_string())) {
+ prop_info->kind = ParsePropertyKind::kAccessorGetter;
+ } else if (impl()->IdentifierEquals(symbol,
+ ast_value_factory()->set_string())) {
+ prop_info->kind = ParsePropertyKind::kAccessorSetter;
+ }
+ }
+ if (!IsAccessor(prop_info->kind)) {
+ prop_info->name = symbol;
+ impl()->PushLiteralName(prop_info->name);
+ return factory()->NewStringLiteral(prop_info->name, position());
+ }
}
int pos = peek_position();
@@ -2237,10 +1959,27 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePropertyName(
bool is_array_index;
uint32_t index;
switch (peek()) {
+ case Token::PRIVATE_NAME:
+ prop_info->is_private = true;
+ is_array_index = false;
+ Consume(Token::PRIVATE_NAME);
+ if (prop_info->kind == ParsePropertyKind::kNotSet) {
+ prop_info->ParsePropertyKindFromToken(peek());
+ }
+ prop_info->name = impl()->GetSymbol();
+ if (prop_info->position == PropertyPosition::kObjectLiteral ||
+ (!allow_harmony_private_methods() &&
+ (IsAccessor(prop_info->kind) ||
+ prop_info->kind == ParsePropertyKind::kMethod))) {
+ ReportUnexpectedToken(Next());
+ return impl()->FailureExpression();
+ }
+ break;
+
case Token::STRING:
Consume(Token::STRING);
- *name = impl()->GetSymbol();
- is_array_index = impl()->IsArrayIndex(*name, &index);
+ prop_info->name = impl()->GetSymbol();
+ is_array_index = impl()->IsArrayIndex(prop_info->name, &index);
break;
case Token::SMI:
@@ -2248,82 +1987,76 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePropertyName(
index = scanner()->smi_value();
is_array_index = true;
// Token::SMI were scanned from their canonical representation.
- *name = impl()->GetSymbol();
+ prop_info->name = impl()->GetSymbol();
break;
case Token::NUMBER: {
Consume(Token::NUMBER);
- *name = impl()->GetNumberAsSymbol();
- is_array_index = impl()->IsArrayIndex(*name, &index);
+ prop_info->name = impl()->GetNumberAsSymbol();
+ is_array_index = impl()->IsArrayIndex(prop_info->name, &index);
break;
}
case Token::LBRACK: {
- *name = impl()->NullIdentifier();
- *is_computed_name = true;
+ prop_info->name = impl()->NullIdentifier();
+ prop_info->is_computed_name = true;
Consume(Token::LBRACK);
- ExpressionClassifier computed_name_classifier(this);
- ExpressionT expression = ParseAssignmentExpression(true, CHECK_OK);
- ValidateExpression(CHECK_OK);
- AccumulateFormalParameterContainmentErrors();
- Expect(Token::RBRACK, CHECK_OK);
- if (*kind == ParsePropertyKind::kNotSet) {
- ParsePropertyKindFromToken(peek(), kind);
+ AcceptINScope scope(this, true);
+ ExpressionT expression = ParseAssignmentExpression();
+ Expect(Token::RBRACK);
+ if (prop_info->kind == ParsePropertyKind::kNotSet) {
+ prop_info->ParsePropertyKindFromToken(peek());
}
return expression;
}
case Token::ELLIPSIS:
- if (*kind == ParsePropertyKind::kNotSet) {
- *name = impl()->NullIdentifier();
+ if (prop_info->kind == ParsePropertyKind::kNotSet) {
+ prop_info->name = impl()->NullIdentifier();
Consume(Token::ELLIPSIS);
- ExpressionT expression = ParseAssignmentExpression(true, CHECK_OK);
- *kind = ParsePropertyKind::kSpread;
-
- if (!impl()->IsIdentifier(expression)) {
- classifier()->RecordBindingPatternError(
- scanner()->location(),
+ AcceptINScope scope(this, true);
+ int start_pos = peek_position();
+ ExpressionT expression =
+ ParsePossibleDestructuringSubPattern(prop_info->accumulation_scope);
+ prop_info->kind = ParsePropertyKind::kSpread;
+
+ if (!IsValidReferenceExpression(expression)) {
+ expression_scope()->RecordDeclarationError(
+ Scanner::Location(start_pos, end_position()),
MessageTemplate::kInvalidRestBindingPattern);
- }
-
- if (!expression->IsValidReferenceExpression()) {
- classifier()->RecordAssignmentPatternError(
- scanner()->location(),
+ expression_scope()->RecordPatternError(
+ Scanner::Location(start_pos, end_position()),
MessageTemplate::kInvalidRestAssignmentPattern);
}
if (peek() != Token::RBRACE) {
- classifier()->RecordPatternError(scanner()->location(),
- MessageTemplate::kElementAfterRest);
+ expression_scope()->RecordPatternError(
+ scanner()->location(), MessageTemplate::kElementAfterRest);
}
return expression;
}
V8_FALLTHROUGH;
default:
- *name = ParseIdentifierName(CHECK_OK);
+ prop_info->name = ParsePropertyName();
is_array_index = false;
break;
}
- if (*kind == ParsePropertyKind::kNotSet) {
- ParsePropertyKindFromToken(peek(), kind);
+ if (prop_info->kind == ParsePropertyKind::kNotSet) {
+ prop_info->ParsePropertyKindFromToken(peek());
}
- impl()->PushLiteralName(*name);
+ impl()->PushLiteralName(prop_info->name);
return is_array_index ? factory()->NewNumberLiteral(index, pos)
- : factory()->NewStringLiteral(*name, pos);
+ : factory()->NewStringLiteral(prop_info->name, pos);
}
template <typename Impl>
typename ParserBase<Impl>::ClassLiteralPropertyT
-ParserBase<Impl>::ParseClassPropertyDefinition(
- ClassLiteralChecker* checker, ClassInfo* class_info, IdentifierT* name,
- bool has_extends, bool* is_computed_name,
- ClassLiteralProperty::Kind* property_kind, bool* is_static, bool* ok) {
+ParserBase<Impl>::ParseClassPropertyDefinition(ClassInfo* class_info,
+ ParsePropertyInfo* prop_info,
+ bool has_extends) {
DCHECK_NOT_NULL(class_info);
- ParseFunctionFlags function_flags = ParseFunctionFlag::kIsNormal;
- *is_static = false;
- *property_kind = ClassLiteralProperty::METHOD;
- ParsePropertyKind kind = ParsePropertyKind::kNotSet;
+ DCHECK_EQ(prop_info->position, PropertyPosition::kClassLiteral);
Token::Value name_token = peek();
DCHECK_IMPLIES(name_token == Token::PRIVATE_NAME,
@@ -2331,48 +2064,39 @@ ParserBase<Impl>::ParseClassPropertyDefinition(
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 = ParsePropertyKind::kMethod;
- *name = impl()->GetSymbol(); // TODO(bakkot) specialize on 'static'
- name_expression = factory()->NewStringLiteral(*name, position());
+ prop_info->kind = ParsePropertyKind::kMethod;
+ // TODO(bakkot) specialize on 'static'
+ prop_info->name = impl()->GetSymbol();
+ name_expression =
+ factory()->NewStringLiteral(prop_info->name, position());
} else if (peek() == Token::ASSIGN || peek() == Token::SEMICOLON ||
peek() == Token::RBRACE) {
- *name = impl()->GetSymbol(); // TODO(bakkot) specialize on 'static'
- name_expression = factory()->NewStringLiteral(*name, position());
- } else if (peek() == Token::PRIVATE_NAME) {
- DCHECK(allow_harmony_private_fields());
- // TODO(gsathya): Make a better error message for this.
- ReportUnexpectedToken(Next());
- *ok = false;
- return impl()->NullLiteralProperty();
- } else {
- *is_static = true;
+ // TODO(bakkot) specialize on 'static'
+ prop_info->name = impl()->GetSymbol();
name_expression =
- ParsePropertyName(name, &kind, &function_flags, is_computed_name,
- CHECK_OK_CUSTOM(NullLiteralProperty));
+ factory()->NewStringLiteral(prop_info->name, position());
+ } else {
+ prop_info->is_static = true;
+ name_expression = ParseProperty(prop_info);
}
- } 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, &function_flags, is_computed_name,
- CHECK_OK_CUSTOM(NullLiteralProperty));
+ name_expression = ParseProperty(prop_info);
}
- if (!class_info->has_name_static_property && *is_static &&
- impl()->IsName(*name)) {
+ if (!class_info->has_name_static_property && prop_info->is_static &&
+ impl()->IsName(prop_info->name)) {
class_info->has_name_static_property = true;
}
- switch (kind) {
+ switch (prop_info->kind) {
+ case ParsePropertyKind::kAssign:
case ParsePropertyKind::kClassField:
+ case ParsePropertyKind::kShorthandOrClassField:
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
@@ -2381,34 +2105,33 @@ ParserBase<Impl>::ParseClassPropertyDefinition(
// 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
- : ClassLiteralProperty::PUBLIC_FIELD;
- if (*is_static && !allow_harmony_static_fields()) {
+ prop_info->kind = ParsePropertyKind::kClassField;
+ DCHECK_IMPLIES(prop_info->is_computed_name, !prop_info->is_private);
+
+ if (prop_info->is_static && !allow_harmony_static_fields()) {
ReportUnexpectedToken(Next());
- *ok = false;
return impl()->NullLiteralProperty();
}
- if (!*is_computed_name) {
- checker->CheckClassFieldName(*is_static,
- CHECK_OK_CUSTOM(NullLiteralProperty));
+
+ if (!prop_info->is_computed_name) {
+ CheckClassFieldName(prop_info->name, prop_info->is_static);
}
- ExpressionT initializer =
- ParseClassFieldInitializer(class_info, property_beg_pos, *is_static,
- CHECK_OK_CUSTOM(NullLiteralProperty));
- ExpectSemicolon(CHECK_OK_CUSTOM(NullLiteralProperty));
+
+ ExpressionT initializer = ParseMemberInitializer(
+ class_info, property_beg_pos, prop_info->is_static);
+ ExpectSemicolon();
+
ClassLiteralPropertyT result = factory()->NewClassLiteralProperty(
- name_expression, initializer, *property_kind, *is_static,
- *is_computed_name);
- impl()->SetFunctionNameFromPropertyName(result, *name);
+ name_expression, initializer, ClassLiteralProperty::FIELD,
+ prop_info->is_static, prop_info->is_computed_name,
+ prop_info->is_private);
+ impl()->SetFunctionNameFromPropertyName(result, prop_info->name);
+
return result;
} else {
ReportUnexpectedToken(Next());
- *ok = false;
return impl()->NullLiteralProperty();
}
@@ -2421,89 +2144,89 @@ ParserBase<Impl>::ParseClassPropertyDefinition(
// async '*' PropertyName '(' StrictFormalParameters ')'
// '{' FunctionBody '}'
- if (!*is_computed_name) {
- checker->CheckClassMethodName(name_token, ParsePropertyKind::kMethod,
- function_flags, *is_static,
- CHECK_OK_CUSTOM(NullLiteralProperty));
+ if (!prop_info->is_computed_name) {
+ CheckClassMethodName(prop_info->name, ParsePropertyKind::kMethod,
+ prop_info->function_flags, prop_info->is_static,
+ &class_info->has_seen_constructor);
}
- FunctionKind kind = MethodKindFor(function_flags);
+ FunctionKind kind = MethodKindFor(prop_info->function_flags);
- if (!*is_static && impl()->IsConstructor(*name)) {
+ if (!prop_info->is_static && impl()->IsConstructor(prop_info->name)) {
class_info->has_seen_constructor = true;
kind = has_extends ? FunctionKind::kDerivedConstructor
: FunctionKind::kBaseConstructor;
}
ExpressionT value = impl()->ParseFunctionLiteral(
- *name, scanner()->location(), kSkipFunctionNameCheck, kind,
+ prop_info->name, scanner()->location(), kSkipFunctionNameCheck, kind,
name_token_position, FunctionLiteral::kAccessorOrMethod,
- language_mode(), nullptr, CHECK_OK_CUSTOM(NullLiteralProperty));
+ language_mode(), nullptr);
- *property_kind = ClassLiteralProperty::METHOD;
ClassLiteralPropertyT result = factory()->NewClassLiteralProperty(
- name_expression, value, *property_kind, *is_static,
- *is_computed_name);
- impl()->SetFunctionNameFromPropertyName(result, *name);
+ name_expression, value, ClassLiteralProperty::METHOD,
+ prop_info->is_static, prop_info->is_computed_name,
+ prop_info->is_private);
+ impl()->SetFunctionNameFromPropertyName(result, prop_info->name);
return result;
}
case ParsePropertyKind::kAccessorGetter:
case ParsePropertyKind::kAccessorSetter: {
- DCHECK_EQ(function_flags, ParseFunctionFlag::kIsNormal);
- bool is_get = kind == ParsePropertyKind::kAccessorGetter;
+ DCHECK_EQ(prop_info->function_flags, ParseFunctionFlag::kIsNormal);
+ bool is_get = prop_info->kind == ParsePropertyKind::kAccessorGetter;
- if (!*is_computed_name) {
- checker->CheckClassMethodName(name_token, kind,
- ParseFunctionFlag::kIsNormal, *is_static,
- CHECK_OK_CUSTOM(NullLiteralProperty));
+ if (!prop_info->is_computed_name) {
+ CheckClassMethodName(prop_info->name, prop_info->kind,
+ ParseFunctionFlag::kIsNormal, prop_info->is_static,
+ &class_info->has_seen_constructor);
// 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.
- name_expression =
- factory()->NewStringLiteral(*name, name_expression->position());
+ name_expression = factory()->NewStringLiteral(
+ prop_info->name, name_expression->position());
}
FunctionKind kind = is_get ? FunctionKind::kGetterFunction
: FunctionKind::kSetterFunction;
FunctionLiteralT value = impl()->ParseFunctionLiteral(
- *name, scanner()->location(), kSkipFunctionNameCheck, kind,
+ prop_info->name, scanner()->location(), kSkipFunctionNameCheck, kind,
name_token_position, FunctionLiteral::kAccessorOrMethod,
- language_mode(), nullptr, CHECK_OK_CUSTOM(NullLiteralProperty));
+ language_mode(), nullptr);
- *property_kind =
+ ClassLiteralProperty::Kind property_kind =
is_get ? ClassLiteralProperty::GETTER : ClassLiteralProperty::SETTER;
ClassLiteralPropertyT result = factory()->NewClassLiteralProperty(
- name_expression, value, *property_kind, *is_static,
- *is_computed_name);
+ name_expression, value, property_kind, prop_info->is_static,
+ prop_info->is_computed_name, prop_info->is_private);
const AstRawString* prefix =
is_get ? ast_value_factory()->get_space_string()
: ast_value_factory()->set_space_string();
- impl()->SetFunctionNameFromPropertyName(result, *name, prefix);
+ impl()->SetFunctionNameFromPropertyName(result, prop_info->name, prefix);
return result;
}
+ case ParsePropertyKind::kValue:
+ case ParsePropertyKind::kShorthand:
case ParsePropertyKind::kSpread:
- ReportUnexpectedTokenAt(
+ impl()->ReportUnexpectedTokenAt(
Scanner::Location(name_token_position, name_expression->position()),
name_token);
- *ok = false;
return impl()->NullLiteralProperty();
}
UNREACHABLE();
}
template <typename Impl>
-typename ParserBase<Impl>::ExpressionT
-ParserBase<Impl>::ParseClassFieldInitializer(ClassInfo* class_info, int beg_pos,
- bool is_static, bool* ok) {
- DeclarationScope* initializer_scope = is_static
- ? class_info->static_fields_scope
- : class_info->instance_fields_scope;
+typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseMemberInitializer(
+ ClassInfo* class_info, int beg_pos, bool is_static) {
+ DeclarationScope* initializer_scope =
+ is_static ? class_info->static_fields_scope
+ : class_info->instance_members_scope;
if (initializer_scope == nullptr) {
initializer_scope =
- NewFunctionScope(FunctionKind::kClassFieldsInitializerFunction);
+ NewFunctionScope(FunctionKind::kClassMembersInitializerFunction);
// TODO(gsathya): Make scopes be non contiguous.
initializer_scope->set_start_position(beg_pos);
initializer_scope->SetLanguageMode(LanguageMode::kStrict);
@@ -2513,11 +2236,9 @@ ParserBase<Impl>::ParseClassFieldInitializer(ClassInfo* class_info, int beg_pos,
if (Check(Token::ASSIGN)) {
FunctionState initializer_state(&function_state_, &scope_,
initializer_scope);
- ExpressionClassifier expression_classifier(this);
- initializer =
- ParseAssignmentExpression(true, CHECK_OK_CUSTOM(NullExpression));
- ValidateExpression(CHECK_OK_CUSTOM(NullExpression));
+ AcceptINScope scope(this, true);
+ initializer = ParseAssignmentExpression();
} else {
initializer = factory()->NewUndefinedLiteral(kNoSourcePosition);
}
@@ -2527,8 +2248,8 @@ ParserBase<Impl>::ParseClassFieldInitializer(ClassInfo* class_info, int beg_pos,
class_info->static_fields_scope = initializer_scope;
class_info->has_static_class_fields = true;
} else {
- class_info->instance_fields_scope = initializer_scope;
- class_info->has_instance_class_fields = true;
+ class_info->instance_members_scope = initializer_scope;
+ class_info->has_instance_members = true;
}
return initializer;
@@ -2536,30 +2257,25 @@ ParserBase<Impl>::ParseClassFieldInitializer(ClassInfo* class_info, int beg_pos,
template <typename Impl>
typename ParserBase<Impl>::ObjectLiteralPropertyT
-ParserBase<Impl>::ParseObjectPropertyDefinition(ObjectLiteralChecker* checker,
- bool* is_computed_name,
- bool* is_rest_property,
- bool* ok) {
- ParseFunctionFlags function_flags = ParseFunctionFlag::kIsNormal;
- ParsePropertyKind kind = ParsePropertyKind::kNotSet;
-
- IdentifierT name = impl()->NullIdentifier();
+ParserBase<Impl>::ParseObjectPropertyDefinition(ParsePropertyInfo* prop_info,
+ bool* has_seen_proto) {
+ DCHECK_EQ(prop_info->position, PropertyPosition::kObjectLiteral);
Token::Value name_token = peek();
- int next_beg_pos = peek_position();
- int next_end_pos = peek_end_position();
+ Scanner::Location next_loc = scanner()->peek_location();
- ExpressionT name_expression =
- ParsePropertyName(&name, &kind, &function_flags, is_computed_name,
- CHECK_OK_CUSTOM(NullLiteralProperty));
+ ExpressionT name_expression = ParseProperty(prop_info);
+ IdentifierT name = prop_info->name;
+ ParseFunctionFlags function_flags = prop_info->function_flags;
+ ParsePropertyKind kind = prop_info->kind;
- switch (kind) {
+ switch (prop_info->kind) {
case ParsePropertyKind::kSpread:
DCHECK_EQ(function_flags, ParseFunctionFlag::kIsNormal);
- DCHECK(!*is_computed_name);
+ DCHECK(!prop_info->is_computed_name);
DCHECK_EQ(Token::ELLIPSIS, name_token);
- *is_computed_name = true;
- *is_rest_property = true;
+ prop_info->is_computed_name = true;
+ prop_info->is_rest = true;
return factory()->NewObjectLiteralProperty(
factory()->NewTheHoleLiteral(), name_expression,
@@ -2568,21 +2284,27 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ObjectLiteralChecker* checker,
case ParsePropertyKind::kValue: {
DCHECK_EQ(function_flags, ParseFunctionFlag::kIsNormal);
- if (!*is_computed_name) {
- checker->CheckDuplicateProto(name_token);
+ if (!prop_info->is_computed_name &&
+ impl()->IdentifierEquals(name, ast_value_factory()->proto_string())) {
+ if (*has_seen_proto) {
+ expression_scope()->RecordExpressionError(
+ scanner()->location(), MessageTemplate::kDuplicateProto);
+ }
+ *has_seen_proto = true;
}
Consume(Token::COLON);
- int beg_pos = peek_position();
+ AcceptINScope scope(this, true);
ExpressionT value =
- ParseAssignmentExpression(true, CHECK_OK_CUSTOM(NullLiteralProperty));
- CheckDestructuringElement(value, beg_pos, end_position());
+ ParsePossibleDestructuringSubPattern(prop_info->accumulation_scope);
ObjectLiteralPropertyT result = factory()->NewObjectLiteralProperty(
- name_expression, value, *is_computed_name);
+ name_expression, value, prop_info->is_computed_name);
impl()->SetFunctionNameFromPropertyName(result, name);
return result;
}
+ case ParsePropertyKind::kAssign:
+ case ParsePropertyKind::kShorthandOrClassField:
case ParsePropertyKind::kShorthand: {
// PropertyDefinition
// IdentifierReference
@@ -2592,56 +2314,43 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ObjectLiteralChecker* checker,
// IdentifierReference Initializer?
DCHECK_EQ(function_flags, ParseFunctionFlag::kIsNormal);
- if (!Token::IsIdentifier(name_token, language_mode(),
- this->is_generator(),
- parsing_module_ || is_async_function())) {
+ if (!Token::IsValidIdentifier(name_token, language_mode(), is_generator(),
+ parsing_module_ || is_async_function())) {
ReportUnexpectedToken(Next());
- *ok = false;
return impl()->NullLiteralProperty();
}
- DCHECK(!*is_computed_name);
-
- if (classifier()->duplicate_finder() != nullptr &&
- scanner()->IsDuplicateSymbol(classifier()->duplicate_finder(),
- ast_value_factory())) {
- classifier()->RecordDuplicateFormalParameterError(
- scanner()->location());
- }
-
- if (impl()->IsEvalOrArguments(name) && is_strict(language_mode())) {
- classifier()->RecordBindingPatternError(
- scanner()->location(), MessageTemplate::kStrictEvalArguments);
- }
+ DCHECK(!prop_info->is_computed_name);
if (name_token == Token::LET) {
- classifier()->RecordLetPatternError(
+ expression_scope()->RecordLexicalDeclarationError(
scanner()->location(), MessageTemplate::kLetInLexicalBinding);
}
if (name_token == Token::AWAIT) {
DCHECK(!is_async_function());
- classifier()->RecordAsyncArrowFormalParametersError(
- Scanner::Location(next_beg_pos, next_end_pos),
- MessageTemplate::kAwaitBindingIdentifier);
+ expression_scope()->RecordAsyncArrowParametersError(
+ next_loc, MessageTemplate::kAwaitBindingIdentifier);
+ }
+ ExpressionT lhs =
+ impl()->ExpressionFromIdentifier(name, next_loc.beg_pos);
+ if (!IsAssignableIdentifier(lhs)) {
+ expression_scope()->RecordPatternError(
+ next_loc, MessageTemplate::kStrictEvalArguments);
}
- ExpressionT lhs = impl()->ExpressionFromIdentifier(name, next_beg_pos);
- CheckDestructuringElement(lhs, next_beg_pos, next_end_pos);
ExpressionT value;
if (peek() == Token::ASSIGN) {
Consume(Token::ASSIGN);
- ExpressionClassifier rhs_classifier(this);
- ExpressionT rhs = ParseAssignmentExpression(
- true, CHECK_OK_CUSTOM(NullLiteralProperty));
- ValidateExpression(CHECK_OK_CUSTOM(NullLiteralProperty));
- AccumulateFormalParameterContainmentErrors();
- value = factory()->NewAssignment(Token::ASSIGN, lhs, rhs,
- kNoSourcePosition);
- classifier()->RecordExpressionError(
- Scanner::Location(next_beg_pos, end_position()),
+ {
+ AcceptINScope scope(this, true);
+ ExpressionT rhs = ParseAssignmentExpression();
+ value = factory()->NewAssignment(Token::ASSIGN, lhs, rhs,
+ kNoSourcePosition);
+ impl()->SetFunctionNameFromIdentifierRef(rhs, lhs);
+ }
+ expression_scope()->RecordExpressionError(
+ Scanner::Location(next_loc.beg_pos, end_position()),
MessageTemplate::kInvalidCoverInitializedName);
-
- impl()->SetFunctionNameFromIdentifierRef(rhs, lhs);
} else {
value = lhs;
}
@@ -2657,20 +2366,20 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ObjectLiteralChecker* checker,
// PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}'
// '*' PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}'
- classifier()->RecordPatternError(
- Scanner::Location(next_beg_pos, end_position()),
+ expression_scope()->RecordPatternError(
+ Scanner::Location(next_loc.beg_pos, end_position()),
MessageTemplate::kInvalidDestructuringTarget);
FunctionKind kind = MethodKindFor(function_flags);
ExpressionT value = impl()->ParseFunctionLiteral(
name, scanner()->location(), kSkipFunctionNameCheck, kind,
- next_beg_pos, FunctionLiteral::kAccessorOrMethod, language_mode(),
- nullptr, CHECK_OK_CUSTOM(NullLiteralProperty));
+ next_loc.beg_pos, FunctionLiteral::kAccessorOrMethod, language_mode(),
+ nullptr);
ObjectLiteralPropertyT result = factory()->NewObjectLiteralProperty(
name_expression, value, ObjectLiteralProperty::COMPUTED,
- *is_computed_name);
+ prop_info->is_computed_name);
impl()->SetFunctionNameFromPropertyName(result, name);
return result;
}
@@ -2680,11 +2389,11 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ObjectLiteralChecker* checker,
DCHECK_EQ(function_flags, ParseFunctionFlag::kIsNormal);
bool is_get = kind == ParsePropertyKind::kAccessorGetter;
- classifier()->RecordPatternError(
- Scanner::Location(next_beg_pos, end_position()),
+ expression_scope()->RecordPatternError(
+ Scanner::Location(next_loc.beg_pos, end_position()),
MessageTemplate::kInvalidDestructuringTarget);
- if (!*is_computed_name) {
+ if (!prop_info->is_computed_name) {
// 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.
@@ -2697,14 +2406,14 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ObjectLiteralChecker* checker,
FunctionLiteralT value = impl()->ParseFunctionLiteral(
name, scanner()->location(), kSkipFunctionNameCheck, kind,
- next_beg_pos, FunctionLiteral::kAccessorOrMethod, language_mode(),
- nullptr, CHECK_OK_CUSTOM(NullLiteralProperty));
+ next_loc.beg_pos, FunctionLiteral::kAccessorOrMethod, language_mode(),
+ nullptr);
ObjectLiteralPropertyT result = factory()->NewObjectLiteralProperty(
name_expression, value,
is_get ? ObjectLiteralProperty::GETTER
: ObjectLiteralProperty::SETTER,
- *is_computed_name);
+ prop_info->is_computed_name);
const AstRawString* prefix =
is_get ? ast_value_factory()->get_space_string()
: ast_value_factory()->set_space_string();
@@ -2715,42 +2424,41 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ObjectLiteralChecker* checker,
case ParsePropertyKind::kClassField:
case ParsePropertyKind::kNotSet:
ReportUnexpectedToken(Next());
- *ok = false;
return impl()->NullLiteralProperty();
}
UNREACHABLE();
}
template <typename Impl>
-typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseObjectLiteral(
- bool* ok) {
+typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseObjectLiteral() {
// ObjectLiteral ::
// '{' (PropertyDefinition (',' PropertyDefinition)* ','? )? '}'
int pos = peek_position();
- typename Types::ObjectPropertyList properties =
- impl()->NewObjectPropertyList(4);
+ ObjectPropertyListT properties(pointer_buffer());
int number_of_boilerplate_properties = 0;
bool has_computed_names = false;
bool has_rest_property = false;
- ObjectLiteralChecker checker(this);
+ bool has_seen_proto = false;
Consume(Token::LBRACE);
+ AccumulationScope accumulation_scope(expression_scope());
while (!Check(Token::RBRACE)) {
FuncNameInferrerState fni_state(&fni_);
- bool is_computed_name = false;
- bool is_rest_property = false;
- ObjectLiteralPropertyT property = ParseObjectPropertyDefinition(
- &checker, &is_computed_name, &is_rest_property, CHECK_OK);
+ ParsePropertyInfo prop_info(this, &accumulation_scope);
+ prop_info.position = PropertyPosition::kObjectLiteral;
+ ObjectLiteralPropertyT property =
+ ParseObjectPropertyDefinition(&prop_info, &has_seen_proto);
+ if (impl()->IsNull(property)) return impl()->FailureExpression();
- if (is_computed_name) {
+ if (prop_info.is_computed_name) {
has_computed_names = true;
}
- if (is_rest_property) {
+ if (prop_info.is_rest) {
has_rest_property = true;
}
@@ -2760,11 +2468,10 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseObjectLiteral(
number_of_boilerplate_properties++;
}
- properties->Add(property, zone());
+ properties.Add(property);
if (peek() != Token::RBRACE) {
- // Need {} because of the CHECK_OK macro.
- Expect(Token::COMMA, CHECK_OK);
+ Expect(Token::COMMA);
}
fni_.Infer();
@@ -2775,8 +2482,8 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseObjectLiteral(
// this runtime function. Here, we make sure that the number of
// properties is less than number of arguments allowed for a runtime
// call.
- if (has_rest_property && properties->length() > Code::kMaxArguments) {
- this->classifier()->RecordPatternError(Scanner::Location(pos, position()),
+ if (has_rest_property && properties.length() > Code::kMaxArguments) {
+ expression_scope()->RecordPatternError(Scanner::Location(pos, position()),
MessageTemplate::kTooManyArguments);
}
@@ -2785,78 +2492,61 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseObjectLiteral(
}
template <typename Impl>
-typename ParserBase<Impl>::ExpressionListT ParserBase<Impl>::ParseArguments(
- Scanner::Location* first_spread_arg_loc, bool maybe_arrow,
- bool* is_simple_parameter_list, bool* ok) {
+void ParserBase<Impl>::ParseArguments(
+ typename ParserBase<Impl>::ExpressionListT* args, bool* has_spread,
+ ParsingArrowHeadFlag maybe_arrow) {
// Arguments ::
// '(' (AssignmentExpression)*[','] ')'
- Scanner::Location spread_arg = Scanner::Location::invalid();
- ExpressionListT result = impl()->NewExpressionList(4);
- Expect(Token::LPAREN, CHECK_OK_CUSTOM(NullExpressionList));
+ *has_spread = false;
+ Consume(Token::LPAREN);
+ AccumulationScope accumulation_scope(expression_scope());
+
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 = false;
+ AcceptINScope scope(this, true);
+ ExpressionT argument = ParseAssignmentExpressionCoverGrammar();
- if (!maybe_arrow) {
- ValidateExpression(CHECK_OK_CUSTOM(NullExpressionList));
+ if (V8_UNLIKELY(maybe_arrow == kMaybeArrowHead)) {
+ ClassifyArrowParameter(&accumulation_scope, expr_pos, argument);
+ if (is_spread) {
+ expression_scope()->RecordNonSimpleParameter();
+ if (argument->IsAssignment()) {
+ expression_scope()->RecordAsyncArrowParametersError(
+ scanner()->location(), MessageTemplate::kRestDefaultInitializer);
+ }
+ if (peek() == Token::COMMA) {
+ expression_scope()->RecordAsyncArrowParametersError(
+ scanner()->peek_location(), MessageTemplate::kParamAfterRest);
+ }
+ }
}
if (is_spread) {
- *is_simple_parameter_list = false;
- if (!spread_arg.IsValid()) {
- spread_arg.beg_pos = start_pos;
- spread_arg.end_pos = peek_position();
- }
- if (argument->IsAssignment()) {
- classifier()->RecordAsyncArrowFormalParametersError(
- scanner()->location(), MessageTemplate::kRestDefaultInitializer);
- }
+ *has_spread = true;
argument = factory()->NewSpread(argument, start_pos, expr_pos);
}
- result->Add(argument, zone_);
-
- if (peek() != Token::COMMA) break;
-
- Next();
-
- if (argument->IsSpread()) {
- classifier()->RecordAsyncArrowFormalParametersError(
- scanner()->location(), MessageTemplate::kParamAfterRest);
- }
+ args->Add(argument);
+ if (!Check(Token::COMMA)) break;
}
- if (result->length() > Code::kMaxArguments) {
+ if (args->length() > Code::kMaxArguments) {
ReportMessage(MessageTemplate::kTooManyArguments);
- *ok = false;
- return impl()->NullExpressionList();
+ return;
}
Scanner::Location location = scanner_->location();
- if (Token::RPAREN != Next()) {
+ if (!Check(Token::RPAREN)) {
impl()->ReportMessageAt(location, MessageTemplate::kUnterminatedArgList);
- *ok = false;
- return impl()->NullExpressionList();
- }
- *first_spread_arg_loc = spread_arg;
-
- if (!maybe_arrow || peek() != Token::ARROW) {
- if (maybe_arrow) {
- ValidateExpression(CHECK_OK_CUSTOM(NullExpressionList));
- }
}
-
- return result;
}
// Precedence = 2
template <typename Impl>
typename ParserBase<Impl>::ExpressionT
-ParserBase<Impl>::ParseAssignmentExpression(bool accept_IN, bool* ok) {
+ParserBase<Impl>::ParseAssignmentExpressionCoverGrammar() {
// AssignmentExpression ::
// ConditionalExpression
// ArrowFunction
@@ -2865,188 +2555,120 @@ ParserBase<Impl>::ParseAssignmentExpression(bool accept_IN, bool* ok) {
int lhs_beg_pos = peek_position();
if (peek() == Token::YIELD && is_generator()) {
- return ParseYieldExpression(accept_IN, ok);
+ return ParseYieldExpression();
}
FuncNameInferrerState fni_state(&fni_);
- ExpressionClassifier arrow_formals_classifier(
- this, classifier()->duplicate_finder());
- Scope::Snapshot scope_snapshot(scope());
- int rewritable_length = static_cast<int>(
- function_state_->destructuring_assignments_to_rewrite().size());
+ DCHECK_IMPLIES(!has_error(), next_arrow_function_info_.HasInitialState());
- bool is_async = peek() == Token::ASYNC &&
- !scanner()->HasLineTerminatorAfterNext() &&
- IsValidArrowFormalParametersStart(PeekAhead());
+ ExpressionT expression = ParseConditionalExpression();
- bool parenthesized_formals = peek() == Token::LPAREN;
- if (!is_async && !parenthesized_formals) {
- ArrowFormalParametersUnexpectedToken();
- }
-
- // Parse a simple, faster sub-grammar (primary expression) if it's evident
- // that we have only a trivial expression to parse.
- ExpressionT expression;
- if (IsTrivialExpression()) {
- expression = ParsePrimaryExpression(&is_async, CHECK_OK);
- } else {
- expression = ParseConditionalExpression(accept_IN, CHECK_OK);
- }
+ Token::Value op = peek();
- if (is_async && impl()->IsIdentifier(expression) && peek_any_identifier() &&
- PeekAhead() == Token::ARROW) {
- // async Identifier => AsyncConciseBody
- IdentifierT name = ParseAndClassifyIdentifier(CHECK_OK);
- expression =
- impl()->ExpressionFromIdentifier(name, position(), InferName::kNo);
- // Remove `async` keyword from inferred name stack.
- fni_.RemoveAsyncKeywordFromEnd();
- }
-
- if (peek() == Token::ARROW) {
- Scanner::Location arrow_loc = scanner()->peek_location();
- ValidateArrowFormalParameters(expression, parenthesized_formals, is_async,
- CHECK_OK);
- // This reads strangely, but is correct: it checks whether any
- // sub-expression of the parameter list failed to be a valid formal
- // parameter initializer. Since YieldExpressions are banned anywhere
- // in an arrow parameter list, this is correct.
- // TODO(adamk): Rename "FormalParameterInitializerError" to refer to
- // "YieldExpression", which is its only use.
- ValidateFormalParameterInitializer(CHECK_OK);
+ if (!Token::IsArrowOrAssignmentOp(op)) return expression;
+ // Arrow functions.
+ if (V8_UNLIKELY(op == Token::ARROW)) {
Scanner::Location loc(lhs_beg_pos, end_position());
- DeclarationScope* scope =
- NewFunctionScope(is_async ? FunctionKind::kAsyncArrowFunction
- : FunctionKind::kArrowFunction);
- // Because the arrow's parameters were parsed in the outer scope,
- // we need to fix up the scope chain appropriately.
- scope_snapshot.Reparent(scope);
-
- FormalParametersT parameters(scope);
- if (!classifier()->is_simple_parameter_list()) {
- scope->SetHasNonSimpleParameters();
- parameters.is_simple = false;
+ if (!impl()->IsIdentifier(expression) && !expression->is_parenthesized()) {
+ impl()->ReportMessageAt(
+ Scanner::Location(expression->position(), position()),
+ MessageTemplate::kMalformedArrowFunParamList);
+ return impl()->FailureExpression();
}
+ DeclarationScope* scope = next_arrow_function_info_.scope;
scope->set_start_position(lhs_beg_pos);
- Scanner::Location duplicate_loc = Scanner::Location::invalid();
- impl()->DeclareArrowFunctionFormalParameters(&parameters, expression, loc,
- &duplicate_loc, CHECK_OK);
- if (duplicate_loc.IsValid()) {
- classifier()->RecordDuplicateFormalParameterError(duplicate_loc);
- }
- expression = ParseArrowFunctionLiteral(accept_IN, parameters,
- rewritable_length, CHECK_OK);
- Accumulate(ExpressionClassifier::AsyncArrowFormalParametersProduction);
- classifier()->RecordPatternError(arrow_loc,
- MessageTemplate::kUnexpectedToken,
- Token::String(Token::ARROW));
- fni_.Infer();
-
- return expression;
- }
+ FormalParametersT parameters(scope);
+ parameters.set_strict_parameter_error(
+ next_arrow_function_info_.strict_parameter_error_location,
+ next_arrow_function_info_.strict_parameter_error_message);
+ parameters.is_simple = scope->has_simple_parameters();
+ next_arrow_function_info_.Reset();
- // "expression" was not itself an arrow function parameter list, but it might
- // form part of one. Propagate speculative formal parameter error locations
- // (including those for binding patterns, since formal parameters can
- // themselves contain binding patterns).
- unsigned productions = ExpressionClassifier::AllProductions &
- ~ExpressionClassifier::ArrowFormalParametersProduction;
+ impl()->DeclareArrowFunctionFormalParameters(&parameters, expression, loc);
- // Parenthesized identifiers and property references are allowed as part
- // of a larger assignment pattern, even though parenthesized patterns
- // themselves are not allowed, e.g., "[(x)] = []". Only accumulate
- // assignment pattern errors if the parsed expression is more complex.
- if (IsValidReferenceExpression(expression)) {
- productions &= ~ExpressionClassifier::AssignmentPatternProduction;
- }
+ expression = ParseArrowFunctionLiteral(parameters);
- const bool is_destructuring_assignment =
- IsValidPattern(expression) && peek() == Token::ASSIGN;
- if (is_destructuring_assignment) {
- // This is definitely not an expression so don't accumulate
- // expression-related errors.
- productions &= ~ExpressionClassifier::ExpressionProduction;
+ return expression;
}
- Accumulate(productions);
- if (!Token::IsAssignmentOp(peek())) return expression;
-
- if (is_destructuring_assignment) {
- ValidateAssignmentPattern(CHECK_OK);
+ if (V8_LIKELY(impl()->IsAssignableIdentifier(expression))) {
+ if (expression->is_parenthesized()) {
+ expression_scope()->RecordDeclarationError(
+ Scanner::Location(lhs_beg_pos, end_position()),
+ MessageTemplate::kInvalidDestructuringTarget);
+ }
+ expression_scope()->MarkIdentifierAsAssigned();
+ } else if (expression->IsProperty()) {
+ expression_scope()->RecordDeclarationError(
+ Scanner::Location(lhs_beg_pos, end_position()),
+ MessageTemplate::kInvalidPropertyBindingPattern);
+ } else if (expression->IsPattern() && op == Token::ASSIGN) {
+ // Destructuring assignmment.
+ if (expression->is_parenthesized()) {
+ expression_scope()->RecordPatternError(
+ Scanner::Location(lhs_beg_pos, end_position()),
+ MessageTemplate::kInvalidDestructuringTarget);
+ }
+ expression_scope()->ValidateAsPattern(expression, lhs_beg_pos,
+ end_position());
} else {
- expression = CheckAndRewriteReferenceExpression(
+ DCHECK(!IsValidReferenceExpression(expression));
+ expression = RewriteInvalidReferenceExpression(
expression, lhs_beg_pos, end_position(),
- MessageTemplate::kInvalidLhsInAssignment, CHECK_OK);
+ MessageTemplate::kInvalidLhsInAssignment);
}
- impl()->MarkExpressionAsAssigned(expression);
+ Consume(op);
+ int op_position = position();
- Token::Value op = Next(); // Get assignment operator.
- if (op != Token::ASSIGN) {
- classifier()->RecordPatternError(scanner()->location(),
- MessageTemplate::kUnexpectedToken,
- Token::String(op));
- }
- int pos = position();
-
- ExpressionClassifier rhs_classifier(this);
+ ExpressionT right = ParseAssignmentExpression();
- ExpressionT right = ParseAssignmentExpression(accept_IN, CHECK_OK);
- ValidateExpression(CHECK_OK);
- AccumulateFormalParameterContainmentErrors();
-
- // We try to estimate the set of properties set by constructors. We define a
- // new property whenever there is an assignment to a property of 'this'. We
- // should probably only add properties if we haven't seen them
- // before. Otherwise we'll probably overestimate the number of properties.
- if (op == Token::ASSIGN && impl()->IsThisProperty(expression)) {
- function_state_->AddProperty();
- }
-
- impl()->CheckAssigningFunctionLiteralToProperty(expression, right);
+ if (op == Token::ASSIGN) {
+ // We try to estimate the set of properties set by constructors. We define a
+ // new property whenever there is an assignment to a property of 'this'. We
+ // should probably only add properties if we haven't seen them before.
+ // Otherwise we'll probably overestimate the number of properties.
+ if (impl()->IsThisProperty(expression)) function_state_->AddProperty();
+
+ impl()->CheckAssigningFunctionLiteralToProperty(expression, right);
+
+ // Check if the right hand side is a call to avoid inferring a
+ // name if we're dealing with "a = function(){...}();"-like
+ // expression.
+ if (right->IsCall() || right->IsCallNew()) {
+ fni_.RemoveLastFunction();
+ } else {
+ fni_.Infer();
+ }
- // 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();
+ impl()->SetFunctionNameFromIdentifierRef(right, expression);
} else {
+ expression_scope()->RecordPatternError(
+ Scanner::Location(lhs_beg_pos, end_position()),
+ MessageTemplate::kInvalidDestructuringTarget);
fni_.RemoveLastFunction();
}
- if (op == Token::ASSIGN) {
- impl()->SetFunctionNameFromIdentifierRef(right, expression);
- }
-
- DCHECK_NE(op, Token::INIT);
- ExpressionT result = factory()->NewAssignment(op, expression, right, pos);
-
- if (is_destructuring_assignment) {
- DCHECK_NE(op, Token::ASSIGN_EXP);
- auto rewritable = factory()->NewRewritableExpression(result, scope());
- impl()->QueueDestructuringAssignmentForRewriting(rewritable);
- result = rewritable;
- }
-
- return result;
+ return factory()->NewAssignment(op, expression, right, op_position);
}
template <typename Impl>
-typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseYieldExpression(
- bool accept_IN, bool* ok) {
+typename ParserBase<Impl>::ExpressionT
+ParserBase<Impl>::ParseYieldExpression() {
// YieldExpression ::
// 'yield' ([no line terminator] '*'? AssignmentExpression)?
int pos = peek_position();
- classifier()->RecordPatternError(
- scanner()->peek_location(), MessageTemplate::kInvalidDestructuringTarget);
- classifier()->RecordFormalParameterInitializerError(
+ expression_scope()->RecordParameterInitializerError(
scanner()->peek_location(), MessageTemplate::kYieldInParameter);
- Expect(Token::YIELD, CHECK_OK);
+ Consume(Token::YIELD);
+
+ CheckStackOverflow();
+
// The following initialization is necessary.
ExpressionT expression = impl()->NullExpression();
bool delegating = false; // yield*
@@ -3069,8 +2691,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseYieldExpression(
// Delegating yields require an RHS; fall through.
V8_FALLTHROUGH;
default:
- expression = ParseAssignmentExpression(accept_IN, CHECK_OK);
- ValidateExpression(CHECK_OK);
+ expression = ParseAssignmentExpressionCoverGrammar();
break;
}
}
@@ -3099,80 +2720,65 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseYieldExpression(
// Precedence = 3
template <typename Impl>
typename ParserBase<Impl>::ExpressionT
-ParserBase<Impl>::ParseConditionalExpression(bool accept_IN,
- bool* ok) {
+ParserBase<Impl>::ParseConditionalExpression() {
// ConditionalExpression ::
// LogicalOrExpression
// LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
int pos = peek_position();
// We start using the binary expression parser for prec >= 4 only!
- ExpressionT expression = ParseBinaryExpression(4, accept_IN, CHECK_OK);
+ ExpressionT expression = ParseBinaryExpression(4);
return peek() == Token::CONDITIONAL
- ? ParseConditionalContinuation(expression, accept_IN, pos, ok)
+ ? ParseConditionalContinuation(expression, pos)
: expression;
}
template <typename Impl>
typename ParserBase<Impl>::ExpressionT
ParserBase<Impl>::ParseConditionalContinuation(ExpressionT expression,
- bool accept_IN, int pos,
- bool* ok) {
+ int pos) {
SourceRange then_range, else_range;
- ValidateExpression(CHECK_OK);
- BindingPatternUnexpectedToken();
- ArrowFormalParametersUnexpectedToken();
ExpressionT left;
{
SourceRangeScope range_scope(scanner(), &then_range);
Consume(Token::CONDITIONAL);
- ExpressionClassifier classifier(this);
// In parsing the first assignment expression in conditional
// expressions we always accept the 'in' keyword; see ECMA-262,
// section 11.12, page 58.
- left = ParseAssignmentExpression(true, CHECK_OK);
- AccumulateNonBindingPatternErrors();
+ AcceptINScope scope(this, true);
+ left = ParseAssignmentExpression();
}
- ValidateExpression(CHECK_OK);
ExpressionT right;
{
SourceRangeScope range_scope(scanner(), &else_range);
- Expect(Token::COLON, CHECK_OK);
- ExpressionClassifier classifier(this);
- right = ParseAssignmentExpression(accept_IN, CHECK_OK);
- AccumulateNonBindingPatternErrors();
+ Expect(Token::COLON);
+ right = ParseAssignmentExpression();
}
- ValidateExpression(CHECK_OK);
ExpressionT expr = factory()->NewConditional(expression, left, right, pos);
impl()->RecordConditionalSourceRange(expr, then_range, else_range);
return expr;
}
-
// Precedence >= 4
template <typename Impl>
-typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseBinaryExpression(
- int prec, bool accept_IN, bool* ok) {
- DCHECK_GE(prec, 4);
- SourceRange right_range;
- ExpressionT x = ParseUnaryExpression(CHECK_OK);
- for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
+typename ParserBase<Impl>::ExpressionT
+ParserBase<Impl>::ParseBinaryContinuation(ExpressionT x, int prec, int prec1) {
+ do {
// prec1 >= 4
- while (Precedence(peek(), accept_IN) == prec1) {
- ValidateExpression(CHECK_OK);
- BindingPatternUnexpectedToken();
- ArrowFormalParametersUnexpectedToken();
-
- SourceRangeScope right_range_scope(scanner(), &right_range);
- Token::Value op = Next();
- int pos = position();
-
- const bool is_right_associative = op == Token::EXP;
- const int next_prec = is_right_associative ? prec1 : prec1 + 1;
- ExpressionT y = ParseBinaryExpression(next_prec, accept_IN, CHECK_OK);
- right_range_scope.Finalize();
- ValidateExpression(CHECK_OK);
+ while (Token::Precedence(peek(), accept_IN_) == prec1) {
+ SourceRange right_range;
+ int pos = peek_position();
+ ExpressionT y;
+ Token::Value op;
+ {
+ SourceRangeScope right_range_scope(scanner(), &right_range);
+ op = Next();
+
+ const bool is_right_associative = op == Token::EXP;
+ const int next_prec = is_right_associative ? prec1 : prec1 + 1;
+ y = ParseBinaryExpression(next_prec);
+ }
// For now we distinguish between comparisons and other binary
// operations. (We could combine the two and get rid of this
@@ -3200,16 +2806,28 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseBinaryExpression(
}
}
}
- }
+ --prec1;
+ } while (prec1 >= prec);
+
return x;
}
+// Precedence >= 4
template <typename Impl>
-typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseUnaryOpExpression(
- bool* ok) {
- BindingPatternUnexpectedToken();
- ArrowFormalParametersUnexpectedToken();
+typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseBinaryExpression(
+ int prec) {
+ DCHECK_GE(prec, 4);
+ ExpressionT x = ParseUnaryExpression();
+ int prec1 = Token::Precedence(peek(), accept_IN_);
+ if (prec1 >= prec) {
+ return ParseBinaryContinuation(x, prec, prec1);
+ }
+ return x;
+}
+template <typename Impl>
+typename ParserBase<Impl>::ExpressionT
+ParserBase<Impl>::ParseUnaryOrPrefixExpression() {
Token::Value op = Next();
int pos = position();
@@ -3218,66 +2836,64 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseUnaryOpExpression(
function_state_->set_next_function_is_likely_called();
}
- ExpressionT expression = ParseUnaryExpression(CHECK_OK);
- ValidateExpression(CHECK_OK);
+ CheckStackOverflow();
+
+ int expression_position = peek_position();
+ ExpressionT expression = ParseUnaryExpression();
+
+ if (Token::IsUnaryOp(op)) {
+ if (op == Token::DELETE) {
+ if (impl()->IsIdentifier(expression) && is_strict(language_mode())) {
+ // "delete identifier" is a syntax error in strict mode.
+ ReportMessage(MessageTemplate::kStrictDelete);
+ return impl()->FailureExpression();
+ }
- 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 (impl()->IsPropertyWithPrivateFieldKey(expression)) {
+ ReportMessage(MessageTemplate::kDeletePrivateField);
+ return impl()->FailureExpression();
+ }
}
- if (impl()->IsPropertyWithPrivateFieldKey(expression)) {
- ReportMessage(MessageTemplate::kDeletePrivateField);
- *ok = false;
- return impl()->NullExpression();
+ if (peek() == Token::EXP) {
+ impl()->ReportMessageAt(
+ Scanner::Location(pos, peek_end_position()),
+ MessageTemplate::kUnexpectedTokenUnaryExponentiation);
+ return impl()->FailureExpression();
}
- }
- if (peek() == Token::EXP) {
- ReportUnexpectedToken(Next());
- *ok = false;
- return impl()->NullExpression();
+ // Allow the parser's implementation to rewrite the expression.
+ return impl()->BuildUnaryExpression(expression, op, pos);
}
- // Allow the parser's implementation to rewrite the expression.
- return impl()->BuildUnaryExpression(expression, op, pos);
-}
+ DCHECK(Token::IsCountOp(op));
-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);
+ if (V8_LIKELY(IsValidReferenceExpression(expression))) {
+ if (impl()->IsIdentifier(expression)) {
+ expression_scope()->MarkIdentifierAsAssigned();
+ }
+ } else {
+ expression = RewriteInvalidReferenceExpression(
+ expression, expression_position, end_position(),
+ MessageTemplate::kInvalidLhsInPrefixOp);
+ }
return factory()->NewCountOperation(op, true /* prefix */, expression,
position());
}
template <typename Impl>
-typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseAwaitExpression(
- bool* ok) {
- classifier()->RecordFormalParameterInitializerError(
+typename ParserBase<Impl>::ExpressionT
+ParserBase<Impl>::ParseAwaitExpression() {
+ expression_scope()->RecordParameterInitializerError(
scanner()->peek_location(),
MessageTemplate::kAwaitExpressionFormalParameter);
int await_pos = peek_position();
Consume(Token::AWAIT);
- ExpressionT value = ParseUnaryExpression(CHECK_OK);
+ CheckStackOverflow();
- classifier()->RecordBindingPatternError(
- Scanner::Location(await_pos, end_position()),
- MessageTemplate::kInvalidDestructuringTarget);
+ ExpressionT value = ParseUnaryExpression();
ExpressionT expr = factory()->NewAwait(value, await_pos);
function_state_->AddSuspend();
@@ -3286,8 +2902,8 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseAwaitExpression(
}
template <typename Impl>
-typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseUnaryExpression(
- bool* ok) {
+typename ParserBase<Impl>::ExpressionT
+ParserBase<Impl>::ParseUnaryExpression() {
// UnaryExpression ::
// PostfixExpression
// 'delete' UnaryExpression
@@ -3302,31 +2918,30 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseUnaryExpression(
// [+Await] AwaitExpression[?Yield]
Token::Value op = peek();
- if (Token::IsUnaryOp(op)) return ParseUnaryOpExpression(ok);
- if (Token::IsCountOp(op)) return ParsePrefixExpression(ok);
+ if (Token::IsUnaryOrCountOp(op)) return ParseUnaryOrPrefixExpression();
if (is_async_function() && op == Token::AWAIT) {
- return ParseAwaitExpression(ok);
+ return ParseAwaitExpression();
}
- return ParsePostfixExpression(ok);
+ return ParsePostfixExpression();
}
template <typename Impl>
-typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePostfixExpression(
- bool* ok) {
+typename ParserBase<Impl>::ExpressionT
+ParserBase<Impl>::ParsePostfixExpression() {
// PostfixExpression ::
// LeftHandSideExpression ('++' | '--')?
int lhs_beg_pos = peek_position();
- ExpressionT expression = ParseLeftHandSideExpression(CHECK_OK);
+ ExpressionT expression = ParseLeftHandSideExpression();
if (!scanner()->HasLineTerminatorBeforeNext() && Token::IsCountOp(peek())) {
- BindingPatternUnexpectedToken();
- ArrowFormalParametersUnexpectedToken();
-
- expression = CheckAndRewriteReferenceExpression(
- expression, lhs_beg_pos, end_position(),
- MessageTemplate::kInvalidLhsInPostfixOp, CHECK_OK);
- impl()->MarkExpressionAsAssigned(expression);
- ValidateExpression(CHECK_OK);
+ if (V8_UNLIKELY(!IsValidReferenceExpression(expression))) {
+ expression = RewriteInvalidReferenceExpression(
+ expression, lhs_beg_pos, end_position(),
+ MessageTemplate::kInvalidLhsInPostfixOp);
+ }
+ if (impl()->IsIdentifier(expression)) {
+ expression_scope()->MarkIdentifierAsAssigned();
+ }
Token::Value next = Next();
expression =
@@ -3340,36 +2955,83 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePostfixExpression(
template <typename Impl>
typename ParserBase<Impl>::ExpressionT
-ParserBase<Impl>::ParseLeftHandSideExpression(bool* ok) {
+ParserBase<Impl>::ParseLeftHandSideExpression() {
// LeftHandSideExpression ::
// (NewExpression | MemberExpression) ...
- bool is_async = false;
- ExpressionT result =
- ParseMemberWithNewPrefixesExpression(&is_async, CHECK_OK);
+ ExpressionT result = ParseMemberWithNewPrefixesExpression();
+ if (!Token::IsPropertyOrCall(peek())) return result;
+ return ParseLeftHandSideContinuation(result);
+}
- while (true) {
+template <typename Impl>
+typename ParserBase<Impl>::ExpressionT
+ParserBase<Impl>::ParseLeftHandSideContinuation(ExpressionT result) {
+ DCHECK(Token::IsPropertyOrCall(peek()));
+
+ if (V8_UNLIKELY(peek() == Token::LPAREN && impl()->IsIdentifier(result) &&
+ scanner()->current_token() == Token::ASYNC &&
+ !scanner()->HasLineTerminatorBeforeNext())) {
+ DCHECK(impl()->IsAsync(impl()->AsIdentifier(result)));
+ int pos = position();
+
+ ArrowHeadParsingScope maybe_arrow(impl(),
+ FunctionKind::kAsyncArrowFunction);
+ Scope::Snapshot scope_snapshot(scope());
+
+ ExpressionListT args(pointer_buffer());
+ bool has_spread;
+ ParseArguments(&args, &has_spread, kMaybeArrowHead);
+ if (V8_LIKELY(peek() == Token::ARROW)) {
+ fni_.RemoveAsyncKeywordFromEnd();
+ next_arrow_function_info_.scope = maybe_arrow.ValidateAndCreateScope();
+ scope_snapshot.Reparent(next_arrow_function_info_.scope);
+ // async () => ...
+ if (!args.length()) return factory()->NewEmptyParentheses(pos);
+ // async ( Arguments ) => ...
+ ExpressionT result = impl()->ExpressionListToExpression(args);
+ result->mark_parenthesized();
+ return result;
+ }
+
+ if (has_spread) {
+ result = impl()->SpreadCall(result, args, pos, Call::NOT_EVAL);
+ } else {
+ result = factory()->NewCall(result, args, pos, Call::NOT_EVAL);
+ }
+
+ maybe_arrow.ValidateExpression();
+
+ fni_.RemoveLastFunction();
+ if (!Token::IsPropertyOrCall(peek())) return result;
+ }
+
+ do {
switch (peek()) {
+ /* Property */
case Token::LBRACK: {
- ValidateExpression(CHECK_OK);
- BindingPatternUnexpectedToken();
- ArrowFormalParametersUnexpectedToken();
Consume(Token::LBRACK);
int pos = position();
- ExpressionT index = ParseExpressionCoverGrammar(true, CHECK_OK);
- ValidateExpression(CHECK_OK);
+ AcceptINScope scope(this, true);
+ ExpressionT index = ParseExpressionCoverGrammar();
result = factory()->NewProperty(result, index, pos);
- Expect(Token::RBRACK, CHECK_OK);
+ Expect(Token::RBRACK);
break;
}
+ /* Property */
+ case Token::PERIOD: {
+ Consume(Token::PERIOD);
+ int pos = position();
+ ExpressionT key = ParsePropertyOrPrivatePropertyName();
+ result = factory()->NewProperty(result, key, pos);
+ break;
+ }
+
+ /* Call */
case Token::LPAREN: {
int pos;
- ValidateExpression(CHECK_OK);
- BindingPatternUnexpectedToken();
- if (scanner()->current_token() == Token::IDENTIFIER ||
- scanner()->current_token() == Token::SUPER ||
- scanner()->current_token() == Token::ASYNC) {
+ if (Token::IsCallable(scanner()->current_token())) {
// For call of an identifier we want to report position of
// the identifier as position of the call in the stack trace.
pos = position();
@@ -3385,43 +3047,16 @@ ParserBase<Impl>::ParseLeftHandSideExpression(bool* ok) {
// function literal eagerly, we can also compile it eagerly.
if (result->IsFunctionLiteral()) {
result->AsFunctionLiteral()->SetShouldEagerCompile();
- result->AsFunctionLiteral()->mark_as_iife();
- }
- }
- Scanner::Location spread_pos;
- ExpressionListT args;
- if (V8_UNLIKELY(is_async && impl()->IsIdentifier(result))) {
- ExpressionClassifier async_classifier(this);
- bool is_simple_parameter_list = true;
- args = ParseArguments(&spread_pos, true, &is_simple_parameter_list,
- CHECK_OK);
- if (peek() == Token::ARROW) {
- fni_.RemoveAsyncKeywordFromEnd();
- ValidateBindingPattern(CHECK_OK);
- ValidateFormalParameterInitializer(CHECK_OK);
- if (!classifier()->is_valid_async_arrow_formal_parameters()) {
- ReportClassifierError(
- classifier()->async_arrow_formal_parameters_error());
- *ok = false;
- return impl()->NullExpression();
- }
- if (args->length()) {
- // async ( Arguments ) => ...
- if (!is_simple_parameter_list) {
- async_classifier.previous()->RecordNonSimpleParameter();
- }
- return impl()->ExpressionListToExpression(args);
+ if (scope()->is_script_scope()) {
+ // A non-top-level iife is likely to be executed multiple times
+ // and so shouldn`t be optimized as one-shot.
+ result->AsFunctionLiteral()->mark_as_oneshot_iife();
}
- // async () => ...
- return factory()->NewEmptyParentheses(pos);
- } else {
- AccumulateFormalParameterContainmentErrors();
}
- } else {
- args = ParseArguments(&spread_pos, CHECK_OK);
}
-
- ArrowFormalParametersUnexpectedToken();
+ bool has_spread;
+ ExpressionListT args(pointer_buffer());
+ ParseArguments(&args, &has_spread);
// Keep track of eval() calls since they disable all local variable
// optimizations.
@@ -3433,7 +3068,7 @@ ParserBase<Impl>::ParseLeftHandSideExpression(bool* ok) {
Call::PossiblyEval is_possibly_eval =
CheckPossibleEvalCall(result, scope());
- if (spread_pos.IsValid()) {
+ if (has_spread) {
result = impl()->SpreadCall(result, args, pos, is_possibly_eval);
} else {
result = factory()->NewCall(result, args, pos, is_possibly_eval);
@@ -3443,36 +3078,19 @@ ParserBase<Impl>::ParseLeftHandSideExpression(bool* ok) {
break;
}
- case Token::PERIOD: {
- ValidateExpression(CHECK_OK);
- BindingPatternUnexpectedToken();
- ArrowFormalParametersUnexpectedToken();
- Consume(Token::PERIOD);
- int pos = position();
- ExpressionT key = ParseIdentifierNameOrPrivateName(CHECK_OK);
- result = factory()->NewProperty(result, key, pos);
- break;
- }
-
- case Token::TEMPLATE_SPAN:
- case Token::TEMPLATE_TAIL: {
- ValidateExpression(CHECK_OK);
- BindingPatternUnexpectedToken();
- ArrowFormalParametersUnexpectedToken();
- result = ParseTemplateLiteral(result, position(), true, CHECK_OK);
- break;
- }
-
+ /* Call */
default:
- return result;
+ DCHECK(Token::IsTemplate(peek()));
+ result = ParseTemplateLiteral(result, position(), true);
+ break;
}
- }
+ } while (Token::IsPropertyOrCall(peek()));
+ return result;
}
template <typename Impl>
typename ParserBase<Impl>::ExpressionT
-ParserBase<Impl>::ParseMemberWithPresentNewPrefixesExpression(bool* is_async,
- bool* ok) {
+ParserBase<Impl>::ParseMemberWithPresentNewPrefixesExpression() {
// NewExpression ::
// ('new')+ MemberExpression
//
@@ -3492,57 +3110,94 @@ ParserBase<Impl>::ParseMemberWithPresentNewPrefixesExpression(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;
+
+ CheckStackOverflow();
+
if (peek() == Token::SUPER) {
const bool is_new = true;
- result = ParseSuperExpression(is_new, CHECK_OK);
+ result = ParseSuperExpression(is_new);
} 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();
+ return impl()->FailureExpression();
} else if (peek() == Token::PERIOD) {
- *is_async = false;
- result = ParseNewTargetExpression(CHECK_OK);
- return ParseMemberExpressionContinuation(result, is_async, ok);
+ result = ParseNewTargetExpression();
+ return ParseMemberExpressionContinuation(result);
} else {
- result = ParseMemberWithNewPrefixesExpression(is_async, CHECK_OK);
+ result = ParseMemberWithNewPrefixesExpression();
}
- ValidateExpression(CHECK_OK);
if (peek() == Token::LPAREN) {
// NewExpression with arguments.
- Scanner::Location spread_pos;
- ExpressionListT args = ParseArguments(&spread_pos, CHECK_OK);
+ {
+ ExpressionListT args(pointer_buffer());
+ bool has_spread;
+ ParseArguments(&args, &has_spread);
- if (spread_pos.IsValid()) {
- result = impl()->SpreadCallNew(result, args, new_pos);
- } else {
- result = factory()->NewCallNew(result, args, new_pos);
+ if (has_spread) {
+ 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.
- return ParseMemberExpressionContinuation(result, is_async, ok);
+ return ParseMemberExpressionContinuation(result);
}
// NewExpression without arguments.
- return factory()->NewCallNew(result, impl()->NewExpressionList(0), new_pos);
+ ExpressionListT args(pointer_buffer());
+ return factory()->NewCallNew(result, args, new_pos);
+}
+
+template <typename Impl>
+typename ParserBase<Impl>::ExpressionT
+ParserBase<Impl>::ParseMemberWithNewPrefixesExpression() {
+ return peek() == Token::NEW ? ParseMemberWithPresentNewPrefixesExpression()
+ : ParseMemberExpression();
}
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);
+ParserBase<Impl>::ParseFunctionExpression() {
+ Consume(Token::FUNCTION);
+ int function_token_position = position();
+
+ FunctionKind function_kind = Check(Token::MUL)
+ ? FunctionKind::kGeneratorFunction
+ : FunctionKind::kNormalFunction;
+ IdentifierT name = impl()->NullIdentifier();
+ bool is_strict_reserved_name = Token::IsStrictReservedWord(peek());
+ Scanner::Location function_name_location = Scanner::Location::invalid();
+ FunctionLiteral::FunctionType function_type =
+ FunctionLiteral::kAnonymousExpression;
+ if (impl()->ParsingDynamicFunctionDeclaration()) {
+ // We don't want dynamic functions to actually declare their name
+ // "anonymous". We just want that name in the toString().
+ Consume(Token::IDENTIFIER);
+ DCHECK_IMPLIES(!has_error(),
+ scanner()->CurrentSymbol(ast_value_factory()) ==
+ ast_value_factory()->anonymous_string());
+ } else if (peek_any_identifier()) {
+ name = ParseIdentifier(function_kind);
+ function_name_location = scanner()->location();
+ function_type = FunctionLiteral::kNamedExpression;
+ }
+ FunctionLiteralT result = impl()->ParseFunctionLiteral(
+ name, function_name_location,
+ is_strict_reserved_name ? kFunctionNameIsStrictReserved
+ : kFunctionNameValidityUnknown,
+ function_kind, function_token_position, function_type, language_mode(),
+ nullptr);
+ // TODO(verwaest): FailureFunctionLiteral?
+ if (impl()->IsNull(result)) return impl()->FailureExpression();
+ return result;
}
template <typename Impl>
-typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseMemberExpression(
- bool* is_async, bool* ok) {
+typename ParserBase<Impl>::ExpressionT
+ParserBase<Impl>::ParseMemberExpression() {
// MemberExpression ::
// (PrimaryExpression | FunctionLiteral | ClassLiteral)
// ('[' Expression ']' | '.' Identifier | Arguments | TemplateLiteral)*
@@ -3558,99 +3213,60 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseMemberExpression(
// Parse the initial primary or function expression.
ExpressionT result;
if (peek() == Token::FUNCTION) {
- BindingPatternUnexpectedToken();
- ArrowFormalParametersUnexpectedToken();
-
- Consume(Token::FUNCTION);
- int function_token_position = position();
-
- FunctionKind function_kind = Check(Token::MUL)
- ? FunctionKind::kGeneratorFunction
- : FunctionKind::kNormalFunction;
- IdentifierT name = impl()->NullIdentifier();
- bool is_strict_reserved_name = false;
- Scanner::Location function_name_location = Scanner::Location::invalid();
- FunctionLiteral::FunctionType function_type =
- FunctionLiteral::kAnonymousExpression;
- if (impl()->ParsingDynamicFunctionDeclaration()) {
- // We don't want dynamic functions to actually declare their name
- // "anonymous". We just want that name in the toString().
- if (stack_overflow()) {
- *ok = false;
- return impl()->NullExpression();
- }
- Consume(Token::IDENTIFIER);
- DCHECK(scanner()->CurrentMatchesContextual(Token::ANONYMOUS));
- } else if (peek_any_identifier()) {
- bool is_await = false;
- name = ParseIdentifierOrStrictReservedWord(
- function_kind, &is_strict_reserved_name, &is_await, CHECK_OK);
- function_name_location = scanner()->location();
- function_type = FunctionLiteral::kNamedExpression;
- }
- result = impl()->ParseFunctionLiteral(
- name, function_name_location,
- is_strict_reserved_name ? kFunctionNameIsStrictReserved
- : kFunctionNameValidityUnknown,
- function_kind, function_token_position, function_type, language_mode(),
- nullptr, CHECK_OK);
+ result = ParseFunctionExpression();
} else if (peek() == Token::SUPER) {
const bool is_new = false;
- result = ParseSuperExpression(is_new, CHECK_OK);
+ result = ParseSuperExpression(is_new);
} else if (allow_harmony_dynamic_import() && peek() == Token::IMPORT) {
- result = ParseImportExpressions(CHECK_OK);
+ result = ParseImportExpressions();
} else {
- result = ParsePrimaryExpression(is_async, CHECK_OK);
+ result = ParsePrimaryExpression();
}
- return ParseMemberExpressionContinuation(result, is_async, ok);
+ return ParseMemberExpressionContinuation(result);
}
template <typename Impl>
-typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseImportExpressions(
- bool* ok) {
+typename ParserBase<Impl>::ExpressionT
+ParserBase<Impl>::ParseImportExpressions() {
DCHECK(allow_harmony_dynamic_import());
- classifier()->RecordPatternError(scanner()->peek_location(),
- MessageTemplate::kUnexpectedToken,
- Token::String(Token::IMPORT));
-
Consume(Token::IMPORT);
int pos = position();
if (allow_harmony_import_meta() && peek() == Token::PERIOD) {
- ExpectMetaProperty(Token::META, "import.meta", pos, CHECK_OK);
+ ExpectMetaProperty(ast_value_factory()->meta_string(), "import.meta", pos);
if (!parsing_module_) {
impl()->ReportMessageAt(scanner()->location(),
MessageTemplate::kImportMetaOutsideModule);
- *ok = false;
- return impl()->NullExpression();
+ return impl()->FailureExpression();
}
return impl()->ImportMetaExpression(pos);
}
- Expect(Token::LPAREN, CHECK_OK);
+ Expect(Token::LPAREN);
if (peek() == Token::RPAREN) {
impl()->ReportMessageAt(scanner()->location(),
MessageTemplate::kImportMissingSpecifier);
- *ok = false;
- return impl()->NullExpression();
+ return impl()->FailureExpression();
}
- ExpressionT arg = ParseAssignmentExpression(true, CHECK_OK);
- Expect(Token::RPAREN, CHECK_OK);
+ AcceptINScope scope(this, true);
+ ExpressionT arg = ParseAssignmentExpressionCoverGrammar();
+ Expect(Token::RPAREN);
+
return factory()->NewImportCallExpression(arg, pos);
}
template <typename Impl>
typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseSuperExpression(
- bool is_new, bool* ok) {
- Expect(Token::SUPER, CHECK_OK);
+ bool is_new) {
+ Consume(Token::SUPER);
int pos = position();
DeclarationScope* scope = GetReceiverScope();
FunctionKind kind = scope->function_kind();
if (IsConciseMethod(kind) || IsAccessorFunction(kind) ||
IsClassConstructor(kind)) {
- if (peek() == Token::PERIOD || peek() == Token::LBRACK) {
+ if (Token::IsProperty(peek())) {
scope->RecordSuperPropertyUsage();
return impl()->NewSuperPropertyReference(pos);
}
@@ -3665,39 +3281,31 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseSuperExpression(
impl()->ReportMessageAt(scanner()->location(),
MessageTemplate::kUnexpectedSuper);
- *ok = false;
- return impl()->NullExpression();
+ return impl()->FailureExpression();
}
template <typename Impl>
-void ParserBase<Impl>::ExpectMetaProperty(Token::Value property_name,
- const char* full_name, int pos,
- bool* ok) {
+void ParserBase<Impl>::ExpectMetaProperty(const AstRawString* property_name,
+ const char* full_name, int pos) {
Consume(Token::PERIOD);
- ExpectContextualKeyword(property_name, CHECK_OK_CUSTOM(Void));
- if (scanner()->literal_contains_escapes()) {
+ ExpectContextualKeyword(property_name);
+ if (V8_UNLIKELY(scanner()->literal_contains_escapes())) {
impl()->ReportMessageAt(Scanner::Location(pos, end_position()),
MessageTemplate::kInvalidEscapedMetaProperty,
full_name);
- *ok = false;
}
}
template <typename Impl>
typename ParserBase<Impl>::ExpressionT
-ParserBase<Impl>::ParseNewTargetExpression(bool* ok) {
+ParserBase<Impl>::ParseNewTargetExpression() {
int pos = position();
- ExpectMetaProperty(Token::TARGET, "new.target", pos, CHECK_OK);
-
- classifier()->RecordAssignmentPatternError(
- Scanner::Location(pos, end_position()),
- MessageTemplate::kInvalidDestructuringTarget);
+ ExpectMetaProperty(ast_value_factory()->target_string(), "new.target", pos);
if (!GetReceiverScope()->is_function_scope()) {
impl()->ReportMessageAt(scanner()->location(),
MessageTemplate::kUnexpectedNewTarget);
- *ok = false;
- return impl()->NullExpression();
+ return impl()->FailureExpression();
}
return impl()->NewTargetExpression(pos);
@@ -3705,45 +3313,31 @@ ParserBase<Impl>::ParseNewTargetExpression(bool* ok) {
template <typename Impl>
typename ParserBase<Impl>::ExpressionT
-ParserBase<Impl>::ParseMemberExpressionContinuation(ExpressionT expression,
- bool* is_async, bool* ok) {
+ParserBase<Impl>::DoParseMemberExpressionContinuation(ExpressionT expression) {
+ DCHECK(Token::IsMember(peek()));
// Parses this part of MemberExpression:
// ('[' Expression ']' | '.' Identifier | TemplateLiteral)*
- while (true) {
+ do {
switch (peek()) {
case Token::LBRACK: {
- *is_async = false;
- ValidateExpression(CHECK_OK);
- BindingPatternUnexpectedToken();
- ArrowFormalParametersUnexpectedToken();
-
Consume(Token::LBRACK);
int pos = position();
- ExpressionT index = ParseExpressionCoverGrammar(true, CHECK_OK);
- ValidateExpression(CHECK_OK);
+ AcceptINScope scope(this, true);
+ ExpressionT index = ParseExpressionCoverGrammar();
expression = factory()->NewProperty(expression, index, pos);
impl()->PushPropertyName(index);
- Expect(Token::RBRACK, CHECK_OK);
+ Expect(Token::RBRACK);
break;
}
case Token::PERIOD: {
- *is_async = false;
- ValidateExpression(CHECK_OK);
- BindingPatternUnexpectedToken();
- ArrowFormalParametersUnexpectedToken();
-
Consume(Token::PERIOD);
int pos = peek_position();
- ExpressionT key = ParseIdentifierNameOrPrivateName(CHECK_OK);
+ ExpressionT key = ParsePropertyOrPrivatePropertyName();
expression = factory()->NewProperty(expression, key, pos);
break;
}
- case Token::TEMPLATE_SPAN:
- case Token::TEMPLATE_TAIL: {
- *is_async = false;
- ValidateExpression(CHECK_OK);
- BindingPatternUnexpectedToken();
- ArrowFormalParametersUnexpectedToken();
+ default: {
+ DCHECK(Token::IsTemplate(peek()));
int pos;
if (scanner()->current_token() == Token::IDENTIFIER) {
pos = position();
@@ -3755,61 +3349,47 @@ ParserBase<Impl>::ParseMemberExpressionContinuation(ExpressionT expression,
expression->AsFunctionLiteral()->SetShouldEagerCompile();
}
}
- expression = ParseTemplateLiteral(expression, pos, true, CHECK_OK);
+ expression = ParseTemplateLiteral(expression, pos, true);
break;
}
- case Token::ILLEGAL: {
- ReportUnexpectedTokenAt(scanner()->peek_location(), Token::ILLEGAL);
- *ok = false;
- return impl()->NullExpression();
- }
- default:
- return expression;
}
- }
- DCHECK(false);
- return impl()->NullExpression();
+ } while (Token::IsMember(peek()));
+ return expression;
}
template <typename Impl>
-void ParserBase<Impl>::ParseFormalParameter(FormalParametersT* parameters,
- bool* ok) {
+void ParserBase<Impl>::ParseFormalParameter(FormalParametersT* parameters) {
// FormalParameter[Yield,GeneratorParameter] :
// BindingElement[?Yield, ?GeneratorParameter]
- bool is_rest = parameters->has_rest;
-
FuncNameInferrerState fni_state(&fni_);
- ExpressionT pattern = ParseBindingPattern(CHECK_OK_CUSTOM(Void));
- if (!impl()->IsIdentifier(pattern)) {
+ int pos = peek_position();
+ ExpressionT pattern = ParseBindingPattern();
+ if (impl()->IsIdentifier(pattern)) {
+ ClassifyParameter(impl()->AsIdentifier(pattern), pos, end_position());
+ } else {
parameters->is_simple = false;
- ValidateFormalParameterInitializer(CHECK_OK_CUSTOM(Void));
}
ExpressionT initializer = impl()->NullExpression();
if (Check(Token::ASSIGN)) {
- if (is_rest) {
+ parameters->is_simple = false;
+
+ if (parameters->has_rest) {
ReportMessage(MessageTemplate::kRestDefaultInitializer);
- *ok = false;
return;
}
- ExpressionClassifier init_classifier(this);
- initializer = ParseAssignmentExpression(true, CHECK_OK_CUSTOM(Void));
- ValidateExpression(CHECK_OK_CUSTOM(Void));
- ValidateFormalParameterInitializer(CHECK_OK_CUSTOM(Void));
- parameters->is_simple = false;
- DiscardExpressionClassifier();
- classifier()->RecordNonSimpleParameter();
+ AcceptINScope scope(this, true);
+ initializer = ParseAssignmentExpression();
impl()->SetFunctionNameFromIdentifierRef(initializer, pattern);
}
impl()->AddFormalParameter(parameters, pattern, initializer, end_position(),
- is_rest);
+ parameters->has_rest);
}
template <typename Impl>
-void ParserBase<Impl>::ParseFormalParameterList(FormalParametersT* parameters,
- bool* ok) {
+void ParserBase<Impl>::ParseFormalParameterList(FormalParametersT* parameters) {
// FormalParameters[Yield] :
// [empty]
// FunctionRestParameter[?Yield]
@@ -3820,26 +3400,25 @@ void ParserBase<Impl>::ParseFormalParameterList(FormalParametersT* parameters,
// FormalParameterList[Yield] :
// FormalParameter[?Yield]
// FormalParameterList[?Yield] , FormalParameter[?Yield]
+ ParameterParsingScope scope(impl(), parameters);
DCHECK_EQ(0, parameters->arity);
if (peek() != Token::RPAREN) {
while (true) {
- if (parameters->arity > Code::kMaxArguments) {
+ // Add one since we're going to be adding a parameter.
+ if (parameters->arity + 1 > Code::kMaxArguments) {
ReportMessage(MessageTemplate::kTooManyParameters);
- *ok = false;
return;
}
parameters->has_rest = Check(Token::ELLIPSIS);
- ParseFormalParameter(parameters, CHECK_OK_CUSTOM(Void));
+ ParseFormalParameter(parameters);
if (parameters->has_rest) {
parameters->is_simple = false;
- classifier()->RecordNonSimpleParameter();
if (peek() == Token::COMMA) {
impl()->ReportMessageAt(scanner()->peek_location(),
MessageTemplate::kParamAfterRest);
- *ok = false;
return;
}
break;
@@ -3852,15 +3431,14 @@ void ParserBase<Impl>::ParseFormalParameterList(FormalParametersT* parameters,
}
}
- impl()->DeclareFormalParameters(parameters->scope, parameters->params,
- parameters->is_simple);
+ impl()->DeclareFormalParameters(parameters);
}
template <typename Impl>
-typename ParserBase<Impl>::BlockT ParserBase<Impl>::ParseVariableDeclarations(
+void ParserBase<Impl>::ParseVariableDeclarations(
VariableDeclarationContext var_context,
DeclarationParsingResult* parsing_result,
- ZonePtrList<const AstRawString>* names, bool* ok) {
+ ZonePtrList<const AstRawString>* names) {
// VariableDeclarations ::
// ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[',']
//
@@ -3869,15 +3447,10 @@ typename ParserBase<Impl>::BlockT ParserBase<Impl>::ParseVariableDeclarations(
// declaration syntax.
DCHECK_NOT_NULL(parsing_result);
- parsing_result->descriptor.declaration_kind = DeclarationDescriptor::NORMAL;
+ parsing_result->descriptor.kind = NORMAL_VARIABLE;
parsing_result->descriptor.declaration_pos = peek_position();
parsing_result->descriptor.initialization_pos = peek_position();
- BlockT init_block = impl()->NullStatement();
- if (var_context != kForStatement) {
- init_block = factory()->NewBlock(1, true);
- }
-
switch (peek()) {
case Token::VAR:
parsing_result->descriptor.mode = VariableMode::kVar;
@@ -3898,40 +3471,29 @@ typename ParserBase<Impl>::BlockT ParserBase<Impl>::ParseVariableDeclarations(
break;
}
- parsing_result->descriptor.scope = scope();
+ VariableDeclarationParsingScope declaration(
+ impl(), parsing_result->descriptor.mode, names);
int bindings_start = peek_position();
do {
// Parse binding pattern.
FuncNameInferrerState fni_state(&fni_);
- ExpressionT pattern = impl()->NullExpression();
int decl_pos = peek_position();
- {
- ExpressionClassifier pattern_classifier(this);
- pattern = ParseBindingPattern(CHECK_OK_CUSTOM(NullStatement));
+ ExpressionT pattern = ParseBindingPattern();
- if (IsLexicalVariableMode(parsing_result->descriptor.mode)) {
- ValidateLetPattern(CHECK_OK_CUSTOM(NullStatement));
- }
- }
Scanner::Location variable_loc = scanner()->location();
- bool single_name = impl()->IsIdentifier(pattern);
- if (single_name) {
- impl()->PushVariableName(impl()->AsIdentifier(pattern));
- }
-
ExpressionT value = impl()->NullExpression();
int initializer_position = kNoSourcePosition;
int value_beg_position = kNoSourcePosition;
if (Check(Token::ASSIGN)) {
value_beg_position = peek_position();
- ExpressionClassifier classifier(this);
- value = ParseAssignmentExpression(var_context != kForStatement,
- CHECK_OK_CUSTOM(NullStatement));
- ValidateExpression(CHECK_OK_CUSTOM(NullStatement));
+ {
+ AcceptINScope scope(this, var_context != kForStatement);
+ value = ParseAssignmentExpression();
+ }
variable_loc.end_pos = end_position();
if (!parsing_result->first_initializer_loc.IsValid()) {
@@ -3939,7 +3501,7 @@ typename ParserBase<Impl>::BlockT ParserBase<Impl>::ParseVariableDeclarations(
}
// Don't infer if it is "a = function(){...}();"-like expression.
- if (single_name) {
+ if (impl()->IsIdentifier(pattern)) {
if (!value->IsCall() && !value->IsCallNew()) {
fni_.Infer();
} else {
@@ -3960,8 +3522,7 @@ typename ParserBase<Impl>::BlockT ParserBase<Impl>::ParseVariableDeclarations(
Scanner::Location(decl_pos, end_position()),
MessageTemplate::kDeclarationMissingInitializer,
!impl()->IsIdentifier(pattern) ? "destructuring" : "const");
- *ok = false;
- return impl()->NullStatement();
+ return;
}
// 'let x' initializes 'x' to undefined.
if (parsing_result->descriptor.mode == VariableMode::kLet) {
@@ -3976,61 +3537,50 @@ typename ParserBase<Impl>::BlockT ParserBase<Impl>::ParseVariableDeclarations(
typename DeclarationParsingResult::Declaration decl(
pattern, initializer_position, value);
decl.value_beg_position = value_beg_position;
- if (var_context == kForStatement) {
- // Save the declaration for further handling in ParseForStatement.
- parsing_result->declarations.push_back(decl);
- } else {
- // Immediately declare the variable otherwise. This avoids O(N^2)
- // behavior (where N is the number of variables in a single
- // declaration) in the PatternRewriter having to do with removing
- // and adding VariableProxies to the Scope (see bug 4699).
- impl()->DeclareAndInitializeVariables(
- init_block, &parsing_result->descriptor, &decl, names,
- CHECK_OK_CUSTOM(NullStatement));
- }
+ parsing_result->declarations.push_back(decl);
} while (Check(Token::COMMA));
parsing_result->bindings_loc =
Scanner::Location(bindings_start, end_position());
-
- DCHECK(*ok);
- return init_block;
}
template <typename Impl>
typename ParserBase<Impl>::StatementT
-ParserBase<Impl>::ParseFunctionDeclaration(bool* ok) {
+ParserBase<Impl>::ParseFunctionDeclaration() {
Consume(Token::FUNCTION);
+
int pos = position();
ParseFunctionFlags flags = ParseFunctionFlag::kIsNormal;
if (Check(Token::MUL)) {
impl()->ReportMessageAt(
scanner()->location(),
MessageTemplate::kGeneratorInSingleStatementContext);
- *ok = false;
return impl()->NullStatement();
}
- return ParseHoistableDeclaration(pos, flags, nullptr, false, ok);
+ return ParseHoistableDeclaration(pos, flags, nullptr, false);
}
template <typename Impl>
typename ParserBase<Impl>::StatementT
ParserBase<Impl>::ParseHoistableDeclaration(
- ZonePtrList<const AstRawString>* names, bool default_export, bool* ok) {
- Expect(Token::FUNCTION, CHECK_OK_CUSTOM(NullStatement));
+ ZonePtrList<const AstRawString>* names, bool default_export) {
+ Consume(Token::FUNCTION);
+
int pos = position();
ParseFunctionFlags flags = ParseFunctionFlag::kIsNormal;
if (Check(Token::MUL)) {
flags |= ParseFunctionFlag::kIsGenerator;
}
- return ParseHoistableDeclaration(pos, flags, names, default_export, ok);
+ return ParseHoistableDeclaration(pos, flags, names, default_export);
}
template <typename Impl>
typename ParserBase<Impl>::StatementT
ParserBase<Impl>::ParseHoistableDeclaration(
int pos, ParseFunctionFlags flags, ZonePtrList<const AstRawString>* names,
- bool default_export, bool* ok) {
+ bool default_export) {
+ CheckStackOverflow();
+
// FunctionDeclaration ::
// 'function' Identifier '(' FormalParameters ')' '{' FunctionBody '}'
// 'function' '(' FormalParameters ')' '{' FunctionBody '}'
@@ -4057,10 +3607,8 @@ ParserBase<Impl>::ParseHoistableDeclaration(
impl()->GetDefaultStrings(&name, &variable_name);
name_validity = kSkipFunctionNameCheck;
} else {
- bool is_strict_reserved;
- bool is_await = false;
- name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved, &is_await,
- CHECK_OK_CUSTOM(NullStatement));
+ bool is_strict_reserved = Token::IsStrictReservedWord(peek());
+ name = ParseIdentifier();
name_validity = is_strict_reserved ? kFunctionNameIsStrictReserved
: kFunctionNameValidityUnknown;
variable_name = name;
@@ -4073,8 +3621,7 @@ ParserBase<Impl>::ParseHoistableDeclaration(
FunctionLiteralT function = impl()->ParseFunctionLiteral(
name, scanner()->location(), name_validity, kind, pos,
- FunctionLiteral::kDeclaration, language_mode(), nullptr,
- CHECK_OK_CUSTOM(NullStatement));
+ FunctionLiteral::kDeclaration, language_mode(), nullptr);
// In ES6, a function behaves as a lexical binding, except in
// a script scope, or the initial scope of eval or another function.
@@ -4092,12 +3639,13 @@ ParserBase<Impl>::ParseHoistableDeclaration(
flags == ParseFunctionFlag::kIsNormal;
return impl()->DeclareFunction(variable_name, function, mode, pos,
- is_sloppy_block_function, names, ok);
+ end_position(), is_sloppy_block_function,
+ names);
}
template <typename Impl>
typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseClassDeclaration(
- ZonePtrList<const AstRawString>* names, bool default_export, bool* ok) {
+ ZonePtrList<const AstRawString>* names, bool default_export) {
// ClassDeclaration ::
// 'class' Identifier ('extends' LeftHandExpression)? '{' ClassBody '}'
// 'class' ('extends' LeftHandExpression)? '{' ClassBody '}'
@@ -4118,24 +3666,22 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseClassDeclaration(
int class_token_pos = position();
IdentifierT name = impl()->NullIdentifier();
- bool is_strict_reserved = false;
+ bool is_strict_reserved = Token::IsStrictReservedWord(peek());
IdentifierT variable_name = impl()->NullIdentifier();
if (default_export && (peek() == Token::EXTENDS || peek() == Token::LBRACE)) {
impl()->GetDefaultStrings(&name, &variable_name);
} else {
- bool is_await = false;
- name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved, &is_await,
- CHECK_OK_CUSTOM(NullStatement));
+ name = ParseIdentifier();
variable_name = name;
}
- ExpressionClassifier no_classifier(this);
- ExpressionT value =
- ParseClassLiteral(name, scanner()->location(), is_strict_reserved,
- class_token_pos, CHECK_OK_CUSTOM(NullStatement));
+ ExpressionParsingScope no_expression_scope(impl());
+ ExpressionT value = ParseClassLiteral(name, scanner()->location(),
+ is_strict_reserved, class_token_pos);
+ no_expression_scope.ValidateExpression();
int end_pos = position();
return impl()->DeclareClass(variable_name, value, names, class_token_pos,
- end_pos, ok);
+ end_pos);
}
// Language extension which is only enabled for source files loaded
@@ -4143,86 +3689,84 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseClassDeclaration(
// declaration is resolved by looking up the function through a
// callback provided by the extension.
template <typename Impl>
-typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseNativeDeclaration(
- bool* ok) {
+typename ParserBase<Impl>::StatementT
+ParserBase<Impl>::ParseNativeDeclaration() {
function_state_->DisableOptimization(BailoutReason::kNativeFunctionLiteral);
int pos = peek_position();
- Expect(Token::FUNCTION, CHECK_OK_CUSTOM(NullStatement));
+ Consume(Token::FUNCTION);
// Allow "eval" or "arguments" for backward compatibility.
- IdentifierT name = ParseIdentifier(kAllowRestrictedIdentifiers,
- CHECK_OK_CUSTOM(NullStatement));
- Expect(Token::LPAREN, CHECK_OK_CUSTOM(NullStatement));
+ IdentifierT name = ParseIdentifier();
+ Expect(Token::LPAREN);
if (peek() != Token::RPAREN) {
do {
- ParseIdentifier(kAllowRestrictedIdentifiers,
- CHECK_OK_CUSTOM(NullStatement));
+ ParseIdentifier();
} while (Check(Token::COMMA));
}
- Expect(Token::RPAREN, CHECK_OK_CUSTOM(NullStatement));
- Expect(Token::SEMICOLON, CHECK_OK_CUSTOM(NullStatement));
- return impl()->DeclareNative(name, pos, ok);
+ Expect(Token::RPAREN);
+ Expect(Token::SEMICOLON);
+ return impl()->DeclareNative(name, pos);
}
template <typename Impl>
typename ParserBase<Impl>::StatementT
ParserBase<Impl>::ParseAsyncFunctionDeclaration(
- ZonePtrList<const AstRawString>* names, bool default_export, bool* ok) {
+ ZonePtrList<const AstRawString>* names, bool default_export) {
// AsyncFunctionDeclaration ::
// async [no LineTerminator here] function BindingIdentifier[Await]
// ( FormalParameters[Await] ) { AsyncFunctionBody }
DCHECK_EQ(scanner()->current_token(), Token::ASYNC);
int pos = position();
- if (scanner()->HasLineTerminatorBeforeNext()) {
- *ok = false;
- impl()->ReportUnexpectedToken(scanner()->current_token());
- return impl()->NullStatement();
- }
- Expect(Token::FUNCTION, CHECK_OK_CUSTOM(NullStatement));
+ DCHECK(!scanner()->HasLineTerminatorBeforeNext());
+ Consume(Token::FUNCTION);
ParseFunctionFlags flags = ParseFunctionFlag::kIsAsync;
- return ParseHoistableDeclaration(pos, flags, names, default_export, ok);
+ return ParseHoistableDeclaration(pos, flags, names, default_export);
}
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, FunctionBodyType body_type,
- bool accept_IN, bool* ok) {
- DeclarationScope* function_scope = scope()->AsDeclarationScope();
+ StatementListT* body, IdentifierT function_name, int pos,
+ const FormalParametersT& parameters, FunctionKind kind,
+ FunctionLiteral::FunctionType function_type, FunctionBodyType body_type) {
+ FunctionBodyParsingScope body_parsing_scope(impl());
+
+ if (IsResumableFunction(kind)) impl()->PrepareGeneratorVariables();
+
+ DeclarationScope* function_scope = parameters.scope;
DeclarationScope* inner_scope = function_scope;
- BlockT inner_block = impl()->NullStatement();
- StatementListT body = result;
- if (!parameters.is_simple) {
+ // Building the parameter initialization block declares the parameters.
+ // TODO(verwaest): Rely on ArrowHeadParsingScope instead.
+ if (V8_UNLIKELY(!parameters.is_simple)) {
+ if (has_error()) return;
+ BlockT init_block = impl()->BuildParameterInitializationBlock(parameters);
+ if (IsAsyncFunction(kind) && !IsAsyncGeneratorFunction(kind)) {
+ init_block = impl()->BuildRejectPromiseOnException(init_block);
+ }
+ body->Add(init_block);
+ if (has_error()) return;
+
inner_scope = NewVarblockScope();
inner_scope->set_start_position(scanner()->location().beg_pos);
- inner_block = factory()->NewBlock(8, true);
- inner_block->set_scope(inner_scope);
- body = inner_block->statements();
}
+ StatementListT inner_body(pointer_buffer());
+
{
BlockState block_state(&scope_, inner_scope);
- if (IsResumableFunction(kind)) impl()->PrepareGeneratorVariables();
-
if (body_type == FunctionBodyType::kExpression) {
- ExpressionClassifier classifier(this);
- ExpressionT expression =
- ParseAssignmentExpression(accept_IN, CHECK_OK_VOID);
- ValidateExpression(CHECK_OK_VOID);
+ ExpressionT expression = ParseAssignmentExpression();
if (IsAsyncFunction(kind)) {
BlockT block = factory()->NewBlock(1, true);
- impl()->RewriteAsyncFunctionBody(body, block, expression,
- CHECK_OK_VOID);
+ impl()->RewriteAsyncFunctionBody(&inner_body, block, expression);
} else {
- body->Add(BuildReturnStatement(expression, expression->position()),
- zone());
+ inner_body.Add(
+ BuildReturnStatement(expression, expression->position()));
}
} else {
- DCHECK(accept_IN);
+ 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.
@@ -4231,63 +3775,64 @@ void ParserBase<Impl>::ParseFunctionBody(
: Token::RBRACE;
if (IsAsyncGeneratorFunction(kind)) {
- impl()->ParseAndRewriteAsyncGeneratorFunctionBody(pos, kind, body,
- CHECK_OK_VOID);
+ impl()->ParseAndRewriteAsyncGeneratorFunctionBody(pos, kind,
+ &inner_body);
} else if (IsGeneratorFunction(kind)) {
- impl()->ParseAndRewriteGeneratorFunctionBody(pos, kind, body,
- CHECK_OK_VOID);
+ impl()->ParseAndRewriteGeneratorFunctionBody(pos, kind, &inner_body);
} else if (IsAsyncFunction(kind)) {
- ParseAsyncFunctionBody(inner_scope, body, CHECK_OK_VOID);
+ ParseAsyncFunctionBody(inner_scope, &inner_body);
} else {
- ParseStatementList(body, closing_token, CHECK_OK_VOID);
+ ParseStatementList(&inner_body, closing_token);
}
if (IsDerivedConstructor(kind)) {
- body->Add(factory()->NewReturnStatement(impl()->ThisExpression(),
- kNoSourcePosition),
- zone());
+ inner_body.Add(factory()->NewReturnStatement(impl()->ThisExpression(),
+ kNoSourcePosition));
}
- Expect(closing_token, CHECK_OK_VOID);
+ Expect(closing_token);
}
}
scope()->set_end_position(end_position());
- if (!parameters.is_simple) {
+ bool allow_duplicate_parameters = false;
+
+ if (V8_LIKELY(parameters.is_simple)) {
+ DCHECK_EQ(inner_scope, function_scope);
+ if (is_sloppy(function_scope->language_mode())) {
+ impl()->InsertSloppyBlockFunctionVarBindings(function_scope);
+ }
+ allow_duplicate_parameters =
+ is_sloppy(function_scope->language_mode()) && !IsConciseMethod(kind);
+ } else {
DCHECK_NOT_NULL(inner_scope);
DCHECK_EQ(function_scope, scope());
DCHECK_EQ(function_scope, inner_scope->outer_scope());
impl()->SetLanguageMode(function_scope, inner_scope->language_mode());
- BlockT init_block =
- impl()->BuildParameterInitializationBlock(parameters, CHECK_OK_VOID);
if (is_sloppy(inner_scope->language_mode())) {
impl()->InsertSloppyBlockFunctionVarBindings(inner_scope);
}
- // TODO(littledan): Merge the two rejection blocks into one
- if (IsAsyncFunction(kind) && !IsAsyncGeneratorFunction(kind)) {
- init_block = impl()->BuildRejectPromiseOnException(init_block);
- }
-
inner_scope->set_end_position(end_position());
if (inner_scope->FinalizeBlockScope() != nullptr) {
- impl()->CheckConflictingVarDeclarations(inner_scope, CHECK_OK_VOID);
+ BlockT inner_block = factory()->NewBlock(true, inner_body);
+ inner_body.Rewind();
+ inner_body.Add(inner_block);
+ inner_block->set_scope(inner_scope);
+ const AstRawString* conflict = inner_scope->FindVariableDeclaredIn(
+ function_scope, VariableMode::kLastLexicalVariableMode);
+ if (conflict != nullptr) {
+ impl()->ReportVarRedeclarationIn(conflict, inner_scope);
+ }
+ impl()->CheckConflictingVarDeclarations(inner_scope);
impl()->InsertShadowingVarBindingInitializers(inner_block);
- } else {
- inner_block->set_scope(nullptr);
- }
- inner_scope = nullptr;
-
- result->Add(init_block, zone());
- result->Add(inner_block, zone());
- } else {
- DCHECK_EQ(inner_scope, function_scope);
- if (is_sloppy(function_scope->language_mode())) {
- impl()->InsertSloppyBlockFunctionVarBindings(function_scope);
}
}
+ ValidateFormalParameters(language_mode(), parameters,
+ allow_duplicate_parameters);
+
if (!IsArrowFunction(kind)) {
// Declare arguments after parsing the function since lexical 'arguments'
// masks the arguments object. Declare arguments before declaring the
@@ -4296,6 +3841,8 @@ void ParserBase<Impl>::ParseFunctionBody(
}
impl()->DeclareFunctionNameVar(function_name, function_type, function_scope);
+
+ inner_body.MergeInto(body);
}
template <typename Impl>
@@ -4303,26 +3850,23 @@ void ParserBase<Impl>::CheckArityRestrictions(int param_count,
FunctionKind function_kind,
bool has_rest,
int formals_start_pos,
- int formals_end_pos, bool* ok) {
+ int formals_end_pos) {
if (IsGetterFunction(function_kind)) {
if (param_count != 0) {
impl()->ReportMessageAt(
Scanner::Location(formals_start_pos, formals_end_pos),
MessageTemplate::kBadGetterArity);
- *ok = false;
}
} else if (IsSetterFunction(function_kind)) {
if (param_count != 1) {
impl()->ReportMessageAt(
Scanner::Location(formals_start_pos, formals_end_pos),
MessageTemplate::kBadSetterArity);
- *ok = false;
}
if (has_rest) {
impl()->ReportMessageAt(
Scanner::Location(formals_start_pos, formals_end_pos),
MessageTemplate::kBadSetterRestParameter);
- *ok = false;
}
}
}
@@ -4353,25 +3897,9 @@ bool ParserBase<Impl>::IsNextLetKeyword() {
}
template <typename Impl>
-bool ParserBase<Impl>::IsTrivialExpression() {
- 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 ||
- Token::IsAssignmentOp(peek_ahead)) {
- return true;
- }
- }
- return false;
-}
-
-template <typename Impl>
typename ParserBase<Impl>::ExpressionT
ParserBase<Impl>::ParseArrowFunctionLiteral(
- bool accept_IN, const FormalParametersT& formal_parameters,
- int rewritable_length, bool* ok) {
+ const FormalParametersT& formal_parameters) {
const RuntimeCallCounterId counters[2][2] = {
{RuntimeCallCounterId::kParseBackgroundArrowFunctionLiteral,
RuntimeCallCounterId::kParseArrowFunctionLiteral},
@@ -4383,16 +3911,15 @@ ParserBase<Impl>::ParseArrowFunctionLiteral(
base::ElapsedTimer timer;
if (V8_UNLIKELY(FLAG_log_function_events)) timer.Start();
- if (peek() == Token::ARROW && scanner_->HasLineTerminatorBeforeNext()) {
+ DCHECK_IMPLIES(!has_error(), peek() == Token::ARROW);
+ if (scanner_->HasLineTerminatorBeforeNext()) {
// ASI inserts `;` after arrow parameters if a line terminator is found.
// `=> ...` is never a valid expression, so report as syntax error.
// If next token is not `=>`, it's a syntax error anyways.
- ReportUnexpectedTokenAt(scanner_->peek_location(), Token::ARROW);
- *ok = false;
- return impl()->NullExpression();
+ impl()->ReportUnexpectedTokenAt(scanner_->peek_location(), Token::ARROW);
+ return impl()->FailureExpression();
}
- StatementListT body = impl()->NullStatementList();
int expected_property_count = -1;
int suspend_count = 0;
int function_literal_id = GetNextFunctionLiteralId();
@@ -4407,93 +3934,102 @@ ParserBase<Impl>::ParseArrowFunctionLiteral(
bool is_lazy_top_level_function =
can_preparse && impl()->AllowsLazyParsingWithoutUnresolvedVariables();
bool has_braces = true;
- ProducedPreParsedScopeData* produced_preparsed_scope_data = nullptr;
+ ProducedPreparseData* produced_preparse_data = nullptr;
+ StatementListT body(pointer_buffer());
{
FunctionState function_state(&function_state_, &scope_,
formal_parameters.scope);
- // Move any queued destructuring assignments which appeared
- // in this function's parameter list into its own function_state.
- function_state.AdoptDestructuringAssignmentsFromParentState(
- rewritable_length);
-
- Expect(Token::ARROW, CHECK_OK);
+ Consume(Token::ARROW);
if (peek() == Token::LBRACE) {
// Multiple statement body
DCHECK_EQ(scope(), formal_parameters.scope);
+
if (is_lazy_top_level_function) {
// FIXME(marja): Arrow function parameters will be parsed even if the
// body is preparsed; move relevant parts of parameter handling to
// simulate consistent parameter handling.
+ // Building the parameter initialization block declares the parameters.
+ // TODO(verwaest): Rely on ArrowHeadParsingScope instead.
+ if (!formal_parameters.is_simple) {
+ impl()->BuildParameterInitializationBlock(formal_parameters);
+ if (has_error()) return impl()->FailureExpression();
+ }
+
// For arrow functions, we don't need to retrieve data about function
// parameters.
int dummy_num_parameters = -1;
DCHECK_NE(kind & FunctionKind::kArrowFunction, 0);
- 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, &hint, CHECK_OK);
+ &produced_preparse_data);
- DCHECK_NULL(produced_preparsed_scope_data);
+ DCHECK_NULL(produced_preparse_data);
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);
+ // Validate parameter names. We can do this only after preparsing the
+ // function, since the function can declare itself strict.
+ ValidateFormalParameters(language_mode(), formal_parameters, false);
} else {
// In case we did not sucessfully preparse the function because of an
// unidentified error we do a full reparse to return the error.
+ // Parse again in the outer scope, since the language mode may change.
+ BlockState block_state(&scope_, scope()->outer_scope());
+ ExpressionT expression = ParseConditionalExpression();
+ // Reparsing the head may have caused a stack overflow.
+ if (has_error()) return impl()->FailureExpression();
+
+ DeclarationScope* function_scope = next_arrow_function_info_.scope;
+ FunctionState function_state(&function_state_, &scope_,
+ function_scope);
+ Scanner::Location loc(function_scope->start_position(),
+ end_position());
+ FormalParametersT parameters(function_scope);
+ parameters.is_simple = function_scope->has_simple_parameters();
+ impl()->DeclareArrowFunctionFormalParameters(&parameters, expression,
+ loc);
+ next_arrow_function_info_.Reset();
+
+ Consume(Token::ARROW);
Consume(Token::LBRACE);
- body = impl()->NewStatementList(8);
- ParseFunctionBody(body, impl()->NullIdentifier(), kNoSourcePosition,
- formal_parameters, kind,
+
+ AcceptINScope scope(this, true);
+ ParseFunctionBody(&body, impl()->NullIdentifier(), kNoSourcePosition,
+ parameters, kind,
FunctionLiteral::kAnonymousExpression,
- FunctionBodyType::kBlock, true, ok);
- CHECK(!*ok);
- return impl()->NullExpression();
+ FunctionBodyType::kBlock);
+ CHECK(has_error());
+ return impl()->FailureExpression();
}
} else {
Consume(Token::LBRACE);
- body = impl()->NewStatementList(8);
- ParseFunctionBody(body, impl()->NullIdentifier(), kNoSourcePosition,
+ AcceptINScope scope(this, true);
+ ParseFunctionBody(&body, impl()->NullIdentifier(), kNoSourcePosition,
formal_parameters, kind,
FunctionLiteral::kAnonymousExpression,
- FunctionBodyType::kBlock, true, CHECK_OK);
+ FunctionBodyType::kBlock);
expected_property_count = function_state.expected_property_count();
}
} else {
// Single-expression body
has_braces = false;
- body = impl()->NewStatementList(1);
- ParseFunctionBody(body, impl()->NullIdentifier(), kNoSourcePosition,
+ ParseFunctionBody(&body, impl()->NullIdentifier(), kNoSourcePosition,
formal_parameters, kind,
FunctionLiteral::kAnonymousExpression,
- FunctionBodyType::kExpression, accept_IN, CHECK_OK);
+ FunctionBodyType::kExpression);
expected_property_count = function_state.expected_property_count();
}
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
- // that duplicates are not allowed. Of course, the arrow function may
- // itself be strict as well.
- const bool allow_duplicate_parameters = false;
- ValidateFormalParameters(language_mode(), allow_duplicate_parameters,
- CHECK_OK);
-
// Validate strict mode.
if (is_strict(language_mode())) {
CheckStrictOctalLiteral(formal_parameters.scope->start_position(),
- end_position(), CHECK_OK);
+ end_position());
}
- impl()->CheckConflictingVarDeclarations(formal_parameters.scope, CHECK_OK);
-
- impl()->RewriteDestructuringAssignments();
suspend_count = function_state.suspend_count();
}
@@ -4504,7 +4040,7 @@ ParserBase<Impl>::ParseArrowFunctionLiteral(
FunctionLiteral::kNoDuplicateParameters,
FunctionLiteral::kAnonymousExpression, eager_compile_hint,
formal_parameters.scope->start_position(), has_braces,
- function_literal_id, produced_preparsed_scope_data);
+ function_literal_id, produced_preparse_data);
function_literal->set_suspend_count(suspend_count);
function_literal->set_function_token_position(
@@ -4528,7 +4064,7 @@ ParserBase<Impl>::ParseArrowFunctionLiteral(
template <typename Impl>
typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseClassLiteral(
IdentifierT name, Scanner::Location class_name_location,
- bool name_is_strict_reserved, int class_token_pos, bool* ok) {
+ bool name_is_strict_reserved, int class_token_pos) {
bool is_anonymous = impl()->IsNull(name);
// All parts of a ClassDeclaration and ClassExpression are strict code.
@@ -4536,14 +4072,12 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseClassLiteral(
if (name_is_strict_reserved) {
impl()->ReportMessageAt(class_name_location,
MessageTemplate::kUnexpectedStrictReserved);
- *ok = false;
- return impl()->NullExpression();
+ return impl()->FailureExpression();
}
if (impl()->IsEvalOrArguments(name)) {
impl()->ReportMessageAt(class_name_location,
MessageTemplate::kStrictEvalArguments);
- *ok = false;
- return impl()->NullExpression();
+ return impl()->FailureExpression();
}
}
@@ -4553,77 +4087,79 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseClassLiteral(
ClassInfo class_info(this);
class_info.is_anonymous = is_anonymous;
- impl()->DeclareClassVariable(name, &class_info, class_token_pos, CHECK_OK);
+ impl()->DeclareClassVariable(name, &class_info, class_token_pos);
scope()->set_start_position(end_position());
if (Check(Token::EXTENDS)) {
FuncNameInferrerState fni_state(&fni_);
- ExpressionClassifier extends_classifier(this);
- class_info.extends = ParseLeftHandSideExpression(CHECK_OK);
- ValidateExpression(CHECK_OK);
- AccumulateFormalParameterContainmentErrors();
+ ExpressionParsingScope scope(impl());
+ class_info.extends = ParseLeftHandSideExpression();
+ scope.ValidateExpression();
}
- ClassLiteralChecker checker(this);
-
- Expect(Token::LBRACE, CHECK_OK);
+ Expect(Token::LBRACE);
const bool has_extends = !impl()->IsNull(class_info.extends);
while (peek() != Token::RBRACE) {
if (Check(Token::SEMICOLON)) continue;
FuncNameInferrerState fni_state(&fni_);
- bool is_computed_name = false; // Classes do not care about computed
- // property names here.
- bool is_static;
- ClassLiteralProperty::Kind property_kind;
- ExpressionClassifier property_classifier(this);
- IdentifierT property_name;
// If we haven't seen the constructor yet, it potentially is the next
// property.
bool is_constructor = !class_info.has_seen_constructor;
- ClassLiteralPropertyT property = ParseClassPropertyDefinition(
- &checker, &class_info, &property_name, has_extends, &is_computed_name,
- &property_kind, &is_static, CHECK_OK);
- if (!class_info.has_static_computed_names && is_static &&
- is_computed_name) {
+ ParsePropertyInfo prop_info(this);
+ prop_info.position = PropertyPosition::kClassLiteral;
+ ClassLiteralPropertyT property =
+ ParseClassPropertyDefinition(&class_info, &prop_info, has_extends);
+
+ if (has_error()) return impl()->FailureExpression();
+
+ ClassLiteralProperty::Kind property_kind =
+ ClassPropertyKindFor(prop_info.kind);
+ if (!class_info.has_static_computed_names && prop_info.is_static &&
+ prop_info.is_computed_name) {
class_info.has_static_computed_names = true;
}
- if (is_computed_name &&
- property_kind == ClassLiteralProperty::PUBLIC_FIELD) {
- class_info.computed_field_count++;
- }
is_constructor &= class_info.has_seen_constructor;
- ValidateExpression(CHECK_OK);
- AccumulateFormalParameterContainmentErrors();
- impl()->DeclareClassProperty(name, property, property_name, property_kind,
- is_static, is_constructor, is_computed_name,
- &class_info, CHECK_OK);
+ if (V8_UNLIKELY(property_kind == ClassLiteralProperty::FIELD)) {
+ if (prop_info.is_computed_name) {
+ DCHECK(!prop_info.is_private);
+ class_info.computed_field_count++;
+ }
+
+ impl()->DeclareClassField(property, prop_info.name, prop_info.is_static,
+ prop_info.is_computed_name,
+ prop_info.is_private, &class_info);
+ } else {
+ impl()->DeclareClassProperty(name, property, is_constructor, &class_info);
+ }
impl()->InferFunctionName();
}
- Expect(Token::RBRACE, CHECK_OK);
+ Expect(Token::RBRACE);
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);
+ class_token_pos, end_pos);
}
template <typename Impl>
-void ParserBase<Impl>::ParseAsyncFunctionBody(Scope* scope, StatementListT body,
- bool* ok) {
- BlockT block = factory()->NewBlock(8, true);
-
- ParseStatementList(block->statements(), Token::RBRACE, CHECK_OK_VOID);
+void ParserBase<Impl>::ParseAsyncFunctionBody(Scope* scope,
+ StatementListT* body) {
+ BlockT block = impl()->NullBlock();
+ {
+ StatementListT statements(pointer_buffer());
+ ParseStatementList(&statements, Token::RBRACE);
+ block = factory()->NewBlock(true, statements);
+ }
impl()->RewriteAsyncFunctionBody(
- body, block, factory()->NewUndefinedLiteral(kNoSourcePosition),
- CHECK_OK_VOID);
+ body, block, factory()->NewUndefinedLiteral(kNoSourcePosition));
scope->set_end_position(end_position());
}
template <typename Impl>
typename ParserBase<Impl>::ExpressionT
-ParserBase<Impl>::ParseAsyncFunctionLiteral(bool* ok) {
+ParserBase<Impl>::ParseAsyncFunctionLiteral() {
// AsyncFunctionLiteral ::
// async [no LineTerminator here] function ( FormalParameters[Await] )
// { AsyncFunctionBody }
@@ -4632,43 +4168,41 @@ ParserBase<Impl>::ParseAsyncFunctionLiteral(bool* ok) {
// ( FormalParameters[Await] ) { AsyncFunctionBody }
DCHECK_EQ(scanner()->current_token(), Token::ASYNC);
int pos = position();
- Expect(Token::FUNCTION, CHECK_OK);
- bool is_strict_reserved = false;
+ Consume(Token::FUNCTION);
IdentifierT name = impl()->NullIdentifier();
FunctionLiteral::FunctionType type = FunctionLiteral::kAnonymousExpression;
ParseFunctionFlags flags = ParseFunctionFlag::kIsAsync;
if (Check(Token::MUL)) flags |= ParseFunctionFlag::kIsGenerator;
const FunctionKind kind = FunctionKindFor(flags);
+ bool is_strict_reserved = Token::IsStrictReservedWord(peek());
if (impl()->ParsingDynamicFunctionDeclaration()) {
// We don't want dynamic functions to actually declare their name
// "anonymous". We just want that name in the toString().
- if (stack_overflow()) {
- *ok = false;
- return impl()->NullExpression();
- }
+
+ // Consuming token we did not peek yet, which could lead to a ILLEGAL token
+ // in the case of a stackoverflow.
Consume(Token::IDENTIFIER);
- DCHECK(scanner()->CurrentMatchesContextual(Token::ANONYMOUS));
+ DCHECK_IMPLIES(!has_error(),
+ scanner()->CurrentSymbol(ast_value_factory()) ==
+ ast_value_factory()->anonymous_string());
} else if (peek_any_identifier()) {
type = FunctionLiteral::kNamedExpression;
- bool is_await = false;
- name = ParseIdentifierOrStrictReservedWord(kind, &is_strict_reserved,
- &is_await, CHECK_OK);
- // If the function name is "await", ParseIdentifierOrStrictReservedWord
- // recognized the error.
- DCHECK(!is_await);
- }
- return impl()->ParseFunctionLiteral(
+ name = ParseIdentifier(kind);
+ }
+ FunctionLiteralT result = impl()->ParseFunctionLiteral(
name, scanner()->location(),
is_strict_reserved ? kFunctionNameIsStrictReserved
: kFunctionNameValidityUnknown,
- kind, pos, type, language_mode(), nullptr, ok);
+ kind, pos, type, language_mode(), nullptr);
+ if (impl()->IsNull(result)) return impl()->FailureExpression();
+ return result;
}
template <typename Impl>
typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseTemplateLiteral(
- ExpressionT tag, int start, bool tagged, bool* ok) {
+ ExpressionT tag, int start, bool tagged) {
// A TemplateLiteral is made up of 0 or more TEMPLATE_SPAN tokens (literal
// text followed by a substitution expression), finalized by a single
// TEMPLATE_TAIL.
@@ -4696,7 +4230,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseTemplateLiteral(
Consume(Token::TEMPLATE_TAIL);
int pos = position();
typename Impl::TemplateLiteralState ts = impl()->OpenTemplateLiteral(pos);
- bool is_valid = CheckTemplateEscapes(forbid_illegal_escapes, CHECK_OK);
+ bool is_valid = CheckTemplateEscapes(forbid_illegal_escapes);
impl()->AddTemplateSpan(&ts, is_valid, true);
return impl()->CloseTemplateLiteral(&ts, start, tag);
}
@@ -4704,7 +4238,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseTemplateLiteral(
Consume(Token::TEMPLATE_SPAN);
int pos = position();
typename Impl::TemplateLiteralState ts = impl()->OpenTemplateLiteral(pos);
- bool is_valid = CheckTemplateEscapes(forbid_illegal_escapes, CHECK_OK);
+ bool is_valid = CheckTemplateEscapes(forbid_illegal_escapes);
impl()->AddTemplateSpan(&ts, is_valid, false);
Token::Value next;
@@ -4714,29 +4248,16 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseTemplateLiteral(
do {
next = peek();
- if (next == Token::EOS) {
- impl()->ReportMessageAt(Scanner::Location(start, peek_position()),
- MessageTemplate::kUnterminatedTemplate);
- *ok = false;
- return impl()->NullExpression();
- } else if (next == Token::ILLEGAL) {
- impl()->ReportMessageAt(
- Scanner::Location(position() + 1, peek_position()),
- MessageTemplate::kUnexpectedToken, "ILLEGAL", kSyntaxError);
- *ok = false;
- return impl()->NullExpression();
- }
int expr_pos = peek_position();
- ExpressionT expression = ParseExpressionCoverGrammar(true, CHECK_OK);
- ValidateExpression(CHECK_OK);
+ AcceptINScope scope(this, true);
+ ExpressionT expression = ParseExpressionCoverGrammar();
impl()->AddTemplateExpression(&ts, expression);
if (peek() != Token::RBRACE) {
impl()->ReportMessageAt(Scanner::Location(expr_pos, peek_position()),
MessageTemplate::kUnterminatedTemplateExpr);
- *ok = false;
- return impl()->NullExpression();
+ return impl()->FailureExpression();
}
// If we didn't die parsing that expression, our next token should be a
@@ -4745,53 +4266,34 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseTemplateLiteral(
Next();
pos = position();
- if (next == Token::EOS) {
- impl()->ReportMessageAt(Scanner::Location(start, pos),
- MessageTemplate::kUnterminatedTemplate);
- *ok = false;
- return impl()->NullExpression();
- } else if (next == Token::ILLEGAL) {
- impl()->ReportMessageAt(
- Scanner::Location(position() + 1, peek_position()),
- MessageTemplate::kUnexpectedToken, "ILLEGAL", kSyntaxError);
- *ok = false;
- return impl()->NullExpression();
- }
-
- bool is_valid = CheckTemplateEscapes(forbid_illegal_escapes, CHECK_OK);
+ bool is_valid = CheckTemplateEscapes(forbid_illegal_escapes);
impl()->AddTemplateSpan(&ts, is_valid, next == Token::TEMPLATE_TAIL);
} while (next == Token::TEMPLATE_SPAN);
- DCHECK_EQ(next, Token::TEMPLATE_TAIL);
+ DCHECK_IMPLIES(!has_error(), next == Token::TEMPLATE_TAIL);
// Once we've reached a TEMPLATE_TAIL, we can close the TemplateLiteral.
return impl()->CloseTemplateLiteral(&ts, start, tag);
}
template <typename Impl>
typename ParserBase<Impl>::ExpressionT
-ParserBase<Impl>::CheckAndRewriteReferenceExpression(
- ExpressionT expression, int beg_pos, int end_pos,
- MessageTemplate::Template message, bool* ok) {
- return CheckAndRewriteReferenceExpression(expression, beg_pos, end_pos,
- message, kReferenceError, ok);
-}
+ParserBase<Impl>::RewriteInvalidReferenceExpression(ExpressionT expression,
+ int beg_pos, int end_pos,
+ MessageTemplate message,
+ ParseErrorType type) {
+ DCHECK(!IsValidReferenceExpression(expression));
+ if (impl()->IsIdentifier(expression)) {
+ DCHECK(is_strict(language_mode()));
+ DCHECK(impl()->IsEvalOrArguments(impl()->AsIdentifier(expression)));
-template <typename Impl>
-typename ParserBase<Impl>::ExpressionT
-ParserBase<Impl>::CheckAndRewriteReferenceExpression(
- ExpressionT expression, int beg_pos, int end_pos,
- MessageTemplate::Template message, ParseErrorType type, bool* ok) {
- if (impl()->IsIdentifier(expression) && is_strict(language_mode()) &&
- impl()->IsEvalOrArguments(impl()->AsIdentifier(expression))) {
ReportMessageAt(Scanner::Location(beg_pos, end_pos),
MessageTemplate::kStrictEvalArguments, kSyntaxError);
- *ok = false;
- return impl()->NullExpression();
- }
- if (expression->IsValidReferenceExpression()) {
- return expression;
+ return impl()->FailureExpression();
}
if (expression->IsCall() && !expression->AsCall()->is_tagged_template()) {
+ expression_scope()->RecordPatternError(
+ Scanner::Location(beg_pos, end_pos),
+ MessageTemplate::kInvalidDestructuringTarget);
// If it is a call, make it a runtime error for legacy web compatibility.
// Bug: https://bugs.chromium.org/p/v8/issues/detail?id=4480
// Rewrite `expr' to `expr[throw ReferenceError]'.
@@ -4803,8 +4305,35 @@ ParserBase<Impl>::CheckAndRewriteReferenceExpression(
return factory()->NewProperty(expression, error, beg_pos);
}
ReportMessageAt(Scanner::Location(beg_pos, end_pos), message, type);
- *ok = false;
- return impl()->NullExpression();
+ return impl()->FailureExpression();
+}
+
+template <typename Impl>
+void ParserBase<Impl>::ClassifyParameter(IdentifierT parameter, int begin,
+ int end) {
+ if (impl()->IsEvalOrArguments(parameter)) {
+ expression_scope()->RecordStrictModeParameterError(
+ Scanner::Location(begin, end), MessageTemplate::kStrictEvalArguments);
+ }
+}
+
+template <typename Impl>
+void ParserBase<Impl>::ClassifyArrowParameter(
+ AccumulationScope* accumulation_scope, int position,
+ ExpressionT parameter) {
+ accumulation_scope->Accumulate();
+ if (parameter->is_parenthesized() ||
+ !(impl()->IsIdentifier(parameter) || parameter->IsPattern() ||
+ parameter->IsAssignment())) {
+ expression_scope()->RecordDeclarationError(
+ Scanner::Location(position, end_position()),
+ MessageTemplate::kInvalidDestructuringTarget);
+ } else if (impl()->IsIdentifier(parameter)) {
+ ClassifyParameter(impl()->AsIdentifier(parameter), position,
+ end_position());
+ } else {
+ expression_scope()->RecordNonSimpleParameter();
+ }
}
template <typename Impl>
@@ -4813,147 +4342,133 @@ bool ParserBase<Impl>::IsValidReferenceExpression(ExpressionT expression) {
}
template <typename Impl>
-void ParserBase<Impl>::CheckDestructuringElement(ExpressionT expression,
- int begin, int end) {
- if (!IsValidPattern(expression) && !expression->IsAssignment() &&
- !IsValidReferenceExpression(expression)) {
- classifier()->RecordAssignmentPatternError(
- Scanner::Location(begin, end),
+typename ParserBase<Impl>::ExpressionT
+ParserBase<Impl>::ParsePossibleDestructuringSubPattern(
+ AccumulationScope* scope) {
+ if (scope) scope->Accumulate();
+ int begin = peek_position();
+ ExpressionT result = ParseAssignmentExpressionCoverGrammar();
+
+ if (IsValidReferenceExpression(result)) {
+ // Parenthesized identifiers and property references are allowed as part of
+ // a larger assignment pattern, even though parenthesized patterns
+ // themselves are not allowed, e.g., "[(x)] = []". Only accumulate
+ // assignment pattern errors if the parsed expression is more complex.
+ if (impl()->IsIdentifier(result)) {
+ if (result->is_parenthesized()) {
+ expression_scope()->RecordDeclarationError(
+ Scanner::Location(begin, end_position()),
+ MessageTemplate::kInvalidDestructuringTarget);
+ }
+ IdentifierT identifier = impl()->AsIdentifier(result);
+ ClassifyParameter(identifier, begin, end_position());
+ } else {
+ DCHECK(result->IsProperty());
+ expression_scope()->RecordDeclarationError(
+ Scanner::Location(begin, end_position()),
+ MessageTemplate::kInvalidPropertyBindingPattern);
+ if (scope != nullptr) scope->ValidateExpression();
+ }
+ } else if (result->is_parenthesized() ||
+ (!result->IsPattern() && !result->IsAssignment())) {
+ expression_scope()->RecordPatternError(
+ Scanner::Location(begin, end_position()),
MessageTemplate::kInvalidDestructuringTarget);
}
+
+ return result;
}
template <typename Impl>
-typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseV8Intrinsic(
- bool* ok) {
+typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseV8Intrinsic() {
// CallRuntime ::
// '%' Identifier Arguments
int pos = peek_position();
- Expect(Token::MOD, CHECK_OK);
+ Consume(Token::MOD);
// Allow "eval" or "arguments" for backward compatibility.
- IdentifierT name = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
- Scanner::Location spread_pos;
- ExpressionClassifier classifier(this);
- ExpressionListT args = ParseArguments(&spread_pos, CHECK_OK);
-
- if (spread_pos.IsValid()) {
- *ok = false;
- ReportMessageAt(spread_pos, MessageTemplate::kIntrinsicWithSpread,
- kSyntaxError);
- return impl()->NullExpression();
+ IdentifierT name = ParseIdentifier();
+ if (peek() != Token::LPAREN) {
+ impl()->ReportUnexpectedToken(peek());
+ return impl()->FailureExpression();
}
+ bool has_spread;
+ ExpressionListT args(pointer_buffer());
+ ParseArguments(&args, &has_spread);
- return impl()->NewV8Intrinsic(name, args, pos, ok);
-}
-
-template <typename Impl>
-typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseDoExpression(
- bool* ok) {
- // AssignmentExpression ::
- // do '{' StatementList '}'
+ if (has_spread) {
+ ReportMessageAt(Scanner::Location(pos, position()),
+ MessageTemplate::kIntrinsicWithSpread, kSyntaxError);
+ return impl()->FailureExpression();
+ }
- int pos = peek_position();
- Expect(Token::DO, CHECK_OK);
- BlockT block = ParseBlock(nullptr, CHECK_OK);
- return impl()->RewriteDoExpression(block, pos, ok);
+ return impl()->NewV8Intrinsic(name, args, pos);
}
-// Redefinition of CHECK_OK for parsing statements.
-#undef CHECK_OK
-#define CHECK_OK CHECK_OK_CUSTOM(NullStatement)
-
template <typename Impl>
-typename ParserBase<Impl>::LazyParsingResult
-ParserBase<Impl>::ParseStatementList(StatementListT body,
- Token::Value end_token, bool may_abort,
- bool* ok) {
+void ParserBase<Impl>::ParseStatementList(StatementListT* body,
+ Token::Value end_token) {
// StatementList ::
// (StatementListItem)* <end_token>
+ DCHECK_NOT_NULL(body);
- // Allocate a target stack to use for this set of source
- // elements. This way, all scripts and functions get their own
- // target stack thus avoiding illegal breaks and continues across
- // functions.
- typename Types::TargetScope target_scope(this);
- int count_statements = 0;
+ while (peek() == Token::STRING) {
+ bool use_strict = false;
+ bool use_asm = false;
- DCHECK(!impl()->IsNull(body));
- bool directive_prologue = true; // Parsing directive prologue.
+ Scanner::Location token_loc = scanner()->peek_location();
- while (peek() != end_token) {
- if (directive_prologue && peek() != Token::STRING) {
- directive_prologue = false;
+ if (scanner()->NextLiteralEquals("use strict")) {
+ use_strict = true;
+ } else if (scanner()->NextLiteralEquals("use asm")) {
+ use_asm = true;
}
- bool starts_with_identifier = peek() == Token::IDENTIFIER;
- Scanner::Location token_loc = scanner()->peek_location();
- StatementT stat =
- ParseStatementListItem(CHECK_OK_CUSTOM(Return, kLazyParsingComplete));
-
- if (impl()->IsNull(stat) || stat->IsEmptyStatement()) {
- directive_prologue = false; // End of directive prologue.
- continue;
- }
-
- if (directive_prologue) {
- // The length of the token is used to distinguish between strings literals
- // that evaluate equal to directives but contain either escape sequences
- // (e.g., "use \x73trict") or line continuations (e.g., "use \(newline)
- // strict").
- if (impl()->IsUseStrictDirective(stat) &&
- token_loc.end_pos - token_loc.beg_pos == sizeof("use strict") + 1) {
- // Directive "use strict" (ES5 14.1).
- RaiseLanguageMode(LanguageMode::kStrict);
- if (!scope()->HasSimpleParameters()) {
- // TC39 deemed "use strict" directives to be an error when occurring
- // in the body of a function with non-simple parameter list, on
- // 29/7/2015. https://goo.gl/ueA7Ln
- impl()->ReportMessageAt(
- token_loc, MessageTemplate::kIllegalLanguageModeDirective,
- "use strict");
- *ok = false;
- return kLazyParsingComplete;
- }
- } else if (impl()->IsUseAsmDirective(stat) &&
- token_loc.end_pos - token_loc.beg_pos ==
- sizeof("use asm") + 1) {
- // Directive "use asm".
- impl()->SetAsmModule();
- } else if (impl()->IsStringLiteral(stat)) {
- // Possibly an unknown directive.
- // Should not change mode, but will increment usage counters
- // as appropriate. Ditto usages below.
- RaiseLanguageMode(LanguageMode::kSloppy);
- } else {
- // End of the directive prologue.
- directive_prologue = false;
- RaiseLanguageMode(LanguageMode::kSloppy);
+ StatementT stat = ParseStatementListItem();
+ if (impl()->IsNull(stat)) return;
+
+ body->Add(stat);
+
+ if (!impl()->IsStringLiteral(stat)) break;
+
+ if (use_strict) {
+ // Directive "use strict" (ES5 14.1).
+ RaiseLanguageMode(LanguageMode::kStrict);
+ if (!scope()->HasSimpleParameters()) {
+ // TC39 deemed "use strict" directives to be an error when occurring
+ // in the body of a function with non-simple parameter list, on
+ // 29/7/2015. https://goo.gl/ueA7Ln
+ impl()->ReportMessageAt(token_loc,
+ MessageTemplate::kIllegalLanguageModeDirective,
+ "use strict");
+ return;
}
+ } else if (use_asm) {
+ // Directive "use asm".
+ impl()->SetAsmModule();
} else {
+ // Possibly an unknown directive.
+ // Should not change mode, but will increment usage counters
+ // as appropriate. Ditto usages below.
RaiseLanguageMode(LanguageMode::kSloppy);
}
+ }
- // If we're allowed to abort, we will do so when we see a "long and
- // trivial" function. Our current definition of "long and trivial" is:
- // - over kLazyParseTrialLimit statements
- // - all starting with an identifier (i.e., no if, for, while, etc.)
- if (may_abort) {
- if (!starts_with_identifier) {
- may_abort = false;
- } else if (++count_statements > kLazyParseTrialLimit) {
- return kLazyParsingAborted;
- }
- }
-
- body->Add(stat, zone());
+ // Allocate a target stack to use for this set of source elements. This way,
+ // all scripts and functions get their own target stack thus avoiding illegal
+ // breaks and continues across functions.
+ TargetScopeT target_scope(this);
+ while (peek() != end_token) {
+ StatementT stat = ParseStatementListItem();
+ if (impl()->IsNull(stat)) return;
+ if (stat->IsEmptyStatement()) continue;
+ body->Add(stat);
}
- return kLazyParsingComplete;
}
template <typename Impl>
-typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseStatementListItem(
- bool* ok) {
+typename ParserBase<Impl>::StatementT
+ParserBase<Impl>::ParseStatementListItem() {
// ECMA 262 6th Edition
// StatementListItem[Yield, Return] :
// Statement[?Yield, ?Return]
@@ -4973,36 +4488,36 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseStatementListItem(
switch (peek()) {
case Token::FUNCTION:
- return ParseHoistableDeclaration(nullptr, false, ok);
+ return ParseHoistableDeclaration(nullptr, false);
case Token::CLASS:
Consume(Token::CLASS);
- return ParseClassDeclaration(nullptr, false, ok);
+ return ParseClassDeclaration(nullptr, false);
case Token::VAR:
case Token::CONST:
- return ParseVariableStatement(kStatementListItem, nullptr, ok);
+ return ParseVariableStatement(kStatementListItem, nullptr);
case Token::LET:
if (IsNextLetKeyword()) {
- return ParseVariableStatement(kStatementListItem, nullptr, ok);
+ return ParseVariableStatement(kStatementListItem, nullptr);
}
break;
case Token::ASYNC:
if (PeekAhead() == Token::FUNCTION &&
!scanner()->HasLineTerminatorAfterNext()) {
Consume(Token::ASYNC);
- return ParseAsyncFunctionDeclaration(nullptr, false, ok);
+ return ParseAsyncFunctionDeclaration(nullptr, false);
}
break;
default:
break;
}
- return ParseStatement(nullptr, nullptr, kAllowLabelledFunctionStatement, ok);
+ return ParseStatement(nullptr, nullptr, kAllowLabelledFunctionStatement);
}
template <typename Impl>
typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseStatement(
ZonePtrList<const AstRawString>* labels,
ZonePtrList<const AstRawString>* own_labels,
- AllowLabelledFunctionStatement allow_function, bool* ok) {
+ AllowLabelledFunctionStatement allow_function) {
// Statement ::
// Block
// VariableStatement
@@ -5031,46 +4546,48 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseStatement(
// parsed into an empty statement.
switch (peek()) {
case Token::LBRACE:
- return ParseBlock(labels, ok);
+ return ParseBlock(labels);
case Token::SEMICOLON:
Next();
- return factory()->NewEmptyStatement(kNoSourcePosition);
+ return factory()->EmptyStatement();
case Token::IF:
- return ParseIfStatement(labels, ok);
+ return ParseIfStatement(labels);
case Token::DO:
- return ParseDoWhileStatement(labels, own_labels, ok);
+ return ParseDoWhileStatement(labels, own_labels);
case Token::WHILE:
- return ParseWhileStatement(labels, own_labels, ok);
+ return ParseWhileStatement(labels, own_labels);
case Token::FOR:
if (V8_UNLIKELY(is_async_function() && PeekAhead() == Token::AWAIT)) {
- return ParseForAwaitStatement(labels, own_labels, ok);
+ return ParseForAwaitStatement(labels, own_labels);
}
- return ParseForStatement(labels, own_labels, ok);
+ return ParseForStatement(labels, own_labels);
case Token::CONTINUE:
- return ParseContinueStatement(ok);
+ return ParseContinueStatement();
case Token::BREAK:
- return ParseBreakStatement(labels, ok);
+ return ParseBreakStatement(labels);
case Token::RETURN:
- return ParseReturnStatement(ok);
+ return ParseReturnStatement();
case Token::THROW:
- return ParseThrowStatement(ok);
+ return ParseThrowStatement();
case Token::TRY: {
// It is somewhat complicated to have labels on try-statements.
// When breaking out of a try-finally statement, one must take
// great care not to treat it as a fall-through. It is much easier
// just to wrap the entire try-statement in a statement block and
// put the labels there.
- if (labels == nullptr) return ParseTryStatement(ok);
- BlockT result = factory()->NewBlock(1, false, labels);
- typename Types::Target target(this, result);
- StatementT statement = ParseTryStatement(CHECK_OK);
- result->statements()->Add(statement, zone());
+ if (labels == nullptr) return ParseTryStatement();
+ StatementListT statements(pointer_buffer());
+ BlockT result = factory()->NewBlock(false, labels);
+ TargetT target(this, result);
+ StatementT statement = ParseTryStatement();
+ statements.Add(statement);
+ result->InitializeStatements(statements, zone());
return result;
}
case Token::WITH:
- return ParseWithStatement(labels, ok);
+ return ParseWithStatement(labels);
case Token::SWITCH:
- return ParseSwitchStatement(labels, ok);
+ return ParseSwitchStatement(labels);
case Token::FUNCTION:
// FunctionDeclaration only allowed as a StatementListItem, not in
// an arbitrary Statement position. Exceptions such as
@@ -5081,72 +4598,77 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseStatement(
is_strict(language_mode())
? MessageTemplate::kStrictFunction
: MessageTemplate::kSloppyFunction);
- *ok = false;
return impl()->NullStatement();
case Token::DEBUGGER:
- return ParseDebuggerStatement(ok);
+ return ParseDebuggerStatement();
case Token::VAR:
- return ParseVariableStatement(kStatement, nullptr, ok);
+ return ParseVariableStatement(kStatement, nullptr);
case Token::ASYNC:
if (!scanner()->HasLineTerminatorAfterNext() &&
PeekAhead() == Token::FUNCTION) {
impl()->ReportMessageAt(
scanner()->peek_location(),
MessageTemplate::kAsyncFunctionInSingleStatementContext);
- *ok = false;
return impl()->NullStatement();
}
V8_FALLTHROUGH;
default:
return ParseExpressionOrLabelledStatement(labels, own_labels,
- allow_function, ok);
+ allow_function);
}
}
template <typename Impl>
typename ParserBase<Impl>::BlockT ParserBase<Impl>::ParseBlock(
- ZonePtrList<const AstRawString>* labels, bool* ok) {
+ ZonePtrList<const AstRawString>* labels) {
// Block ::
// '{' StatementList '}'
- // Construct block expecting 16 statements.
- BlockT body = factory()->NewBlock(16, false, labels);
-
// Parse the statements and collect escaping labels.
- Expect(Token::LBRACE, CHECK_OK_CUSTOM(NullStatement));
+ BlockT body = factory()->NewBlock(false, labels);
+ StatementListT statements(pointer_buffer());
+
+ CheckStackOverflow();
+
{
BlockState block_state(zone(), &scope_);
- scope()->set_start_position(scanner()->location().beg_pos);
- typename Types::Target target(this, body);
+ scope()->set_start_position(peek_position());
+ TargetT target(this, body);
+
+ Expect(Token::LBRACE);
while (peek() != Token::RBRACE) {
- StatementT stat = ParseStatementListItem(CHECK_OK_CUSTOM(NullStatement));
- if (!impl()->IsNull(stat) && !stat->IsEmptyStatement()) {
- body->statements()->Add(stat, zone());
- }
+ StatementT stat = ParseStatementListItem();
+ if (impl()->IsNull(stat)) return body;
+ if (stat->IsEmptyStatement()) continue;
+ statements.Add(stat);
}
- Expect(Token::RBRACE, CHECK_OK_CUSTOM(NullStatement));
+ Expect(Token::RBRACE);
+
int end_pos = end_position();
scope()->set_end_position(end_pos);
+
impl()->RecordBlockSourceRange(body, end_pos);
body->set_scope(scope()->FinalizeBlockScope());
}
+
+ body->InitializeStatements(statements, zone_);
return body;
}
template <typename Impl>
typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseScopedStatement(
- ZonePtrList<const AstRawString>* labels, bool* ok) {
+ ZonePtrList<const AstRawString>* labels) {
if (is_strict(language_mode()) || peek() != Token::FUNCTION) {
- return ParseStatement(labels, nullptr, ok);
+ return ParseStatement(labels, nullptr);
} else {
// Make a block around the statement for a lexical binding
// is introduced by a FunctionDeclaration.
BlockState block_state(zone(), &scope_);
scope()->set_start_position(scanner()->location().beg_pos);
BlockT block = factory()->NewBlock(1, false);
- StatementT body = ParseFunctionDeclaration(CHECK_OK);
+ StatementT body = ParseFunctionDeclaration();
block->statements()->Add(body, zone());
scope()->set_end_position(end_position());
block->set_scope(scope()->FinalizeBlockScope());
@@ -5157,7 +4679,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseScopedStatement(
template <typename Impl>
typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseVariableStatement(
VariableDeclarationContext var_context,
- ZonePtrList<const AstRawString>* names, bool* ok) {
+ ZonePtrList<const AstRawString>* names) {
// VariableStatement ::
// VariableDeclarations ';'
@@ -5174,15 +4696,14 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseVariableStatement(
// is inside an initializer block, it is ignored.
DeclarationParsingResult parsing_result;
- StatementT result =
- ParseVariableDeclarations(var_context, &parsing_result, names, CHECK_OK);
- ExpectSemicolon(ok);
- return result;
+ ParseVariableDeclarations(var_context, &parsing_result, names);
+ ExpectSemicolon();
+ return impl()->BuildInitializationBlock(&parsing_result);
}
template <typename Impl>
-typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseDebuggerStatement(
- bool* ok) {
+typename ParserBase<Impl>::StatementT
+ParserBase<Impl>::ParseDebuggerStatement() {
// In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
// contexts this is used as a statement which invokes the debugger as i a
// break point is present.
@@ -5190,8 +4711,8 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseDebuggerStatement(
// 'debugger' ';'
int pos = peek_position();
- Expect(Token::DEBUGGER, CHECK_OK);
- ExpectSemicolon(CHECK_OK);
+ Consume(Token::DEBUGGER);
+ ExpectSemicolon();
return factory()->NewDebuggerStatement(pos);
}
@@ -5200,7 +4721,7 @@ typename ParserBase<Impl>::StatementT
ParserBase<Impl>::ParseExpressionOrLabelledStatement(
ZonePtrList<const AstRawString>* labels,
ZonePtrList<const AstRawString>* own_labels,
- AllowLabelledFunctionStatement allow_function, bool* ok) {
+ AllowLabelledFunctionStatement allow_function) {
// ExpressionStatement | LabelledStatement ::
// Expression ';'
// Identifier ':' Statement
@@ -5216,7 +4737,6 @@ ParserBase<Impl>::ParseExpressionOrLabelledStatement(
UNREACHABLE(); // Always handled by the callers.
case Token::CLASS:
ReportUnexpectedToken(Next());
- *ok = false;
return impl()->NullStatement();
case Token::LET: {
Token::Value next_next = PeekAhead();
@@ -5230,7 +4750,6 @@ ParserBase<Impl>::ParseExpressionOrLabelledStatement(
}
impl()->ReportMessageAt(scanner()->peek_location(),
MessageTemplate::kUnexpectedLexicalDeclaration);
- *ok = false;
return impl()->NullStatement();
}
default:
@@ -5238,20 +4757,20 @@ ParserBase<Impl>::ParseExpressionOrLabelledStatement(
}
bool starts_with_identifier = peek_any_identifier();
- ExpressionT expr = ParseExpression(CHECK_OK);
+ ExpressionT expr = ParseExpression();
if (peek() == Token::COLON && starts_with_identifier &&
impl()->IsIdentifier(expr)) {
// The whole expression was a single identifier, and not, e.g.,
// something starting with an identifier or a parenthesized identifier.
impl()->DeclareLabel(&labels, &own_labels,
- impl()->AsIdentifierExpression(expr), CHECK_OK);
+ impl()->AsIdentifierExpression(expr));
Consume(Token::COLON);
// ES#sec-labelled-function-declarations Labelled Function Declarations
if (peek() == Token::FUNCTION && is_sloppy(language_mode()) &&
allow_function == kAllowLabelledFunctionStatement) {
- return ParseFunctionDeclaration(ok);
+ return ParseFunctionDeclaration();
}
- return ParseStatement(labels, own_labels, allow_function, ok);
+ return ParseStatement(labels, own_labels, allow_function);
}
// If we have an extension, we allow a native function declaration.
@@ -5260,39 +4779,46 @@ ParserBase<Impl>::ParseExpressionOrLabelledStatement(
if (extension_ != nullptr && peek() == Token::FUNCTION &&
!scanner()->HasLineTerminatorBeforeNext() && impl()->IsNative(expr) &&
!scanner()->literal_contains_escapes()) {
- return ParseNativeDeclaration(ok);
+ return ParseNativeDeclaration();
}
// Parsed expression statement, followed by semicolon.
- ExpectSemicolon(CHECK_OK);
+ ExpectSemicolon();
+ if (expr->IsFailureExpression()) return impl()->NullStatement();
return factory()->NewExpressionStatement(expr, pos);
}
template <typename Impl>
typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseIfStatement(
- ZonePtrList<const AstRawString>* labels, bool* ok) {
+ ZonePtrList<const AstRawString>* labels) {
// IfStatement ::
// 'if' '(' Expression ')' Statement ('else' Statement)?
int pos = peek_position();
- Expect(Token::IF, CHECK_OK);
- Expect(Token::LPAREN, CHECK_OK);
- ExpressionT condition = ParseExpression(CHECK_OK);
- Expect(Token::RPAREN, CHECK_OK);
+ Consume(Token::IF);
+ Expect(Token::LPAREN);
+ ExpressionT condition = ParseExpression();
+ Expect(Token::RPAREN);
SourceRange then_range, else_range;
StatementT then_statement = impl()->NullStatement();
{
SourceRangeScope range_scope(scanner(), &then_range);
- then_statement = ParseScopedStatement(labels, CHECK_OK);
+ // Make a copy of {labels} to avoid conflicts with any
+ // labels that may be applied to the else clause below.
+ auto labels_copy =
+ labels == nullptr
+ ? labels
+ : new (zone()) ZonePtrList<const AstRawString>(*labels, zone());
+ then_statement = ParseScopedStatement(labels_copy);
}
StatementT else_statement = impl()->NullStatement();
if (Check(Token::ELSE)) {
- else_statement = ParseScopedStatement(labels, CHECK_OK);
+ else_statement = ParseScopedStatement(labels);
else_range = SourceRange::ContinuationOf(then_range, end_position());
} else {
- else_statement = factory()->NewEmptyStatement(kNoSourcePosition);
+ else_statement = factory()->EmptyStatement();
}
StatementT stmt =
factory()->NewIfStatement(condition, then_statement, else_statement, pos);
@@ -5301,37 +4827,34 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseIfStatement(
}
template <typename Impl>
-typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseContinueStatement(
- bool* ok) {
+typename ParserBase<Impl>::StatementT
+ParserBase<Impl>::ParseContinueStatement() {
// ContinueStatement ::
// 'continue' Identifier? ';'
int pos = peek_position();
- Expect(Token::CONTINUE, CHECK_OK);
+ Consume(Token::CONTINUE);
IdentifierT label = impl()->NullIdentifier();
Token::Value tok = peek();
- if (!scanner()->HasLineTerminatorBeforeNext() && tok != Token::SEMICOLON &&
- tok != Token::RBRACE && tok != Token::EOS) {
+ if (!scanner()->HasLineTerminatorBeforeNext() &&
+ !Token::IsAutoSemicolon(tok)) {
// ECMA allows "eval" or "arguments" as labels even in strict mode.
- label = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
+ label = ParseIdentifier();
}
- typename Types::IterationStatement target =
- impl()->LookupContinueTarget(label, CHECK_OK);
+ IterationStatementT target = impl()->LookupContinueTarget(label);
if (impl()->IsNull(target)) {
// Illegal continue statement.
- MessageTemplate::Template message = MessageTemplate::kIllegalContinue;
- typename Types::BreakableStatement breakable_target =
- impl()->LookupBreakTarget(label, CHECK_OK);
+ MessageTemplate message = MessageTemplate::kIllegalContinue;
+ BreakableStatementT breakable_target = impl()->LookupBreakTarget(label);
if (impl()->IsNull(label)) {
message = MessageTemplate::kNoIterationStatement;
} else if (impl()->IsNull(breakable_target)) {
message = MessageTemplate::kUnknownLabel;
}
ReportMessage(message, label);
- *ok = false;
return impl()->NullStatement();
}
- ExpectSemicolon(CHECK_OK);
+ ExpectSemicolon();
StatementT stmt = factory()->NewContinueStatement(target, pos);
impl()->RecordJumpStatementSourceRange(stmt, end_position());
return stmt;
@@ -5339,53 +4862,50 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseContinueStatement(
template <typename Impl>
typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseBreakStatement(
- ZonePtrList<const AstRawString>* labels, bool* ok) {
+ ZonePtrList<const AstRawString>* labels) {
// BreakStatement ::
// 'break' Identifier? ';'
int pos = peek_position();
- Expect(Token::BREAK, CHECK_OK);
+ Consume(Token::BREAK);
IdentifierT label = impl()->NullIdentifier();
Token::Value tok = peek();
- if (!scanner()->HasLineTerminatorBeforeNext() && tok != Token::SEMICOLON &&
- tok != Token::RBRACE && tok != Token::EOS) {
+ if (!scanner()->HasLineTerminatorBeforeNext() &&
+ !Token::IsAutoSemicolon(tok)) {
// ECMA allows "eval" or "arguments" as labels even in strict mode.
- label = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
+ label = ParseIdentifier();
}
// Parse labeled break statements that target themselves into
// empty statements, e.g. 'l1: l2: l3: break l2;'
if (!impl()->IsNull(label) && impl()->ContainsLabel(labels, label)) {
- ExpectSemicolon(CHECK_OK);
- return factory()->NewEmptyStatement(pos);
+ ExpectSemicolon();
+ return factory()->EmptyStatement();
}
- typename Types::BreakableStatement target =
- impl()->LookupBreakTarget(label, CHECK_OK);
+ BreakableStatementT target = impl()->LookupBreakTarget(label);
if (impl()->IsNull(target)) {
// Illegal break statement.
- MessageTemplate::Template message = MessageTemplate::kIllegalBreak;
+ MessageTemplate message = MessageTemplate::kIllegalBreak;
if (!impl()->IsNull(label)) {
message = MessageTemplate::kUnknownLabel;
}
ReportMessage(message, label);
- *ok = false;
return impl()->NullStatement();
}
- ExpectSemicolon(CHECK_OK);
+ ExpectSemicolon();
StatementT stmt = factory()->NewBreakStatement(target, pos);
impl()->RecordJumpStatementSourceRange(stmt, end_position());
return stmt;
}
template <typename Impl>
-typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseReturnStatement(
- bool* ok) {
+typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseReturnStatement() {
// ReturnStatement ::
// 'return' [no line terminator] Expression? ';'
// Consume the return token. It is necessary to do that before
// reporting any errors on it, because of the way errors are
// reported (underlining).
- Expect(Token::RETURN, CHECK_OK);
+ Consume(Token::RETURN);
Scanner::Location loc = scanner()->location();
switch (GetDeclarationScope()->scope_type()) {
@@ -5393,7 +4913,6 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseReturnStatement(
case EVAL_SCOPE:
case MODULE_SCOPE:
impl()->ReportMessageAt(loc, MessageTemplate::kIllegalReturn);
- *ok = false;
return impl()->NullStatement();
default:
break;
@@ -5401,15 +4920,15 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseReturnStatement(
Token::Value tok = peek();
ExpressionT return_value = impl()->NullExpression();
- if (scanner()->HasLineTerminatorBeforeNext() || tok == Token::SEMICOLON ||
- tok == Token::RBRACE || tok == Token::EOS) {
+ if (scanner()->HasLineTerminatorBeforeNext() || Token::IsAutoSemicolon(tok)) {
if (IsDerivedConstructor(function_state_->kind())) {
return_value = impl()->ThisExpression(loc.beg_pos);
}
} else {
- return_value = ParseExpression(CHECK_OK);
+ return_value = ParseExpression();
}
- ExpectSemicolon(CHECK_OK);
+ ExpectSemicolon();
+
return_value = impl()->RewriteReturn(return_value, loc.beg_pos);
int continuation_pos = end_position();
StatementT stmt =
@@ -5420,29 +4939,28 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseReturnStatement(
template <typename Impl>
typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseWithStatement(
- ZonePtrList<const AstRawString>* labels, bool* ok) {
+ ZonePtrList<const AstRawString>* labels) {
// WithStatement ::
// 'with' '(' Expression ')' Statement
- Expect(Token::WITH, CHECK_OK);
+ Consume(Token::WITH);
int pos = position();
if (is_strict(language_mode())) {
ReportMessage(MessageTemplate::kStrictWith);
- *ok = false;
return impl()->NullStatement();
}
- Expect(Token::LPAREN, CHECK_OK);
- ExpressionT expr = ParseExpression(CHECK_OK);
- Expect(Token::RPAREN, CHECK_OK);
+ Expect(Token::LPAREN);
+ ExpressionT expr = ParseExpression();
+ Expect(Token::RPAREN);
Scope* with_scope = NewScope(WITH_SCOPE);
StatementT body = impl()->NullStatement();
{
BlockState block_state(&scope_, with_scope);
with_scope->set_start_position(scanner()->peek_location().beg_pos);
- body = ParseStatement(labels, nullptr, CHECK_OK);
+ body = ParseStatement(labels, nullptr);
with_scope->set_end_position(end_position());
}
return factory()->NewWithStatement(with_scope, expr, body, pos);
@@ -5451,27 +4969,30 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseWithStatement(
template <typename Impl>
typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseDoWhileStatement(
ZonePtrList<const AstRawString>* labels,
- ZonePtrList<const AstRawString>* own_labels, bool* ok) {
+ ZonePtrList<const AstRawString>* own_labels) {
// DoStatement ::
// 'do' Statement 'while' '(' Expression ')' ';'
+ typename FunctionState::LoopScope loop_scope(function_state_);
auto loop =
factory()->NewDoWhileStatement(labels, own_labels, peek_position());
- typename Types::Target target(this, loop);
+ TargetT target(this, loop);
SourceRange body_range;
StatementT body = impl()->NullStatement();
- Expect(Token::DO, CHECK_OK);
+ Consume(Token::DO);
+
+ CheckStackOverflow();
{
SourceRangeScope range_scope(scanner(), &body_range);
- body = ParseStatement(nullptr, nullptr, CHECK_OK);
+ body = ParseStatement(nullptr, nullptr);
}
- Expect(Token::WHILE, CHECK_OK);
- Expect(Token::LPAREN, CHECK_OK);
+ Expect(Token::WHILE);
+ Expect(Token::LPAREN);
- ExpressionT cond = ParseExpression(CHECK_OK);
- Expect(Token::RPAREN, CHECK_OK);
+ ExpressionT cond = ParseExpression();
+ Expect(Token::RPAREN);
// Allow do-statements to be terminated with and without
// semi-colons. This allows code such as 'do;while(0)return' to
@@ -5488,23 +5009,24 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseDoWhileStatement(
template <typename Impl>
typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseWhileStatement(
ZonePtrList<const AstRawString>* labels,
- ZonePtrList<const AstRawString>* own_labels, bool* ok) {
+ ZonePtrList<const AstRawString>* own_labels) {
// WhileStatement ::
// 'while' '(' Expression ')' Statement
+ typename FunctionState::LoopScope loop_scope(function_state_);
auto loop = factory()->NewWhileStatement(labels, own_labels, peek_position());
- typename Types::Target target(this, loop);
+ TargetT target(this, loop);
SourceRange body_range;
StatementT body = impl()->NullStatement();
- Expect(Token::WHILE, CHECK_OK);
- Expect(Token::LPAREN, CHECK_OK);
- ExpressionT cond = ParseExpression(CHECK_OK);
- Expect(Token::RPAREN, CHECK_OK);
+ Consume(Token::WHILE);
+ Expect(Token::LPAREN);
+ ExpressionT cond = ParseExpression();
+ Expect(Token::RPAREN);
{
SourceRangeScope range_scope(scanner(), &body_range);
- body = ParseStatement(nullptr, nullptr, CHECK_OK);
+ body = ParseStatement(nullptr, nullptr);
}
loop->Initialize(cond, body);
@@ -5514,20 +5036,18 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseWhileStatement(
}
template <typename Impl>
-typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseThrowStatement(
- bool* ok) {
+typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseThrowStatement() {
// ThrowStatement ::
// 'throw' Expression ';'
- Expect(Token::THROW, CHECK_OK);
+ Consume(Token::THROW);
int pos = position();
if (scanner()->HasLineTerminatorBeforeNext()) {
ReportMessage(MessageTemplate::kNewlineAfterThrow);
- *ok = false;
return impl()->NullStatement();
}
- ExpressionT exception = ParseExpression(CHECK_OK);
- ExpectSemicolon(CHECK_OK);
+ ExpressionT exception = ParseExpression();
+ ExpectSemicolon();
StatementT stmt = impl()->NewThrowStatement(exception, pos);
impl()->RecordThrowSourceRange(stmt, end_position());
@@ -5537,7 +5057,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseThrowStatement(
template <typename Impl>
typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseSwitchStatement(
- ZonePtrList<const AstRawString>* labels, bool* ok) {
+ ZonePtrList<const AstRawString>* labels) {
// SwitchStatement ::
// 'switch' '(' Expression ')' '{' CaseClause* '}'
// CaseClause ::
@@ -5546,10 +5066,10 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseSwitchStatement(
int switch_pos = peek_position();
- Expect(Token::SWITCH, CHECK_OK);
- Expect(Token::LPAREN, CHECK_OK);
- ExpressionT tag = ParseExpression(CHECK_OK);
- Expect(Token::RPAREN, CHECK_OK);
+ Consume(Token::SWITCH);
+ Expect(Token::LPAREN);
+ ExpressionT tag = ParseExpression();
+ Expect(Token::RPAREN);
auto switch_statement =
factory()->NewSwitchStatement(labels, tag, switch_pos);
@@ -5558,38 +5078,41 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseSwitchStatement(
BlockState cases_block_state(zone(), &scope_);
scope()->set_start_position(switch_pos);
scope()->SetNonlinear();
- typename Types::Target target(this, switch_statement);
+ TargetT target(this, switch_statement);
bool default_seen = false;
- Expect(Token::LBRACE, CHECK_OK);
+ Expect(Token::LBRACE);
while (peek() != Token::RBRACE) {
// An empty label indicates the default case.
ExpressionT label = impl()->NullExpression();
+ StatementListT statements(pointer_buffer());
SourceRange clause_range;
- SourceRangeScope range_scope(scanner(), &clause_range);
- if (Check(Token::CASE)) {
- label = ParseExpression(CHECK_OK);
- } else {
- Expect(Token::DEFAULT, CHECK_OK);
- if (default_seen) {
- ReportMessage(MessageTemplate::kMultipleDefaultsInSwitch);
- *ok = false;
- return impl()->NullStatement();
+ {
+ SourceRangeScope range_scope(scanner(), &clause_range);
+ if (Check(Token::CASE)) {
+ label = ParseExpression();
+ } else {
+ Expect(Token::DEFAULT);
+ if (default_seen) {
+ ReportMessage(MessageTemplate::kMultipleDefaultsInSwitch);
+ return impl()->NullStatement();
+ }
+ default_seen = true;
+ }
+ Expect(Token::COLON);
+ while (peek() != Token::CASE && peek() != Token::DEFAULT &&
+ peek() != Token::RBRACE) {
+ StatementT stat = ParseStatementListItem();
+ if (impl()->IsNull(stat)) return stat;
+ if (stat->IsEmptyStatement()) continue;
+ statements.Add(stat);
}
- default_seen = true;
- }
- Expect(Token::COLON, CHECK_OK);
- StatementListT statements = impl()->NewStatementList(5);
- while (peek() != Token::CASE && peek() != Token::DEFAULT &&
- peek() != Token::RBRACE) {
- StatementT stat = ParseStatementListItem(CHECK_OK);
- statements->Add(stat, zone());
}
auto clause = factory()->NewCaseClause(label, statements);
- impl()->RecordCaseClauseSourceRange(clause, range_scope.Finalize());
+ impl()->RecordCaseClauseSourceRange(clause, clause_range);
switch_statement->cases()->Add(clause, zone());
}
- Expect(Token::RBRACE, CHECK_OK);
+ Expect(Token::RBRACE);
int end_pos = end_position();
scope()->set_end_position(end_pos);
@@ -5603,8 +5126,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseSwitchStatement(
}
template <typename Impl>
-typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseTryStatement(
- bool* ok) {
+typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseTryStatement() {
// TryStatement ::
// 'try' Block Catch
// 'try' Block Finally
@@ -5616,22 +5138,21 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseTryStatement(
// Finally ::
// 'finally' Block
- Expect(Token::TRY, CHECK_OK);
+ Consume(Token::TRY);
int pos = position();
- BlockT try_block = ParseBlock(nullptr, CHECK_OK);
+ BlockT try_block = ParseBlock(nullptr);
CatchInfo catch_info(this);
if (peek() != Token::CATCH && peek() != Token::FINALLY) {
ReportMessage(MessageTemplate::kNoCatchOrFinally);
- *ok = false;
return impl()->NullStatement();
}
SourceRange catch_range, finally_range;
- BlockT catch_block = impl()->NullStatement();
+ BlockT catch_block = impl()->NullBlock();
{
SourceRangeScope catch_range_scope(scanner(), &catch_range);
if (Check(Token::CATCH)) {
@@ -5644,57 +5165,74 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseTryStatement(
{
BlockState catch_block_state(&scope_, catch_info.scope);
-
- catch_block = factory()->NewBlock(16, false);
+ StatementListT catch_statements(pointer_buffer());
// Create a block scope to hold any lexical declarations created
// as part of destructuring the catch parameter.
{
BlockState catch_variable_block_state(zone(), &scope_);
- scope()->set_start_position(scanner()->location().beg_pos);
+ scope()->set_start_position(position());
- // This does not simply call ParsePrimaryExpression to avoid
- // ExpressionFromIdentifier from being called in the first
- // branch, which would introduce an unresolved symbol and mess
- // with arrow function names.
if (peek_any_identifier()) {
- catch_info.name =
- ParseIdentifier(kDontAllowRestrictedIdentifiers, CHECK_OK);
+ IdentifierT identifier = ParseNonRestrictedIdentifier();
+ RETURN_IF_PARSE_ERROR;
+ catch_info.variable = impl()->DeclareCatchVariableName(
+ catch_info.scope, identifier);
} else {
- ExpressionClassifier pattern_classifier(this);
- catch_info.pattern = ParseBindingPattern(CHECK_OK);
+ catch_info.variable = catch_info.scope->DeclareCatchVariableName(
+ ast_value_factory()->dot_catch_string());
+ VariableDeclarationParsingScope destructuring(
+ impl(), VariableMode::kLet, nullptr);
+ catch_info.pattern = ParseBindingPattern();
+ RETURN_IF_PARSE_ERROR;
+ catch_statements.Add(impl()->RewriteCatchPattern(&catch_info));
}
- Expect(Token::RPAREN, CHECK_OK);
- impl()->RewriteCatchPattern(&catch_info, CHECK_OK);
- if (!impl()->IsNull(catch_info.init_block)) {
- catch_block->statements()->Add(catch_info.init_block, zone());
+ Expect(Token::RPAREN);
+
+ BlockT inner_block = ParseBlock(nullptr);
+ catch_statements.Add(inner_block);
+
+ // Check for `catch(e) { let e; }` and similar errors.
+ Scope* inner_scope = inner_block->scope();
+ if (inner_scope != nullptr) {
+ const AstRawString* conflict = nullptr;
+ if (impl()->IsNull(catch_info.pattern)) {
+ const AstRawString* name = catch_info.variable->raw_name();
+ if (inner_scope->LookupLocal(name)) conflict = name;
+ } else {
+ conflict = inner_scope->FindVariableDeclaredIn(
+ scope(), VariableMode::kVar);
+ }
+ if (conflict != nullptr) {
+ impl()->ReportVarRedeclarationIn(conflict, inner_scope);
+ }
}
- 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(end_position());
+ catch_block = factory()->NewBlock(false, catch_statements);
catch_block->set_scope(scope()->FinalizeBlockScope());
}
}
catch_info.scope->set_end_position(end_position());
} else {
- catch_block = ParseBlock(nullptr, CHECK_OK);
+ catch_block = ParseBlock(nullptr);
}
}
}
- BlockT finally_block = impl()->NullStatement();
- DCHECK(peek() == Token::FINALLY || !impl()->IsNull(catch_block));
+ BlockT finally_block = impl()->NullBlock();
+ DCHECK(has_error() || peek() == Token::FINALLY ||
+ !impl()->IsNull(catch_block));
{
SourceRangeScope range_scope(scanner(), &finally_range);
if (Check(Token::FINALLY)) {
- finally_block = ParseBlock(nullptr, CHECK_OK);
+ finally_block = ParseBlock(nullptr);
}
}
+ RETURN_IF_PARSE_ERROR;
return impl()->RewriteTryStatement(try_block, catch_block, catch_range,
finally_block, finally_range, catch_info,
pos);
@@ -5703,7 +5241,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseTryStatement(
template <typename Impl>
typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForStatement(
ZonePtrList<const AstRawString>* labels,
- ZonePtrList<const AstRawString>* own_labels, bool* ok) {
+ ZonePtrList<const AstRawString>* own_labels) {
// Either a standard for loop
// for (<init>; <cond>; <next>) { ... }
// or a for-each loop
@@ -5711,18 +5249,19 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForStatement(
//
// We parse a declaration/expression after the 'for (' and then read the first
// expression/declaration before we know if this is a for or a for-each.
+ typename FunctionState::LoopScope loop_scope(function_state_);
int stmt_pos = peek_position();
ForInfo for_info(this);
- Expect(Token::FOR, CHECK_OK);
- Expect(Token::LPAREN, CHECK_OK);
+ Consume(Token::FOR);
+ Expect(Token::LPAREN);
if (peek() == Token::CONST || (peek() == Token::LET && IsNextLetKeyword())) {
// The initializer contains lexical declarations,
// so create an in-between scope.
BlockState for_state(zone(), &scope_);
- scope()->set_start_position(scanner()->location().beg_pos);
+ scope()->set_start_position(position());
// Also record whether inner functions or evals are found inside
// this loop, as this information is used to simplify the desugaring
@@ -5736,78 +5275,94 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForStatement(
{
BlockState inner_state(&scope_, inner_block_scope);
ParseVariableDeclarations(kForStatement, &for_info.parsing_result,
- nullptr, CHECK_OK);
+ &for_info.bound_names);
}
DCHECK(IsLexicalVariableMode(for_info.parsing_result.descriptor.mode));
- for_info.position = scanner()->location().beg_pos;
+ for_info.position = position();
if (CheckInOrOf(&for_info.mode)) {
scope()->set_is_hidden();
return ParseForEachStatementWithDeclarations(
- stmt_pos, &for_info, labels, own_labels, inner_block_scope, ok);
+ stmt_pos, &for_info, labels, own_labels, inner_block_scope);
}
- Expect(Token::SEMICOLON, CHECK_OK);
+ Expect(Token::SEMICOLON);
- StatementT init = impl()->BuildInitializationBlock(
- &for_info.parsing_result, &for_info.bound_names, CHECK_OK);
+ // Parse the remaining code in the inner block scope since the declaration
+ // above was parsed there. We'll finalize the unnecessary outer block scope
+ // after parsing the rest of the loop.
+ StatementT result = impl()->NullStatement();
+ inner_block_scope->set_start_position(scope()->start_position());
+ {
+ BlockState inner_state(&scope_, inner_block_scope);
+ StatementT init =
+ impl()->BuildInitializationBlock(&for_info.parsing_result);
- Scope* finalized = inner_block_scope->FinalizeBlockScope();
- // No variable declarations will have been created in inner_block_scope.
+ result = ParseStandardForLoopWithLexicalDeclarations(
+ stmt_pos, init, &for_info, labels, own_labels);
+ }
+ Scope* finalized = scope()->FinalizeBlockScope();
DCHECK_NULL(finalized);
USE(finalized);
- return ParseStandardForLoopWithLexicalDeclarations(
- stmt_pos, init, &for_info, labels, own_labels, ok);
+ return result;
}
StatementT init = impl()->NullStatement();
if (peek() == Token::VAR) {
- ParseVariableDeclarations(kForStatement, &for_info.parsing_result, nullptr,
- CHECK_OK);
+ ParseVariableDeclarations(kForStatement, &for_info.parsing_result,
+ &for_info.bound_names);
DCHECK_EQ(for_info.parsing_result.descriptor.mode, VariableMode::kVar);
for_info.position = scanner()->location().beg_pos;
if (CheckInOrOf(&for_info.mode)) {
return ParseForEachStatementWithDeclarations(stmt_pos, &for_info, labels,
- own_labels, nullptr, ok);
+ own_labels, scope());
}
- init = impl()->BuildInitializationBlock(&for_info.parsing_result, nullptr,
- CHECK_OK);
+ init = impl()->BuildInitializationBlock(&for_info.parsing_result);
} else if (peek() != Token::SEMICOLON) {
// The initializer does not contain declarations.
int lhs_beg_pos = peek_position();
- ExpressionClassifier classifier(this);
- ExpressionT expression = ParseExpressionCoverGrammar(false, CHECK_OK);
- int lhs_end_pos = end_position();
-
- bool is_for_each = CheckInOrOf(&for_info.mode);
- bool is_destructuring = is_for_each && (expression->IsArrayLiteral() ||
- expression->IsObjectLiteral());
-
- if (is_destructuring) {
- ValidateAssignmentPattern(CHECK_OK);
- } else {
- ValidateExpression(CHECK_OK);
+ int lhs_end_pos;
+ bool is_for_each;
+ ExpressionT expression;
+ {
+ ExpressionParsingScope parsing_scope(impl());
+ AcceptINScope scope(this, false);
+ expression = ParseExpressionCoverGrammar();
+ // Initializer is reference followed by in/of.
+ lhs_end_pos = end_position();
+ is_for_each = CheckInOrOf(&for_info.mode);
+ if (is_for_each) {
+ if (expression->IsPattern()) {
+ parsing_scope.ValidatePattern(expression, lhs_beg_pos, lhs_end_pos);
+ } else {
+ expression = parsing_scope.ValidateAndRewriteReference(
+ expression, lhs_beg_pos, lhs_end_pos);
+ }
+ } else {
+ parsing_scope.ValidateExpression();
+ }
}
if (is_for_each) {
return ParseForEachStatementWithoutDeclarations(
stmt_pos, expression, lhs_beg_pos, lhs_end_pos, &for_info, labels,
- own_labels, ok);
+ own_labels);
}
// Initializer is just an expression.
init = factory()->NewExpressionStatement(expression, lhs_beg_pos);
}
- Expect(Token::SEMICOLON, CHECK_OK);
+ Expect(Token::SEMICOLON);
// Standard 'for' loop, we have parsed the initializer at this point.
ExpressionT cond = impl()->NullExpression();
StatementT next = impl()->NullStatement();
StatementT body = impl()->NullStatement();
- ForStatementT loop = ParseStandardForLoop(stmt_pos, labels, own_labels, &cond,
- &next, &body, CHECK_OK);
+ ForStatementT loop =
+ ParseStandardForLoop(stmt_pos, labels, own_labels, &cond, &next, &body);
+ RETURN_IF_PARSE_ERROR;
loop->Initialize(init, cond, next, body);
return loop;
}
@@ -5816,14 +5371,12 @@ template <typename Impl>
typename ParserBase<Impl>::StatementT
ParserBase<Impl>::ParseForEachStatementWithDeclarations(
int stmt_pos, ForInfo* for_info, ZonePtrList<const AstRawString>* labels,
- ZonePtrList<const AstRawString>* own_labels, Scope* inner_block_scope,
- bool* ok) {
+ ZonePtrList<const AstRawString>* own_labels, Scope* inner_block_scope) {
// Just one declaration followed by in/of.
if (for_info->parsing_result.declarations.size() != 1) {
impl()->ReportMessageAt(for_info->parsing_result.bindings_loc,
MessageTemplate::kForInOfLoopMultiBindings,
ForEachStatement::VisitModeString(for_info->mode));
- *ok = false;
return impl()->NullStatement();
}
if (for_info->parsing_result.first_initializer_loc.IsValid() &&
@@ -5835,80 +5388,66 @@ ParserBase<Impl>::ParseForEachStatementWithDeclarations(
impl()->ReportMessageAt(for_info->parsing_result.first_initializer_loc,
MessageTemplate::kForInOfLoopInitializer,
ForEachStatement::VisitModeString(for_info->mode));
- *ok = false;
return impl()->NullStatement();
}
- // Reset the declaration_kind to ensure proper processing during declaration.
- for_info->parsing_result.descriptor.declaration_kind =
- DeclarationDescriptor::FOR_EACH;
-
BlockT init_block = impl()->RewriteForVarInLegacy(*for_info);
auto loop = factory()->NewForEachStatement(for_info->mode, labels, own_labels,
stmt_pos);
- typename Types::Target target(this, loop);
+ TargetT target(this, loop);
ExpressionT enumerable = impl()->NullExpression();
if (for_info->mode == ForEachStatement::ITERATE) {
- ExpressionClassifier classifier(this);
- enumerable = ParseAssignmentExpression(true, CHECK_OK);
- ValidateExpression(CHECK_OK);
+ AcceptINScope scope(this, true);
+ enumerable = ParseAssignmentExpression();
} else {
- enumerable = ParseExpression(CHECK_OK);
+ enumerable = ParseExpression();
}
- Expect(Token::RPAREN, CHECK_OK);
+ Expect(Token::RPAREN);
- Scope* for_scope = nullptr;
- if (inner_block_scope != nullptr) {
- for_scope = inner_block_scope->outer_scope();
- DCHECK_EQ(for_scope, scope());
- inner_block_scope->set_start_position(scanner()->location().beg_pos);
+ if (IsLexicalVariableMode(for_info->parsing_result.descriptor.mode)) {
+ inner_block_scope->set_start_position(position());
}
ExpressionT each_variable = impl()->NullExpression();
- BlockT body_block = impl()->NullStatement();
+ BlockT body_block = impl()->NullBlock();
{
- BlockState block_state(
- &scope_, inner_block_scope != nullptr ? inner_block_scope : scope_);
+ BlockState block_state(&scope_, inner_block_scope);
SourceRange body_range;
- SourceRangeScope range_scope(scanner(), &body_range);
-
- StatementT body = ParseStatement(nullptr, nullptr, CHECK_OK);
- impl()->RecordIterationStatementSourceRange(loop, range_scope.Finalize());
+ StatementT body = impl()->NullStatement();
+ {
+ SourceRangeScope range_scope(scanner(), &body_range);
+ body = ParseStatement(nullptr, nullptr);
+ }
+ impl()->RecordIterationStatementSourceRange(loop, body_range);
- impl()->DesugarBindingInForEachStatement(for_info, &body_block,
- &each_variable, CHECK_OK);
+ DesugarBindingInForEachStatement(for_info, &body_block, &each_variable);
body_block->statements()->Add(body, zone());
- if (inner_block_scope != nullptr) {
- inner_block_scope->set_end_position(end_position());
- body_block->set_scope(inner_block_scope->FinalizeBlockScope());
+ if (IsLexicalVariableMode(for_info->parsing_result.descriptor.mode)) {
+ scope()->set_end_position(end_position());
+ body_block->set_scope(scope()->FinalizeBlockScope());
}
}
- StatementT final_loop = impl()->InitializeForEachStatement(
- loop, each_variable, enumerable, body_block);
+ loop->Initialize(each_variable, enumerable, body_block);
- init_block =
- impl()->CreateForEachStatementTDZ(init_block, *for_info, CHECK_OK);
-
- if (for_scope != nullptr) {
- for_scope->set_end_position(end_position());
- for_scope = for_scope->FinalizeBlockScope();
- }
+ init_block = impl()->CreateForEachStatementTDZ(init_block, *for_info);
// Parsed for-in loop w/ variable declarations.
if (!impl()->IsNull(init_block)) {
- init_block->statements()->Add(final_loop, zone());
- init_block->set_scope(for_scope);
+ init_block->statements()->Add(loop, zone());
+ if (IsLexicalVariableMode(for_info->parsing_result.descriptor.mode)) {
+ scope()->set_end_position(end_position());
+ init_block->set_scope(scope()->FinalizeBlockScope());
+ }
return init_block;
}
- DCHECK_NULL(for_scope);
- return final_loop;
+ return loop;
}
template <typename Impl>
@@ -5916,38 +5455,31 @@ typename ParserBase<Impl>::StatementT
ParserBase<Impl>::ParseForEachStatementWithoutDeclarations(
int stmt_pos, ExpressionT expression, int lhs_beg_pos, int lhs_end_pos,
ForInfo* for_info, ZonePtrList<const AstRawString>* labels,
- ZonePtrList<const AstRawString>* own_labels, bool* ok) {
- // Initializer is reference followed by in/of.
- if (!expression->IsArrayLiteral() && !expression->IsObjectLiteral()) {
- expression = CheckAndRewriteReferenceExpression(
- expression, lhs_beg_pos, lhs_end_pos, MessageTemplate::kInvalidLhsInFor,
- kSyntaxError, CHECK_OK);
- }
-
+ ZonePtrList<const AstRawString>* own_labels) {
auto loop = factory()->NewForEachStatement(for_info->mode, labels, own_labels,
stmt_pos);
- typename Types::Target target(this, loop);
+ TargetT target(this, loop);
ExpressionT enumerable = impl()->NullExpression();
if (for_info->mode == ForEachStatement::ITERATE) {
- ExpressionClassifier classifier(this);
- enumerable = ParseAssignmentExpression(true, CHECK_OK);
- ValidateExpression(CHECK_OK);
+ AcceptINScope scope(this, true);
+ enumerable = ParseAssignmentExpression();
} else {
- enumerable = ParseExpression(CHECK_OK);
+ enumerable = ParseExpression();
}
- Expect(Token::RPAREN, CHECK_OK);
+ Expect(Token::RPAREN);
StatementT body = impl()->NullStatement();
+ SourceRange body_range;
{
- SourceRange body_range;
SourceRangeScope range_scope(scanner(), &body_range);
-
- body = ParseStatement(nullptr, nullptr, CHECK_OK);
- impl()->RecordIterationStatementSourceRange(loop, range_scope.Finalize());
+ body = ParseStatement(nullptr, nullptr);
}
- return impl()->InitializeForEachStatement(loop, expression, enumerable, body);
+ impl()->RecordIterationStatementSourceRange(loop, body_range);
+ RETURN_IF_PARSE_ERROR;
+ loop->Initialize(expression, enumerable, body);
+ return loop;
}
template <typename Impl>
@@ -5955,7 +5487,7 @@ typename ParserBase<Impl>::StatementT
ParserBase<Impl>::ParseStandardForLoopWithLexicalDeclarations(
int stmt_pos, StatementT init, ForInfo* for_info,
ZonePtrList<const AstRawString>* labels,
- ZonePtrList<const AstRawString>* own_labels, bool* ok) {
+ ZonePtrList<const AstRawString>* own_labels) {
// The condition and the next statement of the for loop must be parsed
// in a new scope.
Scope* inner_scope = NewScope(BLOCK_SCOPE);
@@ -5966,8 +5498,9 @@ ParserBase<Impl>::ParseStandardForLoopWithLexicalDeclarations(
{
BlockState block_state(&scope_, inner_scope);
scope()->set_start_position(scanner()->location().beg_pos);
- loop = ParseStandardForLoop(stmt_pos, labels, own_labels, &cond, &next,
- &body, CHECK_OK);
+ loop =
+ ParseStandardForLoop(stmt_pos, labels, own_labels, &cond, &next, &body);
+ RETURN_IF_PARSE_ERROR;
scope()->set_end_position(end_position());
}
@@ -5976,7 +5509,7 @@ ParserBase<Impl>::ParseStandardForLoopWithLexicalDeclarations(
function_state_->contains_function_or_eval()) {
scope()->set_is_hidden();
return impl()->DesugarLexicalBindingsInForStatement(
- loop, init, cond, next, body, inner_scope, *for_info, ok);
+ loop, init, cond, next, body, inner_scope, *for_info);
} else {
inner_scope = inner_scope->FinalizeBlockScope();
DCHECK_NULL(inner_scope);
@@ -6012,25 +5545,25 @@ template <typename Impl>
typename ParserBase<Impl>::ForStatementT ParserBase<Impl>::ParseStandardForLoop(
int stmt_pos, ZonePtrList<const AstRawString>* labels,
ZonePtrList<const AstRawString>* own_labels, ExpressionT* cond,
- StatementT* next, StatementT* body, bool* ok) {
+ StatementT* next, StatementT* body) {
ForStatementT loop = factory()->NewForStatement(labels, own_labels, stmt_pos);
- typename Types::Target target(this, loop);
+ TargetT target(this, loop);
if (peek() != Token::SEMICOLON) {
- *cond = ParseExpression(CHECK_OK);
+ *cond = ParseExpression();
}
- Expect(Token::SEMICOLON, CHECK_OK);
+ Expect(Token::SEMICOLON);
if (peek() != Token::RPAREN) {
- ExpressionT exp = ParseExpression(CHECK_OK);
+ ExpressionT exp = ParseExpression();
*next = factory()->NewExpressionStatement(exp, exp->position());
}
- Expect(Token::RPAREN, CHECK_OK);
+ Expect(Token::RPAREN);
SourceRange body_range;
{
SourceRangeScope range_scope(scanner(), &body_range);
- *body = ParseStatement(nullptr, nullptr, CHECK_OK);
+ *body = ParseStatement(nullptr, nullptr);
}
impl()->RecordIterationStatementSourceRange(loop, body_range);
@@ -6038,22 +5571,12 @@ typename ParserBase<Impl>::ForStatementT ParserBase<Impl>::ParseStandardForLoop(
}
template <typename Impl>
-void ParserBase<Impl>::MarkLoopVariableAsAssigned(
- Scope* scope, Variable* var,
- typename DeclarationDescriptor::Kind declaration_kind) {
- if (!IsLexicalVariableMode(var->mode()) &&
- (!scope->is_function_scope() ||
- declaration_kind == DeclarationDescriptor::FOR_EACH)) {
- var->set_maybe_assigned();
- }
-}
-
-template <typename Impl>
typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement(
ZonePtrList<const AstRawString>* labels,
- ZonePtrList<const AstRawString>* own_labels, bool* ok) {
+ ZonePtrList<const AstRawString>* own_labels) {
// for await '(' ForDeclaration of AssignmentExpression ')'
DCHECK(is_async_function());
+ typename FunctionState::LoopScope loop_scope(function_state_);
int stmt_pos = peek_position();
@@ -6062,14 +5585,19 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement(
// Create an in-between scope for let-bound iteration variables.
BlockState for_state(zone(), &scope_);
- Expect(Token::FOR, CHECK_OK);
- Expect(Token::AWAIT, CHECK_OK);
- Expect(Token::LPAREN, CHECK_OK);
+ Expect(Token::FOR);
+ Expect(Token::AWAIT);
+ Expect(Token::LPAREN);
scope()->set_start_position(scanner()->location().beg_pos);
scope()->set_is_hidden();
- auto loop = factory()->NewForOfStatement(labels, own_labels, stmt_pos);
- typename Types::Target target(this, loop);
+ auto loop = factory()->NewForOfStatement(labels, own_labels, stmt_pos,
+ IteratorType::kAsync);
+ // Two suspends: one for next() and one for return()
+ function_state_->AddSuspend();
+ function_state_->AddSuspend();
+
+ TargetT target(this, loop);
ExpressionT each_variable = impl()->NullExpression();
@@ -6088,7 +5616,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement(
{
BlockState inner_state(&scope_, inner_block_scope);
ParseVariableDeclarations(kForStatement, &for_info.parsing_result,
- nullptr, CHECK_OK);
+ &for_info.bound_names);
}
for_info.position = scanner()->location().beg_pos;
@@ -6097,7 +5625,6 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement(
impl()->ReportMessageAt(for_info.parsing_result.bindings_loc,
MessageTemplate::kForInOfLoopMultiBindings,
"for-await-of");
- *ok = false;
return impl()->NullStatement();
}
@@ -6106,7 +5633,6 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement(
impl()->ReportMessageAt(for_info.parsing_result.first_initializer_loc,
MessageTemplate::kForInOfLoopInitializer,
"for-await-of");
- *ok = false;
return impl()->NullStatement();
}
} else {
@@ -6115,33 +5641,29 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement(
// Statement
int lhs_beg_pos = peek_position();
BlockState inner_state(&scope_, inner_block_scope);
- ExpressionClassifier classifier(this);
- ExpressionT lhs = each_variable = ParseLeftHandSideExpression(CHECK_OK);
+ ExpressionParsingScope parsing_scope(impl());
+ ExpressionT lhs = each_variable = ParseLeftHandSideExpression();
int lhs_end_pos = end_position();
- if (lhs->IsArrayLiteral() || lhs->IsObjectLiteral()) {
- ValidateAssignmentPattern(CHECK_OK);
+ if (lhs->IsPattern()) {
+ parsing_scope.ValidatePattern(lhs, lhs_beg_pos, lhs_end_pos);
} else {
- ValidateExpression(CHECK_OK);
- each_variable = CheckAndRewriteReferenceExpression(
- lhs, lhs_beg_pos, lhs_end_pos, MessageTemplate::kInvalidLhsInFor,
- kSyntaxError, CHECK_OK);
+ each_variable = parsing_scope.ValidateAndRewriteReference(
+ lhs, lhs_beg_pos, lhs_end_pos);
}
}
- ExpectContextualKeyword(Token::OF, CHECK_OK);
- int each_keyword_pos = scanner()->location().beg_pos;
+ ExpectContextualKeyword(ast_value_factory()->of_string());
const bool kAllowIn = true;
ExpressionT iterable = impl()->NullExpression();
{
- ExpressionClassifier classifier(this);
- iterable = ParseAssignmentExpression(kAllowIn, CHECK_OK);
- ValidateExpression(CHECK_OK);
+ AcceptINScope scope(this, kAllowIn);
+ iterable = ParseAssignmentExpression();
}
- Expect(Token::RPAREN, CHECK_OK);
+ Expect(Token::RPAREN);
StatementT body = impl()->NullStatement();
{
@@ -6149,16 +5671,16 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement(
scope()->set_start_position(scanner()->location().beg_pos);
SourceRange body_range;
- SourceRangeScope range_scope(scanner(), &body_range);
-
- body = ParseStatement(nullptr, nullptr, CHECK_OK);
- scope()->set_end_position(end_position());
- impl()->RecordIterationStatementSourceRange(loop, range_scope.Finalize());
+ {
+ SourceRangeScope range_scope(scanner(), &body_range);
+ body = ParseStatement(nullptr, nullptr);
+ scope()->set_end_position(end_position());
+ }
+ impl()->RecordIterationStatementSourceRange(loop, body_range);
if (has_declarations) {
- BlockT body_block = impl()->NullStatement();
- impl()->DesugarBindingInForEachStatement(&for_info, &body_block,
- &each_variable, CHECK_OK);
+ BlockT body_block = impl()->NullBlock();
+ DesugarBindingInForEachStatement(&for_info, &body_block, &each_variable);
body_block->statements()->Add(body, zone());
body_block->set_scope(scope()->FinalizeBlockScope());
body = body_block;
@@ -6168,103 +5690,85 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement(
USE(block_scope);
}
}
- const bool finalize = true;
- StatementT final_loop = impl()->InitializeForOfStatement(
- loop, each_variable, iterable, body, finalize, IteratorType::kAsync,
- each_keyword_pos);
+
+ loop->Initialize(each_variable, iterable, body);
if (!has_declarations) {
Scope* for_scope = scope()->FinalizeBlockScope();
DCHECK_NULL(for_scope);
USE(for_scope);
- return final_loop;
+ return loop;
}
- BlockT init_block = impl()->CreateForEachStatementTDZ(impl()->NullStatement(),
- for_info, CHECK_OK);
+ BlockT init_block =
+ impl()->CreateForEachStatementTDZ(impl()->NullBlock(), for_info);
scope()->set_end_position(end_position());
Scope* for_scope = scope()->FinalizeBlockScope();
// Parsed for-in loop w/ variable declarations.
if (!impl()->IsNull(init_block)) {
- init_block->statements()->Add(final_loop, zone());
+ init_block->statements()->Add(loop, zone());
init_block->set_scope(for_scope);
return init_block;
}
DCHECK_NULL(for_scope);
- return final_loop;
-}
-
-template <typename Impl>
-void ParserBase<Impl>::ObjectLiteralChecker::CheckDuplicateProto(
- Token::Value property) {
- if (property == Token::SMI || property == Token::NUMBER) return;
-
- if (IsProto()) {
- if (has_seen_proto_) {
- this->parser()->classifier()->RecordExpressionError(
- this->scanner()->location(), MessageTemplate::kDuplicateProto);
- return;
- }
- has_seen_proto_ = true;
- }
+ return loop;
}
template <typename Impl>
-void ParserBase<Impl>::ClassLiteralChecker::CheckClassMethodName(
- Token::Value property, ParsePropertyKind type, ParseFunctionFlags flags,
- bool is_static, bool* ok) {
+void ParserBase<Impl>::CheckClassMethodName(IdentifierT name,
+ ParsePropertyKind type,
+ ParseFunctionFlags flags,
+ bool is_static,
+ bool* has_seen_constructor) {
DCHECK(type == ParsePropertyKind::kMethod || IsAccessor(type));
- if (property == Token::SMI || property == Token::NUMBER) return;
+ AstValueFactory* avf = ast_value_factory();
if (is_static) {
- if (IsPrototype()) {
- this->parser()->ReportMessage(MessageTemplate::kStaticPrototype);
- *ok = false;
+ if (impl()->IdentifierEquals(name, avf->prototype_string())) {
+ ReportMessage(MessageTemplate::kStaticPrototype);
return;
}
- } else if (IsConstructor()) {
+ } else if (impl()->IdentifierEquals(name,
+ avf->private_constructor_string())) {
+ ReportMessage(MessageTemplate::kConstructorIsPrivate);
+ return;
+ } else if (impl()->IdentifierEquals(name, avf->constructor_string())) {
if (flags != ParseFunctionFlag::kIsNormal || IsAccessor(type)) {
- MessageTemplate::Template msg =
- (flags & ParseFunctionFlag::kIsGenerator) != 0
- ? MessageTemplate::kConstructorIsGenerator
- : (flags & ParseFunctionFlag::kIsAsync) != 0
- ? MessageTemplate::kConstructorIsAsync
- : MessageTemplate::kConstructorIsAccessor;
- this->parser()->ReportMessage(msg);
- *ok = false;
+ MessageTemplate msg = (flags & ParseFunctionFlag::kIsGenerator) != 0
+ ? MessageTemplate::kConstructorIsGenerator
+ : (flags & ParseFunctionFlag::kIsAsync) != 0
+ ? MessageTemplate::kConstructorIsAsync
+ : MessageTemplate::kConstructorIsAccessor;
+ ReportMessage(msg);
return;
}
- if (has_seen_constructor_) {
- this->parser()->ReportMessage(MessageTemplate::kDuplicateConstructor);
- *ok = false;
+ if (*has_seen_constructor) {
+ ReportMessage(MessageTemplate::kDuplicateConstructor);
return;
}
- has_seen_constructor_ = true;
+ *has_seen_constructor = true;
return;
}
}
template <typename Impl>
-void ParserBase<Impl>::ClassLiteralChecker::CheckClassFieldName(bool is_static,
- bool* ok) {
- if (is_static && IsPrototype()) {
- this->parser()->ReportMessage(MessageTemplate::kStaticPrototype);
- *ok = false;
+void ParserBase<Impl>::CheckClassFieldName(IdentifierT name, bool is_static) {
+ AstValueFactory* avf = ast_value_factory();
+ if (is_static && impl()->IdentifierEquals(name, avf->prototype_string())) {
+ ReportMessage(MessageTemplate::kStaticPrototype);
return;
}
- if (IsConstructor() || IsPrivateConstructor()) {
- this->parser()->ReportMessage(MessageTemplate::kConstructorClassField);
- *ok = false;
+ if (impl()->IdentifierEquals(name, avf->constructor_string()) ||
+ impl()->IdentifierEquals(name, avf->private_constructor_string())) {
+ ReportMessage(MessageTemplate::kConstructorClassField);
return;
}
}
-#undef CHECK_OK
-#undef CHECK_OK_CUSTOM
-#undef CHECK_OK_VOID
+#undef RETURN_IF_PARSE_ERROR
} // namespace internal
} // namespace v8