#include <cmath>
-#include "../include/v8stdint.h"
-
-#include "allocation.h"
-#include "checks.h"
-#include "conversions.h"
-#include "conversions-inl.h"
-#include "globals.h"
-#include "hashmap.h"
-#include "list.h"
-#include "preparse-data-format.h"
-#include "preparse-data.h"
-#include "preparser.h"
-#include "unicode.h"
-#include "utils.h"
-
-#if V8_LIBC_MSVCRT && (_MSC_VER < 1800)
-namespace std {
-
-// Usually defined in math.h, but not in MSVC until VS2013+.
-// Abstracted to work
-int isfinite(double value);
-
-} // namespace std
-#endif
+#include "src/allocation.h"
+#include "src/base/logging.h"
+#include "src/conversions-inl.h"
+#include "src/conversions.h"
+#include "src/globals.h"
+#include "src/hashmap.h"
+#include "src/list.h"
+#include "src/preparse-data.h"
+#include "src/preparse-data-format.h"
+#include "src/preparser.h"
+#include "src/unicode.h"
+#include "src/utils.h"
namespace v8 {
namespace internal {
-
void PreParserTraits::ReportMessageAt(Scanner::Location location,
const char* message,
- Vector<const char*> args,
+ const char* arg,
bool is_reference_error) {
ReportMessageAt(location.beg_pos,
location.end_pos,
message,
- args.length() > 0 ? args[0] : NULL,
+ arg,
is_reference_error);
}
-void PreParserTraits::ReportMessageAt(Scanner::Location location,
- const char* type,
- const char* name_opt,
- bool is_reference_error) {
- pre_parser_->log_->LogMessage(location.beg_pos, location.end_pos, type,
- name_opt, is_reference_error);
-}
-
-
void PreParserTraits::ReportMessageAt(int start_pos,
int end_pos,
- const char* type,
- const char* name_opt,
+ const char* message,
+ const char* arg,
bool is_reference_error) {
- pre_parser_->log_->LogMessage(start_pos, end_pos, type, name_opt,
+ pre_parser_->log_->LogMessage(start_pos, end_pos, message, arg,
is_reference_error);
}
} else if (scanner->current_token() ==
Token::FUTURE_STRICT_RESERVED_WORD) {
return PreParserIdentifier::FutureStrictReserved();
+ } else if (scanner->current_token() == Token::LET) {
+ return PreParserIdentifier::Let();
+ } else if (scanner->current_token() == Token::STATIC) {
+ return PreParserIdentifier::Static();
} else if (scanner->current_token() == Token::YIELD) {
return PreParserIdentifier::Yield();
}
if (scanner->UnescapedLiteralMatches("arguments", 9)) {
return PreParserIdentifier::Arguments();
}
+ if (scanner->LiteralMatches("prototype", 9)) {
+ return PreParserIdentifier::Prototype();
+ }
+ if (scanner->LiteralMatches("constructor", 11)) {
+ return PreParserIdentifier::Constructor();
+ }
+ return PreParserIdentifier::Default();
+}
+
+
+PreParserIdentifier PreParserTraits::GetNumberAsSymbol(Scanner* scanner) {
return PreParserIdentifier::Default();
}
PreParserExpression PreParserTraits::ParseFunctionLiteral(
- PreParserIdentifier name,
- Scanner::Location function_name_location,
- bool name_is_strict_reserved,
- bool is_generator,
- int function_token_position,
- FunctionLiteral::FunctionType type,
- bool* ok) {
+ PreParserIdentifier name, Scanner::Location function_name_location,
+ bool name_is_strict_reserved, FunctionKind kind,
+ int function_token_position, FunctionLiteral::FunctionType type,
+ FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
return pre_parser_->ParseFunctionLiteral(
- name, function_name_location, name_is_strict_reserved, is_generator,
- function_token_position, type, ok);
+ name, function_name_location, name_is_strict_reserved, kind,
+ function_token_position, type, arity_restriction, ok);
}
log_ = log;
// Lazy functions always have trivial outer scopes (no with/catch scopes).
PreParserScope top_scope(scope_, GLOBAL_SCOPE);
- FunctionState top_state(&function_state_, &scope_, &top_scope);
+ PreParserFactory top_factory(NULL);
+ FunctionState top_state(&function_state_, &scope_, &top_scope, &top_factory);
scope_->SetStrictMode(strict_mode);
PreParserScope function_scope(scope_, FUNCTION_SCOPE);
- FunctionState function_state(&function_state_, &scope_, &function_scope);
+ PreParserFactory function_factory(NULL);
+ FunctionState function_state(&function_state_, &scope_, &function_scope,
+ &function_factory);
function_state.set_is_generator(is_generator);
- ASSERT_EQ(Token::LBRACE, scanner()->current_token());
+ DCHECK_EQ(Token::LBRACE, scanner()->current_token());
bool ok = true;
int start_position = peek_position();
ParseLazyFunctionLiteralBody(&ok);
if (!ok) {
ReportUnexpectedToken(scanner()->current_token());
} else {
- ASSERT_EQ(Token::RBRACE, scanner()->peek());
+ DCHECK_EQ(Token::RBRACE, scanner()->peek());
if (scope_->strict_mode() == STRICT) {
int end_pos = scanner()->location().end_pos;
CheckOctalLiteral(start_position, end_pos, &ok);
switch (peek()) {
case Token::FUNCTION:
return ParseFunctionDeclaration(ok);
- case Token::LET:
+ case Token::CLASS:
+ return ParseClassDeclaration(ok);
case Token::CONST:
return ParseVariableStatement(kSourceElement, ok);
+ case Token::LET:
+ DCHECK(allow_harmony_scoping());
+ if (strict_mode() == STRICT) {
+ return ParseVariableStatement(kSourceElement, ok);
+ }
+ // Fall through.
default:
return ParseStatement(ok);
}
case Token::LBRACE:
return ParseBlock(ok);
- case Token::CONST:
- case Token::LET:
- case Token::VAR:
- return ParseVariableStatement(kStatement, ok);
-
case Token::SEMICOLON:
Next();
return Statement::Default();
if (strict_mode() == STRICT) {
PreParserTraits::ReportMessageAt(start_location.beg_pos,
end_location.end_pos,
- "strict_function",
- NULL);
+ "strict_function");
*ok = false;
return Statement::Default();
} else {
}
}
+ case Token::CLASS:
+ return ParseClassDeclaration(CHECK_OK);
+
case Token::DEBUGGER:
return ParseDebuggerStatement(ok);
+ case Token::VAR:
+ case Token::CONST:
+ return ParseVariableStatement(kStatement, ok);
+
+ case Token::LET:
+ DCHECK(allow_harmony_scoping());
+ if (strict_mode() == STRICT) {
+ return ParseVariableStatement(kStatement, ok);
+ }
+ // Fall through.
default:
return ParseExpressionOrLabelledStatement(ok);
}
// '{' FunctionBody '}'
Expect(Token::FUNCTION, CHECK_OK);
int pos = position();
- bool is_generator = allow_generators() && Check(Token::MUL);
+ bool is_generator = Check(Token::MUL);
bool is_strict_reserved = false;
Identifier name = ParseIdentifierOrStrictReservedWord(
&is_strict_reserved, CHECK_OK);
- ParseFunctionLiteral(name,
- scanner()->location(),
- is_strict_reserved,
- is_generator,
- pos,
- FunctionLiteral::DECLARATION,
- CHECK_OK);
+ ParseFunctionLiteral(name, scanner()->location(), is_strict_reserved,
+ is_generator ? FunctionKind::kGeneratorFunction
+ : FunctionKind::kNormalFunction,
+ pos, FunctionLiteral::DECLARATION,
+ FunctionLiteral::NORMAL_ARITY, CHECK_OK);
return Statement::FunctionDeclaration();
}
+PreParser::Statement PreParser::ParseClassDeclaration(bool* ok) {
+ Expect(Token::CLASS, CHECK_OK);
+ int pos = position();
+ bool is_strict_reserved = false;
+ Identifier name =
+ ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
+ ParseClassLiteral(name, scanner()->location(), is_strict_reserved, pos,
+ CHECK_OK);
+ return Statement::Default();
+}
+
+
PreParser::Statement PreParser::ParseBlock(bool* ok) {
// Block ::
// '{' Statement* '}'
// ConstBinding ::
// BindingPattern '=' AssignmentExpression
bool require_initializer = false;
+ bool is_strict_const = false;
if (peek() == Token::VAR) {
Consume(Token::VAR);
} else if (peek() == Token::CONST) {
*ok = false;
return Statement::Default();
}
- require_initializer = true;
+ is_strict_const = true;
+ require_initializer = var_context != kForStatement;
} else {
Scanner::Location location = scanner()->peek_location();
ReportMessageAt(location, "strict_const");
return Statement::Default();
}
}
- } else if (peek() == Token::LET) {
- // ES6 Draft Rev4 section 12.2.1:
- //
- // LetDeclaration : let LetBindingList ;
- //
- // * It is a Syntax Error if the code that matches this production is not
- // contained in extended code.
- //
- // TODO(rossberg): make 'let' a legal identifier in sloppy mode.
- if (!allow_harmony_scoping() || strict_mode() == SLOPPY) {
- ReportMessageAt(scanner()->peek_location(), "illegal_let");
- *ok = false;
- return Statement::Default();
- }
+ } else if (peek() == Token::LET && strict_mode() == STRICT) {
Consume(Token::LET);
- if (var_context != kSourceElement &&
- var_context != kForStatement) {
+ if (var_context != kSourceElement && var_context != kForStatement) {
ReportMessageAt(scanner()->peek_location(), "unprotected_let");
*ok = false;
return Statement::Default();
if (nvars > 0) Consume(Token::COMMA);
ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
nvars++;
- if (peek() == Token::ASSIGN || require_initializer) {
+ if (peek() == Token::ASSIGN || require_initializer ||
+ // require initializers for multiple consts.
+ (is_strict_const && peek() == Token::COMMA)) {
Expect(Token::ASSIGN, CHECK_OK);
ParseAssignmentExpression(var_context != kForStatement, CHECK_OK);
if (decl_props != NULL) *decl_props = kHasInitializers;
if (starts_with_identifier && expr.IsIdentifier() && peek() == Token::COLON) {
// Expression is a single identifier, and not, e.g., a parenthesized
// identifier.
- ASSERT(!expr.AsIdentifier().IsFutureReserved());
- ASSERT(strict_mode() == SLOPPY ||
- (!expr.AsIdentifier().IsFutureStrictReserved() &&
- !expr.AsIdentifier().IsYield()));
+ DCHECK(!expr.AsIdentifier().IsFutureReserved());
+ DCHECK(strict_mode() == SLOPPY ||
+ !IsFutureStrictReserved(expr.AsIdentifier()));
Consume(Token::COLON);
return ParseStatement(ok);
// Preparsing is disabled for extensions (because the extension details
bool PreParser::CheckInOrOf(bool accept_OF) {
if (Check(Token::IN) ||
- (allow_for_of() && accept_OF &&
- CheckContextualKeyword(CStrVector("of")))) {
+ (accept_OF && CheckContextualKeyword(CStrVector("of")))) {
return true;
}
return false;
Expect(Token::LPAREN, CHECK_OK);
if (peek() != Token::SEMICOLON) {
if (peek() == Token::VAR || peek() == Token::CONST ||
- peek() == Token::LET) {
- bool is_let = peek() == Token::LET;
+ (peek() == Token::LET && strict_mode() == STRICT)) {
+ bool is_lexical = peek() == Token::LET ||
+ (peek() == Token::CONST && strict_mode() == STRICT);
int decl_count;
VariableDeclarationProperties decl_props = kHasNoInitializers;
ParseVariableDeclarations(
kForStatement, &decl_props, &decl_count, CHECK_OK);
bool has_initializers = decl_props == kHasInitializers;
- bool accept_IN = decl_count == 1 && !(is_let && has_initializers);
+ bool accept_IN = decl_count == 1 && !(is_lexical && has_initializers);
bool accept_OF = !has_initializers;
if (accept_IN && CheckInOrOf(accept_OF)) {
ParseExpression(true, CHECK_OK);
PreParser::Expression PreParser::ParseFunctionLiteral(
- Identifier function_name,
- Scanner::Location function_name_location,
- bool name_is_strict_reserved,
- bool is_generator,
- int function_token_pos,
+ Identifier function_name, Scanner::Location function_name_location,
+ bool name_is_strict_reserved, FunctionKind kind, int function_token_pos,
FunctionLiteral::FunctionType function_type,
- bool* ok) {
+ FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
// Function ::
// '(' FormalParameterList? ')' '{' FunctionBody '}'
// Parse function body.
ScopeType outer_scope_type = scope_->type();
PreParserScope function_scope(scope_, FUNCTION_SCOPE);
- FunctionState function_state(&function_state_, &scope_, &function_scope);
- function_state.set_is_generator(is_generator);
+ PreParserFactory factory(NULL);
+ FunctionState function_state(&function_state_, &scope_, &function_scope,
+ &factory);
+ function_state.set_is_generator(IsGeneratorFunction(kind));
// FormalParameterList ::
// '(' (Identifier)*[','] ')'
Expect(Token::LPAREN, CHECK_OK);
int start_position = position();
- bool done = (peek() == Token::RPAREN);
DuplicateFinder duplicate_finder(scanner()->unicode_cache());
// We don't yet know if the function will be strict, so we cannot yet produce
// errors for parameter names or duplicates. However, we remember the
Scanner::Location eval_args_error_loc = Scanner::Location::invalid();
Scanner::Location dupe_error_loc = Scanner::Location::invalid();
Scanner::Location reserved_error_loc = Scanner::Location::invalid();
+
+ bool done = arity_restriction == FunctionLiteral::GETTER_ARITY ||
+ (peek() == Token::RPAREN &&
+ arity_restriction != FunctionLiteral::SETTER_ARITY);
while (!done) {
bool is_strict_reserved = false;
Identifier param_name =
dupe_error_loc = scanner()->location();
}
+ if (arity_restriction == FunctionLiteral::SETTER_ARITY) break;
done = (peek() == Token::RPAREN);
- if (!done) {
- Expect(Token::COMMA, CHECK_OK);
- }
+ if (!done) Expect(Token::COMMA, CHECK_OK);
}
Expect(Token::RPAREN, CHECK_OK);
// Validate strict mode. We can do this only after parsing the function,
// since the function can declare itself strict.
- if (strict_mode() == STRICT) {
+ // Concise methods use StrictFormalParameters.
+ if (strict_mode() == STRICT || IsConciseMethod(kind)) {
if (function_name.IsEvalOrArguments()) {
ReportMessageAt(function_name_location, "strict_eval_arguments");
*ok = false;
if (!*ok) return;
// Position right after terminal '}'.
- ASSERT_EQ(Token::RBRACE, scanner()->peek());
+ DCHECK_EQ(Token::RBRACE, scanner()->peek());
int body_end = scanner()->peek_location().end_pos;
log_->LogFunction(body_start, body_end,
function_state_->materialized_literal_count(),