diff options
author | Michaƫl Zasso <mic.besace@gmail.com> | 2015-10-06 08:42:38 +0200 |
---|---|---|
committer | Ali Ijaz Sheikh <ofrobots@google.com> | 2015-10-14 11:20:34 -0700 |
commit | d8011d1683fe0d977de2bea1147f5213d4490c5a (patch) | |
tree | 54967df8dc1732e59eef39e5c5b39fe99ad88977 /deps/v8/src/parser.cc | |
parent | d1a2e5357ef0357cec9b516fa9ac78cc38a984aa (diff) | |
download | node-new-d8011d1683fe0d977de2bea1147f5213d4490c5a.tar.gz |
deps: upgrade V8 to 4.6.85.23
PR-URL: https://github.com/nodejs/node/pull/3351
Reviewed-By: indutny - Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: bnoordhuis - Ben Noordhuis <info@bnoordhuis.nl>
Diffstat (limited to 'deps/v8/src/parser.cc')
-rw-r--r-- | deps/v8/src/parser.cc | 519 |
1 files changed, 306 insertions, 213 deletions
diff --git a/deps/v8/src/parser.cc b/deps/v8/src/parser.cc index aa0ec104a7..ecc6530135 100644 --- a/deps/v8/src/parser.cc +++ b/deps/v8/src/parser.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/v8.h" +#include "src/parser.h" #include "src/api.h" #include "src/ast.h" @@ -14,7 +14,6 @@ #include "src/codegen.h" #include "src/compiler.h" #include "src/messages.h" -#include "src/parser.h" #include "src/preparser.h" #include "src/runtime/runtime.h" #include "src/scanner-character-streams.h" @@ -346,7 +345,7 @@ FunctionLiteral* Parser::DefaultConstructor(bool call_super, Scope* scope, : FunctionKind::kDefaultBaseConstructor; Scope* function_scope = NewScope(scope, FUNCTION_SCOPE, kind); function_scope->SetLanguageMode( - static_cast<LanguageMode>(language_mode | STRICT_BIT)); + static_cast<LanguageMode>(language_mode | STRICT)); // Set start and end position to the same value function_scope->set_start_position(pos); function_scope->set_end_position(pos); @@ -789,9 +788,11 @@ Expression* ParserTraits::NewTargetExpression(Scope* scope, AstNodeFactory* factory, int pos) { static const int kNewTargetStringLength = 10; - return scope->NewUnresolved( + auto proxy = scope->NewUnresolved( factory, parser_->ast_value_factory()->new_target_string(), Variable::NORMAL, pos, pos + kNewTargetStringLength); + proxy->set_is_new_target(); + return proxy; } @@ -873,12 +874,12 @@ Expression* ParserTraits::ParseV8Intrinsic(bool* ok) { FunctionLiteral* ParserTraits::ParseFunctionLiteral( const AstRawString* name, Scanner::Location function_name_location, - bool name_is_strict_reserved, FunctionKind kind, + FunctionNameValidity function_name_validity, FunctionKind kind, int function_token_position, FunctionLiteral::FunctionType type, FunctionLiteral::ArityRestriction arity_restriction, LanguageMode language_mode, bool* ok) { return parser_->ParseFunctionLiteral( - name, function_name_location, name_is_strict_reserved, kind, + name, function_name_location, function_name_validity, kind, function_token_position, type, arity_restriction, language_mode, ok); } @@ -910,13 +911,12 @@ Parser::Parser(ParseInfo* info) DCHECK(!info->script().is_null() || info->source_stream() != NULL); set_allow_lazy(info->allow_lazy_parsing()); set_allow_natives(FLAG_allow_natives_syntax || info->is_native()); - set_allow_harmony_modules(!info->is_native() && FLAG_harmony_modules); set_allow_harmony_arrow_functions(FLAG_harmony_arrow_functions); set_allow_harmony_sloppy(FLAG_harmony_sloppy); - set_allow_harmony_unicode(FLAG_harmony_unicode); - set_allow_harmony_computed_property_names( - FLAG_harmony_computed_property_names); - set_allow_harmony_rest_params(FLAG_harmony_rest_parameters); + set_allow_harmony_sloppy_function(FLAG_harmony_sloppy_function); + set_allow_harmony_sloppy_let(FLAG_harmony_sloppy_let); + set_allow_harmony_rest_parameters(FLAG_harmony_rest_parameters); + set_allow_harmony_default_parameters(FLAG_harmony_default_parameters); set_allow_harmony_spreadcalls(FLAG_harmony_spreadcalls); set_allow_harmony_destructuring(FLAG_harmony_destructuring); set_allow_harmony_spread_arrays(FLAG_harmony_spread_arrays); @@ -989,7 +989,7 @@ FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) { PrintF("[parsing eval"); } else if (info->script()->name()->IsString()) { String* name = String::cast(info->script()->name()); - SmartArrayPointer<char> name_chars = name->ToCString(); + base::SmartArrayPointer<char> name_chars = name->ToCString(); PrintF("[parsing script: %s", name_chars.get()); } else { PrintF("[parsing script"); @@ -1016,7 +1016,7 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) { FunctionLiteral* result = NULL; { - // TODO(wingo): Add an outer GLOBAL_SCOPE corresponding to the native + // TODO(wingo): Add an outer SCRIPT_SCOPE corresponding to the native // context, which will have the "this" binding for script scopes. Scope* scope = NewScope(scope_, SCRIPT_SCOPE); info->set_script_scope(scope); @@ -1053,7 +1053,6 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) { bool ok = true; int beg_pos = scanner()->location().beg_pos; if (info->is_module()) { - DCHECK(allow_harmony_modules()); ParseModuleItemList(body, &ok); } else { ParseStatementList(body, Token::EOS, &ok); @@ -1065,6 +1064,8 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) { if (ok && is_strict(language_mode())) { CheckStrictOctalLiteral(beg_pos, scanner()->location().end_pos, &ok); + } + if (ok && (is_strict(language_mode()) || allow_harmony_sloppy())) { CheckConflictingVarDeclarations(scope_, &ok); } @@ -1128,7 +1129,8 @@ FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info) { if (FLAG_trace_parse && result != NULL) { double ms = timer.Elapsed().InMillisecondsF(); - SmartArrayPointer<char> name_chars = result->debug_name()->ToCString(); + base::SmartArrayPointer<char> name_chars = + result->debug_name()->ToCString(); PrintF("[parsing function: %s - took %0.3f ms]\n", name_chars.get(), ms); } return result; @@ -1184,7 +1186,7 @@ FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info, scope->SetLanguageMode(shared_info->language_mode()); scope->set_start_position(shared_info->start_position()); ExpressionClassifier formals_classifier; - ParserFormalParameterParsingState parsing_state(scope); + ParserFormalParameters formals(scope); Checkpoint checkpoint(this); { // Parsing patterns as variable reference expression creates @@ -1193,20 +1195,23 @@ FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info, BlockState block_state(&scope_, scope); if (Check(Token::LPAREN)) { // '(' StrictFormalParameters ')' - ParseFormalParameterList(&parsing_state, &formals_classifier, &ok); + ParseFormalParameterList(&formals, &formals_classifier, &ok); if (ok) ok = Check(Token::RPAREN); } else { // BindingIdentifier - const bool is_rest = false; - ParseFormalParameter(is_rest, &parsing_state, &formals_classifier, - &ok); + ParseFormalParameter(&formals, &formals_classifier, &ok); + if (ok) { + DeclareFormalParameter( + formals.scope, formals.at(0), formals.is_simple, + &formals_classifier); + } } } if (ok) { - checkpoint.Restore(&parsing_state.materialized_literals_count); + checkpoint.Restore(&formals.materialized_literals_count); Expression* expression = - ParseArrowFunctionLiteral(parsing_state, formals_classifier, &ok); + ParseArrowFunctionLiteral(formals, formals_classifier, &ok); if (ok) { // Scanning must end at the same position that was recorded // previously. If not, parsing has been interrupted due to a stack @@ -1231,9 +1236,9 @@ FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info, shared_info->language_mode()); } else { result = ParseFunctionLiteral( - raw_name, Scanner::Location::invalid(), false, shared_info->kind(), - RelocInfo::kNoPosition, function_type, FunctionLiteral::NORMAL_ARITY, - shared_info->language_mode(), &ok); + raw_name, Scanner::Location::invalid(), kSkipFunctionNameCheck, + shared_info->kind(), RelocInfo::kNoPosition, function_type, + FunctionLiteral::NORMAL_ARITY, shared_info->language_mode(), &ok); } // Make sure the results agree. DCHECK(ok == (result != NULL)); @@ -1324,20 +1329,17 @@ void* Parser::ParseStatementList(ZoneList<Statement*>* body, int end_token, // / "use strong" directives, do the strict mode changes only once. if (is_sloppy(scope_->language_mode())) { scope_->SetLanguageMode(static_cast<LanguageMode>( - scope_->language_mode() | STRICT_BIT)); + scope_->language_mode() | STRICT)); } if (use_strong_found) { scope_->SetLanguageMode(static_cast<LanguageMode>( - scope_->language_mode() | STRONG_BIT)); + scope_->language_mode() | STRONG)); } // Because declarations in strict eval code don't leak into the scope // of the eval call, it is likely that functions declared in strict // eval code will be used within the eval code, so lazy parsing is - // probably not a win. Also, resolution of "var" bindings defined in - // strict eval code from within nested functions is currently broken - // with the pre-parser; lazy parsing of strict eval code causes - // regress/regress-crbug-135066.js to fail. + // probably not a win. if (scope_->is_eval_scope()) mode_ = PARSE_EAGERLY; } else if (literal->raw_value()->AsString() == ast_value_factory()->use_asm_string() && @@ -1390,7 +1392,7 @@ Statement* Parser::ParseStatementListItem(bool* ok) { case Token::VAR: return ParseVariableStatement(kStatementListItem, NULL, ok); case Token::LET: - if (is_strict(language_mode())) { + if (allow_let()) { return ParseVariableStatement(kStatementListItem, NULL, ok); } break; @@ -1429,7 +1431,7 @@ void* Parser::ParseModuleItemList(ZoneList<Statement*>* body, bool* ok) { DCHECK(scope_->is_module_scope()); scope_->SetLanguageMode( - static_cast<LanguageMode>(scope_->language_mode() | STRICT_BIT)); + static_cast<LanguageMode>(scope_->language_mode() | STRICT)); while (peek() != Token::EOS) { Statement* stat = ParseModuleItem(CHECK_OK); @@ -2008,15 +2010,17 @@ Variable* Parser::Declare(Declaration* declaration, // variable and also set its mode. In any case, a Declaration node // will be added to the scope so that the declaration can be added // to the corresponding activation frame at runtime if necessary. - // For instance declarations inside an eval scope need to be added - // to the calling function context. - // Similarly, strict mode eval scope does not leak variable declarations to - // the caller's scope so we declare all locals, too. + // For instance, var declarations inside a sloppy eval scope need + // to be added to the calling function context. Similarly, strict + // mode eval scope and lexical eval bindings do not leak variable + // declarations to the caller's scope so we declare all locals, too. if (declaration_scope->is_function_scope() || - declaration_scope->is_strict_eval_scope() || declaration_scope->is_block_scope() || declaration_scope->is_module_scope() || - declaration_scope->is_script_scope()) { + declaration_scope->is_script_scope() || + (declaration_scope->is_eval_scope() && + (is_strict(declaration_scope->language_mode()) || + IsLexicalVariableMode(mode)))) { // Declare the variable in the declaration scope. var = declaration_scope->LookupLocal(name); if (var == NULL) { @@ -2052,13 +2056,13 @@ Variable* Parser::Declare(Declaration* declaration, // because the var declaration is hoisted to the function scope where 'x' // is already bound. DCHECK(IsDeclaredVariableMode(var->mode())); - if (is_strict(language_mode())) { + if (is_strict(language_mode()) || allow_harmony_sloppy()) { // In harmony we treat re-declarations as early errors. See // ES5 16 for a definition of early errors. if (declaration_kind == DeclarationDescriptor::NORMAL) { ParserTraits::ReportMessage(MessageTemplate::kVarRedeclaration, name); } else { - ParserTraits::ReportMessage(MessageTemplate::kStrictParamDupe); + ParserTraits::ReportMessage(MessageTemplate::kParamDupe); } *ok = false; return nullptr; @@ -2069,8 +2073,22 @@ Variable* Parser::Declare(Declaration* declaration, } else if (mode == VAR) { var->set_maybe_assigned(); } + } else if (declaration_scope->is_eval_scope() && + is_sloppy(declaration_scope->language_mode()) && + !IsLexicalVariableMode(mode)) { + // In a var binding in a sloppy direct eval, pollute the enclosing scope + // with this new binding by doing the following: + // The proxy is bound to a lookup variable to force a dynamic declaration + // using the DeclareLookupSlot runtime function. + Variable::Kind kind = Variable::NORMAL; + // TODO(sigurds) figure out if kNotAssigned is OK here + var = new (zone()) Variable(declaration_scope, name, mode, kind, + declaration->initialization(), kNotAssigned); + var->AllocateTo(VariableLocation::LOOKUP, -1); + resolve = true; } + // We add a declaration node for every declaration. The compiler // will only generate code if necessary. In particular, declarations // for inner local variables that do not represent functions won't @@ -2095,17 +2113,6 @@ Variable* Parser::Declare(Declaration* declaration, Variable::Kind kind = Variable::NORMAL; var = new (zone()) Variable(declaration_scope, name, mode, kind, kNeedsInitialization, kNotAssigned); - } else if (declaration_scope->is_eval_scope() && - is_sloppy(declaration_scope->language_mode())) { - // For variable declarations in a sloppy eval scope the proxy is bound - // to a lookup variable to force a dynamic declaration using the - // DeclareLookupSlot runtime function. - Variable::Kind kind = Variable::NORMAL; - // TODO(sigurds) figure out if kNotAssigned is OK here - var = new (zone()) Variable(declaration_scope, name, mode, kind, - declaration->initialization(), kNotAssigned); - var->AllocateTo(VariableLocation::LOOKUP, -1); - resolve = true; } // If requested and we have a local variable, bind the proxy to the variable @@ -2196,12 +2203,21 @@ Statement* Parser::ParseFunctionDeclaration( bool is_strict_reserved = false; const AstRawString* name = ParseIdentifierOrStrictReservedWord( &is_strict_reserved, CHECK_OK); + + if (fni_ != NULL) { + fni_->Enter(); + fni_->PushEnclosingName(name); + } FunctionLiteral* fun = ParseFunctionLiteral( - name, scanner()->location(), is_strict_reserved, + name, scanner()->location(), + is_strict_reserved ? kFunctionNameIsStrictReserved + : kFunctionNameValidityUnknown, is_generator ? FunctionKind::kGeneratorFunction : FunctionKind::kNormalFunction, pos, FunctionLiteral::DECLARATION, FunctionLiteral::NORMAL_ARITY, language_mode(), CHECK_OK); + if (fni_ != NULL) fni_->Leave(); + // Even if we're not at the top-level of the global or a function // scope, we treat it as such and introduce the function with its // initial value upon entering the corresponding scope. @@ -2210,9 +2226,8 @@ Statement* Parser::ParseFunctionDeclaration( VariableMode mode = is_strong(language_mode()) ? CONST - : is_strict(language_mode()) && - !(scope_->is_script_scope() || scope_->is_eval_scope() || - scope_->is_function_scope()) + : (is_strict(language_mode()) || allow_harmony_sloppy_function()) && + !scope_->is_declaration_scope() ? LET : VAR; VariableProxy* proxy = NewUnresolved(name, mode); @@ -2290,7 +2305,7 @@ Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names, Block* Parser::ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok) { - if (is_strict(language_mode())) { + if (is_strict(language_mode()) || allow_harmony_sloppy()) { return ParseScopedBlock(labels, ok); } @@ -2442,14 +2457,14 @@ void Parser::ParseVariableDeclarations(VariableDeclarationContext var_context, parsing_result->descriptor.init_op = Token::INIT_CONST_LEGACY; ++use_counts_[v8::Isolate::kLegacyConst]; } else { - DCHECK(is_strict(language_mode())); + DCHECK(is_strict(language_mode()) || allow_harmony_sloppy()); DCHECK(var_context != kStatement); parsing_result->descriptor.mode = CONST; parsing_result->descriptor.init_op = Token::INIT_CONST; } parsing_result->descriptor.is_const = true; parsing_result->descriptor.needs_init = true; - } else if (peek() == Token::LET && is_strict(language_mode())) { + } else if (peek() == Token::LET && allow_let()) { Consume(Token::LET); DCHECK(var_context != kStatement); parsing_result->descriptor.mode = LET; @@ -2823,7 +2838,7 @@ Statement* Parser::ParseReturnStatement(bool* ok) { // // return (temp = expr) === undefined ? this : // %_IsSpecObject(temp) ? temp : throw new TypeError(...); - Variable* temp = scope_->DeclarationScope()->NewTemporary( + Variable* temp = scope_->NewTemporary( ast_value_factory()->empty_string()); Assignment* assign = factory()->NewAssignment( Token::ASSIGN, factory()->NewVariableProxy(temp), return_value, pos); @@ -3177,9 +3192,9 @@ void Parser::InitializeForEachStatement(ForEachStatement* stmt, ForOfStatement* for_of = stmt->AsForOfStatement(); if (for_of != NULL) { - Variable* iterator = scope_->DeclarationScope()->NewTemporary( + Variable* iterator = scope_->NewTemporary( ast_value_factory()->dot_iterator_string()); - Variable* result = scope_->DeclarationScope()->NewTemporary( + Variable* result = scope_->NewTemporary( ast_value_factory()->dot_result_string()); Expression* assign_iterator; @@ -3295,7 +3310,7 @@ Statement* Parser::DesugarLexicalBindingsInForStatement( // make statement: temp_x = x. for (int i = 0; i < names->length(); i++) { VariableProxy* proxy = NewUnresolved(names->at(i), LET); - Variable* temp = scope_->DeclarationScope()->NewTemporary(temp_name); + Variable* temp = scope_->NewTemporary(temp_name); VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); Assignment* assignment = factory()->NewAssignment( Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition); @@ -3308,7 +3323,7 @@ Statement* Parser::DesugarLexicalBindingsInForStatement( Variable* first = NULL; // Make statement: first = 1. if (next) { - first = scope_->DeclarationScope()->NewTemporary(temp_name); + first = scope_->NewTemporary(temp_name); VariableProxy* first_proxy = factory()->NewVariableProxy(first); Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); Assignment* assignment = factory()->NewAssignment( @@ -3388,7 +3403,7 @@ Statement* Parser::DesugarLexicalBindingsInForStatement( ignore_completion_block->AddStatement(clear_first_or_next, zone()); } - Variable* flag = scope_->DeclarationScope()->NewTemporary(temp_name); + Variable* flag = scope_->NewTemporary(temp_name); // Make statement: flag = 1. { VariableProxy* flag_proxy = factory()->NewVariableProxy(flag); @@ -3501,7 +3516,7 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, DeclarationParsingResult parsing_result; if (peek() != Token::SEMICOLON) { if (peek() == Token::VAR || (peek() == Token::CONST && allow_const()) || - (peek() == Token::LET && is_strict(language_mode()))) { + (peek() == Token::LET && allow_let())) { ParseVariableDeclarations(kForStatement, &parsing_result, CHECK_OK); is_const = parsing_result.descriptor.mode == CONST; @@ -3574,7 +3589,7 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, // let x; // for TDZ // } - Variable* temp = scope_->DeclarationScope()->NewTemporary( + Variable* temp = scope_->NewTemporary( ast_value_factory()->dot_for_string()); ForEachStatement* loop = factory()->NewForEachStatement(mode, labels, stmt_pos); @@ -3665,8 +3680,9 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, CHECK_OK); } } else { - Scanner::Location lhs_location = scanner()->peek_location(); + int lhs_beg_pos = peek_position(); Expression* expression = ParseExpression(false, CHECK_OK); + int lhs_end_pos = scanner()->location().end_pos; ForEachStatement::VisitMode mode; bool accept_OF = expression->IsVariableProxy(); is_let_identifier_expression = @@ -3677,8 +3693,8 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, if (CheckInOrOf(accept_OF, &mode, ok)) { if (!*ok) return nullptr; expression = this->CheckAndRewriteReferenceExpression( - expression, lhs_location, MessageTemplate::kInvalidLhsInFor, - CHECK_OK); + expression, lhs_beg_pos, lhs_end_pos, + MessageTemplate::kInvalidLhsInFor, kSyntaxError, CHECK_OK); ForEachStatement* loop = factory()->NewForEachStatement(mode, labels, stmt_pos); @@ -3697,8 +3713,7 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, return loop; } else { - init = - factory()->NewExpressionStatement(expression, lhs_location.beg_pos); + init = factory()->NewExpressionStatement(expression, lhs_beg_pos); } } } @@ -3839,10 +3854,10 @@ Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) { void ParserTraits::ParseArrowFunctionFormalParameters( - ParserFormalParameterParsingState* parsing_state, Expression* expr, - const Scanner::Location& params_loc, Scanner::Location* duplicate_loc, - bool* ok) { - if (parsing_state->scope->num_parameters() >= Code::kMaxArguments) { + ParserFormalParameters* parameters, Expression* expr, + const Scanner::Location& params_loc, + Scanner::Location* duplicate_loc, bool* ok) { + if (parameters->Arity() >= Code::kMaxArguments) { ReportMessageAt(params_loc, MessageTemplate::kMalformedArrowFunParamList); *ok = false; return; @@ -3868,7 +3883,7 @@ void ParserTraits::ParseArrowFunctionFormalParameters( DCHECK_EQ(binop->op(), Token::COMMA); Expression* left = binop->left(); Expression* right = binop->right(); - ParseArrowFunctionFormalParameters(parsing_state, left, params_loc, + ParseArrowFunctionFormalParameters(parameters, left, params_loc, duplicate_loc, ok); if (!*ok) return; // LHS of comma expression should be unparenthesized. @@ -3876,12 +3891,15 @@ void ParserTraits::ParseArrowFunctionFormalParameters( } // Only the right-most expression may be a rest parameter. - DCHECK(!parsing_state->has_rest); + DCHECK(!parameters->has_rest); - bool is_rest = false; - if (expr->IsSpread()) { - is_rest = true; + bool is_rest = expr->IsSpread(); + if (is_rest) { expr = expr->AsSpread()->expression(); + parameters->has_rest = true; + } + if (parameters->is_simple) { + parameters->is_simple = !is_rest && expr->IsVariableProxy(); } if (expr->IsVariableProxy()) { @@ -3893,20 +3911,48 @@ void ParserTraits::ParseArrowFunctionFormalParameters( parser_->scope_->RemoveUnresolved(expr->AsVariableProxy()); } - ExpressionClassifier classifier; - DeclareFormalParameter(parsing_state, expr, &classifier, is_rest); - if (!duplicate_loc->IsValid()) { - *duplicate_loc = classifier.duplicate_formal_parameter_error().location; + Expression* initializer = nullptr; + if (!is_rest && parser_->allow_harmony_default_parameters() && + parser_->Check(Token::ASSIGN)) { + ExpressionClassifier init_classifier; + initializer = + parser_->ParseAssignmentExpression(true, &init_classifier, ok); + if (!*ok) return; + parser_->ValidateExpression(&init_classifier, ok); + if (!*ok) return; + parameters->is_simple = false; + } + + AddFormalParameter(parameters, expr, initializer, is_rest); +} + + +void ParserTraits::ParseArrowFunctionFormalParameterList( + ParserFormalParameters* parameters, Expression* expr, + const Scanner::Location& params_loc, + Scanner::Location* duplicate_loc, bool* ok) { + ParseArrowFunctionFormalParameters(parameters, expr, params_loc, + duplicate_loc, ok); + if (!*ok) return; + + for (int i = 0; i < parameters->Arity(); ++i) { + auto parameter = parameters->at(i); + ExpressionClassifier classifier; + DeclareFormalParameter( + parameters->scope, parameter, parameters->is_simple, &classifier); + if (!duplicate_loc->IsValid()) { + *duplicate_loc = classifier.duplicate_formal_parameter_error().location; + } } + DCHECK_EQ(parameters->is_simple, parameters->scope->has_simple_parameters()); } -void ParserTraits::ReindexLiterals( - const ParserFormalParameterParsingState& parsing_state) { +void ParserTraits::ReindexLiterals(const ParserFormalParameters& parameters) { if (parser_->function_state_->materialized_literal_count() > 0) { AstLiteralReindexer reindexer; - for (const auto p : parsing_state.params) { + for (const auto p : parameters.params) { if (p.pattern != nullptr) reindexer.Reindex(p.pattern); } DCHECK(reindexer.count() <= @@ -3917,8 +3963,8 @@ void ParserTraits::ReindexLiterals( FunctionLiteral* Parser::ParseFunctionLiteral( const AstRawString* function_name, Scanner::Location function_name_location, - bool name_is_strict_reserved, FunctionKind kind, int function_token_pos, - FunctionLiteral::FunctionType function_type, + FunctionNameValidity function_name_validity, FunctionKind kind, + int function_token_pos, FunctionLiteral::FunctionType function_type, FunctionLiteral::ArityRestriction arity_restriction, LanguageMode language_mode, bool* ok) { // Function :: @@ -3945,7 +3991,6 @@ FunctionLiteral* Parser::ParseFunctionLiteral( function_name = ast_value_factory()->empty_string(); } - int num_parameters = 0; // Function declarations are function scoped in normal mode, so they are // hoisted. In harmony block scoping mode they are block scoped, so they // are not hoisted. @@ -3976,13 +4021,14 @@ FunctionLiteral* Parser::ParseFunctionLiteral( Scope* declaration_scope = scope_->DeclarationScope(); Scope* original_declaration_scope = original_scope_->DeclarationScope(); Scope* scope = function_type == FunctionLiteral::DECLARATION && - is_sloppy(language_mode) && + is_sloppy(language_mode) && !allow_harmony_sloppy() && (original_scope_ == original_declaration_scope || declaration_scope != original_declaration_scope) ? NewScope(declaration_scope, FUNCTION_SCOPE, kind) : NewScope(scope_, FUNCTION_SCOPE, kind); scope->SetLanguageMode(language_mode); ZoneList<Statement*>* body = NULL; + int arity = -1; int materialized_literal_count = -1; int expected_property_count = -1; DuplicateFinder duplicate_finder(scanner()->unicode_cache()); @@ -3991,7 +4037,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral( parenthesized_function_ ? FunctionLiteral::kShouldEagerCompile : FunctionLiteral::kShouldLazyCompile; bool should_be_used_once_hint = false; - // Parse function body. + // Parse function. { AstNodeFactory function_factory(ast_value_factory()); FunctionState function_state(&function_state_, &scope_, scope, kind, @@ -4007,7 +4053,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral( // Calling a generator returns a generator object. That object is stored // in a temporary variable, a definition that is used by "yield" // expressions. This also marks the FunctionState as a generator. - Variable* temp = scope_->DeclarationScope()->NewTemporary( + Variable* temp = scope_->NewTemporary( ast_value_factory()->dot_generator_object_string()); function_state.set_generator_object_variable(temp); } @@ -4015,40 +4061,17 @@ FunctionLiteral* Parser::ParseFunctionLiteral( Expect(Token::LPAREN, CHECK_OK); int start_position = scanner()->location().beg_pos; scope_->set_start_position(start_position); - ParserFormalParameterParsingState parsing_state(scope); - num_parameters = - ParseFormalParameterList(&parsing_state, &formals_classifier, CHECK_OK); + ParserFormalParameters formals(scope); + ParseFormalParameterList(&formals, &formals_classifier, CHECK_OK); + arity = formals.Arity(); Expect(Token::RPAREN, CHECK_OK); int formals_end_position = scanner()->location().end_pos; - CheckArityRestrictions(num_parameters, arity_restriction, - parsing_state.has_rest, start_position, + CheckArityRestrictions(arity, arity_restriction, + formals.has_rest, start_position, formals_end_position, CHECK_OK); Expect(Token::LBRACE, CHECK_OK); - // 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). - // NOTE: We create a proxy and resolve it here so that in the - // future we can change the AST to only refer to VariableProxies - // instead of Variables and Proxis as is the case now. - Variable* fvar = NULL; - Token::Value fvar_init_op = Token::INIT_CONST_LEGACY; - if (function_type == FunctionLiteral::NAMED_EXPRESSION) { - if (is_strict(language_mode)) { - fvar_init_op = Token::INIT_CONST; - } - VariableMode fvar_mode = is_strict(language_mode) ? CONST : CONST_LEGACY; - DCHECK(function_name != NULL); - fvar = new (zone()) - Variable(scope_, function_name, fvar_mode, Variable::NORMAL, - kCreatedInitialized, kNotAssigned); - VariableProxy* proxy = factory()->NewVariableProxy(fvar); - VariableDeclaration* fvar_declaration = factory()->NewVariableDeclaration( - proxy, fvar_mode, scope_, RelocInfo::kNoPosition); - scope_->DeclareFunctionVar(fvar_declaration); - } - // Determine if the function can be parsed lazily. Lazy parsing is different // from lazy compilation; we need to parse more eagerly than we compile. @@ -4112,8 +4135,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral( } } if (!is_lazily_parsed) { - body = ParseEagerFunctionBody(function_name, pos, parsing_state, fvar, - fvar_init_op, kind, CHECK_OK); + body = ParseEagerFunctionBody(function_name, pos, formals, kind, + function_type, CHECK_OK); materialized_literal_count = function_state.materialized_literal_count(); expected_property_count = function_state.expected_property_count(); } @@ -4133,19 +4156,18 @@ FunctionLiteral* Parser::ParseFunctionLiteral( // Validate name and parameter names. We can do this only after parsing the // function, since the function can declare itself strict. - CheckFunctionName(language_mode, kind, function_name, - name_is_strict_reserved, function_name_location, - CHECK_OK); - const bool use_strict_params = - !parsing_state.is_simple_parameter_list || IsConciseMethod(kind); + CheckFunctionName(language_mode, function_name, function_name_validity, + function_name_location, CHECK_OK); const bool allow_duplicate_parameters = - is_sloppy(language_mode) && !use_strict_params; + is_sloppy(language_mode) && formals.is_simple && !IsConciseMethod(kind); ValidateFormalParameters(&formals_classifier, language_mode, allow_duplicate_parameters, CHECK_OK); if (is_strict(language_mode)) { CheckStrictOctalLiteral(scope->start_position(), scope->end_position(), CHECK_OK); + } + if (is_strict(language_mode) || allow_harmony_sloppy()) { CheckConflictingVarDeclarations(scope, CHECK_OK); } } @@ -4158,7 +4180,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral( FunctionLiteral* function_literal = factory()->NewFunctionLiteral( function_name, ast_value_factory(), scope, body, - materialized_literal_count, expected_property_count, num_parameters, + materialized_literal_count, expected_property_count, arity, duplicate_parameters, function_type, FunctionLiteral::kIsFunction, eager_compile_hint, kind, pos); function_literal->set_function_token_position(function_token_pos); @@ -4300,15 +4322,15 @@ Statement* Parser::BuildAssertIsCoercible(Variable* var) { Block* Parser::BuildParameterInitializationBlock( - const ParserFormalParameterParsingState& formal_parameters, bool* ok) { + const ParserFormalParameters& parameters, bool* ok) { + DCHECK(!parameters.is_simple); DCHECK(scope_->is_function_scope()); - Block* init_block = nullptr; - for (auto parameter : formal_parameters.params) { - if (parameter.pattern == nullptr) continue; - if (init_block == nullptr) { - init_block = factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition); - } - + Block* init_block = + factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition); + for (int i = 0; i < parameters.params.length(); ++i) { + auto parameter = parameters.params[i]; + // TODO(caitp,rossberg): Remove special handling for rest once desugared. + if (parameter.is_rest) break; DeclarationDescriptor descriptor; descriptor.declaration_kind = DeclarationDescriptor::PARAMETER; descriptor.parser = this; @@ -4320,9 +4342,22 @@ Block* Parser::BuildParameterInitializationBlock( descriptor.declaration_pos = parameter.pattern->position(); descriptor.initialization_pos = parameter.pattern->position(); descriptor.init_op = Token::INIT_LET; + Expression* initial_value = + factory()->NewVariableProxy(parameters.scope->parameter(i)); + if (parameter.initializer != nullptr) { + // IS_UNDEFINED($param) ? initializer : $param + auto condition = factory()->NewCompareOperation( + Token::EQ_STRICT, + factory()->NewVariableProxy(parameters.scope->parameter(i)), + factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), + RelocInfo::kNoPosition); + initial_value = factory()->NewConditional( + condition, parameter.initializer, initial_value, + RelocInfo::kNoPosition); + descriptor.initialization_pos = parameter.initializer->position(); + } DeclarationParsingResult::Declaration decl( - parameter.pattern, parameter.pattern->position(), - factory()->NewVariableProxy(parameter.var)); + parameter.pattern, parameter.pattern->position(), initial_value); PatternRewriter::DeclareAndInitializeVariables(init_block, &descriptor, &decl, nullptr, CHECK_OK); } @@ -4332,81 +4367,140 @@ Block* Parser::BuildParameterInitializationBlock( ZoneList<Statement*>* Parser::ParseEagerFunctionBody( const AstRawString* function_name, int pos, - const ParserFormalParameterParsingState& formal_parameters, Variable* fvar, - Token::Value fvar_init_op, FunctionKind kind, bool* ok) { + const ParserFormalParameters& parameters, FunctionKind kind, + FunctionLiteral::FunctionType function_type, bool* ok) { // Everything inside an eagerly parsed function will be parsed eagerly // (see comment above). ParsingModeScope parsing_mode(this, PARSE_EAGERLY); - ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(8, zone()); - if (fvar != NULL) { - VariableProxy* fproxy = scope_->NewUnresolved(factory(), function_name); - fproxy->BindTo(fvar); - body->Add(factory()->NewExpressionStatement( - factory()->NewAssignment(fvar_init_op, - fproxy, - factory()->NewThisFunction(pos), - RelocInfo::kNoPosition), - RelocInfo::kNoPosition), zone()); - } + ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone()); + static const int kFunctionNameAssignmentIndex = 0; + if (function_type == FunctionLiteral::NAMED_EXPRESSION) { + DCHECK(function_name != NULL); + // 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(NULL, zone()); + } // For concise constructors, check that they are constructed, // not called. if (i::IsConstructor(kind)) { - AddAssertIsConstruct(body, pos); + AddAssertIsConstruct(result, pos); } - auto init_block = - BuildParameterInitializationBlock(formal_parameters, CHECK_OK); - if (init_block != nullptr) { - body->Add(init_block, zone()); + ZoneList<Statement*>* body = result; + Scope* inner_scope = nullptr; + Block* inner_block = nullptr; + if (!parameters.is_simple) { + inner_scope = NewScope(scope_, BLOCK_SCOPE); + inner_scope->set_is_declaration_scope(); + inner_scope->set_start_position(scanner()->location().beg_pos); + inner_block = factory()->NewBlock(NULL, 8, true, RelocInfo::kNoPosition); + inner_block->set_scope(inner_scope); + body = inner_block->statements(); } - // For generators, allocate and yield an iterator on function entry. - if (IsGeneratorFunction(kind)) { - ZoneList<Expression*>* arguments = - new(zone()) ZoneList<Expression*>(0, zone()); - CallRuntime* allocation = factory()->NewCallRuntime( - ast_value_factory()->empty_string(), - Runtime::FunctionForId(Runtime::kCreateJSGeneratorObject), arguments, - pos); - VariableProxy* init_proxy = factory()->NewVariableProxy( - function_state_->generator_object_variable()); - Assignment* assignment = factory()->NewAssignment( - Token::INIT_VAR, init_proxy, allocation, RelocInfo::kNoPosition); - VariableProxy* get_proxy = factory()->NewVariableProxy( - function_state_->generator_object_variable()); - Yield* yield = factory()->NewYield( - get_proxy, assignment, Yield::kInitial, RelocInfo::kNoPosition); - body->Add(factory()->NewExpressionStatement( - yield, RelocInfo::kNoPosition), zone()); - } + { + BlockState block_state(&scope_, inner_scope ? inner_scope : scope_); - ParseStatementList(body, Token::RBRACE, CHECK_OK); + // For generators, allocate and yield an iterator on function entry. + if (IsGeneratorFunction(kind)) { + ZoneList<Expression*>* arguments = + new(zone()) ZoneList<Expression*>(0, zone()); + CallRuntime* allocation = factory()->NewCallRuntime( + ast_value_factory()->empty_string(), + Runtime::FunctionForId(Runtime::kCreateJSGeneratorObject), arguments, + pos); + VariableProxy* init_proxy = factory()->NewVariableProxy( + function_state_->generator_object_variable()); + Assignment* assignment = factory()->NewAssignment( + Token::INIT_VAR, init_proxy, allocation, RelocInfo::kNoPosition); + VariableProxy* get_proxy = factory()->NewVariableProxy( + function_state_->generator_object_variable()); + Yield* yield = factory()->NewYield( + get_proxy, assignment, Yield::kInitial, RelocInfo::kNoPosition); + body->Add(factory()->NewExpressionStatement( + yield, RelocInfo::kNoPosition), zone()); + } - if (IsGeneratorFunction(kind)) { - VariableProxy* get_proxy = factory()->NewVariableProxy( - function_state_->generator_object_variable()); - Expression* undefined = - factory()->NewUndefinedLiteral(RelocInfo::kNoPosition); - Yield* yield = factory()->NewYield(get_proxy, undefined, Yield::kFinal, - RelocInfo::kNoPosition); - body->Add(factory()->NewExpressionStatement( - yield, RelocInfo::kNoPosition), zone()); - } - - if (IsSubclassConstructor(kind)) { - body->Add( - factory()->NewReturnStatement( - this->ThisExpression(scope_, factory(), RelocInfo::kNoPosition), - RelocInfo::kNoPosition), - zone()); + ParseStatementList(body, Token::RBRACE, CHECK_OK); + + if (IsGeneratorFunction(kind)) { + VariableProxy* get_proxy = factory()->NewVariableProxy( + function_state_->generator_object_variable()); + Expression* undefined = + factory()->NewUndefinedLiteral(RelocInfo::kNoPosition); + Yield* yield = factory()->NewYield(get_proxy, undefined, Yield::kFinal, + RelocInfo::kNoPosition); + body->Add(factory()->NewExpressionStatement( + yield, RelocInfo::kNoPosition), zone()); + } + + if (IsSubclassConstructor(kind)) { + body->Add( + factory()->NewReturnStatement( + this->ThisExpression(scope_, factory(), RelocInfo::kNoPosition), + RelocInfo::kNoPosition), + zone()); + } } Expect(Token::RBRACE, CHECK_OK); scope_->set_end_position(scanner()->location().end_pos); - return body; + if (!parameters.is_simple) { + DCHECK_NOT_NULL(inner_scope); + DCHECK_EQ(body, inner_block->statements()); + scope_->SetLanguageMode(inner_scope->language_mode()); + Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK); + DCHECK_NOT_NULL(init_block); + + inner_scope->set_end_position(scanner()->location().end_pos); + inner_scope = inner_scope->FinalizeBlockScope(); + if (inner_scope != nullptr) { + CheckConflictingVarDeclarations(inner_scope, CHECK_OK); + } + + result->Add(init_block, zone()); + result->Add(inner_block, zone()); + } + + if (function_type == FunctionLiteral::NAMED_EXPRESSION) { + // Now that we know the language mode, we can create the const assignment + // in the previously reserved spot. + // NOTE: We create a proxy and resolve it here so that in the + // future we can change the AST to only refer to VariableProxies + // instead of Variables and Proxies as is the case now. + Token::Value fvar_init_op = Token::INIT_CONST_LEGACY; + bool use_strict_const = is_strict(scope_->language_mode()) || + (!allow_legacy_const() && allow_harmony_sloppy()); + if (use_strict_const) { + fvar_init_op = Token::INIT_CONST; + } + VariableMode fvar_mode = use_strict_const ? CONST : CONST_LEGACY; + Variable* fvar = new (zone()) + Variable(scope_, function_name, fvar_mode, Variable::NORMAL, + kCreatedInitialized, kNotAssigned); + VariableProxy* proxy = factory()->NewVariableProxy(fvar); + VariableDeclaration* fvar_declaration = factory()->NewVariableDeclaration( + proxy, fvar_mode, scope_, RelocInfo::kNoPosition); + scope_->DeclareFunctionVar(fvar_declaration); + + VariableProxy* fproxy = scope_->NewUnresolved(factory(), function_name); + fproxy->BindTo(fvar); + result->Set(kFunctionNameAssignmentIndex, + factory()->NewExpressionStatement( + factory()->NewAssignment(fvar_init_op, fproxy, + factory()->NewThisFunction(pos), + RelocInfo::kNoPosition), + RelocInfo::kNoPosition)); + } + + return result; } @@ -4425,12 +4519,11 @@ PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( reusable_preparser_->set_allow_lazy(true); #define SET_ALLOW(name) reusable_preparser_->set_allow_##name(allow_##name()); SET_ALLOW(natives); - SET_ALLOW(harmony_modules); SET_ALLOW(harmony_arrow_functions); SET_ALLOW(harmony_sloppy); - SET_ALLOW(harmony_unicode); - SET_ALLOW(harmony_computed_property_names); - SET_ALLOW(harmony_rest_params); + SET_ALLOW(harmony_sloppy_let); + SET_ALLOW(harmony_rest_parameters); + SET_ALLOW(harmony_default_parameters); SET_ALLOW(harmony_spreadcalls); SET_ALLOW(harmony_destructuring); SET_ALLOW(harmony_spread_arrays); @@ -4472,7 +4565,7 @@ ClassLiteral* Parser::ParseClassLiteral(const AstRawString* name, Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); BlockState block_state(&scope_, block_scope); scope_->SetLanguageMode( - static_cast<LanguageMode>(scope_->language_mode() | STRICT_BIT)); + static_cast<LanguageMode>(scope_->language_mode() | STRICT)); scope_->SetScopeName(name); VariableProxy* proxy = NULL; @@ -5634,7 +5727,7 @@ bool RegExpParser::ParseRegExp(Isolate* isolate, Zone* zone, bool Parser::ParseStatic(ParseInfo* info) { Parser parser(info); if (parser.Parse(info)) { - info->set_language_mode(info->function()->language_mode()); + info->set_language_mode(info->literal()->language_mode()); return true; } return false; @@ -5642,7 +5735,7 @@ bool Parser::ParseStatic(ParseInfo* info) { bool Parser::Parse(ParseInfo* info) { - DCHECK(info->function() == NULL); + DCHECK(info->literal() == NULL); FunctionLiteral* result = NULL; // Ok to use Isolate here; this function is only called in the main thread. DCHECK(parsing_on_main_thread_); @@ -5677,7 +5770,7 @@ bool Parser::Parse(ParseInfo* info) { void Parser::ParseOnBackground(ParseInfo* info) { parsing_on_main_thread_ = false; - DCHECK(info->function() == NULL); + DCHECK(info->literal() == NULL); FunctionLiteral* result = NULL; fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone()); @@ -5903,16 +5996,16 @@ Expression* Parser::SpreadCall(Expression* function, int pos) { if (function->IsSuperCallReference()) { // Super calls - // %_CallSuperWithSpread(%ReflectConstruct(<super>, args, new.target)) - args->InsertAt(0, function, zone()); + // %ReflectConstruct(%GetPrototype(<this-function>), args, new.target)) + ZoneList<Expression*>* tmp = new (zone()) ZoneList<Expression*>(1, zone()); + tmp->Add(function->AsSuperCallReference()->this_function_var(), zone()); + Expression* get_prototype = factory()->NewCallRuntime( + ast_value_factory()->empty_string(), + Runtime::FunctionForId(Runtime::kGetPrototype), tmp, pos); + args->InsertAt(0, get_prototype, zone()); args->Add(function->AsSuperCallReference()->new_target_var(), zone()); - Expression* result = factory()->NewCallRuntime( - ast_value_factory()->reflect_construct_string(), NULL, args, pos); - args = new (zone()) ZoneList<Expression*>(1, zone()); - args->Add(result, zone()); return factory()->NewCallRuntime( - ast_value_factory()->empty_string(), - Runtime::FunctionForId(Runtime::kInlineCallSuperWithSpread), args, pos); + ast_value_factory()->reflect_construct_string(), NULL, args, pos); } else { if (function->IsProperty()) { // Method calls |