| Index: src/parsing/parser-base.h
|
| diff --git a/src/parsing/parser-base.h b/src/parsing/parser-base.h
|
| index aa2a46dc71a2aa849e88af5da77a5b07431d1681..1412748f40524459e082b2d0cf4411e079c14c5e 100644
|
| --- a/src/parsing/parser-base.h
|
| +++ b/src/parsing/parser-base.h
|
| @@ -214,6 +214,7 @@ class ParserBase {
|
| typedef typename Types::StatementList StatementListT;
|
| typedef typename v8::internal::ExpressionClassifier<Types>
|
| ExpressionClassifier;
|
| + typedef typename Types::Block BlockT;
|
|
|
| // All implementation-specific methods must be called through this.
|
| Impl* impl() { return static_cast<Impl*>(this); }
|
| @@ -1177,6 +1178,11 @@ class ParserBase {
|
| bool has_rest, int formals_start_pos,
|
| int formals_end_pos, bool* ok);
|
|
|
| + BlockT ParseVariableDeclarations(VariableDeclarationContext var_context,
|
| + DeclarationParsingResult* parsing_result,
|
| + ZoneList<const AstRawString*>* names,
|
| + bool* ok);
|
| +
|
| bool IsNextLetKeyword();
|
| bool IsTrivialExpression();
|
|
|
| @@ -3410,6 +3416,154 @@ void ParserBase<Impl>::ParseFormalParameterList(FormalParametersT* parameters,
|
| }
|
|
|
| template <typename Impl>
|
| +typename ParserBase<Impl>::BlockT ParserBase<Impl>::ParseVariableDeclarations(
|
| + VariableDeclarationContext var_context,
|
| + DeclarationParsingResult* parsing_result,
|
| + ZoneList<const AstRawString*>* names, bool* ok) {
|
| + // VariableDeclarations ::
|
| + // ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[',']
|
| + //
|
| + // ES6:
|
| + // FIXME(marja, nikolaos): Add an up-to-date comment about ES6 variable
|
| + // declaration syntax.
|
| +
|
| + DeclarationParsingResult temp_result;
|
| + if (parsing_result == nullptr) {
|
| + parsing_result = &temp_result;
|
| + }
|
| + parsing_result->descriptor.declaration_kind = DeclarationDescriptor::NORMAL;
|
| + parsing_result->descriptor.declaration_pos = peek_position();
|
| + parsing_result->descriptor.initialization_pos = peek_position();
|
| +
|
| + BlockT init_block = impl()->NullBlock();
|
| + if (var_context != kForStatement) {
|
| + init_block = impl()->NewBlock(nullptr, 1, true,
|
| + parsing_result->descriptor.declaration_pos);
|
| + }
|
| +
|
| + switch (peek()) {
|
| + case Token::VAR:
|
| + parsing_result->descriptor.mode = VAR;
|
| + Consume(Token::VAR);
|
| + break;
|
| + case Token::CONST:
|
| + Consume(Token::CONST);
|
| + DCHECK(var_context != kStatement);
|
| + parsing_result->descriptor.mode = CONST;
|
| + break;
|
| + case Token::LET:
|
| + Consume(Token::LET);
|
| + DCHECK(var_context != kStatement);
|
| + parsing_result->descriptor.mode = LET;
|
| + break;
|
| + default:
|
| + UNREACHABLE(); // by current callers
|
| + break;
|
| + }
|
| +
|
| + parsing_result->descriptor.scope = scope();
|
| + parsing_result->descriptor.hoist_scope = nullptr;
|
| +
|
| + // The scope of a var/const declared variable anywhere inside a function
|
| + // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope
|
| + // of a let declared variable is the scope of the immediately enclosing
|
| + // block.
|
| + int bindings_start = peek_position();
|
| + do {
|
| + // Parse binding pattern.
|
| + FuncNameInferrer::State fni_state(fni_);
|
| +
|
| + ExpressionT pattern = impl()->EmptyExpression();
|
| + int decl_pos = peek_position();
|
| + {
|
| + ExpressionClassifier pattern_classifier(this);
|
| + pattern = ParsePrimaryExpression(CHECK_OK_CUSTOM(NullBlock));
|
| +
|
| + ValidateBindingPattern(CHECK_OK_CUSTOM(NullBlock));
|
| + if (IsLexicalVariableMode(parsing_result->descriptor.mode)) {
|
| + ValidateLetPattern(CHECK_OK_CUSTOM(NullBlock));
|
| + }
|
| + }
|
| +
|
| + Scanner::Location variable_loc = scanner()->location();
|
| + bool single_name = impl()->IsIdentifier(pattern);
|
| +
|
| + if (single_name && fni_ != nullptr) {
|
| + impl()->PushVariableName(fni_, impl()->AsIdentifier(pattern));
|
| + }
|
| +
|
| + ExpressionT value = impl()->EmptyExpression();
|
| + int initializer_position = kNoSourcePosition;
|
| + if (Check(Token::ASSIGN)) {
|
| + ExpressionClassifier classifier(this);
|
| + value = ParseAssignmentExpression(var_context != kForStatement,
|
| + CHECK_OK_CUSTOM(NullBlock));
|
| + impl()->RewriteNonPattern(CHECK_OK_CUSTOM(NullBlock));
|
| + variable_loc.end_pos = scanner()->location().end_pos;
|
| +
|
| + if (!parsing_result->first_initializer_loc.IsValid()) {
|
| + parsing_result->first_initializer_loc = variable_loc;
|
| + }
|
| +
|
| + // Don't infer if it is "a = function(){...}();"-like expression.
|
| + if (single_name && fni_ != nullptr) {
|
| + if (!value->IsCall() && !value->IsCallNew()) {
|
| + fni_->Infer();
|
| + } else {
|
| + fni_->RemoveLastFunction();
|
| + }
|
| + }
|
| +
|
| + impl()->SetFunctionNameFromIdentifierRef(value, pattern);
|
| +
|
| + // End position of the initializer is after the assignment expression.
|
| + initializer_position = scanner()->location().end_pos;
|
| + } else {
|
| + if (var_context != kForStatement || !PeekInOrOf()) {
|
| + // ES6 'const' and binding patterns require initializers.
|
| + if (parsing_result->descriptor.mode == CONST ||
|
| + !impl()->IsIdentifier(pattern)) {
|
| + impl()->ReportMessageAt(
|
| + Scanner::Location(decl_pos, scanner()->location().end_pos),
|
| + MessageTemplate::kDeclarationMissingInitializer,
|
| + !impl()->IsIdentifier(pattern) ? "destructuring" : "const");
|
| + *ok = false;
|
| + return impl()->NullBlock();
|
| + }
|
| + // 'let x' initializes 'x' to undefined.
|
| + if (parsing_result->descriptor.mode == LET) {
|
| + value = impl()->GetLiteralUndefined(position());
|
| + }
|
| + }
|
| +
|
| + // End position of the initializer is after the variable.
|
| + initializer_position = position();
|
| + }
|
| +
|
| + typename DeclarationParsingResult::Declaration decl(
|
| + pattern, initializer_position, value);
|
| + if (var_context == kForStatement) {
|
| + // Save the declaration for further handling in ParseForStatement.
|
| + parsing_result->declarations.Add(decl);
|
| + } else {
|
| + // Immediately declare the variable otherwise. This avoids O(N^2)
|
| + // behavior (where N is the number of variables in a single
|
| + // declaration) in the PatternRewriter having to do with removing
|
| + // and adding VariableProxies to the Scope (see bug 4699).
|
| + impl()->DeclareAndInitializeVariables(init_block,
|
| + &parsing_result->descriptor, &decl,
|
| + names, CHECK_OK_CUSTOM(NullBlock));
|
| + }
|
| + } while (Check(Token::COMMA));
|
| +
|
| + parsing_result->bindings_loc =
|
| + Scanner::Location(bindings_start, scanner()->location().end_pos);
|
| +
|
| + DCHECK(*ok);
|
| + return init_block;
|
| +}
|
| +
|
| +template <typename Impl>
|
| void ParserBase<Impl>::CheckArityRestrictions(int param_count,
|
| FunctionKind function_kind,
|
| bool has_rest,
|
|
|