2011-05-19 09:22:32 +00:00
|
|
|
// Copyright 2011 the V8 project authors. All rights reserved.
|
2014-04-29 06:42:26 +00:00
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
2010-11-23 11:46:36 +00:00
|
|
|
|
2013-04-19 13:26:47 +00:00
|
|
|
#include <cmath>
|
2011-09-07 12:39:53 +00:00
|
|
|
|
2014-06-03 08:12:43 +00:00
|
|
|
#include "src/allocation.h"
|
2014-06-30 13:25:46 +00:00
|
|
|
#include "src/base/logging.h"
|
2014-06-03 08:12:43 +00:00
|
|
|
#include "src/conversions-inl.h"
|
2014-06-20 08:40:11 +00:00
|
|
|
#include "src/conversions.h"
|
2014-06-03 08:12:43 +00:00
|
|
|
#include "src/globals.h"
|
|
|
|
#include "src/list.h"
|
2016-08-25 11:58:07 +00:00
|
|
|
#include "src/parsing/duplicate-finder.h"
|
2015-12-07 14:26:25 +00:00
|
|
|
#include "src/parsing/parser-base.h"
|
2015-11-26 16:22:34 +00:00
|
|
|
#include "src/parsing/preparse-data-format.h"
|
2016-04-26 17:30:21 +00:00
|
|
|
#include "src/parsing/preparse-data.h"
|
2015-11-26 16:22:34 +00:00
|
|
|
#include "src/parsing/preparser.h"
|
2014-06-03 08:12:43 +00:00
|
|
|
#include "src/unicode.h"
|
|
|
|
#include "src/utils.h"
|
2011-07-05 11:54:11 +00:00
|
|
|
|
2013-04-19 13:26:47 +00:00
|
|
|
namespace v8 {
|
2013-10-14 13:07:20 +00:00
|
|
|
namespace internal {
|
2010-11-23 11:46:36 +00:00
|
|
|
|
2016-07-19 08:03:43 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// The CHECK_OK macro is a convenient macro to enforce error
|
|
|
|
// handling for functions that may fail (by returning !*ok).
|
|
|
|
//
|
|
|
|
// CAUTION: This macro appends extra statements after a call,
|
|
|
|
// thus it must never be used where only a single statement
|
|
|
|
// is correct (e.g. an if statement branch w/o braces)!
|
|
|
|
|
2016-09-01 10:22:54 +00:00
|
|
|
#define CHECK_OK_VALUE(x) ok); \
|
|
|
|
if (!*ok) return x; \
|
2016-07-19 08:03:43 +00:00
|
|
|
((void)0
|
|
|
|
#define DUMMY ) // to make indentation work
|
|
|
|
#undef DUMMY
|
|
|
|
|
2016-09-01 10:22:54 +00:00
|
|
|
#define CHECK_OK CHECK_OK_VALUE(Statement::Default())
|
|
|
|
#define CHECK_OK_VOID CHECK_OK_VALUE(this->Void())
|
2016-07-19 08:03:43 +00:00
|
|
|
|
2016-09-26 14:03:26 +00:00
|
|
|
PreParserIdentifier PreParser::GetSymbol() const {
|
|
|
|
switch (scanner()->current_token()) {
|
2016-08-19 08:14:16 +00:00
|
|
|
case Token::ENUM:
|
|
|
|
return PreParserIdentifier::Enum();
|
|
|
|
case Token::AWAIT:
|
|
|
|
return PreParserIdentifier::Await();
|
|
|
|
case Token::FUTURE_STRICT_RESERVED_WORD:
|
|
|
|
return PreParserIdentifier::FutureStrictReserved();
|
|
|
|
case Token::LET:
|
|
|
|
return PreParserIdentifier::Let();
|
|
|
|
case Token::STATIC:
|
|
|
|
return PreParserIdentifier::Static();
|
|
|
|
case Token::YIELD:
|
|
|
|
return PreParserIdentifier::Yield();
|
|
|
|
case Token::ASYNC:
|
|
|
|
return PreParserIdentifier::Async();
|
|
|
|
default:
|
2016-09-26 14:03:26 +00:00
|
|
|
if (scanner()->UnescapedLiteralMatches("eval", 4))
|
2016-08-19 08:14:16 +00:00
|
|
|
return PreParserIdentifier::Eval();
|
2016-09-26 14:03:26 +00:00
|
|
|
if (scanner()->UnescapedLiteralMatches("arguments", 9))
|
2016-08-19 08:14:16 +00:00
|
|
|
return PreParserIdentifier::Arguments();
|
2016-09-26 14:03:26 +00:00
|
|
|
if (scanner()->UnescapedLiteralMatches("undefined", 9))
|
2016-08-19 08:14:16 +00:00
|
|
|
return PreParserIdentifier::Undefined();
|
2016-09-26 14:03:26 +00:00
|
|
|
if (scanner()->LiteralMatches("prototype", 9))
|
2016-08-19 08:14:16 +00:00
|
|
|
return PreParserIdentifier::Prototype();
|
2016-09-26 14:03:26 +00:00
|
|
|
if (scanner()->LiteralMatches("constructor", 11))
|
2016-08-19 08:14:16 +00:00
|
|
|
return PreParserIdentifier::Constructor();
|
|
|
|
return PreParserIdentifier::Default();
|
2014-02-11 09:35:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-25 09:36:31 +00:00
|
|
|
PreParser::PreParseResult PreParser::PreParseLazyFunction(
|
2016-09-26 14:03:26 +00:00
|
|
|
LanguageMode language_mode, FunctionKind kind, bool has_simple_parameters,
|
|
|
|
bool parsing_module, ParserRecorder* log, bool may_abort, int* use_counts) {
|
2016-04-29 18:12:57 +00:00
|
|
|
parsing_module_ = parsing_module;
|
2011-11-25 09:36:31 +00:00
|
|
|
log_ = log;
|
2016-04-26 00:29:37 +00:00
|
|
|
use_counts_ = use_counts;
|
2016-09-26 14:03:26 +00:00
|
|
|
// Lazy functions always have trivial outer scopes (no with/catch scopes).
|
2016-07-19 10:06:38 +00:00
|
|
|
DCHECK_NULL(scope_state_);
|
2016-09-26 14:03:26 +00:00
|
|
|
DeclarationScope* top_scope = NewScriptScope();
|
|
|
|
FunctionState top_state(&function_state_, &scope_state_, top_scope,
|
|
|
|
kNormalFunction);
|
|
|
|
scope()->SetLanguageMode(language_mode);
|
|
|
|
DeclarationScope* function_scope = NewFunctionScope(kind);
|
|
|
|
if (!has_simple_parameters) function_scope->SetHasNonSimpleParameters();
|
2016-07-19 10:06:38 +00:00
|
|
|
FunctionState function_state(&function_state_, &scope_state_, function_scope,
|
2016-09-26 14:02:17 +00:00
|
|
|
kind);
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK_EQ(Token::LBRACE, scanner()->current_token());
|
2011-11-25 09:36:31 +00:00
|
|
|
bool ok = true;
|
2013-10-15 08:32:58 +00:00
|
|
|
int start_position = peek_position();
|
2016-09-01 10:22:54 +00:00
|
|
|
LazyParsingResult result = ParseLazyFunctionLiteralBody(may_abort, &ok);
|
2016-04-26 00:29:37 +00:00
|
|
|
use_counts_ = nullptr;
|
2016-09-01 10:22:54 +00:00
|
|
|
if (result == kLazyParsingAborted) {
|
|
|
|
return kPreParseAbort;
|
2015-05-06 10:21:20 +00:00
|
|
|
} else if (stack_overflow()) {
|
|
|
|
return kPreParseStackOverflow;
|
|
|
|
} else if (!ok) {
|
2013-10-14 16:46:51 +00:00
|
|
|
ReportUnexpectedToken(scanner()->current_token());
|
2011-11-25 09:36:31 +00:00
|
|
|
} else {
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK_EQ(Token::RBRACE, scanner()->peek());
|
2016-09-26 14:02:17 +00:00
|
|
|
if (is_strict(scope()->language_mode())) {
|
2013-10-14 16:46:51 +00:00
|
|
|
int end_pos = scanner()->location().end_pos;
|
2014-12-18 22:01:25 +00:00
|
|
|
CheckStrictOctalLiteral(start_position, end_pos, &ok);
|
2016-09-08 11:03:46 +00:00
|
|
|
CheckDecimalLiteralWithLeadingZero(start_position, end_pos);
|
2011-11-25 09:36:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return kPreParseSuccess;
|
|
|
|
}
|
|
|
|
|
2014-11-14 15:05:05 +00:00
|
|
|
|
2010-11-23 11:46:36 +00:00
|
|
|
// Preparsing checks a JavaScript program and emits preparse-data that helps
|
|
|
|
// a later parsing to be faster.
|
|
|
|
// See preparser-data.h for the data.
|
|
|
|
|
|
|
|
// The PreParser checks that the syntax follows the grammar for JavaScript,
|
|
|
|
// and collects some information about the program along the way.
|
|
|
|
// The grammar check is only performed in order to understand the program
|
|
|
|
// sufficiently to deduce some information about it, that can be used
|
|
|
|
// to speed up later parsing. Finding errors is not the goal of pre-parsing,
|
|
|
|
// rather it is to speed up properly written and correct programs.
|
|
|
|
// That means that contextual checks (like a label being declared where
|
|
|
|
// it is used) are generally omitted.
|
|
|
|
|
2016-09-05 13:42:01 +00:00
|
|
|
PreParser::Statement PreParser::ParseAsyncFunctionDeclaration(
|
|
|
|
ZoneList<const AstRawString*>* names, bool default_export, bool* ok) {
|
2016-05-16 23:17:13 +00:00
|
|
|
// AsyncFunctionDeclaration ::
|
|
|
|
// async [no LineTerminator here] function BindingIdentifier[Await]
|
|
|
|
// ( FormalParameters[Await] ) { AsyncFunctionBody }
|
|
|
|
DCHECK_EQ(scanner()->current_token(), Token::ASYNC);
|
|
|
|
int pos = position();
|
|
|
|
Expect(Token::FUNCTION, CHECK_OK);
|
|
|
|
ParseFunctionFlags flags = ParseFunctionFlags::kIsAsync;
|
2016-09-05 13:42:01 +00:00
|
|
|
return ParseHoistableDeclaration(pos, flags, names, default_export, ok);
|
2016-05-16 23:17:13 +00:00
|
|
|
}
|
2010-11-23 11:46:36 +00:00
|
|
|
|
2016-09-05 13:42:01 +00:00
|
|
|
PreParser::Statement PreParser::ParseClassDeclaration(
|
|
|
|
ZoneList<const AstRawString*>* names, bool default_export, bool* ok) {
|
2014-09-16 22:15:39 +00:00
|
|
|
int pos = position();
|
|
|
|
bool is_strict_reserved = false;
|
|
|
|
Identifier name =
|
|
|
|
ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
|
2016-09-01 08:58:15 +00:00
|
|
|
ExpressionClassifier no_classifier(this);
|
|
|
|
ParseClassLiteral(name, scanner()->location(), is_strict_reserved, pos,
|
|
|
|
CHECK_OK);
|
2014-09-16 22:15:39 +00:00
|
|
|
return Statement::Default();
|
|
|
|
}
|
|
|
|
|
2016-04-27 19:18:13 +00:00
|
|
|
PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
|
|
|
|
Consume(Token::FUNCTION);
|
|
|
|
int pos = position();
|
2016-05-16 23:17:13 +00:00
|
|
|
ParseFunctionFlags flags = ParseFunctionFlags::kIsNormal;
|
|
|
|
if (Check(Token::MUL)) {
|
|
|
|
flags |= ParseFunctionFlags::kIsGenerator;
|
|
|
|
if (allow_harmony_restrictive_declarations()) {
|
2016-08-19 08:11:04 +00:00
|
|
|
ReportMessageAt(scanner()->location(),
|
|
|
|
MessageTemplate::kGeneratorInLegacyContext);
|
2016-05-16 23:17:13 +00:00
|
|
|
*ok = false;
|
|
|
|
return Statement::Default();
|
|
|
|
}
|
2016-04-27 19:18:13 +00:00
|
|
|
}
|
2016-09-09 07:57:59 +00:00
|
|
|
// PreParser is not able to parse "export default" yet (since PreParser is
|
|
|
|
// at the moment only used for functions, and it cannot occur
|
|
|
|
// there). TODO(marja): update this when it is.
|
2016-09-05 13:42:01 +00:00
|
|
|
return ParseHoistableDeclaration(pos, flags, nullptr, false, ok);
|
2016-04-27 19:18:13 +00:00
|
|
|
}
|
|
|
|
|
2016-07-19 08:03:43 +00:00
|
|
|
// Redefinition of CHECK_OK for parsing expressions.
|
2011-05-19 09:01:46 +00:00
|
|
|
#undef CHECK_OK
|
2016-09-01 10:22:54 +00:00
|
|
|
#define CHECK_OK CHECK_OK_VALUE(Expression::Default())
|
2011-05-19 09:01:46 +00:00
|
|
|
|
2014-02-07 10:47:01 +00:00
|
|
|
PreParser::Expression PreParser::ParseFunctionLiteral(
|
2014-09-10 16:39:42 +00:00
|
|
|
Identifier function_name, Scanner::Location function_name_location,
|
2015-07-09 21:31:11 +00:00
|
|
|
FunctionNameValidity function_name_validity, FunctionKind kind,
|
|
|
|
int function_token_pos, FunctionLiteral::FunctionType function_type,
|
2015-07-15 09:14:49 +00:00
|
|
|
LanguageMode language_mode, bool* ok) {
|
2010-11-23 11:46:36 +00:00
|
|
|
// Function ::
|
|
|
|
// '(' FormalParameterList? ')' '{' FunctionBody '}'
|
|
|
|
|
|
|
|
// Parse function body.
|
2016-09-05 13:42:01 +00:00
|
|
|
PreParserStatementList body;
|
2016-07-19 10:06:38 +00:00
|
|
|
bool outer_is_script_scope = scope()->is_script_scope();
|
2016-08-05 14:30:54 +00:00
|
|
|
DeclarationScope* function_scope = NewFunctionScope(kind);
|
2015-07-15 09:14:49 +00:00
|
|
|
function_scope->SetLanguageMode(language_mode);
|
2016-07-19 10:06:38 +00:00
|
|
|
FunctionState function_state(&function_state_, &scope_state_, function_scope,
|
2016-07-21 11:02:54 +00:00
|
|
|
kind);
|
2015-06-09 17:13:35 +00:00
|
|
|
DuplicateFinder duplicate_finder(scanner()->unicode_cache());
|
2016-02-19 15:58:57 +00:00
|
|
|
ExpressionClassifier formals_classifier(this, &duplicate_finder);
|
2015-04-10 12:04:51 +00:00
|
|
|
|
2015-04-21 11:09:53 +00:00
|
|
|
Expect(Token::LPAREN, CHECK_OK);
|
|
|
|
int start_position = scanner()->location().beg_pos;
|
|
|
|
function_scope->set_start_position(start_position);
|
2015-08-26 14:59:05 +00:00
|
|
|
PreParserFormalParameters formals(function_scope);
|
2016-09-01 08:58:15 +00:00
|
|
|
ParseFormalParameterList(&formals, CHECK_OK);
|
2015-04-17 09:51:22 +00:00
|
|
|
Expect(Token::RPAREN, CHECK_OK);
|
2015-04-21 11:09:53 +00:00
|
|
|
int formals_end_position = scanner()->location().end_pos;
|
|
|
|
|
2016-02-19 02:50:58 +00:00
|
|
|
CheckArityRestrictions(formals.arity, kind, formals.has_rest, start_position,
|
2015-06-22 14:15:53 +00:00
|
|
|
formals_end_position, CHECK_OK);
|
2010-11-23 11:46:36 +00:00
|
|
|
|
2014-02-19 14:50:33 +00:00
|
|
|
// See Parser::ParseFunctionLiteral for more information about lazy parsing
|
|
|
|
// and lazy compilation.
|
2016-04-20 09:33:01 +00:00
|
|
|
bool is_lazily_parsed = (outer_is_script_scope && allow_lazy() &&
|
|
|
|
!function_state_->this_function_is_parenthesized());
|
2010-11-23 11:46:36 +00:00
|
|
|
|
2013-10-15 08:57:36 +00:00
|
|
|
Expect(Token::LBRACE, CHECK_OK);
|
2014-02-19 14:50:33 +00:00
|
|
|
if (is_lazily_parsed) {
|
2016-09-01 10:22:54 +00:00
|
|
|
ParseLazyFunctionLiteralBody(false, CHECK_OK);
|
2010-11-23 11:46:36 +00:00
|
|
|
} else {
|
2016-09-05 13:42:01 +00:00
|
|
|
ParseStatementList(body, Token::RBRACE, CHECK_OK);
|
2010-11-23 11:46:36 +00:00
|
|
|
}
|
2013-10-15 08:57:36 +00:00
|
|
|
Expect(Token::RBRACE, CHECK_OK);
|
2011-05-06 11:41:15 +00:00
|
|
|
|
2015-07-15 09:14:49 +00:00
|
|
|
// Parsing the body may change the language mode in our scope.
|
|
|
|
language_mode = function_scope->language_mode();
|
|
|
|
|
2015-02-06 18:04:11 +00:00
|
|
|
// Validate name and parameter names. We can do this only after parsing the
|
|
|
|
// function, since the function can declare itself strict.
|
2015-07-15 09:14:49 +00:00
|
|
|
CheckFunctionName(language_mode, function_name, function_name_validity,
|
2015-07-09 21:31:11 +00:00
|
|
|
function_name_location, CHECK_OK);
|
2015-05-13 11:45:04 +00:00
|
|
|
const bool allow_duplicate_parameters =
|
2015-07-23 11:53:31 +00:00
|
|
|
is_sloppy(language_mode) && formals.is_simple && !IsConciseMethod(kind);
|
2016-09-01 08:58:15 +00:00
|
|
|
ValidateFormalParameters(language_mode, allow_duplicate_parameters, CHECK_OK);
|
2014-02-07 10:47:01 +00:00
|
|
|
|
2015-07-15 09:14:49 +00:00
|
|
|
if (is_strict(language_mode)) {
|
2013-10-14 16:46:51 +00:00
|
|
|
int end_position = scanner()->location().end_pos;
|
2014-12-18 22:01:25 +00:00
|
|
|
CheckStrictOctalLiteral(start_position, end_position, CHECK_OK);
|
2016-09-08 11:03:46 +00:00
|
|
|
CheckDecimalLiteralWithLeadingZero(start_position, end_position);
|
2011-05-06 11:41:15 +00:00
|
|
|
}
|
|
|
|
|
2011-05-19 09:01:46 +00:00
|
|
|
return Expression::Default();
|
2010-11-23 11:46:36 +00:00
|
|
|
}
|
|
|
|
|
2016-05-16 23:17:13 +00:00
|
|
|
PreParser::Expression PreParser::ParseAsyncFunctionExpression(bool* ok) {
|
|
|
|
// AsyncFunctionDeclaration ::
|
|
|
|
// async [no LineTerminator here] function ( FormalParameters[Await] )
|
|
|
|
// { AsyncFunctionBody }
|
|
|
|
//
|
|
|
|
// async [no LineTerminator here] function BindingIdentifier[Await]
|
|
|
|
// ( FormalParameters[Await] ) { AsyncFunctionBody }
|
|
|
|
int pos = position();
|
|
|
|
Expect(Token::FUNCTION, CHECK_OK);
|
|
|
|
bool is_strict_reserved = false;
|
|
|
|
Identifier name;
|
|
|
|
FunctionLiteral::FunctionType type = FunctionLiteral::kAnonymousExpression;
|
|
|
|
|
|
|
|
if (peek_any_identifier()) {
|
|
|
|
type = FunctionLiteral::kNamedExpression;
|
2016-08-22 18:03:46 +00:00
|
|
|
name = ParseIdentifierOrStrictReservedWord(FunctionKind::kAsyncFunction,
|
|
|
|
&is_strict_reserved, CHECK_OK);
|
2016-05-16 23:17:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ParseFunctionLiteral(name, scanner()->location(),
|
|
|
|
is_strict_reserved ? kFunctionNameIsStrictReserved
|
|
|
|
: kFunctionNameValidityUnknown,
|
|
|
|
FunctionKind::kAsyncFunction, pos, type, language_mode(),
|
|
|
|
CHECK_OK);
|
|
|
|
return Expression::Default();
|
|
|
|
}
|
2010-11-23 11:46:36 +00:00
|
|
|
|
2016-09-01 10:22:54 +00:00
|
|
|
PreParser::LazyParsingResult PreParser::ParseLazyFunctionLiteralBody(
|
|
|
|
bool may_abort, bool* ok) {
|
2013-10-15 08:32:58 +00:00
|
|
|
int body_start = position();
|
2016-09-05 13:42:01 +00:00
|
|
|
PreParserStatementList body;
|
2016-09-01 10:22:54 +00:00
|
|
|
LazyParsingResult result = ParseStatementList(
|
2016-09-05 13:42:01 +00:00
|
|
|
body, Token::RBRACE, may_abort, CHECK_OK_VALUE(kLazyParsingComplete));
|
2016-09-01 10:22:54 +00:00
|
|
|
if (result == kLazyParsingAborted) return result;
|
2011-11-25 09:36:31 +00:00
|
|
|
|
|
|
|
// Position right after terminal '}'.
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK_EQ(Token::RBRACE, scanner()->peek());
|
2013-10-14 16:46:51 +00:00
|
|
|
int body_end = scanner()->peek_location().end_pos;
|
2016-08-23 14:18:12 +00:00
|
|
|
DeclarationScope* scope = this->scope()->AsDeclarationScope();
|
|
|
|
DCHECK(scope->is_function_scope());
|
2015-02-13 18:34:52 +00:00
|
|
|
log_->LogFunction(body_start, body_end,
|
|
|
|
function_state_->materialized_literal_count(),
|
|
|
|
function_state_->expected_property_count(), language_mode(),
|
2016-08-23 14:18:12 +00:00
|
|
|
scope->uses_super_property(), scope->calls_eval());
|
2016-09-01 10:22:54 +00:00
|
|
|
return kLazyParsingComplete;
|
2011-11-25 09:36:31 +00:00
|
|
|
}
|
|
|
|
|
2014-11-14 15:05:05 +00:00
|
|
|
PreParserExpression PreParser::ParseClassLiteral(
|
2016-09-01 08:58:15 +00:00
|
|
|
PreParserIdentifier name, Scanner::Location class_name_location,
|
|
|
|
bool name_is_strict_reserved, int pos, bool* ok) {
|
2014-11-14 15:05:05 +00:00
|
|
|
// All parts of a ClassDeclaration and ClassExpression are strict code.
|
|
|
|
if (name_is_strict_reserved) {
|
2015-05-18 08:34:05 +00:00
|
|
|
ReportMessageAt(class_name_location,
|
|
|
|
MessageTemplate::kUnexpectedStrictReserved);
|
2014-11-14 15:05:05 +00:00
|
|
|
*ok = false;
|
|
|
|
return EmptyExpression();
|
|
|
|
}
|
|
|
|
if (IsEvalOrArguments(name)) {
|
2015-05-18 08:34:05 +00:00
|
|
|
ReportMessageAt(class_name_location, MessageTemplate::kStrictEvalArguments);
|
2014-11-14 15:05:05 +00:00
|
|
|
*ok = false;
|
|
|
|
return EmptyExpression();
|
|
|
|
}
|
|
|
|
|
2016-03-10 12:43:51 +00:00
|
|
|
LanguageMode class_language_mode = language_mode();
|
2016-08-01 09:04:13 +00:00
|
|
|
BlockState block_state(&scope_state_);
|
|
|
|
scope()->SetLanguageMode(
|
2015-07-20 14:31:30 +00:00
|
|
|
static_cast<LanguageMode>(class_language_mode | STRICT));
|
2015-02-10 13:27:08 +00:00
|
|
|
// TODO(marja): Make PreParser use scope names too.
|
2016-07-19 10:06:38 +00:00
|
|
|
// this->scope()->SetScopeName(name);
|
2014-11-14 15:05:05 +00:00
|
|
|
|
2015-02-03 17:42:41 +00:00
|
|
|
bool has_extends = Check(Token::EXTENDS);
|
|
|
|
if (has_extends) {
|
2016-05-03 01:55:27 +00:00
|
|
|
ExpressionClassifier extends_classifier(this);
|
2016-09-01 08:58:15 +00:00
|
|
|
ParseLeftHandSideExpression(CHECK_OK);
|
|
|
|
CheckNoTailCallExpressions(CHECK_OK);
|
|
|
|
ValidateExpression(CHECK_OK);
|
|
|
|
impl()->AccumulateFormalParameterContainmentErrors();
|
2014-11-14 15:05:05 +00:00
|
|
|
}
|
|
|
|
|
2015-01-29 23:12:25 +00:00
|
|
|
ClassLiteralChecker checker(this);
|
2014-11-14 15:05:05 +00:00
|
|
|
bool has_seen_constructor = false;
|
|
|
|
|
|
|
|
Expect(Token::LBRACE, CHECK_OK);
|
|
|
|
while (peek() != Token::RBRACE) {
|
|
|
|
if (Check(Token::SEMICOLON)) continue;
|
2015-01-15 20:02:20 +00:00
|
|
|
bool is_computed_name = false; // Classes do not care about computed
|
|
|
|
// property names here.
|
2016-05-04 23:24:05 +00:00
|
|
|
ExpressionClassifier property_classifier(this);
|
2016-09-06 17:43:17 +00:00
|
|
|
ParseClassPropertyDefinition(&checker, has_extends, &is_computed_name,
|
2016-09-06 18:49:04 +00:00
|
|
|
&has_seen_constructor, CHECK_OK);
|
2016-09-01 08:58:15 +00:00
|
|
|
ValidateExpression(CHECK_OK);
|
|
|
|
impl()->AccumulateFormalParameterContainmentErrors();
|
2014-11-14 15:05:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Expect(Token::RBRACE, CHECK_OK);
|
|
|
|
|
|
|
|
return Expression::Default();
|
|
|
|
}
|
|
|
|
|
2016-09-01 08:58:15 +00:00
|
|
|
void PreParser::ParseAsyncArrowSingleExpressionBody(PreParserStatementList body,
|
|
|
|
bool accept_IN, int pos,
|
|
|
|
bool* ok) {
|
2016-08-23 16:34:39 +00:00
|
|
|
scope()->ForceContextAllocation();
|
2016-05-17 00:26:53 +00:00
|
|
|
|
2016-08-23 16:34:39 +00:00
|
|
|
PreParserExpression return_value =
|
2016-09-01 10:22:54 +00:00
|
|
|
ParseAssignmentExpression(accept_IN, CHECK_OK_VOID);
|
2016-05-17 00:26:53 +00:00
|
|
|
|
|
|
|
body->Add(PreParserStatement::ExpressionStatement(return_value), zone());
|
|
|
|
}
|
|
|
|
|
2011-05-19 09:01:46 +00:00
|
|
|
#undef CHECK_OK
|
2016-07-19 08:03:43 +00:00
|
|
|
#undef CHECK_OK_CUSTOM
|
2011-05-19 09:01:46 +00:00
|
|
|
|
2010-11-23 11:46:36 +00:00
|
|
|
|
2015-09-30 13:46:56 +00:00
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|