summaryrefslogtreecommitdiff
path: root/deps/v8/src/parsing/parser-base.h
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/parsing/parser-base.h')
-rw-r--r--deps/v8/src/parsing/parser-base.h402
1 files changed, 237 insertions, 165 deletions
diff --git a/deps/v8/src/parsing/parser-base.h b/deps/v8/src/parsing/parser-base.h
index b211b85d2a..c393bc5ec2 100644
--- a/deps/v8/src/parsing/parser-base.h
+++ b/deps/v8/src/parsing/parser-base.h
@@ -14,6 +14,7 @@
#include "src/base/hashmap.h"
#include "src/counters.h"
#include "src/globals.h"
+#include "src/log.h"
#include "src/messages.h"
#include "src/parsing/expression-classifier.h"
#include "src/parsing/func-name-inferrer.h"
@@ -236,6 +237,7 @@ class ParserBase {
typedef typename Types::ObjectLiteralProperty ObjectLiteralPropertyT;
typedef typename Types::ClassLiteralProperty ClassLiteralPropertyT;
typedef typename Types::Suspend SuspendExpressionT;
+ typedef typename Types::RewritableExpression RewritableExpressionT;
typedef typename Types::ExpressionList ExpressionListT;
typedef typename Types::FormalParameters FormalParametersT;
typedef typename Types::Statement StatementT;
@@ -251,8 +253,9 @@ class ParserBase {
ParserBase(Zone* zone, Scanner* scanner, uintptr_t stack_limit,
v8::Extension* extension, AstValueFactory* ast_value_factory,
- RuntimeCallStats* runtime_call_stats,
- bool parsing_on_main_thread = true)
+ PendingCompilationErrorHandler* pending_error_handler,
+ RuntimeCallStats* runtime_call_stats, Logger* logger,
+ int script_id, bool parsing_module, bool parsing_on_main_thread)
: scope_(nullptr),
original_scope_(nullptr),
function_state_(nullptr),
@@ -261,25 +264,24 @@ class ParserBase {
ast_value_factory_(ast_value_factory),
ast_node_factory_(ast_value_factory, zone),
runtime_call_stats_(runtime_call_stats),
+ logger_(logger),
parsing_on_main_thread_(parsing_on_main_thread),
- parsing_module_(false),
+ parsing_module_(parsing_module),
stack_limit_(stack_limit),
+ pending_error_handler_(pending_error_handler),
zone_(zone),
classifier_(nullptr),
scanner_(scanner),
- stack_overflow_(false),
default_eager_compile_hint_(FunctionLiteral::kShouldLazyCompile),
function_literal_id_(0),
+ script_id_(script_id),
allow_natives_(false),
allow_harmony_do_expressions_(false),
allow_harmony_function_sent_(false),
- allow_harmony_restrictive_generators_(false),
- allow_harmony_class_fields_(false),
- allow_harmony_object_rest_spread_(false),
+ allow_harmony_public_fields_(false),
allow_harmony_dynamic_import_(false),
allow_harmony_import_meta_(false),
- allow_harmony_async_iteration_(false),
- allow_harmony_template_escapes_(false) {}
+ allow_harmony_async_iteration_(false) {}
#define ALLOW_ACCESSORS(name) \
bool allow_##name() const { return allow_##name##_; } \
@@ -288,16 +290,20 @@ class ParserBase {
ALLOW_ACCESSORS(natives);
ALLOW_ACCESSORS(harmony_do_expressions);
ALLOW_ACCESSORS(harmony_function_sent);
- ALLOW_ACCESSORS(harmony_restrictive_generators);
- ALLOW_ACCESSORS(harmony_class_fields);
- ALLOW_ACCESSORS(harmony_object_rest_spread);
+ ALLOW_ACCESSORS(harmony_public_fields);
ALLOW_ACCESSORS(harmony_dynamic_import);
ALLOW_ACCESSORS(harmony_import_meta);
ALLOW_ACCESSORS(harmony_async_iteration);
- ALLOW_ACCESSORS(harmony_template_escapes);
#undef ALLOW_ACCESSORS
+ bool allow_harmony_bigint() const {
+ return scanner()->allow_harmony_bigint();
+ }
+ void set_allow_harmony_bigint(bool allow) {
+ scanner()->set_allow_harmony_bigint(allow);
+ }
+
uintptr_t stack_limit() const { return stack_limit_; }
void set_stack_limit(uintptr_t stack_limit) { stack_limit_ = stack_limit; }
@@ -366,15 +372,6 @@ class ParserBase {
Scope* const outer_scope_;
};
- struct DestructuringAssignment {
- public:
- DestructuringAssignment(ExpressionT expression, Scope* scope)
- : assignment(expression), scope(scope) {}
-
- ExpressionT assignment;
- Scope* scope;
- };
-
class FunctionState final : public BlockState {
public:
FunctionState(FunctionState** function_state_stack, Scope** scope_stack,
@@ -396,12 +393,12 @@ class ParserBase {
void SetDestructuringAssignmentsScope(int pos, Scope* scope) {
for (int i = pos; i < destructuring_assignments_to_rewrite_.length();
++i) {
- destructuring_assignments_to_rewrite_[i].scope = scope;
+ destructuring_assignments_to_rewrite_[i]->set_scope(scope);
}
}
- const ZoneList<DestructuringAssignment>&
- destructuring_assignments_to_rewrite() const {
+ const ZoneList<RewritableExpressionT>&
+ destructuring_assignments_to_rewrite() const {
return destructuring_assignments_to_rewrite_;
}
@@ -409,7 +406,7 @@ class ParserBase {
return &reported_errors_;
}
- ZoneList<ExpressionT>* non_patterns_to_rewrite() {
+ ZoneList<RewritableExpressionT>* non_patterns_to_rewrite() {
return &non_patterns_to_rewrite_;
}
@@ -450,15 +447,16 @@ class ParserBase {
};
private:
- void AddDestructuringAssignment(DestructuringAssignment pair) {
- destructuring_assignments_to_rewrite_.Add(pair, scope_->zone());
+ void AddDestructuringAssignment(RewritableExpressionT expr) {
+ destructuring_assignments_to_rewrite_.Add(expr, scope_->zone());
}
- void AddNonPatternForRewriting(ExpressionT expr, bool* ok) {
+ void AddNonPatternForRewriting(RewritableExpressionT expr, bool* ok) {
non_patterns_to_rewrite_.Add(expr, scope_->zone());
if (non_patterns_to_rewrite_.length() >=
- std::numeric_limits<uint16_t>::max())
+ std::numeric_limits<uint16_t>::max()) {
*ok = false;
+ }
}
// Properties count estimation.
@@ -468,8 +466,8 @@ class ParserBase {
FunctionState* outer_function_state_;
DeclarationScope* scope_;
- ZoneList<DestructuringAssignment> destructuring_assignments_to_rewrite_;
- ZoneList<ExpressionT> non_patterns_to_rewrite_;
+ ZoneList<RewritableExpressionT> destructuring_assignments_to_rewrite_;
+ ZoneList<RewritableExpressionT> non_patterns_to_rewrite_;
ZoneList<typename ExpressionClassifier::Error> reported_errors_;
@@ -556,21 +554,43 @@ class ParserBase {
: variable(nullptr),
extends(parser->impl()->NullExpression()),
properties(parser->impl()->NewClassPropertyList(4)),
+ static_fields(parser->impl()->NewClassPropertyList(4)),
+ instance_fields(parser->impl()->NewClassPropertyList(4)),
constructor(parser->impl()->NullExpression()),
has_seen_constructor(false),
has_name_static_property(false),
has_static_computed_names(false),
- is_anonymous(false) {}
+ has_static_class_fields(false),
+ has_instance_class_fields(false),
+ is_anonymous(false),
+ static_fields_scope(nullptr),
+ instance_fields_scope(nullptr),
+ computed_field_count(0) {}
Variable* variable;
ExpressionT extends;
typename Types::ClassPropertyList properties;
+ typename Types::ClassPropertyList static_fields;
+ typename Types::ClassPropertyList instance_fields;
FunctionLiteralT constructor;
+
+ // TODO(gsathya): Use a bitfield store all the booleans.
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 is_anonymous;
+ DeclarationScope* static_fields_scope;
+ DeclarationScope* instance_fields_scope;
+ int computed_field_count;
};
+ const AstRawString* ClassFieldVariableName(AstValueFactory* ast_value_factory,
+ int index) {
+ std::string name = ".class-field-" + std::to_string(index);
+ return ast_value_factory->GetOneByteString(name.c_str());
+ }
+
DeclarationScope* NewScriptScope() const {
return new (zone()) DeclarationScope(zone(), ast_value_factory());
}
@@ -635,11 +655,15 @@ class ParserBase {
AstValueFactory* ast_value_factory() const { return ast_value_factory_; }
int position() const { return scanner_->location().beg_pos; }
int peek_position() const { return scanner_->peek_location().beg_pos; }
- bool stack_overflow() const { return stack_overflow_; }
- void set_stack_overflow() { stack_overflow_ = true; }
+ bool stack_overflow() const {
+ return pending_error_handler()->stack_overflow();
+ }
+ void set_stack_overflow() { pending_error_handler()->set_stack_overflow(); }
+ int script_id() { return script_id_; }
+ void set_script_id(int id) { script_id_ = id; }
INLINE(Token::Value peek()) {
- if (stack_overflow_) return Token::ILLEGAL;
+ if (stack_overflow()) return Token::ILLEGAL;
return scanner()->peek();
}
@@ -651,18 +675,18 @@ class ParserBase {
}
INLINE(Token::Value PeekAhead()) {
- if (stack_overflow_) return Token::ILLEGAL;
+ if (stack_overflow()) return Token::ILLEGAL;
return scanner()->PeekAhead();
}
INLINE(Token::Value Next()) {
- if (stack_overflow_) return Token::ILLEGAL;
+ 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.
- stack_overflow_ = true;
+ set_stack_overflow();
}
}
return scanner()->Next();
@@ -874,6 +898,13 @@ class ParserBase {
return IsResumableFunction(function_state_->kind());
}
+ const PendingCompilationErrorHandler* pending_error_handler() const {
+ return pending_error_handler_;
+ }
+ PendingCompilationErrorHandler* pending_error_handler() {
+ return pending_error_handler_;
+ }
+
// Report syntax errors.
void ReportMessage(MessageTemplate::Template message) {
Scanner::Location source_location = scanner()->location();
@@ -1049,8 +1080,8 @@ class ParserBase {
// This method wraps the parsing of the expression inside a new expression
// classifier and calls RewriteNonPattern if parsing is successful.
- // It should be used whenever we're parsing an expression that will be
- // used as a non-pattern (i.e., in most cases).
+ // It should be used whenever we're parsing an expression that is known
+ // to not be a pattern or part of a pattern.
V8_INLINE ExpressionT ParseExpression(bool accept_IN, bool* ok);
// This method does not wrap the parsing of the expression inside a
@@ -1081,11 +1112,12 @@ class ParserBase {
bool* ok);
ExpressionT ParseObjectLiteral(bool* ok);
ClassLiteralPropertyT ParseClassPropertyDefinition(
- ClassLiteralChecker* checker, bool has_extends, bool* is_computed_name,
- bool* has_seen_constructor, ClassLiteralProperty::Kind* property_kind,
- bool* is_static, bool* has_name_static_property, bool* ok);
- FunctionLiteralT ParseClassFieldForInitializer(bool has_initializer,
- bool* ok);
+ ClassLiteralChecker* checker, ClassInfo* class_info, bool has_extends,
+ bool* is_computed_name, bool* has_seen_constructor,
+ ClassLiteralProperty::Kind* property_kind, bool* is_static,
+ bool* has_name_static_property, bool* ok);
+ ExpressionT ParseClassFieldInitializer(ClassInfo* class_info, bool is_static,
+ bool* ok);
ObjectLiteralPropertyT ParseObjectPropertyDefinition(
ObjectLiteralChecker* checker, bool* is_computed_name,
bool* is_rest_property, bool* ok);
@@ -1357,7 +1389,7 @@ class ParserBase {
inline StatementT BuildReturnStatement(ExpressionT expr, int pos,
int end_pos = kNoSourcePosition) {
if (impl()->IsNull(expr)) {
- expr = impl()->GetLiteralUndefined(kNoSourcePosition);
+ expr = factory()->NewUndefinedLiteral(kNoSourcePosition);
} else if (is_async_generator()) {
// In async generators, if there is an explicit operand to the return
// statement, await the operand.
@@ -1399,6 +1431,7 @@ class ParserBase {
void CheckClassMethodName(Token::Value property, PropertyKind type,
bool is_generator, bool is_async, bool is_static,
bool* ok);
+ void CheckClassFieldName(bool is_static, bool* ok);
private:
bool IsConstructor() {
@@ -1478,9 +1511,11 @@ class ParserBase {
AstValueFactory* ast_value_factory_; // Not owned.
typename Types::Factory ast_node_factory_;
RuntimeCallStats* runtime_call_stats_;
+ internal::Logger* logger_;
bool parsing_on_main_thread_;
- bool parsing_module_;
+ const bool parsing_module_;
uintptr_t stack_limit_;
+ PendingCompilationErrorHandler* pending_error_handler_;
// Parser base's private field members.
@@ -1489,22 +1524,19 @@ class ParserBase {
ExpressionClassifier* classifier_;
Scanner* scanner_;
- bool stack_overflow_;
FunctionLiteral::EagerCompileHint default_eager_compile_hint_;
int function_literal_id_;
+ int script_id_;
bool allow_natives_;
bool allow_harmony_do_expressions_;
bool allow_harmony_function_sent_;
- bool allow_harmony_restrictive_generators_;
- bool allow_harmony_class_fields_;
- bool allow_harmony_object_rest_spread_;
+ bool allow_harmony_public_fields_;
bool allow_harmony_dynamic_import_;
bool allow_harmony_import_meta_;
bool allow_harmony_async_iteration_;
- bool allow_harmony_template_escapes_;
friend class DiscardableZoneScope;
};
@@ -1549,6 +1581,7 @@ void ParserBase<Impl>::GetUnexpectedTokenMessage(
break;
case Token::SMI:
case Token::NUMBER:
+ case Token::BIGINT:
*message = MessageTemplate::kUnexpectedTokenNumber;
break;
case Token::STRING:
@@ -1590,7 +1623,7 @@ void ParserBase<Impl>::GetUnexpectedTokenMessage(
break;
default:
const char* name = Token::String(token);
- DCHECK(name != NULL);
+ DCHECK_NOT_NULL(name);
*arg = name;
break;
}
@@ -1780,6 +1813,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePrimaryExpression(
case Token::FALSE_LITERAL:
case Token::SMI:
case Token::NUMBER:
+ case Token::BIGINT:
BindingPatternUnexpectedToken();
return impl()->ExpressionFromLiteral(Next(), beg_pos);
@@ -1881,7 +1915,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePrimaryExpression(
return ParseTemplateLiteral(impl()->NullExpression(), beg_pos, false, ok);
case Token::MOD:
- if (allow_natives() || extension_ != NULL) {
+ if (allow_natives() || extension_ != nullptr) {
BindingPatternUnexpectedToken();
return ParseV8Intrinsic(ok);
}
@@ -1951,6 +1985,10 @@ ParserBase<Impl>::ParseExpressionCoverGrammar(bool accept_IN, bool* ok) {
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);
@@ -1992,7 +2030,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseArrayLiteral(
while (peek() != Token::RBRACK) {
ExpressionT elem;
if (peek() == Token::COMMA) {
- elem = impl()->GetLiteralTheHole(peek_position());
+ elem = factory()->NewTheHoleLiteral();
} else if (peek() == Token::ELLIPSIS) {
int start_pos = peek_position();
Consume(Token::ELLIPSIS);
@@ -2033,8 +2071,8 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseArrayLiteral(
ExpressionT result =
factory()->NewArrayLiteral(values, first_spread_index, pos);
if (first_spread_index >= 0) {
- result = factory()->NewRewritableExpression(result);
- impl()->QueueNonPatternForRewriting(result, ok);
+ auto rewritable = factory()->NewRewritableExpression(result, scope());
+ impl()->QueueNonPatternForRewriting(rewritable, ok);
if (!*ok) {
// If the non-pattern rewriting mechanism is used in the future for
// rewriting other things than spreads, this error message will have
@@ -2043,6 +2081,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseArrayLiteral(
ReportMessage(MessageTemplate::kTooManySpreads);
return impl()->NullExpression();
}
+ result = rewritable;
}
return result;
}
@@ -2079,7 +2118,7 @@ template <class Impl>
typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePropertyName(
IdentifierT* name, PropertyKind* kind, bool* is_generator, bool* is_get,
bool* is_set, bool* is_async, bool* is_computed_name, bool* ok) {
- DCHECK(*kind == PropertyKind::kNotSet);
+ DCHECK_EQ(*kind, PropertyKind::kNotSet);
DCHECK(!*is_generator);
DCHECK(!*is_get);
DCHECK(!*is_set);
@@ -2166,8 +2205,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePropertyName(
}
case Token::ELLIPSIS:
- if (allow_harmony_object_rest_spread() && !*is_generator && !*is_async &&
- !*is_get && !*is_set) {
+ if (!*is_generator && !*is_async && !*is_get && !*is_set) {
*name = impl()->NullIdentifier();
Consume(Token::ELLIPSIS);
expression = ParseAssignmentExpression(true, CHECK_OK);
@@ -2217,9 +2255,10 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePropertyName(
template <typename Impl>
typename ParserBase<Impl>::ClassLiteralPropertyT
ParserBase<Impl>::ParseClassPropertyDefinition(
- ClassLiteralChecker* checker, bool has_extends, bool* is_computed_name,
- bool* has_seen_constructor, ClassLiteralProperty::Kind* property_kind,
- bool* is_static, bool* has_name_static_property, bool* ok) {
+ ClassLiteralChecker* checker, ClassInfo* class_info, bool has_extends,
+ bool* is_computed_name, bool* has_seen_constructor,
+ ClassLiteralProperty::Kind* property_kind, bool* is_static,
+ bool* has_name_static_property, bool* ok) {
DCHECK_NOT_NULL(has_seen_constructor);
DCHECK_NOT_NULL(has_name_static_property);
bool is_get = false;
@@ -2273,14 +2312,17 @@ ParserBase<Impl>::ParseClassPropertyDefinition(
// as an uninitialized field.
case PropertyKind::kShorthandProperty:
case PropertyKind::kValueProperty:
- if (allow_harmony_class_fields()) {
- bool has_initializer = Check(Token::ASSIGN);
- ExpressionT function_literal = ParseClassFieldForInitializer(
- has_initializer, CHECK_OK_CUSTOM(NullLiteralProperty));
- ExpectSemicolon(CHECK_OK_CUSTOM(NullLiteralProperty));
+ if (allow_harmony_public_fields()) {
*property_kind = ClassLiteralProperty::FIELD;
+ if (!*is_computed_name) {
+ checker->CheckClassFieldName(*is_static,
+ CHECK_OK_CUSTOM(NullLiteralProperty));
+ }
+ ExpressionT initializer = ParseClassFieldInitializer(
+ class_info, *is_static, CHECK_OK_CUSTOM(NullLiteralProperty));
+ ExpectSemicolon(CHECK_OK_CUSTOM(NullLiteralProperty));
ClassLiteralPropertyT result = factory()->NewClassLiteralProperty(
- name_expression, function_literal, *property_kind, *is_static,
+ name_expression, initializer, *property_kind, *is_static,
*is_computed_name);
impl()->SetFunctionNameFromPropertyName(result, name);
return result;
@@ -2377,36 +2419,43 @@ ParserBase<Impl>::ParseClassPropertyDefinition(
}
template <typename Impl>
-typename ParserBase<Impl>::FunctionLiteralT
-ParserBase<Impl>::ParseClassFieldForInitializer(bool has_initializer,
- bool* ok) {
- // Makes a concise method which evaluates and returns the initialized value
- // (or undefined if absent).
- FunctionKind kind = FunctionKind::kConciseMethod;
- DeclarationScope* initializer_scope = NewFunctionScope(kind);
- initializer_scope->set_start_position(scanner()->location().end_pos);
- FunctionState initializer_state(&function_state_, &scope_, initializer_scope);
- DCHECK_EQ(initializer_scope, scope());
- scope()->SetLanguageMode(STRICT);
- ExpressionClassifier expression_classifier(this);
- ExpressionT value;
- if (has_initializer) {
- value =
- this->ParseAssignmentExpression(true, CHECK_OK_CUSTOM(NullExpression));
+typename ParserBase<Impl>::ExpressionT
+ParserBase<Impl>::ParseClassFieldInitializer(ClassInfo* class_info,
+ bool is_static, bool* ok) {
+ DeclarationScope* initializer_scope = is_static
+ ? class_info->static_fields_scope
+ : class_info->instance_fields_scope;
+
+ if (initializer_scope == nullptr) {
+ initializer_scope = NewFunctionScope(FunctionKind::kConciseMethod);
+ // TODO(gsathya): Make scopes be non contiguous.
+ initializer_scope->set_start_position(scanner()->location().end_pos);
+ initializer_scope->SetLanguageMode(LanguageMode::kStrict);
+ }
+
+ ExpressionT initializer;
+ if (Check(Token::ASSIGN)) {
+ FunctionState initializer_state(&function_state_, &scope_,
+ initializer_scope);
+ ExpressionClassifier expression_classifier(this);
+
+ initializer =
+ ParseAssignmentExpression(true, CHECK_OK_CUSTOM(NullExpression));
impl()->RewriteNonPattern(CHECK_OK_CUSTOM(NullExpression));
} else {
- value = factory()->NewUndefinedLiteral(kNoSourcePosition);
+ initializer = factory()->NewUndefinedLiteral(kNoSourcePosition);
}
+
initializer_scope->set_end_position(scanner()->location().end_pos);
- typename Types::StatementList body = impl()->NewStatementList(1);
- body->Add(factory()->NewReturnStatement(value, kNoSourcePosition), zone());
- FunctionLiteralT function_literal = factory()->NewFunctionLiteral(
- impl()->EmptyIdentifierString(), initializer_scope, body,
- initializer_state.expected_property_count(), 0, 0,
- FunctionLiteral::kNoDuplicateParameters,
- FunctionLiteral::kAnonymousExpression, default_eager_compile_hint_,
- initializer_scope->start_position(), true, GetNextFunctionLiteralId());
- return function_literal;
+ if (is_static) {
+ 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;
+ }
+
+ return initializer;
}
template <typename Impl>
@@ -2432,7 +2481,6 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ObjectLiteralChecker* checker,
switch (kind) {
case PropertyKind::kSpreadProperty:
- DCHECK(allow_harmony_object_rest_spread());
DCHECK(!is_get && !is_set && !is_generator && !is_async &&
!*is_computed_name);
DCHECK(name_token == Token::ELLIPSIS);
@@ -2441,7 +2489,7 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ObjectLiteralChecker* checker,
*is_rest_property = true;
return factory()->NewObjectLiteralProperty(
- impl()->GetLiteralTheHole(kNoSourcePosition), name_expression,
+ factory()->NewTheHoleLiteral(), name_expression,
ObjectLiteralProperty::SPREAD, true);
case PropertyKind::kValueProperty: {
@@ -2910,7 +2958,7 @@ ParserBase<Impl>::ParseAssignmentExpression(bool accept_IN, bool* ok) {
impl()->CheckAssigningFunctionLiteralToProperty(expression, right);
- if (fni_ != NULL) {
+ if (fni_ != nullptr) {
// Check if the right hand side is a call to avoid inferring a
// name if we're dealing with "a = function(){...}();"-like
// expression.
@@ -2925,17 +2973,14 @@ ParserBase<Impl>::ParseAssignmentExpression(bool accept_IN, bool* ok) {
impl()->SetFunctionNameFromIdentifierRef(right, expression);
}
- if (op == Token::ASSIGN_EXP) {
- DCHECK(!is_destructuring_assignment);
- return impl()->RewriteAssignExponentiation(expression, right, pos);
- }
-
DCHECK_NE(op, Token::INIT);
ExpressionT result = factory()->NewAssignment(op, expression, right, pos);
if (is_destructuring_assignment) {
- result = factory()->NewRewritableExpression(result);
- impl()->QueueDestructuringAssignmentForRewriting(result);
+ DCHECK_NE(op, Token::ASSIGN_EXP);
+ auto rewritable = factory()->NewRewritableExpression(result, scope());
+ impl()->QueueDestructuringAssignmentForRewriting(rewritable);
+ result = rewritable;
}
return result;
@@ -3010,11 +3055,11 @@ ParserBase<Impl>::ParseConditionalExpression(bool accept_IN,
impl()->RewriteNonPattern(CHECK_OK);
BindingPatternUnexpectedToken();
ArrowFormalParametersUnexpectedToken();
- Consume(Token::CONDITIONAL);
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,
@@ -3023,10 +3068,10 @@ ParserBase<Impl>::ParseConditionalExpression(bool accept_IN,
AccumulateNonBindingPatternErrors();
}
impl()->RewriteNonPattern(CHECK_OK);
- Expect(Token::COLON, 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();
@@ -3042,7 +3087,8 @@ ParserBase<Impl>::ParseConditionalExpression(bool accept_IN,
template <typename Impl>
typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseBinaryExpression(
int prec, bool accept_IN, bool* ok) {
- DCHECK(prec >= 4);
+ DCHECK_GE(prec, 4);
+ SourceRange right_range;
ExpressionT x = ParseUnaryExpression(CHECK_OK);
for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
// prec1 >= 4
@@ -3050,12 +3096,15 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseBinaryExpression(
impl()->RewriteNonPattern(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();
impl()->RewriteNonPattern(CHECK_OK);
if (impl()->ShortcutNumericLiteralBinaryExpression(&x, y, op, pos)) {
@@ -3078,11 +3127,14 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseBinaryExpression(
// The comparison was negated - add a NOT.
x = factory()->NewUnaryOperation(Token::NOT, x, pos);
}
- } else if (op == Token::EXP) {
- x = impl()->RewriteExponentiation(x, y, pos);
+ } else if (impl()->CollapseNaryExpression(&x, y, op, pos, right_range)) {
+ continue;
} else {
// We have a "normal" binary operation.
x = factory()->NewBinaryOperation(op, x, y, pos);
+ if (op == Token::OR || op == Token::AND) {
+ impl()->RecordBinaryOperationSourceRange(x, right_range);
+ }
}
}
}
@@ -3316,7 +3368,7 @@ ParserBase<Impl>::ParseLeftHandSideExpression(bool* ok) {
factory()->NewAssignment(Token::INIT, this_expr, result, pos);
}
- if (fni_ != NULL) fni_->RemoveLastFunction();
+ if (fni_ != nullptr) fni_->RemoveLastFunction();
break;
}
@@ -3518,9 +3570,15 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseImportExpressions(
return impl()->NullExpression();
}
- return impl()->ExpressionFromLiteral(Token::NULL_LITERAL, pos);
+ return impl()->ImportMetaExpression(pos);
}
Expect(Token::LPAREN, CHECK_OK);
+ if (peek() == Token::RPAREN) {
+ impl()->ReportMessageAt(scanner()->location(),
+ MessageTemplate::kImportMissingSpecifier);
+ *ok = false;
+ return impl()->NullExpression();
+ }
ExpressionT arg = ParseAssignmentExpression(true, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
return factory()->NewImportCallExpression(arg, pos);
@@ -3666,6 +3724,7 @@ void ParserBase<Impl>::ParseFormalParameter(FormalParametersT* parameters,
// BindingElement[?Yield, ?GeneratorParameter]
bool is_rest = parameters->has_rest;
+ FuncNameInferrer::State fni_state(fni_);
ExpressionT pattern = ParsePrimaryExpression(CHECK_OK_CUSTOM(Void));
ValidateBindingPattern(CHECK_OK_CUSTOM(Void));
@@ -3775,12 +3834,12 @@ typename ParserBase<Impl>::BlockT ParserBase<Impl>::ParseVariableDeclarations(
break;
case Token::CONST:
Consume(Token::CONST);
- DCHECK(var_context != kStatement);
+ DCHECK_NE(var_context, kStatement);
parsing_result->descriptor.mode = CONST;
break;
case Token::LET:
Consume(Token::LET);
- DCHECK(var_context != kStatement);
+ DCHECK_NE(var_context, kStatement);
parsing_result->descriptor.mode = LET;
break;
default:
@@ -3857,7 +3916,7 @@ typename ParserBase<Impl>::BlockT ParserBase<Impl>::ParseVariableDeclarations(
}
// 'let x' initializes 'x' to undefined.
if (parsing_result->descriptor.mode == LET) {
- value = impl()->GetLiteralUndefined(position());
+ value = factory()->NewUndefinedLiteral(position());
}
}
@@ -3979,9 +4038,9 @@ ParserBase<Impl>::ParseHoistableDeclaration(
// sloppy_block_function_map. Don't add them to the map for async functions.
// Generators are also supposed to be prohibited; currently doing this behind
// a flag and UseCounting violations to assess web compatibility.
- bool is_sloppy_block_function =
- is_sloppy(language_mode()) && !scope()->is_declaration_scope() &&
- !is_async && !(allow_harmony_restrictive_generators() && is_generator);
+ bool is_sloppy_block_function = is_sloppy(language_mode()) &&
+ !scope()->is_declaration_scope() &&
+ !is_async && !is_generator;
return impl()->DeclareFunction(variable_name, function, mode, pos,
is_sloppy_block_function, names, ok);
@@ -4078,18 +4137,6 @@ void ParserBase<Impl>::ParseFunctionBody(
typename ParserBase<Impl>::StatementListT result, IdentifierT function_name,
int pos, const FormalParametersT& parameters, FunctionKind kind,
FunctionLiteral::FunctionType function_type, bool* ok) {
- static const int kFunctionNameAssignmentIndex = 0;
- if (function_type == FunctionLiteral::kNamedExpression) {
- DCHECK(!impl()->IsNull(function_name));
- // If we have a named function expression, we add a local variable
- // declaration to the body of the function with the name of the
- // function and let it refer to the function itself (closure).
- // Not having parsed the function body, the language mode may still change,
- // so we reserve a spot and create the actual const assignment later.
- DCHECK_EQ(kFunctionNameAssignmentIndex, result->length());
- result->Add(impl()->NullStatement(), zone());
- }
-
DeclarationScope* function_scope = scope()->AsDeclarationScope();
DeclarationScope* inner_scope = function_scope;
BlockT inner_block = impl()->NullStatement();
@@ -4170,9 +4217,7 @@ void ParserBase<Impl>::ParseFunctionBody(
function_scope->DeclareArguments(ast_value_factory());
}
- impl()->CreateFunctionNameAssignment(function_name, pos, function_type,
- function_scope, result,
- kFunctionNameAssignmentIndex);
+ impl()->DeclareFunctionNameVar(function_name, function_type, function_scope);
}
template <typename Impl>
@@ -4233,9 +4278,10 @@ template <typename Impl>
bool ParserBase<Impl>::IsTrivialExpression() {
Token::Value peek_token = peek();
if (peek_token == Token::SMI || peek_token == Token::NUMBER ||
- peek_token == Token::NULL_LITERAL || peek_token == Token::TRUE_LITERAL ||
- peek_token == Token::FALSE_LITERAL || peek_token == Token::STRING ||
- peek_token == Token::IDENTIFIER || peek_token == Token::THIS) {
+ peek_token == Token::BIGINT || peek_token == Token::NULL_LITERAL ||
+ peek_token == Token::TRUE_LITERAL || peek_token == Token::FALSE_LITERAL ||
+ peek_token == Token::STRING || peek_token == Token::IDENTIFIER ||
+ peek_token == Token::THIS) {
// PeekAhead() is expensive & may not always be called, so we only call it
// after checking peek().
Token::Value peek_ahead = PeekAhead();
@@ -4260,6 +4306,8 @@ ParserBase<Impl>::ParseArrowFunctionLiteral(
RuntimeCallTimerScope runtime_timer(
runtime_call_stats_,
counters[Impl::IsPreParser()][parsing_on_main_thread_]);
+ base::ElapsedTimer timer;
+ if (V8_UNLIKELY(FLAG_log_function_events)) timer.Start();
if (peek() == Token::ARROW && scanner_->HasAnyLineTerminatorBeforeNext()) {
// ASI inserts `;` after arrow parameters if a line terminator is found.
@@ -4302,7 +4350,7 @@ ParserBase<Impl>::ParseArrowFunctionLiteral(
// For arrow functions, we don't need to retrieve data about function
// parameters.
int dummy_num_parameters = -1;
- DCHECK((kind & FunctionKind::kArrowFunction) != 0);
+ DCHECK_NE(kind & FunctionKind::kArrowFunction, 0);
LazyParsingResult result = impl()->SkipFunction(
nullptr, kind, FunctionLiteral::kAnonymousExpression,
formal_parameters.scope, &dummy_num_parameters,
@@ -4313,6 +4361,13 @@ ParserBase<Impl>::ParseArrowFunctionLiteral(
formal_parameters.scope->ResetAfterPreparsing(ast_value_factory_,
false);
+ // Discard any queued destructuring assignments which appeared
+ // in this function's parameter list.
+ FunctionState* parent_state = function_state.outer();
+ DCHECK_NOT_NULL(parent_state);
+ DCHECK_GE(parent_state->destructuring_assignments_to_rewrite().length(),
+ rewritable_length);
+ parent_state->RewindDestructuringAssignments(rewritable_length);
} else {
Consume(Token::LBRACE);
body = impl()->NewStatementList(8);
@@ -4349,23 +4404,9 @@ ParserBase<Impl>::ParseArrowFunctionLiteral(
}
impl()->CheckConflictingVarDeclarations(formal_parameters.scope, CHECK_OK);
- if (is_lazy_top_level_function) {
- FunctionState* parent_state = function_state.outer();
- DCHECK_NOT_NULL(parent_state);
- DCHECK_GE(parent_state->destructuring_assignments_to_rewrite().length(),
- rewritable_length);
- parent_state->RewindDestructuringAssignments(rewritable_length);
- }
-
impl()->RewriteDestructuringAssignments();
}
- if (FLAG_trace_preparse) {
- Scope* scope = formal_parameters.scope;
- PrintF(" [%s]: %i-%i (arrow function)\n",
- is_lazy_top_level_function ? "Preparse no-resolution" : "Full parse",
- scope->start_position(), scope->end_position());
- }
FunctionLiteralT function_literal = factory()->NewFunctionLiteral(
impl()->EmptyIdentifierString(), formal_parameters.scope, body,
expected_property_count, formal_parameters.num_parameters(),
@@ -4380,6 +4421,17 @@ ParserBase<Impl>::ParseArrowFunctionLiteral(
impl()->AddFunctionForNameInference(function_literal);
+ if (V8_UNLIKELY((FLAG_log_function_events))) {
+ Scope* scope = formal_parameters.scope;
+ double ms = timer.Elapsed().InMillisecondsF();
+ const char* event_name =
+ is_lazy_top_level_function ? "preparse-no-resolution" : "parse";
+ const char* name = "arrow function";
+ logger_->FunctionEvent(event_name, nullptr, script_id(), ms,
+ scope->start_position(), scope->end_position(), name,
+ strlen(name));
+ }
+
return function_literal;
}
@@ -4407,7 +4459,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseClassLiteral(
Scope* block_scope = NewScope(BLOCK_SCOPE);
BlockState block_state(&scope_, block_scope);
- RaiseLanguageMode(STRICT);
+ RaiseLanguageMode(LanguageMode::kStrict);
ClassInfo class_info(this);
class_info.is_anonymous = is_anonymous;
@@ -4438,19 +4490,23 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseClassLiteral(
// property.
bool is_constructor = !class_info.has_seen_constructor;
ClassLiteralPropertyT property = ParseClassPropertyDefinition(
- &checker, has_extends, &is_computed_name,
+ &checker, &class_info, has_extends, &is_computed_name,
&class_info.has_seen_constructor, &property_kind, &is_static,
&class_info.has_name_static_property, CHECK_OK);
if (!class_info.has_static_computed_names && is_static &&
is_computed_name) {
class_info.has_static_computed_names = true;
}
+ if (is_computed_name && property_kind == ClassLiteralProperty::FIELD) {
+ class_info.computed_field_count++;
+ }
is_constructor &= class_info.has_seen_constructor;
impl()->RewriteNonPattern(CHECK_OK);
AccumulateFormalParameterContainmentErrors();
impl()->DeclareClassProperty(name, property, property_kind, is_static,
- is_constructor, &class_info, CHECK_OK);
+ is_constructor, is_computed_name, &class_info,
+ CHECK_OK);
impl()->InferFunctionName();
}
@@ -4550,9 +4606,9 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseTemplateLiteral(
//
// When parsing a TemplateLiteral, we must have scanned either an initial
// TEMPLATE_SPAN, or a TEMPLATE_TAIL.
- CHECK(peek() == Token::TEMPLATE_SPAN || peek() == Token::TEMPLATE_TAIL);
+ DCHECK(peek() == Token::TEMPLATE_SPAN || peek() == Token::TEMPLATE_TAIL);
- bool forbid_illegal_escapes = !allow_harmony_template_escapes() || !tagged;
+ bool forbid_illegal_escapes = !tagged;
// If we reach a TEMPLATE_TAIL first, we are parsing a NoSubstitutionTemplate.
// In this case we may simply consume the token and build a template with a
@@ -4656,7 +4712,7 @@ ParserBase<Impl>::CheckAndRewriteReferenceExpression(
if (expression->IsValidReferenceExpression()) {
return expression;
}
- if (expression->IsCall()) {
+ if (expression->IsCall() && !expression->AsCall()->is_tagged_template()) {
// 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]'.
@@ -4763,7 +4819,7 @@ ParserBase<Impl>::ParseStatementList(StatementListT body, int end_token,
if (impl()->IsUseStrictDirective(stat) &&
token_loc.end_pos - token_loc.beg_pos == sizeof("use strict") + 1) {
// Directive "use strict" (ES5 14.1).
- RaiseLanguageMode(STRICT);
+ 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
@@ -4783,14 +4839,14 @@ ParserBase<Impl>::ParseStatementList(StatementListT body, int end_token,
// Possibly an unknown directive.
// Should not change mode, but will increment usage counters
// as appropriate. Ditto usages below.
- RaiseLanguageMode(SLOPPY);
+ RaiseLanguageMode(LanguageMode::kSloppy);
} else {
// End of the directive prologue.
directive_prologue = false;
- RaiseLanguageMode(SLOPPY);
+ RaiseLanguageMode(LanguageMode::kSloppy);
}
} else {
- RaiseLanguageMode(SLOPPY);
+ RaiseLanguageMode(LanguageMode::kSloppy);
}
// If we're allowed to abort, we will do so when we see a "long and
@@ -5121,7 +5177,7 @@ ParserBase<Impl>::ParseExpressionOrLabelledStatement(
ExpectSemicolon(CHECK_OK);
if (labels != nullptr) {
// TODO(adamk): Also measure in the PreParser by passing something
- // non-NULL as |labels|.
+ // non-null as |labels|.
impl()->CountUsage(v8::Isolate::kLabeledExpressionStatement);
}
return factory()->NewExpressionStatement(expr, pos);
@@ -5758,7 +5814,7 @@ ParserBase<Impl>::ParseForEachStatementWithoutDeclarations(
ForInfo* for_info, ZoneList<const AstRawString*>* labels, bool* ok) {
// Initializer is reference followed by in/of.
if (!expression->IsArrayLiteral() && !expression->IsObjectLiteral()) {
- expression = impl()->CheckAndRewriteReferenceExpression(
+ expression = CheckAndRewriteReferenceExpression(
expression, lhs_beg_pos, lhs_end_pos, MessageTemplate::kInvalidLhsInFor,
kSyntaxError, CHECK_OK);
}
@@ -5959,7 +6015,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement(
ValidateAssignmentPattern(CHECK_OK);
} else {
impl()->RewriteNonPattern(CHECK_OK);
- each_variable = impl()->CheckAndRewriteReferenceExpression(
+ each_variable = CheckAndRewriteReferenceExpression(
lhs, lhs_beg_pos, lhs_end_pos, MessageTemplate::kInvalidLhsInFor,
kSyntaxError, CHECK_OK);
}
@@ -6081,6 +6137,22 @@ void ParserBase<Impl>::ClassLiteralChecker::CheckClassMethodName(
}
}
+template <typename Impl>
+void ParserBase<Impl>::ClassLiteralChecker::CheckClassFieldName(bool is_static,
+ bool* ok) {
+ if (is_static && IsPrototype()) {
+ this->parser()->ReportMessage(MessageTemplate::kStaticPrototype);
+ *ok = false;
+ return;
+ }
+
+ if (IsConstructor()) {
+ this->parser()->ReportMessage(MessageTemplate::kConstructorClassField);
+ *ok = false;
+ return;
+ }
+}
+
#undef CHECK_OK
#undef CHECK_OK_CUSTOM
#undef CHECK_OK_VOID