diff options
author | Michaël Zasso <targos@protonmail.com> | 2017-03-21 10:16:54 +0100 |
---|---|---|
committer | Michaël Zasso <targos@protonmail.com> | 2017-03-25 09:44:10 +0100 |
commit | c459d8ea5d402c702948c860d9497b2230ff7e8a (patch) | |
tree | 56c282fc4d40e5cb613b47cf7be3ea0526ed5b6f /deps/v8/src/parsing/parser-base.h | |
parent | e0bc5a7361b1d29c3ed034155fd779ce6f44fb13 (diff) | |
download | android-node-v8-c459d8ea5d402c702948c860d9497b2230ff7e8a.tar.gz android-node-v8-c459d8ea5d402c702948c860d9497b2230ff7e8a.tar.bz2 android-node-v8-c459d8ea5d402c702948c860d9497b2230ff7e8a.zip |
deps: update V8 to 5.7.492.69
PR-URL: https://github.com/nodejs/node/pull/11752
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com>
Diffstat (limited to 'deps/v8/src/parsing/parser-base.h')
-rw-r--r-- | deps/v8/src/parsing/parser-base.h | 304 |
1 files changed, 197 insertions, 107 deletions
diff --git a/deps/v8/src/parsing/parser-base.h b/deps/v8/src/parsing/parser-base.h index 9195aec990..f7fdb26d22 100644 --- a/deps/v8/src/parsing/parser-base.h +++ b/deps/v8/src/parsing/parser-base.h @@ -9,6 +9,7 @@ #include "src/ast/scopes.h" #include "src/bailout-reason.h" #include "src/base/hashmap.h" +#include "src/counters.h" #include "src/globals.h" #include "src/messages.h" #include "src/parsing/expression-classifier.h" @@ -192,7 +193,8 @@ class ParserBase { ParserBase(Zone* zone, Scanner* scanner, uintptr_t stack_limit, v8::Extension* extension, AstValueFactory* ast_value_factory, - RuntimeCallStats* runtime_call_stats) + RuntimeCallStats* runtime_call_stats, + bool parsing_on_main_thread = true) : scope_state_(nullptr), function_state_(nullptr), extension_(extension), @@ -200,6 +202,7 @@ class ParserBase { ast_value_factory_(ast_value_factory), ast_node_factory_(ast_value_factory), runtime_call_stats_(runtime_call_stats), + parsing_on_main_thread_(parsing_on_main_thread), parsing_module_(false), stack_limit_(stack_limit), zone_(zone), @@ -207,29 +210,28 @@ class ParserBase { scanner_(scanner), stack_overflow_(false), default_eager_compile_hint_(FunctionLiteral::kShouldLazyCompile), - allow_lazy_(false), + function_literal_id_(0), allow_natives_(false), allow_tailcalls_(false), allow_harmony_do_expressions_(false), allow_harmony_function_sent_(false), - allow_harmony_async_await_(false), allow_harmony_restrictive_generators_(false), allow_harmony_trailing_commas_(false), - allow_harmony_class_fields_(false) {} + allow_harmony_class_fields_(false), + allow_harmony_object_spread_(false) {} #define ALLOW_ACCESSORS(name) \ bool allow_##name() const { return allow_##name##_; } \ void set_allow_##name(bool allow) { allow_##name##_ = allow; } - ALLOW_ACCESSORS(lazy); ALLOW_ACCESSORS(natives); ALLOW_ACCESSORS(tailcalls); ALLOW_ACCESSORS(harmony_do_expressions); ALLOW_ACCESSORS(harmony_function_sent); - ALLOW_ACCESSORS(harmony_async_await); ALLOW_ACCESSORS(harmony_restrictive_generators); ALLOW_ACCESSORS(harmony_trailing_commas); ALLOW_ACCESSORS(harmony_class_fields); + ALLOW_ACCESSORS(harmony_object_spread); #undef ALLOW_ACCESSORS @@ -246,6 +248,13 @@ class ParserBase { return default_eager_compile_hint_; } + int GetNextFunctionLiteralId() { return ++function_literal_id_; } + int GetLastFunctionLiteralId() const { return function_literal_id_; } + + void SkipFunctionLiterals(int delta) { function_literal_id_ += delta; } + + void ResetFunctionLiteralId() { function_literal_id_ = 0; } + Zone* zone() const { return zone_; } protected: @@ -411,8 +420,9 @@ class ParserBase { FunctionState* outer() const { return outer_function_state_; } void set_generator_object_variable(typename Types::Variable* variable) { - DCHECK(variable != NULL); + DCHECK_NOT_NULL(variable); DCHECK(IsResumableFunction(kind())); + DCHECK(scope()->has_forced_context_allocation()); generator_object_variable_ = variable; } typename Types::Variable* generator_object_variable() const { @@ -458,16 +468,16 @@ class ParserBase { return &non_patterns_to_rewrite_; } - bool next_function_is_parenthesized() const { - return next_function_is_parenthesized_; + bool next_function_is_likely_called() const { + return next_function_is_likely_called_; } - void set_next_function_is_parenthesized(bool parenthesized) { - next_function_is_parenthesized_ = parenthesized; + bool previous_function_was_likely_called() const { + return previous_function_was_likely_called_; } - bool this_function_is_parenthesized() const { - return this_function_is_parenthesized_; + void set_next_function_is_likely_called() { + next_function_is_likely_called_ = true; } private: @@ -508,13 +518,13 @@ class ParserBase { ZoneList<typename ExpressionClassifier::Error> reported_errors_; - // If true, the next (and immediately following) function literal is - // preceded by a parenthesis. - bool next_function_is_parenthesized_; - - // The value of the parents' next_function_is_parenthesized_, as it applies - // to this function. Filled in by constructor. - bool this_function_is_parenthesized_; + // Record whether the next (=== immediately following) function literal is + // preceded by a parenthesis / exclamation mark. Also record the previous + // state. + // These are managed by the FunctionState constructor; the caller may only + // call set_next_function_is_likely_called. + bool next_function_is_likely_called_; + bool previous_function_was_likely_called_; friend Impl; friend class Checkpoint; @@ -633,7 +643,6 @@ class ParserBase { scope(nullptr), init_block(parser->impl()->NullBlock()), inner_block(parser->impl()->NullBlock()), - for_promise_reject(false), bound_names(1, parser->zone()), tail_call_expressions(parser->zone()) {} IdentifierT name; @@ -642,7 +651,6 @@ class ParserBase { Scope* scope; BlockT init_block; BlockT inner_block; - bool for_promise_reject; ZoneList<const AstRawString*> bound_names; TailCallExpressionList tail_call_expressions; }; @@ -666,17 +674,17 @@ class ParserBase { : proxy(nullptr), extends(parser->impl()->EmptyExpression()), properties(parser->impl()->NewClassPropertyList(4)), - instance_field_initializers(parser->impl()->NewExpressionList(0)), constructor(parser->impl()->EmptyFunctionLiteral()), has_seen_constructor(false), - static_initializer_var(nullptr) {} + has_name_static_property(false), + has_static_computed_names(false) {} VariableProxy* proxy; ExpressionT extends; typename Types::ClassPropertyList properties; - ExpressionListT instance_field_initializers; FunctionLiteralT constructor; bool has_seen_constructor; - Variable* static_initializer_var; + bool has_name_static_property; + bool has_static_computed_names; }; DeclarationScope* NewScriptScope() const { @@ -712,10 +720,15 @@ class ParserBase { return new (zone()) Scope(zone(), parent, scope_type); } - DeclarationScope* NewFunctionScope(FunctionKind kind) const { + // Creates a function scope that always allocates in zone(). The function + // scope itself is either allocated in zone() or in target_zone if one is + // passed in. + DeclarationScope* NewFunctionScope(FunctionKind kind, + Zone* target_zone = nullptr) const { DCHECK(ast_value_factory()); - DeclarationScope* result = - new (zone()) DeclarationScope(zone(), scope(), FUNCTION_SCOPE, kind); + if (target_zone == nullptr) target_zone = zone(); + DeclarationScope* result = new (target_zone) + DeclarationScope(zone(), scope(), FUNCTION_SCOPE, kind); // TODO(verwaest): Move into the DeclarationScope constructor. if (!IsArrowFunction(kind)) { result->DeclareDefaultFunctionVariables(ast_value_factory()); @@ -856,35 +869,29 @@ class ParserBase { // Checks whether an octal literal was last seen between beg_pos and end_pos. // If so, reports an error. Only called for strict mode and template strings. - void CheckOctalLiteral(int beg_pos, int end_pos, - MessageTemplate::Template message, bool* ok) { + void CheckOctalLiteral(int beg_pos, int end_pos, bool is_template, bool* ok) { Scanner::Location octal = scanner()->octal_position(); if (octal.IsValid() && beg_pos <= octal.beg_pos && octal.end_pos <= end_pos) { + MessageTemplate::Template message = + is_template ? MessageTemplate::kTemplateOctalLiteral + : 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; } } - // for now, this check just collects statistics. - void CheckDecimalLiteralWithLeadingZero(int beg_pos, int end_pos) { - Scanner::Location token_location = - scanner()->decimal_with_leading_zero_position(); - if (token_location.IsValid() && beg_pos <= token_location.beg_pos && - token_location.end_pos <= end_pos) { - scanner()->clear_decimal_with_leading_zero_position(); - impl()->CountUsage(v8::Isolate::kDecimalWithLeadingZeroInStrictMode); - } - } inline void CheckStrictOctalLiteral(int beg_pos, int end_pos, bool* ok) { - CheckOctalLiteral(beg_pos, end_pos, MessageTemplate::kStrictOctalLiteral, - ok); + CheckOctalLiteral(beg_pos, end_pos, false, ok); } inline void CheckTemplateOctalLiteral(int beg_pos, int end_pos, bool* ok) { - CheckOctalLiteral(beg_pos, end_pos, MessageTemplate::kTemplateOctalLiteral, - ok); + CheckOctalLiteral(beg_pos, end_pos, true, ok); } void CheckDestructuringElement(ExpressionT element, int beg_pos, int end_pos); @@ -1143,6 +1150,7 @@ class ParserBase { kShorthandProperty, kMethodProperty, kClassField, + kSpreadProperty, kNotSet }; @@ -1154,7 +1162,8 @@ class ParserBase { ExpressionT ParseObjectLiteral(bool* ok); ClassLiteralPropertyT ParseClassPropertyDefinition( ClassLiteralChecker* checker, bool has_extends, bool* is_computed_name, - bool* has_seen_constructor, bool* ok); + 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); ObjectLiteralPropertyT ParseObjectPropertyDefinition( @@ -1423,6 +1432,7 @@ class ParserBase { AstValueFactory* ast_value_factory_; // Not owned. typename Types::Factory ast_node_factory_; RuntimeCallStats* runtime_call_stats_; + bool parsing_on_main_thread_; bool parsing_module_; uintptr_t stack_limit_; @@ -1437,15 +1447,16 @@ class ParserBase { FunctionLiteral::EagerCompileHint default_eager_compile_hint_; - bool allow_lazy_; + int function_literal_id_; + bool allow_natives_; bool allow_tailcalls_; bool allow_harmony_do_expressions_; bool allow_harmony_function_sent_; - bool allow_harmony_async_await_; bool allow_harmony_restrictive_generators_; bool allow_harmony_trailing_commas_; bool allow_harmony_class_fields_; + bool allow_harmony_object_spread_; friend class DiscardableZoneScope; }; @@ -1466,13 +1477,13 @@ ParserBase<Impl>::FunctionState::FunctionState( return_expr_context_(ReturnExprContext::kInsideValidBlock), non_patterns_to_rewrite_(0, scope->zone()), reported_errors_(16, scope->zone()), - next_function_is_parenthesized_(false), - this_function_is_parenthesized_(false) { + next_function_is_likely_called_(false), + previous_function_was_likely_called_(false) { *function_state_stack = this; if (outer_function_state_) { - this_function_is_parenthesized_ = - outer_function_state_->next_function_is_parenthesized_; - outer_function_state_->next_function_is_parenthesized_ = false; + outer_function_state_->previous_function_was_likely_called_ = + outer_function_state_->next_function_is_likely_called_; + outer_function_state_->next_function_is_likely_called_ = false; } } @@ -1594,7 +1605,7 @@ ParserBase<Impl>::ParseAndClassifyIdentifier(bool* ok) { } if (classifier()->duplicate_finder() != nullptr && - scanner()->FindSymbol(classifier()->duplicate_finder(), 1) != 0) { + scanner()->FindSymbol(classifier()->duplicate_finder())) { classifier()->RecordDuplicateFormalParameterError(scanner()->location()); } return name; @@ -1728,8 +1739,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePrimaryExpression( return impl()->ExpressionFromLiteral(Next(), beg_pos); case Token::ASYNC: - if (allow_harmony_async_await() && - !scanner()->HasAnyLineTerminatorAfterNext() && + if (!scanner()->HasAnyLineTerminatorAfterNext() && PeekAhead() == Token::FUNCTION) { Consume(Token::ASYNC); return ParseAsyncFunctionLiteral(CHECK_OK); @@ -1789,8 +1799,9 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePrimaryExpression( } // Heuristically try to detect immediately called functions before // seeing the call parentheses. - function_state_->set_next_function_is_parenthesized(peek() == - Token::FUNCTION); + if (peek() == Token::FUNCTION) { + function_state_->set_next_function_is_likely_called(); + } ExpressionT expr = ParseExpressionCoverGrammar(true, CHECK_OK); Expect(Token::RPAREN, CHECK_OK); return expr; @@ -1902,6 +1913,13 @@ ParserBase<Impl>::ParseExpressionCoverGrammar(bool accept_IN, bool* ok) { // a trailing comma is allowed at the end of an arrow parameter list break; } + + // Pass on the 'set_next_function_is_likely_called' flag if we have + // several function literals separated by comma. + if (peek() == Token::FUNCTION && + function_state_->previous_function_was_likely_called()) { + function_state_->set_next_function_is_likely_called(); + } } return result; @@ -2025,7 +2043,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePropertyName( Token::Value token = peek(); int pos = peek_position(); - if (allow_harmony_async_await() && !*is_generator && token == Token::ASYNC && + if (!*is_generator && token == Token::ASYNC && !scanner()->HasAnyLineTerminatorAfterNext()) { Consume(Token::ASYNC); token = peek(); @@ -2091,6 +2109,22 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePropertyName( break; } + case Token::ELLIPSIS: + if (allow_harmony_object_spread()) { + // TODO(gsathya): Implement destructuring/rest + classifier()->RecordPatternError(scanner()->location(), + MessageTemplate::kUnexpectedToken); + + *name = impl()->EmptyIdentifier(); + Consume(Token::ELLIPSIS); + ExpressionClassifier spread_classifier(this); + expression = ParseAssignmentExpression(true, CHECK_OK); + impl()->RewriteNonPattern(CHECK_OK); + impl()->AccumulateFormalParameterContainmentErrors(); + *kind = PropertyKind::kSpreadProperty; + return expression; + } + default: *name = ParseIdentifierName(CHECK_OK); break; @@ -2114,17 +2148,18 @@ 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, - bool* ok) { - DCHECK(has_seen_constructor != nullptr); +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) { + DCHECK_NOT_NULL(has_seen_constructor); + DCHECK_NOT_NULL(has_name_static_property); bool is_get = false; bool is_set = false; bool is_generator = false; bool is_async = false; - bool is_static = false; + *is_static = false; + *property_kind = ClassLiteralProperty::METHOD; PropertyKind kind = PropertyKind::kNotSet; Token::Value name_token = peek(); @@ -2142,7 +2177,7 @@ ParserBase<Impl>::ParseClassPropertyDefinition(ClassLiteralChecker* checker, name = impl()->GetSymbol(); // TODO(bakkot) specialize on 'static' name_expression = factory()->NewStringLiteral(name, position()); } else { - is_static = true; + *is_static = true; name_expression = ParsePropertyName( &name, &kind, &is_generator, &is_get, &is_set, &is_async, is_computed_name, CHECK_OK_CUSTOM(EmptyClassLiteralProperty)); @@ -2153,6 +2188,10 @@ ParserBase<Impl>::ParseClassPropertyDefinition(ClassLiteralChecker* checker, is_computed_name, CHECK_OK_CUSTOM(EmptyClassLiteralProperty)); } + if (!*has_name_static_property && *is_static && impl()->IsName(name)) { + *has_name_static_property = true; + } + switch (kind) { case PropertyKind::kClassField: case PropertyKind::kNotSet: // This case is a name followed by a name or @@ -2169,9 +2208,10 @@ ParserBase<Impl>::ParseClassPropertyDefinition(ClassLiteralChecker* checker, ExpressionT function_literal = ParseClassFieldForInitializer( has_initializer, CHECK_OK_CUSTOM(EmptyClassLiteralProperty)); ExpectSemicolon(CHECK_OK_CUSTOM(EmptyClassLiteralProperty)); + *property_kind = ClassLiteralProperty::FIELD; return factory()->NewClassLiteralProperty( - name_expression, function_literal, ClassLiteralProperty::FIELD, - is_static, *is_computed_name); + name_expression, function_literal, *property_kind, *is_static, + *is_computed_name); } else { ReportUnexpectedToken(Next()); *ok = false; @@ -2188,7 +2228,7 @@ ParserBase<Impl>::ParseClassPropertyDefinition(ClassLiteralChecker* checker, if (!*is_computed_name) { checker->CheckClassMethodName( name_token, PropertyKind::kMethodProperty, is_generator, is_async, - is_static, CHECK_OK_CUSTOM(EmptyClassLiteralProperty)); + *is_static, CHECK_OK_CUSTOM(EmptyClassLiteralProperty)); } FunctionKind kind = is_generator @@ -2196,9 +2236,9 @@ ParserBase<Impl>::ParseClassPropertyDefinition(ClassLiteralChecker* checker, : is_async ? FunctionKind::kAsyncConciseMethod : FunctionKind::kConciseMethod; - if (!is_static && impl()->IsConstructor(name)) { + if (!*is_static && impl()->IsConstructor(name)) { *has_seen_constructor = true; - kind = has_extends ? FunctionKind::kSubclassConstructor + kind = has_extends ? FunctionKind::kDerivedConstructor : FunctionKind::kBaseConstructor; } @@ -2207,9 +2247,10 @@ ParserBase<Impl>::ParseClassPropertyDefinition(ClassLiteralChecker* checker, kNoSourcePosition, FunctionLiteral::kAccessorOrMethod, language_mode(), CHECK_OK_CUSTOM(EmptyClassLiteralProperty)); + *property_kind = ClassLiteralProperty::METHOD; return factory()->NewClassLiteralProperty(name_expression, value, - ClassLiteralProperty::METHOD, - is_static, *is_computed_name); + *property_kind, *is_static, + *is_computed_name); } case PropertyKind::kAccessorProperty: { @@ -2218,7 +2259,7 @@ ParserBase<Impl>::ParseClassPropertyDefinition(ClassLiteralChecker* checker, if (!*is_computed_name) { checker->CheckClassMethodName( name_token, PropertyKind::kAccessorProperty, false, false, - is_static, CHECK_OK_CUSTOM(EmptyClassLiteralProperty)); + *is_static, CHECK_OK_CUSTOM(EmptyClassLiteralProperty)); // 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. @@ -2238,11 +2279,14 @@ ParserBase<Impl>::ParseClassPropertyDefinition(ClassLiteralChecker* checker, impl()->AddAccessorPrefixToFunctionName(is_get, value, name); } - return factory()->NewClassLiteralProperty( - name_expression, value, - is_get ? ClassLiteralProperty::GETTER : ClassLiteralProperty::SETTER, - is_static, *is_computed_name); + *property_kind = + is_get ? ClassLiteralProperty::GETTER : ClassLiteralProperty::SETTER; + return factory()->NewClassLiteralProperty(name_expression, value, + *property_kind, *is_static, + *is_computed_name); } + case PropertyKind::kSpreadProperty: + UNREACHABLE(); } UNREACHABLE(); return impl()->EmptyClassLiteralProperty(); @@ -2279,8 +2323,7 @@ ParserBase<Impl>::ParseClassFieldForInitializer(bool has_initializer, initializer_state.expected_property_count(), 0, 0, FunctionLiteral::kNoDuplicateParameters, FunctionLiteral::kAnonymousExpression, default_eager_compile_hint_, - initializer_scope->start_position(), true); - function_literal->set_is_class_field_initializer(true); + initializer_scope->start_position(), true, GetNextFunctionLiteralId()); return function_literal; } @@ -2305,6 +2348,18 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ObjectLiteralChecker* checker, is_computed_name, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); switch (kind) { + case PropertyKind::kSpreadProperty: + DCHECK(allow_harmony_object_spread()); + DCHECK(!is_get && !is_set && !is_generator && !is_async && + !*is_computed_name); + DCHECK(name_token == Token::ELLIPSIS); + + *is_computed_name = true; + + return factory()->NewObjectLiteralProperty( + impl()->GetLiteralTheHole(kNoSourcePosition), name_expression, + ObjectLiteralProperty::SPREAD, true); + case PropertyKind::kValueProperty: { DCHECK(!is_get && !is_set && !is_generator && !is_async); @@ -2347,7 +2402,7 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ObjectLiteralChecker* checker, DCHECK(!*is_computed_name); if (classifier()->duplicate_finder() != nullptr && - scanner()->FindSymbol(classifier()->duplicate_finder(), 1) != 0) { + scanner()->FindSymbol(classifier()->duplicate_finder())) { classifier()->RecordDuplicateFormalParameterError( scanner()->location()); } @@ -2612,7 +2667,7 @@ ParserBase<Impl>::ParseAssignmentExpression(bool accept_IN, bool* ok) { Scope::Snapshot scope_snapshot(scope()); - bool is_async = allow_harmony_async_await() && peek() == Token::ASYNC && + bool is_async = peek() == Token::ASYNC && !scanner()->HasAnyLineTerminatorAfterNext() && IsValidArrowFormalParametersStart(PeekAhead()); @@ -2732,7 +2787,7 @@ ParserBase<Impl>::ParseAssignmentExpression(bool accept_IN, bool* ok) { MessageTemplate::kInvalidLhsInAssignment, CHECK_OK); } - expression = impl()->MarkExpressionAsAssigned(expression); + impl()->MarkExpressionAsAssigned(expression); Token::Value op = Next(); // Get assignment operator. if (op != Token::ASSIGN) { @@ -2944,6 +2999,12 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseUnaryExpression( op = Next(); int pos = position(); + + // Assume "! function ..." indicates the function is likely to be called. + if (op == Token::NOT && peek() == Token::FUNCTION) { + function_state_->set_next_function_is_likely_called(); + } + ExpressionT expression = ParseUnaryExpression(CHECK_OK); impl()->RewriteNonPattern(CHECK_OK); @@ -2973,7 +3034,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseUnaryExpression( expression = CheckAndRewriteReferenceExpression( expression, beg_pos, scanner()->location().end_pos, MessageTemplate::kInvalidLhsInPrefixOp, CHECK_OK); - expression = impl()->MarkExpressionAsAssigned(expression); + impl()->MarkExpressionAsAssigned(expression); impl()->RewriteNonPattern(CHECK_OK); return factory()->NewCountOperation(op, @@ -3013,7 +3074,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePostfixExpression( expression = CheckAndRewriteReferenceExpression( expression, lhs_beg_pos, scanner()->location().end_pos, MessageTemplate::kInvalidLhsInPostfixOp, CHECK_OK); - expression = impl()->MarkExpressionAsAssigned(expression); + impl()->MarkExpressionAsAssigned(expression); impl()->RewriteNonPattern(CHECK_OK); Token::Value next = Next(); @@ -3119,7 +3180,6 @@ ParserBase<Impl>::ParseLeftHandSideExpression(bool* ok) { bool is_super_call = result->IsSuperCallReference(); if (spread_pos.IsValid()) { - args = impl()->PrepareSpreadArguments(args); result = impl()->SpreadCall(result, args, pos); } else { result = factory()->NewCall(result, args, pos, is_possibly_eval); @@ -3128,7 +3188,6 @@ ParserBase<Impl>::ParseLeftHandSideExpression(bool* ok) { // Explicit calls to the super constructor using super() perform an // implicit binding assignment to the 'this' variable. if (is_super_call) { - result = impl()->RewriteSuperCall(result); ExpressionT this_expr = impl()->ThisExpression(pos); result = factory()->NewAssignment(Token::INIT, this_expr, result, pos); @@ -3211,7 +3270,6 @@ ParserBase<Impl>::ParseMemberWithNewPrefixesExpression(bool* is_async, ExpressionListT args = ParseArguments(&spread_pos, CHECK_OK); if (spread_pos.IsValid()) { - args = impl()->PrepareSpreadArguments(args); result = impl()->SpreadCallNew(result, args, new_pos); } else { result = factory()->NewCallNew(result, args, new_pos); @@ -3310,7 +3368,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseSuperExpression( } // new super() is never allowed. // super() is only allowed in derived constructor - if (!is_new && peek() == Token::LPAREN && IsSubclassConstructor(kind)) { + if (!is_new && peek() == Token::LPAREN && IsDerivedConstructor(kind)) { // TODO(rossberg): This might not be the correct FunctionState for the // method here. return impl()->NewSuperCallReference(pos); @@ -3501,10 +3559,7 @@ void ParserBase<Impl>::ParseFormalParameterList(FormalParametersT* parameters, } } - for (int i = 0; i < parameters->arity; ++i) { - auto parameter = parameters->at(i); - impl()->DeclareFormalParameter(parameters->scope, parameter); - } + impl()->DeclareFormalParameters(parameters->scope, parameters->params); } template <typename Impl> @@ -3725,8 +3780,23 @@ ParserBase<Impl>::ParseHoistableDeclaration( pos, FunctionLiteral::kDeclaration, language_mode(), CHECK_OK_CUSTOM(NullStatement)); - return impl()->DeclareFunction(variable_name, function, pos, is_generator, - is_async, names, ok); + // In ES6, a function behaves as a lexical binding, except in + // a script scope, or the initial scope of eval or another function. + VariableMode mode = + (!scope()->is_declaration_scope() || scope()->is_module_scope()) ? LET + : VAR; + // Async functions don't undergo sloppy mode block scoped hoisting, and don't + // allow duplicates in a block. Both are represented by the + // 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); + + return impl()->DeclareFunction(variable_name, function, mode, pos, + is_generator, is_async, + is_sloppy_block_function, names, ok); } template <typename Impl> @@ -3890,10 +3960,14 @@ template <typename Impl> typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseArrowFunctionLiteral( bool accept_IN, const FormalParametersT& formal_parameters, bool* ok) { + const RuntimeCallStats::CounterId counters[2][2] = { + {&RuntimeCallStats::ParseBackgroundArrowFunctionLiteral, + &RuntimeCallStats::ParseArrowFunctionLiteral}, + {&RuntimeCallStats::PreParseBackgroundArrowFunctionLiteral, + &RuntimeCallStats::PreParseArrowFunctionLiteral}}; RuntimeCallTimerScope runtime_timer( runtime_call_stats_, - Impl::IsPreParser() ? &RuntimeCallStats::ParseArrowFunctionLiteral - : &RuntimeCallStats::PreParseArrowFunctionLiteral); + counters[Impl::IsPreParser()][parsing_on_main_thread_]); if (peek() == Token::ARROW && scanner_->HasAnyLineTerminatorBeforeNext()) { // ASI inserts `;` after arrow parameters if a line terminator is found. @@ -3907,6 +3981,7 @@ ParserBase<Impl>::ParseArrowFunctionLiteral( StatementListT body = impl()->NullStatementList(); int materialized_literal_count = -1; int expected_property_count = -1; + int function_literal_id = GetNextFunctionLiteralId(); FunctionKind kind = formal_parameters.scope->function_kind(); FunctionLiteral::EagerCompileHint eager_compile_hint = @@ -4044,7 +4119,8 @@ ParserBase<Impl>::ParseArrowFunctionLiteral( formal_parameters.num_parameters(), formal_parameters.function_length, FunctionLiteral::kNoDuplicateParameters, FunctionLiteral::kAnonymousExpression, eager_compile_hint, - formal_parameters.scope->start_position(), has_braces); + formal_parameters.scope->start_position(), has_braces, + function_literal_id); function_literal->set_function_token_position( formal_parameters.scope->start_position()); @@ -4102,14 +4178,26 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseClassLiteral( FuncNameInferrer::State 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); + // 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, has_extends, &is_computed_name, - &class_info.has_seen_constructor, CHECK_OK); + &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; + } + is_constructor &= class_info.has_seen_constructor; impl()->RewriteNonPattern(CHECK_OK); impl()->AccumulateFormalParameterContainmentErrors(); - impl()->DeclareClassProperty(name, property, &class_info, CHECK_OK); + impl()->DeclareClassProperty(name, property, property_kind, is_static, + is_constructor, &class_info, CHECK_OK); impl()->InferFunctionName(); } @@ -4123,8 +4211,6 @@ void ParserBase<Impl>::ParseAsyncFunctionBody(Scope* scope, StatementListT body, FunctionBodyType body_type, bool accept_IN, int pos, bool* ok) { - scope->ForceContextAllocation(); - impl()->PrepareAsyncFunctionBody(body, kind, pos); BlockT block = factory()->NewBlock(nullptr, 8, true, kNoSourcePosition); @@ -4291,7 +4377,12 @@ ParserBase<Impl>::CheckAndRewriteReferenceExpression( } if (expression->IsCall()) { // 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]'. + impl()->CountUsage( + is_strict(language_mode()) + ? v8::Isolate::kAssigmentExpressionLHSIsCallInStrict + : v8::Isolate::kAssigmentExpressionLHSIsCallInSloppy); ExpressionT error = impl()->NewThrowReferenceError(message, beg_pos); return factory()->NewProperty(expression, error, beg_pos); } @@ -4473,7 +4564,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseStatementListItem( } break; case Token::ASYNC: - if (allow_harmony_async_await() && PeekAhead() == Token::FUNCTION && + if (PeekAhead() == Token::FUNCTION && !scanner()->HasAnyLineTerminatorAfterNext()) { Consume(Token::ASYNC); return ParseAsyncFunctionDeclaration(nullptr, false, ok); @@ -4866,13 +4957,13 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseReturnStatement( ExpressionT return_value = impl()->EmptyExpression(); if (scanner()->HasAnyLineTerminatorBeforeNext() || tok == Token::SEMICOLON || tok == Token::RBRACE || tok == Token::EOS) { - if (IsSubclassConstructor(function_state_->kind())) { + if (IsDerivedConstructor(function_state_->kind())) { return_value = impl()->ThisExpression(loc.beg_pos); } else { return_value = impl()->GetLiteralUndefined(position()); } } else { - if (IsSubclassConstructor(function_state_->kind())) { + if (IsDerivedConstructor(function_state_->kind())) { // Because of the return code rewriting that happens in case of a subclass // constructor we don't want to accept tail calls, therefore we don't set // ReturnExprScope to kInsideValidReturnStatement here. @@ -5073,7 +5164,6 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseTryStatement( } CatchInfo catch_info(this); - catch_info.for_promise_reject = allow_natives() && Check(Token::MOD); if (peek() != Token::CATCH && peek() != Token::FINALLY) { ReportMessage(MessageTemplate::kNoCatchOrFinally); |